-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathJsonObjectArrayDecode.lean
More file actions
103 lines (81 loc) · 3.11 KB
/
Copy pathJsonObjectArrayDecode.lean
File metadata and controls
103 lines (81 loc) · 3.11 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
import LeanExe.Ascii.Json.Decode
namespace LeanExe
namespace Examples.JsonObjectArrayDecode
open Ascii.Json
structure Item where
id : UInt64
weight : UInt64
structure Request where
items : Array Item
scale : UInt64
def itemsFieldName : AsciiString :=
AsciiString.ofTrustedByteArray "items".toUTF8
def idFieldName : AsciiString :=
AsciiString.ofTrustedByteArray "id".toUTF8
def weightFieldName : AsciiString :=
AsciiString.ofTrustedByteArray "weight".toUTF8
def scaleFieldName : AsciiString :=
AsciiString.ofTrustedByteArray "scale".toUTF8
def weightedFieldName : AsciiString :=
AsciiString.ofTrustedByteArray "weighted".toUTF8
def countFieldName : AsciiString :=
AsciiString.ofTrustedByteArray "count".toUTF8
def itemFieldNames : Array AsciiString :=
#[idFieldName, weightFieldName]
def requestFieldNames : Array AsciiString :=
#[itemsFieldName, scaleFieldName]
def checkedAdd (left right : UInt64) : Except ByteArray UInt64 :=
let sum := left + right
if sum < left then
Except.error decodeError
else
Except.ok sum
def checkedMul (left right : UInt64) : Except ByteArray UInt64 :=
let product := left * right
if right == (0 : UInt64) then
Except.ok product
else if product / right == left then
Except.ok product
else
Except.error decodeError
def decodeItem (value : Value) : Except ByteArray Item := do
let fields <- requireObject value
let _ <- requireOnlyFields fields itemFieldNames
let id <- decodeRequiredField fields idFieldName (fun raw => requireUInt64 raw)
let weight <- decodeRequiredField fields weightFieldName (fun raw => requireUInt64 raw)
pure { id := id, weight := weight }
def decodeRequest (value : Value) : Except ByteArray Request := do
let fields <- requireObject value
let _ <- requireOnlyFields fields requestFieldNames
let items <-
decodeRequiredField fields itemsFieldName
(fun raw => decodeArray (fun item => decodeItem item) raw)
let scale <- decodeRequiredField fields scaleFieldName (fun raw => requireUInt64 raw)
pure { items := items, scale := scale }
def itemContribution (item : Item) : Except ByteArray UInt64 := do
checkedMul item.id item.weight
def weightedSum (items : Array Item) : Except ByteArray UInt64 :=
items.foldl
(fun state item =>
match state with
| Except.error err => Except.error err
| Except.ok sum =>
match itemContribution item with
| Except.error err => Except.error err
| Except.ok contribution => checkedAdd sum contribution)
(Except.ok 0)
def resultValue (weighted : UInt64) (count : Nat) : Value :=
Value.obj #[
Field.mk weightedFieldName (Value.num weighted),
Field.mk countFieldName (Value.num (UInt64.ofNat count))
]
def runRequest (request : Request) : Except ByteArray ByteArray := do
let base <- weightedSum request.items
let scaled <- checkedMul base request.scale
renderExcept (resultValue scaled request.items.size)
def transform (input : ByteArray) : Except ByteArray ByteArray := do
let value <- parseBytesExcept input
let request <- decodeRequest value
runRequest request
end Examples.JsonObjectArrayDecode
end LeanExe