1 # ezjson: JSON for Bend 2, with a parser, a printer and a pull cursor 2 # 3 # `parse` reads text into Maybe Json. `print` writes compact text and 4 # `pretty` indented text. `cursor` reads one event at a time. Build null, 5 # booleans, numbers, strings, arrays, and objects; read them with get, at, and 6 # as_bool, as_str, as_num, as_u32, as_f32; has and len tell a missing key or 7 # index from a null. 8 import Base 9 import ./src/value.bend as Value 10 import ./src/parse.bend as Parse 11 import ./src/print.bend as Print 12 import ./src/pull.bend as Pull 13 14 # a text as a value, or None when it is not JSON 15 def parse(txt: String) -> Maybe<&2, Value.Json>: 16 Parse.parse(txt) 17 18 # a value as compact JSON 19 def print(val: Value.Json) -> String: 20 Print.print(val) 21 22 # a value as JSON indented two spaces a level, one element or member a line, 23 # with no newline at the end 24 def pretty(val: Value.Json) -> String: 25 Print.pretty(val) 26 27 # null 28 def null() -> Value.Json: 29 Value.null() 30 31 # a boolean 32 def bool(flag: Bool) -> Value.Json: 33 Value.bool(flag) 34 35 # a string 36 def str(txt: String) -> Value.Json: 37 Value.str(txt) 38 39 # a JSON number from its text, or null when that text is not one 40 def num(raw: String) -> Value.Json: 41 Value.num(raw) 42 43 # an object from pairs 44 def obj(pairs: List<&1, String & Value.Json>) -> Value.Json: 45 Value.obj(pairs) 46 47 # an array from a list 48 def arr(items: List<&2, Value.Json>) -> Value.Json: 49 Value.arr(items) 50 51 # an object's value at a key; JNull when it is not an object or has no such 52 # key 53 def get(val: Value.Json, key: String) -> Value.Json: 54 Value.get(val, key) 55 56 # an array's item at an index; JNull when it is not an array or has none 57 def at(val: Value.Json, idx: U32) -> Value.Json: 58 Value.at(val, idx) 59 60 # whether an object has a key; false when the value is not an object. Tells 61 # a missing key from a key whose value is null, which `get` does not 62 def has(val: Value.Json, key: String) -> Bool: 63 Value.has(val, key) 64 65 # how many elements an array, or members an object, has; 0 for anything else 66 def len(val: Value.Json) -> U32: 67 Value.len(val) 68 69 # a boolean, or none when the value is not one 70 def as_bool(val: Value.Json) -> Maybe<&2, Bool>: 71 Value.as_bool(val) 72 73 # a string, or none when the value is not one 74 def as_str(val: Value.Json) -> Maybe<&2, String>: 75 Value.as_str(val) 76 77 # a number's text, or none when the value is not a number 78 def as_num(val: Value.Json) -> Maybe<&2, String>: 79 Value.as_num(val) 80 81 # a number as a U32, or none when it is not one or does not fit 82 def as_u32(val: Value.Json) -> Maybe<&2, U32>: 83 Value.as_u32(val) 84 85 # a number as an F32, or none when it is not one or does not fit 86 def as_f32(val: Value.Json) -> Maybe<&2, F32>: 87 Value.as_f32(val) 88 89 # a cursor at the start of a JSON text. It holds the unread suffix of that 90 # text. A span event keeps its own suffix, so it stays valid after `next` 91 # moves the cursor, and it is gone when the event is dropped 92 def cursor(src: String) -> Pull.Cur: 93 Pull.cursor(src) 94 95 # the next event. Commas and colons are not events. After the root value, 96 # the next call is the end, or an error if another value follows 97 def next(cur: Pull.Cur) -> (Pull.Ev & Pull.Cur): 98 Pull.next(cur) 99 100 # drop the next value, scalar or container, without building it 101 def skip(cur: Pull.Cur) -> Pull.Cur: 102 Pull.skip(cur) 103 104 # the text of a string, key, or number event, copying a span. None otherwise 105 def text(ev: Pull.Ev) -> Maybe<&2, String>: 106 Pull.text(ev)