/// <summary> /// Reads the next JSON token value from the source transcoded as a <see cref="string"/>. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of the JSON token that is not a string /// (i.e. other than <see cref="JsonTokenType.String"/> or <see cref="JsonTokenType.PropertyName"/>). /// <seealso cref="TokenType" /> /// </exception> /// <exception cref="ArgumentException"> /// Thrown if invalid UTF-8 byte sequences are detected while transcoding. /// </exception> public string GetStringValue() { if (TokenType != JsonTokenType.String && TokenType != JsonTokenType.PropertyName) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } ReadOnlySpan <byte> span = HasValueSequence ? ValueSequence.ToArray() : ValueSpan; #if BUILDING_INBOX_LIBRARY // TODO: https://github.com/dotnet/corefx/issues/33292 return(s_utf8Encoding.GetString(span)); #else if (span.IsEmpty) { return(string.Empty); } unsafe { fixed(byte *bytePtr = span) { // TODO: https://github.com/dotnet/corefx/issues/33292 return(s_utf8Encoding.GetString(bytePtr, span.Length)); } } #endif }
/// <summary> /// Parses the current JSON token value from the source as a <see cref="Guid"/>. /// Returns <see langword="true"/> if the entire UTF-8 encoded token value can be successfully /// parsed to a <see cref="Guid"/> value. Only supports <see cref="Guid"/> values with hyphens /// and without any surrounding decorations. /// Returns <see langword="false"/> otherwise. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of a JSON token that is not a <see cref="JsonTokenType.String"/>. /// <seealso cref="TokenType" /> /// </exception> public bool TryGetGuid(out Guid value) { if (TokenType != JsonTokenType.String) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } return(TryGetGuidCore(out value)); }
/// <summary> /// Parses the current JSON token value from the source as a <see cref="DateTimeOffset"/>. /// Returns <see langword="true"/> if the entire UTF-8 encoded token value can be successfully /// parsed to a <see cref="DateTimeOffset"/> value. /// Returns <see langword="false"/> otherwise. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of a JSON token that is not a <see cref="JsonTokenType.String"/>. /// <seealso cref="TokenType" /> /// </exception> public bool TryGetDateTimeOffset(out DateTimeOffset value) { if (TokenType != JsonTokenType.String) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } return(TryGetDateTimeOffsetCore(out value)); }
/// <summary> /// Reads the next JSON token value from the source transcoded as a <see cref="string"/>. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of the JSON token that is not a string /// (i.e. other than <see cref="JsonTokenType.String"/> or <see cref="JsonTokenType.PropertyName"/>). /// <seealso cref="TokenType" /> /// </exception> /// <exception cref="ArgumentException"> /// Thrown if invalid UTF-8 byte sequences are detected while transcoding. /// </exception> public string GetStringValue() { if (TokenType != JsonTokenType.String && TokenType != JsonTokenType.PropertyName) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } // TODO: https://github.com/dotnet/corefx/issues/33292 return(s_utf8Encoding.GetString(ValueSpan)); }
/// <summary> /// Parses the current JSON token value from the source as a <see cref="DateTimeOffset"/>. /// Returns <see langword="true"/> if the entire UTF-8 encoded token value can be successfully /// parsed to a <see cref="DateTimeOffset"/> value. /// Returns <see langword="false"/> otherwise. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of a JSON token that is not a <see cref="JsonTokenType.String"/>. /// <seealso cref="TokenType" /> /// </exception> public bool TryGetDateTimeOffset(out DateTimeOffset value) { if (TokenType != JsonTokenType.String) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } ReadOnlySpan <byte> span = stackalloc byte[0]; if (HasValueSequence) { long sequenceLength = ValueSequence.Length; if (!JsonReaderHelper.IsValidDateTimeOffsetParseLength(sequenceLength)) { value = default; return(false); } Debug.Assert(sequenceLength <= JsonConstants.MaximumEscapedDateTimeOffsetParseLength); Span <byte> stackSpan = stackalloc byte[(int)sequenceLength]; ValueSequence.CopyTo(stackSpan); span = stackSpan; } else { if (!JsonReaderHelper.IsValidDateTimeOffsetParseLength(ValueSpan.Length)) { value = default; return(false); } span = ValueSpan; } if (_stringHasEscaping) { return(JsonReaderHelper.TryGetEscapedDateTimeOffset(span, out value)); } Debug.Assert(span.IndexOf(JsonConstants.BackSlash) == -1); if (span.Length <= JsonConstants.MaximumDateTimeOffsetParseLength && JsonHelpers.TryParseAsISO(span, out DateTimeOffset tmp, out int bytesConsumed) && span.Length == bytesConsumed) { value = tmp; return(true); } value = default; return(false); }
/// <summary> /// Reads the next JSON token value from the source and parses it to a <see cref="DateTimeOffset"/>. /// Returns true if the entire UTF-8 encoded token value can be successfully /// parsed to a <see cref="DateTimeOffset"/> value. /// Returns false otherwise. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of a JSON token that is not a <see cref="JsonTokenType.String"/>. /// <seealso cref="TokenType" /> /// </exception> public bool TryGetDateTimeOffset(out DateTimeOffset value) { if (TokenType != JsonTokenType.String) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } ReadOnlySpan <byte> span = HasValueSequence ? ValueSequence.ToArray() : ValueSpan; return(JsonHelpers.TryParseAsISO(span, out value, out int bytesConsumed) && span.Length == bytesConsumed); }
/// <summary> /// Reads the next JSON token value from the source transcoded as a <see cref="string"/>. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of the JSON token that is not a string /// (i.e. other than <see cref="JsonTokenType.String"/> or <see cref="JsonTokenType.PropertyName"/>). /// <seealso cref="TokenType" /> /// </exception> /// <exception cref="ArgumentException"> /// Thrown if invalid UTF-8 byte sequences are detected while transcoding. /// </exception> public string GetStringValue() { if (TokenType != JsonTokenType.String && TokenType != JsonTokenType.PropertyName) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } ReadOnlySpan <byte> span = HasValueSequence ? ValueSequence.ToArray() : ValueSpan; // TODO: https://github.com/dotnet/corefx/issues/33292 return(s_utf8Encoding.GetString(span)); }
/// <summary> /// Parses the current JSON token value from the source as a <see cref="Guid"/>. /// Returns <see langword="true"/> if the entire UTF-8 encoded token value can be successfully /// parsed to a <see cref="Guid"/> value. Only supports <see cref="Guid"/> values with hyphens /// and without any surrounding decorations. /// Returns <see langword="false"/> otherwise. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of a JSON token that is not a <see cref="JsonTokenType.String"/>. /// <seealso cref="TokenType" /> /// </exception> public bool TryGetGuid(out Guid value) { if (TokenType != JsonTokenType.String) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } ReadOnlySpan <byte> span = stackalloc byte[0]; if (HasValueSequence) { long sequenceLength = ValueSequence.Length; if (sequenceLength > JsonConstants.MaximumEscapedGuidLength) { value = default; return(false); } Debug.Assert(sequenceLength <= JsonConstants.MaximumEscapedGuidLength); Span <byte> stackSpan = stackalloc byte[(int)sequenceLength]; ValueSequence.CopyTo(stackSpan); span = stackSpan; } else { if (ValueSpan.Length > JsonConstants.MaximumEscapedGuidLength) { value = default; return(false); } span = ValueSpan; } if (_stringHasEscaping) { return(JsonReaderHelper.TryGetEscapedGuid(span, out value)); } Debug.Assert(span.IndexOf(JsonConstants.BackSlash) == -1); if (span.Length == JsonConstants.MaximumFormatGuidLength && Utf8Parser.TryParse(span, out Guid tmp, out _, 'D')) { value = tmp; return(true); } value = default; return(false); }
/// <summary> /// Reads the next JSON token value from the source and parses it to a <see cref="Guid"/>. /// Returns <see langword="true"/> if the entire UTF-8 encoded token value can be successfully /// parsed to a <see cref="Guid"/> value. Only supports <see cref="Guid"/> values with hyphens /// and without any surrounding decorations. /// Returns <see langword="false"/> otherwise. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of a JSON token that is not a <see cref="JsonTokenType.String"/>. /// <seealso cref="TokenType" /> /// </exception> public bool TryGetGuid(out Guid value) { if (TokenType != JsonTokenType.String) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } ReadOnlySpan <byte> span = ValueSpan; Span <byte> stackSpan; if (HasValueSequence) { long sequenceLength = ValueSequence.Length; if (sequenceLength > JsonConstants.MaximumEscapedGuidLength) { value = default; return(false); } // Cannot create a span directly since it gets passed to instance methods on a ref struct. unsafe { byte *ptr = stackalloc byte[(int)sequenceLength]; stackSpan = new Span <byte>(ptr, (int)sequenceLength); } ValueSequence.CopyTo(stackSpan); span = stackSpan; } if (span.Length > JsonConstants.MaximumEscapedGuidLength) { value = default; return(false); } if (_stringHasEscaping) { return(JsonReaderHelper.TryGetEscapedGuid(span, out value)); } Debug.Assert(span.IndexOf(JsonConstants.BackSlash) == -1); if (span.Length != JsonConstants.MaximumFormatGuidLength) { value = default; return(false); } return(Utf8Parser.TryParse(span, out value, out int bytesConsumed) && span.Length == bytesConsumed); }
/// <summary> /// Parses the current JSON token value from the source and decodes the Base64 encoded JSON string as bytes. /// Returns <see langword="true"/> if the entire token value is encoded as valid Base64 text and can be successfully /// decoded to bytes. /// Returns <see langword="false"/> otherwise. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of a JSON token that is not a <see cref="JsonTokenType.String"/>. /// <seealso cref="TokenType" /> /// </exception> public bool TryGetBytesFromBase64(out byte[] value) { if (TokenType != JsonTokenType.String) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } ReadOnlySpan <byte> span = HasValueSequence ? ValueSequence.ToArray() : ValueSpan; if (_stringHasEscaping) { int idx = span.IndexOf(JsonConstants.BackSlash); Debug.Assert(idx != -1); return(JsonReaderHelper.TryGetUnescapedBase64Bytes(span, idx, out value)); } Debug.Assert(span.IndexOf(JsonConstants.BackSlash) == -1); return(JsonReaderHelper.TryDecodeBase64(span, out value)); }
/// <summary> /// Parses the current JSON token value from the source, unescaped, and transcoded as a <see cref="string"/>. /// </summary> /// <exception cref="InvalidOperationException"> /// Thrown if trying to get the value of the JSON token that is not a string /// (i.e. other than <see cref="JsonTokenType.String"/> or <see cref="JsonTokenType.PropertyName"/>). /// <seealso cref="TokenType" /> /// It will also throw when the JSON string contains invalid UTF-8 bytes, or invalid UTF-16 surrogates. /// </exception> public string GetString() { if (TokenType != JsonTokenType.String && TokenType != JsonTokenType.PropertyName) { throw ThrowHelper.GetInvalidOperationException_ExpectedString(TokenType); } ReadOnlySpan <byte> span = HasValueSequence ? ValueSequence.ToArray() : ValueSpan; if (_stringHasEscaping) { int idx = span.IndexOf(JsonConstants.BackSlash); Debug.Assert(idx != -1); return(JsonReaderHelper.GetUnescapedString(span, idx)); } Debug.Assert(span.IndexOf(JsonConstants.BackSlash) == -1); return(JsonReaderHelper.TranscodeHelper(span)); }