[M2] mxaccess-rpc: OXID + RemQI body codecs (wave 2)
Lands M2 wave 2 — two pure-Rust body-codec modules under crates/mxaccess-rpc, plus a small inline ORPC framing port and a crate-level type consolidation. Resolves F7+F8 from wave 1. New modules - guid.rs (4 tests) — hoisted from objref::Guid; shared by all of mxaccess-rpc. Resolves F7. - error.rs — hoisted RpcError union (ShortRead, UnexpectedPacketType, UnknownPacketType, InvalidFragmentLength, TruncatedBindBody, InvalidAuthTrailer, MissingAuthValue, Decode). Resolves F8. - orpc.rs (8 tests) — port of OrpcStructures.cs:1-141. ComVersion, OrpcThis (32-byte header), OrpcThat (8-byte header), MInterfacePointer (length-prefixed OBJREF), StdObjRef (40 bytes). - object_exporter.rs (~530 LoC, 20 tests) — port of ObjectExporterMessages.cs:1-141. IObjectExporter IID, opnums, ResolveOxid request encoder + ResolveOxidResult/Failure parsers. Owned-string protocol labels cleaned up via Cow upgrade rather than Box::leak (ComDualStringEntry::protocol is now Cow<'static, str>). - rem_unknown.rs (~340 LoC, 11 tests) — port of RemUnknownMessages.cs. IRemUnknown IID, RemQueryInterface request/response, RemQiResult. 4-byte NDR pad in REMQIRESULT preserved as pad_after_hresult per CLAUDE.md unknown-bytes rule. Test count delta: 277 -> 319 (+42; codec 215 unchanged, mxaccess-rpc 60 -> 102, codec parity 2 unchanged). Open followups touched: F7 + F8 resolved; F9, F10, F11 added. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
//! Crate-level RPC error type.
|
||||
//!
|
||||
//! Hoisted from per-module enums in M2 wave 2 — see `design/followups.md` F8.
|
||||
//! Every parser/encoder in `mxaccess-rpc` returns this single shared
|
||||
//! [`RpcError`] so consumers can match on one error surface across PDU
|
||||
//! decode, OBJREF parse, ORPC `ResolveOxid` body decode, and
|
||||
//! `IRemUnknown::RemQueryInterface` response decode.
|
||||
//!
|
||||
//! Variants here are the union of what M1 wave 1 defined locally in
|
||||
//! `pdu.rs` and `objref.rs` (`design/followups.md` F8 source list),
|
||||
//! plus a generic [`RpcError::Decode`] for one-off conditions wave 2's
|
||||
//! ORPC parsers need (referent-id mismatches, conformant-array max-count
|
||||
//! underflow, NDR alignment overrun) without growing the enum further.
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
/// Errors raised by any codec under `mxaccess-rpc`.
|
||||
#[derive(Debug, Error, PartialEq, Eq)]
|
||||
#[non_exhaustive]
|
||||
pub enum RpcError {
|
||||
/// Buffer was shorter than required to decode the type.
|
||||
#[error("short read: expected {expected} bytes, got {actual}")]
|
||||
ShortRead { expected: usize, actual: usize },
|
||||
|
||||
/// Packet type byte at offset 2 (`DceRpcPdu.cs:52`) did not match the
|
||||
/// expected `DceRpcPacketType` for the parser invoked.
|
||||
#[error("unexpected packet type {actual}, expected {expected}")]
|
||||
UnexpectedPacketType { expected: u8, actual: u8 },
|
||||
|
||||
/// Packet type byte was not a known [`crate::pdu::PacketType`] value.
|
||||
#[error("unknown packet type byte {0}")]
|
||||
UnknownPacketType(u8),
|
||||
|
||||
/// `header.frag_length` is inconsistent with the supplied buffer or
|
||||
/// `auth_length` (`DceRpcPdu.cs:94,150,188,226,101-104,156-159,195-198`).
|
||||
#[error(
|
||||
"fragment length {frag_length} inconsistent with buffer length {buffer_len} \
|
||||
(auth_length={auth_length})"
|
||||
)]
|
||||
InvalidFragmentLength {
|
||||
frag_length: usize,
|
||||
buffer_len: usize,
|
||||
auth_length: usize,
|
||||
},
|
||||
|
||||
/// A bind PDU's per-context list ran past `frag_length`
|
||||
/// (`DceRpcPdu.cs:237`) or a syntax identifier was truncated
|
||||
/// (`DceRpcPdu.cs:354`).
|
||||
#[error("truncated bind body at offset {offset}; need {need} bytes, frag_length={frag_length}")]
|
||||
TruncatedBindBody {
|
||||
offset: usize,
|
||||
need: usize,
|
||||
frag_length: usize,
|
||||
},
|
||||
|
||||
/// Auth-trailer offset is below the 16-byte header
|
||||
/// (`DceRpcPdu.cs:341-345`).
|
||||
#[error("invalid auth trailer offset {offset}")]
|
||||
InvalidAuthTrailer { offset: usize },
|
||||
|
||||
/// Tried to extract an auth value from a PDU whose `auth_length` is 0
|
||||
/// (`DceRpcPdu.cs:336-339`).
|
||||
#[error("PDU has no auth value")]
|
||||
MissingAuthValue,
|
||||
|
||||
/// Generic decode failure with a position and reason. Used by ORPC
|
||||
/// body decoders for one-off conditions that don't justify a typed
|
||||
/// variant (e.g. NDR conformant-array max-count underflow per
|
||||
/// `ObjectExporterMessages.cs:66-69`, referent-id of zero with no
|
||||
/// trailing status per `:57-61`, NDR alignment overrun, etc.).
|
||||
#[error("decode at offset {offset} ({reason}); buffer len {buffer_len}")]
|
||||
Decode {
|
||||
offset: usize,
|
||||
reason: &'static str,
|
||||
buffer_len: usize,
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user