shen_nbt5/
writer.rs

1use crate::nbt_version::{BedrockDisk, BedrockNetVarInt, Java, JavaNetAfter1_20_2, NbtWriteTrait};
2use crate::{NbtError, NbtResult, NbtValue};
3
4/// 最简单的一集
5impl NbtWriteTrait for Java {
6    #[inline]
7    fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]) {
8        // 写好 tag 了, 直接写入信息
9        // 写入长度
10        writer.extend_from_slice(&(data.len() as i32).to_be_bytes());
11        // 写入数据
12        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        // 写好 tag 了, 直接写入信息
17        // 写入长度
18        writer.extend_from_slice(&(data.len() as i32).to_be_bytes());
19        // 写入数据
20        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        // 写好 tag 了, 直接写入信息
27        // 写入长度
28        writer.extend_from_slice(&(data.len() as i32).to_be_bytes());
29        // 写入数据
30        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        // 写入长度
37        writer.extend_from_slice(&(data.len() as u16).to_be_bytes());
38        // 写入数据
39        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            // 写入一个空的 tag
45            writer.extend_from_slice(&0i8.to_be_bytes());
46            // 写入空长度
47            writer.extend_from_slice(&0i32.to_be_bytes());
48            return Ok(());
49        }
50        // 遍历检查一遍所有的 tag 是否一致
51        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        // 写入 tag
56        writer.push(tag);
57        // 写入长度
58        writer.extend_from_slice(&(data.len() as i32).to_be_bytes());
59        // 写入数据
60        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        // 如果是列表元素时不用写入名字和key
85        // 写入自己的名字
86        if let Some(name) = name {
87            Self::write_nbt_string(writer, name);
88        }
89        for (key, value) in data {
90            // 写入 tag
91            writer.push(value.tag());
92            // 写入 key,如果是Compound就不写入,因为key就是名字
93            if let NbtValue::Compound(_, _) = value {
94            } else {
95                Self::write_nbt_string(writer, key)
96            };
97            // 写入 value
98            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        // 写入结束 tag
116        writer.push(0);
117        Ok(())
118    }
119    fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
120        // 写入 tag
121        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        // 写入 tag
132        buff.push(value.tag());
133        // 写入 key
134        Self::write_nbt_string(buff, name);
135        // 写入 value
136        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        // 写入 tag
165        match value {
166            NbtValue::Compound(_, data) => {
167                // 忽略名字
168                buff.push(value.tag());
169                for (key, value) in data {
170                    // 写入 tag
171                    buff.push(value.tag());
172                    // 写入 key
173                    Self::write_nbt_string(buff, key);
174                    // 写入 value
175                    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                // 写入结束 tag
193                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        // drop name
202        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
212/// 比较痛苦的一集
213impl NbtWriteTrait for BedrockDisk {
214    #[inline]
215    fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]) {
216        // 写入长度
217        writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
218        // 写入数据
219        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        // 写入长度
224        writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
225        // 写入数据
226        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        // 写入长度
233        writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
234        // 写入数据
235        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        // 写入长度
242        writer.extend_from_slice(&(data.len() as u16).to_le_bytes());
243        // 写入数据
244        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            // 写入一个空的 tag
250            writer.extend_from_slice(&0i8.to_le_bytes());
251            return Ok(());
252        }
253        // 遍历检查一遍所有的 tag 是否一致
254        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        // 写入 tag
259        writer.push(tag);
260        // 写入长度
261        writer.extend_from_slice(&(data.len() as i32).to_le_bytes());
262        // 写入数据
263        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        // 写入自己的名字
288        if let Some(name) = name {
289            Self::write_nbt_string(writer, name);
290        }
291        for (key, value) in data {
292            // 写入 tag
293            writer.push(value.tag());
294            // 写入 key
295            Self::write_nbt_string(writer, key);
296            // 写入 value
297            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        // 写入结束 tag
315        writer.push(0);
316        Ok(())
317    }
318
319    fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
320        // 写入 tag
321        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        // 写入 tag
337        buff.push(value.tag());
338        // 写入 key
339        Self::write_nbt_string(buff, name);
340        // 写入 value
341        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
420/// 最痛苦的一集
421impl NbtWriteTrait for BedrockNetVarInt {
422    fn write_i8_array(writer: &mut Vec<u8>, data: &[i8]) {
423        // zigzag var i32
424        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        // zigzag var i32
429        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        // zigzag var i32
436        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        // zigzag var i32
443        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            // 写入一个空的 tag
449            writer.extend_from_slice(&0i8.to_le_bytes());
450            return Ok(());
451        }
452        // 遍历检查一遍所有的 tag 是否一致
453        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        // 写入 tag
458        writer.push(tag);
459        // zigzag var i32
460        writer.extend_from_slice(&zigzag_var_i32_to_bytes(data.len() as i32));
461        // 写入数据
462        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        // 写入自己的名字
486        if let Some(name) = name {
487            Self::write_nbt_string(writer, name);
488        }
489        for (key, value) in data {
490            // 写入 tag
491            writer.push(value.tag());
492            // 写入 key
493            Self::write_nbt_string(writer, key);
494            // 写入 value
495            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        // 写入结束 tag
513        writer.push(0);
514        Ok(())
515    }
516
517    fn write_to(value: &NbtValue, buff: &mut Vec<u8>) -> NbtResult<()> {
518        // 写入 tag
519        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        // 写入 tag
534        buff.push(value.tag());
535        // 写入 key
536        Self::write_nbt_string(buff, name);
537        // 写入 value
538        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}