diff --git a/rust/crates/mxaccess-asb/src/operations.rs b/rust/crates/mxaccess-asb/src/operations.rs index cdb41e6..cba9fb2 100644 --- a/rust/crates/mxaccess-asb/src/operations.rs +++ b/rust/crates/mxaccess-asb/src/operations.rs @@ -1157,8 +1157,30 @@ pub fn collect_asbidata_payloads(tokens: &[NbfxToken]) -> Vec> { ) { inner += 1; } - if let Some(NbfxToken::Text(NbfxText::Bytes(payload))) = tokens.get(inner) { - out.push(payload.clone()); + // CONCATENATE all consecutive `Bytes` text records. + // .NET's `XmlBinaryWriter.WriteBase64` chunks the byte + // array into multiple NBFX `Bytes8/16/32` records when + // the total exceeds the per-record budget — captured + // live response showed an ASBIData payload split into + // a Bytes8(78) + Bytes8WithEndElement(1) pair, total + // 79 bytes. Earlier we only returned the first chunk + // and the consumer hit a `ShortRead` decoding the + // truncated ItemStatus. The decoder collapses adjacent + // Bytes-followed-by-Bytes pairs into a single text + // token, but a `Bytes`-then-`EndElement` (from the + // `WithEndElement` variant) leaves a sequence of + // `Bytes` tokens we walk here. + let mut combined: Option> = None; + while let Some(NbfxToken::Text(NbfxText::Bytes(payload))) = tokens.get(inner) + { + match combined.as_mut() { + Some(buf) => buf.extend_from_slice(payload), + None => combined = Some(payload.clone()), + } + inner += 1; + } + if let Some(buf) = combined { + out.push(buf); } } }