1use std::io;
2use std::ops::Deref;
3
4use base64::Engine;
5use scuffle_bytes_util::BitWriter;
6use scuffle_bytes_util::zero_copy::{Deserialize, Serialize, ZeroCopyReader};
7
8use crate::IsoSized;
9
10#[derive(Debug, PartialEq, Eq)]
14pub struct Utf8String(pub String);
15
16impl From<String> for Utf8String {
17 fn from(string: String) -> Self {
18 Utf8String(string)
19 }
20}
21
22impl From<Utf8String> for String {
23 fn from(utf8_string: Utf8String) -> Self {
24 utf8_string.0
25 }
26}
27
28impl Deref for Utf8String {
29 type Target = str;
30
31 fn deref(&self) -> &Self::Target {
32 &self.0
33 }
34}
35
36impl<'a> Deserialize<'a> for Utf8String {
37 fn deserialize<R>(mut reader: R) -> io::Result<Self>
38 where
39 R: ZeroCopyReader<'a>,
40 {
41 let mut bytes = Vec::new();
42
43 loop {
44 let byte = u8::deserialize(&mut reader)?;
45 if byte == 0 {
46 break;
47 }
48 bytes.push(byte);
49 }
50
51 let string =
52 String::from_utf8(bytes).map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8 sequence"))?;
53 Ok(Utf8String(string))
54 }
55}
56
57impl Serialize for Utf8String {
58 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
59 where
60 W: std::io::Write,
61 {
62 writer.write_all(self.0.as_bytes())?;
63 writer.write_all(&[0])?;
64 Ok(())
65 }
66}
67
68impl IsoSized for Utf8String {
69 fn size(&self) -> usize {
70 self.0.len() + 1
71 }
72}
73
74#[derive(Debug, PartialEq, Eq)]
78pub struct Base64String(pub Vec<u8>);
79
80impl Deref for Base64String {
81 type Target = [u8];
82
83 fn deref(&self) -> &Self::Target {
84 &self.0
85 }
86}
87
88impl<'a> Deserialize<'a> for Base64String {
89 fn deserialize<R>(mut reader: R) -> io::Result<Self>
90 where
91 R: ZeroCopyReader<'a>,
92 {
93 let mut bytes = Vec::new();
94
95 loop {
96 let byte = u8::deserialize(&mut reader)?;
97 if byte == 0 {
98 break;
99 }
100 bytes.push(byte);
101 }
102
103 let data = base64::prelude::BASE64_STANDARD
104 .decode(bytes)
105 .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, format!("Base64 decode error: {e}")))?;
106 Ok(Base64String(data))
107 }
108}
109
110impl Serialize for Base64String {
111 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
112 where
113 W: std::io::Write,
114 {
115 let encoded = base64::prelude::BASE64_STANDARD.encode(&self.0);
116 writer.write_all(encoded.as_bytes())?;
117 writer.write_all(&[0])?;
118 Ok(())
119 }
120}
121
122impl IsoSized for Base64String {
123 fn size(&self) -> usize {
124 base64::prelude::BASE64_STANDARD.encode(&self.0).len() + 1
125 }
126}
127
128#[derive(Debug, PartialEq, Eq)]
132pub struct Utf8List(pub Vec<String>);
133
134impl<'a> Deserialize<'a> for Utf8List {
135 fn deserialize<R>(mut reader: R) -> io::Result<Self>
136 where
137 R: ZeroCopyReader<'a>,
138 {
139 let mut strings = Vec::new();
140
141 'list: loop {
142 let mut bytes = Vec::new();
143
144 'string: loop {
145 let byte = u8::deserialize(&mut reader)?;
146 if byte == b' ' {
147 break 'string;
148 } else if byte == 0 {
149 break 'list;
150 }
151 bytes.push(byte);
152 }
153
154 let string = String::from_utf8(bytes)
155 .map_err(|_| io::Error::new(io::ErrorKind::InvalidData, "Invalid UTF-8 sequence"))?;
156
157 strings.push(string);
158 }
159
160 Ok(Self(strings))
161 }
162}
163
164impl Serialize for Utf8List {
165 fn serialize<W>(&self, mut writer: W) -> io::Result<()>
166 where
167 W: std::io::Write,
168 {
169 for string in &self.0 {
170 writer.write_all(string.as_bytes())?;
171 writer.write_all(b" ")?;
172 }
173 writer.write_all(&[0])?;
174
175 Ok(())
176 }
177}
178
179impl IsoSized for Utf8List {
180 fn size(&self) -> usize {
181 self.0.iter().map(|s| s.len() + 1).sum::<usize>() + 1
182 }
183}
184
185#[derive(Debug, Clone, Copy, PartialEq, Eq)]
189pub struct Langauge(pub [u8; 3]);
190
191impl Langauge {
192 pub const UNDETERMINED: Self = Self([0x15, 0x0E, 0x04]); }
195
196impl<'a> Deserialize<'a> for Langauge {
197 fn deserialize<R>(reader: R) -> std::io::Result<Self>
198 where
199 R: scuffle_bytes_util::zero_copy::ZeroCopyReader<'a>,
200 {
201 let language = u16::deserialize(reader)?;
203 let language = [
204 ((language >> 10) & 0b11111) as u8,
205 ((language >> 5) & 0b11111) as u8,
206 (language & 0b11111) as u8,
207 ];
208
209 Ok(Langauge(language))
210 }
211}
212
213impl Serialize for Langauge {
214 fn serialize<W>(&self, writer: W) -> std::io::Result<()>
215 where
216 W: std::io::Write,
217 {
218 let mut bit_writer = BitWriter::new(writer);
219 bit_writer.write_bit(false)?;
220 bit_writer.write_bits(self.0[0] as u64, 5)?;
221 bit_writer.write_bits(self.0[1] as u64, 5)?;
222 bit_writer.write_bits(self.0[2] as u64, 5)?;
223 Ok(())
224 }
225}
226
227impl IsoSized for Langauge {
228 fn size(&self) -> usize {
229 2
230 }
231}
232
233impl Langauge {
234 pub fn code(&self) -> [char; 3] {
236 [
237 (self.0[0] + 0x60) as char,
238 (self.0[1] + 0x60) as char,
239 (self.0[2] + 0x60) as char,
240 ]
241 }
242}