Skip to content

Commit

Permalink
Update
Browse files Browse the repository at this point in the history
  • Loading branch information
Heptazhou committed Apr 6, 2024
1 parent 6bbca62 commit b9ee948
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 70 deletions.
8 changes: 5 additions & 3 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,16 +32,18 @@ jobs:
- os: macos-latest
julia-version: nightly
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
with:
persist-credentials: false
- uses: julia-actions/setup-julia@v1
- uses: julia-actions/setup-julia@v2
with:
show-versioninfo: true
version: ${{ matrix.julia-version }}
- uses: julia-actions/julia-buildpkg@v1
with:
ignore-no-cache: true
- uses: julia-actions/julia-runtest@v1
- uses: heptazhou/julia-codecov@v1
- uses: codecov/codecov-action@v3
- uses: codecov/codecov-action@v3.1.5
with:
file: lcov.info
6 changes: 3 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
name = "UUID4"
uuid = "379725f3-1ad5-416d-b88a-50ced391fe04"
authors = ["Heptazhou <zhou at 0h7z dot com>"]
version = "1.8.0"
version = "1.10.0"

[deps]
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
Random = "9a3f8284-a2c9-5f02-9a11-845980a1fd5c"

[extras]
OrderedCollections = "bac558e1-5e72-5ebc-8fee-abe8a469f55d"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

[targets]
test = ["Test"]
test = ["OrderedCollections", "Test"]
109 changes: 49 additions & 60 deletions src/UUID4.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2022-2023 Heptazhou <[email protected]>
# Copyright (C) 2022-2024 Heptazhou <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
Expand All @@ -16,29 +16,31 @@
"""
UUID4
The `UUID4` module provides universally unique identifier (UUID), version 4,
This module provides universally unique identifier (UUID) version 4,
along with related functions.
"""
module UUID4

export uuid, uuid4

export uuid_formats
export uuid_parse
export uuid_string
export uuid_tryparse
export uuid_version

export AbstractRNG, MersenneTwister, RandomDevice
export LittleDict, OrderedDict
export UUID

const Maybe{T} = Union{Nothing, T}
const UUID = Base.UUID
using OrderedCollections: LittleDict, OrderedDict
using Random: AbstractRNG, MersenneTwister, RandomDevice

"""
uuid(rng::AbstractRNG = RandomDevice()) -> UUID
uuid(rng::AbstractRNG = Random.RandomDevice()) -> UUID
Generate a version 4 (random or pseudo-random) universally unique identifier
(UUID), as specified by [RFC 4122](https://www.ietf.org/rfc/rfc4122).
Generate a version 4 (random or pseudo-random) universally unique identifier (UUID),
as specified by [RFC 4122](https://tools.ietf.org/html/rfc4122).
# Examples
```jldoctest
Expand Down Expand Up @@ -76,39 +78,22 @@ function uuid_formats()::Vector{Int}
end

"""
uuid_parse(str::String; fmt::Int = length(str)) -> Tuple{Int, UUID}
uuid_parse(str::AbstractString; fmt::Int = length(str)) -> Tuple{Int, UUID}
"""
function uuid_parse end
function uuid_parse(str::UUID; fmt::Any = 0x0)::Tuple{Int, UUID}
uuid_parse(string(str); fmt = Int(fmt))
function uuid_parse(id::UUID)::Tuple{Int, UUID}
(length("$id"), id) # (36, id)
end
function uuid_parse(str::Any; fmt::Number = 0)::Tuple{Int, UUID}
uuid_parse(String(str); fmt = Int(fmt))
end
function uuid_parse(str::String; fmt::Int = 0)::Tuple{Int, UUID}
function uuid_parse(str::AbstractString; fmt::Int = 0)::Tuple{Int, UUID}
len = length(str)
ret = if 0 > fmt
argumenterror("Invalid format `$fmt` (should be positive)")
elseif len fmt > 0
argumenterror("Invalid id `$str` with length = $len (should be $fmt)")
elseif len 24
uuid_parse(replace((str), "-" => ""), fmt = 22)[end]
elseif len 29
uuid_parse(replace((str), "-" => ""), fmt = 25)[end]
elseif len 39
uuid_parse(replace((str), "-" => ""), fmt = 32)[end]
elseif len 22
UUID(parse(UInt128, str, base = 62))
elseif len 25
UUID(parse(UInt128, str, base = 36))
elseif len 32
UUID(parse(UInt128, str, base = 16))
elseif len 36
UUID(str)
else
(id = uuid_tryparse(str)) |> isnothing &&
argumenterror("Invalid id `$str` with length = $len")
if 0 < fmt len
argumenterror("Invalid id `$str` with length = $len (should be $fmt)")
elseif fmt < 0
argumenterror("Invalid format `$fmt` (should be positive)")
end
len, ret
len, id |> UUID
end

"""
Expand Down Expand Up @@ -159,33 +144,38 @@ function uuid_string(fmt::Int, id::UUID = uuid())::String
uuid_string(id, fmt)
end
function uuid_string(id::UUID, fmt::Int)::String
if 0 fmt
argumenterror("Invalid format `$fmt` (should be positive)")
elseif fmt 36
string(id)
elseif fmt 22
string(id.value, base = 62, pad = fmt)
elseif fmt 25
string(id.value, base = 36, pad = fmt)
elseif fmt 32
string(id.value, base = 16, pad = fmt)
elseif fmt 24
replace(uuid_string(id, 22), r"(.{7})" => s"\1-", count = fmt - 22)
elseif fmt 29
replace(uuid_string(id, 25), r"(.{5})" => s"\1-", count = fmt - 25)
elseif fmt 39
replace(uuid_string(id, 32), r"(.{4})" => s"\1-", count = fmt - 32)
else
argumenterror("Invalid format `$fmt` (undefined)")
end
fmt 0 ?
argumenterror("Invalid format `$fmt` (should be positive)") :
fmt 36 ? string(id) :
fmt 22 ? string(id.value, base = 62, pad = fmt) :
fmt 25 ? string(id.value, base = 36, pad = fmt) :
fmt 32 ? string(id.value, base = 16, pad = fmt) :
fmt 24 ? replace(uuid_string(id, 22), r"(.{7})" => s"\1-", count = fmt - 22) :
fmt 29 ? replace(uuid_string(id, 25), r"(.{5})" => s"\1-", count = fmt - 25) :
fmt 39 ? replace(uuid_string(id, 32), r"(.{4})" => s"\1-", count = fmt - 32) :
argumenterror("Invalid format `$fmt` (not defined)")
end

"""
uuid_tryparse(s::AbstractString) -> Maybe{Union{UInt128, UUID}}
"""
function uuid_tryparse(str::AbstractString)::Maybe{Union{UInt128, UUID}}
len = ncodeunits(str)
len 24 ? uuid_tryparse(replace(str, "-" => "")) :
len 29 ? uuid_tryparse(replace(str, "-" => "")) :
len 39 ? uuid_tryparse(replace(str, "-" => "")) :
len 22 ? Base.tryparse(UInt128, str, base = 62) :
len 25 ? Base.tryparse(UInt128, str, base = 36) :
len 32 ? Base.tryparse(UInt128, str, base = 16) :
len 36 ? Base.tryparse(UUID, str) : nothing
end

"""
uuid_version(id::String) -> Int
uuid_version(id::UUID) -> Int
uuid_version(id::AbstractString) -> Int
uuid_version(id::UUID) -> Int
Inspect the given UUID or UUID string and return its version (see [RFC
4122](https://www.ietf.org/rfc/rfc4122)).
Inspect the given UUID or UUID string and return its version
(see [RFC 4122](https://tools.ietf.org/html/rfc4122)).
# Examples
```jldoctest
Expand All @@ -194,9 +184,8 @@ julia> uuid_version(uuid())
```
"""
function uuid_version end
uuid_version(id::Any)::Int = uuid_version(String(id))
uuid_version(id::String)::Int = uuid_version(uuid_parse(id)[end])
uuid_version(id::UUID)::Int = Int(id.value >> 76 & 0xf)
uuid_version(id::Any)::Int = uuid_version(uuid_parse(id)[end])
uuid_version(id::UUID)::Int = id.value >> 76 & 0xf |> Int

@noinline argumenterror(msg::AbstractString) = throw(ArgumentError(msg))

Expand Down
11 changes: 7 additions & 4 deletions test/runtests.jl
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright (C) 2022-2023 Heptazhou <[email protected]>
# Copyright (C) 2022-2024 Heptazhou <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
Expand All @@ -13,6 +13,7 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.

using OrderedCollections: LittleDict, OrderedDict
using Random: Random
using Test, UUID4

Expand Down Expand Up @@ -40,7 +41,7 @@ str = "22b4a8a1-e548-4eeb-9270-60426d66a48e"
@test_throws ArgumentError UUID("22b4a8a1-e548-4eeba9270-60426d66a48e")
@test_throws ArgumentError UUID("22b4a8a1-e548-4eeb-9270a60426d66a48e")
@test UUID(uppercase(str)) == UUID(str)
for r in (rand(UInt128, 10^3))
for r rand(UInt128, 10^3)
@test UUID(r) == UUID(string(UUID(r)))
end

Expand All @@ -58,9 +59,10 @@ d_o, d_u = OrderedDict(vec), Dict(vec)
u = UUID(d_u[36])
s = GenericString(string(u))

@test uuid_tryparse("") |> isnothing
@test uuid_parse(s) == uuid_parse(u) == (36, u)
@test uuid_formats() == d_o.keys == fmt
for n in fmt
for n fmt
@test (n, u) == uuid_parse(d_u[n]) == uuid_parse(d_u[n] |> GenericString)
@test d_u[n] == uuid_string(n, u) == uuid_string(u, n |> UInt32) == d_o[n]
@test d_o[n] == uuid_string(n, u |> string) == uuid_string(u |> string, n)
Expand All @@ -71,9 +73,10 @@ end
@test_throws ArgumentError uuid_parse(d_u[32], fmt = 42)
@test_throws ArgumentError uuid_parse(d_u[32]^2)

@test uuid_string(u, LittleDict) == uuid_string(LittleDict, u)
@test uuid_string(u, OrderedDict) == uuid_string(OrderedDict, u)
@test uuid_string(u) == uuid_string(Dict, u) == d_u == Dict(d_o)
@test uuid_string(u) == uuid_string(Dict, s) == uuid_string(s, Dict)
@test uuid_string(u) == uuid_string(s, Dict) == uuid_string(Dict, s)
@test_throws ArgumentError uuid_string(u, -1)
@test_throws ArgumentError uuid_string(u, 42)

0 comments on commit b9ee948

Please sign in to comment.