Sign in

    moonuuid

    UUIDs: parse and write every spelling, make versions 1 to 8, and a generator over a clock and randomness you supply.

    uuid
    guid
    identifier
    rfc9562
    moonbit
    Download zip
    Version
    0.1.0
    License
    Apache-2.0
    Last updated
    3 days ago
    Downloads
    14

    #moonuuid

    UUIDs for MoonBit. Read every spelling in use, write the canonical one, and make all eight versions of RFC 9562. Time and randomness come from functions you pass in, so the same code runs on every backend and in every test.

    let id = @moonuuid.parse("{C232AB00-9414-11EC-B3C8-9F6BDECED846}")
    id.to_string() // "c232ab00-9414-11ec-b3c8-9f6bdeced846"
    id.version() // Some(1)


    #Install

    moon add moonbitstack/moonuuid

    #Quick start

    // Name-based ids are the same every time.
    let page = @moonuuid.v5(@moonuuid.namespace_url, "https://example.org/")

    // Time-ordered ids from a generator over your clock and randomness.
    let gen = @moonuuid.Generator::new(
    clock=() => now_in_nanoseconds(),
    random=n => system_random_bytes(n),
    )
    let row = gen.v7() // sorts in the order made, even within one millisecond

    #The versions

    VersionMade fromFunctionSorts by time
    1timestamp, clock sequence, nodev1(ticks~, clock_seq~, node~) · gen.v1(node~)
    3MD5 of a namespace and a namev3(space, name)
    4122 random bitsv4(random) · gen.v4()
    5SHA-1 of a namespace and a namev5(space, name)
    6version 1's fields, high time bits firstv6(ticks~, clock_seq~, node~) · gen.v6(node~)✓
    7Unix milliseconds, a counter and random bitsv7(millis~, random) · gen.v7()✓
    8122 bits of your own layoutv8(custom)

    ticks_of(unix_nanos) turns nanoseconds since 1970 into the 100-nanosecond intervals since 1582 that versions 1 and 6 count. The namespaces are namespace_dns, namespace_url, namespace_oid and namespace_x500; nil and max are all zeros and all ones.

    #Reading and writing

    parse takes the canonical form, any case, with or without hyphens, in braces, or after urn:uuid::

    @moonuuid.parse("6ba7b8109dad11d180b400c04fd430c8")
    @moonuuid.parse("urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8")

    WriteGives
    id.to_string()6ba7b810-9dad-11d1-80b4-00c04fd430c8
    id.hex()6ba7b8109dad11d180b400c04fd430c8
    id.urn()urn:uuid:6ba7b810-9dad-11d1-80b4-00c04fd430c8
    id.bytes()the 16 bytes, most significant first
    Json(id)the canonical text; @json.from_json reads any spelling back

    Uuid::of_bytes and Uuid::of_parts(hi, lo) build one from 16 bytes or two 64-bit halves. Identifiers compare, hash and sort by their bytes.

    #Fields

    MethodReturns
    variant()Ncs, Rfc, Microsoft or Future
    version()the version for an RFC 9562 id, else None
    time()100-ns ticks since 1582 for versions 1 and 6, milliseconds since 1970 for version 7
    clock_seq()the 14-bit clock sequence
    node()the 48-bit node

    #The generator

    Generator::new(clock~, random~) keeps what the time-based versions need between calls. clock gives nanoseconds since 1970 and random gives a number of random bytes.

    • Version 1 and 6 timestamps never repeat or go back; the clock sequence is random unless you pass one.
    • Version 7 ids made within one millisecond count up with a fresh random tail. If the clock steps back, the next id uses the millisecond after the last one, so the order holds.

    #Errors

    RefusedWhen
    Malformed(at~, reason~)text that is not 32 hexadecimal digits; at is where it went wrong
    Size(want~, got~)bytes, or a random source, of the wrong length

    #Licence

    Apache-2.0. See LICENSE.

    Refused

    pub(all) suberror Refused {
    Malformed(at~ : Int, reason~ : String)
    Size(want~ : Int, got~ : Int)
    } derive(Eq,
    Debug
    )

    Why text or bytes are not a UUID.
    impl Show for Refused

    Refused::equal

    fn Refused::equal(Refused, Refused) -> Bool

    Refused::not_equal

    fn Refused::not_equal(x : Refused, y : Refused) -> Bool

    Refused::output

    fn Refused::output(self : Refused, logger : &Logger) -> Unit

    Refused::to_repr

    Refused::to_string

    fn Refused::to_string(self : Refused) -> String

    Generator

    pub struct Generator {
    // private fields
    }

    Identifiers from a clock and a source of random bytes the caller supplies, keeping what the time-based versions need between calls: version 1 and 6 timestamps never repeat or go back, and version 7 ids made within one millisecond count up, so they sort in the order made.

    Generator::new

    fn Generator::new(clock~ : () -> Int64, random~ : (Int) -> Bytes) -> Generator

    clock gives nanoseconds since 1970; random gives that many random bytes.

    Generator::v1

    fn Generator::v1(self : Generator, node~ : Int64, clock_seq? : Int) -> Uuid raise Refused

    Version 1 with node; the clock sequence is random unless given.

    Generator::v4

    fn Generator::v4(self : Generator) -> Uuid raise Refused

    Version 4 from 16 random bytes.

    Generator::v6

    fn Generator::v6(self : Generator, node~ : Int64, clock_seq? : Int) -> Uuid raise Refused

    Version 6 with node; the clock sequence is random unless given.

    Generator::v7

    fn Generator::v7(self : Generator) -> Uuid raise Refused

    Version 7. Within one millisecond the counter goes up by one with a fresh random tail; when the clock steps back, the millisecond after the last one is used; when the counter runs out, the millisecond moves on.

    Uuid

    pub struct Uuid {
    // private fields
    } derive(Compare, Eq, Hash,
    Debug
    )

    A 128-bit identifier as RFC 9562 lays it out. Compared, hashed and ordered by its bytes, so a sorted list of time-ordered ids is in time order.
    impl Show for Uuid
    impl ToJson for Uuid

    Uuid::bytes

    fn Uuid::bytes(self : Uuid) -> Bytes

    The 16 bytes, most significant first.

    Uuid::clock_seq

    fn Uuid::clock_seq(self : Uuid) -> Int

    The 14-bit clock sequence of versions 1 and 6.

    Uuid::compare

    fn Uuid::compare(Uuid, Uuid) -> Int

    Uuid::equal

    fn Uuid::equal(Uuid, Uuid) -> Bool

    Uuid::hash

    fn Uuid::hash(self : Uuid) -> Int

    Uuid::hash_combine

    fn Uuid::hash_combine(Uuid, Hasher) -> Unit

    Uuid::hex

    fn Uuid::hex(self : Uuid) -> String

    The 32 hexadecimal digits, lowercase, without hyphens.

    Uuid::node

    fn Uuid::node(self : Uuid) -> Int64

    The 48-bit node of versions 1 and 6.

    Uuid::not_equal

    fn Uuid::not_equal(x : Uuid, y : Uuid) -> Bool

    Uuid::of_bytes

    fn Uuid::of_bytes(bytes : BytesView) -> Uuid raise Refused

    The identifier from its 16 bytes, most significant first.

    Uuid::of_parts

    fn Uuid::of_parts(hi : UInt64, lo : UInt64) -> Uuid

    The identifier from its high and low 64 bits.

    Uuid::op_ge

    fn Uuid::op_ge(x : Uuid, y : Uuid) -> Bool

    Uuid::op_gt

    fn Uuid::op_gt(x : Uuid, y : Uuid) -> Bool

    Uuid::op_le

    fn Uuid::op_le(x : Uuid, y : Uuid) -> Bool

    Uuid::op_lt

    fn Uuid::op_lt(x : Uuid, y : Uuid) -> Bool

    Uuid::output

    fn Uuid::output(self : Uuid, logger : &Logger) -> Unit

    Uuid::parts

    fn Uuid::parts(self : Uuid) -> (UInt64, UInt64)

    The high and low 64 bits.

    Uuid::time

    fn Uuid::time(self : Uuid) -> Int64

    The timestamp the fields hold: 100-nanosecond intervals since 1582-10-15 for versions 1 and 6, milliseconds since 1970 for version 7, the version 1 reading of the fields otherwise.

    Uuid::to_json

    fn Uuid::to_json(self : Uuid) -> Json

    Uuid::to_repr

    Uuid::to_string

    fn Uuid::to_string(self : Uuid) -> String

    Uuid::urn

    fn Uuid::urn(self : Uuid) -> String

    urn:uuid: and the canonical text, as RFC 9562 names an identifier.

    Uuid::variant

    fn Uuid::variant(self : Uuid) -> Variant

    The variant its bits name.

    Uuid::version

    fn Uuid::version(self : Uuid) -> Int?

    The version, 1 to 8 for the ones RFC 9562 defines; None when the variant is not RFC 9562's, where the version bits mean nothing.

    Variant

    pub(all) enum Variant {
    Ncs
    Rfc
    Microsoft
    Future
    } derive(Eq,
    Debug
    )

    Who an identifier's variant bits say it belongs to.
    impl Show for Variant

    Variant::equal

    fn Variant::equal(Variant, Variant) -> Bool

    Variant::not_equal

    fn Variant::not_equal(x : Variant, y : Variant) -> Bool

    Variant::output

    fn Variant::output(self : Variant, logger : &Logger) -> Unit

    Variant::to_repr

    Variant::to_string

    fn Variant::to_string(self : Variant) -> String

    gregorian_offset

    let gregorian_offset : Int64

    100-nanosecond intervals between 1582-10-15, where version 1 and 6 timestamps start, and 1970-01-01.

    max

    let max : Uuid

    The max identifier, all ones.

    namespace_dns

    let namespace_dns : Uuid

    The namespaces RFC 9562 assigns for names that are domain names, URLs, ISO OIDs and X.500 distinguished names.

    namespace_oid

    let namespace_oid : Uuid

    namespace_url

    let namespace_url : Uuid

    namespace_x500

    let namespace_x500 : Uuid

    nil

    let nil : Uuid

    The nil identifier, all zeros.

    parse

    fn parse(text : StringView) -> Uuid raise Refused

    Text in any of the spellings in use: canonical, with or without hyphens, in braces, with the urn:uuid: prefix; any case.

    ticks_of

    fn ticks_of(unix_nanos : Int64) -> Int64

    A version 1 or 6 timestamp from nanoseconds since 1970.
    fn v1(ticks~ : Int64, clock_seq~ : Int, node~ : Int64) -> Uuid

    Time-based: a 60-bit timestamp from ticks_of, a 14-bit clock sequence and a 48-bit node, laid out with the low time bits first.
    fn v3(space : Uuid, name : StringView) -> Uuid

    Name-based with MD5: the same namespace and name always give the same identifier. The name is hashed as UTF-8.
    fn v4(random : BytesView) -> Uuid raise Refused

    Random: 122 of the 16 bytes given are kept.
    fn v5(space : Uuid, name : StringView) -> Uuid

    Name-based with SHA-1, preferred over version 3.
    fn v6(ticks~ : Int64, clock_seq~ : Int, node~ : Int64) -> Uuid

    Version 1's fields with the timestamp's high bits first, so the identifiers sort in time order.
    fn v7(millis~ : Int64, random : BytesView) -> Uuid raise Refused

    Milliseconds since 1970 in the top 48 bits, then 74 bits from the 10 random bytes given: a 42-bit counter whose top bit starts clear, so a generator can count up within a millisecond, and 32 random bits.
    fn v8(custom : BytesView) -> Uuid raise Refused

    Custom: 122 bits of the 16 bytes given, laid out as the caller likes; only version and variant are written over.