imsg_obex/lib.rs
1//! Sans-IO OBEX packet codec, framing, and client/server state machines.
2
3use thiserror::Error;
4use tokio::io::{AsyncRead, AsyncWrite};
5use tokio_util::codec::Framed;
6
7/// OBEX client state machine — encodes requests and processes responses.
8pub mod client;
9/// OBEX length-prefix framing codec for [`tokio_util::codec::Framed`].
10pub mod codec;
11/// OBEX header types; wire tag bytes 0x01–0xCB.
12pub mod headers;
13/// [`Packet`], [`OpCode`], `PacketExtra`, and `PacketError` types.
14pub mod packet;
15/// OBEX server state machine — decodes requests and encodes responses.
16pub mod server;
17
18pub use codec::ObexCodec;
19
20/// OBEX framing errors — invalid length, unexpected EOF, and external transport failures.
21#[derive(Debug, Error)]
22pub enum TransportError {
23 /// OS-level socket error; check `kind()` for connection-refused, permission-denied, etc.
24 #[error("I/O: {0}")]
25 Io(#[from] std::io::Error),
26 /// Declared packet length is below the 3-byte OBEX minimum.
27 #[error("declared packet length {declared} is below the 3-byte OBEX minimum")]
28 InvalidLength {
29 /// The value read from wire bytes 1–2.
30 declared: usize,
31 },
32 /// Stream closed before a complete packet arrived.
33 #[error("unexpected end of stream")]
34 UnexpectedEof,
35 /// External transport driver error (QUIC, TLS, or other); carries the driver error message.
36 #[error("transport driver: {0}")]
37 External(String),
38}
39
40/// OBEX-framed async transport over any [`AsyncRead`] + [`AsyncWrite`] stream.
41///
42/// Yields and accepts complete OBEX packets as [`bytes::Bytes`]. Obtain via
43/// [`wrap`]; use [`futures::SinkExt`] / [`futures::StreamExt`] to send and receive.
44pub type ObexTransport<T> = Framed<T, ObexCodec>;
45
46/// Buffers reads until a complete OBEX packet arrives.
47pub fn wrap<T: AsyncRead + AsyncWrite>(inner: T) -> ObexTransport<T> {
48 Framed::new(inner, ObexCodec)
49}