chunkedge_binary/impls/
other.rs

1use std::hash::Hash;
2use std::io::Write;
3
4use anyhow::Context;
5use chunkedge_generated::attributes::{EntityAttribute, EntityAttributeOperation};
6use chunkedge_generated::block::{BlockEntityKind, BlockKind, BlockState};
7use chunkedge_generated::item::ItemKind;
8use chunkedge_generated::registry_id::RegistryId;
9use chunkedge_ident::{Ident, IdentError};
10use chunkedge_nbt::compound::NetworkCompound;
11use chunkedge_nbt::Compound;
12use chunkedge_text::color::RgbColor;
13use indexmap::IndexMap;
14use uuid::Uuid;
15
16use crate::{Decode, Encode, VarInt};
17
18impl<T: Encode> Encode for Option<T> {
19    fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
20        match self {
21            Some(t) => {
22                true.encode(&mut w)?;
23                t.encode(w)
24            }
25            None => false.encode(w),
26        }
27    }
28}
29
30impl<'a, T: Decode<'a>> Decode<'a> for Option<T> {
31    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
32        Ok(if bool::decode(r)? {
33            Some(T::decode(r)?)
34        } else {
35            None
36        })
37    }
38}
39
40impl Encode for Uuid {
41    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
42        self.as_u128().encode(w)
43    }
44}
45
46impl<'a> Decode<'a> for Uuid {
47    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
48        u128::decode(r).map(Uuid::from_u128)
49    }
50}
51
52impl Encode for Compound {
53    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
54        Ok(chunkedge_nbt::to_binary(self, w, None::<&'static str>)?)
55    }
56}
57
58impl Decode<'_> for Compound {
59    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
60        // Check for null compound.
61        if r.first() == Some(&0) {
62            *r = &r[1..];
63            return Ok(Compound::new());
64        }
65
66        // TODO: consider if we need to bound the input slice or add some other
67        // mitigation to prevent excessive memory usage on hostile input.
68        Ok(chunkedge_nbt::from_binary(r)?.0)
69    }
70}
71
72impl Encode for NetworkCompound {
73    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
74        Ok(chunkedge_nbt::to_network_binary(&self.compound, w)?)
75    }
76}
77
78impl Decode<'_> for NetworkCompound {
79    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
80        Ok(NetworkCompound {
81            compound: chunkedge_nbt::from_network_binary(r)?,
82        })
83    }
84}
85
86impl<S: Encode> Encode for Ident<S> {
87    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
88        self.as_ref().encode(w)
89    }
90}
91
92impl<'a, S> Decode<'a> for Ident<S>
93where
94    S: Decode<'a>,
95    Ident<S>: TryFrom<S, Error = IdentError>,
96{
97    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
98        Ok(Ident::try_from(S::decode(r)?)?)
99    }
100}
101
102impl Encode for BlockState {
103    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
104        VarInt(i32::from(self.to_raw())).encode(w)
105    }
106}
107
108impl Decode<'_> for BlockState {
109    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
110        let id = VarInt::decode(r)?.0;
111        let errmsg = "invalid block state ID";
112
113        BlockState::from_raw(id.try_into().context(errmsg)?).context(errmsg)
114    }
115}
116
117impl Encode for BlockKind {
118    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
119        VarInt(i32::from(self.to_raw())).encode(w)
120    }
121}
122
123impl Decode<'_> for BlockKind {
124    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
125        let id = VarInt::decode(r)?.0;
126        let errmsg = "invalid block kind ID";
127
128        BlockKind::from_raw(id.try_into().context(errmsg)?).context(errmsg)
129    }
130}
131
132impl Encode for BlockEntityKind {
133    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
134        VarInt(self.id() as i32).encode(w)
135    }
136}
137
138impl<'a> Decode<'a> for BlockEntityKind {
139    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
140        let id = VarInt::decode(r)?;
141        Self::from_id(id.0 as u32).with_context(|| format!("id {}", id.0))
142    }
143}
144
145impl Encode for ItemKind {
146    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
147        VarInt(i32::from(self.to_raw())).encode(w)
148    }
149}
150
151impl Decode<'_> for ItemKind {
152    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
153        let id = VarInt::decode(r)?.0;
154        let errmsg = "invalid item ID";
155
156        ItemKind::from_raw(id.try_into().context(errmsg)?).context(errmsg)
157    }
158}
159
160impl Encode for RegistryId {
161    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
162        VarInt(self.id()).encode(w)
163    }
164}
165
166impl<'a> Decode<'a> for RegistryId {
167    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
168        let id = VarInt::decode(r)?;
169        Ok(RegistryId::new(id.0))
170    }
171}
172
173impl Encode for EntityAttributeOperation {
174    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
175        VarInt(*self as i32).encode(w)
176    }
177}
178
179impl Decode<'_> for EntityAttributeOperation {
180    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
181        match VarInt::decode(r)?.0 {
182            0 => Ok(EntityAttributeOperation::Add),
183            1 => Ok(EntityAttributeOperation::MultiplyTotal),
184            2 => Ok(EntityAttributeOperation::MultiplyBase),
185            _ => Err(anyhow::anyhow!("invalid entity attribute operation")),
186        }
187    }
188}
189
190impl Encode for EntityAttribute {
191    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
192        VarInt(i32::from(self.get_id())).encode(w)?;
193        Ok(())
194    }
195}
196
197impl<'a> Decode<'a> for EntityAttribute {
198    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
199        let id = VarInt::decode(r)?.0;
200        EntityAttribute::from_id(id as u8).context("invalid entity attribute ID")
201    }
202}
203
204impl Encode for RgbColor {
205    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
206        self.into_bits().encode(w)
207    }
208}
209
210impl Decode<'_> for RgbColor {
211    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
212        let color = u32::decode(r)?;
213        Ok(Self::from_bits(color))
214    }
215}
216
217impl<K: Encode, V: Encode> Encode for IndexMap<K, V> {
218    fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
219        VarInt(self.len() as i32).encode(&mut w)?;
220        for (key, value) in self {
221            key.encode(&mut w)?;
222            value.encode(&mut w)?;
223        }
224        Ok(())
225    }
226}
227
228impl<'a, K: Decode<'a> + Hash + Eq, V: Decode<'a>> Decode<'a> for IndexMap<K, V> {
229    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
230        let len = VarInt::decode(r)?.0 as usize;
231        let mut map = IndexMap::with_capacity(len);
232        for _ in 0..len {
233            let key = K::decode(r)?;
234            let value = V::decode(r)?;
235            map.insert(key, value);
236        }
237        Ok(map)
238    }
239}