bacnet-bip-codec 0.13.0

Portable no-std BACnet/IP and BACnet/IPv6 (Annexes J and U) BVLL codec
Documentation
# bacnet-bip-codec

The BVLL codec of [rusty-bacnet](https://github.com/jscott3201/rusty-bacnet):
the wire format of BACnet/IP (Annex J of ASHRAE 135) at the crate root and
of BACnet/IPv6 (Annex U) in its `ipv6` module, and nothing above it.
Sockets, BBMD forwarding and foreign-device registration belong to the
layer that uses it, such as `bacnet-bip-core`.

- `#![no_std]`, no allocator and no dependencies in the default build.
- The twelve B/IP messages and the twelve B/IPv6 ones, as `Bvll` and
  `Bvll6` values that borrow their NPDU or table from the datagram.
- Decoding is strict about shape (BVLC type, a Length field equal to the
  datagram, a payload the function's layout allows) and lenient about
  values; encoding refuses what the Length field can't state and a
  BVLC-Result with an undefined code.
- `BvlcFunction`, `BvlcResultCode` and their B/IPv6 counterparts are open
  sets: a constant for each code the standard defines, and `from_raw` for
  any other, so a decoder can report a code it doesn't know.
- BDT and FDT entries, read through iterators straight from the wire.
- A B/IP address is a plain `SocketAddrV4`, since all of it travels; a
  B/IPv6 address is a `Bip6Address`, which keeps the 18 octets that travel
  and none of a `SocketAddrV6`'s flow label or scope ID.

## Features

None is on by default, and none needs `std`. Each adds a `BvllSink`, which
both encoders write to:

- `alloc`: for `Vec<u8>`.
- `bytes`: for `bytes::BytesMut`; implies `alloc`.
- `heapless`: for `heapless::Vec<u8, N>`.

## Example

```rust
use core::net::{Ipv4Addr, SocketAddrV4};
use bacnet_bip_codec::{decode, BvlcFunction, Bvll, BvllFrame};

// Encode an Original-Broadcast-NPDU into caller storage.
let npdu = [0x01, 0x20, 0xFF, 0xFF, 0x00, 0xFF];
let mut wire = [0u8; 64];
let length = Bvll::OriginalBroadcastNpdu(&npdu).encode_into(&mut wire).unwrap();
assert_eq!(wire[..4], [0x81, 0x0B, 0x00, 0x0A]);
assert_eq!(decode(&wire[..length]), Ok(Bvll::OriginalBroadcastNpdu(&npdu)));

// A Forwarded-NPDU carries its originator's address.
let wire = [0x81, 0x04, 0x00, 0x0C, 192, 168, 1, 20, 0xBA, 0xC0, 0x01, 0x00];
let origin = SocketAddrV4::new(Ipv4Addr::new(192, 168, 1, 20), 47808);
assert_eq!(decode(&wire).unwrap().origin(), Some(origin));

// A function the standard doesn't define still has a frame, so a
// receiver can see what arrived before refusing it.
let frame = BvllFrame::decode(&[0x81, 0x0C, 0x00, 0x04]).unwrap();
assert_eq!(frame.function, BvlcFunction::from_raw(0x0C));
assert!(!frame.function.is_defined());
assert!(frame.message().is_err());
```

## License

MIT