parse_binary/
lib.rs

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}