async Task <ArgsParseResult <object> > IArgumentParser.Parse(IImmutableList <string> args, Type[] genericTypes) { ArgsParseResult <T> parseResult = await Parse(args, genericTypes); return(parseResult.SuccessResult != null ? ArgsParseResult <object> .Success(parseResult.Failures, parseResult.SuccessResult.Value.Result !, parseResult.SuccessResult.Value.RemainingArgs) : ArgsParseResult <object> .Failure(parseResult.Failures)); }
/// <summary> /// For a list of strings, tries to parse those strings into instance of the supplied types. /// </summary> /// <param name="args">The input to be parsed, supplied as a list of string arguments</param> /// <param name="types">The types of which instances will be attempted to be created from the input.</param> /// <param name="errorOnRemainingArgs">Whether it is an error if the arguments weren't fully consumed.</param> /// <returns>A parsing result object. On success that will contain a list of objects with the same length /// and same types as supplied in <paramref name="types"/></returns> /// <exception cref="MissingParserException">If there was no parser found for one of the supplied types. /// You must register a parser using <see cref="AddArgumentParser{T}"/> for each type.</exception> /// <exception cref="InvalidOperationException">If the requested types cannot be parsed, /// because their types or respective parsers are not implemented correctly.</exception> public async Task <ArgsParseResult <List <object> > > ParseRaw( IImmutableList <string> args, IEnumerable <Type> types, bool errorOnRemainingArgs = false) { var allRemainingArgs = args; var results = new List <object>(); bool success = true; var failures = new List <Failure>(); foreach (var type in types) { Type?queryType = type.IsGenericType ? type.BaseType : type; if (queryType == null || queryType.IsGenericType) { throw new InvalidOperationException($"generic type {type} need a non-generic base type"); } if (!_parsers.TryGetValue(queryType, out IArgumentParser? parser)) { throw new MissingParserException(typeWithoutParser: type); } Debug.Assert(parser != null, "try-get succeeded and the dictionary does not contain null values"); Type[] genericTypes = type.IsGenericType ? type.GenericTypeArguments : new Type[] { }; ArgsParseResult <object> parseResult; try { parseResult = await parser.Parse(allRemainingArgs, genericTypes); } catch (ArgumentOutOfRangeException) { failures.Add(new Failure(ErrorRelevanceConfidence.Unlikely, "too few arguments")); success = false; break; } failures.AddRange(parseResult.Failures); if (parseResult.SuccessResult != null) { Success <object> successResult = parseResult.SuccessResult.Value; results.Add(successResult.Result); allRemainingArgs = successResult.RemainingArgs; } else { success = false; break; } } if (success && errorOnRemainingArgs && allRemainingArgs.Any()) { success = false; failures.Add(new Failure(ErrorRelevanceConfidence.Unlikely, "too many arguments")); } return(success ? ArgsParseResult <List <object> > .Success(failures.ToImmutableList(), results, allRemainingArgs) : ArgsParseResult <List <object> > .Failure(failures.ToImmutableList())); }
/// <summary> /// Try to parse arguments into <typeparamref name="T1"/> /// and get the respective <see cref="ArgsParseResult{T}"/>. /// This is a type-safe wrapper around <see cref="ArgsParser.ParseRaw"/>. /// </summary> /// <param name="argsParser">args parser used for parsing</param> /// <param name="args">List of string arguments to parse from.</param> /// <typeparam name="T1">Type to attempt to create an instance of.</typeparam> /// <returns>The respective parse result, /// containing an instance of <c>T1</c> on success.</returns> public static async Task <ArgsParseResult <T1> > TryParse <T1>( this ArgsParser argsParser, IImmutableList <string> args) { IEnumerable <Type> types = new[] { typeof(T1) }; ArgsParseResult <List <object> > parseResult = await argsParser.ParseRaw(args, types, errorOnRemainingArgs : true); if (parseResult.SuccessResult == null) { return(ArgsParseResult <T1> .Failure(parseResult.Failures)); } Success <List <object> > success = parseResult.SuccessResult.Value; return(ArgsParseResult <T1> .Success(parseResult.Failures, (T1)success.Result[0], success.RemainingArgs)); }