Crates.io | nsap-address |
lib.rs | nsap-address |
version | 1.0.0 |
created_at | 2025-08-29 10:27:48.538925+00 |
updated_at | 2025-08-29 10:27:48.538925+00 |
description | ITU-T Rec. X.213 NSAP address parsing, printing, etc. |
homepage | |
repository | https://github.com/JonathanWilbur/asn1.rs/tree/master/nsap-address |
max_upload_size | |
id | 1815671 |
size | 136,085 |
ITU-T Recommendation X.213 Network Service Access Point (NSAP) address parsing and printing. These address types were designed for use in OSI networking, but have full compatibility with IP networking. Since OSI networking is ancient history, this library prioritizes the IP networking aspects, but everything should be supported.
This module decodes and encodes a Network Service Access Point (NSAP) to and from the "preferred binary encoding" described in Annex A, Section A.5.3 of ITU-T Recommendation X.213 (2001).
In addition to this, it displays and decodes NSAPs to and from human-readable strings according to the procedures defined in IETF RFC 1278, drawing on additional information found in IETF RFC 1277.
There are some deviations to the above, however. Since the human-friendly string syntax was defined, new AFIs were added, including one for directly representing IP addresses and another for representing URLs. As such this library extends the specification, but should be completely backwards compatible with it.
You should not expect an NSAP decoded from a string to encode back into the same exact string. You should not expect an NSAP decoded from bytes to encode back into the same exact bytes. You should not expect all NSAP syntaxes to be recognized everywhere; your application and dependencies should handle unrecognized NSAP syntaxes gracefully.
This crate is no_std
and supports almost everything with no alloc
as well;
the only thing alloc
gives you is better URL encoding and decoding, per
ITU-T Recommendation X.519. Only extremely short URLs are supported without
alloc
.
An NSAP address is represented using X213NetworkAddress
. You can construct
this using several methods:
X213NetworkAddress::from_vec()
X213NetworkAddress::from_vec_unchecked()
X213NetworkAddress::from_slice()
X213NetworkAddress::from_slice_unchecked()
X213NetworkAddress::from_ip()
X213NetworkAddress::from_ipv4()
X213NetworkAddress::from_ipv6()
X213NetworkAddress::from_itot_url()
X213NetworkAddress::from_non_osi_url()
X213NetworkAddress::from_itot_socket_addr()
X213NetworkAddress::try_from()
(for Vec<u8>
or &[u8]
)X213NetworkAddress::from_str()
X213NetworkAddress::from()
(for &IpAddr
, &Ipv4Addr
, or &Ipv6Addr
)The X213NetworkAddress
type implements Display
, which prints the NSAP
address according to IETF RFC 1278.
If you need to pass NSAP addresses between heterogeneous systems, consider using
to_ns_string
or fmt_as_ns_string()
instead. This will always encode the
NSAP address using the NS+
syntax like: NS+A433BB93C1
. These are not
human-friendly, but they are really easy to parse and completely unambiguous.
There is no way in this crate to compare two NSAP addresses. The rationale for
this is documented along with X213NetworkAddress
, but if you want to compare
the addresses byte-for-byte, you can use get_octets()
, like so:
assert_eq!(addr1.get_octets(), addr2.get_octets());
This crate also supports several functions for working specifically with IP networking, above and beyond those already named, which are:
X213NetworkAddress::get_url()
X213NetworkAddress::get_ip()
X213NetworkAddress::get_rfc1277_socket()
In a TCP/IP only environment, you'll likely want to invoke all three of these methods until one of them returns a result, then perform the appropriate connection setup.
Here is an example usage of this crate:
extern crate alloc;
use alloc::vec::Vec;
use nsap_address::X213NetworkAddress;
use nsap_address::AFI_F69_DEC_LEADING_ZERO;
use core::net::{IpAddr, Ipv4Addr};
use core::str::FromStr;
let addrstr = "TELEX+00728722+RFC-1006+03+255.0.0.2+65535+2";
let addr = X213NetworkAddress::from_str(addrstr).unwrap();
let (_, sock, _) = addr.get_rfc1277_socket().unwrap();
assert_eq!(sock.ip(), &Ipv4Addr::new(255, 0, 0, 2));
assert_eq!(sock.port(), 65535);
let idi_digits: Vec<u8> = addr.idi_digits().unwrap().collect();
assert_eq!(idi_digits.as_slice(), &[ 0, 0, 7, 2, 8, 7, 2, 2 ]);
assert_eq!(addr.get_octets(), &[
AFI_F69_DEC_LEADING_ZERO, // AFI
0x00, 0x72, 0x87, 0x22, // Telex 00728722
0x03, // Network prefix (0x03 = Internet)
0x25, 0x50, 0x00, 0x00, 0x00, 0x02, // IP address
0x65, 0x53, 0x50, 0x00, 0x02, // port + tset
]);
let ns_string = addr.to_ns_string();
assert_eq!(ns_string.as_str(), "NS+5400728722032550000000026553500002");
alloc
: heap allocation, which enables URL encoding and decoding for URLsx25
: Parsing of X.25 DSP strings, per
IETF RFC 1278ecma117
: Parsing of ECMA 177 DSP strings, per
IETF RFC 1278nonstd
: Parsing for non-standard syntaxes: those defined by this crate, but
not in any standard, which are the IP4
, IP6
, URL
, ICP
, and IND
.nonstddisplay
: implementation of std::fmt::Display
for the above
non-standard syntaxes. This is a separate feature flag so that, if you have an
application that passes NSAPs as strings, you can ensure that you only use
standardized syntaxes, while still being able to parse the non-standard ones.alloc
is the only one enabled by default. Keeping x25
off is a good idea
unless, somehow, you are still using or working with X.25 networks. The ECMA 117
syntax was not widely used, so you are unlikely to encounter that as well; for
this reason, you might want to keep ecma117
off. nonstd
and nonstddisplay
will be big quality-of-life improvements for you in almost all cases.
No code, tests, or documentation was produced by AI or an LLM of any kind,
except for two small internal functions in utils
, which were reviewed by the
crate's author.
ICP
and IND
AFIs recognized in the <afi>-<idi>-<dsp>
syntaxIP4
, IP6
, and URL
schemes supported in FromStr
and Display
likely
/ unlikely
branch prediction macros