ussr_nbt/borrow/
util.rs

1use std::io;
2
3use super::{reader::Reader, writer::Writer};
4use crate::{endian::RawSlice, mutf8::mstr, num::Num, NbtReadError};
5
6#[inline]
7pub(super) fn read_str<'a>(reader: &mut impl Reader<'a>) -> Result<&'a mstr, NbtReadError> {
8    let len: u16 = reader.read_u16()?;
9    let buf: &[u8] = reader.read_slice(len as usize)?;
10    Ok(mstr::from_mutf8(buf))
11}
12
13#[inline]
14pub(super) fn read_slice_with_len<'a, T: Num>(
15    reader: &mut impl Reader<'a>,
16) -> Result<RawSlice<'a, T>, NbtReadError> {
17    let len: i32 = reader.read_i32()?;
18
19    if len <= 0 {
20        return Ok(RawSlice::new());
21    }
22
23    read_slice(reader, len as usize)
24}
25
26#[inline]
27pub(super) fn read_byte_slice_with_len<'a>(reader: &mut impl Reader<'a>) -> io::Result<&'a [u8]> {
28    let len: i32 = reader.read_i32()?;
29
30    if len <= 0 {
31        return Ok(&[]);
32    }
33
34    reader.read_slice(len as usize)
35}
36
37#[inline]
38pub(super) fn read_slice<'a, T: Num>(
39    reader: &mut impl Reader<'a>,
40    len: usize,
41) -> Result<RawSlice<'a, T>, NbtReadError> {
42    let buf: &[u8] = reader.read_slice(len * size_of::<T>())?;
43    Ok(RawSlice::from_bytes(buf))
44}
45
46#[inline]
47pub(super) fn write_str(writer: &mut impl Writer, str: &mstr) {
48    let len: u16 = str.len().min(u16::MAX as usize) as u16;
49    writer.write_u16(len);
50    writer.write_slice(&str.as_bytes()[..len as usize]);
51}
52
53#[inline]
54pub(super) fn write_slice<'a, T: Num>(writer: &mut impl Writer, slice: RawSlice<'a, T>) {
55    let len: i32 = (slice.len() as i32).min(i32::MAX);
56    writer.write_i32(len);
57    writer.write_slice(&slice.to_bytes()[..len as usize * size_of::<T>()]);
58}
59
60macro_rules! impl_tag {
61    ($name:ident, $( $(@$deref:tt)? + )? $type:ty) => {
62        paste! {
63            #[inline]
64            pub fn $name(&self) -> Option<$type> {
65                match self {
66                    Tag::[< $name:camel >](val) => Some(impl_tag!(@internal { $( $($deref)? + )? } { val } { *val })),
67                    _ => None,
68                }
69            }
70
71            impl_tag!(@internal { $( $($deref)? + )? } {} {
72                #[inline]
73                pub fn [< $name _mut >](&mut self) -> Option<&mut $type> {
74                    match self {
75                        Tag::[< $name:camel >](val) => Some(val),
76                        _ => None,
77                    }
78                }
79
80                #[inline]
81                pub fn [< into_ $name >](self) -> Option<$type> {
82                    match self {
83                        Tag::[< $name:camel >](val) => Some(val),
84                        _ => None,
85                    }
86                }
87            });
88
89        }
90    };
91    ( @internal {   } { $($then:tt)* } { $($else:tt)* } ) => { $($then)* };
92    ( @internal { + } { $($then:tt)* } { $($else:tt)* } ) => { $($else)* };
93}
94pub(super) use impl_tag;
95
96macro_rules! impl_list {
97    ($name:ident, $( $(@$deref:tt)? + )? $type:ty, $new:expr) => {
98        paste! {
99            #[inline]
100            pub fn [< $name s >](&self) -> Option<$type> {
101                match self {
102                    List::[< $name:camel >](val) => Some(impl_list!(@internal { $( $($deref)? + )? } { val } { *val })),
103                    List::Empty => Some(const { $new }),
104                    _ => None,
105                }
106            }
107        }
108    };
109    ( @internal {   } { $($then:tt)* } { $($else:tt)* } ) => { $($then)* };
110    ( @internal { + } { $($then:tt)* } { $($else:tt)* } ) => { $($else)* };
111}
112pub(super) use impl_list;