using System; namespace GitConverter.Lib.Models { /// /// Represents the outcome of a conversion operation. /// /// /// - Immutable value object intended to be returned from converter implementations and passed between layers. /// - Use the factory helpers and to create instances. /// - Contains a timestamp (UTC) to help diagnostics and logging. /// - Implements so callers can compare logical results. /// - Equality semantics: /// - Two ConversionResult instances are considered equal when their and /// normalized values are equal. The is intentionally /// excluded from equality because it represents creation time (diagnostic metadata) and not the logical /// outcome of the conversion. /// - If you need TimestampUtc to be part of equality for a specific scenario, implement a comparer or extend /// the type (for example ConversionResultWithMeta) rather than changing these semantics. /// public sealed class ConversionResult : IEquatable { /// /// The status of the conversion. /// public ConversionStatus Status { get; } /// /// Human-friendly message describing the result. Empty string when not provided. /// Use this to surface concise diagnostics to CLI users or logs. /// public string Message { get; } /// /// UTC timestamp when the result instance was created. /// public DateTime TimestampUtc { get; } /// /// True when the conversion succeeded. /// public bool IsSuccess => Status == ConversionStatus.Success; private ConversionResult(ConversionStatus status, string message) { Status = status; Message = message ?? string.Empty; TimestampUtc = DateTime.UtcNow; } /// /// Create a success result with an optional message. /// public static ConversionResult Success(string message = null) => new ConversionResult(ConversionStatus.Success, message); /// /// Create a failure result with an optional message describing the error. /// public static ConversionResult Failure(string message = null) => new ConversionResult(ConversionStatus.Failure, message); /// /// Returns a compact textual representation useful for logs. /// public override string ToString() => $"{Status}: {Message}"; /// /// Strongly-typed equality comparing logical result values. /// - Compares and (ordinal). /// - Does not consider in equality. /// public bool Equals(ConversionResult other) { if (ReferenceEquals(null, other)) return false; if (ReferenceEquals(this, other)) return true; return Status == other.Status && string.Equals(Message, other.Message, StringComparison.Ordinal); } /// /// Object equality override delegates to strongly-typed equality. /// public override bool Equals(object obj) => Equals(obj as ConversionResult); /// /// Hash code based on the logical equality components. /// public override int GetHashCode() { unchecked { // combine Status and Message (ordinal) into hash int hash = 17; hash = hash * 31 + Status.GetHashCode(); hash = hash * 31 + (Message != null ? StringComparer.Ordinal.GetHashCode(Message) : 0); return hash; } } /// /// Equality operator uses the same semantics as . /// public static bool operator ==(ConversionResult left, ConversionResult right) { if (ReferenceEquals(left, right)) return true; if (ReferenceEquals(left, null)) return false; return left.Equals(right); } /// /// Inequality operator. /// public static bool operator !=(ConversionResult left, ConversionResult right) => !(left == right); } /// /// Status codes for . /// public enum ConversionStatus { /// Conversion completed successfully. Success = 0, /// Conversion failed (see for details). Failure = 1 } }