1use crate::nbt_version::{BedrockDisk, BedrockNetVarInt, Java, JavaNetAfter1_20_2, NbtWriteTrait};
2use crate::{NbtError, NbtResult, NbtValue};
3
4impl NbtWriteTrait for Java {
6 #[inline]
7 fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]) {
8 writer.extend_from_slice(&(data.len() as i32).to_be_bytes());
11 writer.extend_from_slice(data.iter().map(|x| *x as u8).collect::<Vec<u8>>().as_slice());
13 }
14 #[inline]
15 fn write_i32_array(writer: &mut Vec<u8>, data: &[i32]) {
16 writer.extend_from_slice(&(data.len() as i32).to_be_bytes());
19 writer.extend_from_slice(
21 &data.iter().map(|x| x.to_be_bytes()).collect::<Vec<[u8; 4]>>().concat(),
22 );
23 }
24 #[inline]
25 fn write_i64_array(writer: &mut Vec<u8>, data: &[i64]) {
26 writer.extend_from_slice(&(data.len() as i32).to_be_bytes());
29 writer.extend_from_slice(
31 &data.iter().map(|x| x.to_be_bytes()).collect::<Vec<[u8; 8]>>().concat(),
32 );
33 }
34 #[inline]
35 fn write_nbt_string(writer: &mut Vec<u8>, data: &str) {
36 writer.extend_from_slice(&(data.len() as u16).to_be_bytes());
38 writer.extend_from_slice(data.as_bytes());
40 }
41 #[inline]
42 fn write_list(writer: &mut Vec<u8>, data: &[NbtValue]) -> NbtResult<()> {
43 if data.is_empty() {
44 writer.extend_from_slice(&0i8.to_be_bytes());
46 writer.extend_from_slice(&0i32.to_be_bytes());
48 return Ok(());
49 }
50 let tag = data.first().unwrap().tag();
52 if !data.iter().all(|x| x.tag() == tag) {
53 return Err(NbtError::ListTypeNotSame(data.iter().map(|x| x.tag()).collect()));
54 }
55 writer.push(tag);
57 writer.extend_from_slice(&(data.len() as i32).to_be_bytes());
59 for i in data {
61 match i {
62 NbtValue::Byte(x) => writer.push(*x as u8),
63 NbtValue::Short(x) => writer.extend_from_slice(&x.to_be_bytes()),
64 NbtValue::Int(x) => writer.extend_from_slice(&x.to_be_bytes()),
65 NbtValue::Long(x) => writer.extend_from_slice(&x.to_be_bytes()),
66 NbtValue::Float(x) => writer.extend_from_slice(&x.to_be_bytes()),
67 NbtValue::Double(x) => writer.extend_from_slice(&x.to_be_bytes()),
68 NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
69 NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
70 NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
71 NbtValue::String(x) => Self::write_nbt_string(writer, x),
72 NbtValue::List(x) => Self::write_list(writer, x)?,
73 NbtValue::Compound(_, data) => Self::write_compound(writer, None, data)?,
74 }
75 }
76 Ok(())
77 }
78 #[inline]
79 fn write_compound(
80 writer: &mut Vec<u8>,
81 name: Option<&String>,
82 data: &[(String, NbtValue)],
83 ) -> NbtResult<()> {
84 if let Some(name) = name {
87 Self::write_nbt_string(writer, name);
88 }
89 for (key, value) in data {
90 writer.push(value.tag());
92 if let NbtValue::Compound(_, _) = value {
94 } else {
95 Self::write_nbt_string(writer, key)
96 };
97 match value {
99 NbtValue::Byte(x) => writer.push(*x as u8),
100 NbtValue::Short(x) => writer.extend_from_slice(&x.to_be_bytes()),
101 NbtValue::Int(x) => writer.extend_from_slice(&x.to_be_bytes()),
102 NbtValue::Long(x) => writer.extend_from_slice(&x.to_be_bytes()),
103 NbtValue::Float(x) => writer.extend_from_slice(&x.to_be_bytes()),
104 NbtValue::Double(x) => writer.extend_from_slice(&x.to_be_bytes()),
105 NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
106 NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
107 NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
108 NbtValue::String(x) => Self::write_nbt_string(writer, x),
109 NbtValue::List(x) => Self::write_list(writer, x)?,
110 NbtValue::Compound(name, data) => {
111 Self::write_compound(writer, name.as_ref(), data)?
112 }
113 }
114 }
115 writer.push(0);
117 Ok(())
118 }
119 fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
120 match value {
122 NbtValue::Compound(name, data) => {
123 buff.push(value.tag());
124 Self::write_compound(buff, name.as_ref(), data)?
125 }
126 x => return Err(NbtError::WrongRootType(x.tag())),
127 }
128 Ok(())
129 }
130 fn write_to_with_name(name: &str, value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
131 buff.push(value.tag());
133 Self::write_nbt_string(buff, name);
135 Self::write_to(value, buff)?;
137 Ok(())
138 }
139}
140
141impl NbtWriteTrait for JavaNetAfter1_20_2 {
142 #[inline]
143 fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]) { Java::write_i8_array(writer, data); }
144 #[inline]
145 fn write_i32_array(writer: &mut Vec<u8>, data: &[i32]) { Java::write_i32_array(writer, data); }
146 #[inline]
147 fn write_i64_array(writer: &mut Vec<u8>, data: &[i64]) { Java::write_i64_array(writer, data); }
148 #[inline]
149 fn write_nbt_string(writer: &mut Vec<u8>, data: &str) { Java::write_nbt_string(writer, data); }
150 #[inline]
151 fn write_list(writer: &mut Vec<u8>, data: &[NbtValue]) -> NbtResult<()> {
152 Java::write_list(writer, data)
153 }
154 #[inline]
155 fn write_compound(
156 writer: &mut Vec<u8>,
157 name: Option<&String>,
158 data: &[(String, NbtValue)],
159 ) -> NbtResult<()> {
160 Java::write_compound(writer, name, data)
161 }
162 #[inline]
163 fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
164 match value {
166 NbtValue::Compound(_, data) => {
167 buff.push(value.tag());
169 for (key, value) in data {
170 buff.push(value.tag());
172 Self::write_nbt_string(buff, key);
174 match value {
176 NbtValue::Byte(x) => buff.push(*x as u8),
177 NbtValue::Short(x) => buff.extend_from_slice(&x.to_be_bytes()),
178 NbtValue::Int(x) => buff.extend_from_slice(&x.to_be_bytes()),
179 NbtValue::Long(x) => buff.extend_from_slice(&x.to_be_bytes()),
180 NbtValue::Float(x) => buff.extend_from_slice(&x.to_be_bytes()),
181 NbtValue::Double(x) => buff.extend_from_slice(&x.to_be_bytes()),
182 NbtValue::ByteArray(x) => Self::write_i8_array(buff, x),
183 NbtValue::IntArray(x) => Self::write_i32_array(buff, x),
184 NbtValue::LongArray(x) => Self::write_i64_array(buff, x),
185 NbtValue::String(x) => Self::write_nbt_string(buff, x),
186 NbtValue::List(x) => Self::write_list(buff, x)?,
187 NbtValue::Compound(name, data) => {
188 Self::write_compound(buff, name.as_ref(), data)?
189 }
190 }
191 }
192 buff.push(0);
194 Ok(())
195 }
196 x => Err(NbtError::WrongRootType(x.tag())),
197 }
198 }
199 #[inline]
200 fn write_to_with_name(_name: &str, value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
201 JavaNetAfter1_20_2::write_to(value, buff)
203 }
204 #[inline]
205 fn to_bytes(value: &NbtValue) -> NbtResult<Vec<u8>> {
206 let mut buff = Vec::new();
207 JavaNetAfter1_20_2::write_to(value, &mut buff)?;
208 Ok(buff)
209 }
210}
211
212impl NbtWriteTrait for BedrockDisk {
214 #[inline]
215 fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]) {
216 writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
218 writer.extend_from_slice(data.iter().map(|x| *x as u8).collect::<Vec<u8>>().as_slice());
220 }
221 #[inline]
222 fn write_i32_array(writer: &mut Vec<u8>, data: &[i32]) {
223 writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
225 writer.extend_from_slice(
227 &data.iter().map(|x| x.to_le_bytes()).collect::<Vec<[u8; 4]>>().concat(),
228 );
229 }
230 #[inline]
231 fn write_i64_array(writer: &mut Vec<u8>, data: &[i64]) {
232 writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
234 writer.extend_from_slice(
236 &data.iter().map(|x| x.to_le_bytes()).collect::<Vec<[u8; 8]>>().concat(),
237 );
238 }
239 #[inline]
240 fn write_nbt_string(writer: &mut Vec<u8>, data: &str) {
241 writer.extend_from_slice(&(data.len() as u16).to_le_bytes());
243 writer.extend_from_slice(data.as_bytes());
245 }
246 #[inline]
247 fn write_list(writer: &mut Vec<u8>, data: &[NbtValue]) -> NbtResult<()> {
248 if data.is_empty() {
249 writer.extend_from_slice(&0i8.to_le_bytes());
251 return Ok(());
252 }
253 let tag = data.first().unwrap().tag();
255 if !data.iter().all(|x| x.tag() == tag) {
256 return Err(NbtError::ListTypeNotSame(data.iter().map(|x| x.tag()).collect()));
257 }
258 writer.push(tag);
260 writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
262 for i in data {
264 match i {
265 NbtValue::Byte(x) => writer.push(*x as u8),
266 NbtValue::Short(x) => writer.extend_from_slice(&x.to_le_bytes()),
267 NbtValue::Int(x) => writer.extend_from_slice(&x.to_le_bytes()),
268 NbtValue::Long(x) => writer.extend_from_slice(&x.to_le_bytes()),
269 NbtValue::Float(x) => writer.extend_from_slice(&x.to_le_bytes()),
270 NbtValue::Double(x) => writer.extend_from_slice(&x.to_le_bytes()),
271 NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
272 NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
273 NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
274 NbtValue::String(x) => Self::write_nbt_string(writer, x),
275 NbtValue::List(x) => Self::write_list(writer, x)?,
276 NbtValue::Compound(_, data) => Self::write_compound(writer, None, data)?,
277 }
278 }
279 Ok(())
280 }
281 #[inline]
282 fn write_compound(
283 writer: &mut Vec<u8>,
284 name: Option<&String>,
285 data: &[(String, NbtValue)],
286 ) -> NbtResult<()> {
287 if let Some(name) = name {
289 Self::write_nbt_string(writer, name);
290 }
291 for (key, value) in data {
292 writer.push(value.tag());
294 Self::write_nbt_string(writer, key);
296 match value {
298 NbtValue::Byte(x) => writer.push(*x as u8),
299 NbtValue::Short(x) => writer.extend_from_slice(&x.to_le_bytes()),
300 NbtValue::Int(x) => writer.extend_from_slice(&x.to_le_bytes()),
301 NbtValue::Long(x) => writer.extend_from_slice(&x.to_le_bytes()),
302 NbtValue::Float(x) => writer.extend_from_slice(&x.to_le_bytes()),
303 NbtValue::Double(x) => writer.extend_from_slice(&x.to_le_bytes()),
304 NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
305 NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
306 NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
307 NbtValue::String(x) => Self::write_nbt_string(writer, x),
308 NbtValue::List(x) => Self::write_list(writer, x)?,
309 NbtValue::Compound(name, data) => {
310 Self::write_compound(writer, name.as_ref(), data)?
311 }
312 }
313 }
314 writer.push(0);
316 Ok(())
317 }
318
319 fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
320 match value {
322 NbtValue::Compound(name, data) => {
323 buff.push(value.tag());
324 Self::write_compound(buff, name.as_ref(), data)?
325 }
326 NbtValue::List(data) => {
327 buff.push(value.tag());
328 Self::write_list(buff, data)?
329 }
330 x => return Err(NbtError::WrongRootType(x.tag())),
331 }
332 Ok(())
333 }
334
335 fn write_to_with_name(name: &str, value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
336 buff.push(value.tag());
338 Self::write_nbt_string(buff, name);
340 Self::write_to(value, buff)?;
342 Ok(())
343 }
344
345 fn to_bytes(value: &NbtValue) -> NbtResult<Vec<u8>> {
346 let mut buff = Vec::new();
347 BedrockDisk::write_to(value, &mut buff)?;
348 Ok(buff)
349 }
350}
351
352pub fn var_i32_to_bytes(value: i32) -> Vec<u8> {
353 let mut buff = Vec::new();
354 let mut value = value;
355 loop {
356 let mut temp = (value & 0b01111111) as u8;
357 value >>= 7;
358 if value != 0 {
359 temp |= 0b10000000;
360 }
361 buff.push(temp);
362 if value == 0 {
363 break;
364 }
365 }
366 buff
367}
368
369pub fn var_i64_to_bytes(value: i64) -> Vec<u8> {
370 let mut buff = Vec::new();
371 let mut value = value;
372 loop {
373 let mut temp = (value & 0b01111111) as u8;
374 value >>= 7;
375 if value != 0 {
376 temp |= 0b10000000;
377 }
378 buff.push(temp);
379 if value == 0 {
380 break;
381 }
382 }
383 buff
384}
385
386pub fn zigzag_var_i32_to_bytes(value: i32) -> Vec<u8> {
387 let mut buff = Vec::new();
388 let mut value = (value << 1) ^ (value >> 31);
389 loop {
390 let mut temp = (value & 0b01111111) as u8;
391 value >>= 7;
392 if value != 0 {
393 temp |= 0b10000000;
394 }
395 buff.push(temp);
396 if value == 0 {
397 break;
398 }
399 }
400 buff
401}
402
403pub fn zigzag_var_i64_to_bytes(value: i64) -> Vec<u8> {
404 let mut buff = Vec::new();
405 let mut value = (value << 1) ^ (value >> 63);
406 loop {
407 let mut temp = (value & 0b01111111) as u8;
408 value >>= 7;
409 if value != 0 {
410 temp |= 0b10000000;
411 }
412 buff.push(temp);
413 if value == 0 {
414 break;
415 }
416 }
417 buff
418}
419
420impl NbtWriteTrait for BedrockNetVarInt {
422 fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]) {
423 writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
425 writer.extend_from_slice(data.iter().map(|x| *x as u8).collect::<Vec<u8>>().as_slice());
426 }
427 fn write_i32_array(writer: &mut Vec<u8>, data: &[i32]) {
428 writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
430 writer.extend_from_slice(
431 &data.iter().map(|x| x.to_le_bytes()).collect::<Vec<[u8; 4]>>().concat(),
432 );
433 }
434 fn write_i64_array(writer: &mut Vec<u8>, data: &[i64]) {
435 writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
437 writer.extend_from_slice(
438 &data.iter().map(|x| x.to_le_bytes()).collect::<Vec<[u8; 8]>>().concat(),
439 );
440 }
441 fn write_nbt_string(writer: &mut Vec<u8>, data: &str) {
442 writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
444 writer.extend_from_slice(data.as_bytes());
445 }
446 fn write_list(writer: &mut Vec<u8>, data: &[NbtValue]) -> NbtResult<()> {
447 if data.is_empty() {
448 writer.extend_from_slice(&0i8.to_le_bytes());
450 return Ok(());
451 }
452 let tag = data.first().unwrap().tag();
454 if !data.iter().all(|x| x.tag() == tag) {
455 return Err(NbtError::ListTypeNotSame(data.iter().map(|x| x.tag()).collect()));
456 }
457 writer.push(tag);
459 writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
461 for i in data {
463 match i {
464 NbtValue::Byte(x) => writer.push(*x as u8),
465 NbtValue::Short(x) => writer.extend_from_slice(&x.to_le_bytes()),
466 NbtValue::Int(x) => writer.extend_from_slice(&x.to_le_bytes()),
467 NbtValue::Long(x) => writer.extend_from_slice(&x.to_le_bytes()),
468 NbtValue::Float(x) => writer.extend_from_slice(&x.to_le_bytes()),
469 NbtValue::Double(x) => writer.extend_from_slice(&x.to_le_bytes()),
470 NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
471 NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
472 NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
473 NbtValue::String(x) => Self::write_nbt_string(writer, x),
474 NbtValue::List(x) => Self::write_list(writer, x)?,
475 NbtValue::Compound(_, data) => Self::write_compound(writer, None, data)?,
476 }
477 }
478 Ok(())
479 }
480 fn write_compound(
481 writer: &mut Vec<u8>,
482 name: Option<&String>,
483 data: &[(String, NbtValue)],
484 ) -> NbtResult<()> {
485 if let Some(name) = name {
487 Self::write_nbt_string(writer, name);
488 }
489 for (key, value) in data {
490 writer.push(value.tag());
492 Self::write_nbt_string(writer, key);
494 match value {
496 NbtValue::Byte(x) => writer.push(*x as u8),
497 NbtValue::Short(x) => writer.extend_from_slice(&x.to_le_bytes()),
498 NbtValue::Int(x) => writer.extend_from_slice(&x.to_le_bytes()),
499 NbtValue::Long(x) => writer.extend_from_slice(&x.to_le_bytes()),
500 NbtValue::Float(x) => writer.extend_from_slice(&x.to_le_bytes()),
501 NbtValue::Double(x) => writer.extend_from_slice(&x.to_le_bytes()),
502 NbtValue::ByteArray(x) => Self::write_i8_array(writer, x),
503 NbtValue::IntArray(x) => Self::write_i32_array(writer, x),
504 NbtValue::LongArray(x) => Self::write_i64_array(writer, x),
505 NbtValue::String(x) => Self::write_nbt_string(writer, x),
506 NbtValue::List(x) => Self::write_list(writer, x)?,
507 NbtValue::Compound(name, data) => {
508 Self::write_compound(writer, name.as_ref(), data)?
509 }
510 }
511 }
512 writer.push(0);
514 Ok(())
515 }
516
517 fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
518 match value {
520 NbtValue::Compound(name, data) => {
521 buff.push(value.tag());
522 Self::write_compound(buff, name.as_ref(), data)?
523 }
524 NbtValue::List(data) => {
525 buff.push(value.tag());
526 Self::write_list(buff, data)?
527 }
528 x => return Err(NbtError::WrongRootType(x.tag())),
529 }
530 Ok(())
531 }
532 fn write_to_with_name(name: &str, value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
533 buff.push(value.tag());
535 Self::write_nbt_string(buff, name);
537 Self::write_to(value, buff)?;
539 Ok(())
540 }
541 fn to_bytes(value: &NbtValue) -> NbtResult<Vec<u8>> {
542 let mut buff = Vec::new();
543 BedrockNetVarInt::write_to(value, &mut buff)?;
544 Ok(buff)
545 }
546}