chunkedge_binary/impls/
other.rs1use 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 if r.first() == Some(&0) {
62 *r = &r[1..];
63 return Ok(Compound::new());
64 }
65
66 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}