Py_sax2sab/README.md
arda.aydin@ontrol.com.tr 3e313f8223 First commit tekrar
Bu dosyalar Claude uzerinden olusturuldu
2026-08-12 20:49:31 +03:00

74 lines
3.1 KiB
Markdown

# PySedonac
Pure-Python `.sax` -> `.sab` encoder. No Java, no JRE.
Ported from the Sedona 1.2 runtime library — `sedona/src/sedona/src/sedona/offline/OfflineApp.java`
and friends, **not** from `sedonac/` (that's the language compiler; app file conversion lives in the
runtime lib).
Verified byte-identical to `sedonac.exe` on a 189-component / 217-link app across 18 kits.
## Usage
python sab.py <app.sax> <sedona_home> <out.sab>
`sedona_home` is the directory holding `manifests/` — kit manifests are required, since slot ids and
types are resolved from them.
## Verify
python verify.py [sedona_home]
Compares our output against the checked-in `test_normal_sedonac.sab`. Pass a sedona home containing
`bin/sedonac.exe` and call `check(sax)` with no reference to diff against a live sedonac run instead.
## Format
Big-endian. **No padding, no alignment**`Buf.bigEndian = true`, `checkAlignment = false`. The
`align()`/`pad()` helpers exist on `Buf` but the app encoder never calls them.
"sapp" (i4 0x73617070) | version (i4 0x0003)
schema: u1 kitCount, then per kit: cstr name, i4 checksum
u2 maxId
components (ascending id, NOT tree order), each:
u2 id | u1 kitId | u1 typeId
cstr name | u2 parentId | u2 firstChildId | u2 nextSiblingId (0xffff = none)
config prop values in slot-id order, bare - no names, no ids
u1 ';'
u2 0xffff
links: u2 fromComp | u1 fromSlot | u2 toComp | u1 toSlot
u2 0xffff
u1 '.'
Values: `bool` -> u1 (0/1, **2 = null**) | `byte` -> u1 | `short` -> u2 | `int` -> i4 | `long` -> i8 |
`float` -> f4 | `double` -> f8 | `Buf` -> u2 len + raw bytes | `asStr` -> u2 (len+1) + ASCII + NUL.
Slot flags (`SlotManifest.flagsToString`): `a` = action, `c` = config, `s` = asStr, `o` = operator.
## Three things that will bite you
**Kit order is normative.** `sys` at index 0, everything else alphabetical (`Schema.sortKits`). Kit id
is the position in that sorted list, and every component record references it. Document order of the
`<schema>` block in the SAX is irrelevant.
**Slot ids come from flattening.** `Type.resolveSlots` inherits base slots then appends declared ones;
the resulting index is the id written into links. An **action override** reuses the inherited id rather
than appending (`Type.addSlot`) — get that wrong and every subsequent slot id shifts.
**Missing prop is not null.** When a `<prop>` is absent the value is the manifest's `default`
attribute, or failing that `Value.defaultForType` -> **zero**. `null` (NaN, `0x7fc00000` for float)
only when the SAX literally says `val="null"`. This was the single bug between "same length" and
"byte identical".
## Not covered
Only what `test_normal.sax` exercises is proven. Untested: action overrides, `Buf`-typed props
(base64 path is written but unexercised), non-ASCII strings (Sedona `Str` is ASCII-only and will
raise), and apps whose component ids exceed the 256-entry lookup table.
## Alternative
If a JRE is present, `sedona/bin/sedonac.exe <file.sax|.sab>` converts either direction off the file
extension, and additionally validates the app (schema resolution, RAM/FLASH sizing) in a way this
encoder does not.