Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 9 additions & 10 deletions spec/toml_test.almd
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import self as toml
import json

type ServerConfig: Codec = { host: String, port: Int }

Expand All @@ -17,44 +16,44 @@ fn unwrap(r: Result[Value, String]) -> Value = match r {
},
}

fn gs(v: Value, key: String) -> String = match value.get(v, key) {
fn gs(v: Value, key: String) -> String = match value.field(v, key) {
ok(inner) => match value.as_string(inner) {
ok(s) => s,
err(_) => "",
},
err(_) => "",
}

fn gi(v: Value, key: String) -> Int = match value.get(v, key) {
fn gi(v: Value, key: String) -> Int = match value.field(v, key) {
ok(inner) => match value.as_int(inner) {
ok(n) => n,
err(_) => 0,
},
err(_) => 0,
}

fn gf(v: Value, key: String) -> Float = match value.get(v, key) {
fn gf(v: Value, key: String) -> Float = match value.field(v, key) {
ok(inner) => match value.as_float(inner) {
ok(f) => f,
err(_) => 0.0,
},
err(_) => 0.0,
}

fn gb(v: Value, key: String) -> Bool = match value.get(v, key) {
fn gb(v: Value, key: String) -> Bool = match value.field(v, key) {
ok(inner) => match value.as_bool(inner) {
ok(b) => b,
err(_) => false,
},
err(_) => false,
}

fn go(v: Value, key: String) -> Value = match value.get(v, key) {
fn go(v: Value, key: String) -> Value = match value.field(v, key) {
ok(x) => x,
err(_) => value.object([]),
}

fn ga(v: Value, key: String) -> List[Value] = match value.get(v, key) {
fn ga(v: Value, key: String) -> List[Value] = match value.field(v, key) {
ok(inner) => match value.as_array(inner) {
ok(xs) => xs,
err(_) => [],
Expand Down Expand Up @@ -336,7 +335,7 @@ test "inline table" {

test "empty inline table" {
let v = unwrap(toml.parse("empty = {}"));
assert_eq(list.len(json.keys(go(v, "empty"))), 0)
assert_eq(list.len(value.keys(go(v, "empty"))), 0)
}

test "inline table with dotted key" {
Expand All @@ -356,12 +355,12 @@ test "comments" {

test "empty input" {
let v = unwrap(toml.parse(""));
assert_eq(json.keys(v), [])
assert_eq(value.keys(v), [])
}

test "only comments" {
let v = unwrap(toml.parse("# comment\n# another"));
assert_eq(json.keys(v), [])
assert_eq(value.keys(v), [])
}

test "blank lines between kv" {
Expand Down
21 changes: 10 additions & 11 deletions src/mod.almd
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
// toml.encode(config) → Codec type to TOML string
// Config.decode(toml.parse(s)!) → TOML string to Codec type

import json

// ── Public API ──────────────────────────────────────

Expand Down Expand Up @@ -350,7 +349,7 @@ local fn set_nested(root: Value, path: List[String], v: Value) -> Value =
some(key) => {
let rest = list.drop(path, 1)
let child = if list.is_empty(rest) then v
else set_nested(value.get(root, key) ?? value.object([]), rest, v)
else set_nested(value.field(root, key) ?? value.object([]), rest, v)
value.merge(root, value.object([(key, child)]))
},
}
Expand All @@ -361,10 +360,10 @@ local fn append_aot(root: Value, path: List[String]) -> Value =
some(key) => {
let rest = list.drop(path, 1)
if list.is_empty(rest) then {
let arr = value.as_array(value.get(root, key) ?? value.object([])) ?? []
let arr = value.as_array(value.field(root, key) ?? value.object([])) ?? []
value.merge(root, value.object([(key, value.array(arr + [value.object([])]))]))
} else {
let child = value.get(root, key) ?? value.object([])
let child = value.field(root, key) ?? value.object([])
value.merge(root, value.object([(key, append_aot(child, rest))]))
}
},
Expand All @@ -376,14 +375,14 @@ local fn set_in_aot_last(root: Value, aot_path: List[String], keys: List[String]
some(key) => {
let rest = list.drop(aot_path, 1)
if list.is_empty(rest) then {
let items = value.as_array(value.get(root, key) ?? value.object([])) ?? []
let items = value.as_array(value.field(root, key) ?? value.object([])) ?? []
let idx = list.len(items) - 1
if idx >= 0 then {
let updated = list.set(items, idx, set_nested(list.get(items, idx) ?? value.object([]), keys, v))
value.merge(root, value.object([(key, value.array(updated))]))
} else root
} else {
let child = value.get(root, key) ?? value.object([])
let child = value.field(root, key) ?? value.object([])
value.merge(root, value.object([(key, set_in_aot_last(child, rest, keys, v))]))
}
},
Expand All @@ -392,14 +391,14 @@ local fn set_in_aot_last(root: Value, aot_path: List[String], keys: List[String]
// ── Serializer ──────────────────────────────────────

local fn emit_sections(v: Value, path: List[String]) -> List[String] = {
let keys = json.keys(v)
let keys = value.keys(v)
let simple = keys |> list.filter_map((key) => {
let val = value.get(v, key) ?? value.null()
let val = value.field(v, key) ?? value.null()
if not is_table(val) and not is_aot(val) then some("${emit_key(key)} = ${emit_val(val)}")
else none
})
let nested = keys |> list.flat_map((key) => {
let val = value.get(v, key) ?? value.null()
let val = value.field(v, key) ?? value.null()
if is_aot(val) then
(value.as_array(val) ?? []) |> list.flat_map((item) =>
["", "[[${emit_path(path + [key])}]]"] + emit_sections(item, path + [key])
Expand Down Expand Up @@ -453,11 +452,11 @@ local fn emit_float(f: Float) -> String =
}

local fn emit_inline_obj(v: Value) -> String = {
let keys = json.keys(v)
let keys = value.keys(v)
if list.is_empty(keys) then "{ }"
else {
let pairs = keys |> list.map((k) => {
let val = value.get(v, k) ?? value.null()
let val = value.field(v, k) ?? value.null()
"${emit_key(k)} = ${emit_val(val)}"
})
"{ ${list.join(pairs, ", ")} }"
Expand Down