Please check the build logs for more information.
See Builds for ideas on how to fix a failed build, or Metadata for how to configure docs.rs builds.
If you believe this is docs.rs' fault, open an issue.
oxirush-ngap
A complete NGAP (NG Application Protocol) codec for 5G, auto-generated from 3GPP ASN.1 definitions (TS 38.413) using Aligned PER (APER) encoding.
Part of the OxiRush project — a 5G Core Network testing framework.
Features
- Full TS 38.413 coverage — every NGAP procedure, IE, and PDU type
- Auto-generated from ASN.1 — the codec is rebuilt at
cargo buildfrom the canonical 3GPP ASN.1 files, tracking spec updates automatically - APER encoding/decoding — standards-compliant Aligned PER via
asn1-codecs - Serde support — all generated types derive
Serialize/Deserialize - Round-trip fidelity — encode then decode produces identical structures
- Builder macros —
build_ngap!andbuild_ngap_ie!eliminate the deeply nested ProtocolIEs boilerplate - Extraction macro —
extract_ngap_ies!pulls typed fields from decoded messages withreq/optsemantics - Auto-derived IE IDs and procedure codes — no manual constants needed, derived at build time from ASN.1
#[asn(key = N)]attributes - Encode/decode convenience —
pdu.encode()andNGAP_PDU::decode(&bytes)wrap the raw APER codec - PDU inspection —
pdu.procedure_name(),pdu.direction(),pdu.procedure_code(),pdu.is_initiating() - Display impl —
format!("{pdu}")→"InitiatingMessage NGSetup (code=21)" - Type builders —
plmn(),guami(),tai(),nr_cgi(),global_gnb_id(),s_nssai()for common NGAP IEs - Bitvec helpers —
int_to_bitvec(),bytes_to_bitvec()for AMF identity, security keys, cell IDs
Quick start
[]
= "0.3"
Encode an NGAP PDU (with macros)
The auto-generated types are deeply nested. The build_ngap! macro provides a concise DSL:
use ;
use *;
// Simple: UEContextReleaseRequest with a cause
let pdu = build_ngap!;
// Complex: InitialContextSetupRequest with GUAMI, NSSAI, security key helpers
let pdu = build_ngap!;
// Encode to APER wire format
let wire_bytes = pdu.encode.unwrap;
// Inspect the PDU
println!; // "InitiatingMessage InitialContextSetup (code=14)"
assert_eq!;
assert!;
build_ngap! arguments: (Direction, Procedure, Criticality, MessageType, IEs...)
Each IE: Criticality IeName(value) — IE IDs and procedure codes are auto-derived at build time.
Raw values (e.g. u64) auto-convert to newtypes via .into().
Build individual IEs when you need conditional logic:
use ;
let cause_ie = build_ngap_ie!;
Decode and extract IEs (with macros)
The extract_ngap_ies! macro pulls typed fields from a decoded message. Required fields that are missing cause the enclosing function to return Err(MissingIeError). Optional fields stay as Option<T>.
use ;
// Simple: extract UE IDs and an optional cause
// Complex: extract many IEs with pattern matching and type conversions
extract_ngap_ies! arguments: (msg_var, MessageType, fields...)
Each field: req|opt name: Type = IeName(binding) with optional => custom_expr
When => expr is omitted, defaults to binding.0 (newtype unwrap).
Encode / Decode
use NGAP_PDU;
// Encode NGAP_PDU to APER bytes
let bytes = pdu.encode.unwrap;
// Decode APER bytes to NGAP_PDU
let decoded = NGAP_PDUdecode.unwrap;
Type builders (helpers module)
use *;
let p = plmn; // PLMNIdentity (3-byte TBCD)
let g = guami; // GUAMI (PLMN + AMF identity)
let t = tai; // TAI (PLMN + TAC)
let cgi = nr_cgi; // NR-CGI (36-bit cell ID)
let gnb = global_gnb_id; // GlobalGNB-ID (24-bit gNB-ID)
let nssai = s_nssai; // S-NSSAI (SST + optional SD)
let sec = ue_security_capabilities; // UESecurityCapabilities
// Bitvec conversion for NGAP bitstring fields
let key = bytes_to_bitvec; // SecurityKey (256 bits)
let region = int_to_bitvec; // AMFRegionID (8 bits)
Without macros
The auto-generated types are fully usable without macros — you can construct NGAP_PDU values directly and pattern-match on decoded ones. The macros simply eliminate the repetitive ProtocolIE_ID(...), Criticality(...), and {Msg}ProtocolIEs_EntryValue::Id_... boilerplate. See examples/decode_manually.rs for a complete encode → decode → inspect example without macros.
How code generation works
The build script (build/main.rs) runs at cargo build time:
- ASN.1 compilation — reads the 3GPP ASN.1 source files from
ngap/(NGAP-PDU-Descriptions.asn,NGAP-PDU-Contents.asn,NGAP-IEs.asn,NGAP-CommonDataTypes.asn,NGAP-Constants.asn,NGAP-Containers.asn) and compiles them to Rust usingasn1-compiler - Post-processing — the build script then parses the generated code to emit:
From<InnerType>impls for all single-field newtypes (enables.into()auto-conversion inbuild_ngap!)__ngap_ie_id!macro — maps IE variant names to numeric IDs by parsing#[asn(key = N)]attributes onProtocolIEs_EntryValueenums (207 arms)__ngap_proc_code!macro — maps procedure names to codes by parsing{Direction}Valueenums (66 arms)impl NGAP_PDU—procedure_code(),direction(),procedure_name(),is_initiating()/is_successful()/is_unsuccessful()impl Display for NGAP_PDU— human-readable PDU formatting
- Output —
src/ngap.rs, the complete APER codec with helper macros and impls (~21K lines)
Do not edit src/ngap.rs manually. Modify the ASN.1 files in ngap/ or the build script in build/ instead.
Key types
| Type | Description |
|---|---|
NGAP_PDU |
Top-level enum: InitiatingMessage, SuccessfulOutcome, UnsuccessfulOutcome |
InitiatingMessage |
Procedure code + criticality + value (e.g., NGSetupRequest, InitialUEMessage) |
SuccessfulOutcome |
Response to initiating message (e.g., NGSetupResponse) |
UnsuccessfulOutcome |
Failure response (e.g., NGSetupFailure, HandoverPreparationFailure) |
AMF_UE_NGAP_ID / RAN_UE_NGAP_ID |
UE context identifiers (u64 / u32 newtypes) |
Cause |
Enum: RadioNetwork, Transport, NAS, Protocol, Misc sub-causes |
PLMNIdentity |
3-byte TBCD-encoded PLMN (MCC + MNC) |
S_NSSAI |
Network slice: SST (1 byte) + optional SD (3 bytes) |
TAI |
Tracking Area Identity: PLMN + TAC |
NAS_PDU |
Opaque NAS payload (decode with oxirush-nas) |
GNB_ID |
gNodeB identifier (22-32 bits) |
Criticality |
IE criticality: REJECT, IGNORE, or NOTIFY |
MissingIeError |
Error returned by extract_ngap_ies! when a required IE is absent |
Macro reference
| Macro | Purpose |
|---|---|
build_ngap!(Dir, Proc, Crit, Msg, IEs...) |
Build a complete NGAP_PDU |
build_ngap_ie!(Msg, Crit IE(val)) |
Build a single ProtocolIEs_Entry |
extract_ngap_ies!(var, Msg, fields...) |
Extract typed fields from a decoded message |
build_ngap! and build_ngap_ie! auto-derive IE IDs, procedure codes, and Id_ variant names. Raw values auto-convert to newtypes via .into(). extract_ngap_ies! accesses .protocol_i_es.0 internally — pass the message variable directly.
Examples
3GPP references
- TS 38.413 — NGAP specification (procedures, messages, IEs)
- ITU-T X.691 — ASN.1 Packed Encoding Rules (PER)
Contributing
Contributions welcome! See CONTRIBUTING.md for guidelines.
All commits must be signed off (git commit -s) per the Developer Certificate of Origin.
Developer Certificate of Origin (DCO)
By contributing to this project, you agree to the Developer Certificate of Origin (DCO). This means that you have the right to submit your contributions and you agree to license them according to the project's license.
All commits should be signed-off with git commit -s to indicate your agreement to the DCO.
License
Copyright 2026 Valentin D'Emmanuele
Licensed under the Apache License, Version 2.0. See LICENSE for details.