// Copyright Epic Games, Inc. All Rights Reserved. using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; namespace EpicGames.Perforce { /// /// Base class for returning untyped response data /// public class PerforceResponse { /// /// Stores the response data /// protected object InternalData { get; } /// /// Constructor /// /// The response data public PerforceResponse(object data) { InternalData = data; } /// /// True if the response is successful /// #pragma warning disable IDE0083 // Use pattern matching - "is not" is not supported by version 8 of the language and this library is used by UGS public bool Succeeded => !(InternalData is PerforceError); #pragma warning restore IDE0083 // Use pattern matching /// /// True if the response is an error /// public bool Failed => InternalData is PerforceError; /// /// Accessor for the succcessful response data. Throws an exception if the response is an error. /// public object Data { get { EnsureSuccess(); return InternalData; } } /// /// Returns the info data. /// public PerforceInfo? Info => InternalData as PerforceInfo; /// /// Returns the error data, or null if this is a succesful response. /// public PerforceError? Error => InternalData as PerforceError; /// /// Returns the io data, or null if this is a regular response. /// public PerforceIo? Io => InternalData as PerforceIo; /// /// Throws an exception if the response is an error /// public void EnsureSuccess() { PerforceError? error = InternalData as PerforceError; if (error != null) { throw new PerforceException(error); } } /// /// Returns a string representation of this object for debugging /// /// String representation of the object for debugging public override string? ToString() { return InternalData.ToString(); } } /// /// Represents a successful Perforce response of the given type, or an error. Throws a PerforceException with the error /// text if the response value is attempted to be accessed and an error has occurred. /// /// Type of data returned on success public class PerforceResponse : PerforceResponse where T : class { /// /// Constructor /// /// The successful response data public PerforceResponse(T data) : base(data) { } /// /// Constructor /// /// The info data public PerforceResponse(PerforceInfo info) : base(info) { } /// /// Constructor /// /// The error data public PerforceResponse(PerforceError error) : base(error) { } /// /// Construct a typed response from an untyped response /// /// The untyped response public PerforceResponse(PerforceResponse untypedResponse) : base(untypedResponse.Error ?? untypedResponse.Info ?? (object)(T)untypedResponse.Data) { } /// /// Accessor for the succcessful response data. Throws an exception if the response is an error. /// public new T Data { get { T? result = InternalData as T; if (result == null) { if (InternalData is PerforceInfo) { throw new PerforceException($"Expected record of type '{typeof(T).Name}', got info: {InternalData}"); } else if (InternalData is PerforceError) { throw new PerforceException($"{InternalData}"); } else { throw new PerforceException($"Expected record of type '{typeof(T).Name}', got: {InternalData}"); } } return result; } } } /// /// Extension methods for responses /// public static class PerforceResponseExtensions { /// /// Whether all responses in this list are successful /// public static bool Succeeded(this IEnumerable> responses) where T : class { return responses.All(x => x.Succeeded); } /// /// Sequence of all the error responses. /// public static IEnumerable GetErrors(this IEnumerable> responses) where T : class { foreach (PerforceResponse response in responses) { PerforceError? error = response.Error; if (error != null) { yield return error; } } } /// /// Throws an exception if any response is an error /// public static void EnsureSuccess(this IEnumerable> responses) where T : class { foreach (PerforceResponse response in responses) { response.EnsureSuccess(); } } /// /// Unwrap a task returning a response object /// public static async Task UnwrapAsync(this Task> response) where T : class { return (await response).Data; } } }