Skip to content

feat(avn): implement ASN.1 Value Notation codec#544

Open
jp-marcotte wants to merge 3 commits intolibrasn:mainfrom
jp-marcotte:feat/avn-codec
Open

feat(avn): implement ASN.1 Value Notation codec#544
jp-marcotte wants to merge 3 commits intolibrasn:mainfrom
jp-marcotte:feat/avn-codec

Conversation

@jp-marcotte
Copy link

Add a new Codec::Avn variant implementing the ASN.1 Value Notation text format as defined in ITU-T X.680. AVN is the native textual representation used in ASN.1 modules for DEFAULT values and value assignments, distinct from JER (JSON) and XER (XML).

Architecture mirrors the JER codec:

  • src/avn/value.rs: AvnValue IR enum with Display impl for pretty-printed output (indented SEQUENCEs, 'HEX'H/'BIN'B bit strings, { arc... } OIDs, id : val CHOICEs)
  • src/avn/enc.rs: Encoder struct preserving SEQUENCE field declaration order via Vec<(String, AvnValue)> (vs JER's BTreeMap)
  • src/avn/de.rs: two-phase decode — recursive-descent lexer/parser producing AvnValue tree, then type-directed dispatch; handles space-separated OID arc notation and underscore identifiers
  • Error types AvnDecodeErrorKind / AvnEncodeErrorKind integrated into the existing snafu error hierarchy
  • Codec::Avn dispatch wired into all five Codec methods

Key format rules:

  • BOOLEAN: TRUE / FALSE
  • OCTET STRING: '01FF'H
  • BIT STRING: 'A0'H (byte-aligned) or '10'B (non-byte-aligned)
  • OID: { 2 5 4 3 } (space-separated, no commas)
  • SEQUENCE: {\n field value,\n ...\n}
  • CHOICE: identifier : value
  • Absent OPTIONAL fields omitted entirely

Round-trip tests cover: bool, integer, null, octet string, bit string, OID, enumerated, choice, sequence-of, nested sequences with absent optionals, and hyphenated/underscored field identifiers.

Add a new `Codec::Avn` variant implementing the ASN.1 Value Notation
text format as defined in ITU-T X.680. AVN is the native textual
representation used in ASN.1 modules for DEFAULT values and value
assignments, distinct from JER (JSON) and XER (XML).

Architecture mirrors the JER codec:
- `src/avn/value.rs`: `AvnValue` IR enum with `Display` impl for
  pretty-printed output (indented SEQUENCEs, `'HEX'H`/`'BIN'B`
  bit strings, `{ arc... }` OIDs, `id : val` CHOICEs)
- `src/avn/enc.rs`: `Encoder` struct preserving SEQUENCE field
  declaration order via `Vec<(String, AvnValue)>` (vs JER's BTreeMap)
- `src/avn/de.rs`: two-phase decode — recursive-descent lexer/parser
  producing `AvnValue` tree, then type-directed dispatch; handles
  space-separated OID arc notation and underscore identifiers
- Error types `AvnDecodeErrorKind` / `AvnEncodeErrorKind` integrated
  into the existing snafu error hierarchy
- `Codec::Avn` dispatch wired into all five `Codec` methods

Key format rules:
- BOOLEAN: `TRUE` / `FALSE`
- OCTET STRING: `'01FF'H`
- BIT STRING: `'A0'H` (byte-aligned) or `'10'B` (non-byte-aligned)
- OID: `{ 2 5 4 3 }` (space-separated, no commas)
- SEQUENCE: `{\n  field value,\n  ...\n}`
- CHOICE: `identifier : value`
- Absent OPTIONAL fields omitted entirely

Round-trip tests cover: bool, integer, null, octet string, bit string,
OID, enumerated, choice, sequence-of, nested sequences with absent
optionals, and hyphenated/underscored field identifiers.
@jp-marcotte jp-marcotte marked this pull request as ready for review March 12, 2026 02:13
Null,
}

fn lex(input: &str) -> Result<alloc::vec::Vec<Token>, DecodeError> {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason not to use nom for parsing? We already depend on it for binary parsing, so it wouldn't add any cost to use it here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no reasons, beside lack of caffeine I guess. Let me change that.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean it will be easier now that you've written it, so it will be easy to rewrite it with the tests ensuring it doesn't regress 🙂

@XAMPPRocky
Copy link
Collaborator

Thank you for your PR! Exciting o see more formats added. What are you using it for if you're comfortable sharing?

@jp-marcotte
Copy link
Author

jp-marcotte commented Mar 13, 2026

Thank you for your PR! Exciting o see more formats added. What are you using it for if you're comfortable sharing?

AVN is used with Trusted Connectivity Alliance specs, is the industry standard format to describe the content of an eSIM.

…coder stack

Sequence now stores Vec<(String, Option<AvnValue>)> where None represents
an absent optional field. The decoder stack changes from Vec<AvnValue> to
Vec<Option<AvnValue>> for the same reason. This removes the Absent variant
from the public AvnValue enum entirely.

Thanks to @XAMPPRocky for the review.
@XAMPPRocky
Copy link
Collaborator

XAMPPRocky commented Mar 13, 2026

Interesting! Would you also be interested in contributing some those specs to be added in the specs crates directory?

@jp-marcotte
Copy link
Author

Interesting! Would you also be interested in contributing some those specs to be added in the specs crates directory?

Can you elaborate on this? Do you mean the rasn/standards ?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants