pelite/util/
mod.rs

1/*!
2Utilities and other tidbits.
3*/
4
5use std::prelude::v1::*;
6
7mod c_str;
8#[allow(dead_code)]
9mod wide_str;
10mod guid;
11mod align;
12
13#[cfg(feature = "serde")]
14pub(crate) mod serde_helper;
15
16pub use self::c_str::CStr;
17// pub use self::wide_str::WideStr;
18pub(crate) use self::wide_str::FmtUtf16;
19pub use self::align::*;
20
21/// Converts from a byte slice to a string.
22pub trait FromBytes {
23	/// Minimum size argument.
24	const MIN_SIZE_OF: usize;
25	/// Alignment argument.
26	const ALIGN_OF: usize;
27	/// Converts from a byte slice to a string.
28	///
29	/// # Safety
30	///
31	/// The given byte slice must have the minimum size and alignment as specified.
32	unsafe fn from_bytes(bytes: &[u8]) -> Option<&Self>;
33}
34
35/// Splits a slice at the point defined by the callback.
36#[inline]
37pub(crate) fn split_f<T, F: FnMut(&T) -> bool>(slice: &[T], f: F) -> (&[T], &[T]) {
38	let i = slice.iter().position(f).unwrap_or(slice.len());
39	(&slice[..i], &slice[i..])
40}
41
42/// Reads an optionally nul-terminated string from byte buffer.
43///
44/// Returns the slice split before the nul byte and the whole slice if no nul byte is found.
45///
46/// Analog to the `strn*` family of C string functions.
47///
48/// # Examples
49///
50/// ```
51/// use pelite::util::strn;
52///
53/// let buf: &[u8; 8] = b"STRING\0\0";
54/// assert_eq!(strn(buf), b"STRING");
55///
56/// let buf: &[u8; 4] = b"FOUR";
57/// assert_eq!(strn(buf), b"FOUR");
58/// ```
59#[inline]
60pub fn strn(buf: &[u8]) -> &[u8] {
61	split_f(buf, |&byte| byte == 0).0
62}
63
64// Trim nul bytes from the end
65pub(crate) fn trimn(buf: &[u8]) -> &[u8] {
66	let mut len = buf.len();
67	while len > 0 {
68		if buf[len - 1] != 0 {
69			break;
70		}
71		len -= 1;
72	}
73	&buf[..len]
74}
75
76/// Parses an optionally nul-terminated string from byte buffer.
77pub(crate) fn parsen(buf: &[u8]) -> Result<&str, &[u8]> {
78	std::str::from_utf8(trimn(buf)).map_err(|_| buf)
79}
80
81/// Reads an optionally nul-terminated wide char string from buffer.
82///
83/// Returns the slice split before the nul word and the whole slice if no nul word is found.
84///
85/// Analog to the `wcsn*` family of C string functions.
86///
87/// # Examples
88///
89/// ```
90/// use pelite::util::wstrn;
91///
92/// let buf: [u16; 8] = [83, 84, 82, 73, 78, 71, 0, 0];
93/// assert_eq!(wstrn(&buf), &[83, 84, 82, 73, 78, 71]);
94///
95/// let buf: [u16; 4] = [70, 79, 85, 82];
96/// assert_eq!(wstrn(&buf), &[70, 79, 85, 82]);
97/// ```
98#[inline]
99pub fn wstrn(buf: &[u16]) -> &[u16] {
100	split_f(buf, |&word| word == 0).0
101}
102
103/// Bits of entropy represented in a given byte slice.
104#[cfg(feature = "std")]
105pub fn shannon_entropy(data: &[u8]) -> f64 {
106	let mut map = [0usize; 256];
107
108	for &byte in data {
109		map[byte as usize] += 1;
110	}
111
112	let mut result = 0.0;
113	let len = data.len() as f64;
114	for &item in &map[..] {
115		if item != 0 {
116			let freq = item as f64 / len;
117			result -= freq * freq.log2();
118		}
119	}
120
121	result
122}
123
124/// Extends the given Vec with a number of additional elements initialised by the callable.
125///
126/// # Safety
127///
128/// The callback is passed uninitialized memory, take care when writing to it.
129/// When returning all the elements in the slice passed to the callable _must_ be initialised.
130///
131/// The underlying Vec is only extended once the callable returns without panicking.
132/// If the callable panics, any already initialised elements are lost and leaked.
133pub(crate) unsafe fn extend_in_place<'a, T, F: FnMut(&'a mut [T])>(vec: &'a mut Vec<T>, additional: usize, mut f: F) {
134	let vec_len = vec.len();
135	if vec_len + additional > vec.capacity() {
136		vec.reserve(additional);
137	}
138	f(std::slice::from_raw_parts_mut(vec.as_mut_ptr().offset(vec_len as isize), additional));
139	vec.set_len(vec_len + additional);
140}