/// <summary>
        ///   Attempts to read the next value as an OCTET STRING with a specified tag, returning the contents
        ///   as a <see cref="ReadOnlyMemory{T}"/> over the original data.
        /// </summary>
        /// <param name="expectedTag">The tag to check for before reading.</param>
        /// <param name="contents">
        ///   On success, receives a <see cref="ReadOnlyMemory{T}"/> over the original data
        ///   corresponding to the value of the OCTET STRING.
        /// </param>
        /// <returns>
        ///   <see langword="true"/> and advances the reader if the OCTET STRING value had a primitive encoding,
        ///   <see langword="false"/> and does not advance the reader if it had a constructed encoding.
        /// </returns>
        /// <exception cref="AsnContentException">
        ///   the next value does not have the correct tag.
        ///
        ///   -or-
        ///
        ///   the length encoding is not valid under the current encoding rules.
        ///
        ///   -or-
        ///
        ///   the contents are not valid under the current encoding rules.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is
        ///   <see cref="TagClass.Universal"/>, but
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for
        ///   the method.
        /// </exception>
        /// <seealso cref="TryReadOctetString"/>
        public bool TryReadPrimitiveOctetString(out ReadOnlyMemory <byte> contents, Asn1Tag?expectedTag = null)
        {
            bool ret = AsnDecoder.TryReadPrimitiveOctetString(
                _data.Span,
                RuleSet,
                out ReadOnlySpan <byte> span,
                out int consumed,
                expectedTag);

            if (ret)
            {
                contents = AsnDecoder.Slice(_data, span);
                _data    = _data.Slice(consumed);
            }
            else
            {
                contents = default;
            }

            return(ret);
        }
Exemple #2
0
        /// <summary>
        ///   Write a single value which has already been encoded.
        /// </summary>
        /// <param name="value">The value to write.</param>
        /// <remarks>
        ///   This method only checks that the tag and length are encoded according to the current ruleset,
        ///   and that the end of the value is the end of the input. The contents are not evaluated for
        ///   semantic meaning.
        /// </remarks>
        /// <exception cref="ArgumentException">
        ///   <paramref name="value"/> could not be read under the current encoding rules.
        ///
        ///   -or-
        ///
        ///   <paramref name="value"/> has data beyond the end of the first value.
        /// </exception>
        public void WriteEncodedValue(ReadOnlySpan <byte> value)
        {
            // Is it legal under the current rules?
            bool read = AsnDecoder.TryReadEncodedValue(
                value,
                RuleSet,
                out _,
                out _,
                out _,
                out int consumed);

            if (!read || consumed != value.Length)
            {
                throw new ArgumentException(
                          SR.Argument_WriteEncodedValue_OneValueAtATime,
                          nameof(value));
            }

            EnsureWriteCapacity(value.Length);
            value.CopyTo(_buffer.AsSpan(_offset));
            _offset += value.Length;
        }
Exemple #3
0
        /// <summary>
        ///   Reads the next value as a BIT STRING with a specified tag, copying the value
        ///   into a provided destination buffer.
        /// </summary>
        /// <param name="destination">The buffer in which to write.</param>
        /// <param name="unusedBitCount">
        ///   On success, receives the number of bits in the last byte which were reported as
        ///   "unused" by the writer.
        /// </param>
        /// <param name="bytesWritten">
        ///   On success, receives the number of bytes written to <paramref name="destination"/>.
        /// </param>
        /// <param name="expectedTag">
        ///   The tag to check for before reading, or <see langword="null"/> for the default tag (Universal 1).
        /// </param>
        /// <returns>
        ///   <see langword="true"/> and advances the reader if <paramref name="destination"/> had sufficient
        ///   length to receive the value, otherwise
        ///   <see langword="false"/> and the reader does not advance.
        /// </returns>
        /// <exception cref="AsnContentException">
        ///   the next value does not have the correct tag.
        ///
        ///   -or-
        ///
        ///   the length encoding is not valid under the current encoding rules.
        ///
        ///   -or-
        ///
        ///   the contents are not valid under the current encoding rules.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is
        ///   <see cref="TagClass.Universal"/>, but
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for
        ///   the method.
        /// </exception>
        /// <seealso cref="TryReadPrimitiveBitString"/>
        /// <seealso cref="ReadBitString"/>
        public bool TryReadBitString(
            Span <byte> destination,
            out int unusedBitCount,
            out int bytesWritten,
            Asn1Tag?expectedTag = null)
        {
            bool ret = AsnDecoder.TryReadBitString(
                _data.Span,
                destination,
                RuleSet,
                out unusedBitCount,
                out int consumed,
                out bytesWritten,
                expectedTag);

            if (ret)
            {
                _data = _data.Slice(consumed);
            }

            return(ret);
        }
        /// <summary>
        ///   Reads the next value as a character with a specified tag, returning the contents
        ///   as an unprocessed <see cref="ReadOnlyMemory{T}"/> over the original data.
        /// </summary>
        /// <param name="expectedTag">The tag to check for before reading.</param>
        /// <param name="contents">
        ///   On success, receives a <see cref="ReadOnlyMemory{T}"/> over the original data
        ///   corresponding to the value of the character string.
        /// </param>
        /// <returns>
        ///   <see langword="true"/> and advances the reader if the character string value had a primitive encoding,
        ///   <see langword="false"/> and does not advance the reader if it had a constructed encoding.
        /// </returns>
        /// <remarks>
        ///   This method does not determine if the string used only characters defined by the encoding.
        /// </remarks>
        /// <exception cref="AsnContentException">
        ///   the next value does not have the correct tag.
        ///
        ///   -or-
        ///
        ///   the length encoding is not valid under the current encoding rules.
        ///
        ///   -or-
        ///
        ///   the contents are not valid under the current encoding rules.
        /// </exception>
        /// <exception cref="ArgumentException">
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is
        ///   <see cref="TagClass.Universal"/>, but
        ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not a character
        ///   string tag type.
        /// </exception>
        /// <seealso cref="TryReadCharacterStringBytes"/>
        public bool TryReadPrimitiveCharacterStringBytes(
            Asn1Tag expectedTag,
            out ReadOnlyMemory <byte> contents)
        {
            bool ret = AsnDecoder.TryReadPrimitiveCharacterStringBytes(
                _data.Span,
                RuleSet,
                expectedTag,
                out ReadOnlySpan <byte> span,
                out int consumed);

            if (ret)
            {
                contents = AsnDecoder.Slice(_data, span);
                _data    = _data.Slice(consumed);
            }
            else
            {
                contents = default;
            }

            return(ret);
        }
 internal ReadOnlySpan <byte> PeekEncodedValue()
 {
     AsnDecoder.ReadEncodedValue(_span, _ruleSet, out _, out _, out int consumed);
     return(_span.Slice(0, consumed));
 }
 /// <summary>
 ///   Reads the next value as an OCTET STRING with tag UNIVERSAL 4, returning the value
 ///   in a byte array.
 /// </summary>
 /// <param name="expectedTag">
 ///   The tag to check for before reading, or <see langword="null"/> for the default tag (Universal 4).
 /// </param>
 /// <returns>
 ///   A copy of the value in a newly allocated, precisely sized, array.
 /// </returns>
 /// <exception cref="AsnContentException">
 ///   the next value does not have the correct tag.
 ///
 ///   -or-
 ///
 ///   the length encoding is not valid under the current encoding rules.
 ///
 ///   -or-
 ///
 ///   the contents are not valid under the current encoding rules.
 /// </exception>
 /// <exception cref="ArgumentException">
 ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagClass"/> is
 ///   <see cref="TagClass.Universal"/>, but
 ///   <paramref name="expectedTag"/>.<see cref="Asn1Tag.TagValue"/> is not correct for
 ///   the method.
 /// </exception>
 /// <seealso cref="TryReadPrimitiveOctetString"/>
 /// <seealso cref="TryReadOctetString"/>
 public byte[] ReadOctetString(Asn1Tag?expectedTag = null)
 {
     byte[] ret = AsnDecoder.ReadOctetString(_data.Span, RuleSet, out int consumed, expectedTag);
     _data = _data.Slice(consumed);
     return(ret);
 }