// Copyright 2005-2015 Giacomo Stelluti Scala & Contributors. All rights reserved. See License.md in the project root for license information. using System; using System.Collections.Generic; using System.Linq; namespace CommandLine { public sealed class TypeInfo { private readonly Type current; private readonly IEnumerable choices; private TypeInfo(Type current, IEnumerable choices) { this.current = current; this.choices = choices; } public Type Current { get { return this.current; } } public IEnumerable Choices { get { return this.choices; } } internal static TypeInfo Create(Type current) { return new TypeInfo(current, Enumerable.Empty()); } internal static TypeInfo Create(Type current, IEnumerable choices) { return new TypeInfo(current, choices); } } /// /// Discriminator enumeration of derivates. /// public enum ParserResultType { /// /// Value of type. /// Parsed, /// /// Value of type. /// NotParsed } /// /// Models a parser result. When inherited by , it contains an instance of type /// with parsed values. /// When inherited by , it contains a sequence of . /// /// The type with attributes that define the syntax of parsing rules. public abstract class ParserResult { private readonly ParserResultType tag; private readonly TypeInfo typeInfo; internal ParserResult(IEnumerable errors, TypeInfo typeInfo) { this.tag = ParserResultType.NotParsed; this.typeInfo = typeInfo ?? TypeInfo.Create(typeof(T)); Errors = errors ?? new Error[0]; Value = default; } internal ParserResult(T value, TypeInfo typeInfo) { Value = value ?? throw new ArgumentNullException(nameof(value)); this.tag = ParserResultType.Parsed; this.typeInfo = typeInfo ?? TypeInfo.Create(value.GetType()); Errors = new Error[0]; } /// /// Parser result type discriminator, defined as enumeration. /// public ParserResultType Tag { get { return this.tag; } } public TypeInfo TypeInfo { get { return typeInfo; } } /// /// Gets the instance with parsed values. If one or more errors occures, is returned. /// public T Value { get; } /// /// Gets the sequence of parsing errors. If there are no errors, then an empty IEnumerable is returned. /// public IEnumerable Errors { get; } } /// /// It contains an instance of type with parsed values. /// /// The type with attributes that define the syntax of parsing rules. public sealed class Parsed : ParserResult, IEquatable> { internal Parsed(T value, TypeInfo typeInfo) : base(value, typeInfo) { } internal Parsed(T value) : this(value, TypeInfo.Create(value.GetType())) { } /// /// Determines whether the specified is equal to the current . /// /// The to compare with the current . /// true if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { if (obj is Parsed other) { return Equals(other); } return base.Equals(obj); } /// /// Serves as a hash function for a particular type. /// /// A hash code for the current . public override int GetHashCode() { return new { Tag, Value }.GetHashCode(); } /// /// Returns a value that indicates whether the current instance and a specified have the same value. /// /// The instance to compare. /// true if this instance of and have the same value; otherwise, false. public bool Equals(Parsed other) { if (other == null) { return false; } return this.Tag.Equals(other.Tag) && Value.Equals(other.Value); } } /// /// It contains a sequence of . /// /// The type with attributes that define the syntax of parsing rules. public sealed class NotParsed : ParserResult, IEquatable> { internal NotParsed(TypeInfo typeInfo, IEnumerable errors) : base(errors, typeInfo) { } /// /// Determines whether the specified is equal to the current . /// /// The to compare with the current . /// true if the specified is equal to the current ; otherwise, false. public override bool Equals(object obj) { if (obj is NotParsed other) { return Equals(other); } return base.Equals(obj); } /// /// Serves as a hash function for a particular type. /// /// A hash code for the current . public override int GetHashCode() { return new { Tag, Errors }.GetHashCode(); } /// /// Returns a value that indicates whether the current instance and a specified have the same value. /// /// The instance to compare. /// true if this instance of and have the same value; otherwise, false. public bool Equals(NotParsed other) { if (other == null) { return false; } return this.Tag.Equals(other.Tag) && Errors.SequenceEqual(other.Errors); } } }