public bool TryGetDecimal(Guid publicId, out decimal id) { Span <byte> idBytes = stackalloc byte[16]; var decimals = MemoryMarshal.Cast <byte, decimal>(idBytes); var decimalComponents = MemoryMarshal.Cast <byte, int>(idBytes); // Invalid input if sign-and-scale component (4 bytes) are non-zero or max value is exceeded if (!TryGetIdBytes(publicId, idBytes) || DecimalStructure.GetSignAndScale(decimalComponents) != 0 || (id = decimals[0]) > DistributedIdGenerator.MaxValue) { id = default; return(false); } return(true); }
private static Guid Guid(decimal value) { var decimals = MemoryMarshal.CreateSpan(ref value, length: 1); var components = MemoryMarshal.Cast <decimal, int>(decimals); var lo = DecimalStructure.GetLo(components); var mid = DecimalStructure.GetMid(components); var hi = (uint)DecimalStructure.GetHi(components); var signAndScale = DecimalStructure.GetSignAndScale(components); Span <byte> bytes = stackalloc byte[16]; BinaryPrimitives.TryWriteInt32LittleEndian(bytes, 0); BinaryPrimitives.TryWriteUInt16LittleEndian(bytes[4..], (ushort)(hi >> 16));
/// <summary> /// Validates that the given ID is valid, and returns its components. /// </summary> private static (int SignAndScale, int Hi, int Mid, int Lo) ExtractAndValidateIdComponents(decimal id) { if (id < 0m) { throw new ArgumentOutOfRangeException(); } // Extract the components var decimals = MemoryMarshal.CreateReadOnlySpan(ref id, length: 1); var components = MemoryMarshal.Cast <decimal, int>(decimals); var signAndScale = DecimalStructure.GetSignAndScale(components); var hi = DecimalStructure.GetHi(components); var lo = DecimalStructure.GetLo(components); var mid = DecimalStructure.GetMid(components); // Validate format and range if (id > DistributedIdGenerator.MaxValue || signAndScale != 0) { throw new ArgumentException($"The ID must be positive, have no decimal places, and consist of no more than 28 digits.", nameof(id)); } return(signAndScale, hi, mid, lo); }