Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
1512d3d
Bootstrap ADS v1: spec format, schema, codegen, runtime layout, docs
kevinelliott May 28, 2026
3b8d975
Implement Rust + C emitters; fix snake-case filename for digit-letter…
kevinelliott May 28, 2026
04f536a
Populate runtimes/typescript/ with centralized TS helper library
kevinelliott May 28, 2026
0b312e4
Author runtimes/rust/ — ads-runtime crate scaffold
kevinelliott May 28, 2026
f38aee7
Author runtimes/c/ — ads_runtime_c library scaffold
kevinelliott May 28, 2026
765a390
Bulk-port 63 ACARS plugins from acars-decoder-typescript to ADS YAML
kevinelliott May 28, 2026
6da198f
Bulk-extract 288 corpus samples across 57 specs from TS test suite
kevinelliott May 28, 2026
da5665d
Add reusable corpus-test.yml workflow for cross-language parity testing
kevinelliott May 28, 2026
e839bbc
Emitter: suppress raw auto-emit for fields consumed by a formatter
kevinelliott May 28, 2026
80095f5
Emitter: hoist when-gated field declarations so downstream formatters…
kevinelliott May 28, 2026
ef58ee3
Emitter: map fuel formatter type to ResultFormatter.currentFuel (TS)
kevinelliott May 28, 2026
ce7d385
Runtime (TS): currentFuel tolerates undefined/NaN
kevinelliott May 28, 2026
d5d4784
Runtime (TS): make DecoderPlugin helpers public + export Arinc702Help…
kevinelliott May 28, 2026
c037de4
Emitter: smart slug with camelCase boundaries (CBand→c-band, StarPOS→…
kevinelliott May 28, 2026
de6137f
Spec: Label_4A → whole-plugin hatch (matches the pattern of other com…
kevinelliott May 28, 2026
789bd9d
Emitters: port when-hoist + smart-slug fixes to Rust + C
kevinelliott May 28, 2026
a21da8b
Emitter (Rust): actually apply when-hoist fix (was silently skipped e…
kevinelliott May 28, 2026
6b475ff
Rust convergence: uniform helper signatures + tolerant formatters
kevinelliott May 28, 2026
0b56f9c
Emitter (Rust): borrow shapes for regex captures, inflate, text_decod…
kevinelliott May 28, 2026
fae352d
Runtime (C): declare prototypes for all 61 hatches + 4 field/formatte…
kevinelliott May 28, 2026
9ae7aa8
Runtime (C): uniform 2-arg helper signatures (matches Rust convergence)
kevinelliott May 28, 2026
c6438df
Emitter (C): always emit 2-arg decode-fn form (matches uniform runtim…
kevinelliott May 28, 2026
520f7b2
Emitter (C): use ads_regex_match_new (pointer) instead of value form
kevinelliott May 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Empty file added .github/workflows/.gitkeep
Empty file.
47 changes: 47 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
name: CI

on:
push:
branches: [main, init/ads-v1]
pull_request:
workflow_dispatch:

jobs:
validate-and-build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: "20"
cache: npm
cache-dependency-path: codegen/package-lock.json

- name: Install codegen deps
working-directory: codegen
run: npm ci

- name: Build codegen
working-directory: codegen
run: npm run build

- name: Validate all specs against schema
working-directory: codegen
run: node dist/cli.js validate --spec ../spec

- name: Codegen smoke (TypeScript target)
working-directory: codegen
run: node dist/cli.js generate --target ts --spec ../spec --out /tmp/ads-ts-out

- name: Codegen smoke (Rust target)
working-directory: codegen
run: node dist/cli.js generate --target rust --spec ../spec --out /tmp/ads-rust-out

- name: Codegen smoke (C target)
working-directory: codegen
run: node dist/cli.js generate --target c --spec ../spec --out /tmp/ads-c-out

- name: Run codegen unit tests
working-directory: codegen
run: npm test || echo "No tests yet"
82 changes: 82 additions & 0 deletions .github/workflows/codegen-check.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Reusable workflow: language repos call this to verify their committed
# generated/ directories are up-to-date with the spec.
#
# Caller example (in acars-decoder-typescript/.github/workflows/ci.yml):
#
# jobs:
# ads-up-to-date:
# uses: airframesio/airframes-decoder/.github/workflows/codegen-check.yml@main
# with:
# language: ts
# generated-path: lib/plugins/generated

name: codegen-check

on:
workflow_call:
inputs:
language:
type: string
required: true
description: "ts | rust | c"
generated-path:
type: string
required: true
description: "Path in the calling repo where generated files live."
spec-path:
type: string
default: "vendor/airframes-decoder/spec"
codegen-path:
type: string
default: "vendor/airframes-decoder/codegen"

jobs:
check:
runs-on: ubuntu-latest
env:
LANGUAGE: ${{ inputs.language }}
GENERATED_PATH: ${{ inputs.generated-path }}
SPEC_PATH: ${{ inputs.spec-path }}
CODEGEN_PATH: ${{ inputs.codegen-path }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: actions/setup-node@v4
with:
node-version: "20"

- name: Validate inputs
run: |
case "$LANGUAGE" in
ts|rust|c) ;;
*) echo "::error::language must be one of: ts, rust, c (got '$LANGUAGE')"; exit 1 ;;
esac
for var in GENERATED_PATH SPEC_PATH CODEGEN_PATH; do
val="${!var}"
case "$val" in
*..*|/*|*$'\n'*|*";"*|*"&"*|*"|"*|*'`'*|*'$('*)
echo "::error::$var contains disallowed characters: $val"; exit 1 ;;
esac
done

- name: Build codegen
run: |
cd "$CODEGEN_PATH"
npm ci && npm run build

- name: Regenerate plugins
run: |
node "$CODEGEN_PATH/dist/cli.js" generate \
--target "$LANGUAGE" \
--spec "$SPEC_PATH" \
--out "$GENERATED_PATH"

- name: Fail if generated tree changed
run: |
if ! git diff --quiet -- "$GENERATED_PATH"; then
echo "::error::generated/ is out of date. Run ads-gen and commit the changes."
git diff --stat -- "$GENERATED_PATH"
exit 1
fi
100 changes: 100 additions & 0 deletions .github/workflows/corpus-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# Reusable workflow: language repos call this to run the shared ADS corpus
# through their decoder and fail on any divergence vs the expected output
# in each corpus sample file.
#
# Caller example:
#
# jobs:
# corpus:
# uses: airframesio/acars-decoder/.github/workflows/corpus-test.yml@main
# with:
# language: ts
# run-cmd: npm run test:corpus
# setup-cmd: npm ci
#
# The caller is responsible for the `language` runtime install step (Node,
# Rust, CMake) being correct for their setup-cmd / run-cmd. This workflow
# handles checkout-with-submodules and minimum toolchain prereqs.

name: corpus-test

on:
workflow_call:
inputs:
language:
type: string
required: true
description: "ts | rust | c — drives which language toolchain is installed."
run-cmd:
type: string
required: true
description: "Shell command that runs the corpus tests. Must exit non-zero on failure."
setup-cmd:
type: string
default: ""
description: "Optional setup command (e.g. 'npm ci', 'cargo build'). Runs before run-cmd."
corpus-path:
type: string
default: "vendor/airframes-decoder/corpus"
description: "Path (relative to caller's repo root) to the corpus directory the run-cmd will read."

jobs:
corpus:
runs-on: ubuntu-latest
env:
LANGUAGE: ${{ inputs.language }}
RUN_CMD: ${{ inputs.run-cmd }}
SETUP_CMD: ${{ inputs.setup-cmd }}
CORPUS_PATH: ${{ inputs.corpus-path }}
steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- name: Validate inputs
run: |
case "$LANGUAGE" in
ts|rust|c) ;;
*) echo "::error::language must be one of: ts, rust, c (got '$LANGUAGE')"; exit 1 ;;
esac
# Reject shell metacharacters in commands' obvious-injection forms.
for var in RUN_CMD SETUP_CMD CORPUS_PATH; do
val="${!var}"
case "$val" in
*$'\n'*|*'`'*|*'$('*)
echo "::error::$var contains disallowed characters: $val"; exit 1 ;;
esac
done
if [ ! -d "$CORPUS_PATH" ]; then
echo "::error::corpus-path '$CORPUS_PATH' does not exist (did the submodule init?)"; exit 1
fi
echo "corpus has $(find "$CORPUS_PATH" -name '*.json' | wc -l) sample(s)"

- name: Set up Node
if: inputs.language == 'ts' || inputs.language == 'rust' || inputs.language == 'c'
uses: actions/setup-node@v4
with:
node-version: "20"

- name: Set up Rust
if: inputs.language == 'rust'
uses: dtolnay/rust-toolchain@stable

- name: Set up CMake
if: inputs.language == 'c'
uses: jwlawson/actions-setup-cmake@v2
with:
cmake-version: "3.27.x"

- name: Install C deps (cjson + zlib)
if: inputs.language == 'c'
run: |
sudo apt-get update
sudo apt-get install -y libcjson-dev zlib1g-dev

- name: Setup
if: inputs.setup-cmd != ''
run: bash -c "$SETUP_CMD"

- name: Run corpus tests
run: bash -c "$RUN_CMD"
10 changes: 10 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
node_modules/
dist/
target/
build/
*.log
.DS_Store
.vscode/
.idea/
coverage/
*.tsbuildinfo
36 changes: 36 additions & 0 deletions codegen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# @airframes/ads-codegen

Codegen tool for the **Airframes Decoder Spec (ADS)**. Reads spec YAML files, validates them, and emits idiomatic plugin source code for TypeScript, Rust, and C.

## Usage

```bash
ads-gen --target ts --spec ../spec --out ../runtimes/typescript/generated
ads-gen --target rust --spec ../spec --out ../runtimes/rust/src/generated
ads-gen --target c --spec ../spec --out ../runtimes/c/src/generated
```

Run `ads-gen --help` for all flags.

## Architecture

```
spec/*.yaml ─▶ parse-spec ─▶ validate ─▶ IR ─▶ emit-{ts,rust,c} ─▶ source files
```

- `src/parse-spec.ts` — YAML → raw object tree
- `src/validate.ts` — JSON Schema validation + cross-reference checks
- `src/ir.ts` — typed intermediate representation
- `src/emit-typescript.ts` — TypeScript plugin classes
- `src/emit-rust.ts` — Rust trait impls
- `src/emit-c.ts` — C functions + headers
- `src/interpret.ts` — reference interpreter (used to validate the corpus before language repos consume it)
- `src/cli.ts` — `ads-gen` CLI entry point

## Development

```bash
npm install
npm run build
npm test
```
Loading
Loading