Expand description
§bacnet-encoding
BACnet tag, primitive, APDU and NPDU codecs for the Rusty BACnet workspace. Encoding a value produces bytes; it does not send a message or establish that a peer accepted it.
§Quickstart
The tag-sink API below has been available since 0.14.0:
[dependencies]
bacnet-encoding = "0.15"Write a Real tag header into caller-owned storage, then verify that a header which cannot fit leaves the existing bytes intact. This writes headers only; the four Real value bytes announced by the first header are not appended.
use bacnet_encoding::sink::SinkFull;
use bacnet_encoding::tags::{encode_opening_tag_to_sink, encode_tag_to_sink, TagClass};
fn main() -> Result<(), SinkFull> {
let mut storage = [0xA5; 2];
let mut tail = &mut storage[..];
assert_eq!(encode_tag_to_sink(&mut tail, 4, TagClass::Application, 4)?, 1);
let refused = encode_opening_tag_to_sink(&mut tail, 15).unwrap_err();
assert_eq!((refused.needed, refused.available), (2, 1));
assert_eq!(tail.len(), 1);
assert_eq!(storage, [0x44, 0xA5]);
Ok(())
}The tag-sink functions append one complete header or return SinkFull without
changing the sink. They do not validate every tag number or datatype-specific
length, and their atomic write guarantee does not span several encoder calls.
A variable-length value, such as a CharacterString with its header, goes out
through EncodeSink::write_parts, all of it or none. See
the sink design.
§Features and allocation
The crate has three profiles. With neither std nor alloc it builds without
an allocator (#1614), for firmware with no heap.
| Profile | Features | What it has |
|---|---|---|
| Hosted | std (default) | Everything; enables alloc and the dependencies’ standard-library support. Adds tracing for reserved NPDU control bits. |
no_std with a heap | alloc | Everything but the tracing. Firmware must supply a global allocator. |
| No allocator | neither | Tag decoding and the _to_sink encoders (tags, scalars, timestamps, strings, octet and bit strings), the primitive decoders and the borrowed views (primitives::CharacterStringRef, primitives::ApplicationValueRef), the tagged-field readers in constructed::tagged, and apdu::header, which reads and writes the header of an Unconfirmed-Request, an unsegmented Confirmed-Request or ComplexACK and an Error, and a whole Reject or Abort. The owned APDU and NPDU, segmentation, the other constructed codecs and every BytesMut encoder need alloc. |
heapless | Adds sink::EncodeSink for heapless::Vec<u8, N>, in any profile. |
EncodeSink also supports caller slices, and with alloc Vec<u8> and
bytes::BytesMut. Only the alloc profile has bytes in its graph.
For an alloc-only dependency build, replace the dependency block with:
[dependencies]
bacnet-encoding = { path = "../rusty-bacnet/crates/bacnet-encoding", default-features = false, features = ["alloc"] }For a build without an allocator, leave out features = ["alloc"]: the
quickstart runs unchanged with any of the three blocks on a host. With
alloc, firmware also needs a global allocator and a compatible bytes
configuration: on targets without atomic compare-and-swap, such as ARMv6-M,
enable bytes’s extra-platforms feature and select a portable-atomic
backend in the firmware. Without alloc there is no bytes, so no backend to
choose. CI builds each profile for ARMv6-M, ARMv7E-M and RISC-V
(scripts/ci/check-no-std.sh) but doesn’t run it there. Cargo features are
additive, so check whether another dependency enables alloc or std.
§API documentation
This README is included in the crate’s Rust documentation. The docs.rs profile
explicitly enables std and heapless, disables implicit defaults, and renders
only the default x86_64-unknown-linux-gnu target. That makes the optional sink
adapter visible through its actual feature gate; it does not qualify a
bare-metal target.
Modules§
- apdu
- APDU encoding and decoding per ASHRAE 135-2020 Clause 20.1.
- constructed
- Full ASN.1 framing codecs for constructed Clause-21 types whose property values are CHOICE/SEQUENCE productions — context-tagged framing per ASHRAE 135-2020 Clause 20.2.1.5/20.2.1.6.
- npdu
- The owned NPDU (ASHRAE 135-2020 Clause 6) and its codec.
- primitives
- Application-tagged primitive encode/decode per ASHRAE 135-2020 Clause 20.2.
- segmentation
- Segmentation: split and reassemble large APDU payloads.
- sink
- Append-only output for the sink-based encoders.
- tags
- BACnet ASN.1 tag encoding and decoding per ASHRAE 135-2020 Clause 20.2.1.