pub mod can;
pub mod module_description;
pub mod root_file;
use crate::types::PduUniqueRespIdentifier;
use cfg_if::cfg_if;
use rand::RngExt;
use std::ffi::{CStr, c_char, c_void};
use std::fs::{File, OpenOptions};
use std::io::{BufReader, Cursor, Read, Seek};
use std::marker::PhantomData;
use std::num::NonZeroUsize;
use std::ops::{Deref, DerefMut};
use std::path::Path;
use std::ptr;
use std::ptr::NonNull;
use winreg::RegKey;
use winreg::enums::HKEY_LOCAL_MACHINE;
pub(crate) fn c_str(ptr: *const c_char) -> Option<String> {
NonNull::new(ptr as _)
.map(|wrapped_ptr| unsafe {
CStr::from_ptr(wrapped_ptr.as_ptr())
.to_string_lossy()
.into_owned()
})
.filter(|s| !s.is_empty())
}
pub(crate) fn get_bomless_file_reader(path: &Path) -> Result<BufReader<File>, std::io::Error> {
let file = OpenOptions::new().read(true).open(path)?;
let mut reader = BufReader::new(file);
let mut bom_header = [0u8; 3];
reader.read_exact(&mut bom_header)?;
if !bom_header.starts_with(&[239, 187, 191]) {
reader.rewind()?;
}
Ok(reader)
}
#[repr(C)]
pub(crate) struct PhantomRef<'a, T> {
pub data: T,
_marker: PhantomData<&'a ()>,
}
impl<'a, T> PhantomRef<'a, T> {
pub fn new(data: T) -> PhantomRef<'a, T> {
Self {
data,
_marker: PhantomData,
}
}
pub fn as_ptr(&self) -> *const T {
&self.data
}
pub fn as_mut_ptr(&mut self) -> *mut T {
&mut self.data
}
}
impl<'a, T> Deref for PhantomRef<'a, T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.data
}
}
#[derive(Debug)]
pub struct UnsafePtr<T>(pub *const T);
unsafe impl<T> Send for UnsafePtr<T> {}
unsafe impl<T> Sync for UnsafePtr<T> {}
#[derive(Debug)]
pub(crate) struct PhantomPtr<'a> {
pub ptr: *const c_void,
_marker: PhantomData<&'a ()>,
}
impl<'a> PhantomPtr<'a> {
pub fn new(ptr: *const c_void) -> Self {
Self {
ptr,
_marker: PhantomData,
}
}
pub fn as_ptr(&self) -> *const c_void {
self.ptr
}
pub fn as_mut_ptr(&self) -> *mut c_void {
self.ptr as _
}
}
#[derive(Debug, Clone)]
pub(crate) struct SendSync<T>(pub T);
unsafe impl<T> Send for SendSync<T> {}
unsafe impl<T> Sync for SendSync<T> {}
impl<T> Deref for SendSync<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<T> DerefMut for SendSync<T> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub fn ecu_name_to_unique_resp_id<S>(name: S) -> PduUniqueRespIdentifier
where
S: AsRef<str>,
{
murmur3::murmur3_32(&mut Cursor::new(name.as_ref()), 0).expect("murmur failed")
}
pub(crate) fn random_non_zero_usize() -> NonZeroUsize {
NonZeroUsize::new(rand::rng().random_range(1..=usize::MAX))
.expect("internal error: random_range(1..=usize::MAX) cannot return zero")
}
pub fn take_slice_ptr<T>(slice: &[T]) -> *mut T {
if slice.is_empty() {
ptr::null_mut()
} else {
slice.as_ptr() as _
}
}
#[derive(Debug)]
pub struct NonClonable<T>(pub(crate) T);
impl<T> NonClonable<T> {
pub const fn new(value: T) -> Self {
Self(value)
}
pub fn into_inner(self) -> T {
self.0
}
pub const fn get_ref(&self) -> &T {
&self.0
}
pub fn get_mut(&mut self) -> &mut T {
&mut self.0
}
}
pub const HKEY_LM_REG_KEY: RegKey = RegKey::predef(HKEY_LOCAL_MACHINE);
pub const fn get_winreg_arch_flags() -> u32 {
use winreg::enums;
cfg_if! {
if #[cfg(target_arch = "x86_64")] {
enums::KEY_READ
} else if #[cfg(target_arch = "x86")] {
enums::KEY_READ | enums::KEY_WOW64_32KEY
} else {
compile_error!("Unsupported target architecture");
}
}
}