// 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(ParserResultType tag, TypeInfo typeInfo) { this.tag = tag; this.typeInfo = typeInfo; } /// /// Parser result type discriminator, defined as enumeration. /// public ParserResultType Tag { get { return this.tag; } } public TypeInfo TypeInfo { get { return typeInfo; } } } /// /// 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> { private readonly T value; internal Parsed(T value, TypeInfo typeInfo) : base(ParserResultType.Parsed, typeInfo) { this.value = value; } internal Parsed(T value) : this(value, TypeInfo.Create(value.GetType())) { } /// /// Gets the instance with parsed values. /// public T Value { get { return value; } } /// /// 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) { var other = obj as Parsed; if (other != null) { 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> { private readonly IEnumerable errors; internal NotParsed(TypeInfo typeInfo, IEnumerable errors) : base(ParserResultType.NotParsed, typeInfo) { this.errors = errors; } /// /// Gets the sequence of parsing errors. /// public IEnumerable Errors { get { return errors; } } /// /// 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) { var other = obj as NotParsed; if (other != null) { 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); } } }