diff options
Diffstat (limited to 'libphobos/src/std/uuid.d')
-rw-r--r-- | libphobos/src/std/uuid.d | 129 |
1 files changed, 78 insertions, 51 deletions
diff --git a/libphobos/src/std/uuid.d b/libphobos/src/std/uuid.d index c804e8eb7e8..dec2a1c276d 100644 --- a/libphobos/src/std/uuid.d +++ b/libphobos/src/std/uuid.d @@ -68,11 +68,11 @@ $(TR $(TDNW UUID namespaces) * * For efficiency, UUID is implemented as a struct. UUIDs are therefore empty if not explicitly * initialized. An UUID is empty if $(MYREF3 UUID.empty, empty) is true. Empty UUIDs are equal to - * $(D UUID.init), which is a UUID with all 16 bytes set to 0. + * `UUID.init`, which is a UUID with all 16 bytes set to 0. * Use UUID's constructors or the UUID generator functions to get an initialized UUID. * * This is a port of $(LINK2 http://www.boost.org/doc/libs/1_42_0/libs/uuid/uuid.html, - * boost._uuid) from the Boost project with some minor additions and API + * boost.uuid) from the Boost project with some minor additions and API * changes for a more D-like API. * * Standards: @@ -84,11 +84,11 @@ $(TR $(TDNW UUID namespaces) * Copyright: Copyright Johannes Pfau 2011 - . * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). * Authors: Johannes Pfau - * Source: $(PHOBOSSRC std/_uuid.d) + * Source: $(PHOBOSSRC std/uuid.d) * * Macros: * MYREF2 = <a href="#$2">$(TT $1)</a> - * MYREF3 = <a href="#$2">$(D $1)</a> + * MYREF3 = <a href="#$2">`$1`</a> */ /* Copyright Johannes Pfau 2011 - 2012. * Distributed under the Boost Software License, Version 1.0. @@ -178,7 +178,7 @@ public struct UUID * * Note: * All of these UUID versions can be read and processed by - * $(D std.uuid), but only version 3, 4 and 5 UUIDs can be generated. + * `std.uuid`, but only version 3, 4 and 5 UUIDs can be generated. */ enum Version { @@ -249,12 +249,12 @@ public struct UUID * Construct a UUID struct from the 16 byte representation * of a UUID. */ - @safe pure nothrow @nogc this(ref in ubyte[16] uuidData) + @safe pure nothrow @nogc this(ref const scope ubyte[16] uuidData) { data = uuidData; } /// ditto - @safe pure nothrow @nogc this(in ubyte[16] uuidData) + @safe pure nothrow @nogc this(const ubyte[16] uuidData) { data = uuidData; } @@ -331,7 +331,7 @@ public struct UUID * * For a less strict parser, see $(LREF parseUUID) */ - this(T)(in T[] uuid) if (isSomeChar!(Unqual!T)) + this(T)(in T[] uuid) if (isSomeChar!T) { import std.conv : to, parse; if (uuid.length < 36) @@ -404,13 +404,13 @@ public struct UUID { import std.conv : to; import std.exception; - import std.meta; + import std.meta : AliasSeq; - foreach (S; AliasSeq!(char[], const(char)[], immutable(char)[], + static foreach (S; AliasSeq!(char[], const(char)[], immutable(char)[], wchar[], const(wchar)[], immutable(wchar)[], dchar[], const(dchar)[], immutable(dchar)[], immutable(char[]), immutable(wchar[]), immutable(dchar[]))) - { + {{ //Test valid, working cases assert(UUID(to!S("00000000-0000-0000-0000-000000000000")).empty); @@ -456,7 +456,7 @@ public struct UUID == UUID(cast(ubyte[16])[0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef,0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef])); } - } + }} /** * Returns true if and only if the UUID is equal @@ -664,7 +664,7 @@ public struct UUID * All of the standard numeric operators are defined for * the UUID struct. */ - @safe pure nothrow @nogc bool opEquals(in UUID s) const + @safe pure nothrow @nogc bool opEquals(const UUID s) const { return ulongs[0] == s.ulongs[0] && ulongs[1] == s.ulongs[1]; } @@ -693,7 +693,7 @@ public struct UUID /** * ditto */ - @safe pure nothrow @nogc bool opEquals(ref in UUID s) const + @safe pure nothrow @nogc bool opEquals(ref const scope UUID s) const { return ulongs[0] == s.ulongs[0] && ulongs[1] == s.ulongs[1]; } @@ -701,7 +701,7 @@ public struct UUID /** * ditto */ - @safe pure nothrow @nogc int opCmp(in UUID s) const + @safe pure nothrow @nogc int opCmp(const UUID s) const { import std.algorithm.comparison : cmp; return cmp(this.data[], s.data[]); @@ -710,7 +710,7 @@ public struct UUID /** * ditto */ - @safe pure nothrow @nogc int opCmp(ref in UUID s) const + @safe pure nothrow @nogc int opCmp(ref const scope UUID s) const { import std.algorithm.comparison : cmp; return cmp(this.data[], s.data[]); @@ -719,7 +719,7 @@ public struct UUID /** * ditto */ - @safe pure nothrow @nogc UUID opAssign(in UUID s) + @safe pure nothrow @nogc UUID opAssign(const UUID s) { ulongs[0] = s.ulongs[0]; ulongs[1] = s.ulongs[1]; @@ -729,7 +729,7 @@ public struct UUID /** * ditto */ - @safe pure nothrow @nogc UUID opAssign(ref in UUID s) + @safe pure nothrow @nogc UUID opAssign(ref const scope UUID s) { ulongs[0] = s.ulongs[0]; ulongs[1] = s.ulongs[1]; @@ -880,13 +880,15 @@ public struct UUID const uint lo = (entry) & 0x0F; result[pos+1] = toChar!char(lo); } - foreach (i, c; result) + static if (!__traits(compiles, put(sink, result[])) || isSomeString!Writer) { - static if (__traits(compiles, put(sink, c))) - put(sink, c); - else + foreach (i, c; result) sink[i] = cast(typeof(sink[i]))c; } + else + { + put(sink, result[]); + } } /** @@ -911,8 +913,8 @@ public struct UUID @safe pure nothrow @nogc unittest { import std.meta : AliasSeq; - foreach (Char; AliasSeq!(char, wchar, dchar)) - { + static foreach (Char; AliasSeq!(char, wchar, dchar)) + {{ alias String = immutable(Char)[]; //CTFE enum String s = "8ab3060e-2cba-4f23-b74c-b52db3bdfb46"; @@ -926,7 +928,7 @@ public struct UUID Char[36] str; id.toString(str[]); assert(str == s); - } + }} } @system pure nothrow @nogc unittest @@ -952,7 +954,7 @@ public struct UUID assert(u1.toString() == "8ab3060e-2cba-4f23-b74c-b52db3bdfb46"); char[] buf; - void sink(const(char)[] data) + void sink(scope const(char)[] data) { buf ~= data; } @@ -961,10 +963,23 @@ public struct UUID } } +/// +@safe unittest +{ + UUID id; + assert(id.empty); + + id = randomUUID; + assert(!id.empty); + + id = UUID(cast(ubyte[16]) [138, 179, 6, 14, 44, 186, 79, + 35, 183, 76, 181, 45, 179, 189, 251, 70]); + assert(id.toString() == "8ab3060e-2cba-4f23-b74c-b52db3bdfb46"); +} /** * This function generates a name based (Version 3) UUID from a namespace UUID and a name. - * If no namespace UUID was passed, the empty UUID $(D UUID.init) is used. + * If no namespace UUID was passed, the empty UUID `UUID.init` is used. * * Note: * The default namespaces ($(LREF dnsNamespace), ...) defined by @@ -980,8 +995,8 @@ public struct UUID * RFC 4122 isn't very clear on how UUIDs should be generated from names. * It is possible that different implementations return different UUIDs * for the same input, so be warned. The implementation for UTF-8 strings - * and byte arrays used by $(D std.uuid) is compatible with Boost's implementation. - * $(D std.uuid) guarantees that the same input to this function will generate + * and byte arrays used by `std.uuid` is compatible with Boost's implementation. + * `std.uuid` guarantees that the same input to this function will generate * the same output at any time, on any system (this especially means endianness * doesn't matter). * @@ -1078,7 +1093,7 @@ public struct UUID /** * This function generates a name based (Version 5) UUID from a namespace * UUID and a name. - * If no namespace UUID was passed, the empty UUID $(D UUID.init) is used. + * If no namespace UUID was passed, the empty UUID `UUID.init` is used. * * Note: * The default namespaces ($(LREF dnsNamespace), ...) defined by @@ -1091,8 +1106,8 @@ public struct UUID * RFC 4122 isn't very clear on how UUIDs should be generated from names. * It is possible that different implementations return different UUIDs * for the same input, so be warned. The implementation for UTF-8 strings - * and byte arrays used by $(D std.uuid) is compatible with Boost's implementation. - * $(D std.uuid) guarantees that the same input to this function will generate + * and byte arrays used by `std.uuid` is compatible with Boost's implementation. + * `std.uuid` guarantees that the same input to this function will generate * the same output at any time, on any system (this especially means endianness * doesn't matter). * @@ -1104,13 +1119,13 @@ public struct UUID * for strings and wstrings. It's always possible to pass wstrings and dstrings * by using the ubyte[] function overload (but be aware of endianness issues!). */ -@safe pure nothrow @nogc UUID sha1UUID(in char[] name, const UUID namespace = UUID.init) +@safe pure nothrow @nogc UUID sha1UUID(scope const(char)[] name, scope const UUID namespace = UUID.init) { return sha1UUID(cast(const(ubyte[]))name, namespace); } /// ditto -@safe pure nothrow @nogc UUID sha1UUID(in ubyte[] data, const UUID namespace = UUID.init) +@safe pure nothrow @nogc UUID sha1UUID(scope const(ubyte)[] data, scope const UUID namespace = UUID.init) { import std.digest.sha : SHA1; @@ -1195,7 +1210,25 @@ public struct UUID @safe UUID randomUUID() { import std.random : rndGen; - return randomUUID(rndGen); + // A PRNG with fewer than `n` bytes of state cannot produce + // every distinct `n` byte sequence. + static if (typeof(rndGen).sizeof >= UUID.sizeof) + { + return randomUUID(rndGen); + } + else + { + import std.random : unpredictableSeed, Xorshift192; + static assert(Xorshift192.sizeof >= UUID.sizeof); + static Xorshift192 rng; + static bool initialized; + if (!initialized) + { + rng.seed(unpredictableSeed); + initialized = true; + } + return randomUUID(rng); + } } /// ditto @@ -1245,18 +1278,6 @@ if (isInputRange!RNG && isIntegral!(ElementType!RNG)) auto uuid3 = randomUUID(gen); } -/* - * Original boost.uuid used Mt19937, we don't want - * to use anything worse than that. If Random is changed - * to something else, this assert and the randomUUID function - * have to be updated. - */ -@safe unittest -{ - import std.random : rndGen, Mt19937; - static assert(is(typeof(rndGen) == Mt19937)); -} - @safe unittest { import std.random : Xorshift192, unpredictableSeed; @@ -1311,8 +1332,7 @@ if (isSomeString!T) ///ditto UUID parseUUID(Range)(ref Range uuidRange) -if (isInputRange!Range - && is(Unqual!(ElementType!Range) == dchar)) +if (isInputRange!Range && isSomeChar!(ElementType!Range)) { import std.ascii : isHexDigit; import std.conv : ConvException, parse; @@ -1527,12 +1547,12 @@ if (isInputRange!Range return parseUUID(to!T(input)); } - foreach (S; AliasSeq!(char[], const(char)[], immutable(char)[], + static foreach (S; AliasSeq!(char[], const(char)[], immutable(char)[], wchar[], const(wchar)[], immutable(wchar)[], dchar[], const(dchar)[], immutable(dchar)[], immutable(char[]), immutable(wchar[]), immutable(dchar[]), TestForwardRange, TestInputRange)) - { + {{ //Verify examples. auto id = parseHelper!S("8AB3060E-2CBA-4F23-b74c-B52Db3BDFB46"); //no dashes @@ -1608,6 +1628,13 @@ if (isInputRange!Range //multiple trailing/leading characters assert(parseHelper!S("///8ab3060e2cba4f23b74cb52db3bdfb46||") == parseUUID("8ab3060e-2cba-4f23-b74c-b52db3bdfb46")); + }} + + // Test input range with non-dchar element type. + { + import std.utf : byCodeUnit; + auto range = "8AB3060E-2CBA-4F23-b74c-B52Db3BDFB46".byCodeUnit; + assert(parseUUID(range).data == [138, 179, 6, 14, 44, 186, 79, 35, 183, 76, 181, 45, 179, 189, 251, 70]); } } |