// This file is part of YamlDotNet - A .NET library for YAML. // Copyright (c) Antoine Aubry and contributors // // Permission is hereby granted, free of charge, to any person obtaining a copy of // this software and associated documentation files (the "Software"), to deal in // the Software without restriction, including without limitation the rights to // use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies // of the Software, and to permit persons to whom the Software is furnished to do // so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. using System; using System.Diagnostics.CodeAnalysis; using System.IO; using YamlDotNet.Core.Events; namespace YamlDotNet.Core { /// /// Extension methods that provide useful abstractions over . /// public static class ParserExtensions { /// /// Ensures that the current event is of the specified type, returns it and moves to the next event. /// /// Type of the . /// Returns the current event. /// If the current event is not of the specified type. public static T Consume(this IParser parser) where T : ParsingEvent { var required = parser.Require(); parser.MoveNext(); return required; } /// /// Checks whether the current event is of the specified type. /// If the event is of the specified type, returns it and moves to the next event. /// Otherwise returns null. /// /// Type of the . /// Returns true if the current event is of type T; otherwise returns null. public static bool TryConsume(this IParser parser, [MaybeNullWhen(false)] out T @event) where T : ParsingEvent { if (parser.Accept(out @event!)) { parser.MoveNext(); return true; } return false; } /// /// Enforces that the current event is of the specified type. /// /// Type of the . /// Returns the current event. /// If the current event is not of the specified type. public static T Require(this IParser parser) where T : ParsingEvent { if (!parser.Accept(out var required)) { var @event = parser.Current; if (@event == null) { throw new YamlException($"Expected '{typeof(T).Name}', got nothing."); } throw new YamlException(@event.Start, @event.End, $"Expected '{typeof(T).Name}', got '{@event.GetType().Name}' (at {@event.Start})."); } return required; } /// /// Checks whether the current event is of the specified type. /// /// Type of the event. /// Returns true if the current event is of type . Otherwise returns false. public static bool Accept(this IParser parser, [MaybeNullWhen(false)] out T @event) where T : ParsingEvent { if (parser.Current == null) { if (!parser.MoveNext()) { throw new EndOfStreamException(); } } if (parser.Current is T evt) { @event = evt; return true; } else { @event = default!; return false; } } /// /// Skips the current event and any nested event. /// public static void SkipThisAndNestedEvents(this IParser parser) { var depth = 0; do { var next = parser.Consume(); depth += next.NestingIncrease; } while (depth > 0); } [Obsolete("Please use Consume() instead")] public static T Expect(this IParser parser) where T : ParsingEvent { return parser.Consume(); } [Obsolete("Please use TryConsume(out var evt) instead")] [return: MaybeNull] public static T Allow(this IParser parser) where T : ParsingEvent { return parser.TryConsume(out var @event) ? @event : default; } [Obsolete("Please use Accept(out var evt) instead")] [return: MaybeNull] public static T Peek(this IParser parser) where T : ParsingEvent { return parser.Accept(out var @event) ? @event : default; } [Obsolete("Please use TryConsume(out var evt) or Accept(out var evt) instead")] public static bool Accept(this IParser parser) where T : ParsingEvent { return Accept(parser, out var _); } } }