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 fn build_header(op: OpCode, payload_len: u32) -> [u8; 12] {
153    let mut h = [0u8; 12];
154    h[0..4].copy_from_slice(&WIRE_MAGIC.to_le_bytes());
155    h[4..6].copy_from_slice(&WIRE_VERSION.to_le_bytes());
156    let op_u16 = op as u16;
157    h[6..8].copy_from_slice(&op_u16.to_le_bytes());
158    h[8..12].copy_from_slice(&payload_len.to_le_bytes());
159    h
160}
161
162pub fn parse_header(buf: &[u8]) -> Result<(OpCode, u32), CodecError> {
163    if buf.len() < 12 {
164        return Err(CodecError::InvalidHeader);
165    }
166    let magic = u32::from_le_bytes(buf[0..4].try_into().unwrap());
167    if magic != WIRE_MAGIC {
168        return Err(CodecError::WrongMagic);
169    }
170    let version = u16::from_le_bytes(buf[4..6].try_into().unwrap());
171    if version != WIRE_VERSION {
172        return Err(CodecError::WrongVersion);
173    }
174    let op = u16::from_le_bytes(buf[6..8].try_into().unwrap());
175    let payload_len = u32::from_le_bytes(buf[8..12].try_into().unwrap());
176    let op = match op {
177        1 => OpCode::EchoTyped,
178        2 => OpCode::ListProcessTyped,
179        _ => return Err(CodecError::InvalidHeader),
180    };
181    Ok((op, payload_len))
182}
183
184pub fn encode_frame_raw(op: OpCode, payload: &[u8]) -> Vec<u8> {
185    let header = build_header(op, payload.len() as u32);
186    let mut frame = Vec::with_capacity(12 + payload.len());
187    frame.extend_from_slice(&header);
188    frame.extend_from_slice(payload);
189    frame
190}
191
192pub fn decode_frame_raw<'a>(buf: &'a [u8]) -> Result<(OpCode, &'a [u8]), CodecError> {
193    let (op, payload_len) = parse_header(buf)?;
194    let total = 12usize + payload_len as usize;
195    if buf.len() < total {
196        return Err(CodecError::Truncated);
197    }
198    Ok((op, &buf[12..total]))
199}
200
201pub fn encode_typed<T: Codec>(v: &T) -> Vec<u8> {
202    let mut out = Vec::new();
203    v.encode(&mut out);
204    out
205}
206pub fn decode_typed<T: Codec>(buf: &[u8]) -> Result<(T, usize), CodecError> {
207    T::decode(buf)
208}
209pub fn encode_frame_typed<T: Codec>(op: OpCode, v: &T) -> Vec<u8> {
210    let payload = encode_typed(v);
211    encode_frame_raw(op, &payload)
212}
213pub fn decode_frame_typed<'a, T: Codec>(buf: &'a [u8]) -> Result<(OpCode, T), CodecError> {
214    let (op, payload) = decode_frame_raw(buf)?;
215    let (v, _) = decode_typed::<T>(payload)?;
216    Ok((op, v))
217}