Skip to main content

oxirush_utils/
lib.rs

1/*
2   OxiRush
3   Copyright 2025-2026 Valentin D'Emmanuele
4
5   Licensed under the Apache License, Version 2.0 (the "License");
6   you may not use this file except in compliance with the License.
7   You may obtain a copy of the License at
8
9   http://www.apache.org/licenses/LICENSE-2.0
10
11   Unless required by applicable law or agreed to in writing, software
12   distributed under the License is distributed on an "AS IS" BASIS,
13   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   See the License for the specific language governing permissions and
15   limitations under the License.
16*/
17
18//! What the OxiRush crates share: the identities of 3GPP networks as values, and one
19//! tree with paths for the messages of every family. `no_std`, without a dependency
20//! unless a feature asks for one.
21//!
22//! ```rust
23//! use oxirush_utils::identity::{Guti5g, Plmn};
24//!
25//! fn main() -> Result<(), Box<dyn std::error::Error>> {
26//!     let plmn: Plmn = "310-410".parse()?;
27//!     let guti = Guti5g::new(plmn, 0xca, 0x3fe, 0x01, 0xdead_beef)?;
28//!
29//!     // The three octets of a PLMN in a NAS message, and in an NGAP or S1AP message
30//!     println!("{plmn}: {:02x?} in NAS, {:02x?} in NGAP", plmn.to_nas_octets(), plmn.to_ap_octets());
31//!
32//!     // A 5G-GUTI as text, and as a 5GS mobile identity
33//!     println!("{guti}: {:02x?}", guti.to_nas_octets());
34//!     Ok(())
35//! }
36//! ```
37//!
38//! ```text
39//! 310-410: [13, 00, 14] in NAS, [13, 40, 01] in NGAP
40//! 5g-guti-310410caff81deadbeef: [f2, 13, 00, 14, ca, ff, 81, de, ad, be, ef]
41//! ```
42//!
43//! # Tasks
44//!
45//! The [README](https://github.com/linouxis9/oxirush-utils#readme) has an example of
46//! each, with what it prints, except the rules of a family of messages: the
47//! documentation of [`tree::Family`] has theirs.
48//!
49//! | Task | Items |
50//! |------|-------|
51//! | An identity through its forms | [`Imsi`](identity::Imsi), [`Plmn`](identity::Plmn), [`ImsiSuci`](identity::ImsiSuci), [`Supi`](identity::Supi), [`Guti5g`](identity::Guti5g), [`STmsi5g`](identity::STmsi5g) |
52//! | IMEI, IMEISV, and the identities of EPS | [`Imei`](identity::Imei), [`Imeisv`](identity::Imeisv), [`GutiEps`](identity::GutiEps), [`Tai5gs`](identity::Tai5gs), [`TaiEps`](identity::TaiEps) |
53//! | The SUCI in the form of a NAI | [`NaiSuci`](identity::NaiSuci), [`nai::check_realm`](identity::nai::check_realm) |
54//! | What other implementations send | [`Imeisv::from_nas_octets_tolerant`](identity::Imeisv::from_nas_octets_tolerant), [`Fault`](identity::Fault) |
55//! | A type as a tree | [`tree::Tree`], [`tree!`], [`tree::to_value`], [`tree::from_value`] |
56//! | Paths | [`tree::select`], [`tree::paths`], [`tree::set`], [`tree::insert`], [`tree::remove`] |
57//! | The rules of a family of messages | [`tree::Family`], [`tree::select_in`], [`tree::written_as`] |
58//! | Any format of serde | [`impl_serde!`] |
59//!
60// Without its feature an item of the tasks is plain text: the links are checked in the
61// build of every feature, which docs.rs makes.
62#![cfg_attr(not(feature = "serde"), allow(rustdoc::broken_intra_doc_links))]
63//! # Modules
64//!
65//! | Module | Has | Feature |
66//! |--------|-----|---------|
67//! | [`identity`] | The PLMN with its two codings, TBCD digits, IMSI, IMEI, IMEISV, the SUPI with its type, the SUCI of an IMSI and the SUCI in the form of a NAI with the grammar of a NAI, the GUTI and the S-TMSI of 5GS and of EPS, the tracking area identities, the types of identity | none |
68// A module that a feature turns on is a link when the build has it.
69#![cfg_attr(
70    feature = "tree",
71    doc = "| [`tree`](mod@tree) | The tree of a message as a JSON value that keeps the order of its members, and `tree!` that writes one: the forms of the plain values, the writer and the reader of members, and paths with `select`, `paths`, `set`, `remove`, `insert` | `tree` |"
72)]
73#![cfg_attr(
74    not(feature = "tree"),
75    doc = "| `tree` | The tree of a message as a JSON value that keeps the order of its members, and `tree!` that writes one: the forms of the plain values, the writer and the reader of members, and paths with `select`, `paths`, `set`, `remove`, `insert` | `tree` |"
76)]
77#![cfg_attr(
78    feature = "serde",
79    doc = "| [`tree::serde`] | `Serialize` and `Deserialize` for a type through its tree | `serde` |"
80)]
81#![cfg_attr(
82    not(feature = "serde"),
83    doc = "| `tree::serde` | `Serialize` and `Deserialize` for a type through its tree | `serde` |"
84)]
85//!
86//! The crate is `no_std` with `alloc`, has no dependency without a feature, and no
87//! `unsafe`. With the feature `idna`, the realm and the username of a NAI are also
88//! checked as internationalized names (see [`identity::nai::check_realm`]).
89//!
90//! A tree keeps the order of the specification by itself: the crate turns on no
91//! feature of `serde_json` that orders a map, and the JSON of a program that depends on
92//! it keeps the order that the program chose.
93//!
94//! # The OxiRush family
95//!
96//! - [oxirush-utils](https://docs.rs/oxirush-utils): the 3GPP identities, and the JSON tree with its paths that the others share.
97//! - [oxirush-aper](https://docs.rs/oxirush-aper): aligned PER, the runtime of the NGAP and S1AP codecs.
98//! - [oxirush-nas](https://docs.rs/oxirush-nas): the NAS messages of 5GS and EPS.
99//! - [oxirush-security](https://docs.rs/oxirush-security): NAS security, AKA and the derivation of keys.
100//! - [oxirush-ngap](https://docs.rs/oxirush-ngap): NGAP, between a gNB and an AMF.
101//! - [oxirush-s1ap](https://docs.rs/oxirush-s1ap): S1AP, between an eNB and an MME.
102//! - [oxirush-gtp-u](https://docs.rs/oxirush-gtp-u): GTP-U tunnels, with a test UPF.
103//! - [oxirush-sctp](https://docs.rs/oxirush-sctp): SCTP sockets, which carry NGAP and S1AP.
104
105#![no_std]
106#![forbid(unsafe_code)]
107#![warn(missing_docs)]
108#![cfg_attr(docsrs, feature(doc_cfg))]
109
110#[cfg(feature = "alloc")]
111extern crate alloc;
112
113pub mod identity;
114#[cfg(feature = "tree")]
115#[cfg_attr(docsrs, doc(cfg(feature = "tree")))]
116pub mod tree;
117
118/// The blocks of the README, which are compiled and run with the documentation tests.
119#[cfg(all(doctest, feature = "serde"))]
120#[doc = include_str!("../README.md")]
121struct _Readme;