[go: up one dir, main page]

reis/wire/
mod.rs

1/// EI wire protcol.
2///
3/// This is the lowest level component of reis. It provides serialization
4/// and deserialization of the protocol, and uses Rustix to handle socket IO.
5use std::{
6    collections::{self, VecDeque},
7    fmt, iter,
8    os::unix::io::OwnedFd,
9    string::FromUtf8Error,
10};
11
12use crate::Object;
13
14mod arg;
15pub(crate) use arg::{Arg, OwnedArg};
16mod backend;
17pub use backend::PendingRequestResult;
18pub(crate) use backend::{Backend, BackendWeak};
19
20#[derive(Debug)]
21pub(crate) struct Header {
22    pub object_id: u64,
23    pub length: u32,
24    pub opcode: u32,
25}
26
27impl Header {
28    pub fn parse(bytes: [u8; 16]) -> Self {
29        Self {
30            object_id: u64::from_ne_bytes(bytes[0..8].try_into().unwrap()),
31            length: u32::from_ne_bytes(bytes[8..12].try_into().unwrap()),
32            opcode: u32::from_ne_bytes(bytes[12..16].try_into().unwrap()),
33        }
34    }
35
36    pub fn as_bytes(&self) -> impl Iterator<Item = u8> {
37        self.object_id
38            .to_ne_bytes()
39            .into_iter()
40            .chain(self.length.to_ne_bytes())
41            .chain(self.opcode.to_ne_bytes())
42    }
43}
44
45pub trait Interface: crate::private::Sealed {
46    const NAME: &'static str;
47    const VERSION: u32;
48    const CLIENT_SIDE: bool;
49
50    fn new_unchecked(object: Object) -> Self;
51
52    fn as_object(&self) -> &Object;
53
54    fn as_arg(&self) -> Arg<'_>;
55}
56
57pub(crate) trait MessageEnum {
58    fn args(&self) -> Vec<Arg<'_>>;
59}
60
61pub(crate) struct ByteStream<'a> {
62    pub backend: &'a Backend,
63    pub bytes: std::collections::vec_deque::Drain<'a, u8>,
64    pub fds: &'a mut VecDeque<OwnedFd>,
65}
66
67impl<'a> ByteStream<'a> {
68    pub fn backend(&self) -> &Backend {
69        self.backend
70    }
71
72    // TODO: Using impl Iterator ran into lifetime issues
73    fn read_n<'b>(
74        &'b mut self,
75        n: usize,
76    ) -> Result<iter::Take<&'b mut collections::vec_deque::Drain<'a, u8>>, ParseError> {
77        if self.bytes.len() >= n {
78            Ok(self.bytes.by_ref().take(n))
79        } else {
80            Err(ParseError::EndOfMessage)
81        }
82    }
83
84    fn read<const N: usize>(&mut self) -> Result<[u8; N], ParseError> {
85        Ok(crate::util::array_from_iterator_unchecked(self.read_n(N)?))
86    }
87
88    fn read_fd(&mut self) -> Result<OwnedFd, ParseError> {
89        self.fds.pop_front().ok_or(ParseError::NoFd)
90    }
91
92    pub fn read_arg<T: OwnedArg>(&mut self) -> Result<T, ParseError> {
93        T::parse(self)
94    }
95}
96
97#[derive(Debug)]
98pub enum ParseError {
99    EndOfMessage,
100    Utf8(FromUtf8Error),
101    InvalidId(u64),
102    NoFd,
103    InvalidOpcode(&'static str, u32),
104    InvalidVariant(&'static str, u32),
105    InvalidInterface(String),
106    HeaderLength(u32),
107    MessageLength(u32, u32),
108}
109
110impl fmt::Display for ParseError {
111    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112        match self {
113            Self::EndOfMessage => write!(f, "found end of message while parsing argument"),
114            Self::Utf8(e) => write!(f, "invalid UTF-8 string in message: {}", e),
115            Self::InvalidId(id) => write!(f, "new object id '{}' invalid", id),
116            Self::NoFd => write!(f, "expected fd"),
117            Self::InvalidOpcode(intr, op) => {
118                write!(f, "opcode '{}' invallid for interface '{}'", op, intr)
119            }
120            Self::InvalidVariant(enum_, var) => {
121                write!(f, "variant '{}' invallid for enum '{}'", var, enum_)
122            }
123            Self::InvalidInterface(intr) => write!(f, "unknown interface '{}'", intr),
124            Self::HeaderLength(len) => write!(f, "header length {} < 16", len),
125            Self::MessageLength(a, b) => {
126                write!(f, "message length didn't match header ({} != {})", a, b)
127            }
128        }
129    }
130}
131
132impl From<FromUtf8Error> for ParseError {
133    fn from(err: FromUtf8Error) -> Self {
134        Self::Utf8(err)
135    }
136}
137
138impl std::error::Error for ParseError {}