Beispiel #1
0
        internal static unsafe Guid Read(ref ProtoReader.State state)
        {
            // note: we can't use a stackalloc-span here because the compiler doesn't trust
            // state, which is a ref-local (and can store spans), not to store it; since we *don't*
            // do that, we can be evil
            byte *ptr       = stackalloc byte[MAX_LENGTH];
            var   available = state.ReadBytes(new Span <byte>(ptr, MAX_LENGTH));

            char standardFormat;

            switch (available.Length)
            {
            case 0:
                return(Guid.Empty);

            case 16:     // treat as big-endian bytes
                // expand those bytes to hex, backwards so we don't overwrite live data
                int write = 32;
                for (int i = 15; i >= 0; i--)
                {
                    var val = ptr[i];
                    ptr[--write] = ToHex(val & 0b1111);
                    ptr[--write] = ToHex((val >> 4) & 0b1111);
                }
                available      = new Span <byte>(ptr, 32);
                standardFormat = 'N';
                break;

            case 32:     // no hyphens
                standardFormat = 'N';
                break;

            case 36:     // hyphens
                standardFormat = 'D';
                break;

            default:
                ThrowHelper.Format($"Unexpected Guid length: {available.Length}");
                return(default);
            }

            if (!(Utf8Parser.TryParse(available, out Guid guid, out int bytes, standardFormat) && bytes == available.Length))
            {
                ThrowHelper.Format($"Failed to read Guid: '{Encoding.UTF8.GetString(ptr, available.Length)}'");
            }

            return(guid);