Add ASN.1 schema export from static serialization templates.
Gajumaru Serialization Tests / tests (push) Successful in 48m24s
Gajumaru Serialization Tests / tests (push) Successful in 48m24s
Introduce gmser_schema_export to emit portable ASN.1 type definitions from tag/version/template triples (RLP remains the wire format). Export tag/1 and rev_tag/1 for discovery and naming, with docs and eunit coverage.
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
# Schema export (ASN.1)
|
||||
|
||||
`gmser_schema_export` turns static serialization templates into ASN.1 type
|
||||
definitions. ASN.1 is the **portable abstract model** (headers / codegen for
|
||||
other languages). The on-chain wire format remains RLP via `gmserialization`
|
||||
and `gmser_rlp`.
|
||||
|
||||
## Core API
|
||||
|
||||
Callers supply the three facts that fully define a static object layout:
|
||||
|
||||
```erlang
|
||||
Tag = gmser_chain_objects:tag(spend_tx), %% 12
|
||||
Vsn = 1,
|
||||
Template = [ {sender_id, id}
|
||||
, {recipient_id, id}
|
||||
, {amount, int}
|
||||
, {gas_price, int}
|
||||
, {gas, int}
|
||||
, {ttl, int}
|
||||
, {nonce, int}
|
||||
, {payload, binary}
|
||||
], %% e.g. aec_spend_tx:serialization_template(1)
|
||||
|
||||
{ok, TypeName, Defs} =
|
||||
gmser_schema_export:object_to_asn1(Tag, Vsn, Template).
|
||||
%% TypeName = "SpendTxV1"
|
||||
%% Defs = ASN.1 SEQUENCE body for that type
|
||||
```
|
||||
|
||||
Assemble a full module:
|
||||
|
||||
```erlang
|
||||
{ok, Asn1} =
|
||||
gmser_schema_export:module_to_asn1(
|
||||
'GajumaruChainObjects',
|
||||
[ {spend_tx, Tag, Vsn, Template}
|
||||
, {signed_tx, 11, 1, SignedTemplate}
|
||||
]).
|
||||
|
||||
ok = gmser_schema_export:write_module(
|
||||
"asn1_generated/GajumaruChainObjects.asn",
|
||||
'GajumaruChainObjects',
|
||||
Objects).
|
||||
```
|
||||
|
||||
Object specs are either `{Tag, Vsn, Template}` or
|
||||
`{TypeName, Tag, Vsn, Template}`. When the name is omitted, it is derived
|
||||
from `gmser_chain_objects:rev_tag(Tag)` (e.g. `spend_tx` → `SpendTxV1`).
|
||||
|
||||
## Options
|
||||
|
||||
```erlang
|
||||
#{ type_name => atom() | string() | binary() %% override derived name
|
||||
, include_tag_vsn => boolean() %% default true:
|
||||
%% first fields are
|
||||
%% tag INTEGER (Tag),
|
||||
%% vsn INTEGER (Vsn)
|
||||
}
|
||||
```
|
||||
|
||||
## Type mapping
|
||||
|
||||
| Template type | ASN.1 |
|
||||
|---------------|--------|
|
||||
| `int` | `BigInt` (`INTEGER (0..MAX)`) |
|
||||
| `uint8` … `uint128` | `Uint8` … `Uint128` |
|
||||
| `bool` | `BOOLEAN` |
|
||||
| `binary` | `OCTET STRING` |
|
||||
| `id` | `Id` |
|
||||
| `[T]` | `SEQUENCE OF T` |
|
||||
| `{T1,...,Tn}` | anonymous `SEQUENCE { c1 T1, ... }` |
|
||||
| `#{items := [{f,T},...]}` | anonymous `SEQUENCE { f T, ... }` |
|
||||
|
||||
Field names are lowerCamelCase (`gas_price` → `gasPrice`). Type names are
|
||||
UpperCamelCase with a version suffix (`spend_tx` + vsn 1 → `SpendTxV1`).
|
||||
|
||||
## Discovery of templates
|
||||
|
||||
This module does **not** scan the tree for all templates. Callers (or a later
|
||||
harvester in gajumaru) are expected to gather `{Tag, Vsn, Template}` triples
|
||||
from `serialization_template/1` and `gmser_chain_objects:tag/1`.
|
||||
|
||||
## Related
|
||||
|
||||
- Template language: `doc/static.md`, `gmserialization.erl`
|
||||
- Tag registry: `gmser_chain_objects:tag/1`, `rev_tag/1`
|
||||
- Earlier ASN.1 experiments: `asn1/`, `doc/asn1_compact.md`
|
||||
Reference in New Issue
Block a user