[M5] mxaccess-asb: F25 step 3 — response decoders + Read request body

Foundation for response decoding. Adds:

* `contracts::ItemStatus` — ports `AsbContracts.cs:639-722`. Wire
  layout matches `WriteToStream` exactly: Item (ItemIdentity binary)
  → Status (AsbStatus binary, from F24) → ErrorCode (u16) →
  ErrorCodeSpecified (u8 bool). Note this is NOT the DataMember
  declaration order — the binary serialiser hand-picks Item-first.

* `encode_item_status_array` / `decode_item_status_array` — same
  4-byte int32 count + per-element WriteToStream pattern as the
  ItemIdentity array codec.

* `operations::collect_asbidata_payloads(tokens, field_name)` — walks
  an NBFX token stream and pulls out `<{field}><ASBIData>{Bytes}
  </ASBIData></{field}>` payload bytes. Returns Vec<Vec<u8>> because
  some response shapes (ReadResponse) carry multiple ASBIData
  payloads (Status + Values).

* `decode_register_items_response` / `decode_unregister_items_response`
  — parse SOAP body NBFX tokens into typed RegisterItemsResponse /
  UnregisterItemsResponse. The optional ItemCapabilities array (XML-
  serialised, not binary) is recorded as a presence flag for now;
  decoding the individual ItemRegistration records is a follow-up.

* `build_read_request_body(items)` — simplest unary IASBIDataV2
  request, just `<ReadRequest xmlns="..."><Items><ASBIData>...
  </ASBIData></Items></ReadRequest>`.

* `OperationError` — typed error for response-decode failures
  (`MissingField { field }` and codec wraps).

9 new tests: ItemStatus round-trip (default + with id + with status
payload), ItemStatus array round-trip, RegisterItemsResponse
round-trip via synthetic body, ItemCapabilities presence detection,
UnregisterItemsResponse round-trip, multi-payload extraction (ReadResponse-
shape Status + Values), Read body shape correctness, MissingField
error when Status is absent.

Stubbed for next F25 iteration: Write / PublishWriteComplete /
CreateSubscription / AddMonitoredItems / DeleteMonitoredItems /
Publish builders, ReadResponse + WriteResponse decoders (need
WriteValue / RuntimeValue contract codecs), and the AsbClient
network loop.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Joseph Doherty
2026-05-05 11:32:36 -04:00
parent a2b8989cbf
commit c4bf0a0a04
4 changed files with 429 additions and 6 deletions
+7 -3
View File
@@ -14,11 +14,15 @@ pub mod envelope;
pub mod operations;
pub use contracts::{
ItemIdentity, ItemIdentityType, ItemReferenceType, decode_item_identity_array,
encode_item_identity_array,
ItemIdentity, ItemIdentityType, ItemReferenceType, ItemStatus, decode_item_identity_array,
decode_item_status_array, encode_item_identity_array, encode_item_status_array,
};
pub use envelope::{
ConnectionValidator, DecodedEnvelope, EnvelopeError, SoapEnvelope, actions, decode_envelope,
encode_envelope,
};
pub use operations::{build_register_items_request_body, build_unregister_items_request_body};
pub use operations::{
OperationError, RegisterItemsResponse, UnregisterItemsResponse, build_read_request_body,
build_register_items_request_body, build_unregister_items_request_body,
collect_asbidata_payloads, decode_register_items_response, decode_unregister_items_response,
};