valence_protocol/impls/
other.rs

1use std::io::Write;
2
3use anyhow::Context;
4use uuid::Uuid;
5use valence_generated::block::{BlockEntityKind, BlockKind, BlockState};
6use valence_generated::item::ItemKind;
7use valence_ident::{Ident, IdentError};
8use valence_nbt::Compound;
9
10use crate::{Decode, Encode, VarInt};
11
12impl<T: Encode> Encode for Option<T> {
13    fn encode(&self, mut w: impl Write) -> anyhow::Result<()> {
14        match self {
15            Some(t) => {
16                true.encode(&mut w)?;
17                t.encode(w)
18            }
19            None => false.encode(w),
20        }
21    }
22}
23
24impl<'a, T: Decode<'a>> Decode<'a> for Option<T> {
25    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
26        Ok(if bool::decode(r)? {
27            Some(T::decode(r)?)
28        } else {
29            None
30        })
31    }
32}
33
34impl Encode for Uuid {
35    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
36        self.as_u128().encode(w)
37    }
38}
39
40impl<'a> Decode<'a> for Uuid {
41    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
42        u128::decode(r).map(Uuid::from_u128)
43    }
44}
45
46impl Encode for Compound {
47    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
48        Ok(valence_nbt::to_binary(self, w, "")?)
49    }
50}
51
52impl Decode<'_> for Compound {
53    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
54        // Check for null compound.
55        if r.first() == Some(&0) {
56            *r = &r[1..];
57            return Ok(Compound::new());
58        }
59
60        // TODO: consider if we need to bound the input slice or add some other
61        // mitigation to prevent excessive memory usage on hostile input.
62        Ok(valence_nbt::from_binary(r)?.0)
63    }
64}
65
66impl<S: Encode> Encode for Ident<S> {
67    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
68        self.as_ref().encode(w)
69    }
70}
71
72impl<'a, S> Decode<'a> for Ident<S>
73where
74    S: Decode<'a>,
75    Ident<S>: TryFrom<S, Error = IdentError>,
76{
77    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
78        Ok(Ident::try_from(S::decode(r)?)?)
79    }
80}
81
82impl Encode for BlockState {
83    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
84        VarInt(i32::from(self.to_raw())).encode(w)
85    }
86}
87
88impl Decode<'_> for BlockState {
89    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
90        let id = VarInt::decode(r)?.0;
91        let errmsg = "invalid block state ID";
92
93        BlockState::from_raw(id.try_into().context(errmsg)?).context(errmsg)
94    }
95}
96
97impl Encode for BlockKind {
98    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
99        VarInt(i32::from(self.to_raw())).encode(w)
100    }
101}
102
103impl Decode<'_> for BlockKind {
104    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
105        let id = VarInt::decode(r)?.0;
106        let errmsg = "invalid block kind ID";
107
108        BlockKind::from_raw(id.try_into().context(errmsg)?).context(errmsg)
109    }
110}
111
112impl Encode for BlockEntityKind {
113    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
114        VarInt(self.id() as i32).encode(w)
115    }
116}
117
118impl<'a> Decode<'a> for BlockEntityKind {
119    fn decode(r: &mut &'a [u8]) -> anyhow::Result<Self> {
120        let id = VarInt::decode(r)?;
121        Self::from_id(id.0 as u32).with_context(|| format!("id {}", id.0))
122    }
123}
124
125impl Encode for ItemKind {
126    fn encode(&self, w: impl Write) -> anyhow::Result<()> {
127        VarInt(i32::from(self.to_raw())).encode(w)
128    }
129}
130
131impl Decode<'_> for ItemKind {
132    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
133        let id = VarInt::decode(r)?.0;
134        let errmsg = "invalid item ID";
135
136        ItemKind::from_raw(id.try_into().context(errmsg)?).context(errmsg)
137    }
138}