gel_protogen/
datatypes.rs

1use std::{marker::PhantomData, ops::Add, str::Utf8Error};
2pub use uuid::Uuid;
3
4use crate::{arrays::ArrayExt, Array, ZTArray};
5
6/// Represents the remainder of data in a message.
7#[derive(Copy, Debug, PartialEq, Eq, Default, Clone)]
8pub struct Rest<'a> {
9    buf: &'a [u8],
10}
11
12impl<'a> Rest<'a> {
13    pub fn new(buf: &'a [u8]) -> Self {
14        Self { buf }
15    }
16}
17
18impl Rest<'_> {}
19
20impl AsRef<[u8]> for Rest<'_> {
21    fn as_ref(&self) -> &[u8] {
22        self.buf
23    }
24}
25
26impl<'a> ArrayExt<'a> for Rest<'a> {
27    fn into_slice(self) -> &'a [u8] {
28        self.buf
29    }
30}
31
32impl std::ops::Deref for Rest<'_> {
33    type Target = [u8];
34    fn deref(&self) -> &Self::Target {
35        self.buf
36    }
37}
38
39impl PartialEq<[u8]> for Rest<'_> {
40    fn eq(&self, other: &[u8]) -> bool {
41        self.buf == other
42    }
43}
44
45impl<const N: usize> PartialEq<&[u8; N]> for Rest<'_> {
46    fn eq(&self, other: &&[u8; N]) -> bool {
47        self.buf == *other
48    }
49}
50
51impl PartialEq<&[u8]> for Rest<'_> {
52    fn eq(&self, other: &&[u8]) -> bool {
53        self.buf == *other
54    }
55}
56
57/// A zero-terminated string.
58pub type ZTString<'a> = ArrayString<'a, ZTArray<'a, u8>>;
59
60/// A length-prefixed string.
61pub type LString<'a> = ArrayString<'a, Array<'a, u32, u8>>;
62
63/// A string which consumes the remainder of the buffer.
64pub type RestString<'a> = ArrayString<'a, Rest<'a>>;
65
66/// A string, which lives on top of a given array type.
67#[derive(Copy, Clone, Default)]
68pub struct ArrayString<'a, A> {
69    buf: &'a [u8],
70    _phantom: PhantomData<A>,
71}
72
73impl<A> std::fmt::Debug for ArrayString<'_, A> {
74    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
75        String::from_utf8_lossy(self.buf).fmt(f)
76    }
77}
78
79impl<'a, A> ArrayString<'a, A> {
80    pub fn new(buf: &'a [u8]) -> Self {
81        Self {
82            buf,
83            _phantom: PhantomData,
84        }
85    }
86}
87
88impl<A> ArrayString<'_, A> {
89    pub fn to_owned(&self) -> Result<String, std::str::Utf8Error> {
90        std::str::from_utf8(self.buf).map(|s| s.to_owned())
91    }
92
93    pub fn to_str(&self) -> Result<&str, std::str::Utf8Error> {
94        std::str::from_utf8(self.buf)
95    }
96
97    pub fn to_string_lossy(&self) -> std::borrow::Cow<'_, str> {
98        String::from_utf8_lossy(self.buf)
99    }
100
101    pub fn to_bytes(&self) -> &[u8] {
102        self.buf
103    }
104}
105
106impl<A> PartialEq for ArrayString<'_, A> {
107    fn eq(&self, other: &Self) -> bool {
108        self.buf == other.buf
109    }
110}
111impl<A> Eq for ArrayString<'_, A> {}
112
113impl<A> PartialEq<str> for ArrayString<'_, A> {
114    fn eq(&self, other: &str) -> bool {
115        self.buf == other.as_bytes()
116    }
117}
118
119impl<A> PartialEq<&str> for ArrayString<'_, A> {
120    fn eq(&self, other: &&str) -> bool {
121        self.buf == other.as_bytes()
122    }
123}
124
125impl<'a, A> TryInto<&'a str> for ArrayString<'a, A> {
126    type Error = Utf8Error;
127    fn try_into(self) -> Result<&'a str, Self::Error> {
128        std::str::from_utf8(self.buf)
129    }
130}
131
132#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
133/// An encoded row value.
134pub enum Encoded<'a> {
135    #[default]
136    Null,
137    Value(&'a [u8]),
138}
139
140impl Encoded<'_> {
141    pub fn to_string_lossy(&self) -> std::borrow::Cow<'_, str> {
142        match self {
143            Encoded::Null => "".into(),
144            Encoded::Value(value) => String::from_utf8_lossy(value),
145        }
146    }
147}
148
149impl<'a> AsRef<Encoded<'a>> for Encoded<'a> {
150    fn as_ref(&self) -> &Encoded<'a> {
151        self
152    }
153}
154
155impl<'a> From<&'a [u8]> for Encoded<'a> {
156    fn from(value: &'a [u8]) -> Self {
157        Encoded::Value(value)
158    }
159}
160
161impl<'a> Into<Option<&'a [u8]>> for Encoded<'a> {
162    fn into(self) -> Option<&'a [u8]> {
163        match self {
164            Encoded::Null => None,
165            Encoded::Value(value) => Some(value),
166        }
167    }
168}
169
170impl<'a, 'b> Into<Option<&'a [u8]>> for &'b Encoded<'a> {
171    fn into(self) -> Option<&'a [u8]> {
172        match self {
173            Encoded::Null => None,
174            Encoded::Value(value) => Some(value),
175        }
176    }
177}
178
179impl Encoded<'_> {}
180
181impl PartialEq<str> for Encoded<'_> {
182    fn eq(&self, other: &str) -> bool {
183        self == &Encoded::Value(other.as_bytes())
184    }
185}
186
187impl PartialEq<&str> for Encoded<'_> {
188    fn eq(&self, other: &&str) -> bool {
189        self == &Encoded::Value(other.as_bytes())
190    }
191}
192
193impl PartialEq<[u8]> for Encoded<'_> {
194    fn eq(&self, other: &[u8]) -> bool {
195        self == &Encoded::Value(other)
196    }
197}
198
199impl PartialEq<&[u8]> for Encoded<'_> {
200    fn eq(&self, other: &&[u8]) -> bool {
201        self == &Encoded::Value(other)
202    }
203}
204
205#[derive(
206    Copy,
207    Clone,
208    Default,
209    derive_more::Debug,
210    derive_more::Display,
211    derive_more::Deref,
212    derive_more::DerefMut,
213    PartialEq,
214    Eq,
215)]
216#[display("{_0}")]
217#[debug("{_0}")]
218pub struct Length(pub i32);
219
220impl Add<usize> for Length {
221    type Output = usize;
222    fn add(self, other: usize) -> Self::Output {
223        (self.0 as isize + other as isize) as usize
224    }
225}
226
227/// A length-prefixed value.
228#[derive(
229    Copy,
230    Clone,
231    Default,
232    derive_more::Debug,
233    derive_more::Display,
234    derive_more::Deref,
235    derive_more::DerefMut,
236    PartialEq,
237    Eq,
238)]
239#[display("{_0}")]
240#[debug("{_0:?}")]
241pub struct LengthPrefixed<T>(pub T);