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.
Files changed (167) hide show
  1. package/dist/Extensions/StringBuilder.js +2 -5
  2. package/dist/Extensions/TextNode.js +29 -54
  3. package/dist/FSharp.Oracle.Schema/Schema.js +113 -218
  4. package/dist/Generate.js +33 -63
  5. package/dist/Helpers.js +1 -2
  6. package/dist/Plugin.js +17 -31
  7. package/dist/Render/Documentation.js +1 -2
  8. package/dist/Render/Entries.js +29 -34
  9. package/dist/Render/Pages.js +10 -19
  10. package/dist/Render/Primitives.js +19 -32
  11. package/dist/Themes.js +3 -5
  12. package/dist/fable_modules/Fable.Promise.3.2.0/AsyncIterable.fs +57 -0
  13. package/dist/fable_modules/Fable.Promise.3.2.0/AsyncIterable.fs.js +105 -0
  14. package/dist/fable_modules/Fable.Promise.3.2.0/Fable.Promise.fableproj +20 -0
  15. package/dist/fable_modules/Fable.Promise.3.2.0/Promise.fs +766 -0
  16. package/dist/fable_modules/Fable.Promise.3.2.0/Promise.fs.js +232 -0
  17. package/dist/fable_modules/Fable.Promise.3.2.0/PromiseImpl.fs +31 -0
  18. package/dist/fable_modules/Fable.Promise.3.2.0/PromiseImpl.fs.js +20 -0
  19. package/dist/fable_modules/Thoth.Json.Core.0.9.0/Decode.fs +1592 -0
  20. package/dist/fable_modules/Thoth.Json.Core.0.9.0/Decode.fs.js +1417 -0
  21. package/dist/fable_modules/Thoth.Json.Core.0.9.0/DecoderCE.fs +106 -0
  22. package/dist/fable_modules/Thoth.Json.Core.0.9.0/DecoderCE.fs.js +63 -0
  23. package/dist/fable_modules/Thoth.Json.Core.0.9.0/Encode.fs +380 -0
  24. package/dist/fable_modules/Thoth.Json.Core.0.9.0/Encode.fs.js +289 -0
  25. package/dist/fable_modules/Thoth.Json.Core.0.9.0/Thoth.Json.Core.fableproj +37 -0
  26. package/dist/fable_modules/Thoth.Json.Core.0.9.0/Types.fs +76 -0
  27. package/dist/fable_modules/Thoth.Json.Core.0.9.0/Types.fs.js +37 -0
  28. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Casing.fs +113 -0
  29. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Casing.fs.js +173 -0
  30. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Decode.fs +1153 -0
  31. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Decode.fs.js +622 -0
  32. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Domain.fs +91 -0
  33. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Domain.fs.js +103 -0
  34. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Encode.fs +893 -0
  35. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Encode.fs.js +836 -0
  36. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Prelude.fs +435 -0
  37. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Prelude.fs.js +389 -0
  38. package/dist/fable_modules/Thoth.Json.Core.Auto.0.1.0/Thoth.Json.Core.Auto.fableproj +43 -0
  39. package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Decode.fs +88 -0
  40. package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Decode.fs.js +102 -0
  41. package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Encode.fs +40 -0
  42. package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Encode.fs.js +59 -0
  43. package/dist/fable_modules/Thoth.Json.JavaScript.0.5.0/Thoth.Json.JavaScript.fableproj +31 -0
  44. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Array.js +1347 -0
  45. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Async.js +134 -0
  46. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/AsyncBuilder.js +183 -0
  47. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/BigInt.js +306 -0
  48. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/BitConverter.js +138 -0
  49. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Boolean.js +22 -0
  50. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/CHANGELOG.md +191 -0
  51. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Char.js +202 -0
  52. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Choice.js +184 -0
  53. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/CollectionUtil.js +182 -0
  54. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/ConditionalWeakTable.js +21 -0
  55. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Date.js +755 -0
  56. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/DateOffset.js +261 -0
  57. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/DateOnly.js +124 -0
  58. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Decimal.js +236 -0
  59. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Double.js +47 -0
  60. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Encoding.js +185 -0
  61. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Event.js +93 -0
  62. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/FSharp.Collections.js +45 -0
  63. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/FSharp.Core.CompilerServices.js +27 -0
  64. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/FSharp.Core.js +156 -0
  65. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Global.js +29 -0
  66. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Guid.js +161 -0
  67. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Int32.js +135 -0
  68. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/List.js +1323 -0
  69. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Long.js +47 -0
  70. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/MailboxProcessor.js +94 -0
  71. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Map.js +1396 -0
  72. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/MapUtil.js +130 -0
  73. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/MutableMap.js +339 -0
  74. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/MutableSet.js +233 -0
  75. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Native.js +14 -0
  76. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Numeric.js +75 -0
  77. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Observable.js +113 -0
  78. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Option.js +104 -0
  79. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/README.md +3 -0
  80. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Random.js +172 -0
  81. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Range.js +45 -0
  82. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Reflection.js +460 -0
  83. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/RegExp.js +141 -0
  84. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Result.js +165 -0
  85. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Seq.js +1409 -0
  86. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Seq2.js +111 -0
  87. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Set.js +1788 -0
  88. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/String.js +649 -0
  89. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/System.Collections.Generic.js +333 -0
  90. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/System.Text.js +168 -0
  91. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/System.js +283 -0
  92. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/TimeOnly.js +122 -0
  93. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/TimeSpan.js +180 -0
  94. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Timer.js +67 -0
  95. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Types.js +198 -0
  96. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Unicode.13.0.0.js +4 -0
  97. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Uri.js +165 -0
  98. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/Util.js +792 -0
  99. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/big.d.ts +338 -0
  100. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/lib/big.js +825 -0
  101. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/package.json +24 -0
  102. package/dist/fable_modules/fable-library-js.5.0.0-rc.7/quotation.js +618 -0
  103. package/package.json +4 -5
  104. package/packages/FSharp.Oracle/XmlDoc.fs +12 -1
  105. package/packages/FSharp.Oracle/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.fs +3 -0
  106. package/packages/FSharp.Oracle/obj/Debug/net10.0/FSharp.Oracle.AssemblyInfo.fs +17 -0
  107. package/packages/FSharp.Oracle/obj/Release/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.fs +3 -0
  108. package/packages/FSharp.Oracle/obj/Release/net10.0/FSharp.Oracle.AssemblyInfo.fs +17 -0
  109. package/packages/FSharp.Oracle.Schema/obj/Debug/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.fs +3 -0
  110. package/packages/FSharp.Oracle.Schema/obj/Debug/net10.0/FSharp.Oracle.Schema.AssemblyInfo.fs +17 -0
  111. package/packages/FSharp.Oracle.Schema/obj/Release/net10.0/.NETCoreApp,Version=v10.0.AssemblyAttributes.fs +3 -0
  112. package/packages/FSharp.Oracle.Schema/obj/Release/net10.0/FSharp.Oracle.Schema.AssemblyInfo.fs +17 -0
  113. package/oracle-bin/FSharp.Compiler.Service.dll +0 -0
  114. package/oracle-bin/FSharp.Core.dll +0 -0
  115. package/oracle-bin/FSharp.DependencyManager.Nuget.dll +0 -0
  116. package/oracle-bin/FSharp.Oracle.Schema.dll +0 -0
  117. package/oracle-bin/FSharp.Oracle.Schema.pdb +0 -0
  118. package/oracle-bin/FSharp.Oracle.Schema.xml +0 -219
  119. package/oracle-bin/Fable.Core.dll +0 -0
  120. package/oracle-bin/Oracle +0 -0
  121. package/oracle-bin/Oracle.deps.json +0 -280
  122. package/oracle-bin/Oracle.dll +0 -0
  123. package/oracle-bin/Oracle.pdb +0 -0
  124. package/oracle-bin/Oracle.runtimeconfig.json +0 -13
  125. package/oracle-bin/Oracle.xml +0 -111
  126. package/oracle-bin/Thoth.Json.Core.Auto.dll +0 -0
  127. package/oracle-bin/Thoth.Json.Core.dll +0 -0
  128. package/oracle-bin/Thoth.Json.System.Text.Json.dll +0 -0
  129. package/oracle-bin/cs/FSharp.Compiler.Service.resources.dll +0 -0
  130. package/oracle-bin/cs/FSharp.Core.resources.dll +0 -0
  131. package/oracle-bin/cs/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  132. package/oracle-bin/de/FSharp.Compiler.Service.resources.dll +0 -0
  133. package/oracle-bin/de/FSharp.Core.resources.dll +0 -0
  134. package/oracle-bin/de/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  135. package/oracle-bin/es/FSharp.Compiler.Service.resources.dll +0 -0
  136. package/oracle-bin/es/FSharp.Core.resources.dll +0 -0
  137. package/oracle-bin/es/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  138. package/oracle-bin/fr/FSharp.Compiler.Service.resources.dll +0 -0
  139. package/oracle-bin/fr/FSharp.Core.resources.dll +0 -0
  140. package/oracle-bin/fr/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  141. package/oracle-bin/it/FSharp.Compiler.Service.resources.dll +0 -0
  142. package/oracle-bin/it/FSharp.Core.resources.dll +0 -0
  143. package/oracle-bin/it/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  144. package/oracle-bin/ja/FSharp.Compiler.Service.resources.dll +0 -0
  145. package/oracle-bin/ja/FSharp.Core.resources.dll +0 -0
  146. package/oracle-bin/ja/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  147. package/oracle-bin/ko/FSharp.Compiler.Service.resources.dll +0 -0
  148. package/oracle-bin/ko/FSharp.Core.resources.dll +0 -0
  149. package/oracle-bin/ko/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  150. package/oracle-bin/pl/FSharp.Compiler.Service.resources.dll +0 -0
  151. package/oracle-bin/pl/FSharp.Core.resources.dll +0 -0
  152. package/oracle-bin/pl/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  153. package/oracle-bin/pt-BR/FSharp.Compiler.Service.resources.dll +0 -0
  154. package/oracle-bin/pt-BR/FSharp.Core.resources.dll +0 -0
  155. package/oracle-bin/pt-BR/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  156. package/oracle-bin/ru/FSharp.Compiler.Service.resources.dll +0 -0
  157. package/oracle-bin/ru/FSharp.Core.resources.dll +0 -0
  158. package/oracle-bin/ru/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  159. package/oracle-bin/tr/FSharp.Compiler.Service.resources.dll +0 -0
  160. package/oracle-bin/tr/FSharp.Core.resources.dll +0 -0
  161. package/oracle-bin/tr/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  162. package/oracle-bin/zh-Hans/FSharp.Compiler.Service.resources.dll +0 -0
  163. package/oracle-bin/zh-Hans/FSharp.Core.resources.dll +0 -0
  164. package/oracle-bin/zh-Hans/FSharp.DependencyManager.Nuget.resources.dll +0 -0
  165. package/oracle-bin/zh-Hant/FSharp.Compiler.Service.resources.dll +0 -0
  166. package/oracle-bin/zh-Hant/FSharp.Core.resources.dll +0 -0
  167. 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&lt;'T&gt;) =
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