valence_server/layer/chunk/
paletted_container.rs

1use std::array;
2use std::io::Write;
3
4use arrayvec::ArrayVec;
5use valence_protocol::{Encode, VarInt};
6
7use super::chunk::bit_width;
8
9/// `HALF_LEN` must be equal to `ceil(LEN / 2)`.
10#[derive(Clone, Debug)]
11pub(super) enum PalettedContainer<T, const LEN: usize, const HALF_LEN: usize> {
12    Single(T),
13    Indirect(Box<Indirect<T, LEN, HALF_LEN>>),
14    Direct(Box<[T; LEN]>),
15}
16
17#[derive(Clone, Debug)]
18pub(super) struct Indirect<T, const LEN: usize, const HALF_LEN: usize> {
19    /// Each element is a unique instance of `T`. The length of the palette is
20    /// always ≥2.
21    palette: ArrayVec<T, 16>,
22    /// Each half-byte is an index into `palette`.
23    indices: [u8; HALF_LEN],
24}
25
26impl<T: Copy + Eq + Default, const LEN: usize, const HALF_LEN: usize>
27    PalettedContainer<T, LEN, HALF_LEN>
28{
29    pub(super) fn new() -> Self {
30        assert_eq!(LEN.div_ceil(2), HALF_LEN);
31        assert_ne!(LEN, 0);
32
33        Self::Single(T::default())
34    }
35
36    pub(super) fn fill(&mut self, val: T) {
37        *self = Self::Single(val)
38    }
39
40    #[track_caller]
41    pub(super) fn get(&self, idx: usize) -> T {
42        debug_assert!(idx < LEN);
43
44        match self {
45            Self::Single(elem) => *elem,
46            Self::Indirect(ind) => ind.get(idx),
47            Self::Direct(elems) => elems[idx],
48        }
49    }
50
51    #[track_caller]
52    pub(super) fn set(&mut self, idx: usize, val: T) -> T {
53        debug_assert!(idx < LEN);
54
55        match self {
56            Self::Single(old_val) => {
57                if *old_val == val {
58                    *old_val
59                } else {
60                    // Upgrade to indirect.
61                    let old = *old_val;
62                    let mut ind = Box::new(Indirect {
63                        palette: ArrayVec::from_iter([old, val]),
64                        // All indices are initialized to index 0 (the old element).
65                        indices: [0; HALF_LEN],
66                    });
67
68                    ind.indices[idx / 2] = 1 << (idx % 2 * 4);
69                    *self = Self::Indirect(ind);
70                    old
71                }
72            }
73            Self::Indirect(ind) => {
74                if let Some(old) = ind.set(idx, val) {
75                    old
76                } else {
77                    // Upgrade to direct.
78                    *self = Self::Direct(Box::new(array::from_fn(|i| ind.get(i))));
79                    self.set(idx, val)
80                }
81            }
82            Self::Direct(vals) => {
83                let old = vals[idx];
84                vals[idx] = val;
85                old
86            }
87        }
88    }
89
90    pub(super) fn shrink_to_fit(&mut self) {
91        match self {
92            Self::Single(_) => {}
93            Self::Indirect(ind) => {
94                let mut new_ind = Indirect {
95                    palette: ArrayVec::new(),
96                    indices: [0; HALF_LEN],
97                };
98
99                for i in 0..LEN {
100                    new_ind.set(i, ind.get(i));
101                }
102
103                if new_ind.palette.len() == 1 {
104                    *self = Self::Single(new_ind.palette[0]);
105                } else {
106                    **ind = new_ind;
107                }
108            }
109            Self::Direct(dir) => {
110                let mut ind = Indirect {
111                    palette: ArrayVec::new(),
112                    indices: [0; HALF_LEN],
113                };
114
115                for (i, val) in dir.iter().copied().enumerate() {
116                    if ind.set(i, val).is_none() {
117                        return;
118                    }
119                }
120
121                *self = if ind.palette.len() == 1 {
122                    Self::Single(ind.palette[0])
123                } else {
124                    Self::Indirect(Box::new(ind))
125                };
126            }
127        }
128    }
129
130    /// Encodes the paletted container in the format that Minecraft expects.
131    ///
132    /// - **`writer`**: The [`Write`] instance to write the paletted container
133    ///   to.
134    /// - **`to_bits`**: A function to convert the element type to bits. The
135    ///   output must be less than two to the power of `direct_bits`.
136    /// - **`min_indirect_bits`**: The minimum number of bits used to represent
137    ///   the element type in the indirect representation. If the bits per index
138    ///   is lower, it will be rounded up to this.
139    /// - **`max_indirect_bits`**: The maximum number of bits per element
140    ///   allowed in the indirect representation. Any higher than this will
141    ///   force conversion to the direct representation while encoding.
142    /// - **`direct_bits`**: The minimum number of bits required to represent
143    ///   all instances of the element type. If `N` is the total number of
144    ///   possible values, then `DIRECT_BITS` is `floor(log2(N - 1)) + 1`.
145    pub(super) fn encode_mc_format<W, F>(
146        &self,
147        mut writer: W,
148        mut to_bits: F,
149        min_indirect_bits: usize,
150        max_indirect_bits: usize,
151        direct_bits: usize,
152    ) -> anyhow::Result<()>
153    where
154        W: Write,
155        F: FnMut(T) -> u64,
156    {
157        debug_assert!(min_indirect_bits <= 4);
158        debug_assert!(min_indirect_bits <= max_indirect_bits);
159        debug_assert!(max_indirect_bits <= 64);
160        debug_assert!(direct_bits <= 64);
161
162        match self {
163            Self::Single(val) => {
164                // Bits per entry
165                0_u8.encode(&mut writer)?;
166
167                // Palette
168                VarInt(to_bits(*val) as i32).encode(&mut writer)?;
169
170                // Number of longs
171                VarInt(0).encode(writer)?;
172            }
173            Self::Indirect(ind) => {
174                let bits_per_entry = min_indirect_bits.max(bit_width(ind.palette.len() - 1));
175
176                // Encode as direct if necessary.
177                if bits_per_entry > max_indirect_bits {
178                    // Bits per entry
179                    (direct_bits as u8).encode(&mut writer)?;
180
181                    // Number of longs in data array.
182                    VarInt(compact_u64s_len(LEN, direct_bits) as i32).encode(&mut writer)?;
183                    // Data array
184                    encode_compact_u64s(
185                        writer,
186                        (0..LEN).map(|i| to_bits(ind.get(i))),
187                        direct_bits,
188                    )?;
189                } else {
190                    // Bits per entry
191                    (bits_per_entry as u8).encode(&mut writer)?;
192
193                    // Palette len
194                    VarInt(ind.palette.len() as i32).encode(&mut writer)?;
195                    // Palette
196                    for val in &ind.palette {
197                        VarInt(to_bits(*val) as i32).encode(&mut writer)?;
198                    }
199
200                    // Number of longs in data array.
201                    VarInt(compact_u64s_len(LEN, bits_per_entry) as i32).encode(&mut writer)?;
202                    // Data array
203                    encode_compact_u64s(
204                        writer,
205                        ind.indices
206                            .iter()
207                            .copied()
208                            .flat_map(|byte| [byte & 0b1111, byte >> 4])
209                            .map(u64::from)
210                            .take(LEN),
211                        bits_per_entry,
212                    )?;
213                }
214            }
215            Self::Direct(dir) => {
216                // Bits per entry
217                (direct_bits as u8).encode(&mut writer)?;
218
219                // Number of longs in data array.
220                VarInt(compact_u64s_len(LEN, direct_bits) as i32).encode(&mut writer)?;
221                // Data array
222                encode_compact_u64s(writer, dir.iter().copied().map(to_bits), direct_bits)?;
223            }
224        }
225
226        Ok(())
227    }
228}
229
230impl<T: Copy + Eq + Default, const LEN: usize, const HALF_LEN: usize> Default
231    for PalettedContainer<T, LEN, HALF_LEN>
232{
233    fn default() -> Self {
234        Self::new()
235    }
236}
237
238impl<T: Copy + Eq + Default, const LEN: usize, const HALF_LEN: usize> Indirect<T, LEN, HALF_LEN> {
239    pub(super) fn get(&self, idx: usize) -> T {
240        let palette_idx = (self.indices[idx / 2] >> (idx % 2 * 4)) & 0b1111;
241        self.palette[palette_idx as usize]
242    }
243
244    pub(super) fn set(&mut self, idx: usize, val: T) -> Option<T> {
245        let palette_idx = if let Some(i) = self.palette.iter().position(|v| *v == val) {
246            i
247        } else {
248            self.palette.try_push(val).ok()?;
249            self.palette.len() - 1
250        };
251
252        let old_val = self.get(idx);
253        let u8 = &mut self.indices[idx / 2];
254        let shift = idx % 2 * 4;
255        *u8 = (*u8 & !(0b1111 << shift)) | ((palette_idx as u8) << shift);
256        Some(old_val)
257    }
258}
259
260#[inline]
261fn compact_u64s_len(vals_count: usize, bits_per_val: usize) -> usize {
262    let vals_per_u64 = 64 / bits_per_val;
263    vals_count.div_ceil(vals_per_u64)
264}
265
266#[inline]
267fn encode_compact_u64s(
268    mut w: impl Write,
269    mut vals: impl Iterator<Item = u64>,
270    bits_per_val: usize,
271) -> anyhow::Result<()> {
272    debug_assert!(bits_per_val <= 64);
273
274    let vals_per_u64 = 64 / bits_per_val;
275
276    loop {
277        let mut n = 0;
278        for i in 0..vals_per_u64 {
279            match vals.next() {
280                Some(val) => {
281                    debug_assert!(val < 2_u128.pow(bits_per_val as u32) as u64);
282                    n |= val << (i * bits_per_val);
283                }
284                None if i > 0 => return n.encode(&mut w),
285                None => return Ok(()),
286            }
287        }
288        n.encode(&mut w)?;
289    }
290}
291
292#[cfg(test)]
293mod tests {
294    use rand::Rng;
295
296    use super::*;
297
298    fn check<T: Copy + Eq + Default, const LEN: usize, const HALF_LEN: usize>(
299        p: &PalettedContainer<T, LEN, HALF_LEN>,
300        s: &[T],
301    ) -> bool {
302        assert_eq!(s.len(), LEN);
303        (0..LEN).all(|i| p.get(i) == s[i])
304    }
305
306    #[test]
307    fn random_assignments() {
308        const LEN: usize = 100;
309        let range = 0..64;
310
311        let mut rng = rand::thread_rng();
312
313        for _ in 0..20 {
314            let mut p = PalettedContainer::<u32, LEN, { LEN / 2 }>::new();
315
316            let init = rng.gen_range(range.clone());
317
318            p.fill(init);
319            let mut a = [init; LEN];
320
321            assert!(check(&p, &a));
322
323            let mut rng = rand::thread_rng();
324
325            for _ in 0..LEN * 10 {
326                let idx = rng.gen_range(0..LEN);
327                let val = rng.gen_range(range.clone());
328
329                assert_eq!(p.get(idx), p.set(idx, val));
330                assert_eq!(val, p.get(idx));
331                a[idx] = val;
332
333                p.shrink_to_fit();
334
335                assert!(check(&p, &a));
336            }
337        }
338    }
339}