Skip to main content

oxicode/features/
impl_std.rs

1//! Encode/Decode implementations for std-dependent types
2
3use crate::{
4    de::{read::Reader, Decode, Decoder},
5    enc::{write::Writer, Encode, Encoder},
6    error::Error,
7};
8use std::{
9    collections::{HashMap, HashSet},
10    ffi::{CStr, CString},
11    hash::{BuildHasher, Hash},
12    net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, SocketAddrV6},
13    path::{Path, PathBuf},
14    sync::{Mutex, RwLock},
15};
16
17// ===== HashMap<K, V> =====
18
19impl<K, V, S> Encode for HashMap<K, V, S>
20where
21    K: Encode,
22    V: Encode,
23{
24    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
25        (self.len() as u64).encode(encoder)?;
26        for (key, value) in self.iter() {
27            key.encode(encoder)?;
28            value.encode(encoder)?;
29        }
30        Ok(())
31    }
32}
33
34impl<K, V, S> Decode for HashMap<K, V, S>
35where
36    K: Decode + Eq + Hash,
37    V: Decode,
38    S: BuildHasher + Default,
39{
40    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
41        let len = u64::decode(decoder)? as usize;
42
43        let mut map = HashMap::with_capacity_and_hasher(len, S::default());
44        for _ in 0..len {
45            let key = K::decode(decoder)?;
46            let value = V::decode(decoder)?;
47            map.insert(key, value);
48        }
49        Ok(map)
50    }
51}
52
53// ===== HashSet<T> =====
54
55impl<T, S> Encode for HashSet<T, S>
56where
57    T: Encode,
58{
59    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
60        (self.len() as u64).encode(encoder)?;
61        for item in self.iter() {
62            item.encode(encoder)?;
63        }
64        Ok(())
65    }
66}
67
68impl<T, S> Decode for HashSet<T, S>
69where
70    T: Decode + Eq + Hash,
71    S: BuildHasher + Default,
72{
73    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
74        let len = u64::decode(decoder)? as usize;
75
76        let mut set = HashSet::with_capacity_and_hasher(len, S::default());
77        for _ in 0..len {
78            set.insert(T::decode(decoder)?);
79        }
80        Ok(set)
81    }
82}
83
84// ===== Mutex<T> =====
85
86impl<T: Encode> Encode for Mutex<T> {
87    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
88        let guard = self.lock().map_err(|_| Error::Custom {
89            message: "Mutex poisoned",
90        })?;
91        (*guard).encode(encoder)
92    }
93}
94
95impl<T: Decode> Decode for Mutex<T> {
96    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
97        Ok(Mutex::new(T::decode(decoder)?))
98    }
99}
100
101// ===== RwLock<T> =====
102
103impl<T: Encode> Encode for RwLock<T> {
104    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
105        let guard = self.read().map_err(|_| Error::Custom {
106            message: "RwLock poisoned",
107        })?;
108        (*guard).encode(encoder)
109    }
110}
111
112impl<T: Decode> Decode for RwLock<T> {
113    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
114        Ok(RwLock::new(T::decode(decoder)?))
115    }
116}
117
118// ===== Path & PathBuf =====
119
120impl Encode for Path {
121    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
122        let os_str = self.as_os_str();
123        #[cfg(unix)]
124        {
125            use std::os::unix::ffi::OsStrExt;
126            let bytes = os_str.as_bytes();
127            (bytes.len() as u64).encode(encoder)?;
128            encoder.writer().write(bytes)
129        }
130        #[cfg(windows)]
131        {
132            use std::os::windows::ffi::OsStrExt;
133            let wide: Vec<u16> = os_str.encode_wide().collect();
134            (wide.len() as u64).encode(encoder)?;
135            for code_unit in wide {
136                code_unit.encode(encoder)?;
137            }
138            Ok(())
139        }
140        #[cfg(not(any(unix, windows)))]
141        {
142            // Fallback: convert to string lossy
143            let string = os_str.to_string_lossy();
144            string.encode(encoder)
145        }
146    }
147}
148
149impl Encode for PathBuf {
150    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
151        self.as_path().encode(encoder)
152    }
153}
154
155impl Decode for PathBuf {
156    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
157        #[cfg(unix)]
158        {
159            use std::ffi::OsStr;
160            use std::os::unix::ffi::OsStrExt;
161
162            let len = u64::decode(decoder)? as usize;
163            decoder.claim_bytes_read(len)?;
164
165            let mut bytes = alloc::vec![0u8; len];
166            decoder.reader().read(&mut bytes)?;
167
168            Ok(PathBuf::from(OsStr::from_bytes(&bytes)))
169        }
170        #[cfg(windows)]
171        {
172            use std::ffi::OsString;
173            use std::os::windows::ffi::OsStringExt;
174
175            let len = u64::decode(decoder)? as usize;
176            let mut wide = alloc::vec![0u16; len];
177            for code_unit in &mut wide {
178                *code_unit = u16::decode(decoder)?;
179            }
180
181            Ok(PathBuf::from(OsString::from_wide(&wide)))
182        }
183        #[cfg(not(any(unix, windows)))]
184        {
185            let string = String::decode(decoder)?;
186            Ok(PathBuf::from(string))
187        }
188    }
189}
190
191// ===== IpAddr =====
192
193impl Encode for IpAddr {
194    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
195        match self {
196            IpAddr::V4(addr) => {
197                0u8.encode(encoder)?;
198                addr.encode(encoder)
199            }
200            IpAddr::V6(addr) => {
201                1u8.encode(encoder)?;
202                addr.encode(encoder)
203            }
204        }
205    }
206}
207
208impl Decode for IpAddr {
209    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
210        let variant = u8::decode(decoder)?;
211        match variant {
212            0 => Ok(IpAddr::V4(Ipv4Addr::decode(decoder)?)),
213            1 => Ok(IpAddr::V6(Ipv6Addr::decode(decoder)?)),
214            _ => Err(Error::InvalidData {
215                message: "Invalid IpAddr variant",
216            }),
217        }
218    }
219}
220
221// ===== Ipv4Addr =====
222
223impl Encode for Ipv4Addr {
224    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
225        encoder.writer().write(&self.octets())
226    }
227}
228
229impl Decode for Ipv4Addr {
230    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
231        let mut octets = [0u8; 4];
232        decoder.reader().read(&mut octets)?;
233        Ok(Ipv4Addr::from(octets))
234    }
235}
236
237// ===== Ipv6Addr =====
238
239impl Encode for Ipv6Addr {
240    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
241        encoder.writer().write(&self.octets())
242    }
243}
244
245impl Decode for Ipv6Addr {
246    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
247        let mut octets = [0u8; 16];
248        decoder.reader().read(&mut octets)?;
249        Ok(Ipv6Addr::from(octets))
250    }
251}
252
253// ===== SocketAddr =====
254
255impl Encode for SocketAddr {
256    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
257        match self {
258            SocketAddr::V4(addr) => {
259                0u8.encode(encoder)?;
260                addr.encode(encoder)
261            }
262            SocketAddr::V6(addr) => {
263                1u8.encode(encoder)?;
264                addr.encode(encoder)
265            }
266        }
267    }
268}
269
270impl Decode for SocketAddr {
271    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
272        let variant = u8::decode(decoder)?;
273        match variant {
274            0 => Ok(SocketAddr::V4(SocketAddrV4::decode(decoder)?)),
275            1 => Ok(SocketAddr::V6(SocketAddrV6::decode(decoder)?)),
276            _ => Err(Error::InvalidData {
277                message: "Invalid SocketAddr variant",
278            }),
279        }
280    }
281}
282
283// ===== SocketAddrV4 =====
284
285impl Encode for SocketAddrV4 {
286    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
287        self.ip().encode(encoder)?;
288        self.port().encode(encoder)
289    }
290}
291
292impl Decode for SocketAddrV4 {
293    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
294        let ip = Ipv4Addr::decode(decoder)?;
295        let port = u16::decode(decoder)?;
296        Ok(SocketAddrV4::new(ip, port))
297    }
298}
299
300// ===== SocketAddrV6 =====
301
302impl Encode for SocketAddrV6 {
303    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
304        self.ip().encode(encoder)?;
305        self.port().encode(encoder)?;
306        self.flowinfo().encode(encoder)?;
307        self.scope_id().encode(encoder)
308    }
309}
310
311impl Decode for SocketAddrV6 {
312    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
313        let ip = Ipv6Addr::decode(decoder)?;
314        let port = u16::decode(decoder)?;
315        let flowinfo = u32::decode(decoder)?;
316        let scope_id = u32::decode(decoder)?;
317        Ok(SocketAddrV6::new(ip, port, flowinfo, scope_id))
318    }
319}
320
321// ===== CString =====
322
323impl Encode for CString {
324    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
325        // Encode as bytes without the null terminator
326        let bytes = self.as_bytes();
327        (bytes.len() as u64).encode(encoder)?;
328        encoder.writer().write(bytes)
329    }
330}
331
332impl Decode for CString {
333    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
334        let len = u64::decode(decoder)? as usize;
335        decoder.claim_bytes_read(len)?;
336
337        let mut bytes = alloc::vec![0u8; len];
338        decoder.reader().read(&mut bytes)?;
339
340        // Verify no null bytes in the middle
341        if bytes.contains(&0) {
342            return Err(Error::Custom {
343                message: "CString contains null byte",
344            });
345        }
346
347        CString::new(bytes).map_err(|_| Error::Custom {
348            message: "CString contains null byte",
349        })
350    }
351}
352
353// ===== CStr =====
354
355impl Encode for CStr {
356    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
357        let bytes = self.to_bytes();
358        (bytes.len() as u64).encode(encoder)?;
359        encoder.writer().write(bytes)
360    }
361}
362
363// ===== OsStr & OsString =====
364
365#[cfg(not(target_family = "wasm"))]
366impl Encode for std::ffi::OsStr {
367    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
368        self.to_string_lossy().as_ref().encode(encoder)
369    }
370}
371
372#[cfg(not(target_family = "wasm"))]
373impl Encode for std::ffi::OsString {
374    fn encode<E: Encoder>(&self, encoder: &mut E) -> Result<(), Error> {
375        self.as_os_str().encode(encoder)
376    }
377}
378
379#[cfg(not(target_family = "wasm"))]
380impl Decode for std::ffi::OsString {
381    fn decode<D: Decoder<Context = ()>>(decoder: &mut D) -> Result<Self, Error> {
382        let s = String::decode(decoder)?;
383        Ok(std::ffi::OsString::from(s))
384    }
385}
386
387// ===== BorrowDecode for std types (delegate to Decode) =====
388
389crate::impl_borrow_decode!(PathBuf);
390crate::impl_borrow_decode!(IpAddr);
391crate::impl_borrow_decode!(Ipv4Addr);
392crate::impl_borrow_decode!(Ipv6Addr);
393crate::impl_borrow_decode!(SocketAddr);
394crate::impl_borrow_decode!(SocketAddrV4);
395crate::impl_borrow_decode!(SocketAddrV6);
396crate::impl_borrow_decode!(CString);
397#[cfg(not(target_family = "wasm"))]
398crate::impl_borrow_decode!(std::ffi::OsString);
399
400impl<'de, T, S> crate::de::BorrowDecode<'de> for HashSet<T, S>
401where
402    T: crate::de::Decode + Eq + Hash + 'static,
403    S: BuildHasher + Default + 'static,
404{
405    fn borrow_decode<D: crate::de::BorrowDecoder<'de, Context = ()>>(
406        decoder: &mut D,
407    ) -> Result<Self, Error> {
408        HashSet::<T, S>::decode(decoder)
409    }
410}
411
412impl<'de, K, V, S> crate::de::BorrowDecode<'de> for HashMap<K, V, S>
413where
414    K: crate::de::Decode + Eq + Hash + 'static,
415    V: crate::de::Decode + 'static,
416    S: BuildHasher + Default + 'static,
417{
418    fn borrow_decode<D: crate::de::BorrowDecoder<'de, Context = ()>>(
419        decoder: &mut D,
420    ) -> Result<Self, Error> {
421        HashMap::<K, V, S>::decode(decoder)
422    }
423}
424
425impl<'de, T: crate::de::Decode + 'static> crate::de::BorrowDecode<'de> for Mutex<T> {
426    fn borrow_decode<D: crate::de::BorrowDecoder<'de, Context = ()>>(
427        decoder: &mut D,
428    ) -> Result<Self, Error> {
429        Mutex::<T>::decode(decoder)
430    }
431}
432
433impl<'de, T: crate::de::Decode + 'static> crate::de::BorrowDecode<'de> for RwLock<T> {
434    fn borrow_decode<D: crate::de::BorrowDecoder<'de, Context = ()>>(
435        decoder: &mut D,
436    ) -> Result<Self, Error> {
437        RwLock::<T>::decode(decoder)
438    }
439}