starlight-fsharp-oracle 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Extensions/StringBuilder.js +2 -5
- package/dist/Extensions/TextNode.js +29 -54
- package/dist/FSharp.Oracle.Schema/Schema.js +113 -218
- package/dist/Generate.js +33 -63
- package/dist/Helpers.js +1 -2
- package/dist/Plugin.js +17 -31
- package/dist/Render/Documentation.js +1 -2
- package/dist/Render/Entries.js +29 -34
- package/dist/Render/Pages.js +10 -19
- package/dist/Render/Primitives.js +19 -32
- package/dist/Themes.js +3 -5
- package/dist/fable_modules/Fable.Promise.3.2.0/AsyncIterable.fs +57 -0
- package/dist/fable_modules/Fable.Promise.3.2.0/AsyncIterable.fs.js +105 -0
- package/dist/fable_modules/Fable.Promise.3.2.0/Fable.Promise.fableproj +20 -0
- package/dist/fable_modules/Fable.Promise.3.2.0/Promise.fs +766 -0
- package/dist/fable_modules/Fable.Promise.3.2.0/Promise.fs.js +232 -0
- package/dist/fable_modules/Fable.Promise.3.2.0/PromiseImpl.fs +31 -0
- package/dist/fable_modules/Fable.Promise.3.2.0/PromiseImpl.fs.js +20 -0
- package/dist/fable_modules/Thoth.Json.Core.0.9.0/Decode.fs +1592 -0
- package/dist/fable_modules/Thoth.Json.Core.0.9.0/Decode.fs.js +1417 -0
- package/dist/fable_modules/Thoth.Json.Core.0.9.0/DecoderCE.fs +106 -0
- package/dist/fable_modules/Thoth.Json.Core.0.9.0/DecoderCE.fs.js +63 -0
- package/dist/fable_modules/Thoth.Json.Core.0.9.0/Encode.fs +380 -0
- package/dist/fable_modules/Thoth.Json.Core.0.9.0/Encode.fs.js +289 -0
- package/dist/fable_modules/Thoth.Json.Core.0.9.0/Thoth.Json.Core.fableproj +37 -0
- package/dist/fable_modules/Thoth.Json.Core.0.9.0/Types.fs +76 -0
- package/dist/fable_modules/Thoth.Json.Core.0.9.0/Types.fs.js +37 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Casing.fs +113 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Casing.fs.js +173 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Decode.fs +1153 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Decode.fs.js +622 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Domain.fs +91 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Domain.fs.js +103 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Encode.fs +893 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Encode.fs.js +836 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Prelude.fs +435 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Prelude.fs.js +389 -0
- package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Thoth.Json.Core.Auto.fableproj +43 -0
- package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Decode.fs +88 -0
- package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Decode.fs.js +102 -0
- package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Encode.fs +40 -0
- package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Encode.fs.js +59 -0
- package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Thoth.Json.JavaScript.fableproj +31 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Array.js +1347 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Async.js +134 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/AsyncBuilder.js +183 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/BigInt.js +306 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/BitConverter.js +138 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Boolean.js +22 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/CHANGELOG.md +191 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Char.js +202 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Choice.js +184 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/CollectionUtil.js +182 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/ConditionalWeakTable.js +21 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Date.js +755 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/DateOffset.js +261 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/DateOnly.js +124 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Decimal.js +236 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Double.js +47 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Encoding.js +185 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Event.js +93 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/FSharp.Collections.js +45 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/FSharp.Core.CompilerServices.js +27 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/FSharp.Core.js +156 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Global.js +29 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Guid.js +161 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Int32.js +135 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/List.js +1323 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Long.js +47 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/MailboxProcessor.js +94 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Map.js +1396 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/MapUtil.js +130 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/MutableMap.js +339 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/MutableSet.js +233 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Native.js +14 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Numeric.js +75 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Observable.js +113 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Option.js +104 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/README.md +3 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Random.js +172 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Range.js +45 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Reflection.js +460 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/RegExp.js +141 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Result.js +165 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Seq.js +1409 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Seq2.js +111 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Set.js +1788 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/String.js +649 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/System.Collections.Generic.js +333 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/System.Text.js +168 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/System.js +283 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/TimeOnly.js +122 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/TimeSpan.js +180 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Timer.js +67 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Types.js +198 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Unicode.13.0.0.js +4 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Uri.js +165 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Util.js +792 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/big.d.ts +338 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/lib/big.js +825 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/package.json +24 -0
- package/dist/fable_modules/fable-library-js.5.0.0-rc.7/quotation.js +618 -0
- package/package.json +4 -5
- package/packages/FSharp.Oracle/XmlDoc.fs +12 -1
- package/packages/FSharp.Oracle/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.fs +3 -0
- package/packages/FSharp.Oracle/obj/Debug/net10.0/FSharp.Oracle.AssemblyInfo.fs +17 -0
- package/packages/FSharp.Oracle/obj/Release/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.fs +3 -0
- package/packages/FSharp.Oracle/obj/Release/net10.0/FSharp.Oracle.AssemblyInfo.fs +17 -0
- package/packages/FSharp.Oracle.Schema/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.fs +3 -0
- package/packages/FSharp.Oracle.Schema/obj/Debug/net10.0/FSharp.Oracle.Schema.AssemblyInfo.fs +17 -0
- package/packages/FSharp.Oracle.Schema/obj/Release/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.fs +3 -0
- package/packages/FSharp.Oracle.Schema/obj/Release/net10.0/FSharp.Oracle.Schema.AssemblyInfo.fs +17 -0
- package/oracle-bin/FSharp.Compiler.Service.dll +0 -0
- package/oracle-bin/FSharp.Core.dll +0 -0
- package/oracle-bin/FSharp.DependencyManager.Nuget.dll +0 -0
- package/oracle-bin/FSharp.Oracle.Schema.dll +0 -0
- package/oracle-bin/FSharp.Oracle.Schema.pdb +0 -0
- package/oracle-bin/FSharp.Oracle.Schema.xml +0 -219
- package/oracle-bin/Fable.Core.dll +0 -0
- package/oracle-bin/Oracle +0 -0
- package/oracle-bin/Oracle.deps.json +0 -280
- package/oracle-bin/Oracle.dll +0 -0
- package/oracle-bin/Oracle.pdb +0 -0
- package/oracle-bin/Oracle.runtimeconfig.json +0 -13
- package/oracle-bin/Oracle.xml +0 -111
- package/oracle-bin/Thoth.Json.Core.Auto.dll +0 -0
- package/oracle-bin/Thoth.Json.Core.dll +0 -0
- package/oracle-bin/Thoth.Json.System.Text.Json.dll +0 -0
- package/oracle-bin/cs/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/cs/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/cs/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/de/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/de/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/de/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/es/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/es/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/es/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/fr/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/fr/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/fr/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/it/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/it/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/it/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/ja/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/ja/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/ja/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/ko/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/ko/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/ko/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/pl/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/pl/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/pl/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/pt-BR/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/pt-BR/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/pt-BR/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/ru/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/ru/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/ru/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/tr/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/tr/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/tr/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/zh-Hans/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/zh-Hans/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/zh-Hans/FSharp.DependencyManager.Nuget.resources.dll +0 -0
- package/oracle-bin/zh-Hant/FSharp.Compiler.Service.resources.dll +0 -0
- package/oracle-bin/zh-Hant/FSharp.Core.resources.dll +0 -0
- package/oracle-bin/zh-Hant/FSharp.DependencyManager.Nuget.resources.dll +0 -0
|
@@ -0,0 +1,1592 @@
|
|
|
1
|
+
namespace Thoth.Json.Core
|
|
2
|
+
|
|
3
|
+
open System
|
|
4
|
+
open System.Globalization
|
|
5
|
+
|
|
6
|
+
[<RequireQualifiedAccess>]
|
|
7
|
+
module Decode =
|
|
8
|
+
|
|
9
|
+
module Helpers =
|
|
10
|
+
|
|
11
|
+
let prependPath
|
|
12
|
+
(path: string)
|
|
13
|
+
(err: DecoderError<'JsonValue>)
|
|
14
|
+
: DecoderError<'JsonValue>
|
|
15
|
+
=
|
|
16
|
+
let (oldPath, reason) = err
|
|
17
|
+
(path + oldPath, reason)
|
|
18
|
+
|
|
19
|
+
let inline prependPathToResult<'T, 'JsonValue>
|
|
20
|
+
(path: string)
|
|
21
|
+
(res: Result<'T, DecoderError<'JsonValue>>)
|
|
22
|
+
=
|
|
23
|
+
res |> Result.mapError (prependPath path)
|
|
24
|
+
|
|
25
|
+
let private genericMsg
|
|
26
|
+
(helpers: IDecoderHelpers<'JsonValue>)
|
|
27
|
+
msg
|
|
28
|
+
value
|
|
29
|
+
newLine
|
|
30
|
+
=
|
|
31
|
+
try
|
|
32
|
+
"Expecting "
|
|
33
|
+
+ msg
|
|
34
|
+
+ " but instead got:"
|
|
35
|
+
+ (if newLine then
|
|
36
|
+
"\n"
|
|
37
|
+
else
|
|
38
|
+
" ")
|
|
39
|
+
+ (helpers.anyToString value)
|
|
40
|
+
with _ ->
|
|
41
|
+
"Expecting "
|
|
42
|
+
+ msg
|
|
43
|
+
+ " but decoder failed. Couldn't report given value due to circular structure."
|
|
44
|
+
+ (if newLine then
|
|
45
|
+
"\n"
|
|
46
|
+
else
|
|
47
|
+
" ")
|
|
48
|
+
|
|
49
|
+
let rec errorToString
|
|
50
|
+
(helpers: IDecoderHelpers<'JsonValue>)
|
|
51
|
+
(path: string, error)
|
|
52
|
+
=
|
|
53
|
+
let reason =
|
|
54
|
+
match error with
|
|
55
|
+
| BadPrimitive(msg, value) -> genericMsg helpers msg value false
|
|
56
|
+
| BadType(msg, value) -> genericMsg helpers msg value true
|
|
57
|
+
| BadPrimitiveExtra(msg, value, reason) ->
|
|
58
|
+
genericMsg helpers msg value false + "\nReason: " + reason
|
|
59
|
+
| BadField(msg, value) -> genericMsg helpers msg value true
|
|
60
|
+
| BadPath(msg, value, fieldName) ->
|
|
61
|
+
genericMsg helpers msg value true
|
|
62
|
+
+ ("\nNode `" + fieldName + "` is unkown.")
|
|
63
|
+
| TooSmallArray(msg, value) ->
|
|
64
|
+
"Expecting " + msg + ".\n" + (helpers.anyToString value)
|
|
65
|
+
| BadOneOf(errors) ->
|
|
66
|
+
let messages =
|
|
67
|
+
errors
|
|
68
|
+
|> List.map (fun error ->
|
|
69
|
+
Helpers.prependPath path error |> errorToString helpers
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
"The following errors were found:\n\n"
|
|
73
|
+
+ String.concat "\n\n" messages
|
|
74
|
+
| FailMessage msg ->
|
|
75
|
+
"The following `failure` occurred with the decoder: " + msg
|
|
76
|
+
|
|
77
|
+
match error with
|
|
78
|
+
| BadOneOf _ ->
|
|
79
|
+
// Don't need to show the path here because each error case will show it's own path
|
|
80
|
+
reason
|
|
81
|
+
| _ -> "Error at: `" + path + "`\n" + reason
|
|
82
|
+
|
|
83
|
+
// Low-level API
|
|
84
|
+
module Advanced =
|
|
85
|
+
|
|
86
|
+
/// <summary>
|
|
87
|
+
/// Runs the decoder against the given JSON value.
|
|
88
|
+
///
|
|
89
|
+
/// If the decoder fails, it reports the error prefixed with the given path.
|
|
90
|
+
///
|
|
91
|
+
/// </summary>
|
|
92
|
+
/// <example>
|
|
93
|
+
/// <code lang="fsharp">
|
|
94
|
+
/// module Decode =
|
|
95
|
+
/// let fromRootValue (decoder : Decoder<'T>) =
|
|
96
|
+
/// Decode.fromValue "$" decoder
|
|
97
|
+
/// </code>
|
|
98
|
+
/// </example>
|
|
99
|
+
/// <param name="path">Path used to report the error</param>
|
|
100
|
+
/// <param name="decoder">Decoder to apply</param>
|
|
101
|
+
/// <param name="value">JSON value to decoder</param>
|
|
102
|
+
/// <returns>
|
|
103
|
+
/// Returns <c>Ok</c> if the decoder succeeds, otherwise <c>Error</c> with the error message.
|
|
104
|
+
/// </returns>
|
|
105
|
+
let fromValue
|
|
106
|
+
(helpers: IDecoderHelpers<'JsonValue>)
|
|
107
|
+
(decoder: Decoder<'T>)
|
|
108
|
+
=
|
|
109
|
+
fun value ->
|
|
110
|
+
match decoder.Decode(helpers, value) with
|
|
111
|
+
| Ok success -> Ok success
|
|
112
|
+
| Error error -> Error(errorToString helpers error)
|
|
113
|
+
|
|
114
|
+
/// <summary>
|
|
115
|
+
/// Decode a JSON string into an F# string.
|
|
116
|
+
/// </summary>
|
|
117
|
+
///
|
|
118
|
+
/// <example>
|
|
119
|
+
/// <code lang="fsharp">
|
|
120
|
+
/// Decode.fromString Decode.string "Hello" == Ok "Hello"
|
|
121
|
+
/// Decode.fromString Decode.string "42" == Error ...
|
|
122
|
+
/// Decode.fromString Decode.string "true" == Error ...
|
|
123
|
+
/// Decode.fromString Decode.string "{ \"foo\": 42 }" == Error ...
|
|
124
|
+
/// </code>
|
|
125
|
+
/// </example>
|
|
126
|
+
let string: Decoder<string> =
|
|
127
|
+
{ new Decoder<string> with
|
|
128
|
+
member _.Decode(helpers, value) =
|
|
129
|
+
if helpers.isString value then
|
|
130
|
+
Ok(helpers.asString value)
|
|
131
|
+
else
|
|
132
|
+
Error("", BadPrimitive("a string", value))
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/// <summary>
|
|
136
|
+
/// Decode a JSON string into an F# char.
|
|
137
|
+
/// </summary>
|
|
138
|
+
///
|
|
139
|
+
/// <example>
|
|
140
|
+
/// <code lang="fsharp">
|
|
141
|
+
/// Decode.fromString Decode.char "a" == Ok 'a'
|
|
142
|
+
/// Decode.fromString Decode.char "ab" == Error ...
|
|
143
|
+
/// Decode.fromString Decode.char "true" == Error ...
|
|
144
|
+
/// Decode.fromString Decode.char "42" == Error ...
|
|
145
|
+
/// </code>
|
|
146
|
+
/// </example>
|
|
147
|
+
let char: Decoder<char> =
|
|
148
|
+
{ new Decoder<char> with
|
|
149
|
+
member _.Decode(helpers, value) =
|
|
150
|
+
if helpers.isString value then
|
|
151
|
+
let str = helpers.asString value
|
|
152
|
+
|
|
153
|
+
if str.Length = 1 then
|
|
154
|
+
Ok(str.[0])
|
|
155
|
+
else
|
|
156
|
+
("", BadPrimitive("a single character string", value))
|
|
157
|
+
|> Error
|
|
158
|
+
else
|
|
159
|
+
("", BadPrimitive("a char", value)) |> Error
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/// <summary>
|
|
163
|
+
/// Decode a JSON string into an F# Guid.
|
|
164
|
+
/// </summary>
|
|
165
|
+
///
|
|
166
|
+
/// <example>
|
|
167
|
+
/// <code lang="fsharp">
|
|
168
|
+
/// Decode.fromString Decode.guid "58bd4436-7583-40e2-bd3c-aa3c5d0b4286" == Ok (System.Guid "58bd4436-7583-40e2-bd3c-aa3c5d0b4286")
|
|
169
|
+
/// Decode.fromString Decode.guid "58bd4436-aa3c5d0b4286" == Error ...
|
|
170
|
+
/// </code>
|
|
171
|
+
/// </example>
|
|
172
|
+
let guid: Decoder<System.Guid> =
|
|
173
|
+
{ new Decoder<System.Guid> with
|
|
174
|
+
member _.Decode(helpers, value) =
|
|
175
|
+
if helpers.isString value then
|
|
176
|
+
match System.Guid.TryParse(helpers.asString value) with
|
|
177
|
+
| true, x -> Ok x
|
|
178
|
+
| _ -> ("", BadPrimitive("a guid", value)) |> Error
|
|
179
|
+
else
|
|
180
|
+
("", BadPrimitive("a guid", value)) |> Error
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/// <summary>
|
|
184
|
+
/// Decode a JSON null value into an F# unit.
|
|
185
|
+
/// </summary>
|
|
186
|
+
///
|
|
187
|
+
/// <example>
|
|
188
|
+
/// <code lang="fsharp">
|
|
189
|
+
/// Decode.fromString Decode.unit "null" == Ok ()
|
|
190
|
+
/// Decode.fromString Decode.unit "42" == Error ...
|
|
191
|
+
/// </code>
|
|
192
|
+
/// </example>
|
|
193
|
+
let unit: Decoder<unit> =
|
|
194
|
+
{ new Decoder<unit> with
|
|
195
|
+
member _.Decode(helpers, value) =
|
|
196
|
+
if helpers.isNullValue value then
|
|
197
|
+
Ok()
|
|
198
|
+
else
|
|
199
|
+
("", BadPrimitive("null", value)) |> Error
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
let inline private integral
|
|
203
|
+
(name: string)
|
|
204
|
+
(tryParse: (string -> bool * 'T))
|
|
205
|
+
(min: unit -> 'T)
|
|
206
|
+
(max: unit -> 'T)
|
|
207
|
+
(conv: float -> 'T)
|
|
208
|
+
: Decoder<'T>
|
|
209
|
+
=
|
|
210
|
+
|
|
211
|
+
{ new Decoder<'T> with
|
|
212
|
+
member _.Decode(helpers, value) =
|
|
213
|
+
if helpers.isNumber value then
|
|
214
|
+
if helpers.isIntegralValue value then
|
|
215
|
+
let floatValue: float = helpers.asFloat value
|
|
216
|
+
|
|
217
|
+
if
|
|
218
|
+
(float (min ())) <= floatValue
|
|
219
|
+
&& floatValue <= (float (max ()))
|
|
220
|
+
then
|
|
221
|
+
Ok(conv floatValue)
|
|
222
|
+
else
|
|
223
|
+
("",
|
|
224
|
+
BadPrimitiveExtra(
|
|
225
|
+
name,
|
|
226
|
+
value,
|
|
227
|
+
"Value was either too large or too small for "
|
|
228
|
+
+ name
|
|
229
|
+
))
|
|
230
|
+
|> Error
|
|
231
|
+
else
|
|
232
|
+
("",
|
|
233
|
+
BadPrimitiveExtra(
|
|
234
|
+
name,
|
|
235
|
+
value,
|
|
236
|
+
"Value is not an integral value"
|
|
237
|
+
))
|
|
238
|
+
|> Error
|
|
239
|
+
elif helpers.isString value then
|
|
240
|
+
match tryParse (helpers.asString value) with
|
|
241
|
+
| true, x -> Ok x
|
|
242
|
+
| _ -> ("", BadPrimitive(name, value)) |> Error
|
|
243
|
+
else
|
|
244
|
+
("", BadPrimitive(name, value)) |> Error
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
let sbyte: Decoder<sbyte> =
|
|
248
|
+
integral
|
|
249
|
+
"a sbyte"
|
|
250
|
+
System.SByte.TryParse
|
|
251
|
+
(fun () -> System.SByte.MinValue)
|
|
252
|
+
(fun () -> System.SByte.MaxValue)
|
|
253
|
+
sbyte
|
|
254
|
+
|
|
255
|
+
/// Alias to Decode.uint8
|
|
256
|
+
let byte: Decoder<byte> =
|
|
257
|
+
integral
|
|
258
|
+
"a byte"
|
|
259
|
+
System.Byte.TryParse
|
|
260
|
+
(fun () -> System.Byte.MinValue)
|
|
261
|
+
(fun () -> System.Byte.MaxValue)
|
|
262
|
+
byte
|
|
263
|
+
|
|
264
|
+
let int16: Decoder<int16> =
|
|
265
|
+
integral
|
|
266
|
+
"an int16"
|
|
267
|
+
System.Int16.TryParse
|
|
268
|
+
(fun () -> System.Int16.MinValue)
|
|
269
|
+
(fun () -> System.Int16.MaxValue)
|
|
270
|
+
int16
|
|
271
|
+
|
|
272
|
+
let uint16: Decoder<uint16> =
|
|
273
|
+
integral
|
|
274
|
+
"an uint16"
|
|
275
|
+
System.UInt16.TryParse
|
|
276
|
+
(fun () -> System.UInt16.MinValue)
|
|
277
|
+
(fun () -> System.UInt16.MaxValue)
|
|
278
|
+
uint16
|
|
279
|
+
|
|
280
|
+
let int: Decoder<int> =
|
|
281
|
+
integral
|
|
282
|
+
"an int"
|
|
283
|
+
System.Int32.TryParse
|
|
284
|
+
(fun () -> System.Int32.MinValue)
|
|
285
|
+
(fun () -> System.Int32.MaxValue)
|
|
286
|
+
int
|
|
287
|
+
|
|
288
|
+
let uint32: Decoder<uint32> =
|
|
289
|
+
integral
|
|
290
|
+
"an uint32"
|
|
291
|
+
System.UInt32.TryParse
|
|
292
|
+
(fun () -> System.UInt32.MinValue)
|
|
293
|
+
(fun () -> System.UInt32.MaxValue)
|
|
294
|
+
uint32
|
|
295
|
+
|
|
296
|
+
let int64: Decoder<int64> =
|
|
297
|
+
integral
|
|
298
|
+
"an int64"
|
|
299
|
+
System.Int64.TryParse
|
|
300
|
+
(fun () -> System.Int64.MinValue)
|
|
301
|
+
(fun () -> System.Int64.MaxValue)
|
|
302
|
+
int64
|
|
303
|
+
|
|
304
|
+
let uint64: Decoder<uint64> =
|
|
305
|
+
integral
|
|
306
|
+
"an uint64"
|
|
307
|
+
System.UInt64.TryParse
|
|
308
|
+
(fun () -> System.UInt64.MinValue)
|
|
309
|
+
(fun () -> System.UInt64.MaxValue)
|
|
310
|
+
uint64
|
|
311
|
+
|
|
312
|
+
let bigint: Decoder<bigint> =
|
|
313
|
+
{ new Decoder<bigint> with
|
|
314
|
+
member _.Decode(helpers, value) =
|
|
315
|
+
if helpers.isNumber value then
|
|
316
|
+
helpers.asInt value |> bigint |> Ok
|
|
317
|
+
elif helpers.isString value then
|
|
318
|
+
let parseResult =
|
|
319
|
+
#if FABLE_COMPILER
|
|
320
|
+
bigint.TryParse(helpers.asString value)
|
|
321
|
+
#else
|
|
322
|
+
bigint.TryParse(
|
|
323
|
+
helpers.asString value,
|
|
324
|
+
NumberStyles.Any,
|
|
325
|
+
CultureInfo.InvariantCulture
|
|
326
|
+
)
|
|
327
|
+
#endif
|
|
328
|
+
|
|
329
|
+
match parseResult with
|
|
330
|
+
| true, x -> Ok x
|
|
331
|
+
| _ -> ("", BadPrimitive("a bigint", value)) |> Error
|
|
332
|
+
else
|
|
333
|
+
("", BadPrimitive("a bigint", value)) |> Error
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
let bool: Decoder<bool> =
|
|
337
|
+
{ new Decoder<bool> with
|
|
338
|
+
member _.Decode(helpers, value) =
|
|
339
|
+
if helpers.isBoolean value then
|
|
340
|
+
Ok(helpers.asBoolean value)
|
|
341
|
+
else
|
|
342
|
+
("", BadPrimitive("a boolean", value)) |> Error
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
let float: Decoder<float> =
|
|
346
|
+
{ new Decoder<float> with
|
|
347
|
+
member _.Decode(helpers, value) =
|
|
348
|
+
if helpers.isNumber value then
|
|
349
|
+
Ok(helpers.asFloat value)
|
|
350
|
+
else
|
|
351
|
+
("", BadPrimitive("a float", value)) |> Error
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
|
|
355
|
+
let float32: Decoder<float32> =
|
|
356
|
+
{ new Decoder<float32> with
|
|
357
|
+
member _.Decode(helpers, value) =
|
|
358
|
+
if helpers.isNumber value then
|
|
359
|
+
Ok(helpers.asFloat32 value)
|
|
360
|
+
else
|
|
361
|
+
("", BadPrimitive("a float32", value)) |> Error
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
let decimal: Decoder<decimal> =
|
|
365
|
+
{ new Decoder<decimal> with
|
|
366
|
+
member _.Decode(helpers, value) =
|
|
367
|
+
if helpers.isNumber value then
|
|
368
|
+
helpers.asFloat value |> decimal |> Ok
|
|
369
|
+
elif helpers.isString value then
|
|
370
|
+
match System.Decimal.TryParse(helpers.asString value) with
|
|
371
|
+
| true, x -> Ok x
|
|
372
|
+
| _ -> ("", BadPrimitive("a decimal", value)) |> Error
|
|
373
|
+
else
|
|
374
|
+
("", BadPrimitive("a decimal", value)) |> Error
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
#if !FABLE_COMPILER_PYTHON
|
|
378
|
+
/// Decode a System.DateTime value using Sytem.DateTime.TryParse, then convert it to UTC.
|
|
379
|
+
let datetimeUtc: Decoder<System.DateTime> =
|
|
380
|
+
{ new Decoder<System.DateTime> with
|
|
381
|
+
member _.Decode(helpers, value) =
|
|
382
|
+
if helpers.isString value then
|
|
383
|
+
match System.DateTime.TryParse(helpers.asString value) with
|
|
384
|
+
| true, datetime -> datetime.ToUniversalTime() |> Ok
|
|
385
|
+
| _ -> ("", BadPrimitive("a datetime", value)) |> Error
|
|
386
|
+
else
|
|
387
|
+
("", BadPrimitive("a datetime", value)) |> Error
|
|
388
|
+
}
|
|
389
|
+
#endif
|
|
390
|
+
|
|
391
|
+
/// Decode a System.DateTime with DateTime.TryParse; uses default System.DateTimeStyles.
|
|
392
|
+
let datetimeLocal: Decoder<System.DateTime> =
|
|
393
|
+
{ new Decoder<System.DateTime> with
|
|
394
|
+
member _.Decode(helpers, value) =
|
|
395
|
+
if helpers.isString value then
|
|
396
|
+
match System.DateTime.TryParse(helpers.asString value) with
|
|
397
|
+
| true, datetime -> Ok datetime
|
|
398
|
+
| _ -> ("", BadPrimitive("a datetime", value)) |> Error
|
|
399
|
+
else
|
|
400
|
+
("", BadPrimitive("a datetime", value)) |> Error
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
#if !FABLE_COMPILER_PYTHON
|
|
404
|
+
let datetimeOffset: Decoder<System.DateTimeOffset> =
|
|
405
|
+
{ new Decoder<System.DateTimeOffset> with
|
|
406
|
+
member _.Decode(helpers, value) =
|
|
407
|
+
if helpers.isString value then
|
|
408
|
+
match
|
|
409
|
+
System.DateTimeOffset.TryParse(helpers.asString value)
|
|
410
|
+
with
|
|
411
|
+
| true, datetimeOffset -> Ok datetimeOffset
|
|
412
|
+
| _ ->
|
|
413
|
+
("", BadPrimitive("a datetimeoffset", value)) |> Error
|
|
414
|
+
else
|
|
415
|
+
("", BadPrimitive("a datetime", value)) |> Error
|
|
416
|
+
}
|
|
417
|
+
#endif
|
|
418
|
+
|
|
419
|
+
let timespan: Decoder<System.TimeSpan> =
|
|
420
|
+
{ new Decoder<System.TimeSpan> with
|
|
421
|
+
member _.Decode(helpers, value) =
|
|
422
|
+
if helpers.isString value then
|
|
423
|
+
match System.TimeSpan.TryParse(helpers.asString value) with
|
|
424
|
+
| true, timespan -> Ok timespan
|
|
425
|
+
| _ -> ("", BadPrimitive("a timespan", value)) |> Error
|
|
426
|
+
else
|
|
427
|
+
("", BadPrimitive("a timespan", value)) |> Error
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/////////////////////////
|
|
431
|
+
// Object primitives ///
|
|
432
|
+
///////////////////////
|
|
433
|
+
|
|
434
|
+
let private decodeMaybeNull
|
|
435
|
+
(helpers: IDecoderHelpers<'JsonValue>)
|
|
436
|
+
(path: string)
|
|
437
|
+
(decoder: Decoder<'value>)
|
|
438
|
+
(value: 'JsonValue)
|
|
439
|
+
=
|
|
440
|
+
// The decoder may be an option decoder so give it an opportunity to check null values
|
|
441
|
+
|
|
442
|
+
// We catch the null value case first to avoid executing the decoder logic
|
|
443
|
+
// Indeed, if the decoder logic try to access the value to do something with it,
|
|
444
|
+
// it can throw an exception about the value being null
|
|
445
|
+
if helpers.isNullValue value then
|
|
446
|
+
Ok None
|
|
447
|
+
else
|
|
448
|
+
match decoder.Decode(helpers, value) with
|
|
449
|
+
| Ok v -> Ok(Some v)
|
|
450
|
+
| Error er -> er |> Helpers.prependPath path |> Error
|
|
451
|
+
|
|
452
|
+
let optional
|
|
453
|
+
(fieldName: string)
|
|
454
|
+
(decoder: Decoder<'value>)
|
|
455
|
+
: Decoder<'value option>
|
|
456
|
+
=
|
|
457
|
+
{ new Decoder<'value option> with
|
|
458
|
+
member _.Decode(helpers, value) =
|
|
459
|
+
if helpers.isObject value then
|
|
460
|
+
|
|
461
|
+
if helpers.hasProperty fieldName value then
|
|
462
|
+
let fieldValue = helpers.getProperty (fieldName, value)
|
|
463
|
+
|
|
464
|
+
decodeMaybeNull
|
|
465
|
+
helpers
|
|
466
|
+
("." + fieldName)
|
|
467
|
+
decoder
|
|
468
|
+
fieldValue
|
|
469
|
+
else
|
|
470
|
+
Ok None
|
|
471
|
+
else
|
|
472
|
+
Error("", BadType("an object", value))
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
let private badPathError fieldNames currentPath value =
|
|
476
|
+
let currentPath =
|
|
477
|
+
defaultArg currentPath (fieldNames |> String.concat ".")
|
|
478
|
+
|
|
479
|
+
let msg = "an object with path `" + (String.concat "." fieldNames) + "`"
|
|
480
|
+
|
|
481
|
+
Error(
|
|
482
|
+
"." + currentPath,
|
|
483
|
+
BadPath(
|
|
484
|
+
msg,
|
|
485
|
+
value,
|
|
486
|
+
List.tryLast fieldNames |> Option.defaultValue ""
|
|
487
|
+
)
|
|
488
|
+
)
|
|
489
|
+
|
|
490
|
+
let map2
|
|
491
|
+
(ctor: 'a -> 'b -> 'Output)
|
|
492
|
+
(d1: Decoder<'a>)
|
|
493
|
+
(d2: Decoder<'b>)
|
|
494
|
+
: Decoder<'Output>
|
|
495
|
+
=
|
|
496
|
+
{ new Decoder<'Output> with
|
|
497
|
+
member _.Decode(helpers, value) =
|
|
498
|
+
match d1.Decode(helpers, value), d2.Decode(helpers, value) with
|
|
499
|
+
| Ok v1, Ok v2 -> Ok(ctor v1 v2)
|
|
500
|
+
| Error er, _ -> Error er
|
|
501
|
+
| _, Error er -> Error er
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// let custom =
|
|
505
|
+
// map2 (|>)
|
|
506
|
+
|
|
507
|
+
let optionalAt
|
|
508
|
+
(fieldNames: string list)
|
|
509
|
+
(decoder: Decoder<'value>)
|
|
510
|
+
: Decoder<'value option>
|
|
511
|
+
=
|
|
512
|
+
{ new Decoder<'value option> with
|
|
513
|
+
member _.Decode(helpers, firstValue) =
|
|
514
|
+
(("", firstValue, None), fieldNames)
|
|
515
|
+
||> List.fold (fun (curPath, curValue, res) field ->
|
|
516
|
+
match res with
|
|
517
|
+
| Some _ -> curPath, curValue, res
|
|
518
|
+
| None ->
|
|
519
|
+
if helpers.isNullValue curValue then
|
|
520
|
+
curPath, curValue, Some(Ok None)
|
|
521
|
+
elif helpers.isObject curValue then
|
|
522
|
+
if helpers.hasProperty field curValue then
|
|
523
|
+
let curValue =
|
|
524
|
+
helpers.getProperty (field, curValue)
|
|
525
|
+
|
|
526
|
+
curPath + "." + field, curValue, None
|
|
527
|
+
else
|
|
528
|
+
curPath, curValue, Some(Ok None)
|
|
529
|
+
else
|
|
530
|
+
let res =
|
|
531
|
+
Error(curPath, BadType("an object", curValue))
|
|
532
|
+
|
|
533
|
+
curPath, curValue, Some res
|
|
534
|
+
)
|
|
535
|
+
|> function
|
|
536
|
+
| _, _, Some res -> res
|
|
537
|
+
| lastPath, lastValue, None ->
|
|
538
|
+
if helpers.isNullValue lastValue then
|
|
539
|
+
Ok None
|
|
540
|
+
else
|
|
541
|
+
decodeMaybeNull helpers lastPath decoder lastValue
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
let field (fieldName: string) (decoder: Decoder<'value>) : Decoder<'value> =
|
|
545
|
+
{ new Decoder<'value> with
|
|
546
|
+
member _.Decode(helpers, value) =
|
|
547
|
+
if helpers.isObject value then
|
|
548
|
+
if helpers.hasProperty fieldName value then
|
|
549
|
+
let fieldValue = helpers.getProperty (fieldName, value)
|
|
550
|
+
|
|
551
|
+
decoder.Decode(helpers, fieldValue)
|
|
552
|
+
|> Helpers.prependPathToResult ("." + fieldName)
|
|
553
|
+
else
|
|
554
|
+
Error(
|
|
555
|
+
"",
|
|
556
|
+
BadField(
|
|
557
|
+
"an object with a field named `"
|
|
558
|
+
+ fieldName
|
|
559
|
+
+ "`",
|
|
560
|
+
value
|
|
561
|
+
)
|
|
562
|
+
)
|
|
563
|
+
else
|
|
564
|
+
Error("", BadType("an object", value))
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
let at
|
|
568
|
+
(fieldNames: string list)
|
|
569
|
+
(decoder: Decoder<'value>)
|
|
570
|
+
: Decoder<'value>
|
|
571
|
+
=
|
|
572
|
+
{ new Decoder<'value> with
|
|
573
|
+
member _.Decode(helpers, firstValue) =
|
|
574
|
+
(("", firstValue, None), fieldNames)
|
|
575
|
+
||> List.fold (fun (curPath, curValue, res) field ->
|
|
576
|
+
match res with
|
|
577
|
+
| Some _ -> curPath, curValue, res
|
|
578
|
+
| None ->
|
|
579
|
+
if helpers.isNullValue curValue then
|
|
580
|
+
let res =
|
|
581
|
+
badPathError
|
|
582
|
+
fieldNames
|
|
583
|
+
(Some curPath)
|
|
584
|
+
firstValue
|
|
585
|
+
|
|
586
|
+
curPath, curValue, Some res
|
|
587
|
+
elif helpers.isObject curValue then
|
|
588
|
+
if helpers.hasProperty field curValue then
|
|
589
|
+
let curValue =
|
|
590
|
+
helpers.getProperty (field, curValue)
|
|
591
|
+
|
|
592
|
+
curPath + "." + field, curValue, None
|
|
593
|
+
else
|
|
594
|
+
let res =
|
|
595
|
+
badPathError fieldNames None firstValue
|
|
596
|
+
|
|
597
|
+
curPath, curValue, Some res
|
|
598
|
+
else
|
|
599
|
+
let res =
|
|
600
|
+
Error(curPath, BadType("an object", curValue))
|
|
601
|
+
|
|
602
|
+
curPath, curValue, Some res
|
|
603
|
+
)
|
|
604
|
+
|> function
|
|
605
|
+
| _, _, Some res -> res
|
|
606
|
+
| lastPath, lastValue, None ->
|
|
607
|
+
decoder.Decode(helpers, lastValue)
|
|
608
|
+
|> Helpers.prependPathToResult lastPath
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
let index
|
|
612
|
+
(requestedIndex: int)
|
|
613
|
+
(decoder: Decoder<'value>)
|
|
614
|
+
: Decoder<'value>
|
|
615
|
+
=
|
|
616
|
+
{ new Decoder<'value> with
|
|
617
|
+
member _.Decode(helpers, value) =
|
|
618
|
+
if helpers.isArray value then
|
|
619
|
+
let vArray = helpers.asArray value
|
|
620
|
+
|
|
621
|
+
let path = ".[" + (Operators.string requestedIndex) + "]"
|
|
622
|
+
|
|
623
|
+
if requestedIndex < vArray.Length then
|
|
624
|
+
decoder.Decode(helpers, vArray.[requestedIndex])
|
|
625
|
+
|> Helpers.prependPathToResult path
|
|
626
|
+
else
|
|
627
|
+
let msg =
|
|
628
|
+
"a longer array. Need index `"
|
|
629
|
+
+ (Operators.string requestedIndex)
|
|
630
|
+
+ "` but there are only `"
|
|
631
|
+
+ (Operators.string vArray.Length)
|
|
632
|
+
+ "` entries"
|
|
633
|
+
|
|
634
|
+
(path, TooSmallArray(msg, value)) |> Error
|
|
635
|
+
else
|
|
636
|
+
("", BadPrimitive("an array", value)) |> Error
|
|
637
|
+
}
|
|
638
|
+
|
|
639
|
+
//////////////////////
|
|
640
|
+
// Data structure ///
|
|
641
|
+
////////////////////
|
|
642
|
+
|
|
643
|
+
let list (decoder: Decoder<'value>) : Decoder<'value list> =
|
|
644
|
+
{ new Decoder<'value list> with
|
|
645
|
+
member _.Decode(helpers, value) =
|
|
646
|
+
if helpers.isArray value then
|
|
647
|
+
let tokens = helpers.asArray value
|
|
648
|
+
let mutable i = 0
|
|
649
|
+
let mutable result = []
|
|
650
|
+
let mutable error: DecoderError<_> option = None
|
|
651
|
+
|
|
652
|
+
while i < tokens.Length && error.IsNone do
|
|
653
|
+
let value = tokens.[i]
|
|
654
|
+
|
|
655
|
+
match decoder.Decode(helpers, value) with
|
|
656
|
+
| Ok value -> result <- result @ [ value ]
|
|
657
|
+
| Error er ->
|
|
658
|
+
let x =
|
|
659
|
+
Some(
|
|
660
|
+
er
|
|
661
|
+
|> Helpers.prependPath (
|
|
662
|
+
".[" + (i.ToString()) + "]"
|
|
663
|
+
)
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
error <- x
|
|
667
|
+
|
|
668
|
+
i <- i + 1
|
|
669
|
+
|
|
670
|
+
if error.IsNone then
|
|
671
|
+
Ok result
|
|
672
|
+
else
|
|
673
|
+
Error error.Value
|
|
674
|
+
else
|
|
675
|
+
("", BadPrimitive("a list", value)) |> Error
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
let resizeArray (decoder: Decoder<'value>) : Decoder<'value ResizeArray> =
|
|
679
|
+
{ new Decoder<'value ResizeArray> with
|
|
680
|
+
member _.Decode(helpers, value) =
|
|
681
|
+
if helpers.isArray value then
|
|
682
|
+
let tokens = helpers.asArray value
|
|
683
|
+
let mutable i = 0
|
|
684
|
+
let result = ResizeArray tokens.Length
|
|
685
|
+
let mutable error: DecoderError<_> option = None
|
|
686
|
+
|
|
687
|
+
while i < tokens.Length && error.IsNone do
|
|
688
|
+
let value = tokens.[i]
|
|
689
|
+
|
|
690
|
+
match decoder.Decode(helpers, value) with
|
|
691
|
+
| Ok value ->
|
|
692
|
+
// Setting the value via the index fails with a runtime error
|
|
693
|
+
// but because we iterate over the tokens in order, adding the value
|
|
694
|
+
// should keep the order
|
|
695
|
+
result.Add value
|
|
696
|
+
| Error er ->
|
|
697
|
+
error <-
|
|
698
|
+
Some(
|
|
699
|
+
er
|
|
700
|
+
|> Helpers.prependPath (
|
|
701
|
+
".[" + (i.ToString()) + "]"
|
|
702
|
+
)
|
|
703
|
+
)
|
|
704
|
+
|
|
705
|
+
i <- i + 1
|
|
706
|
+
|
|
707
|
+
if error.IsNone then
|
|
708
|
+
Ok(ResizeArray result)
|
|
709
|
+
else
|
|
710
|
+
Error error.Value
|
|
711
|
+
else
|
|
712
|
+
("", BadPrimitive("a ResizeArray", value)) |> Error
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
let seq (decoder: Decoder<'value>) : Decoder<'value seq> =
|
|
716
|
+
{ new Decoder<'value seq> with
|
|
717
|
+
member _.Decode(helpers, value) =
|
|
718
|
+
if helpers.isArray value then
|
|
719
|
+
let mutable i = -1
|
|
720
|
+
let tokens = helpers.asArray value
|
|
721
|
+
|
|
722
|
+
(Ok(seq []), tokens)
|
|
723
|
+
||> Array.fold (fun acc value ->
|
|
724
|
+
i <- i + 1
|
|
725
|
+
|
|
726
|
+
match acc with
|
|
727
|
+
| Error _ -> acc
|
|
728
|
+
| Ok acc ->
|
|
729
|
+
match decoder.Decode(helpers, value) with
|
|
730
|
+
| Error er ->
|
|
731
|
+
Error(
|
|
732
|
+
er
|
|
733
|
+
|> Helpers.prependPath (
|
|
734
|
+
".[" + (i.ToString()) + "]"
|
|
735
|
+
)
|
|
736
|
+
)
|
|
737
|
+
| Ok value -> Ok(Seq.append [ value ] acc)
|
|
738
|
+
)
|
|
739
|
+
|> Result.map Seq.rev
|
|
740
|
+
else
|
|
741
|
+
("", BadPrimitive("a seq", value)) |> Error
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
let array (decoder: Decoder<'value>) : Decoder<'value array> =
|
|
745
|
+
{ new Decoder<'value array> with
|
|
746
|
+
member _.Decode(helpers, value) =
|
|
747
|
+
if helpers.isArray value then
|
|
748
|
+
let mutable i = -1
|
|
749
|
+
let tokens = helpers.asArray value
|
|
750
|
+
let arr = Array.zeroCreate tokens.Length
|
|
751
|
+
|
|
752
|
+
(Ok arr, tokens)
|
|
753
|
+
||> Array.fold (fun acc value ->
|
|
754
|
+
i <- i + 1
|
|
755
|
+
|
|
756
|
+
match acc with
|
|
757
|
+
| Error _ -> acc
|
|
758
|
+
| Ok acc ->
|
|
759
|
+
match decoder.Decode(helpers, value) with
|
|
760
|
+
| Error er ->
|
|
761
|
+
Error(
|
|
762
|
+
er
|
|
763
|
+
|> Helpers.prependPath (
|
|
764
|
+
".[" + (i.ToString()) + "]"
|
|
765
|
+
)
|
|
766
|
+
)
|
|
767
|
+
| Ok value ->
|
|
768
|
+
acc.[i] <- value
|
|
769
|
+
Ok acc
|
|
770
|
+
)
|
|
771
|
+
else
|
|
772
|
+
("", BadPrimitive("an array", value)) |> Error
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
|
|
776
|
+
let keys: Decoder<string list> =
|
|
777
|
+
{ new Decoder<string list> with
|
|
778
|
+
member _.Decode(helpers, value) =
|
|
779
|
+
if helpers.isObject value then
|
|
780
|
+
helpers.getProperties value |> List.ofSeq |> Ok
|
|
781
|
+
else
|
|
782
|
+
("", BadPrimitive("an object", value)) |> Error
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
|
|
786
|
+
let keyValuePairs
|
|
787
|
+
(decoder: Decoder<'value>)
|
|
788
|
+
: Decoder<(string * 'value) list>
|
|
789
|
+
=
|
|
790
|
+
{ new Decoder<(string * 'value) list> with
|
|
791
|
+
member _.Decode(helpers, value) =
|
|
792
|
+
match keys.Decode(helpers, value) with
|
|
793
|
+
| Ok objectKeys ->
|
|
794
|
+
(Ok [], objectKeys)
|
|
795
|
+
||> List.fold (fun acc prop ->
|
|
796
|
+
match acc with
|
|
797
|
+
| Error _ -> acc
|
|
798
|
+
| Ok acc ->
|
|
799
|
+
let fieldValue = helpers.getProperty (prop, value)
|
|
800
|
+
|
|
801
|
+
match decoder.Decode(helpers, fieldValue) with
|
|
802
|
+
| Error er -> Error er
|
|
803
|
+
| Ok value -> (prop, value) :: acc |> Ok
|
|
804
|
+
)
|
|
805
|
+
|> Result.map List.rev
|
|
806
|
+
| Error e -> Error e
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
//////////////////////////////
|
|
810
|
+
// Inconsistent Structure ///
|
|
811
|
+
////////////////////////////
|
|
812
|
+
|
|
813
|
+
let oneOf (decoders: Decoder<'value> list) : Decoder<'value> =
|
|
814
|
+
{ new Decoder<'value> with
|
|
815
|
+
member _.Decode(helpers, value) =
|
|
816
|
+
let rec runner
|
|
817
|
+
(decoders: Decoder<'value> list)
|
|
818
|
+
(errors: DecoderError<'JsonValue> list)
|
|
819
|
+
=
|
|
820
|
+
match decoders with
|
|
821
|
+
| head :: tail ->
|
|
822
|
+
match head.Decode(helpers, value) with
|
|
823
|
+
| Ok v -> Ok v
|
|
824
|
+
| Error error ->
|
|
825
|
+
runner tail (List.append errors [ error ])
|
|
826
|
+
| [] -> ("", BadOneOf errors) |> Error
|
|
827
|
+
|
|
828
|
+
runner decoders []
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
//////////////////////
|
|
832
|
+
// Fancy decoding ///
|
|
833
|
+
////////////////////
|
|
834
|
+
|
|
835
|
+
let nil (output: 'a) : Decoder<'a> =
|
|
836
|
+
{ new Decoder<'a> with
|
|
837
|
+
member _.Decode(helpers, value) =
|
|
838
|
+
if helpers.isNullValue value then
|
|
839
|
+
Ok output
|
|
840
|
+
else
|
|
841
|
+
("", BadPrimitive("null", value)) |> Error
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
type private ValueDecoder() =
|
|
845
|
+
interface Decoder<Json> with
|
|
846
|
+
member this.Decode
|
|
847
|
+
(helpers: IDecoderHelpers<'JsonValue>, value: 'JsonValue)
|
|
848
|
+
: Result<Json, DecoderError<'JsonValue>>
|
|
849
|
+
=
|
|
850
|
+
let decoder = this :> Decoder<_>
|
|
851
|
+
|
|
852
|
+
if helpers.isBoolean value then
|
|
853
|
+
helpers.asBoolean value |> Json.Boolean |> Ok
|
|
854
|
+
elif helpers.isNullValue value then
|
|
855
|
+
Json.Null |> Ok
|
|
856
|
+
elif helpers.isString value then
|
|
857
|
+
helpers.asString value |> Json.String |> Ok
|
|
858
|
+
elif helpers.isNumber value then
|
|
859
|
+
helpers.asFloat value |> Json.Number |> Ok
|
|
860
|
+
elif helpers.isArray value then
|
|
861
|
+
let tokens = helpers.asArray value
|
|
862
|
+
let result = Array.zeroCreate (Array.length tokens)
|
|
863
|
+
|
|
864
|
+
let mutable i = 0
|
|
865
|
+
let mutable error: DecoderError<_> option = None
|
|
866
|
+
|
|
867
|
+
while i < tokens.Length && error.IsNone do
|
|
868
|
+
let value = tokens.[i]
|
|
869
|
+
|
|
870
|
+
match decoder.Decode(helpers, value) with
|
|
871
|
+
| Ok value -> result[i] <- value
|
|
872
|
+
| Error er ->
|
|
873
|
+
let x = Some(er |> Helpers.prependPath $".[%i{i}]")
|
|
874
|
+
|
|
875
|
+
error <- x
|
|
876
|
+
|
|
877
|
+
i <- i + 1
|
|
878
|
+
|
|
879
|
+
if error.IsNone then
|
|
880
|
+
result |> Seq.toList |> Json.Array |> Ok
|
|
881
|
+
else
|
|
882
|
+
Error error.Value
|
|
883
|
+
elif helpers.isObject value then
|
|
884
|
+
let props = helpers.getProperties value |> Seq.toArray
|
|
885
|
+
let result = Array.zeroCreate (Array.length props)
|
|
886
|
+
|
|
887
|
+
let mutable i = 0
|
|
888
|
+
let mutable error: DecoderError<_> option = None
|
|
889
|
+
|
|
890
|
+
while i < props.Length && error.IsNone do
|
|
891
|
+
let key = props[i]
|
|
892
|
+
let value = helpers.getProperty (key, value)
|
|
893
|
+
|
|
894
|
+
match decoder.Decode(helpers, value) with
|
|
895
|
+
| Ok value -> result[i] <- key, value
|
|
896
|
+
| Error er ->
|
|
897
|
+
let x = Some(er |> Helpers.prependPath ("." + key))
|
|
898
|
+
|
|
899
|
+
error <- x
|
|
900
|
+
|
|
901
|
+
i <- i + 1
|
|
902
|
+
|
|
903
|
+
if error.IsNone then
|
|
904
|
+
result |> Seq.toList |> Json.Object |> Ok
|
|
905
|
+
else
|
|
906
|
+
Error error.Value
|
|
907
|
+
else
|
|
908
|
+
Error("", BadPrimitive("any", value))
|
|
909
|
+
|
|
910
|
+
let value: Decoder<Json> = ValueDecoder()
|
|
911
|
+
|
|
912
|
+
let succeed (output: 'a) : Decoder<'a> =
|
|
913
|
+
{ new Decoder<'a> with
|
|
914
|
+
member _.Decode(_, _) = Ok output
|
|
915
|
+
}
|
|
916
|
+
|
|
917
|
+
let fail (msg: string) : Decoder<'a> =
|
|
918
|
+
{ new Decoder<'a> with
|
|
919
|
+
member _.Decode(_, _) = Error("", FailMessage msg)
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
let andThen (cb: 'a -> Decoder<'b>) (decoder: Decoder<'a>) : Decoder<'b> =
|
|
923
|
+
{ new Decoder<'b> with
|
|
924
|
+
member _.Decode(helpers, value) =
|
|
925
|
+
match decoder.Decode(helpers, value) with
|
|
926
|
+
| Error er -> Error er
|
|
927
|
+
| Ok result -> (cb result).Decode(helpers, value)
|
|
928
|
+
}
|
|
929
|
+
|
|
930
|
+
let all (decoders: Decoder<'a> list) : Decoder<'a list> =
|
|
931
|
+
{ new Decoder<'a list> with
|
|
932
|
+
member _.Decode(helpers, value) =
|
|
933
|
+
let rec runner (decoders: Decoder<'a> list) (values: 'a list) =
|
|
934
|
+
match decoders with
|
|
935
|
+
| decoder :: tail ->
|
|
936
|
+
match decoder.Decode(helpers, value) with
|
|
937
|
+
| Ok value -> runner tail (List.append values [ value ])
|
|
938
|
+
| Error error -> Error error
|
|
939
|
+
| [] -> Ok values
|
|
940
|
+
|
|
941
|
+
runner decoders []
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
[<NoComparison>]
|
|
945
|
+
type private LazyDecoder<'t>(x: Lazy<Decoder<'t>>) =
|
|
946
|
+
struct
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
interface Decoder<'t> with
|
|
950
|
+
member this.Decode<'json>
|
|
951
|
+
(helpers: IDecoderHelpers<'json>, json: 'json)
|
|
952
|
+
=
|
|
953
|
+
let decoder = x.Force()
|
|
954
|
+
decoder.Decode(helpers, json)
|
|
955
|
+
|
|
956
|
+
let lazily (x: Lazy<Decoder<'t>>) : Decoder<'t> = LazyDecoder(x) :> _
|
|
957
|
+
|
|
958
|
+
/////////////////////
|
|
959
|
+
// Map functions ///
|
|
960
|
+
///////////////////
|
|
961
|
+
|
|
962
|
+
let map (ctor: 'a -> 'Output) (d1: Decoder<'a>) : Decoder<'Output> =
|
|
963
|
+
{ new Decoder<'Output> with
|
|
964
|
+
member _.Decode(helpers, value) =
|
|
965
|
+
match d1.Decode(helpers, value) with
|
|
966
|
+
| Ok v1 -> Ok(ctor v1)
|
|
967
|
+
| Error er -> Error er
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
let map3
|
|
971
|
+
(ctor: 'a -> 'b -> 'c -> 'Output)
|
|
972
|
+
(d1: Decoder<'a>)
|
|
973
|
+
(d2: Decoder<'b>)
|
|
974
|
+
(d3: Decoder<'c>)
|
|
975
|
+
: Decoder<'Output>
|
|
976
|
+
=
|
|
977
|
+
{ new Decoder<'Output> with
|
|
978
|
+
member _.Decode(helpers, value) =
|
|
979
|
+
match
|
|
980
|
+
d1.Decode(helpers, value),
|
|
981
|
+
d2.Decode(helpers, value),
|
|
982
|
+
d3.Decode(helpers, value)
|
|
983
|
+
with
|
|
984
|
+
| Ok v1, Ok v2, Ok v3 -> Ok(ctor v1 v2 v3)
|
|
985
|
+
| Error er, _, _ -> Error er
|
|
986
|
+
| _, Error er, _ -> Error er
|
|
987
|
+
| _, _, Error er -> Error er
|
|
988
|
+
}
|
|
989
|
+
|
|
990
|
+
let map4
|
|
991
|
+
(ctor: 'a -> 'b -> 'c -> 'd -> 'Output)
|
|
992
|
+
(d1: Decoder<'a>)
|
|
993
|
+
(d2: Decoder<'b>)
|
|
994
|
+
(d3: Decoder<'c>)
|
|
995
|
+
(d4: Decoder<'d>)
|
|
996
|
+
: Decoder<'Output>
|
|
997
|
+
=
|
|
998
|
+
{ new Decoder<'Output> with
|
|
999
|
+
member _.Decode(helpers, value) =
|
|
1000
|
+
match
|
|
1001
|
+
d1.Decode(helpers, value),
|
|
1002
|
+
d2.Decode(helpers, value),
|
|
1003
|
+
d3.Decode(helpers, value),
|
|
1004
|
+
d4.Decode(helpers, value)
|
|
1005
|
+
with
|
|
1006
|
+
| Ok v1, Ok v2, Ok v3, Ok v4 -> Ok(ctor v1 v2 v3 v4)
|
|
1007
|
+
| Error er, _, _, _ -> Error er
|
|
1008
|
+
| _, Error er, _, _ -> Error er
|
|
1009
|
+
| _, _, Error er, _ -> Error er
|
|
1010
|
+
| _, _, _, Error er -> Error er
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
let map5
|
|
1014
|
+
(ctor: 'a -> 'b -> 'c -> 'd -> 'e -> 'Output)
|
|
1015
|
+
(d1: Decoder<'a>)
|
|
1016
|
+
(d2: Decoder<'b>)
|
|
1017
|
+
(d3: Decoder<'c>)
|
|
1018
|
+
(d4: Decoder<'d>)
|
|
1019
|
+
(d5: Decoder<'e>)
|
|
1020
|
+
: Decoder<'Output>
|
|
1021
|
+
=
|
|
1022
|
+
{ new Decoder<'Output> with
|
|
1023
|
+
member _.Decode(helpers, value) =
|
|
1024
|
+
match
|
|
1025
|
+
d1.Decode(helpers, value),
|
|
1026
|
+
d2.Decode(helpers, value),
|
|
1027
|
+
d3.Decode(helpers, value),
|
|
1028
|
+
d4.Decode(helpers, value),
|
|
1029
|
+
d5.Decode(helpers, value)
|
|
1030
|
+
with
|
|
1031
|
+
| Ok v1, Ok v2, Ok v3, Ok v4, Ok v5 -> Ok(ctor v1 v2 v3 v4 v5)
|
|
1032
|
+
| Error er, _, _, _, _ -> Error er
|
|
1033
|
+
| _, Error er, _, _, _ -> Error er
|
|
1034
|
+
| _, _, Error er, _, _ -> Error er
|
|
1035
|
+
| _, _, _, Error er, _ -> Error er
|
|
1036
|
+
| _, _, _, _, Error er -> Error er
|
|
1037
|
+
}
|
|
1038
|
+
|
|
1039
|
+
let map6
|
|
1040
|
+
(ctor: 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'Output)
|
|
1041
|
+
(d1: Decoder<'a>)
|
|
1042
|
+
(d2: Decoder<'b>)
|
|
1043
|
+
(d3: Decoder<'c>)
|
|
1044
|
+
(d4: Decoder<'d>)
|
|
1045
|
+
(d5: Decoder<'e>)
|
|
1046
|
+
(d6: Decoder<'f>)
|
|
1047
|
+
: Decoder<'Output>
|
|
1048
|
+
=
|
|
1049
|
+
{ new Decoder<'Output> with
|
|
1050
|
+
member _.Decode(helpers, value) =
|
|
1051
|
+
match
|
|
1052
|
+
d1.Decode(helpers, value),
|
|
1053
|
+
d2.Decode(helpers, value),
|
|
1054
|
+
d3.Decode(helpers, value),
|
|
1055
|
+
d4.Decode(helpers, value),
|
|
1056
|
+
d5.Decode(helpers, value),
|
|
1057
|
+
d6.Decode(helpers, value)
|
|
1058
|
+
with
|
|
1059
|
+
| Ok v1, Ok v2, Ok v3, Ok v4, Ok v5, Ok v6 ->
|
|
1060
|
+
Ok(ctor v1 v2 v3 v4 v5 v6)
|
|
1061
|
+
| Error er, _, _, _, _, _ -> Error er
|
|
1062
|
+
| _, Error er, _, _, _, _ -> Error er
|
|
1063
|
+
| _, _, Error er, _, _, _ -> Error er
|
|
1064
|
+
| _, _, _, Error er, _, _ -> Error er
|
|
1065
|
+
| _, _, _, _, Error er, _ -> Error er
|
|
1066
|
+
| _, _, _, _, _, Error er -> Error er
|
|
1067
|
+
}
|
|
1068
|
+
|
|
1069
|
+
let map7
|
|
1070
|
+
(ctor: 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'Output)
|
|
1071
|
+
(d1: Decoder<'a>)
|
|
1072
|
+
(d2: Decoder<'b>)
|
|
1073
|
+
(d3: Decoder<'c>)
|
|
1074
|
+
(d4: Decoder<'d>)
|
|
1075
|
+
(d5: Decoder<'e>)
|
|
1076
|
+
(d6: Decoder<'f>)
|
|
1077
|
+
(d7: Decoder<'g>)
|
|
1078
|
+
: Decoder<'Output>
|
|
1079
|
+
=
|
|
1080
|
+
{ new Decoder<'Output> with
|
|
1081
|
+
member _.Decode(helpers, value) =
|
|
1082
|
+
match
|
|
1083
|
+
d1.Decode(helpers, value),
|
|
1084
|
+
d2.Decode(helpers, value),
|
|
1085
|
+
d3.Decode(helpers, value),
|
|
1086
|
+
d4.Decode(helpers, value),
|
|
1087
|
+
d5.Decode(helpers, value),
|
|
1088
|
+
d6.Decode(helpers, value),
|
|
1089
|
+
d7.Decode(helpers, value)
|
|
1090
|
+
with
|
|
1091
|
+
| Ok v1, Ok v2, Ok v3, Ok v4, Ok v5, Ok v6, Ok v7 ->
|
|
1092
|
+
Ok(ctor v1 v2 v3 v4 v5 v6 v7)
|
|
1093
|
+
| Error er, _, _, _, _, _, _ -> Error er
|
|
1094
|
+
| _, Error er, _, _, _, _, _ -> Error er
|
|
1095
|
+
| _, _, Error er, _, _, _, _ -> Error er
|
|
1096
|
+
| _, _, _, Error er, _, _, _ -> Error er
|
|
1097
|
+
| _, _, _, _, Error er, _, _ -> Error er
|
|
1098
|
+
| _, _, _, _, _, Error er, _ -> Error er
|
|
1099
|
+
| _, _, _, _, _, _, Error er -> Error er
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1102
|
+
let map8
|
|
1103
|
+
(ctor: 'a -> 'b -> 'c -> 'd -> 'e -> 'f -> 'g -> 'h -> 'Output)
|
|
1104
|
+
(d1: Decoder<'a>)
|
|
1105
|
+
(d2: Decoder<'b>)
|
|
1106
|
+
(d3: Decoder<'c>)
|
|
1107
|
+
(d4: Decoder<'d>)
|
|
1108
|
+
(d5: Decoder<'e>)
|
|
1109
|
+
(d6: Decoder<'f>)
|
|
1110
|
+
(d7: Decoder<'g>)
|
|
1111
|
+
(d8: Decoder<'h>)
|
|
1112
|
+
: Decoder<'Output>
|
|
1113
|
+
=
|
|
1114
|
+
{ new Decoder<'Output> with
|
|
1115
|
+
member _.Decode(helpers, value) =
|
|
1116
|
+
match
|
|
1117
|
+
d1.Decode(helpers, value),
|
|
1118
|
+
d2.Decode(helpers, value),
|
|
1119
|
+
d3.Decode(helpers, value),
|
|
1120
|
+
d4.Decode(helpers, value),
|
|
1121
|
+
d5.Decode(helpers, value),
|
|
1122
|
+
d6.Decode(helpers, value),
|
|
1123
|
+
d7.Decode(helpers, value),
|
|
1124
|
+
d8.Decode(helpers, value)
|
|
1125
|
+
with
|
|
1126
|
+
| Ok v1, Ok v2, Ok v3, Ok v4, Ok v5, Ok v6, Ok v7, Ok v8 ->
|
|
1127
|
+
Ok(ctor v1 v2 v3 v4 v5 v6 v7 v8)
|
|
1128
|
+
| Error er, _, _, _, _, _, _, _ -> Error er
|
|
1129
|
+
| _, Error er, _, _, _, _, _, _ -> Error er
|
|
1130
|
+
| _, _, Error er, _, _, _, _, _ -> Error er
|
|
1131
|
+
| _, _, _, Error er, _, _, _, _ -> Error er
|
|
1132
|
+
| _, _, _, _, Error er, _, _, _ -> Error er
|
|
1133
|
+
| _, _, _, _, _, Error er, _, _ -> Error er
|
|
1134
|
+
| _, _, _, _, _, _, Error er, _ -> Error er
|
|
1135
|
+
| _, _, _, _, _, _, _, Error er -> Error er
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
///////////////////////
|
|
1139
|
+
// Option decoders //
|
|
1140
|
+
///////////////////////
|
|
1141
|
+
|
|
1142
|
+
/// <summary>
|
|
1143
|
+
/// Decode a JSON null value into an F# option.
|
|
1144
|
+
///
|
|
1145
|
+
/// Attention, this decoder is lossy, it will not be able to distinguish between `'T option` and `'T option option`.
|
|
1146
|
+
///
|
|
1147
|
+
/// If you need to distinguish between `'T option` and `'T option option`, use `losslessOption`.
|
|
1148
|
+
/// </summary>
|
|
1149
|
+
/// <param name="decoder">
|
|
1150
|
+
/// The decoder to apply to the value if it is not null.
|
|
1151
|
+
/// </param>
|
|
1152
|
+
/// <typeparam name="'value">The type of the value to decode.</typeparam>
|
|
1153
|
+
/// <returns>
|
|
1154
|
+
/// <c>None</c> if the value is null, otherwise <c>Some value</c> where <c>value</c> is the result of the decoder.
|
|
1155
|
+
/// </returns>
|
|
1156
|
+
let lossyOption (decoder: Decoder<'value>) : Decoder<'value option> =
|
|
1157
|
+
{ new Decoder<'value option> with
|
|
1158
|
+
member _.Decode(helpers, value) =
|
|
1159
|
+
if helpers.isNullValue value then
|
|
1160
|
+
Ok None
|
|
1161
|
+
else
|
|
1162
|
+
decoder.Decode(helpers, value) |> Result.map Some
|
|
1163
|
+
}
|
|
1164
|
+
|
|
1165
|
+
/// <summary>
|
|
1166
|
+
/// Decode a JSON null value into an F# option.
|
|
1167
|
+
///
|
|
1168
|
+
/// This decoder is lossless, it will be able to distinguish between `'T option` and `'T option option`.
|
|
1169
|
+
///
|
|
1170
|
+
/// If you don't need to distinguish between `'T option` and `'T option option`, you can use `lossyOption` which is more efficient.
|
|
1171
|
+
/// </summary>
|
|
1172
|
+
/// <param name="decoder">
|
|
1173
|
+
/// The decoder to apply to the value if it is not null.
|
|
1174
|
+
/// </param>
|
|
1175
|
+
/// <typeparam name="'value">The type of the value to decode.</typeparam>
|
|
1176
|
+
/// <returns>
|
|
1177
|
+
/// <c>None</c> if the value is null, otherwise <c>Some value</c> where <c>value</c> is the result of the decoder.
|
|
1178
|
+
/// </returns>
|
|
1179
|
+
let losslessOption (decoder: Decoder<'value>) : Decoder<'value option> =
|
|
1180
|
+
field "$type" string
|
|
1181
|
+
|> andThen (fun typeName ->
|
|
1182
|
+
match typeName with
|
|
1183
|
+
| "option" ->
|
|
1184
|
+
field "$case" string
|
|
1185
|
+
|> andThen (fun state ->
|
|
1186
|
+
match state with
|
|
1187
|
+
| "none" -> succeed None
|
|
1188
|
+
| "some" -> field "$value" decoder |> map Some
|
|
1189
|
+
| _ ->
|
|
1190
|
+
fail (
|
|
1191
|
+
"Expecting a state field with value 'none' or 'some' but got "
|
|
1192
|
+
+ state
|
|
1193
|
+
)
|
|
1194
|
+
)
|
|
1195
|
+
| _ -> fail ("Expecting an Option type but got " + typeName)
|
|
1196
|
+
)
|
|
1197
|
+
|
|
1198
|
+
//////////////////////
|
|
1199
|
+
// Object builder ///
|
|
1200
|
+
////////////////////
|
|
1201
|
+
|
|
1202
|
+
/// <summary>
|
|
1203
|
+
/// Allow to incrementally apply a decoder, for building large objects.
|
|
1204
|
+
/// </summary>
|
|
1205
|
+
/// <example>
|
|
1206
|
+
/// <code lang="fsharp">
|
|
1207
|
+
/// type Point =
|
|
1208
|
+
/// {
|
|
1209
|
+
/// X : float
|
|
1210
|
+
/// Y : float
|
|
1211
|
+
/// }
|
|
1212
|
+
///
|
|
1213
|
+
/// module Point =
|
|
1214
|
+
/// let create x y = { X = x; Y = y }
|
|
1215
|
+
///
|
|
1216
|
+
/// let decode =
|
|
1217
|
+
/// Decode.succeed create
|
|
1218
|
+
/// |> Decode.andMap (Decode.field "x" Decode.float)
|
|
1219
|
+
/// |> Decode.andMap (Decode.field "y" Decode.float)
|
|
1220
|
+
/// </code>
|
|
1221
|
+
/// </example>
|
|
1222
|
+
let andMap<'a, 'b> : 'a Decoder -> ('a -> 'b) Decoder -> 'b Decoder =
|
|
1223
|
+
map2 (|>)
|
|
1224
|
+
|
|
1225
|
+
type IRequiredGetter =
|
|
1226
|
+
abstract Field: string -> Decoder<'a> -> 'a
|
|
1227
|
+
abstract At: List<string> -> Decoder<'a> -> 'a
|
|
1228
|
+
abstract Raw: Decoder<'a> -> 'a
|
|
1229
|
+
|
|
1230
|
+
type IOptionalGetter =
|
|
1231
|
+
abstract Field: string -> Decoder<'a> -> 'a option
|
|
1232
|
+
abstract At: List<string> -> Decoder<'a> -> 'a option
|
|
1233
|
+
abstract Raw: Decoder<'a> -> 'a option
|
|
1234
|
+
|
|
1235
|
+
type IGetters =
|
|
1236
|
+
abstract Required: IRequiredGetter
|
|
1237
|
+
abstract Optional: IOptionalGetter
|
|
1238
|
+
|
|
1239
|
+
let private unwrapWith
|
|
1240
|
+
(errors: ResizeArray<DecoderError<'JsonValue>>)
|
|
1241
|
+
(helpers: IDecoderHelpers<'JsonValue>)
|
|
1242
|
+
(decoder: Decoder<'T>)
|
|
1243
|
+
(value: 'JsonValue)
|
|
1244
|
+
: 'T
|
|
1245
|
+
=
|
|
1246
|
+
match decoder.Decode(helpers, value) with
|
|
1247
|
+
| Ok v -> v
|
|
1248
|
+
| Error er ->
|
|
1249
|
+
errors.Add(er)
|
|
1250
|
+
Unchecked.defaultof<'T>
|
|
1251
|
+
|
|
1252
|
+
|
|
1253
|
+
type Getters<'JsonValue, 'T>
|
|
1254
|
+
(helpers: IDecoderHelpers<'JsonValue>, value: 'JsonValue)
|
|
1255
|
+
=
|
|
1256
|
+
let mutable errors = ResizeArray<DecoderError<'JsonValue>>()
|
|
1257
|
+
|
|
1258
|
+
let required =
|
|
1259
|
+
{ new IRequiredGetter with
|
|
1260
|
+
member __.Field (fieldName: string) (decoder: Decoder<_>) =
|
|
1261
|
+
unwrapWith errors helpers (field fieldName decoder) value
|
|
1262
|
+
|
|
1263
|
+
member __.At (fieldNames: string list) (decoder: Decoder<_>) =
|
|
1264
|
+
unwrapWith errors helpers (at fieldNames decoder) value
|
|
1265
|
+
|
|
1266
|
+
member __.Raw(decoder: Decoder<_>) =
|
|
1267
|
+
unwrapWith errors helpers decoder value
|
|
1268
|
+
}
|
|
1269
|
+
|
|
1270
|
+
let optional =
|
|
1271
|
+
{ new IOptionalGetter with
|
|
1272
|
+
member __.Field (fieldName: string) (decoder: Decoder<_>) =
|
|
1273
|
+
unwrapWith errors helpers (optional fieldName decoder) value
|
|
1274
|
+
|
|
1275
|
+
member __.At (fieldNames: string list) (decoder: Decoder<_>) =
|
|
1276
|
+
unwrapWith
|
|
1277
|
+
errors
|
|
1278
|
+
helpers
|
|
1279
|
+
(optionalAt fieldNames decoder)
|
|
1280
|
+
value
|
|
1281
|
+
|
|
1282
|
+
member __.Raw(decoder: Decoder<_>) =
|
|
1283
|
+
match decoder.Decode(helpers, value) with
|
|
1284
|
+
| Ok v -> Some v
|
|
1285
|
+
| Error((_, reason) as error) ->
|
|
1286
|
+
match reason with
|
|
1287
|
+
| BadPrimitive(_, v)
|
|
1288
|
+
| BadPrimitiveExtra(_, v, _)
|
|
1289
|
+
| BadType(_, v) ->
|
|
1290
|
+
if helpers.isNullValue v then
|
|
1291
|
+
None
|
|
1292
|
+
else
|
|
1293
|
+
errors.Add(error)
|
|
1294
|
+
Unchecked.defaultof<_>
|
|
1295
|
+
| BadField _
|
|
1296
|
+
| BadPath _ -> None
|
|
1297
|
+
| TooSmallArray _
|
|
1298
|
+
| FailMessage _
|
|
1299
|
+
| BadOneOf _ ->
|
|
1300
|
+
errors.Add(error)
|
|
1301
|
+
Unchecked.defaultof<_>
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
member __.Errors: _ list = Seq.toList errors
|
|
1305
|
+
|
|
1306
|
+
interface IGetters with
|
|
1307
|
+
member __.Required = required
|
|
1308
|
+
member __.Optional = optional
|
|
1309
|
+
|
|
1310
|
+
let object (builder: IGetters -> 'value) : Decoder<'value> =
|
|
1311
|
+
{ new Decoder<'value> with
|
|
1312
|
+
member _.Decode(helpers, value) =
|
|
1313
|
+
let getters = Getters(helpers, value)
|
|
1314
|
+
let result = builder getters
|
|
1315
|
+
|
|
1316
|
+
match getters.Errors with
|
|
1317
|
+
| [] -> Ok result
|
|
1318
|
+
| fst :: _ as errors ->
|
|
1319
|
+
if errors.Length > 1 then
|
|
1320
|
+
("", BadOneOf errors) |> Error
|
|
1321
|
+
else
|
|
1322
|
+
Error fst
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
///////////////////////
|
|
1326
|
+
// Tuples decoders ///
|
|
1327
|
+
////////////////////
|
|
1328
|
+
|
|
1329
|
+
let tuple2
|
|
1330
|
+
(decoder1: Decoder<'T1>)
|
|
1331
|
+
(decoder2: Decoder<'T2>)
|
|
1332
|
+
: Decoder<'T1 * 'T2>
|
|
1333
|
+
=
|
|
1334
|
+
index 0 decoder1
|
|
1335
|
+
|> andThen (fun v1 ->
|
|
1336
|
+
index 1 decoder2 |> andThen (fun v2 -> succeed (v1, v2))
|
|
1337
|
+
)
|
|
1338
|
+
|
|
1339
|
+
let tuple3
|
|
1340
|
+
(decoder1: Decoder<'T1>)
|
|
1341
|
+
(decoder2: Decoder<'T2>)
|
|
1342
|
+
(decoder3: Decoder<'T3>)
|
|
1343
|
+
: Decoder<'T1 * 'T2 * 'T3>
|
|
1344
|
+
=
|
|
1345
|
+
index 0 decoder1
|
|
1346
|
+
|> andThen (fun v1 ->
|
|
1347
|
+
index 1 decoder2
|
|
1348
|
+
|> andThen (fun v2 ->
|
|
1349
|
+
index 2 decoder3 |> andThen (fun v3 -> succeed (v1, v2, v3))
|
|
1350
|
+
)
|
|
1351
|
+
)
|
|
1352
|
+
|
|
1353
|
+
let tuple4
|
|
1354
|
+
(decoder1: Decoder<'T1>)
|
|
1355
|
+
(decoder2: Decoder<'T2>)
|
|
1356
|
+
(decoder3: Decoder<'T3>)
|
|
1357
|
+
(decoder4: Decoder<'T4>)
|
|
1358
|
+
: Decoder<'T1 * 'T2 * 'T3 * 'T4>
|
|
1359
|
+
=
|
|
1360
|
+
index 0 decoder1
|
|
1361
|
+
|> andThen (fun v1 ->
|
|
1362
|
+
index 1 decoder2
|
|
1363
|
+
|> andThen (fun v2 ->
|
|
1364
|
+
index 2 decoder3
|
|
1365
|
+
|> andThen (fun v3 ->
|
|
1366
|
+
index 3 decoder4
|
|
1367
|
+
|> andThen (fun v4 -> succeed (v1, v2, v3, v4))
|
|
1368
|
+
)
|
|
1369
|
+
)
|
|
1370
|
+
)
|
|
1371
|
+
|
|
1372
|
+
let tuple5
|
|
1373
|
+
(decoder1: Decoder<'T1>)
|
|
1374
|
+
(decoder2: Decoder<'T2>)
|
|
1375
|
+
(decoder3: Decoder<'T3>)
|
|
1376
|
+
(decoder4: Decoder<'T4>)
|
|
1377
|
+
(decoder5: Decoder<'T5>)
|
|
1378
|
+
: Decoder<'T1 * 'T2 * 'T3 * 'T4 * 'T5>
|
|
1379
|
+
=
|
|
1380
|
+
index 0 decoder1
|
|
1381
|
+
|> andThen (fun v1 ->
|
|
1382
|
+
index 1 decoder2
|
|
1383
|
+
|> andThen (fun v2 ->
|
|
1384
|
+
index 2 decoder3
|
|
1385
|
+
|> andThen (fun v3 ->
|
|
1386
|
+
index 3 decoder4
|
|
1387
|
+
|> andThen (fun v4 ->
|
|
1388
|
+
index 4 decoder5
|
|
1389
|
+
|> andThen (fun v5 -> succeed (v1, v2, v3, v4, v5))
|
|
1390
|
+
)
|
|
1391
|
+
)
|
|
1392
|
+
)
|
|
1393
|
+
)
|
|
1394
|
+
|
|
1395
|
+
let tuple6
|
|
1396
|
+
(decoder1: Decoder<'T1>)
|
|
1397
|
+
(decoder2: Decoder<'T2>)
|
|
1398
|
+
(decoder3: Decoder<'T3>)
|
|
1399
|
+
(decoder4: Decoder<'T4>)
|
|
1400
|
+
(decoder5: Decoder<'T5>)
|
|
1401
|
+
(decoder6: Decoder<'T6>)
|
|
1402
|
+
: Decoder<'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6>
|
|
1403
|
+
=
|
|
1404
|
+
index 0 decoder1
|
|
1405
|
+
|> andThen (fun v1 ->
|
|
1406
|
+
index 1 decoder2
|
|
1407
|
+
|> andThen (fun v2 ->
|
|
1408
|
+
index 2 decoder3
|
|
1409
|
+
|> andThen (fun v3 ->
|
|
1410
|
+
index 3 decoder4
|
|
1411
|
+
|> andThen (fun v4 ->
|
|
1412
|
+
index 4 decoder5
|
|
1413
|
+
|> andThen (fun v5 ->
|
|
1414
|
+
index 5 decoder6
|
|
1415
|
+
|> andThen (fun v6 ->
|
|
1416
|
+
succeed (v1, v2, v3, v4, v5, v6)
|
|
1417
|
+
)
|
|
1418
|
+
)
|
|
1419
|
+
)
|
|
1420
|
+
)
|
|
1421
|
+
)
|
|
1422
|
+
)
|
|
1423
|
+
|
|
1424
|
+
let tuple7
|
|
1425
|
+
(decoder1: Decoder<'T1>)
|
|
1426
|
+
(decoder2: Decoder<'T2>)
|
|
1427
|
+
(decoder3: Decoder<'T3>)
|
|
1428
|
+
(decoder4: Decoder<'T4>)
|
|
1429
|
+
(decoder5: Decoder<'T5>)
|
|
1430
|
+
(decoder6: Decoder<'T6>)
|
|
1431
|
+
(decoder7: Decoder<'T7>)
|
|
1432
|
+
: Decoder<'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7>
|
|
1433
|
+
=
|
|
1434
|
+
index 0 decoder1
|
|
1435
|
+
|> andThen (fun v1 ->
|
|
1436
|
+
index 1 decoder2
|
|
1437
|
+
|> andThen (fun v2 ->
|
|
1438
|
+
index 2 decoder3
|
|
1439
|
+
|> andThen (fun v3 ->
|
|
1440
|
+
index 3 decoder4
|
|
1441
|
+
|> andThen (fun v4 ->
|
|
1442
|
+
index 4 decoder5
|
|
1443
|
+
|> andThen (fun v5 ->
|
|
1444
|
+
index 5 decoder6
|
|
1445
|
+
|> andThen (fun v6 ->
|
|
1446
|
+
index 6 decoder7
|
|
1447
|
+
|> andThen (fun v7 ->
|
|
1448
|
+
succeed (v1, v2, v3, v4, v5, v6, v7)
|
|
1449
|
+
)
|
|
1450
|
+
)
|
|
1451
|
+
)
|
|
1452
|
+
)
|
|
1453
|
+
)
|
|
1454
|
+
)
|
|
1455
|
+
)
|
|
1456
|
+
|
|
1457
|
+
let tuple8
|
|
1458
|
+
(decoder1: Decoder<'T1>)
|
|
1459
|
+
(decoder2: Decoder<'T2>)
|
|
1460
|
+
(decoder3: Decoder<'T3>)
|
|
1461
|
+
(decoder4: Decoder<'T4>)
|
|
1462
|
+
(decoder5: Decoder<'T5>)
|
|
1463
|
+
(decoder6: Decoder<'T6>)
|
|
1464
|
+
(decoder7: Decoder<'T7>)
|
|
1465
|
+
(decoder8: Decoder<'T8>)
|
|
1466
|
+
: Decoder<'T1 * 'T2 * 'T3 * 'T4 * 'T5 * 'T6 * 'T7 * 'T8>
|
|
1467
|
+
=
|
|
1468
|
+
index 0 decoder1
|
|
1469
|
+
|> andThen (fun v1 ->
|
|
1470
|
+
index 1 decoder2
|
|
1471
|
+
|> andThen (fun v2 ->
|
|
1472
|
+
index 2 decoder3
|
|
1473
|
+
|> andThen (fun v3 ->
|
|
1474
|
+
index 3 decoder4
|
|
1475
|
+
|> andThen (fun v4 ->
|
|
1476
|
+
index 4 decoder5
|
|
1477
|
+
|> andThen (fun v5 ->
|
|
1478
|
+
index 5 decoder6
|
|
1479
|
+
|> andThen (fun v6 ->
|
|
1480
|
+
index 6 decoder7
|
|
1481
|
+
|> andThen (fun v7 ->
|
|
1482
|
+
index 7 decoder8
|
|
1483
|
+
|> andThen (fun v8 ->
|
|
1484
|
+
succeed (
|
|
1485
|
+
v1,
|
|
1486
|
+
v2,
|
|
1487
|
+
v3,
|
|
1488
|
+
v4,
|
|
1489
|
+
v5,
|
|
1490
|
+
v6,
|
|
1491
|
+
v7,
|
|
1492
|
+
v8
|
|
1493
|
+
)
|
|
1494
|
+
)
|
|
1495
|
+
)
|
|
1496
|
+
)
|
|
1497
|
+
)
|
|
1498
|
+
)
|
|
1499
|
+
)
|
|
1500
|
+
)
|
|
1501
|
+
)
|
|
1502
|
+
|
|
1503
|
+
///////////
|
|
1504
|
+
// Map ///
|
|
1505
|
+
/////////
|
|
1506
|
+
|
|
1507
|
+
let dict (decoder: Decoder<'value>) : Decoder<Map<string, 'value>> =
|
|
1508
|
+
map Map.ofList (keyValuePairs decoder)
|
|
1509
|
+
|
|
1510
|
+
let map'
|
|
1511
|
+
(keyDecoder: Decoder<'key>)
|
|
1512
|
+
(valueDecoder: Decoder<'value>)
|
|
1513
|
+
: Decoder<Map<'key, 'value>>
|
|
1514
|
+
=
|
|
1515
|
+
map Map.ofSeq (array (tuple2 keyDecoder valueDecoder))
|
|
1516
|
+
|
|
1517
|
+
type private FixDecoder<'a>(make: Decoder<'a> -> Decoder<'a>) as this =
|
|
1518
|
+
let self = make this
|
|
1519
|
+
|
|
1520
|
+
interface Decoder<'a> with
|
|
1521
|
+
member this.Decode
|
|
1522
|
+
(helpers: IDecoderHelpers<'JsonValue>, value: 'JsonValue)
|
|
1523
|
+
=
|
|
1524
|
+
self.Decode(helpers, value)
|
|
1525
|
+
|
|
1526
|
+
/// <summary>
|
|
1527
|
+
/// Allow to build a decoder that can call itself
|
|
1528
|
+
/// </summary>
|
|
1529
|
+
/// <example>
|
|
1530
|
+
/// <code lang="fsharp">
|
|
1531
|
+
/// type Tree =
|
|
1532
|
+
/// | Empty
|
|
1533
|
+
/// | Branch of Tree * int * Tree
|
|
1534
|
+
///
|
|
1535
|
+
/// module Tree =
|
|
1536
|
+
///
|
|
1537
|
+
/// let decode =
|
|
1538
|
+
/// Decode.fix
|
|
1539
|
+
/// (fun self ->
|
|
1540
|
+
/// Decode.oneOf
|
|
1541
|
+
/// [
|
|
1542
|
+
/// Decode.unit
|
|
1543
|
+
/// |> Decode.map (fun () -> Tree.Empty)
|
|
1544
|
+
///
|
|
1545
|
+
/// Decode.tuple3 self Decode.int self
|
|
1546
|
+
/// |> Decode.map Tree.Branch
|
|
1547
|
+
/// ])
|
|
1548
|
+
/// </code>
|
|
1549
|
+
/// </example>
|
|
1550
|
+
let fix (make: Decoder<'a> -> Decoder<'a>) : Decoder<'a> =
|
|
1551
|
+
FixDecoder<'a>(make)
|
|
1552
|
+
|
|
1553
|
+
////////////
|
|
1554
|
+
// Enum ///
|
|
1555
|
+
/////////
|
|
1556
|
+
|
|
1557
|
+
#if !FABLE_REPL_LIB
|
|
1558
|
+
module Enum =
|
|
1559
|
+
|
|
1560
|
+
let inline private enumOfValue value =
|
|
1561
|
+
if Enum.IsDefined(typeof<'TEnum>, value) then
|
|
1562
|
+
LanguagePrimitives.EnumOfValue<_, 'TEnum> value |> succeed
|
|
1563
|
+
else
|
|
1564
|
+
{ new Decoder<_> with
|
|
1565
|
+
member _.Decode<'JsonValue>(_, value: 'JsonValue) =
|
|
1566
|
+
("",
|
|
1567
|
+
BadPrimitiveExtra(
|
|
1568
|
+
typeof<'TEnum>.FullName,
|
|
1569
|
+
value,
|
|
1570
|
+
"Unkown value provided for the enum"
|
|
1571
|
+
))
|
|
1572
|
+
|> Error
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
let inline byte<'TEnum when 'TEnum: enum<byte>> : Decoder<'TEnum> =
|
|
1576
|
+
byte |> andThen enumOfValue
|
|
1577
|
+
|
|
1578
|
+
let inline sbyte<'TEnum when 'TEnum: enum<sbyte>> : Decoder<'TEnum> =
|
|
1579
|
+
sbyte |> andThen enumOfValue
|
|
1580
|
+
|
|
1581
|
+
let inline int16<'TEnum when 'TEnum: enum<int16>> : Decoder<'TEnum> =
|
|
1582
|
+
int16 |> andThen enumOfValue
|
|
1583
|
+
|
|
1584
|
+
let inline uint16<'TEnum when 'TEnum: enum<uint16>> : Decoder<'TEnum> =
|
|
1585
|
+
uint16 |> andThen enumOfValue
|
|
1586
|
+
|
|
1587
|
+
let inline int<'TEnum when 'TEnum: enum<int>> : Decoder<'TEnum> =
|
|
1588
|
+
int |> andThen enumOfValue
|
|
1589
|
+
|
|
1590
|
+
let inline uint32<'TEnum when 'TEnum: enum<uint32>> : Decoder<'TEnum> =
|
|
1591
|
+
uint32 |> andThen enumOfValue
|
|
1592
|
+
#endif
|