type Count { expected: Id total: Int } encode(text: Text) (answer: Id) { answer = dever.id.fromText(text) } decode(value: Id) (answer: Text) { answer = dever.id.toText(value) } roundtrip(text: Text) (answer: Text) { answer = dever.id.toText(dever.id.fromText(text)) } encodeAll(texts: List) (answer: List) { answer = each(dever.id.fromText, texts) } countMatch(value: Id, state: Count) (next: Count) { next = state next.total = state.total + matching(value == state.expected) } matching(value: true) (answer: Int) { answer = 1 } matching(value: false) (answer: Int) { answer = 0 } countEqual(values: List, expected: Id) (answer: Int) { state = reduce(countMatch, values, Count { expected = expected total = 0 }) answer = state.total } readKey(key: Id, values: Map) (answer: Int) { answer = present(get(values, key)) } present(value: Int) (answer: Int) { answer = value } present(value: null) (answer: Int) { answer = 0 } lookup(values: Map, keys: List) (answer: Int) { answer = sum(readKey, keys, values) } insert(text: Text, state: Map) (next: Map) { next = put(state, dever.id.fromText(text), length(text)) } buildMap(texts: List) (answer: Map) { answer = reduce(insert, texts, {}) } buildEntries(texts: List) (answer: List>) { answer = entries(buildMap(texts)) } optionalId(value: Id) (answer: Text) { answer = dever.id.toText(value) } optionalId(value: null) (answer: Text) { answer = "missing" } duplicate(left: Text, right: Text) (answer: Map) { answer = { dever.id.fromText(left) = 1 dever.id.fromText(right) = 2 } } duplicateEntry() (answer: Map) { answer = duplicate("same", "same") } failureEntry() (answer: Id) { answer = dever.id.fromText(dever.bytes.toText(dever.bytes.fromInts([255]))) } verify() (answer: Bool) { original = encode("雪🙂") alias = original original = encode("changed") answer = decode(alias) == "雪🙂" and decode(original) == "changed" answer = answer and encode("same") == encode("same") and encode("Same") != encode("same") answer = answer and encode("é") != encode("é") and roundtrip(" 雪\n\t") == " 雪\n\t" answer = answer and optionalId(encode("")) == "" and optionalId(null) == "missing" nul = dever.bytes.toText(dever.bytes.fromInts([97, 0, 98])) answer = answer and roundtrip(nul) == nul ids = encodeAll(["a", "a", "b"]) answer = answer and countEqual(ids, encode("a")) == 2 and countEqual([], encode("")) == 0 answer = answer and first(ids) == encode("a") and first(encodeAll([])) == null state = Count { expected = alias total = 2 } changed = state changed.expected = encode("new") answer = answer and decode(state.expected) == "雪🙂" and decode(changed.expected) == "new" values = buildMap(["雪", "a", "雪", "🙂"]) updated = put(values, encode("a"), 9) removed = remove(updated, encode("雪")) answer = answer and get(values, encode("a")) == 1 and get(updated, encode("a")) == 9 answer = answer and length(removed) == 2 and get(removed, encode("雪")) == null answer = answer and lookup(values, encodeAll(["a", "missing", "雪"])) == 2 answer = answer and buildEntries(["a", "b", "a"]) == entries(buildMap(["a", "b"])) answer = answer and values != buildMap(["a", "雪", "🙂"]) }