use std::collections::HashMap;
use std::ffi::CString;
use std::hash::Hash;
use bytes::Buf;
use enumflags2::{BitFlag, BitFlags};
use num_traits::FromPrimitive;
use crate::Address;
pub(crate) trait BufExt: Buf {
fn get_address(&mut self) -> Address {
Address::from(self.get_array_u8())
}
fn get_array_u8<const N: usize>(&mut self) -> [u8; N] {
let mut arr = [0u8; N];
self.copy_to_slice(&mut arr[..]);
arr
}
fn get_vec_u8(&mut self, len: usize) -> Vec<u8> {
let mut ret = vec![0; len];
self.copy_to_slice(ret.as_mut_slice());
ret
}
fn get_bool(&mut self) -> bool {
self.get_u8() != 0
}
fn get_primitive_u8<T: FromPrimitive>(&mut self) -> T {
FromPrimitive::from_u8(self.get_u8()).unwrap()
}
fn get_primitive_u16_le<T: FromPrimitive>(&mut self) -> T {
FromPrimitive::from_u16(self.get_u16_le()).unwrap()
}
fn get_flags_u8<T: BitFlag<Numeric = u8>>(&mut self) -> BitFlags<T> {
BitFlags::<T, u8>::from_bits_truncate(self.get_u8())
}
fn get_flags_u16_le<T: BitFlag<Numeric = u16>>(&mut self) -> BitFlags<T> {
BitFlags::from_bits_truncate(self.get_u16_le())
}
fn get_flags_u32_le<T: BitFlag<Numeric = u32>>(&mut self) -> BitFlags<T> {
BitFlags::from_bits_truncate(self.get_u32_le())
}
fn get_c_string(&mut self) -> CString {
let mut bytes = vec![];
let mut current = self.get_u8();
while current != 0 && self.has_remaining() {
bytes.push(current);
current = self.get_u8();
}
unsafe { CString::from_vec_unchecked(bytes) }
}
fn get_tlv_map<T: FromPrimitive + Eq + Hash>(&mut self) -> HashMap<T, Vec<u8>> {
let mut parameters = HashMap::new();
while self.has_remaining() {
let parameter_type: T = self.get_primitive_u16_le();
let value_size = self.get_u8() as usize;
parameters.insert(parameter_type, self.get_vec_u8(value_size));
}
parameters
}
}
impl<T: Buf> BufExt for T {}
pub(crate) fn check_error(value: libc::c_int) -> Result<libc::c_int, std::io::Error> {
if value < 0 {
Err(std::io::Error::last_os_error())
} else {
Ok(value)
}
}