Expand description
Decode helpers for tagged fields, shared by the constructed codecs, the
formal Error bodies in apdu/ and the service parameters bacnet-services
decodes.
Each helper reads one field at an offset and returns what it read with the
offset just past it. Each takes the what label its codec passes (the
production, sometimes narrowed to one alternative or member), so every
codec words a refusal the same way:
- a tag of the wrong number, class or form:
{what}: expected context tag [n],{what}: expected opening tag [n],{what}: expected closing tag [n]or{what}: expected application-tagged Unsigned, reported at the offending tag; - a fixed-size primitive of the wrong length:
{what}: [n] REAL has 5 contents octets, expected 4; - an Unsigned or ENUMERATED too large for its field:
{what}: [n] value 70000 exceeds u16, or{what}: Unsigned exceeds u16for an application-tagged one; - bytes left after a value that must fill its input:
{what}: 2 trailing byte(s).
One error-kind rule holds across the crate’s decoders (#1333):
- Contents that run past the end of the data fail with
Error::BufferTooShort, wherever the member stands: at the top level, or inside a constructed frame, wheretags::extract_context_valuefinds it whiledecode_ctx_constructedordecode_framed_valueextracts the frame. - A fixed-size member has its length checked against its header before
its contents are read, so a wrong length is
Error::Decodingeven when the data also stops early. That covers the context-tagged ones (an object identifier, REAL, BOOLEAN, or any type read withdecode_ctx_fixed), the application-tagged ones read withdecode_app_fixedordecode_app_object_id, and the REAL, Double, Date, Time and object identifier thatprimitives::decode_application_valuereads. - Every other refusal is
Error::Decoding, including a tag header cut short, whichtags::decode_tagrefuses, and a frame whose closing tag never comes.
An Error::Decoding carries the DecodingKind of the fault, which a
responder turns into a Reject reason (#1446):
DecodingKind::Missing: the data ends where a required member, a tag header’s remaining octets or a frame’s closing tag is due, or the tag found there shows the member was left out (seemisplaced_kind);DecodingKind::InvalidTag: any other tag that doesn’t fit where it stands, a malformed tag header, or nesting deeper than the walk takes;DecodingKind::Trailing: octets after the last member of a value that must fill its input (expect_end) or close its frame (expect_closing), unless they open with a closing tag or a header that doesn’t decode, which isDecodingKind::InvalidTag;DecodingKind::OutOfRange: an Unsigned or ENUMERATED too large for its field;DecodingKind::Overflow: more items than a framed value takes, or a tag length past its sanity bound;DecodingKind::InvalidEncoding: contents whose encoding isn’t valid for their datatype, such as a fixed-size member of the wrong length, the kindError::decodingmakes.
The helpers another crate needs are public: the peeks for an optional
member, a frame’s opening and closing tags and its body, the context
readers for contents, fixed-size contents, Unsigned or ENUMERATED values,
REAL, BOOLEAN, BIT STRING, OCTET STRING, CharacterString and object
identifiers, the optional-member wrapper, the application readers, the
trailing-data check, and the kinds a misplaced tag is (misplaced_kind,
misplaced_tag, unclosed_kind). The rest stay private to this
crate.
use bacnet_encoding::constructed::tagged::{decode_ctx_unsigned, expect_end, next_is_context};
use bacnet_types::error::Error;
// A required `[0]` Unsigned 7 and no optional `[1]` after it.
let data = [0x09, 0x07];
let (value, end) = decode_ctx_unsigned::<u32>(&data, 0, 0, "Example")?;
assert_eq!((value, end), (7, 2));
assert!(!next_is_context(&data, end, 1)?);
expect_end(&data, end, end, "Example")?;
// The same member announcing two contents octets but holding one.
let cut = decode_ctx_unsigned::<u32>(&[0x0A, 0x07], 0, 0, "Example");
assert!(matches!(cut, Err(Error::BufferTooShort { need: 3, have: 2 })));Traits§
- Unsigned
Width - An unsigned integer type a decoded Unsigned or ENUMERATED is narrowed to:
u8,u16,u32oru64. Sealed, so no other type implements it.
Functions§
- decode_
app_ bit_ string - Decode one application-tagged BIT STRING (
SEQUENCE OF BIT STRINGitem). - decode_
app_ character_ string - Decode one application-tagged CharacterString.
- decode_
app_ enumerated - Decode one application-tagged ENUMERATED (a
SEQUENCE OFitem, or an error class or code) that fitsT. Leading zero octets are accepted. - decode_
app_ fixed - Require an application tag
numberatoffsetholding exactlyoctetscontents octets; return them and the offset past them. As withdecode_ctx_fixed, a header announcing any other length isError::Decodingeven when the data also stops early. - decode_
app_ object_ id - Require an application-tagged object identifier, four contents octets,
at
offset. - decode_
app_ primitive - Require an application tag
number(one oftags::app_tag) atoffset; return its contents and the offset past them. - decode_
app_ unsigned - Decode one application-tagged Unsigned that fits
T. Leading zero octets are accepted. - decode_
canonical_ unsigned - The value of Unsigned or ENUMERATED contents in their shortest encoding:
one to eight octets, and no leading zero octet unless it is the only one.
Errors report
offset, the field’s tag. - decode_
ctx_ bit_ string - Require a primitive context tag
tagatoffsetholding a BIT STRING; returns its unused-bit count and data octets. - decode_
ctx_ boolean - Require a primitive context tag
tagatoffsetholding a BOOLEAN: one contents octet, 0 or 1 (Clause 20.2.3). - decode_
ctx_ canonical_ unsigned decode_ctx_unsignedfor a codec that must re-encode what it read octet for octet: the contents must also be the shortest encoding (seedecode_canonical_unsigned).- decode_
ctx_ character_ string - Require a primitive context tag
tagatoffsetholding a CharacterString. - decode_
ctx_ constructed - Require constructed context tag
tagatoffset; return its body (the octets between its opening and closing tags, with nested frames balanced) and the offset past its closing tag. - decode_
ctx_ fixed - Require a primitive context tag
tagatoffsetholding exactlyoctetscontents octets of the typekindnames ("Time", say, for the error); return those contents and the offset past them. A header announcing any other length isError::Decodingeven when the data also stops early. - decode_
ctx_ object_ id - Require a primitive context tag
tagatoffsetholding an object identifier, which is always four octets. - decode_
ctx_ octet_ string - Require a primitive context tag
tagatoffsetholding an OCTET STRING; returns a copy of its octets. - decode_
ctx_ primitive - Require a primitive context tag
tagatoffset; return its contents and the offset past them. - decode_
ctx_ real - Require a primitive context tag
tagatoffsetholding a REAL. - decode_
ctx_ unsigned - Require a primitive context tag
tagatoffsetholding an Unsigned that fitsT. An ENUMERATED’s contents are encoded the same way, so this reads those too. Leading zero octets are accepted, asprimitives::decode_unsignedaccepts them. - decode_
optional_ ctx - Read the optional member under primitive context tag
tagwithdecodewhen that tag comes next; otherwiseNonewith the offset unchanged. Whatdecodereturns may borrow fromdata, sodecode_ctx_primitiveyields the member’s contents. - expect_
closing - Require a closing context tag
tagatoffset; return the offset past it. Any other tag there is of the kindunclosed_kindgives. - expect_
end - Require a value that stopped at
endto have used all ofdata. - expect_
opening - Require an opening context tag
tagatoffset; return the offset of its content. - misplaced_
kind - The kind of fault the tag
found, atatindata, is where a required member is due. - misplaced_
tag - The error for the tag
found, atoffsetindata, where a required member is due, of the kindmisplaced_kindgives. - next_
is_ application - Whether an application tag
number(one oftags::app_tag) starts atoffset;falseat the end of the data, so an optional application-tagged member may be the last one. A malformed tag there is an error. - next_
is_ context - Whether a primitive context tag
tagstarts atoffset;falseat the end of the data, so an optional member may be the last one. A malformed tag there is an error. - next_
is_ opening - Whether an opening context tag
tagstarts atoffset;falseat the end of the data. A malformed tag there is an error. - unclosed_
kind - The kind of fault the tag
foundis where a frame’s closing tag is due: another closing tag isDecodingKind::InvalidTag; any other tag is a member the frame holds beyond its last one,DecodingKind::Trailing.