Adds DataMessage.CloneCodec and DataMessage.SnapshotForRelay (an opt-in,
relay-optimized snapshot clone), and fixes a data race in secs2.ListItem.Clone
exposed on the concurrent fan-out (multi-handler / broadcast) path — closing the
related ASCIIItem aliasing hazard and a stale serialization-cache bug. Also
decodes JIS8 and localized-string items, which previously failed to decode.
Added
hsms:DataMessage.CloneCodec— returns an independent deep copy of the
message typed only as theencoding.BinaryMarshaler/BinaryUnmarshalerpair.
This lets external code obtain a fan-out-safe deep copy through a capability
interface it declares itself, without importing this package or depending on
the concrete*DataMessagetype. Thin wrapper overClone.hsms:DataMessage.SnapshotForRelay— opt-in, relay-optimized snapshot
that serializes the message once and serves those bytes fromToByteswithout
re-encoding, decoding the item structure lazily only if a structural method
(e.g.Item,ToDataMessage) is called on the result. For the
serialize-and-forward (relay / broadcast / shadow) path it is markedly cheaper
thanClone(measured ~4.6× faster for a single large-leaf payload; ~110–200×
faster for multi-item / nested lists; 2–5 allocations vs 12–2024). It is a
trade-off, not a free win: if the consumer accesses items,SnapshotForRelay
is slower thanClone(serialize-at-clone plus lazy-decode-at-access), so
Cloneremains the right choice for structural consumers (including the
in-process handler fan-out path).Clone/CloneCodecare unchanged
(structural deep copy).Item()on the returned message yields a
lazily-decoded item — use thesecs2.Iteminterface, not concrete-type
assertions, to remain compatible with future implementations.
Fixed
hsms: decode JIS8 and localized-string items.DecodeSECS2Item/
DecodeHSMSMessagepreviously returned "invalid format" for JIS8 (0o21) and
localized-string (0o22) payloads; both are now decoded correctly.secs2:ListItem.Clonenow performs a recursive deep copy. Previously it
shared child items with the original, which caused a data race when a cloned
message and its source were serialized concurrently (the fan-out / multi-handler
path). Clones are now fully independent.secs2:ASCIIItem.SetValuesno longer retains a caller-supplied[]byte
(it now copies the input). Combined with the deepListItem.Clone, ASCII
leaves can safely share their now-owned/immutable backing, so common payloads
(including large ASCII recipes built from strings) still clone without copying
the data.secs2:SetValuesnow invalidates the cached serialization. Calling
SetValueson an item that had already been serialized viaToBytesleft the
stalerawBytescache in place, so the nextToBytesreturned the previous
value's bytes. AffectsASCIIItem,BinaryItem,BooleanItem, andListItem.