aboutsummaryrefslogtreecommitdiff
path: root/src/deserialize.rs
blob: 044560db77e041aa3051d83123d1edebda2ea42c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
use crate::types::VarInt;
use std::fmt;
use std::string::FromUtf8Error;

pub enum DeserializeErr {
    Eof,
    VarNumTooLong(Vec<u8>),
    NegativeLength(VarInt),
    BadStringEncoding(FromUtf8Error),
    InvalidBool(u8),
    NbtUnknownTagType(u8),
    NbtBadLength(isize),
    NbtInvalidStartTag(u8),
    CannotUnderstandValue(String),
    FailedJsonDeserialize(String),
}

impl fmt::Display for DeserializeErr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        use DeserializeErr::*;
        match self {
            Eof => f.write_str("unexpected eof"),
            VarNumTooLong(data) => {
                f.write_fmt(format_args!("var num is too long: data={:?}", data))
            }
            NegativeLength(data) => {
                f.write_fmt(format_args!("negative length encountered {:?}", data))
            }
            BadStringEncoding(data) => f.write_fmt(format_args!(
                "failed to decode string, utf error: {:?}",
                data
            )),
            InvalidBool(value) => f.write_fmt(format_args!(
                "could not decode boolean, unexpected byte: {:?}",
                value
            )),
            NbtUnknownTagType(data) => f.write_fmt(format_args!("nbt: bad tag type {}", data)),
            NbtBadLength(data) => f.write_fmt(format_args!("nbt: bad length {:?}", data)),
            NbtInvalidStartTag(data) => {
                f.write_fmt(format_args!("nbt: unexpected start tag id: {:?}", data))
            }
            CannotUnderstandValue(data) => {
                f.write_fmt(format_args!("cannot understand value: {:?}", data))
            }
            FailedJsonDeserialize(data) => {
                f.write_fmt(format_args!("failed to deserialize json: {:?}", data))
            }
        }
    }
}
impl fmt::Debug for DeserializeErr {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        <dyn fmt::Display>::fmt(self, f)
    }
}

impl std::error::Error for DeserializeErr {}

impl<'b, R> Into<DeserializeResult<'b, R>> for DeserializeErr {
    #[inline]
    fn into(self) -> DeserializeResult<'b, R> {
        Err(self)
    }
}

pub struct Deserialized<'b, R> {
    pub value: R,
    pub data: &'b [u8],
}

impl<'b, R> Into<DeserializeResult<'b, R>> for Deserialized<'b, R> {
    #[inline]
    fn into(self) -> DeserializeResult<'b, R> {
        Ok(self)
    }
}

impl<'b, R> Deserialized<'b, R> {
    #[inline]
    pub fn create(value: R, data: &'b [u8]) -> Self {
        Deserialized { value, data }
    }

    #[inline]
    pub fn ok(value: R, rest: &'b [u8]) -> DeserializeResult<'b, R> {
        Self::create(value, rest).into()
    }

    #[inline]
    pub fn replace<T>(self, other: T) -> Deserialized<'b, T> {
        Deserialized {
            value: other,
            data: self.data,
        }
    }

    #[inline]
    pub fn map<F, T>(self, f: F) -> Deserialized<'b, T>
    where
        F: FnOnce(R) -> T,
    {
        Deserialized {
            value: f(self.value),
            data: self.data,
        }
    }

    #[inline]
    pub fn try_map<F, T>(self, f: F) -> DeserializeResult<'b, T>
    where
        F: FnOnce(R) -> Result<T, DeserializeErr>,
    {
        match f(self.value) {
            Ok(new_value) => Ok(Deserialized {
                value: new_value,
                data: self.data,
            }),
            Err(err) => Err(err),
        }
    }

    #[inline]
    pub fn and_then<F, T>(self, f: F) -> DeserializeResult<'b, T>
    where
        F: FnOnce(R, &'b [u8]) -> DeserializeResult<'b, T>,
    {
        f(self.value, self.data)
    }
}

impl<'b, R> From<(R, &'b [u8])> for Deserialized<'b, R> {
    fn from(v: (R, &'b [u8])) -> Self {
        let (value, data) = v;
        Deserialized { value, data }
    }
}

pub type DeserializeResult<'b, R> = Result<Deserialized<'b, R>, DeserializeErr>;

pub trait Deserialize: Sized {
    fn mc_deserialize(data: &[u8]) -> DeserializeResult<Self>;
}