Ejemplo n.º 1
0
        public int?ReadStartArray()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Array);

            if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
            {
                if (_isConformanceLevelCheckEnabled && CborConformanceLevelHelpers.RequiresDefiniteLengthItems(ConformanceLevel))
                {
                    throw new FormatException("Indefinite-length items are not supported under the current conformance level.");
                }

                AdvanceBuffer(1);
                PushDataItem(CborMajorType.Array, null);
                return(null);
            }
            else
            {
                ulong arrayLength = ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes);

                if (arrayLength > (ulong)_buffer.Length)
                {
                    throw new FormatException("Insufficient buffer size for declared definite length in CBOR data item.");
                }

                AdvanceBuffer(1 + additionalBytes);
                PushDataItem(CborMajorType.Array, (int)arrayLength);
                return((int)arrayLength);
            }
        }
Ejemplo n.º 2
0
        public bool TryReadTextString(Span <char> destination, out int charsWritten)
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.TextString);

            if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
            {
                return(TryReadChunkedTextStringConcatenated(destination, out charsWritten));
            }

            int byteLength = checked ((int)ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes));

            EnsureBuffer(1 + additionalBytes + byteLength);

            ReadOnlySpan <byte> encodedSlice = _buffer.Span.Slice(1 + additionalBytes, byteLength);

            int charLength = ValidateUtf8AndGetCharCount(encodedSlice);

            if (charLength > destination.Length)
            {
                charsWritten = 0;
                return(false);
            }

            s_utf8Encoding.GetChars(encodedSlice, destination);
            AdvanceBuffer(1 + additionalBytes + byteLength);
            AdvanceDataItemCounters();
            charsWritten = charLength;
            return(true);
        }
Ejemplo n.º 3
0
        public void ReadEndMap()
        {
            if (_remainingDataItems == null)
            {
                CborInitialByte value = PeekInitialByte();

                if (value.InitialByte != CborInitialByte.IndefiniteLengthBreakByte)
                {
                    throw new InvalidOperationException("Not at end of indefinite-length map.");
                }

                if (!_isEvenNumberOfDataItemsRead)
                {
                    throw new FormatException("CBOR Map types require an even number of key/value combinations");
                }

                PopDataItem(expectedType: CborMajorType.Map);
                AdvanceDataItemCounters();
                AdvanceBuffer(1);
            }
            else
            {
                PopDataItem(expectedType: CborMajorType.Map);
                AdvanceDataItemCounters();
            }
        }
Ejemplo n.º 4
0
        public ulong?ReadStartMap()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Map);

            if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
            {
                AdvanceBuffer(1);
                AdvanceDataItemCounters();
                PushDataItem(CborMajorType.Map, null);
                return(null);
            }
            else
            {
                ulong mapSize = ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes);

                if (mapSize > long.MaxValue)
                {
                    throw new OverflowException("Read CBOR map field count exceeds supported size.");
                }

                AdvanceBuffer(1 + additionalBytes);
                AdvanceDataItemCounters();
                PushDataItem(CborMajorType.Map, 2 * mapSize);
                return(mapSize);
            }
        }
Ejemplo n.º 5
0
        public double ReadDouble()
        {
            CborInitialByte     header = PeekInitialByte(expectedType: CborMajorType.Special);
            ReadOnlySpan <byte> buffer = _buffer.Span;
            double result;

            switch (header.AdditionalInfo)
            {
            case CborAdditionalInfo.Additional16BitData:
                EnsureBuffer(buffer, 3);
                result = ReadHalfBigEndian(buffer.Slice(1));
                AdvanceBuffer(3);
                AdvanceDataItemCounters();
                return(result);

            case CborAdditionalInfo.Additional32BitData:
                EnsureBuffer(buffer, 5);
                result = BinaryPrimitives.ReadSingleBigEndian(buffer.Slice(1));
                AdvanceBuffer(5);
                AdvanceDataItemCounters();
                return(result);

            case CborAdditionalInfo.Additional64BitData:
                EnsureBuffer(buffer, 9);
                result = BinaryPrimitives.ReadDoubleBigEndian(buffer.Slice(1));
                AdvanceBuffer(9);
                AdvanceDataItemCounters();
                return(result);

            default:
                throw new InvalidOperationException("CBOR data item does not encode a floating point number.");
            }
        }
Ejemplo n.º 6
0
        public bool TryReadByteString(Span <byte> destination, out int bytesWritten)
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.ByteString);

            if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
            {
                return(TryReadChunkedByteStringConcatenated(destination, out bytesWritten));
            }

            int length = checked ((int)ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes));

            EnsureBuffer(1 + additionalBytes + length);

            if (length > destination.Length)
            {
                bytesWritten = 0;
                return(false);
            }

            _buffer.Span.Slice(1 + additionalBytes, length).CopyTo(destination);
            AdvanceBuffer(1 + additionalBytes + length);
            AdvanceDataItemCounters();

            bytesWritten = length;
            return(true);
        }
Ejemplo n.º 7
0
        public string ReadTextString()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.TextString);

            if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
            {
                return(ReadChunkedTextStringConcatenated());
            }

            int length = checked ((int)ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes));

            EnsureBuffer(1 + additionalBytes + length);
            ReadOnlySpan <byte> encodedString = _buffer.Span.Slice(1 + additionalBytes, length);

            string result;

            try
            {
                result = s_utf8Encoding.GetString(encodedString);
            }
            catch (DecoderFallbackException e)
            {
                throw new FormatException("Text string payload is not a valid UTF8 string.", e);
            }

            AdvanceBuffer(1 + additionalBytes + length);
            AdvanceDataItemCounters();
            return(result);
        }
Ejemplo n.º 8
0
        // Implements major type 0,1 decoding per https://tools.ietf.org/html/rfc7049#section-2.1
        public long ReadInt64()
        {
            long value;
            int  additionalBytes;

            CborInitialByte header = PeekInitialByte();

            switch (header.MajorType)
            {
            case CborMajorType.UnsignedInteger:
                value = checked ((long)ReadUnsignedInteger(_buffer.Span, header, out additionalBytes));
                AdvanceBuffer(1 + additionalBytes);
                AdvanceDataItemCounters();
                return(value);

            case CborMajorType.NegativeInteger:
                value = checked (-1 - (long)ReadUnsignedInteger(_buffer.Span, header, out additionalBytes));
                AdvanceBuffer(1 + additionalBytes);
                AdvanceDataItemCounters();
                return(value);

            default:
                throw new InvalidOperationException("Data item major type mismatch.");
            }
        }
Ejemplo n.º 9
0
        public CborSpecialValue ReadSpecialValue()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Special);

            switch (header.AdditionalInfo)
            {
            case CborAdditionalInfo info when(byte) info < 24:
                AdvanceBuffer(1);

                AdvanceDataItemCounters();
                return((CborSpecialValue)header.AdditionalInfo);

            case CborAdditionalInfo.Additional8BitData:
                EnsureBuffer(2);
                byte value = _buffer.Span[1];

                if (value < 32)
                {
                    throw new FormatException("Two-byte CBOR special value must be between 32 and 255.");
                }

                AdvanceBuffer(2);
                AdvanceDataItemCounters();
                return((CborSpecialValue)value);

            default:
                throw new InvalidOperationException("CBOR data item does not encode a special value.");
            }
        }
Ejemplo n.º 10
0
        // Unsigned integer decoding https://tools.ietf.org/html/rfc7049#section-2.1
        private static ulong ReadUnsignedInteger(ReadOnlySpan <byte> buffer, CborInitialByte header, out int additionalBytes)
        {
            switch (header.AdditionalInfo)
            {
            case CborAdditionalInfo x when(x < CborAdditionalInfo.Additional8BitData):
                additionalBytes = 0;

                return((ulong)x);

            case CborAdditionalInfo.Additional8BitData:
                EnsureBuffer(buffer, 2);
                additionalBytes = 1;
                return(buffer[1]);

            case CborAdditionalInfo.Additional16BitData:
                EnsureBuffer(buffer, 3);
                additionalBytes = 2;
                return(BinaryPrimitives.ReadUInt16BigEndian(buffer.Slice(1)));

            case CborAdditionalInfo.Additional32BitData:
                EnsureBuffer(buffer, 5);
                additionalBytes = 4;
                return(BinaryPrimitives.ReadUInt32BigEndian(buffer.Slice(1)));

            case CborAdditionalInfo.Additional64BitData:
                EnsureBuffer(buffer, 9);
                additionalBytes = 8;
                return(BinaryPrimitives.ReadUInt64BigEndian(buffer.Slice(1)));

            default:
                throw new FormatException("initial byte contains invalid integer encoding data");
            }
        }
Ejemplo n.º 11
0
        // Returns the next CBOR negative integer encoding according to
        // https://tools.ietf.org/html/rfc7049#section-2.1
        public ulong ReadCborNegativeIntegerEncoding()
        {
            CborInitialByte header = Peek(expectedType: CborMajorType.NegativeInteger);
            ulong           value  = ReadUnsignedInteger(header, out int additionalBytes);

            AdvanceBuffer(1 + additionalBytes);
            return(value);
        }
Ejemplo n.º 12
0
        public static void Peek_SingleByteBuffer_ShouldReturnSameByte(byte initialByte)
        {
            ReadOnlySpan <byte> buffer = stackalloc byte[] { initialByte };
            var             reader     = new CborValueReader(buffer);
            CborInitialByte header     = reader.Peek();

            Assert.Equal(initialByte, header.InitialByte);
        }
Ejemplo n.º 13
0
        public CborTag ReadTag()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Tag);
            ulong           tag    = ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes);

            AdvanceBuffer(1 + additionalBytes);
            // NB tag reads do not advance data item counters
            _isTagContext = true;
            return((CborTag)tag);
        }
Ejemplo n.º 14
0
        public ulong?ReadStartArray()
        {
            CborInitialByte header      = PeekInitialByte(expectedType: CborMajorType.Array);
            ulong           arrayLength = checked ((ulong)ReadUnsignedInteger(header, out int additionalBytes));

            AdvanceBuffer(1 + additionalBytes);
            _remainingDataItems--;

            PushDataItem(CborMajorType.Array, arrayLength);
            return(arrayLength);
        }
Ejemplo n.º 15
0
        // Implements major type 2 decoding per https://tools.ietf.org/html/rfc7049#section-2.1
        public byte[] ReadByteString()
        {
            CborInitialByte header = Peek(expectedType: CborMajorType.ByteString);
            int             length = checked ((int)ReadUnsignedInteger(header, out int additionalBytes));

            EnsureBuffer(1 + additionalBytes + length);
            byte[] result = new byte[length];
            _buffer.Slice(1 + additionalBytes, length).CopyTo(result);
            AdvanceBuffer(1 + additionalBytes + length);
            return(result);
        }
Ejemplo n.º 16
0
        public void ReadStartByteStringIndefiniteLength()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.ByteString);

            if (header.AdditionalInfo != CborAdditionalInfo.IndefiniteLength)
            {
                throw new InvalidOperationException("CBOR text string is not of indefinite length.");
            }

            PushDataItem(CborMajorType.ByteString, expectedNestedItems: null);
            AdvanceBuffer(1);
        }
Ejemplo n.º 17
0
        // Implements major type 3 decoding per https://tools.ietf.org/html/rfc7049#section-2.1
        public string ReadTextString()
        {
            CborInitialByte header = Peek(expectedType: CborMajorType.TextString);
            int             length = checked ((int)ReadUnsignedInteger(header, out int additionalBytes));

            EnsureBuffer(1 + additionalBytes + length);
            ReadOnlySpan <byte> encodedString = _buffer.Slice(1 + additionalBytes, length);
            string result = s_utf8Encoding.GetString(encodedString);

            AdvanceBuffer(1 + additionalBytes + length);
            return(result);
        }
Ejemplo n.º 18
0
        public void ReadNull()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Special);

            switch (header.AdditionalInfo)
            {
            case CborAdditionalInfo.SpecialValueNull:
                AdvanceBuffer(1);
                AdvanceDataItemCounters();
                return;

            default:
                throw new InvalidOperationException("CBOR data item does not encode a null value.");
            }
        }
Ejemplo n.º 19
0
        public bool ReadBoolean()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Simple);

            bool result = header.AdditionalInfo switch
            {
                CborAdditionalInfo.SimpleValueFalse => false,
                CborAdditionalInfo.SimpleValueTrue => true,
                _ => throw new InvalidOperationException("CBOR data item does not encode a boolean value."),
            };

            AdvanceBuffer(1);
            AdvanceDataItemCounters();
            return(result);
        }
Ejemplo n.º 20
0
        public ulong?ReadStartMap()
        {
            CborInitialByte header      = PeekInitialByte(expectedType: CborMajorType.Map);
            ulong           arrayLength = checked ((ulong)ReadUnsignedInteger(header, out int additionalBytes));

            AdvanceBuffer(1 + additionalBytes);
            _remainingDataItems--;

            if (arrayLength > long.MaxValue)
            {
                throw new OverflowException("Read CBOR map field count exceeds supported size.");
            }

            PushDataItem(CborMajorType.Map, 2 * arrayLength);
            return(arrayLength);
        }
Ejemplo n.º 21
0
        private ulong PeekUnsignedInteger(out int additionalBytes)
        {
            CborInitialByte header = PeekInitialByte();

            switch (header.MajorType)
            {
            case CborMajorType.UnsignedInteger:
                ulong value = ReadUnsignedInteger(_buffer.Span, header, out additionalBytes);
                return(value);

            case CborMajorType.NegativeInteger:
                throw new OverflowException();

            default:
                throw new InvalidOperationException("Data item major type mismatch.");
            }
        }
Ejemplo n.º 22
0
        // Implements major type 0 decoding per https://tools.ietf.org/html/rfc7049#section-2.1
        public ulong ReadUInt64()
        {
            CborInitialByte header = Peek();

            switch (header.MajorType)
            {
            case CborMajorType.UnsignedInteger:
                ulong value = ReadUnsignedInteger(header, out int additionalBytes);
                AdvanceBuffer(1 + additionalBytes);
                return(value);

            case CborMajorType.NegativeInteger:
                throw new OverflowException();

            default:
                throw new InvalidOperationException("Data item major type mismatch.");
            }
        }
Ejemplo n.º 23
0
        public ulong?ReadStartArray()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Array);

            if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
            {
                PushDataItem(CborMajorType.Array, null);
                AdvanceBuffer(1);
                return(null);
            }
            else
            {
                ulong arrayLength = ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes);
                PushDataItem(CborMajorType.Array, arrayLength);
                AdvanceBuffer(1 + additionalBytes);
                return(arrayLength);
            }
        }
Ejemplo n.º 24
0
        public byte[] ReadByteString()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.ByteString);

            if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
            {
                return(ReadChunkedByteStringConcatenated());
            }

            int length = checked ((int)ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes));

            EnsureBuffer(1 + additionalBytes + length);
            byte[] result = new byte[length];
            _buffer.Slice(1 + additionalBytes, length).CopyTo(result);
            AdvanceBuffer(1 + additionalBytes + length);
            AdvanceDataItemCounters();
            return(result);
        }
Ejemplo n.º 25
0
        public string ReadTextString()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.TextString);

            if (header.AdditionalInfo == CborAdditionalInfo.IndefiniteLength)
            {
                return(ReadChunkedTextStringConcatenated());
            }

            int length = checked ((int)ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes));

            EnsureBuffer(1 + additionalBytes + length);
            ReadOnlySpan <byte> encodedString = _buffer.Span.Slice(1 + additionalBytes, length);
            string result = s_utf8Encoding.GetString(encodedString);

            AdvanceBuffer(1 + additionalBytes + length);
            AdvanceDataItemCounters();
            return(result);
        }
Ejemplo n.º 26
0
        public void ReadEndArray()
        {
            if (_remainingDataItems == null)
            {
                CborInitialByte value = PeekInitialByte();

                if (value.InitialByte != CborInitialByte.IndefiniteLengthBreakByte)
                {
                    throw new InvalidOperationException("Not at end of indefinite-length array.");
                }

                PopDataItem(expectedType: CborMajorType.Array);
                AdvanceBuffer(1);
            }
            else
            {
                PopDataItem(expectedType: CborMajorType.Array);
            }
        }
Ejemplo n.º 27
0
        public bool TryReadByteString(Span <byte> destination, out int bytesWritten)
        {
            CborInitialByte header = Peek(expectedType: CborMajorType.ByteString);
            int             length = checked ((int)ReadUnsignedInteger(header, out int additionalBytes));

            EnsureBuffer(1 + additionalBytes + length);

            if (length > destination.Length)
            {
                bytesWritten = 0;
                return(false);
            }

            _buffer.Slice(1 + additionalBytes, length).CopyTo(destination);
            AdvanceBuffer(1 + additionalBytes + length);

            bytesWritten = length;
            return(true);
        }
Ejemplo n.º 28
0
        private long PeekSignedInteger(out int additionalBytes)
        {
            CborInitialByte header = PeekInitialByte();
            long            value;

            switch (header.MajorType)
            {
            case CborMajorType.UnsignedInteger:
                value = checked ((long)ReadUnsignedInteger(_buffer.Span, header, out additionalBytes));
                return(value);

            case CborMajorType.NegativeInteger:
                value = checked (-1 - (long)ReadUnsignedInteger(_buffer.Span, header, out additionalBytes));
                return(value);

            default:
                throw new InvalidOperationException("Data item major type mismatch.");
            }
        }
Ejemplo n.º 29
0
        public bool ReadBoolean()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Special);

            switch (header.AdditionalInfo)
            {
            case CborAdditionalInfo.SpecialValueFalse:
                AdvanceBuffer(1);
                AdvanceDataItemCounters();
                return(false);

            case CborAdditionalInfo.SpecialValueTrue:
                AdvanceBuffer(1);
                AdvanceDataItemCounters();
                return(true);

            default:
                throw new InvalidOperationException("CBOR data item does not encode a boolean value.");
            }
        }
Ejemplo n.º 30
0
        public bool TryReadTextString(Span <char> destination, out int charsWritten)
        {
            CborInitialByte header     = Peek(expectedType: CborMajorType.TextString);
            int             byteLength = checked ((int)ReadUnsignedInteger(header, out int additionalBytes));

            EnsureBuffer(1 + additionalBytes + byteLength);

            ReadOnlySpan <byte> encodedSlice = _buffer.Slice(1 + additionalBytes, byteLength);
            int charLength = s_utf8Encoding.GetCharCount(encodedSlice);

            if (charLength > destination.Length)
            {
                charsWritten = 0;
                return(false);
            }

            s_utf8Encoding.GetChars(encodedSlice, destination);
            AdvanceBuffer(1 + additionalBytes + byteLength);
            charsWritten = charLength;
            return(true);
        }