Skip to content

[0.7] Writer must reject keys it cannot round-trip #5

Description

@PHPCraftdream

Target branch: 0.7 (breaking — calls that return Ok today would return Err).

Split out of #4. That PR carries two kinds of change: fixes that turn silent corruption into correct output (non-breaking, going to main), and this one — refusing to emit keys no form can round-trip.

The keys

Verified against main at 0.6.2 — every one of these emits happily today and re-parses to something else:

Key Emitted Re-parses as
"" : v root flips Object → Array
"##note" ##note: v pair eaten as a comment → {}
" k" / "k " raw edges trimmed by the parser (§ 4)
"k\nx" raw line split
"a,b", "a{b", … raw InvalidKey or structural break

The CR-in-String rule (§ 5.9.7) is the precedent: unrepresentable means error, not silent corruption.

Why breaking, and why not main

These calls succeed today. The output is wrong, but it parses — so in principle someone could be depending on it. That is the line we drew: main gets everything that was already broken beyond use (unparseable output, lost bytes), 0.7 gets the cases that quietly parsed into different data.

Depends on

Do #7 first. § 4 mandates ten key escapes and the parser accepts three; once the parser catches up, keys containing ( ) { } [ ] , become representable and drop out of this issue entirely — leaving only "", "##note", edge whitespace and line breaks. Landing this issue first would bake in refusals we are about to make unnecessary.

Definition of done

  • Writer validates keys on all three surfaces (emit_canonical, serde to_string, render / to_string_force_strings) and returns a descriptive error naming the reason and the spec section.
  • Regression tests in the crate: one per rejected class, per surface — asserting the error, not just "not Ok". Plus guard tests for tricky-but-representable keys so the check does not over-reject.
  • Regression fixtures in ktav-lang/spec: this needs the new "unrepresentable value" fixture category (see the spec-side issue) — a JSON value plus the expected refusal. Without fixtures the other six bindings will drift, which is exactly what the conformance suite exists to prevent.

A working implementation already exists in #4 (9 tests); it needs re-basing onto 0.7 once the escape work lands.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions