-
Notifications
You must be signed in to change notification settings - Fork 284
Expand file tree
/
Copy pathConversionsGenerator.fs
More file actions
128 lines (113 loc) · 5.72 KB
/
ConversionsGenerator.fs
File metadata and controls
128 lines (113 loc) · 5.72 KB
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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
// Copyright 2011-2015, Tomas Petricek (http://tomasp.net), Gustavo Guerra (http://functionalflow.co.uk), and other contributors
// Licensed under the Apache License, Version 2.0, see LICENSE.md in this project
//
// Conversions from string to various primitive types
module ProviderImplementation.ConversionsGenerator
open System
open FSharp.Quotations
open FSharp.Data.Runtime
open FSharp.Data.Runtime.StructuralTypes
open ProviderImplementation
open ProviderImplementation.ProvidedTypes
open ProviderImplementation.QuotationBuilder
let getConversionQuotation missingValuesStr cultureStr typ (value: Expr<string option>) =
if typ = typeof<string> then
<@@ TextRuntime.ConvertString(%value) @@>
elif typ = typeof<int> || typ = typeof<Bit0> || typ = typeof<Bit1> then
<@@ TextRuntime.ConvertInteger(cultureStr, %value) @@>
elif typ = typeof<int64> then
<@@ TextRuntime.ConvertInteger64(cultureStr, %value) @@>
elif typ = typeof<decimal> then
<@@ TextRuntime.ConvertDecimal(cultureStr, %value) @@>
elif typ = typeof<float> then
<@@ TextRuntime.ConvertFloat(cultureStr, missingValuesStr, %value) @@>
elif typ = typeof<bool> || typ = typeof<Bit> then
<@@ TextRuntime.ConvertBoolean(%value) @@>
elif typ = typeof<DateTime> then
<@@ TextRuntime.ConvertDateTime(cultureStr, %value) @@>
elif typ = typeof<DateTimeOffset> then
<@@ TextRuntime.ConvertDateTimeOffset(cultureStr, %value) @@>
elif typ = typeof<TimeSpan> then
<@@ TextRuntime.ConvertTimeSpan(cultureStr, %value) @@>
#if NET6_0_OR_GREATER
elif typ = typeof<DateOnly> then
<@@ TextRuntime.ConvertDateOnly(cultureStr, %value) @@>
elif typ = typeof<TimeOnly> then
<@@ TextRuntime.ConvertTimeOnly(cultureStr, %value) @@>
#endif
elif typ = typeof<Guid> then
<@@ TextRuntime.ConvertGuid(%value) @@>
else
failwith "getConversionQuotation: Unsupported primitive type"
let getBackConversionQuotation missingValuesStr cultureStr typ value : Expr<string> =
if typ = typeof<int> || typ = typeof<Bit0> || typ = typeof<Bit1> then
<@ TextRuntime.ConvertIntegerBack(cultureStr, %%value) @>
elif typ = typeof<int64> then
<@ TextRuntime.ConvertInteger64Back(cultureStr, %%value) @>
elif typ = typeof<decimal> then
<@ TextRuntime.ConvertDecimalBack(cultureStr, %%value) @>
elif typ = typeof<float> then
<@ TextRuntime.ConvertFloatBack(cultureStr, missingValuesStr, %%value) @>
elif typ = typeof<string> then
<@ TextRuntime.ConvertStringBack(%%value) @>
elif typ = typeof<bool> || typ = typeof<Bit> then
<@ TextRuntime.ConvertBooleanBack(%%value, false) @>
elif typ = typeof<Guid> then
<@ TextRuntime.ConvertGuidBack(%%value) @>
elif typ = typeof<DateTime> then
<@ TextRuntime.ConvertDateTimeBack(cultureStr, %%value) @>
elif typ = typeof<DateTimeOffset> then
<@ TextRuntime.ConvertDateTimeOffsetBack(cultureStr, %%value) @>
elif typ = typeof<TimeSpan> then
<@ TextRuntime.ConvertTimeSpanBack(cultureStr, %%value) @>
#if NET6_0_OR_GREATER
elif typ = typeof<DateOnly> then
<@ TextRuntime.ConvertDateOnlyBack(cultureStr, %%value) @>
elif typ = typeof<TimeOnly> then
<@ TextRuntime.ConvertTimeOnlyBack(cultureStr, %%value) @>
#endif
else
failwith "getBackConversionQuotation: Unsupported primitive type"
/// Creates a function that takes Expr<string option> and converts it to
/// an expression of other type - the type is specified by `field`
let internal convertStringValue missingValuesStr cultureStr exceptionIfMissing (field: PrimitiveInferedProperty) =
let fieldName = field.Name
let field = field.Value
let returnType =
match field.TypeWrapper with
| TypeWrapper.None -> field.TypeWithMeasure
| TypeWrapper.Option -> typedefof<option<_>>.MakeGenericType field.TypeWithMeasure
| TypeWrapper.Nullable -> typedefof<Nullable<_>>.MakeGenericType field.TypeWithMeasure
let returnTypeWithoutMeasure =
match field.TypeWrapper with
| TypeWrapper.None -> field.RuntimeType
| TypeWrapper.Option -> typedefof<option<_>>.MakeGenericType field.RuntimeType
| TypeWrapper.Nullable -> typedefof<Nullable<_>>.MakeGenericType field.RuntimeType
let convert (value: Expr<string option>) =
let convert value =
getConversionQuotation missingValuesStr cultureStr field.InferedType value
let getNonOptionalValueMethod =
if exceptionIfMissing then
nameof (TextRuntime.GetNonOptionalValueStrict)
else
nameof (TextRuntime.GetNonOptionalValue)
match field.TypeWrapper with
| TypeWrapper.None ->
//prevent value being calculated twice
let var = Var("value", typeof<string option>)
let varExpr = Expr.Cast<string option>(Expr.Var var)
let body =
typeof<TextRuntime>?(getNonOptionalValueMethod) field.RuntimeType (fieldName, convert varExpr, varExpr)
Expr.Let(var, value, body)
| TypeWrapper.Option -> convert value
| TypeWrapper.Nullable ->
typeof<TextRuntime>?(nameof (TextRuntime.OptionToNullable)) field.RuntimeType (convert value)
let convertBack value =
let value =
match field.TypeWrapper with
| TypeWrapper.None -> ProviderHelpers.some field.RuntimeType value
| TypeWrapper.Option -> value
| TypeWrapper.Nullable ->
typeof<TextRuntime>?(nameof (TextRuntime.NullableToOption)) field.RuntimeType value
getBackConversionQuotation missingValuesStr cultureStr field.InferedType value :> Expr
returnType, returnTypeWithoutMeasure, convert, convertBack