{
"description": "Shared conformance fixtures for the readable Links Notation format. Every implementation must encode `value` to exactly `text` in the indented form and to exactly `line` in the single-line form, and decode both back to exactly `value`, so the four languages produce byte-identical documents.",
"valueEncoding": "A value is a single-key object naming its type: {\"null\": true}, {\"bool\": …}, {\"int\": …}, {\"float\": … | \"NaN\" | \"Infinity\" | \"-Infinity\"}, {\"str\": …}, {\"array\": [value, …]} or {\"object\": [[key, value], …]}. Object pairs are a list, not a map, because key order is part of the document.",
"skip": "`skip` maps a language id (js, python, rust, csharp) to the reason its value model cannot represent the case. A suite skips exactly the cases naming it.",
"cases": [
{
"name": "null_scalar",
"value": {
"null": true
},
"text": "null",
"line": "null"
},
{
"name": "bool_true",
"value": {
"bool": true
},
"text": "true",
"line": "true"
},
{
"name": "bool_false",
"value": {
"bool": false
},
"text": "false",
"line": "false"
},
{
"name": "int_positive",
"value": {
"int": 42
},
"text": "42",
"line": "42"
},
{
"name": "int_negative",
"value": {
"int": -7
},
"text": "-7",
"line": "-7"
},
{
"name": "int_zero",
"value": {
"int": 0
},
"text": "0",
"line": "0"
},
{
"name": "float_fraction",
"value": {
"float": 3.5
},
"text": "3.5",
"line": "3.5"
},
{
"name": "float_whole",
"value": {
"float": 2.0
},
"text": "2.0",
"skip": {
"js": "JavaScript has one number type, so 2.0 and 2 are the same value and the trailing '.0' cannot be recovered when encoding"
},
"line": "2.0"
},
{
"name": "float_negative",
"value": {
"float": -0.5
},
"text": "-0.5",
"line": "-0.5"
},
{
"name": "float_nan",
"value": {
"float": "NaN"
},
"text": "NaN",
"line": "NaN"
},
{
"name": "float_infinity",
"value": {
"float": "Infinity"
},
"text": "Infinity",
"line": "Infinity"
},
{
"name": "float_negative_infinity",
"value": {
"float": "-Infinity"
},
"text": "-Infinity",
"line": "-Infinity"
},
{
"name": "string_plain",
"value": {
"str": "root"
},
"text": "\"root\"",
"line": "\"root\""
},
{
"name": "string_empty",
"value": {
"str": ""
},
"text": "\"\"",
"line": "\"\""
},
{
"name": "string_with_spaces",
"value": {
"str": "with spaces"
},
"text": "\"with spaces\"",
"line": "\"with spaces\""
},
{
"name": "string_apostrophe",
"value": {
"str": "it's"
},
"text": "\"it's\"",
"line": "\"it's\""
},
{
"name": "string_double_quote",
"value": {
"str": "he said \"hello\""
},
"text": "'he said \"hello\"'",
"line": "'he said \"hello\"'"
},
{
"name": "string_both_quote_kinds",
"value": {
"str": "both \"kinds\" of 'quotes'"
},
"text": "\"\"\"both \"kinds\" of 'quotes'\"\"\"",
"line": "\"\"\"both \"kinds\" of 'quotes'\"\"\""
},
{
"name": "string_ending_with_the_quote_delimiter",
"value": {
"str": "it's \"quoted\""
},
"text": "\"\"\"it's \"quoted\"\"\"\"",
"line": "\"\"\"it's \"quoted\"\"\"\""
},
{
"name": "string_starting_with_the_quote_delimiter",
"value": {
"str": "\"quoted\" and it's"
},
"text": "'''\"quoted\" and it's'''",
"line": "'''\"quoted\" and it's'''"
},
{
"name": "string_unicode",
"value": {
"str": "unicode: 你好世界 🌍"
},
"text": "\"unicode: 你好世界 🌍\"",
"line": "\"unicode: 你好世界 🌍\""
},
{
"name": "string_parens_and_colon",
"value": {
"str": "parens (and) colons: yes"
},
"text": "\"parens (and) colons: yes\"",
"line": "\"parens (and) colons: yes\""
},
{
"name": "string_numeric",
"value": {
"str": "18878"
},
"text": "\"18878\"",
"line": "\"18878\""
},
{
"name": "string_boolean",
"value": {
"str": "true"
},
"text": "\"true\"",
"line": "\"true\""
},
{
"name": "string_with_newline",
"value": {
"str": "line1\nline2"
},
"text": "\"line1\nline2\"",
"line": "(escaped \"line1%0Aline2\")"
},
{
"name": "string_with_tab",
"value": {
"str": "a\tb"
},
"text": "\"a\tb\"",
"line": "\"a\tb\""
},
{
"name": "string_with_carriage_return",
"value": {
"str": "line1\r\nline2"
},
"text": "(escaped \"line1%0D\nline2\")",
"line": "(escaped \"line1%0D%0Aline2\")"
},
{
"name": "string_with_control_character",
"value": {
"str": "a\u0000b"
},
"text": "(escaped \"a%00b\")",
"line": "(escaped \"a%00b\")"
},
{
"name": "string_with_percent_sign",
"value": {
"str": "100% done, %0A is not an escape here"
},
"text": "\"100% done, %0A is not an escape here\"",
"line": "\"100% done, %0A is not an escape here\""
},
{
"name": "empty_array",
"value": {
"array": []
},
"text": "()",
"line": "()"
},
{
"name": "empty_object",
"value": {
"object": []
},
"text": "(\n)",
"line": "(o:)"
},
{
"name": "array_of_scalars",
"value": {
"array": [
{
"int": 1
},
{
"str": "two"
},
{
"bool": true
},
{
"null": true
}
]
},
"text": "(\n 1\n \"two\"\n true\n null\n)",
"line": "(1 \"two\" true null)"
},
{
"name": "object_of_scalars",
"value": {
"object": [
[
"name",
{
"str": "Alice"
}
],
[
"age",
{
"int": 30
}
]
]
},
"text": "(\n name \"Alice\"\n age 30\n)",
"line": "(o: (name \"Alice\") (age 30))"
},
{
"name": "nested_empty_containers",
"value": {
"object": [
[
"empty_array",
{
"array": []
}
],
[
"empty_object",
{
"object": []
}
]
]
},
"text": "(\n empty_array ()\n empty_object (\n )\n)",
"line": "(o: (empty_array ()) (empty_object (o:)))"
},
{
"name": "array_of_objects_keeps_record_boundaries",
"value": {
"array": [
{
"object": [
[
"id",
{
"str": "1"
}
],
[
"label",
{
"str": "one"
}
]
]
},
{
"object": [
[
"id",
{
"str": "2"
}
],
[
"label",
{
"str": "two"
}
]
]
}
]
},
"text": "(\n (\n id \"1\"\n label \"one\"\n )\n (\n id \"2\"\n label \"two\"\n )\n)",
"line": "((o: (id \"1\") (label \"one\")) (o: (id \"2\") (label \"two\")))"
},
{
"name": "array_of_arrays",
"value": {
"array": [
{
"array": [
{
"int": 1
},
{
"int": 2
}
]
},
{
"array": [
{
"int": 3
}
]
}
]
},
"text": "(\n (\n 1\n 2\n )\n (\n 3\n )\n)",
"line": "((1 2) (3))"
},
{
"name": "array_of_pairs_is_not_an_object",
"value": {
"array": [
{
"array": [
{
"str": "a"
},
{
"int": 1
}
]
},
{
"array": [
{
"str": "b"
},
{
"int": 2
}
]
}
]
},
"text": "(\n (\n \"a\"\n 1\n )\n (\n \"b\"\n 2\n )\n)",
"line": "((\"a\" 1) (\"b\" 2))"
},
{
"name": "array_holding_one_object",
"value": {
"array": [
{
"object": [
[
"a",
{
"int": 1
}
]
]
}
]
},
"text": "(\n (\n a 1\n )\n)",
"line": "((o: (a 1)))"
},
{
"name": "array_holding_an_empty_object",
"value": {
"array": [
{
"object": []
}
]
},
"text": "(\n (\n )\n)",
"line": "((o:))"
},
{
"name": "log_record_of_one_line",
"value": {
"object": [
[
"bytes",
{
"int": 2827
}
],
[
"complete",
{
"bool": true
}
],
[
"phase",
{
"str": "stream_end"
}
]
]
},
"text": "(\n bytes 2827\n complete true\n phase \"stream_end\"\n)",
"line": "(o: (bytes 2827) (complete true) (phase \"stream_end\"))"
},
{
"name": "single_pair_object_is_not_a_two_element_array",
"value": {
"object": [
[
"key",
{
"str": "value"
}
]
]
},
"text": "(\n key \"value\"\n)",
"line": "(o: (key \"value\"))"
},
{
"name": "two_element_array_is_not_a_single_pair_object",
"value": {
"array": [
{
"str": "key"
},
{
"str": "value"
}
]
},
"text": "(\n \"key\"\n \"value\"\n)",
"line": "(\"key\" \"value\")"
},
{
"name": "keys_that_need_quoting",
"value": {
"object": [
[
"two words",
{
"int": 1
}
],
[
"",
{
"int": 2
}
],
[
"base64",
{
"int": 3
}
],
[
"escaped",
{
"int": 4
}
],
[
"with:colon",
{
"int": 5
}
],
[
"with\"quote",
{
"int": 6
}
]
]
},
"text": "(\n \"two words\" 1\n \"\" 2\n \"base64\" 3\n \"escaped\" 4\n \"with:colon\" 5\n 'with\"quote' 6\n)",
"line": "(o: (\"two words\" 1) (\"\" 2) (\"base64\" 3) (\"escaped\" 4) (\"with:colon\" 5) ('with\"quote' 6))"
},
{
"name": "base64_key_with_plain_value_is_not_a_marker",
"value": {
"object": [
[
"base64",
{
"str": "plain text"
}
]
]
},
"text": "(\n \"base64\" \"plain text\"\n)",
"line": "(o: (\"base64\" \"plain text\"))"
},
{
"name": "escaped_key_with_plain_value_is_not_a_marker",
"value": {
"object": [
[
"escaped",
{
"str": "plain text"
}
]
]
},
"text": "(\n \"escaped\" \"plain text\"\n)",
"line": "(o: (\"escaped\" \"plain text\"))"
},
{
"name": "key_holding_a_newline_stays_a_key",
"value": {
"object": [
[
"a\nb",
{
"int": 1
}
]
]
},
"text": "(\n \"a\nb\" 1\n)",
"line": "(o: ((escaped \"a%0Ab\") 1))"
},
{
"name": "documented_router_state",
"value": {
"object": [
[
"type",
{
"str": "RouterState"
}
],
[
"server",
{
"object": [
[
"host",
{
"str": "127.0.0.1"
}
],
[
"port",
{
"int": 18878
}
]
]
}
],
[
"models",
{
"array": [
{
"str": "claude-haiku"
},
{
"str": "claude-opus"
}
]
}
]
]
},
"text": "(\n type \"RouterState\"\n server (\n host \"127.0.0.1\"\n port 18878\n )\n models (\n \"claude-haiku\"\n \"claude-opus\"\n )\n)",
"line": "(o: (type \"RouterState\") (server (o: (host \"127.0.0.1\") (port 18878))) (models (\"claude-haiku\" \"claude-opus\")))"
},
{
"name": "mixed_types_in_one_object",
"value": {
"object": [
[
"int",
{
"int": -7
}
],
[
"float",
{
"float": 3.5
}
],
[
"whole_float",
{
"float": 2.0
}
],
[
"yes",
{
"bool": true
}
],
[
"no",
{
"bool": false
}
],
[
"nothing",
{
"null": true
}
],
[
"numeric_string",
{
"str": "18878"
}
],
[
"boolean_string",
{
"str": "true"
}
]
]
},
"text": "(\n int -7\n float 3.5\n whole_float 2.0\n yes true\n no false\n nothing null\n numeric_string \"18878\"\n boolean_string \"true\"\n)",
"skip": {
"js": "JavaScript has one number type, so 2.0 and 2 are the same value and the trailing '.0' cannot be recovered when encoding"
},
"line": "(o: (int -7) (float 3.5) (whole_float 2.0) (yes true) (no false) (nothing null) (numeric_string \"18878\") (boolean_string \"true\"))"
},
{
"name": "only_unwritable_values_are_marked",
"value": {
"object": [
[
"readable",
{
"str": "still visible"
}
],
[
"multiline",
{
"str": "line1\nline2"
}
],
[
"tabbed",
{
"str": "a\tb"
}
],
[
"returned",
{
"str": "line1\rline2"
}
],
[
"control",
{
"str": "a\u0000b"
}
]
]
},
"text": "(\n readable \"still visible\"\n multiline \"line1\nline2\"\n tabbed \"a\tb\"\n returned (escaped \"line1%0Dline2\")\n control (escaped \"a%00b\")\n)",
"line": "(o: (readable \"still visible\") (multiline (escaped \"line1%0Aline2\")) (tabbed \"a\tb\") (returned (escaped \"line1%0Dline2\")) (control (escaped \"a%00b\")))"
},
{
"name": "repeated_value_is_written_every_time",
"value": {
"object": [
[
"first",
{
"str": "same"
}
],
[
"second",
{
"str": "same"
}
],
[
"third",
{
"str": "same"
}
]
]
},
"text": "(\n first \"same\"\n second \"same\"\n third \"same\"\n)",
"line": "(o: (first \"same\") (second \"same\") (third \"same\"))"
},
{
"name": "multi_line_log_record_stays_greppable",
"value": {
"object": [
[
"level",
{
"str": "error"
}
],
[
"message",
{
"str": "Traceback (most recent call last):\n File \"app.py\", line 42\nValueError: boom"
}
]
]
},
"text": "(\n level \"error\"\n message 'Traceback (most recent call last):\n File \"app.py\", line 42\nValueError: boom'\n)",
"line": "(o: (level \"error\") (message (escaped 'Traceback (most recent call last):%0A File \"app.py\", line 42%0AValueError: boom')))"
},
{
"name": "deeply_nested_objects",
"value": {
"object": [
[
"a",
{
"object": [
[
"b",
{
"object": [
[
"c",
{
"array": [
{
"int": 1
}
]
}
]
]
}
]
]
}
]
]
},
"text": "(\n a (\n b (\n c (\n 1\n )\n )\n )\n)",
"line": "(o: (a (o: (b (o: (c (1)))))))"
}
],
"lineEncoding": "`line` is the single-line form: the same document written without any line break, one record per line. Line breaks no longer separate rows there, so an object names itself with the `o` link id (`(o: (key value) ...)`, `(o:)` when empty) and a bare link is always an array.",
"legacyDecoding": "`legacy` holds documents written by versions up to 0.6.0, which every implementation must still decode: a string holding a control character was replaced by a `(base64 \"...\")` payload, and a string holding both quote kinds was written with its double quotes doubled. These are read only -- no implementation writes them any more, so they have no `line` of their own.",
"legacy": [
{
"name": "base64_marked_string",
"value": {
"str": "line1\nline2"
},
"text": "(base64 \"bGluZTEKbGluZTI=\")"
},
{
"name": "base64_marked_value_in_an_object",
"value": {
"object": [
[
"readable",
{
"str": "still visible"
}
],
[
"multiline",
{
"str": "line1\nline2"
}
]
]
},
"text": "(\n readable \"still visible\"\n multiline (base64 \"bGluZTEKbGluZTI=\")\n)"
},
{
"name": "base64_marked_value_on_one_line",
"value": {
"object": [
[
"multiline",
{
"str": "line1\nline2"
}
]
]
},
"text": "(o: (multiline (base64 \"bGluZTEKbGluZTI=\")))"
},
{
"name": "doubled_quotes_in_a_string",
"value": {
"str": "both \"kinds\" of 'quotes'"
},
"text": "\"both \"\"kinds\"\" of 'quotes'\""
}
]
}