Skip to main content

moon_wire_codec/
lib.rs

1#![no_std]
2extern crate alloc;
3
4use alloc::string::String;
5use alloc::string::ToString;
6use alloc::vec::Vec;
7
8pub const WIRE_MAGIC: u32 = u32::from_le_bytes(*b"MOON");
9pub const WIRE_VERSION: u16 = 1;
10
11#[repr(u16)]
12#[derive(Clone, Copy)]
13pub enum OpCode {
14    EchoTyped = 1,
15    ListProcessTyped = 2,
16}
17
18#[repr(C)]
19pub struct WireHeader {
20    pub magic: u32,
21    pub version: u16,
22    pub op: u16,
23    pub payload_len: u32,
24}
25
26#[derive(Debug)]
27pub enum CodecError {
28    InvalidHeader,
29    WrongMagic,
30    WrongVersion,
31    Truncated,
32    Deserialize,
33    Serialize,
34}
35
36pub trait Codec: Sized {
37    fn encode(&self, out: &mut Vec<u8>);
38    fn decode(input: &[u8]) -> Result<(Self, usize), CodecError>;
39}
40
41impl Codec for u64 {
42    fn encode(&self, out: &mut Vec<u8>) {
43        out.extend_from_slice(&self.to_le_bytes());
44    }
45    fn decode(input: &[u8]) -> Result<(Self, usize), CodecError> {
46        if input.len() < 8 {
47            return Err(CodecError::Truncated);
48        }
49        let mut a = [0u8; 8];
50        a.copy_from_slice(&input[0..8]);
51        Ok((u64::from_le_bytes(a), 8))
52    }
53}
54impl Codec for u32 {
55    fn encode(&self, out: &mut Vec<u8>) {
56        out.extend_from_slice(&self.to_le_bytes());
57    }
58    fn decode(input: &[u8]) -> Result<(Self, usize), CodecError> {
59        if input.len() < 4 {
60            return Err(CodecError::Truncated);
61        }
62        let mut a = [0u8; 4];
63        a.copy_from_slice(&input[0..4]);
64        Ok((u32::from_le_bytes(a), 4))
65    }
66}
67impl Codec for u16 {
68    fn encode(&self, out: &mut Vec<u8>) {
69        out.extend_from_slice(&self.to_le_bytes());
70    }
71    fn decode(input: &[u8]) -> Result<(Self, usize), CodecError> {
72        if input.len() < 2 {
73            return Err(CodecError::Truncated);
74        }
75        let mut a = [0u8; 2];
76        a.copy_from_slice(&input[0..2]);
77        Ok((u16::from_le_bytes(a), 2))
78    }
79}
80impl Codec for bool {
81    fn encode(&self, out: &mut Vec<u8>) {
82        out.push(if *self { 1 } else { 0 });
83    }
84    fn decode(input: &[u8]) -> Result<(Self, usize), CodecError> {
85        if input.is_empty() {
86            Err(CodecError::Truncated)
87        } else {
88            Ok((input[0] != 0, 1))
89        }
90    }
91}
92impl Codec for String {
93    fn encode(&self, out: &mut Vec<u8>) {
94        let b = self.as_bytes();
95        (b.len() as u32).encode(out);
96        out.extend_from_slice(b);
97    }
98    fn decode(input: &[u8]) -> Result<(Self, usize), CodecError> {
99        let (len, mut off) = u32::decode(input)?;
100        let len = len as usize;
101        if input.len() < off + len {
102            return Err(CodecError::Truncated);
103        }
104        let s = core::str::from_utf8(&input[off..off + len])
105            .map_err(|_| CodecError::Deserialize)?
106            .to_string();
107        off += len;
108        Ok((s, off))
109    }
110}
111impl<T: Codec> Codec for Vec<T> {
112    fn encode(&self, out: &mut Vec<u8>) {
113        (self.len() as u32).encode(out);
114        for item in self {
115            item.encode(out);
116        }
117    }
118    fn decode(input: &[u8]) -> Result<(Self, usize), CodecError> {
119        let (count, mut off) = u32::decode(input)?;
120        let mut v = Vec::with_capacity(count as usize);
121        for _ in 0..count {
122            let (item, read) = T::decode(&input[off..])?;
123            off += read;
124            v.push(item);
125        }
126        Ok((v, off))
127    }
128}
129impl<T: Codec> Codec for Option<T> {
130    fn encode(&self, out: &mut Vec<u8>) {
131        match self {
132            Some(v) => {
133                out.push(1);
134                v.encode(out);
135            }
136            None => out.push(0),
137        }
138    }
139    fn decode(input: &[u8]) -> Result<(Self, usize), CodecError> {
140        if input.is_empty() {
141            return Err(CodecError::Truncated);
142        }
143        if input[0] == 0 {
144            Ok((None, 1))
145        } else {
146            let (v, r) = T::decode(&input[1..])?;
147            Ok((Some(v), 1 + r))
148        }
149    }
150}
151
152pub struct Empty;
153
154impl Codec for Empty {
155    fn encode(&self, _out: &mut Vec<u8>) {}
156    fn decode(_input: &[u8]) -> Result<(Self, usize), CodecError> {
157        Ok((Empty, 0))
158    }
159}
160
161pub fn build_header(op: u16, payload_len: u32) -> [u8; 12] {
162    let mut h = [0u8; 12];
163    h[0..4].copy_from_slice(&WIRE_MAGIC.to_le_bytes());
164    h[4..6].copy_from_slice(&WIRE_VERSION.to_le_bytes());
165    h[6..8].copy_from_slice(&op.to_le_bytes());
166    h[8..12].copy_from_slice(&payload_len.to_le_bytes());
167    h
168}
169
170pub fn parse_header(buf: &[u8]) -> Result<(OpCode, u32), CodecError> {
171    if buf.len() < 12 {
172        return Err(CodecError::InvalidHeader);
173    }
174    let magic = u32::from_le_bytes(buf[0..4].try_into().unwrap());
175    if magic != WIRE_MAGIC {
176        return Err(CodecError::WrongMagic);
177    }
178    let version = u16::from_le_bytes(buf[4..6].try_into().unwrap());
179    if version != WIRE_VERSION {
180        return Err(CodecError::WrongVersion);
181    }
182    let op = u16::from_le_bytes(buf[6..8].try_into().unwrap());
183    let payload_len = u32::from_le_bytes(buf[8..12].try_into().unwrap());
184    let op = match op {
185        1 => OpCode::EchoTyped,
186        2 => OpCode::ListProcessTyped,
187        _ => return Err(CodecError::InvalidHeader),
188    };
189    Ok((op, payload_len))
190}
191
192pub fn encode_frame_raw(op: u16, payload: &[u8]) -> Vec<u8> {
193    let header = build_header(op, payload.len() as u32);
194    let mut frame = Vec::with_capacity(12 + payload.len());
195    frame.extend_from_slice(&header);
196    frame.extend_from_slice(payload);
197    frame
198}
199
200pub fn decode_frame_raw<'a>(buf: &'a [u8]) -> Result<(OpCode, &'a [u8]), CodecError> {
201    let (op, payload_len) = parse_header(buf)?;
202    let total = 12usize + payload_len as usize;
203    if buf.len() < total {
204        return Err(CodecError::Truncated);
205    }
206    Ok((op, &buf[12..total]))
207}
208
209pub fn encode_frame<T: Codec>(op: u16, payload: &T) -> Vec<u8> {
210    let mut buf = Vec::new();
211    payload.encode(&mut buf);
212    encode_frame_raw(op, &buf)
213}
214
215pub fn decode_frame<T: Codec>(buf: &[u8]) -> Result<(OpCode, T), CodecError> {
216    let (op, payload) = decode_frame_raw(buf)?;
217    let (req, _) = T::decode(payload)?;
218    Ok((op, req))
219}
220
221pub fn encode_typed<T: Codec>(v: &T) -> Vec<u8> {
222    let mut out = Vec::new();
223    v.encode(&mut out);
224    out
225}
226pub fn decode_typed<T: Codec>(buf: &[u8]) -> Result<(T, usize), CodecError> {
227    T::decode(buf)
228}
229pub fn encode_frame_typed<T: Codec>(op: OpCode, v: &T) -> Vec<u8> {
230    let payload = encode_typed(v);
231    encode_frame_raw(op as u16, &payload)
232}
233pub fn decode_frame_typed<'a, T: Codec>(buf: &'a [u8]) -> Result<(OpCode, T), CodecError> {
234    let (op, payload) = decode_frame_raw(buf)?;
235    let (v, _) = decode_typed::<T>(payload)?;
236    Ok((op, v))
237}