1#![no_std]
2use core::mem;
3use core::slice::from_raw_parts;
4use core::str::{from_utf8, from_utf8_unchecked};
5
6pub fn read<T: Pod>(input: &[u8]) -> &T
7{
8 assert!(mem::size_of::<T>() <= input.len());
9 let address = input.as_ptr() as usize;
10 assert!((address & (mem::align_of::<T>() - 1)) == 0);
11 unsafe
12 {
13 readunsafe(input)
14 }
15}
16
17pub fn readarray<T: Pod>(input: &[u8]) -> &[T]
18{
19 let tsize = mem::size_of::<T>();
20 assert!(tsize > 0, "[ERR] CANNOT READ ARRAYS OF ZERO-SIZED TYPES");
21 assert!(input.len() % tsize == 0);
22 let address = input.as_ptr() as usize;
23 assert!(address & (mem::align_of::<T>() - 1) == 0);
24 unsafe
25 {
26 read_arrayunsafe(input)
27 }
28}
29
30pub fn readstr(input: &[u8]) -> &str
31{
32 from_utf8(read_strbytes(input)).expect("[ERR] INVALID UTF-8 STRING")
33}
34
35pub fn readstr2null(input: &[u8]) -> StrReadIter
36{
37 StrReadIter
38 {
39 dat: input
40 }
41}
42
43pub unsafe trait Pod: Sized {}
44
45unsafe impl Pod for u8 {}
46unsafe impl Pod for u16 {}
47unsafe impl Pod for u32 {}
48unsafe impl Pod for u64 {}
49unsafe impl Pod for u128 {}
50unsafe impl Pod for i8 {}
51unsafe impl Pod for i16 {}
52unsafe impl Pod for i32 {}
53unsafe impl Pod for i64 {}
54unsafe impl Pod for i128 {}
55
56pub unsafe fn readunsafe<T: Sized>(input: &[u8]) -> &T
57{
58 &*(input.as_ptr() as *const T)
59}
60
61pub unsafe fn read_arrayunsafe<T: Sized>(input: &[u8]) -> &[T]
62{
63 let ptr = input.as_ptr() as *const T;
64 from_raw_parts(ptr, input.len() / mem::size_of::<T>())
65}
66
67pub unsafe fn read_strunsafe(input: &[u8]) -> &str
68{
69 from_utf8_unchecked(read_strbytes(input))
70}
71
72#[derive(Clone, Debug)]
73pub struct StrReadIter<'a>
74{
75 dat: &'a [u8],
76}
77
78impl<'a> Iterator for StrReadIter<'a>
79{
80 type Item = &'a str;
81 fn next(&mut self) -> Option<&'a str>
82 {
83 if self.dat.is_empty() || self.dat[0] == 0
84 {
85 return None;
86 }
87 let result = readstr(self.dat);
88 self.dat = &self.dat[result.len() + 1..];
89 Some(result)
90 }
91 fn size_hint(&self) -> (usize, Option<usize>)
92 {
93 (0, Some(self.dat.len() / 2))
94 }
95}
96
97fn read_strbytes(input: &[u8]) -> &[u8]
98{
99 for (i, byte) in input.iter().enumerate()
100 {
101 if *byte == 0
102 {
103 return &input[..i];
104 }
105 }
106 panic!("[ERR] NO NULL BYTE IN INPUT");
107}