From 93c38d0f73e9c83509c5804d3f79ba01e4c4d571 Mon Sep 17 00:00:00 2001 From: hadashiA Date: Thu, 14 Sep 2023 12:36:16 +0900 Subject: [PATCH] Fix insufficient big-endian support --- src/Ulid.Unity/Assets/Scripts/Ulid/Ulid.cs | 76 ++++++++++++++-------- src/Ulid/Ulid.cs | 76 ++++++++++++++-------- 2 files changed, 100 insertions(+), 52 deletions(-) diff --git a/src/Ulid.Unity/Assets/Scripts/Ulid/Ulid.cs b/src/Ulid.Unity/Assets/Scripts/Ulid/Ulid.cs index 569b280..05d34fb 100644 --- a/src/Ulid.Unity/Assets/Scripts/Ulid/Ulid.cs +++ b/src/Ulid.Unity/Assets/Scripts/Ulid/Ulid.cs @@ -97,34 +97,46 @@ public DateTimeOffset Time var lower = Unsafe.As(ref Unsafe.AsRef(this.timestamp0)); var upper = Unsafe.As(ref Unsafe.AsRef(this.timestamp4)); var time = (long)BinaryPrimitives.ReverseEndianness(upper) + (((long)BinaryPrimitives.ReverseEndianness(lower)) << 16); - return DateTimeOffset.FromUnixTimeMilliseconds(time); } - - Span buffer = stackalloc byte[8]; - buffer[0] = timestamp5; - buffer[1] = timestamp4; - buffer[2] = timestamp3; - buffer[3] = timestamp2; - buffer[4] = timestamp1; - buffer[5] = timestamp0; // [6], [7] = 0 - - var timestampMilliseconds = Unsafe.As(ref MemoryMarshal.GetReference(buffer)); - return DateTimeOffset.FromUnixTimeMilliseconds(timestampMilliseconds); + else + { + // |A|B|C|D|E|F|G|H|... -> |A|B|C|D|E|F|0|0| + + // Upper |A|B|C|D| + // Lower |E|F| + // Time |A|B|C|D| + |E|F|0|0| + var upper = Unsafe.As(ref Unsafe.AsRef(this.timestamp0)); + var lower = Unsafe.As(ref Unsafe.AsRef(this.timestamp4)); + var time = ((long)upper << 32) + ((long)lower << 16); + return DateTimeOffset.FromUnixTimeMilliseconds(time); + } } } internal Ulid(long timestampMilliseconds, XorShift64 random) : this() { - // Get memory in stack and copy to ulid(Little->Big reverse order). ref var firstByte = ref Unsafe.As(ref timestampMilliseconds); - this.timestamp0 = Unsafe.Add(ref firstByte, 5); - this.timestamp1 = Unsafe.Add(ref firstByte, 4); - this.timestamp2 = Unsafe.Add(ref firstByte, 3); - this.timestamp3 = Unsafe.Add(ref firstByte, 2); - this.timestamp4 = Unsafe.Add(ref firstByte, 1); - this.timestamp5 = Unsafe.Add(ref firstByte, 0); + if (BitConverter.IsLittleEndian) + { + // Get memory in stack and copy to ulid(Little->Big reverse order). + this.timestamp0 = Unsafe.Add(ref firstByte, 5); + this.timestamp1 = Unsafe.Add(ref firstByte, 4); + this.timestamp2 = Unsafe.Add(ref firstByte, 3); + this.timestamp3 = Unsafe.Add(ref firstByte, 2); + this.timestamp4 = Unsafe.Add(ref firstByte, 1); + this.timestamp5 = Unsafe.Add(ref firstByte, 0); + } + else + { + this.timestamp0 = Unsafe.Add(ref firstByte, 0); + this.timestamp1 = Unsafe.Add(ref firstByte, 1); + this.timestamp2 = Unsafe.Add(ref firstByte, 2); + this.timestamp3 = Unsafe.Add(ref firstByte, 3); + this.timestamp4 = Unsafe.Add(ref firstByte, 4); + this.timestamp5 = Unsafe.Add(ref firstByte, 5); + } // Get first byte of randomness from Ulid Struct. Unsafe.WriteUnaligned(ref randomness0, random.Next()); // randomness0~7(but use 0~1 only) @@ -134,14 +146,26 @@ internal Ulid(long timestampMilliseconds, XorShift64 random) internal Ulid(long timestampMilliseconds, ReadOnlySpan randomness) : this() { - // Get memory in stack and copy to ulid(Little->Big reverse order). ref var firstByte = ref Unsafe.As(ref timestampMilliseconds); - this.timestamp0 = Unsafe.Add(ref firstByte, 5); - this.timestamp1 = Unsafe.Add(ref firstByte, 4); - this.timestamp2 = Unsafe.Add(ref firstByte, 3); - this.timestamp3 = Unsafe.Add(ref firstByte, 2); - this.timestamp4 = Unsafe.Add(ref firstByte, 1); - this.timestamp5 = Unsafe.Add(ref firstByte, 0); + if (BitConverter.IsLittleEndian) + { + // Get memory in stack and copy to ulid(Little->Big reverse order). + this.timestamp0 = Unsafe.Add(ref firstByte, 5); + this.timestamp1 = Unsafe.Add(ref firstByte, 4); + this.timestamp2 = Unsafe.Add(ref firstByte, 3); + this.timestamp3 = Unsafe.Add(ref firstByte, 2); + this.timestamp4 = Unsafe.Add(ref firstByte, 1); + this.timestamp5 = Unsafe.Add(ref firstByte, 0); + } + else + { + this.timestamp0 = Unsafe.Add(ref firstByte, 0); + this.timestamp1 = Unsafe.Add(ref firstByte, 1); + this.timestamp2 = Unsafe.Add(ref firstByte, 2); + this.timestamp3 = Unsafe.Add(ref firstByte, 3); + this.timestamp4 = Unsafe.Add(ref firstByte, 4); + this.timestamp5 = Unsafe.Add(ref firstByte, 5); + } ref var src = ref MemoryMarshal.GetReference(randomness); // length = 10 randomness0 = randomness[0]; diff --git a/src/Ulid/Ulid.cs b/src/Ulid/Ulid.cs index 569b280..05d34fb 100644 --- a/src/Ulid/Ulid.cs +++ b/src/Ulid/Ulid.cs @@ -97,34 +97,46 @@ public DateTimeOffset Time var lower = Unsafe.As(ref Unsafe.AsRef(this.timestamp0)); var upper = Unsafe.As(ref Unsafe.AsRef(this.timestamp4)); var time = (long)BinaryPrimitives.ReverseEndianness(upper) + (((long)BinaryPrimitives.ReverseEndianness(lower)) << 16); - return DateTimeOffset.FromUnixTimeMilliseconds(time); } - - Span buffer = stackalloc byte[8]; - buffer[0] = timestamp5; - buffer[1] = timestamp4; - buffer[2] = timestamp3; - buffer[3] = timestamp2; - buffer[4] = timestamp1; - buffer[5] = timestamp0; // [6], [7] = 0 - - var timestampMilliseconds = Unsafe.As(ref MemoryMarshal.GetReference(buffer)); - return DateTimeOffset.FromUnixTimeMilliseconds(timestampMilliseconds); + else + { + // |A|B|C|D|E|F|G|H|... -> |A|B|C|D|E|F|0|0| + + // Upper |A|B|C|D| + // Lower |E|F| + // Time |A|B|C|D| + |E|F|0|0| + var upper = Unsafe.As(ref Unsafe.AsRef(this.timestamp0)); + var lower = Unsafe.As(ref Unsafe.AsRef(this.timestamp4)); + var time = ((long)upper << 32) + ((long)lower << 16); + return DateTimeOffset.FromUnixTimeMilliseconds(time); + } } } internal Ulid(long timestampMilliseconds, XorShift64 random) : this() { - // Get memory in stack and copy to ulid(Little->Big reverse order). ref var firstByte = ref Unsafe.As(ref timestampMilliseconds); - this.timestamp0 = Unsafe.Add(ref firstByte, 5); - this.timestamp1 = Unsafe.Add(ref firstByte, 4); - this.timestamp2 = Unsafe.Add(ref firstByte, 3); - this.timestamp3 = Unsafe.Add(ref firstByte, 2); - this.timestamp4 = Unsafe.Add(ref firstByte, 1); - this.timestamp5 = Unsafe.Add(ref firstByte, 0); + if (BitConverter.IsLittleEndian) + { + // Get memory in stack and copy to ulid(Little->Big reverse order). + this.timestamp0 = Unsafe.Add(ref firstByte, 5); + this.timestamp1 = Unsafe.Add(ref firstByte, 4); + this.timestamp2 = Unsafe.Add(ref firstByte, 3); + this.timestamp3 = Unsafe.Add(ref firstByte, 2); + this.timestamp4 = Unsafe.Add(ref firstByte, 1); + this.timestamp5 = Unsafe.Add(ref firstByte, 0); + } + else + { + this.timestamp0 = Unsafe.Add(ref firstByte, 0); + this.timestamp1 = Unsafe.Add(ref firstByte, 1); + this.timestamp2 = Unsafe.Add(ref firstByte, 2); + this.timestamp3 = Unsafe.Add(ref firstByte, 3); + this.timestamp4 = Unsafe.Add(ref firstByte, 4); + this.timestamp5 = Unsafe.Add(ref firstByte, 5); + } // Get first byte of randomness from Ulid Struct. Unsafe.WriteUnaligned(ref randomness0, random.Next()); // randomness0~7(but use 0~1 only) @@ -134,14 +146,26 @@ internal Ulid(long timestampMilliseconds, XorShift64 random) internal Ulid(long timestampMilliseconds, ReadOnlySpan randomness) : this() { - // Get memory in stack and copy to ulid(Little->Big reverse order). ref var firstByte = ref Unsafe.As(ref timestampMilliseconds); - this.timestamp0 = Unsafe.Add(ref firstByte, 5); - this.timestamp1 = Unsafe.Add(ref firstByte, 4); - this.timestamp2 = Unsafe.Add(ref firstByte, 3); - this.timestamp3 = Unsafe.Add(ref firstByte, 2); - this.timestamp4 = Unsafe.Add(ref firstByte, 1); - this.timestamp5 = Unsafe.Add(ref firstByte, 0); + if (BitConverter.IsLittleEndian) + { + // Get memory in stack and copy to ulid(Little->Big reverse order). + this.timestamp0 = Unsafe.Add(ref firstByte, 5); + this.timestamp1 = Unsafe.Add(ref firstByte, 4); + this.timestamp2 = Unsafe.Add(ref firstByte, 3); + this.timestamp3 = Unsafe.Add(ref firstByte, 2); + this.timestamp4 = Unsafe.Add(ref firstByte, 1); + this.timestamp5 = Unsafe.Add(ref firstByte, 0); + } + else + { + this.timestamp0 = Unsafe.Add(ref firstByte, 0); + this.timestamp1 = Unsafe.Add(ref firstByte, 1); + this.timestamp2 = Unsafe.Add(ref firstByte, 2); + this.timestamp3 = Unsafe.Add(ref firstByte, 3); + this.timestamp4 = Unsafe.Add(ref firstByte, 4); + this.timestamp5 = Unsafe.Add(ref firstByte, 5); + } ref var src = ref MemoryMarshal.GetReference(randomness); // length = 10 randomness0 = randomness[0];