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}