From a3e5ce5f5a6f5fbcafa5f71cc7873ccbf6a9a479 Mon Sep 17 00:00:00 2001 From: ForeverZer0 Date: Wed, 25 Aug 2021 00:55:43 -0400 Subject: [PATCH] Added callbacks to TagReader class to permit user-handled parsing --- SharpNBT/Events/TagEventArgs.cs | 34 +++++++++++++++++ SharpNBT/Events/TagHandledEventArgs.cs | 52 ++++++++++++++++++++++++++ SharpNBT/Events/TagReaderCallback.cs | 12 ++++++ SharpNBT/TagReader.cs | 32 ++++++++++++---- 4 files changed, 122 insertions(+), 8 deletions(-) create mode 100644 SharpNBT/Events/TagEventArgs.cs create mode 100644 SharpNBT/Events/TagHandledEventArgs.cs create mode 100644 SharpNBT/Events/TagReaderCallback.cs diff --git a/SharpNBT/Events/TagEventArgs.cs b/SharpNBT/Events/TagEventArgs.cs new file mode 100644 index 0000000..81b70ce --- /dev/null +++ b/SharpNBT/Events/TagEventArgs.cs @@ -0,0 +1,34 @@ +using System; +using JetBrains.Annotations; + +namespace SharpNBT +{ + /// + /// Arguments supplied with tag-related events. + /// + public class TagEventArgs : EventArgs + { + /// + /// Gets a constant describing the basic NBT type of the tag. + /// + public TagType Type { get; } + + /// + /// Gets the parsed instance. + /// + [NotNull] + public Tag Tag { get; } + + /// + /// Creates a new instance of the class. + /// + /// A constant describing the basic NBT type of the tag. + /// The parsed instance. + /// Thrown when is . + public TagEventArgs(TagType type, [NotNull] Tag tag) + { + Type = type; + Tag = tag ?? throw new ArgumentNullException(nameof(tag)); + } + } +} \ No newline at end of file diff --git a/SharpNBT/Events/TagHandledEventArgs.cs b/SharpNBT/Events/TagHandledEventArgs.cs new file mode 100644 index 0000000..7bdf9f4 --- /dev/null +++ b/SharpNBT/Events/TagHandledEventArgs.cs @@ -0,0 +1,52 @@ +using System; +using System.ComponentModel; +using System.IO; +using JetBrains.Annotations; + +namespace SharpNBT +{ + /// + /// Arguments supplied when an event that can be handled by an event subscriber. + /// + public class TagHandledEventArgs : HandledEventArgs + { + /// + /// Gets a constant describing the basic NBT type of the tag. + /// + public TagType Type { get; } + + /// + /// Gets flag indicating if this tag is named, only when a tag is a direct child of a . + /// + public bool IsNamed { get; } + + /// + /// Gets the stream being read from, positioned at the beginning of the tag payload. + /// + /// When handling this event, the stream position must be moved to the end of the payload, ready for the next tag to be parsed. + /// + [NotNull] + public Stream Stream { get; } + + /// + /// Gets or sets the resulting tag from this event being handled. + /// + /// This property must set to a non-null value when is . + [CanBeNull] + public Tag Result { get; set; } + + /// + /// Creates a new instance of the class. + /// + /// A constant describing the basic NBT type of the tag. + /// Flag indicating if this tag is named, only when a tag is a direct child of a . + /// The stream being read from, positioned at the beginning of the tag payload. + /// Thrown when is . + public TagHandledEventArgs(TagType type, bool isNamed, [NotNull] Stream stream) + { + Type = type; + IsNamed = isNamed; + Stream = stream ?? throw new ArgumentNullException(nameof(stream)); + } + } +} \ No newline at end of file diff --git a/SharpNBT/Events/TagReaderCallback.cs b/SharpNBT/Events/TagReaderCallback.cs new file mode 100644 index 0000000..4f7b7b6 --- /dev/null +++ b/SharpNBT/Events/TagReaderCallback.cs @@ -0,0 +1,12 @@ +using System; + +namespace SharpNBT +{ + /// + /// Handler for events used with the class. + /// + /// A type derived from . + /// The instance invoking the event. + /// Any relevant args to be supplied with the callback, + public delegate void TagReaderCallback(TagReader reader, T args) where T : EventArgs; +} \ No newline at end of file diff --git a/SharpNBT/TagReader.cs b/SharpNBT/TagReader.cs index 44a5b2f..3c54912 100644 --- a/SharpNBT/TagReader.cs +++ b/SharpNBT/TagReader.cs @@ -7,12 +7,7 @@ using JetBrains.Annotations; namespace SharpNBT { - /// - /// Delegate type for tag-related events that can occur within the class. - /// - /// - public delegate void TagReadCallback(TagReader reader, TagType type, Tag tag); - + /// /// Provides methods for reading NBT data from a stream. /// @@ -22,7 +17,9 @@ namespace SharpNBT /// /// Occurs when a tag has been fully deserialized from the stream. /// - public event TagReadCallback TagRead; + public event TagReaderCallback TagRead; + + public event TagReaderCallback TagEncountered; /// /// Gets the underlying stream this is operating on. @@ -351,6 +348,13 @@ namespace SharpNBT [NotNull] private Tag ReadTag(TagType type, bool named) { + var result = OnTagEncountered(type, named); + if (result != null) + { + OnTagRead(result); + return result; + } + Tag tag = type switch { TagType.End => new EndTag(), @@ -447,7 +451,19 @@ namespace SharpNBT /// Invokes the event when a tag has been fully deserialized from the . /// /// The deserialized instance. - protected virtual void OnTagRead(Tag tag) => TagRead?.Invoke(this, tag.Type, tag); + protected virtual void OnTagRead(Tag tag) => TagRead?.Invoke(this, new TagEventArgs(tag.Type, tag)); + + [CanBeNull] + protected virtual Tag OnTagEncountered(TagType type, bool named) + { + // Early out if no subscribers. + if (TagEncountered is null) + return null; + + var args = new TagHandledEventArgs(type, named, BaseStream); + TagEncountered.Invoke(this, args); + return args.Handled ? args.Result : null; + } } } \ No newline at end of file