valence_protocol/impls/
sequence.rs

1use std::io::Write;
2use std::mem::{self, MaybeUninit};
3use std::slice;
4
5use anyhow::ensure;
6
7use crate::impls::cautious_capacity;
8use crate::{Bounded, Decode, Encode, VarInt};
9
10/// Like tuples, fixed-length arrays are encoded and decoded without a `VarInt`
11/// length prefix.
12impl<T: Encode, const N: usize> Encode for [T; N] {
13    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
14        T::encode_slice(self, w)
15    }
16}
17
18impl<'a, T: Decode<'a>, const N: usize> Decode<'a> for [T; N] {
19    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
20        // TODO: rewrite using std::array::try_from_fn when stabilized?
21
22        let mut data: [MaybeUninit<T>; N] = unsafe { MaybeUninit::uninit().assume_init() };
23
24        for (i, elem) in data.iter_mut().enumerate() {
25            match T::decode(r) {
26                Ok(val) => {
27                    elem.write(val);
28                }
29                Err(e) => {
30                    // Call destructors for values decoded so far.
31                    for elem in &mut data[..i] {
32                        unsafe { elem.assume_init_drop() };
33                    }
34                    return Err(e);
35                }
36            }
37        }
38
39        // All values in `data` are initialized.
40        unsafe { Ok(mem::transmute_copy(&data)) }
41    }
42}
43
44/// References to fixed-length arrays are not length prefixed.
45impl<'a, const N: usize> Decode<'a> for &'a [u8; N] {
46    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
47        ensure!(
48            r.len() >= N,
49            "not enough data to decode u8 array of length {N}"
50        );
51
52        let (res, remaining) = r.split_at(N);
53        let arr = <&[u8; N]>::try_from(res).unwrap();
54        *r = remaining;
55        Ok(arr)
56    }
57}
58
59impl<T: Encode> Encode for [T] {
60    fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
61        let len = self.len();
62        ensure!(
63            i32::try_from(len).is_ok(),
64            "length of {} slice exceeds i32::MAX (got {len})",
65            std::any::type_name::<T>()
66        );
67
68        VarInt(len as i32).encode(&mut w)?;
69
70        T::encode_slice(self, w)
71    }
72}
73
74impl<T: Encode, const MAX_LEN: usize> Encode for Bounded<&'_ [T], MAX_LEN> {
75    fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
76        let len = self.len();
77        ensure!(
78            len <= MAX_LEN,
79            "length of {} slice exceeds max of {MAX_LEN} (got {len})",
80            std::any::type_name::<T>(),
81        );
82
83        VarInt(len as i32).encode(&mut w)?;
84
85        T::encode_slice(self, w)
86    }
87}
88
89impl<'a> Decode<'a> for &'a [u8] {
90    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
91        let len = VarInt::decode(r)?.0;
92        ensure!(len >= 0, "attempt to decode slice with negative length");
93        let len = len as usize;
94        ensure!(
95            len <= r.len(),
96            "not enough data remaining to decode byte slice (slice len is {len}, but input len is \
97             {})",
98            r.len()
99        );
100
101        let (res, remaining) = r.split_at(len);
102        *r = remaining;
103        Ok(res)
104    }
105}
106
107impl<'a, const MAX_LEN: usize> Decode<'a> for Bounded<&'a [u8], MAX_LEN> {
108    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
109        let res = <&[u8]>::decode(r)?;
110
111        ensure!(
112            res.len() <= MAX_LEN,
113            "length of decoded byte slice exceeds max of {MAX_LEN} (got {})",
114            res.len()
115        );
116
117        Ok(Bounded(res))
118    }
119}
120
121impl<'a> Decode<'a> for &'a [i8] {
122    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
123        let bytes = <&[u8]>::decode(r)?;
124
125        // SAFETY: i8 and u8 have the same layout.
126        let bytes = unsafe { slice::from_raw_parts(bytes.as_ptr() as *const i8, bytes.len()) };
127
128        Ok(bytes)
129    }
130}
131
132impl<T: Encode> Encode for Vec<T> {
133    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
134        self.as_slice().encode(w)
135    }
136}
137
138impl<'a, T: Decode<'a>> Decode<'a> for Vec<T> {
139    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
140        let len = VarInt::decode(r)?.0;
141        ensure!(len >= 0, "attempt to decode Vec with negative length");
142        let len = len as usize;
143
144        let mut vec = Vec::with_capacity(cautious_capacity::<T>(len));
145
146        for _ in 0..len {
147            vec.push(T::decode(r)?);
148        }
149
150        Ok(vec)
151    }
152}
153
154impl<'a, T: Decode<'a>, const MAX_LEN: usize> Decode<'a> for Bounded<Vec<T>, MAX_LEN> {
155    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
156        let len = VarInt::decode(r)?.0;
157        ensure!(len >= 0, "attempt to decode Vec with negative length");
158        let len = len as usize;
159
160        ensure!(
161            len <= MAX_LEN,
162            "length of Vec exceeds max of {MAX_LEN} (got {len})"
163        );
164
165        let mut vec = Vec::with_capacity(len);
166
167        for _ in 0..len {
168            vec.push(T::decode(r)?);
169        }
170
171        Ok(Bounded(vec))
172    }
173}
174
175impl<'a, T: Decode<'a>> Decode<'a> for Box<[T]> {
176    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
177        Ok(Vec::decode(r)?.into_boxed_slice())
178    }
179}
180
181impl<'a, T: Decode<'a>, const MAX_LEN: usize> Decode<'a> for Bounded<Box<[T]>, MAX_LEN> {
182    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
183        Ok(Bounded::<Vec<_>, MAX_LEN>::decode(r)?.map_into())
184    }
185}