Skip to content

Commit eecd853

Browse files
committed
Fixed conversion bug from FdbTuple<..> to IFdbTuple, added support for remaining number types (short, byte, ...)
1 parent efb185f commit eecd853

File tree

4 files changed

+346
-34
lines changed

4 files changed

+346
-34
lines changed

FoundationDB.Client/Converters/FdbConverters.cs

Lines changed: 159 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#region BSD Licence
2-
/* Copyright (c) 2013, Doxense SARL
2+
/* Copyright (c) 2013-2015, Doxense SAS
33
All rights reserved.
44
55
Redistribution and use in source and binary forms, with or without
@@ -150,79 +150,195 @@ static FdbConverters()
150150
/// <summary>Register all the default converters</summary>
151151
private static void RegisterDefaultConverters()
152152
{
153+
//TODO: there is too much generic type combinations! need to refactor this ...
154+
153155
RegisterUnsafe<bool, Slice>((value) => Slice.FromByte(value ? (byte)1 : default(byte)));
154156
RegisterUnsafe<bool, byte[]>((value) => Slice.FromByte(value ? (byte)1 : default(byte)).GetBytes());
157+
RegisterUnsafe<bool, string>((value) => value ? "true" : "false");
158+
RegisterUnsafe<bool, sbyte>((value) => value ? (sbyte)1 : default(sbyte));
159+
RegisterUnsafe<bool, byte>((value) => value ? (byte)1 : default(byte));
160+
RegisterUnsafe<bool, short>((value) => value ? (short)1 : default(short));
161+
RegisterUnsafe<bool, ushort>((value) => value ? (ushort)1 : default(ushort));
155162
RegisterUnsafe<bool, int>((value) => value ? 1 : default(int));
156163
RegisterUnsafe<bool, uint>((value) => value ? 1U : default(uint));
157164
RegisterUnsafe<bool, long>((value) => value ? 1L : default(long));
158165
RegisterUnsafe<bool, ulong>((value) => value ? 1UL : default(ulong));
159-
RegisterUnsafe<bool, string>((value) => value ? "true" : "false");
160166
RegisterUnsafe<bool, double>((value) => value ? 0.0d : 1.0d);
161167
RegisterUnsafe<bool, float>((value) => value ? 0.0f : 1.0f);
162168

163169
RegisterUnsafe<int, Slice>((value) => Slice.FromInt32(value));
164170
RegisterUnsafe<int, byte[]>((value) => Slice.FromInt32(value).GetBytes());
165-
RegisterUnsafe<int, string>((value) => value.ToString(CultureInfo.InvariantCulture));
171+
RegisterUnsafe<int, string>((value) => value.ToString(CultureInfo.InvariantCulture)); //TODO: string table!
172+
RegisterUnsafe<int, bool>((value) => value != 0);
173+
RegisterUnsafe<int, sbyte>((value) => checked((sbyte)value));
174+
RegisterUnsafe<int, byte>((value) => checked((byte)value));
175+
RegisterUnsafe<int, short>((value) => checked((short)value));
176+
RegisterUnsafe<int, ushort>((value) => checked((ushort)value));
166177
RegisterUnsafe<int, uint>((value) => (uint)value);
167-
RegisterUnsafe<int, long>((value) => (long)value);
178+
RegisterUnsafe<int, long>((value) => value);
168179
RegisterUnsafe<int, ulong>((value) => (ulong)value);
169-
RegisterUnsafe<int, bool>((value) => value != 0);
180+
RegisterUnsafe<int, double>((value) => value);
181+
RegisterUnsafe<int, float>((value) => checked((float)value));
170182
RegisterUnsafe<int, FdbTupleAlias>((value) => (FdbTupleAlias)value);
171-
RegisterUnsafe<int, double>((value) => (double)value);
172-
RegisterUnsafe<int, float>((value) => { checked { return (float)value; } });
173183

174184
RegisterUnsafe<uint, Slice>((value) => Slice.FromUInt64(value));
175185
RegisterUnsafe<uint, byte[]>((value) => Slice.FromUInt64(value).GetBytes());
176-
RegisterUnsafe<uint, string>((value) => value.ToString(CultureInfo.InvariantCulture));
177-
RegisterUnsafe<uint, int>((value) => (int)value);
178-
RegisterUnsafe<uint, long>((value) => (long)value);
179-
RegisterUnsafe<uint, ulong>((value) => (ulong)value);
186+
RegisterUnsafe<uint, string>((value) => value.ToString(CultureInfo.InvariantCulture)); //TODO: string table!
180187
RegisterUnsafe<uint, bool>((value) => value != 0);
181-
RegisterUnsafe<uint, double>((value) => (double)value);
182-
RegisterUnsafe<uint, float>((value) => { checked { return (float)value; } });
188+
RegisterUnsafe<uint, sbyte>((value) => checked((sbyte)value));
189+
RegisterUnsafe<uint, byte>((value) => checked((byte)value));
190+
RegisterUnsafe<uint, short>((value) => checked((short)value));
191+
RegisterUnsafe<uint, ushort>((value) => checked((ushort)value));
192+
RegisterUnsafe<uint, int>((value) => (int)value);
193+
RegisterUnsafe<uint, long>((value) => value);
194+
RegisterUnsafe<uint, ulong>((value) => value);
195+
RegisterUnsafe<uint, double>((value) => value);
196+
RegisterUnsafe<uint, float>((value) => checked((float)value));
183197

184198
RegisterUnsafe<long, Slice>((value) => Slice.FromInt64(value));
185199
RegisterUnsafe<long, byte[]>((value) => Slice.FromInt64(value).GetBytes());
186-
RegisterUnsafe<long, string>((value) => value.ToString(CultureInfo.InvariantCulture));
187-
RegisterUnsafe<long, short>((value) => { checked { return (short)value; } });
188-
RegisterUnsafe<long, int>((value) => { checked { return (int)value; } });
200+
RegisterUnsafe<long, string>((value) => value.ToString(CultureInfo.InvariantCulture)); //TODO: string table!
201+
RegisterUnsafe<long, bool>((value) => value != 0);
202+
RegisterUnsafe<long, sbyte>((value) => checked((sbyte)value));
203+
RegisterUnsafe<long, byte>((value) => checked((byte)value));
204+
RegisterUnsafe<long, short>((value) => checked((short)value));
205+
RegisterUnsafe<long, ushort>((value) => checked((ushort)value));
206+
RegisterUnsafe<long, int>((value) => checked((int)value));
189207
RegisterUnsafe<long, uint>((value) => (uint)value);
190208
RegisterUnsafe<long, ulong>((value) => (ulong)value);
191-
RegisterUnsafe<long, bool>((value) => value != 0);
209+
RegisterUnsafe<long, double>((value) => checked((double)value));
210+
RegisterUnsafe<long, float>((value) => checked((float)value));
192211
RegisterUnsafe<long, TimeSpan>((value) => TimeSpan.FromTicks(value));
193-
RegisterUnsafe<long, double>((value) => { checked { return (double)value; } });
194-
RegisterUnsafe<long, float>((value) => { checked { return (float)value; } });
195212
RegisterUnsafe<long, Uuid64>((value) => new Uuid64(value));
196213
RegisterUnsafe<long, System.Net.IPAddress>((value) => new System.Net.IPAddress(value));
197214

198215
RegisterUnsafe<ulong, Slice>((value) => Slice.FromUInt64(value));
199216
RegisterUnsafe<ulong, byte[]>((value) => Slice.FromUInt64(value).GetBytes());
200-
RegisterUnsafe<ulong, string>((value) => value.ToString(CultureInfo.InvariantCulture));
201-
RegisterUnsafe<ulong, int>((value) => { checked { return (int)value; } });
202-
RegisterUnsafe<ulong, uint>((value) => { checked { return (uint)value; } });
203-
RegisterUnsafe<ulong, long>((value) => { checked { return (long)value; } });
217+
RegisterUnsafe<ulong, string>((value) => value.ToString(CultureInfo.InvariantCulture)); //TODO: string table!
204218
RegisterUnsafe<ulong, bool>((value) => value != 0);
205-
RegisterUnsafe<ulong, double>((value) => { checked { return (double)value; } });
206-
RegisterUnsafe<ulong, float>((value) => { checked { return (float)value; } });
219+
RegisterUnsafe<ulong, sbyte>((value) => checked((sbyte)value));
220+
RegisterUnsafe<ulong, byte>((value) => checked((byte)value));
221+
RegisterUnsafe<ulong, short>((value) => checked((short)value));
222+
RegisterUnsafe<ulong, ushort>((value) => checked((ushort)value));
223+
RegisterUnsafe<ulong, int>((value) => checked((int)value));
224+
RegisterUnsafe<ulong, uint>((value) => checked((uint)value));
225+
RegisterUnsafe<ulong, long>((value) => checked((long)value));
226+
RegisterUnsafe<ulong, double>((value) => checked((double)value));
227+
RegisterUnsafe<ulong, float>((value) => checked((float)value));
207228
RegisterUnsafe<ulong, Uuid64>((value) => new Uuid64(value));
229+
RegisterUnsafe<ulong, TimeSpan>((value) => TimeSpan.FromTicks(checked((long)value)));
230+
231+
RegisterUnsafe<short, Slice>((value) => Slice.FromInt32(value));
232+
RegisterUnsafe<short, byte[]>((value) => Slice.FromInt32(value).GetBytes());
233+
RegisterUnsafe<short, string>((value) => value.ToString(CultureInfo.InvariantCulture)); //TODO: string table!
234+
RegisterUnsafe<short, bool>((value) => value != 0);
235+
RegisterUnsafe<short, sbyte>((value) => checked((sbyte)value));
236+
RegisterUnsafe<short, byte>((value) => checked((byte)value));
237+
RegisterUnsafe<short, ushort>((value) => checked((ushort)value));
238+
RegisterUnsafe<short, int>((value) => value);
239+
RegisterUnsafe<short, uint>((value) => checked((uint)value));
240+
RegisterUnsafe<short, long>((value) => value);
241+
RegisterUnsafe<short, ulong>((value) => checked ((ulong)value));
242+
RegisterUnsafe<short, double>((value) => value);
243+
RegisterUnsafe<short, float>((value) => value);
244+
RegisterUnsafe<short, FdbTupleAlias>((value) => (FdbTupleAlias)value);
245+
246+
RegisterUnsafe<ushort, Slice>((value) => Slice.FromUInt64(value));
247+
RegisterUnsafe<ushort, byte[]>((value) => Slice.FromUInt64(value).GetBytes());
248+
RegisterUnsafe<ushort, string>((value) => value.ToString(CultureInfo.InvariantCulture)); //TODO: string table!
249+
RegisterUnsafe<ushort, bool>((value) => value != 0);
250+
RegisterUnsafe<ushort, byte>((value) => checked((byte)value));
251+
RegisterUnsafe<ushort, sbyte>((value) => checked((sbyte)value));
252+
RegisterUnsafe<ushort, short>((value) => checked((short)value));
253+
RegisterUnsafe<ushort, int>((value) => value);
254+
RegisterUnsafe<ushort, uint>((value) => value);
255+
RegisterUnsafe<ushort, long>((value) => value);
256+
RegisterUnsafe<ushort, ulong>((value) => value);
257+
RegisterUnsafe<ushort, double>((value) => value);
258+
RegisterUnsafe<ushort, float>((value) => value);
259+
260+
RegisterUnsafe<byte, Slice>((value) => Slice.FromInt32(value));
261+
RegisterUnsafe<byte, byte[]>((value) => Slice.FromInt32(value).GetBytes());
262+
RegisterUnsafe<byte, string>((value) => value.ToString(CultureInfo.InvariantCulture)); //TODO: string table!
263+
RegisterUnsafe<byte, bool>((value) => value != 0);
264+
RegisterUnsafe<byte, sbyte>((value) => checked((sbyte)value));
265+
RegisterUnsafe<byte, short>((value) => value);
266+
RegisterUnsafe<byte, ushort>((value) => value);
267+
RegisterUnsafe<byte, int>((value) => value);
268+
RegisterUnsafe<byte, uint>((value) => value);
269+
RegisterUnsafe<byte, long>((value) => value);
270+
RegisterUnsafe<byte, ulong>((value) => value);
271+
RegisterUnsafe<byte, double>((value) => value);
272+
RegisterUnsafe<byte, float>((value) => value);
273+
RegisterUnsafe<byte, FdbTupleAlias>((value) => (FdbTupleAlias)value);
274+
275+
RegisterUnsafe<sbyte, Slice>((value) => Slice.FromInt64(value));
276+
RegisterUnsafe<sbyte, byte[]>((value) => Slice.FromInt64(value).GetBytes());
277+
RegisterUnsafe<sbyte, string>((value) => value.ToString(CultureInfo.InvariantCulture)); //TODO: string table!
278+
RegisterUnsafe<sbyte, bool>((value) => value != 0);
279+
RegisterUnsafe<sbyte, byte>((value) => checked((byte)value));
280+
RegisterUnsafe<sbyte, short>((value) => value);
281+
RegisterUnsafe<sbyte, ushort>((value) => checked((ushort)value));
282+
RegisterUnsafe<sbyte, int>((value) => value);
283+
RegisterUnsafe<sbyte, uint>((value) => checked((uint)value));
284+
RegisterUnsafe<sbyte, long>((value) => value);
285+
RegisterUnsafe<sbyte, ulong>((value) => checked((ulong)value));
286+
RegisterUnsafe<sbyte, double>((value) => value);
287+
RegisterUnsafe<sbyte, float>((value) => value);
288+
289+
RegisterUnsafe<float, Slice>((value) => Slice.FromSingle(value));
290+
RegisterUnsafe<float, byte[]>((value) => Slice.FromSingle(value).GetBytes());
291+
RegisterUnsafe<float, string>((value) => value.ToString("R", CultureInfo.InvariantCulture));
292+
RegisterUnsafe<float, bool>((value) => !(value == 0f || float.IsNaN(value)));
293+
RegisterUnsafe<float, sbyte>((value) => checked((sbyte)value));
294+
RegisterUnsafe<float, byte>((value) => checked((byte)value));
295+
RegisterUnsafe<float, short>((value) => checked((short)value));
296+
RegisterUnsafe<float, ushort>((value) => checked((ushort)value));
297+
RegisterUnsafe<float, int>((value) => checked((int)value));
298+
RegisterUnsafe<float, uint>((value) => (uint)value);
299+
RegisterUnsafe<float, long>((value) => checked((long)value));
300+
RegisterUnsafe<float, ulong>((value) => (ulong)value);
301+
RegisterUnsafe<float, double>((value) => value);
302+
303+
RegisterUnsafe<double, Slice>((value) => Slice.FromDouble(value));
304+
RegisterUnsafe<double, byte[]>((value) => Slice.FromDouble(value).GetBytes());
305+
RegisterUnsafe<double, string>((value) => value.ToString("R", CultureInfo.InvariantCulture));
306+
RegisterUnsafe<double, bool>((value) => !(value == 0d || double.IsNaN(value)));
307+
RegisterUnsafe<double, sbyte>((value) => checked((sbyte)value));
308+
RegisterUnsafe<double, byte>((value) => checked((byte)value));
309+
RegisterUnsafe<double, short>((value) => checked((short)value));
310+
RegisterUnsafe<double, ushort>((value) => checked((ushort)value));
311+
RegisterUnsafe<double, int>((value) => checked((int)value));
312+
RegisterUnsafe<double, uint>((value) => (uint)value);
313+
RegisterUnsafe<double, long>((value) => checked((long)value));
314+
RegisterUnsafe<double, ulong>((value) => (ulong)value);
315+
RegisterUnsafe<double, float>((value) => checked((float)value));
208316

209317
RegisterUnsafe<string, Slice>((value) => Slice.FromString(value));
210318
RegisterUnsafe<string, byte[]>((value) => Slice.FromString(value).GetBytes());
319+
RegisterUnsafe<string, bool>((value) => !string.IsNullOrEmpty(value));
320+
RegisterUnsafe<string, sbyte>((value) => string.IsNullOrEmpty(value) ? default(sbyte) : SByte.Parse(value, CultureInfo.InvariantCulture));
321+
RegisterUnsafe<string, byte>((value) => string.IsNullOrEmpty(value) ? default(byte) : Byte.Parse(value, CultureInfo.InvariantCulture));
322+
RegisterUnsafe<string, short>((value) => string.IsNullOrEmpty(value) ? default(short) : Int16.Parse(value, CultureInfo.InvariantCulture));
323+
RegisterUnsafe<string, ushort>((value) => string.IsNullOrEmpty(value) ? default(ushort) : UInt16.Parse(value, CultureInfo.InvariantCulture));
211324
RegisterUnsafe<string, int>((value) => string.IsNullOrEmpty(value) ? default(int) : Int32.Parse(value, CultureInfo.InvariantCulture));
212325
RegisterUnsafe<string, uint>((value) => string.IsNullOrEmpty(value) ? default(uint) : UInt32.Parse(value, CultureInfo.InvariantCulture));
213326
RegisterUnsafe<string, long>((value) => string.IsNullOrEmpty(value) ? default(long) : Int64.Parse(value, CultureInfo.InvariantCulture));
214327
RegisterUnsafe<string, ulong>((value) => string.IsNullOrEmpty(value) ? default(ulong) : UInt64.Parse(value, CultureInfo.InvariantCulture));
328+
RegisterUnsafe<string, float>((value) => string.IsNullOrEmpty(value) ? default(float) : Single.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture));
329+
RegisterUnsafe<string, double>((value) => string.IsNullOrEmpty(value) ? default(double) : Double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture));
215330
RegisterUnsafe<string, Guid>((value) => string.IsNullOrEmpty(value) ? default(Guid) : Guid.Parse(value));
216331
RegisterUnsafe<string, Uuid128>((value) => string.IsNullOrEmpty(value) ? default(Uuid128) : Uuid128.Parse(value));
217332
RegisterUnsafe<string, Uuid64>((value) => string.IsNullOrEmpty(value) ? default(Uuid64) : Uuid64.Parse(value));
218-
RegisterUnsafe<string, bool>((value) => !string.IsNullOrEmpty(value));
219-
RegisterUnsafe<string, float>((value) => string.IsNullOrEmpty(value) ? default(float) : Single.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture));
220-
RegisterUnsafe<string, double>((value) => string.IsNullOrEmpty(value) ? default(double) : Double.Parse(value, NumberStyles.Float, CultureInfo.InvariantCulture));
221333
RegisterUnsafe<string, System.Net.IPAddress>((value) => string.IsNullOrEmpty(value) ? default(System.Net.IPAddress) : System.Net.IPAddress.Parse(value));
222334

223335
RegisterUnsafe<byte[], Slice>((value) => Slice.Create(value));
224336
RegisterUnsafe<byte[], string>((value) => value == null ? default(string) : value.Length == 0 ? String.Empty : System.Convert.ToBase64String(value));
225337
RegisterUnsafe<byte[], bool>((value) => value != null && value.Length > 0);
338+
RegisterUnsafe<byte[], sbyte>((value) => value == null ? default(sbyte) : Slice.Create(value).ToSByte());
339+
RegisterUnsafe<byte[], byte>((value) => value == null ? default(byte) : Slice.Create(value).ToByte());
340+
RegisterUnsafe<byte[], short>((value) => value == null ? default(short) : Slice.Create(value).ToInt16());
341+
RegisterUnsafe<byte[], ushort>((value) => value == null ? default(ushort) : Slice.Create(value).ToUInt16());
226342
RegisterUnsafe<byte[], int>((value) => value == null ? 0 : Slice.Create(value).ToInt32());
227343
RegisterUnsafe<byte[], uint>((value) => value == null ? 0U : Slice.Create(value).ToUInt32());
228344
RegisterUnsafe<byte[], long>((value) => value == null ? 0L : Slice.Create(value).ToInt64());
@@ -257,20 +373,26 @@ private static void RegisterDefaultConverters()
257373
RegisterUnsafe<TimeSpan, Slice>((value) => Slice.FromInt64(value.Ticks));
258374
RegisterUnsafe<TimeSpan, byte[]>((value) => Slice.FromInt64(value.Ticks).GetBytes());
259375
RegisterUnsafe<TimeSpan, long>((value) => value.Ticks);
376+
RegisterUnsafe<TimeSpan, ulong>((value) => checked((ulong)value.Ticks));
260377
RegisterUnsafe<TimeSpan, double>((value) => value.TotalSeconds);
261378
RegisterUnsafe<TimeSpan, bool>((value) => value == TimeSpan.Zero);
262379

263380
RegisterUnsafe<System.Net.IPAddress, Slice>((value) => value != null ? Slice.Create(value.GetAddressBytes()) : Slice.Nil);
264381
RegisterUnsafe<System.Net.IPAddress, byte[]>((value) => value != null ? value.GetAddressBytes() : null);
265382
RegisterUnsafe<System.Net.IPAddress, string>((value) => value != null ? value.ToString() : null);
266383

384+
RegisterUnsafe<FdbTupleAlias, byte>((value) => (byte)value);
267385
RegisterUnsafe<FdbTupleAlias, int>((value) => (int)value);
268386
RegisterUnsafe<FdbTupleAlias, Slice>((value) => Slice.FromByte((byte)value));
269387

270388
//REVIEW: this should go in the Tuples layer !
271389
RegisterUnsafe<Slice, byte[]>((value) => value.GetBytes());
272390
RegisterUnsafe<Slice, string>((value) => value.ToUnicode());
273391
RegisterUnsafe<Slice, bool>((value) => value.ToBool());
392+
RegisterUnsafe<Slice, sbyte>((value) => value.ToSByte());
393+
RegisterUnsafe<Slice, byte>((value) => value.ToByte());
394+
RegisterUnsafe<Slice, short>((value) => value.ToInt16());
395+
RegisterUnsafe<Slice, ushort>((value) => value.ToUInt16());
274396
RegisterUnsafe<Slice, int>((value) => value.ToInt32());
275397
RegisterUnsafe<Slice, uint>((value) => value.ToUInt32());
276398
RegisterUnsafe<Slice, long>((value) => value.ToInt64());
@@ -284,8 +406,8 @@ private static void RegisterDefaultConverters()
284406
}
285407

286408
/// <summary>Helper method to throw an exception when we don't know how to convert from <paramref name="source"/> to <paramref name="destination"/></summary>
287-
/// <param name="source"></param>
288-
/// <param name="destination"></param>
409+
/// <param name="source">Type of the source object</param>
410+
/// <param name="destination">Target type of the conversion</param>
289411
[ContractAnnotation("=> halt")]
290412
private static void FailCannotConvert(Type source, Type destination)
291413
{
@@ -368,6 +490,7 @@ public static void Register<T, R>([NotNull] IFdbConverter<T, R> converter)
368490
[NotNull]
369491
public static IFdbConverter<T, R> GetConverter<T, R>()
370492
{
493+
371494
if (typeof(T) == typeof(R))
372495
{ // R == T : identity function
373496
return (IFdbConverter<T, R>)Identity<T>.Default;
@@ -419,14 +542,16 @@ public static R ConvertBoxed<R>(object value)
419542
if (value == null) return default(R);
420543
var type = value.GetType();
421544

545+
var targetType = typeof (R);
546+
422547
// cast !
423-
if (type == typeof(R)) return (R)value;
548+
if (targetType.IsAssignableFrom(type)) return (R)value;
424549

425550
IFdbConverter converter;
426-
if (!Converters.TryGetValue(new ComparisonHelper.TypePair(type, typeof(R)), out converter))
551+
if (!Converters.TryGetValue(new ComparisonHelper.TypePair(type, targetType), out converter))
427552
{
428553
// maybe it is a nullable type ?
429-
var nullableType = Nullable.GetUnderlyingType(typeof(R));
554+
var nullableType = Nullable.GetUnderlyingType(targetType);
430555
if (nullableType != null)
431556
{ // we already nullchecked value above, so we just have to convert it to the underlying type...
432557

@@ -440,7 +565,7 @@ public static R ConvertBoxed<R>(object value)
440565
}
441566
}
442567

443-
FailCannotConvert(type, typeof(R));
568+
FailCannotConvert(type, targetType);
444569
}
445570

446571
return (R)converter.ConvertBoxed(value);

0 commit comments

Comments
 (0)