luanti_protocol/types/
options.rs

1use crate::wire::{
2    deser::{Deserialize, DeserializeResult, Deserializer},
3    ser::{Serialize, SerializeResult, Serializer, VecSerializer},
4};
5
6/// Option is used for optional values at the end of a structure.
7/// Once Option is used, all following must be Option as well.
8impl<T: Serialize> Serialize for Option<T>
9where
10    <T as Serialize>::Input: Sized,
11{
12    type Input = Option<T::Input>;
13    fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
14        match value {
15            Some(value) => <T as Serialize>::serialize(value, ser),
16            None => Ok(()),
17        }
18    }
19}
20
21impl<T: Deserialize> Deserialize for Option<T> {
22    type Output = Option<T::Output>;
23    fn deserialize(deser: &mut Deserializer<'_>) -> DeserializeResult<Self::Output> {
24        if deser.has_remaining() {
25            Ok(Some(<T as Deserialize>::deserialize(deser)?))
26        } else {
27            Ok(None)
28        }
29    }
30}
31
32// An Optional value controlled by a u16 size parameter.
33// Unlike Option, this can appear anywhere in the message.
34#[derive(Debug, Clone, PartialEq)]
35pub enum Option16<T> {
36    None,
37    Some(T),
38}
39impl<T: Serialize> Serialize for Option16<T>
40where
41    <T as Serialize>::Input: Sized,
42{
43    type Input = Option16<T::Input>;
44    fn serialize<S: Serializer>(value: &Self::Input, ser: &mut S) -> SerializeResult {
45        match value {
46            Option16::None => u16::serialize(&0_u16, ser),
47            Option16::Some(value) => {
48                let mut buf = VecSerializer::new(ser.context(), 64);
49                <T as Serialize>::serialize(value, &mut buf)?;
50                let buf = buf.take();
51                let num_bytes = u16::try_from(buf.len())?;
52                u16::serialize(&num_bytes, ser)?;
53                ser.write_bytes(&buf)?;
54                Ok(())
55            }
56        }
57    }
58}
59
60impl<T: Deserialize> Deserialize for Option16<T> {
61    type Output = Option16<T::Output>;
62    fn deserialize(deser: &mut Deserializer<'_>) -> DeserializeResult<Self::Output> {
63        match u16::deserialize(deser)? {
64            0 => Ok(Option16::None),
65            num_bytes => {
66                let mut buf = deser.slice(num_bytes as usize)?;
67                Ok(Option16::Some(<T as Deserialize>::deserialize(&mut buf)?))
68            }
69        }
70    }
71}