Skip to content

Commit 55b8b2e

Browse files
committed
Implement IParsable<T> for url parameters
1 parent 4e18b84 commit 55b8b2e

File tree

29 files changed

+985
-73
lines changed

29 files changed

+985
-73
lines changed

global.json

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,7 @@
11
{
22
"sdk": {
3-
"version": "8.0.400",
3+
"version": "9.0.100",
44
"rollForward": "latestFeature",
55
"allowPrerelease": false
6-
},
7-
"version": "8.8.0-alpha.1",
8-
"doc_current": "main",
9-
"doc_branch": "main"
6+
}
107
}

src/Elastic.Clients.Elasticsearch/_Shared/Core/DateTime/Duration.cs

+38-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
// See the LICENSE file in the project root for more information.
44

55
using System;
6+
using System.Collections.Generic;
7+
using System.Diagnostics.CodeAnalysis;
68
using System.Globalization;
79
using System.Text.Json;
810
using System.Text.Json.Serialization;
@@ -15,7 +17,13 @@ namespace Elastic.Clients.Elasticsearch;
1517
/// Represents a duration value.
1618
/// </summary>
1719
[JsonConverter(typeof(DurationConverter))]
18-
public sealed class Duration : IComparable<Duration>, IEquatable<Duration>, IUrlParameter
20+
public sealed class Duration :
21+
IComparable<Duration>,
22+
IEquatable<Duration>,
23+
IUrlParameter
24+
#if NET7_0_OR_GREATER
25+
, IParsable<Duration>
26+
#endif
1927
{
2028
private const double MicrosecondsInATick = 0.1; // 10 ticks = 1 microsecond
2129
private const double MillisecondsInADay = MillisecondsInAnHour * 24;
@@ -390,6 +398,35 @@ private static string ExponentFormat(double d)
390398
var exponent = (int)((bits >> 52) & 0x7ffL);
391399
return new string('#', Math.Max(2, exponent));
392400
}
401+
402+
#region IParsable
403+
404+
public static Duration Parse(string s, IFormatProvider? provider) =>
405+
TryParse(s, provider, out var result) ? result : throw new FormatException();
406+
407+
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider,
408+
[NotNullWhen(true)] out Duration? result)
409+
{
410+
if (s is null)
411+
{
412+
result = null;
413+
return false;
414+
}
415+
416+
try
417+
{
418+
result = new Duration(s);
419+
}
420+
catch
421+
{
422+
result = null;
423+
return false;
424+
}
425+
426+
return true;
427+
}
428+
429+
#endregion IParsable
393430
}
394431

395432
internal sealed class DurationConverter : JsonConverter<Duration>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
namespace Elastic.Clients.Elasticsearch;
2+
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Runtime.Serialization;
6+
7+
internal static class EnumValueParser<T>
8+
where T : struct, Enum
9+
{
10+
private static readonly Dictionary<string, T> ValueMap = new(StringComparer.OrdinalIgnoreCase);
11+
12+
static EnumValueParser()
13+
{
14+
foreach (var value in Enum.GetValues<T>())
15+
{
16+
var name = value.ToString();
17+
ValueMap[name] = value;
18+
19+
var field = typeof(T).GetField(name);
20+
var attribute = (EnumMemberAttribute?)Attribute.GetCustomAttribute(field!, typeof(EnumMemberAttribute));
21+
if (attribute?.Value is not null)
22+
{
23+
ValueMap[attribute.Value] = value;
24+
}
25+
}
26+
}
27+
28+
public static bool TryParse(string input, out T result)
29+
{
30+
return ValueMap.TryGetValue(input, out result);
31+
}
32+
33+
public static T Parse(string input)
34+
{
35+
if (ValueMap.TryGetValue(input, out var result))
36+
{
37+
return result;
38+
}
39+
40+
throw new ArgumentException($"Unknown member '{input}' for enum '{typeof(T).Name}'.");
41+
}
42+
}

src/Elastic.Clients.Elasticsearch/_Shared/Core/Fluent/Descriptor.cs

+5-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,11 @@ public abstract class Descriptor<TDescriptor> : Descriptor
5858
protected TDescriptor Self => _self;
5959

6060
[MethodImpl(MethodImplOptions.AggressiveInlining)]
61-
protected TDescriptor Assign<TValue>(TValue value, Action<TDescriptor, TValue> assign) => FluentAssign.Assign(_self, value, assign);
61+
protected TDescriptor Assign<TValue>(TValue value, Action<TDescriptor, TValue> assign)
62+
{
63+
assign(_self, value);
64+
return _self;
65+
}
6266
}
6367

6468
public abstract class SerializableDescriptor<TDescriptor> : Descriptor<TDescriptor>, ISelfSerializable

src/Elastic.Clients.Elasticsearch/_Shared/Core/Fluent/Fluent.cs

-19
This file was deleted.

src/Elastic.Clients.Elasticsearch/_Shared/Core/Infer/Field/Field.cs

+23
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ namespace Elastic.Clients.Elasticsearch;
2424
public sealed class Field :
2525
IEquatable<Field>,
2626
IUrlParameter
27+
#if NET7_0_OR_GREATER
28+
, IParsable<Field>
29+
#endif
2730
{
2831
private readonly object _comparisonValue;
2932
private readonly Type? _type;
@@ -197,6 +200,26 @@ public override int GetHashCode()
197200

198201
#endregion Equality
199202

203+
#region IParsable
204+
205+
public static Field Parse(string s, IFormatProvider? provider) =>
206+
TryParse(s, provider, out var result) ? result : throw new FormatException();
207+
208+
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider,
209+
[NotNullWhen(true)] out Field? result)
210+
{
211+
if (s is null)
212+
{
213+
result = null;
214+
return false;
215+
}
216+
217+
result = new Field(s);
218+
return true;
219+
}
220+
221+
#endregion IParsable
222+
200223
#region IUrlParameter
201224

202225
string IUrlParameter.GetString(ITransportConfiguration settings)

src/Elastic.Clients.Elasticsearch/_Shared/Core/Infer/Fields/Fields.cs

+42
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Collections;
77
using System.Collections.Generic;
88
using System.Diagnostics;
9+
using System.Diagnostics.CodeAnalysis;
910
using System.Linq;
1011
using System.Linq.Expressions;
1112
using System.Reflection;
@@ -19,6 +20,9 @@ public sealed class Fields :
1920
IEquatable<Fields>,
2021
IEnumerable<Field>,
2122
IUrlParameter
23+
#if NET7_0_OR_GREATER
24+
, IParsable<Fields>
25+
#endif
2226
{
2327
internal readonly List<Field> ListOfFields;
2428

@@ -183,6 +187,44 @@ public override bool Equals(object? obj) =>
183187

184188
#endregion IEnumerable
185189

190+
#region IParsable
191+
192+
public static Fields Parse(string s, IFormatProvider? provider) =>
193+
TryParse(s, provider, out var result) ? result : throw new FormatException();
194+
195+
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider,
196+
[NotNullWhen(true)] out Fields? result)
197+
{
198+
if (s is null)
199+
{
200+
result = null;
201+
return false;
202+
}
203+
204+
if (s.IsNullOrEmptyCommaSeparatedList(out var list))
205+
{
206+
result = new Fields();
207+
return true;
208+
}
209+
210+
var fields = new List<Field>();
211+
foreach (var item in list)
212+
{
213+
if (!Field.TryParse(item, provider, out var field))
214+
{
215+
result = null;
216+
return false;
217+
}
218+
219+
fields.Add(field);
220+
}
221+
222+
result = new Fields(fields);
223+
return true;
224+
}
225+
226+
#endregion IParsable
227+
186228
#region IUrlParameter
187229

188230
string IUrlParameter.GetString(ITransportConfiguration? settings)

src/Elastic.Clients.Elasticsearch/_Shared/Core/Infer/Id/Id.cs

+32-1
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,23 @@
44

55
using System;
66
using System.Diagnostics;
7+
using System.Diagnostics.CodeAnalysis;
78
using System.Globalization;
89
using System.Text.Json;
910
using System.Text.Json.Serialization;
11+
1012
using Elastic.Transport;
1113

1214
namespace Elastic.Clients.Elasticsearch;
1315

1416
[DebuggerDisplay("{DebugDisplay,nq}")]
1517
[JsonConverter(typeof(IdConverter))]
16-
public class Id : IEquatable<Id>, IUrlParameter
18+
public class Id :
19+
IEquatable<Id>,
20+
IUrlParameter
21+
#if NET7_0_OR_GREATER
22+
, IParsable<Id>
23+
#endif
1724
{
1825
public Id(string id)
1926
{
@@ -81,12 +88,16 @@ public override bool Equals(object obj)
8188
{
8289
case Id r:
8390
return Equals(r);
91+
8492
case string s:
8593
return Equals(s);
94+
8695
case int l:
8796
return Equals(l);
97+
8898
case long l:
8999
return Equals(l);
100+
90101
case Guid g:
91102
return Equals(g);
92103
}
@@ -108,4 +119,24 @@ public override int GetHashCode()
108119
public static bool operator ==(Id left, Id right) => Equals(left, right);
109120

110121
public static bool operator !=(Id left, Id right) => !Equals(left, right);
122+
123+
#region IParsable
124+
125+
public static Id Parse(string s, IFormatProvider? provider) =>
126+
TryParse(s, provider, out var result) ? result : throw new FormatException();
127+
128+
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider,
129+
[NotNullWhen(true)] out Id? result)
130+
{
131+
if (s is null)
132+
{
133+
result = null;
134+
return false;
135+
}
136+
137+
result = new Id(s);
138+
return true;
139+
}
140+
141+
#endregion IParsable
111142
}

0 commit comments

Comments
 (0)