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());
}
}