using System; using System.Collections.Generic; using System.Linq; namespace Unity.VisualScripting.FullSerializer { /// /// The result of some sort of operation. A result is either successful or /// not, but if it is successful then there may be a set of warnings/messages /// associated with it. These warnings describe the performed error recovery /// operations. /// public struct fsResult { // We cache the empty string array so we can unify some collections // processing code. private static readonly string[] EmptyStringArray = { }; /// /// Is this result successful? /// /// /// This is intentionally a `success` state so that when the object is /// default constructed it defaults to a failure state. /// private bool _success; /// /// The warning or error messages associated with the result. This may be /// null if there are no messages. /// private List _messages; /// /// Adds a new message to this result. /// /// public void AddMessage(string message) { if (_messages == null) { _messages = new List(); } _messages.Add(message); } /// /// Adds only the messages from the other result into this result, /// ignoring the success/failure status of the other result. /// public void AddMessages(fsResult result) { if (result._messages == null) { return; } if (_messages == null) { _messages = new List(); } _messages.AddRange(result._messages); } /// /// Merges the other result into this one. If the other result failed, /// then this one too will have failed. /// /// /// Note that you can use += instead of this method so that you don't /// bury the actual method call that is generating the other fsResult. /// public fsResult Merge(fsResult other) { // Copy success over _success = _success && other._success; // Copy messages over if (other._messages != null) { if (_messages == null) { _messages = new List(other._messages); } else { _messages.AddRange(other._messages); } } return this; } /// /// A successful result. /// public static fsResult Success = new fsResult { _success = true }; /// /// Create a result that is successful but contains the given warning /// message. /// public static fsResult Warn(string warning) { return new fsResult { _success = true, _messages = new List { warning } }; } /// /// Create a result that failed. /// public static fsResult Fail(string warning) { return new fsResult { _success = false, _messages = new List { warning } }; } // TODO: how to make sure this is only used as +=? /// /// Only use this as +=! /// public static fsResult operator +(fsResult a, fsResult b) { return a.Merge(b); } /// /// Did this result fail? If so, you can see the reasons why in /// `RawMessages`. /// public bool Failed => _success == false; /// /// Was the result a success? Note that even successful operations may /// have warning messages (`RawMessages`) associated with them. /// public bool Succeeded => _success; /// /// Does this result have any warnings? This says nothing about if it /// failed or succeeded, just if it has warning messages associated with /// it. /// public bool HasWarnings => _messages != null && _messages.Any(); /// /// A simply utility method that will assert that this result is /// successful. If it is not, then an exception is thrown. /// public fsResult AssertSuccess() { if (Failed) { throw AsException; } return this; } /// /// A simple utility method that will assert that this result is /// successful and that there are no warning messages. This throws an /// exception if either of those asserts are false. /// public fsResult AssertSuccessWithoutWarnings() { if (Failed || RawMessages.Any()) { throw AsException; } return this; } /// /// Utility method to convert the result to an exception. This method is /// only defined is `Failed` returns true. /// public Exception AsException { get { if (!Failed && !RawMessages.Any()) { throw new Exception("Only a failed result can be converted to an exception"); } return new Exception(FormattedMessages); } } public IEnumerable RawMessages { get { if (_messages != null) { return _messages; } return EmptyStringArray; } } public string FormattedMessages => string.Join(",\n", RawMessages.ToArray()); } }