예제 #1
0
        public double ReadDouble()
        {
            CborInitialByte     header = PeekInitialByte(expectedType: CborMajorType.Simple);
            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.");
            }
        }
예제 #2
0
        public double ReadDouble()
        {
            CborInitialByte     header = PeekInitialByte(expectedType: CborMajorType.Simple);
            ReadOnlySpan <byte> buffer = GetRemainingBytes();
            double result;

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

            case CborAdditionalInfo.Additional32BitData:
                EnsureReadCapacity(buffer, 1 + sizeof(float));
                result = BinaryPrimitives.ReadSingleBigEndian(buffer.Slice(1));
                AdvanceBuffer(1 + sizeof(float));
                AdvanceDataItemCounters();
                return(result);

            case CborAdditionalInfo.Additional64BitData:
                EnsureReadCapacity(buffer, 1 + sizeof(double));
                result = BinaryPrimitives.ReadDoubleBigEndian(buffer.Slice(1));
                AdvanceBuffer(1 + sizeof(double));
                AdvanceDataItemCounters();
                return(result);

            default:
                throw new InvalidOperationException(SR.Cbor_Reader_NotAFloatEncoding);
            }
        }
예제 #3
0
        public CborSimpleValue ReadSimpleValue()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Simple);

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

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

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

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

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

            default:
                throw new InvalidOperationException("CBOR data item does not encode a simple value.");
            }
        }
예제 #4
0
        /// <summary>Reads the next data item as a single-precision floating point number (major type 7).</summary>
        /// <returns>The decoded value.</returns>
        /// <exception cref="InvalidOperationException"><para>The next data item does not have the correct major type.</para>
        /// <para>-or-</para>
        /// <para>The next simple value is not a floating-point number encoding.</para>
        /// <para>-or-</para>
        /// <para>The encoded value is a double-precision float.</para></exception>
        /// <exception cref="CborContentException"><para>The next value has an invalid CBOR encoding.</para>
        /// <para>-or-</para>
        /// <para>There was an unexpected end of CBOR encoding data.</para>
        /// <para>-or-</para>
        /// <para>The next value uses a CBOR encoding that is not valid under the current conformance mode.</para></exception>
        public float ReadSingle()
        {
            CborInitialByte     header = PeekInitialByte(expectedType: CborMajorType.Simple);
            ReadOnlySpan <byte> buffer = GetRemainingBytes();
            float result;

            switch (header.AdditionalInfo)
            {
            case CborAdditionalInfo.Additional16BitData:
                EnsureReadCapacity(buffer, 1 + sizeof(ushort));
                result = HalfHelpers.HalfToFloat(CborHelpers.ReadHalfBigEndian(buffer.Slice(1)));
                AdvanceBuffer(1 + sizeof(ushort));
                AdvanceDataItemCounters();
                return(result);

            case CborAdditionalInfo.Additional32BitData:
                EnsureReadCapacity(buffer, 1 + sizeof(float));
                result = CborHelpers.ReadSingleBigEndian(buffer.Slice(1));
                AdvanceBuffer(1 + sizeof(float));
                AdvanceDataItemCounters();
                return(result);

            case CborAdditionalInfo.Additional64BitData:
                throw new InvalidOperationException(SR.Cbor_Reader_ReadingAsLowerPrecision);

            default:
                throw new InvalidOperationException(SR.Cbor_Reader_NotAFloatEncoding);
            }
        }
예제 #5
0
        public ulong ReadCborNegativeIntegerRepresentation()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.NegativeInteger);
            ulong           value  = DecodeUnsignedInteger(header, GetRemainingBytes(), out int bytesRead);

            AdvanceBuffer(bytesRead);
            AdvanceDataItemCounters();
            return(value);
        }
예제 #6
0
        // Returns the next CBOR negative integer encoding according to
        // https://tools.ietf.org/html/rfc7049#section-2.1
        public ulong ReadCborNegativeIntegerEncoding()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.NegativeInteger);
            ulong           value  = ReadUnsignedInteger(_buffer.Span, header, out int additionalBytes);

            AdvanceBuffer(1 + additionalBytes);
            AdvanceDataItemCounters();
            return(value);
        }
예제 #7
0
        public bool ReadBoolean()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Simple);

            bool result = header.AdditionalInfo switch
            {
                (CborAdditionalInfo)CborSimpleValue.False => false,
                (CborAdditionalInfo)CborSimpleValue.True => true,
                _ => throw new InvalidOperationException(SR.Cbor_Reader_NotABooleanEncoding),
            };
예제 #8
0
        // Peek definite length for given data item
        private int DecodeDefiniteLength(CborInitialByte header, ReadOnlySpan <byte> data, out int bytesRead)
        {
            ulong length = DecodeUnsignedInteger(header, data, out bytesRead);

            // conservative check: ensure the buffer has the minimum required length for declared definite length.
            if (length > (ulong)(data.Length - bytesRead))
            {
                throw new CborContentException(SR.Cbor_Reader_DefiniteLengthExceedsBufferSize);
            }

            return((int)length);
        }
예제 #9
0
        public void ReadNull()
        {
            CborInitialByte header = PeekInitialByte(expectedType: CborMajorType.Simple);

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

            default:
                throw new InvalidOperationException("CBOR data item does not encode a null value.");
            }
        }
예제 #10
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);
        }
예제 #11
0
        private ulong PeekUnsignedInteger(out int bytesRead)
        {
            CborInitialByte header = PeekInitialByte();

            switch (header.MajorType)
            {
            case CborMajorType.UnsignedInteger:
                ulong value = DecodeUnsignedInteger(header, GetRemainingBytes(), out bytesRead);
                return(value);

            case CborMajorType.NegativeInteger:
                throw new OverflowException();

            default:
                throw new InvalidOperationException(SR.Format(SR.Cbor_Reader_MajorTypeMismatch, (int)header.MajorType));
            }
        }
예제 #12
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.");
            }
        }
예제 #13
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.");
            }
        }
예제 #14
0
        // Unsigned integer decoding https://tools.ietf.org/html/rfc7049#section-2.1
        private ulong DecodeUnsignedInteger(CborInitialByte header, ReadOnlySpan <byte> data, out int bytesRead)
        {
            ulong result;

            switch (header.AdditionalInfo)
            {
            case CborAdditionalInfo x when(x < CborAdditionalInfo.Additional8BitData):
                bytesRead = 1;

                return((ulong)x);

            case CborAdditionalInfo.Additional8BitData:
                EnsureReadCapacity(data, 1 + sizeof(byte));
                result = data[1];

                if (result < (int)CborAdditionalInfo.Additional8BitData)
                {
                    ValidateIsNonStandardIntegerRepresentationSupported();
                }

                bytesRead = 1 + sizeof(byte);
                return(result);

            case CborAdditionalInfo.Additional16BitData:
                EnsureReadCapacity(data, 1 + sizeof(ushort));
                result = BinaryPrimitives.ReadUInt16BigEndian(data.Slice(1));

                if (result <= byte.MaxValue)
                {
                    ValidateIsNonStandardIntegerRepresentationSupported();
                }

                bytesRead = 1 + sizeof(ushort);
                return(result);

            case CborAdditionalInfo.Additional32BitData:
                EnsureReadCapacity(data, 1 + sizeof(uint));
                result = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(1));

                if (result <= ushort.MaxValue)
                {
                    ValidateIsNonStandardIntegerRepresentationSupported();
                }

                bytesRead = 1 + sizeof(uint);
                return(result);

            case CborAdditionalInfo.Additional64BitData:
                EnsureReadCapacity(data, 1 + sizeof(ulong));
                result = BinaryPrimitives.ReadUInt64BigEndian(data.Slice(1));

                if (result <= uint.MaxValue)
                {
                    ValidateIsNonStandardIntegerRepresentationSupported();
                }

                bytesRead = 1 + sizeof(ulong);
                return(result);

            default:
                throw new CborContentException(SR.Cbor_Reader_InvalidCbor_InvalidIntegerEncoding);
            }

            void ValidateIsNonStandardIntegerRepresentationSupported()
            {
                if (_isConformanceModeCheckEnabled && CborConformanceModeHelpers.RequiresCanonicalIntegerRepresentation(ConformanceMode))
                {
                    throw new CborContentException(SR.Format(SR.Cbor_ConformanceMode_NonCanonicalIntegerRepresentation, ConformanceMode));
                }
            }
        }
예제 #15
0
        // Unsigned integer decoding https://tools.ietf.org/html/rfc7049#section-2.1
        private ulong ReadUnsignedInteger(ReadOnlySpan <byte> buffer, CborInitialByte header, out int additionalBytes)
        {
            ulong result;

            switch (header.AdditionalInfo)
            {
            case CborAdditionalInfo x when(x < CborAdditionalInfo.Additional8BitData):
                additionalBytes = 0;

                return((ulong)x);

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

                if (result < (int)CborAdditionalInfo.Additional8BitData)
                {
                    ValidateIsNonStandardIntegerRepresentationSupported();
                }

                additionalBytes = 1;
                return(result);

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

                if (result <= byte.MaxValue)
                {
                    ValidateIsNonStandardIntegerRepresentationSupported();
                }

                additionalBytes = 2;
                return(result);

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

                if (result <= ushort.MaxValue)
                {
                    ValidateIsNonStandardIntegerRepresentationSupported();
                }

                additionalBytes = 4;
                return(result);

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

                if (result <= uint.MaxValue)
                {
                    ValidateIsNonStandardIntegerRepresentationSupported();
                }

                additionalBytes = 8;
                return(result);

            default:
                throw new FormatException("initial byte contains invalid integer encoding data.");
            }

            void ValidateIsNonStandardIntegerRepresentationSupported()
            {
                if (_isConformanceLevelCheckEnabled && CborConformanceLevelHelpers.RequiresMinimalIntegerRepresentation(ConformanceLevel))
                {
                    throw new FormatException("Non-minimal integer representations are not permitted under the current conformance level.");
                }
            }
        }