1
0

m1-container-and-ordered-json-tree.md 2.7 KB

M1: xpj container and ordered JSON tree

Branch: m1-xpj-tree → main

What changed

  • New Go module git.monoexp.com/bajdev/mpckit (go 1.24).
  • New package internal/xpj (no Wails, no domain knowledge), per build plan 4.1:
    • Container (file.go): gunzip, split off the five header lines, parse the body; write header + body, gzip level 6 with mtime 0, XFL 0, OS 3 (the same 10 header bytes the device writes). ReadFile / WriteFile, Data(), Clone().
    • Ordered tree (node.go, json.go): parsed token by token with json.Decoder + UseNumber(). Objects keep key order (and duplicate keys); numbers keep their original text. Written in the device layout: one key or value per line, no indentation, ": " after keys, [] / {} for empty containers, no trailing newline, < > & / not escaped.
    • New values: NewInt (4), NewFloat (always 96.0, never 96; Python-repr shortest form, matching the reference writer), NewFloat32 (rounds to float32 first: 12.4 → 12.399999618530273), plus string/bool/null/array/object.
    • Helpers: Get / Set by path (tracks[0].program.drum.instruments[4].layersv[0]), Lookup / SetKey / DeleteKey, array Insert / Append / Remove, deep Clone, Int() / Float() accessors.
  • Moved demo-projects/ to testdata/device/ (build plan section 3 and 10.1); updated the two doc references.

Notes

  • Only the decompressed bytes are guaranteed identical. The compressed bytes differ from the device's (different deflate implementation); the device accepted the Python writer's gzip output, which uses the same header bytes as ours.
  • String escaping follows the reference writer (Python json, ensure_ascii=False). None of the device files contain an escape, so the device's own escaping style is unknown.
  • Writing a NaN/Inf float panics, and a Number node with invalid text fails at write time rather than producing a bad file.

Testing

go vet ./... and go test ./... pass.

  • M1 done-when: TestRoundTripDeviceProjects reads DemoBlank, Demo02 and DemoFile and re-encodes each byte-identical to the decompressed original (about 3 MB each), both directly and through gzip and back.
  • The same passes for the device-accepted files in testdata/accepted (T1-T3) and testdata/wav-formats (W1, W2).
  • Shape check on DemoBlank: tested header, 66 data keys, data.version 28, 128 pads, "Sequence 01" at 128 BPM.
  • Unit tests for layout, key order, escapes, parse errors, invalid number text, float formatting against Python repr values, paths, array edits and clone independence.

Next

M2: edit operations in internal/project, matching MpckitT1.xpj / MpckitT3.xpj and rebuilding Demo02.