-
Notifications
You must be signed in to change notification settings - Fork 481
/
Copy pathValueMapper.cs
106 lines (95 loc) · 4.15 KB
/
ValueMapper.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
// 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;
using CommandLine.Infrastructure;
using CSharpx;
using RailwaySharp.ErrorHandling;
namespace CommandLine.Core
{
static class ValueMapper
{
public static Result<
IEnumerable<SpecificationProperty>, Error>
MapValues(
IEnumerable<SpecificationProperty> specProps,
IEnumerable<string> values,
Func<IEnumerable<string>, Type, bool, Maybe<object>> converter)
{
var propAndErrors = MapValuesImpl(specProps, values, converter);
return Result.Succeed(
propAndErrors.Select(pe => pe.Item1),
propAndErrors.Select(pe => pe.Item2)
.OfType<Just<Error>>().Select(e => e.Value)
);
}
private static IEnumerable<Tuple<SpecificationProperty, Maybe<Error>>> MapValuesImpl(
IEnumerable<SpecificationProperty> specProps,
IEnumerable<string> values,
Func<IEnumerable<string>, Type, bool, Maybe<object>> converter)
{
if (specProps.Empty())
{
yield break;
}
var pt = specProps.First();
var taken = values.Take(pt.Specification.CountOfMaxNumberOfValues().GetValueOrDefault(values.Count()));
if (taken.Empty())
{
yield return
Tuple.Create(pt, pt.Specification.MakeErrorInCaseOfMinConstraint());
yield break;
}
var next = specProps.Skip(1).FirstOrDefault(s => s.Specification.IsValue()).ToMaybe();
if (pt.Specification.Max.IsJust()
&& next.IsNothing()
&& values.Skip(taken.Count()).Any())
{
yield return
Tuple.Create<SpecificationProperty, Maybe<Error>>(
pt, Maybe.Just<Error>(new SequenceOutOfRangeError(NameInfo.EmptyName)));
yield break;
}
yield return
converter(taken, pt.Property.PropertyType, pt.Specification.TargetType != TargetType.Sequence)
.MapValueOrDefault(
converted => Tuple.Create(pt.WithValue(Maybe.Just(converted)), Maybe.Nothing<Error>()),
Tuple.Create<SpecificationProperty, Maybe<Error>>(
pt, Maybe.Just<Error>(new BadFormatConversionError(NameInfo.EmptyName))));
var remainingSpecs = specProps.Skip(1);
var remainingValues = values.Skip(taken.Count());
if (remainingValues.Any() && remainingSpecs.Empty())
{
foreach ( var value in remainingValues )
{
yield return Tuple.Create<SpecificationProperty, Maybe<Error>>(pt, Maybe.Just<Error>(new UnknownValueError(value)));
}
}
foreach (var value in MapValuesImpl(remainingSpecs, remainingValues, converter))
{
yield return value;
}
}
private static Maybe<int> CountOfMaxNumberOfValues(this Specification specification)
{
switch (specification.TargetType)
{
case TargetType.Scalar:
return Maybe.Just(1);
case TargetType.Sequence:
if (specification.Max.IsJust())
{
return Maybe.Just(specification.Max.FromJustOrFail());
}
break;
}
return Maybe.Nothing<int>();
}
private static Maybe<Error> MakeErrorInCaseOfMinConstraint(this Specification specification)
{
return specification.Min.IsJust()
? Maybe.Just<Error>(new SequenceOutOfRangeError(NameInfo.EmptyName))
: Maybe.Nothing<Error>();
}
}
}