Skip to main content

Crate bacnet_encoding

Crate bacnet_encoding 

Source
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.

ProfileFeaturesWhat it has
Hostedstd (default)Everything; enables alloc and the dependencies’ standard-library support. Adds tracing for reserved NPDU control bits.
no_std with a heapallocEverything but the tracing. Firmware must supply a global allocator.
No allocatorneitherTag 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.
heaplessAdds 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.