Skip to content

kdl: KDL 2.0 parser, writer and struct marshaler (consensus version) - #6

Merged
Jengro777 merged 7 commits into
vlang-community:mainfrom
davlgd:davlgd-consensus-community
Sep 23, 2026
Merged

Jengro777 merged 7 commits into
vlang-community:mainfrom
davlgd:davlgd-consensus-community

Conversation

@davlgd

@davlgd davlgd commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

kdl: KDL 2.0 parser, writer and struct marshaler

@Jengro777, this is the consensus version we discussed in vlang/v#28819, built from your implementation and mine; the details of what comes from where are below. It is opened here because vlang/kdl is still empty and cannot take a pull request yet; it replaces the current content of this repository, in six commits.

kdl reads and writes KDL 2.0 documents and maps them to V structs.

import kdl

doc := kdl.parse(text)!
port := doc.get('server')?.prop('port').as_int() or { 80 }
println(doc) // canonical KDL 2.0

cfg := kdl.decode[Config](text, rename: .kebab_case)!
println(kdl.encode(cfg)!)

A document is a list of nodes; a node has a name, arguments, properties and children; a value is string | i64 | f64 | bool | Null | BigInt with an optional type annotation. Syntax errors carry a line and a column. The writer produces the canonical form of the specification. encode and decode map a struct to a document: each field is a node, scalars inside a node are properties, structs and lists are children, and field tags (arg, args, props, child, omitempty, skip) cover the other layouts. Decoding fills the fields it finds, keeps defaults for the others, ignores what it does not know, and reports the rest with a typed error and a path such as server.route[1].timeout: expected f64, got string.

The module passes the official kdl-org test suite, vendored in tests/test_cases: the 95 invalid documents are rejected, the 243 valid ones produce the expected canonical output (floats compared as f64) and round-trip.

Where it comes from

This merges the two implementations proposed for vlib, vlang/v#28819 and vlang/v#27724 (vlang-community/kdl). The parser, writer and data model are those of #28819, the smaller of the two and the one that passed the whole official suite. The struct marshaling, its tags and its examples come from #27724, rewritten on this data model with stricter decoding: typed errors instead of silent coercions, and the struct validated before any data is read. Commits that reuse that work carry Co-authored-by: Jengro777.

Two features of #27724 are left out for now and will each get an issue: the relaxed parsing modes (NGINX-style identifiers, key: value, 10ms) and a writer that keeps the original formatting and comments.

Compilers and performance

The tests run with the new compiler, with the automatic fallback disabled, and with -old-compiler; CI covers Linux, macOS and Windows on V master plus an old-compiler job. A few constructs are written in a specific way to work around compiler behaviour, each with a comment in the code: with the old compiler under -prod, passing a large struct by value before every call made the writer quadratic (vlang/v#28418), so the internals pass references; with the new compiler, options are unwrapped with or rather than if x := opt inside generics, nodes are built in place rather than pushed as filled locals, and one wrong-code case around strings.Builder is avoided by binding an if expression first (a reproducer will be reported).

Parsing and encoding allocate about 2 KB per node, so on documents beyond roughly 100 000 nodes the Boehm collector dominates: 640 000 flat nodes (35 MB) parse in 12.7 s by default and in 0.7 s with GC_INITIAL_HEAP_SIZE=8G, which the README documents. Reducing that footprint would change the public types and make the API less direct (properties as an ordered list instead of a map, an annotation flag instead of ?string), so it is left for a later discussion.

Copilot AI balanced review requested due to automatic review settings September 21, 2026 14:33
@davlgd
davlgd force-pushed the davlgd-consensus-community branch from d3d4d90 to 31dd860 Compare September 21, 2026 14:42

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Schema validation currently occurs after parsing, and optional omitempty fields are encoded incorrectly.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 Medium severity · 1 Low severity

Open (3)
What changed in this PR

Replaces the previous implementation with a consensus KDL 2.0 parser, canonical writer, data model, and V struct marshaler.

Changes:

  • Adds strict parsing, writing, typed accessors, and struct encoding/decoding.
  • Vendors the official conformance suite and adds extensive tests.
  • Reorganizes examples, documentation, licensing, and CI.
File Description
kdl.v Defines the public data model and accessors.
parser.v Implements KDL 2.0 parsing.
scanner.v Handles tokens, numbers, Unicode, and escapes.
writer.v Produces canonical KDL output.
marshal.v Implements struct encoding and decoding.
*_test.v Tests parsing, writing, marshaling, regressions, fuzzing, and conformance.
examples/​** Adds updated usage examples.
tests/​test_cases/​input/​** Vendors 338 official parser fixtures.
tests/​test_cases/​expected_kdl/​** Vendors expected output for valid fixtures.
tests/​test_cases/​{README,LICENSE,CC-BY-SA-4.0}.txt Documents fixture provenance and licensing.
coerce/​**, document/​**, parser/​**, relaxed/​**, tokenizer/​** Removes the superseded implementation.
example/​**, tests/​{document,options,unicode}_test.v Removes obsolete examples and tests.
README.md, LICENSE, v.mod Updates API documentation, licensing, and metadata.
.github/​workflows/​ci.yml Tests both V compilers across supported platforms.
.gitattributes, .gitignore Configures fixture preservation and build exclusions.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread marshal.v
Comment thread marshal.v
Comment thread README.md Outdated
Copilot AI review requested due to automatic review settings September 21, 2026 14:43
@davlgd
davlgd force-pushed the davlgd-consensus-community branch from 31dd860 to 636a0c4 Compare September 21, 2026 14:45

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Decoding has schema-validation and numeric-underflow defects, and Windows CI can pass without running module checks.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 4 Medium severity · 1 Low severity

Open (5)

Comment thread .github/workflows/ci.yml Outdated
Comment thread marshal.v
Copilot AI review requested due to automatic review settings September 21, 2026 14:48
@davlgd
davlgd force-pushed the davlgd-consensus-community branch from 636a0c4 to 5b71121 Compare September 21, 2026 14:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Schema-validation ordering, optional omitempty behavior, and skipped Windows validation leave correctness and coverage gaps.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 Medium severity · 1 Low severity

Open (3)
Resolved since last review (5)

Comment thread .github/workflows/ci.yml Outdated
Comment thread marshal.v
Comment thread README.md Outdated
Copilot AI review requested due to automatic review settings September 21, 2026 14:59

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

BOM-prefixed error columns and enum omitempty behavior are currently incorrect.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 2 Medium severity

Open (2)
Resolved since last review (3)

Comment thread marshal.v
Comment thread parser.v
Copilot AI review requested due to automatic review settings September 21, 2026 15:15
@davlgd
davlgd force-pushed the davlgd-consensus-community branch from 5b71121 to a37fb66 Compare September 21, 2026 15:15
@davlgd
davlgd force-pushed the davlgd-consensus-community branch from a37fb66 to f95561f Compare September 21, 2026 15:16

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot review overview

🟡 Changes recommended

Optional-struct decoding can discard configured defaults, and one schema error template is grammatically incorrect.

Get a fresh assessment by requesting another Copilot review.

Review effort: Balanced
Findings: 1 Medium severity · 1 Low severity

Open (2)
Resolved since last review (2)

Comment thread marshal.v Outdated
Comment thread marshal.v Outdated
Copilot AI review requested due to automatic review settings September 21, 2026 15:21

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings September 21, 2026 15:35
@davlgd
davlgd force-pushed the davlgd-consensus-community branch from f95561f to adc2597 Compare September 21, 2026 15:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings September 21, 2026 15:36
@davlgd
davlgd force-pushed the davlgd-consensus-community branch from adc2597 to 112304a Compare September 21, 2026 15:36

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@davlgd
davlgd requested a balanced review from Copilot September 21, 2026 16:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Jengro777
Jengro777 merged commit c3ac060 into vlang-community:main Sep 23, 2026
4 checks passed
@Jengro777

Copy link
Copy Markdown
Member

Although the PR has been merged, the code organization is not very good.
Files of the same type should be merged into folders instead of all being spread out.
This is not conducive to maintenance.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants