use crate::{ModuleSigScanError, SigscanPtr, modulescan::Scanner};
type SigByte = Option<u8>;
#[derive(Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct Signature(Vec<SigByte>);
impl Signature {
#[inline]
pub fn with_capacity(capacity: usize) -> Self {
Signature(Vec::with_capacity(capacity))
}
#[inline]
pub fn push_byte(&mut self, byte: u8) {
self.push(Some(byte));
}
#[inline]
pub fn push_any(&mut self) {
self.push(None);
}
pub fn scan(&self, bytes: &[u8]) -> Option<usize> {
let mut iter_bytes = bytes.iter().enumerate();
let mut start = 0;
let mut i = 0;
while i < self.len() {
let (byte_pos, byte) = iter_bytes.next()?;
if let Some(sig_byte) = &self.0[i] {
if sig_byte == byte {
i += 1;
if start == 0 {
start = byte_pos;
}
} else {
start = 0;
i = 0;
}
} else {
i += 1;
}
}
Some(start)
}
pub unsafe fn scan_ptr<P: SigscanPtr>(&self, mut ptr: P, max: P) -> Option<P> {
let mut i = 0;
while ptr < max {
let byte = ptr.byte();
let sig_byte = &self.0[i];
if let Some(sig_byte) = sig_byte {
if *sig_byte != byte {
i = 0;
ptr = ptr.next();
continue;
}
}
i += 1;
if i >= self.len() {
return Some(ptr.rewind(self.len() - 1));
}
ptr = ptr.next();
}
None
}
pub unsafe fn scan_module<S: AsRef<str>>(&self, module: S) -> Result<*mut u8, ModuleSigScanError> {
let scanner = Scanner::for_module(module.as_ref()).ok_or(ModuleSigScanError::InvalidModule)?;
scanner.find(&*self)
}
}
impl From<Vec<Option<u8>>> for Signature {
fn from(bytes: Vec<Option<u8>>) -> Self {
Self(bytes)
}
}
impl From<&[Option<u8>]> for Signature {
fn from(bytes: &[Option<u8>]) -> Self {
Self(bytes.to_vec())
}
}
impl From<Vec<u8>> for Signature {
fn from(bytes: Vec<u8>) -> Self {
Self(bytes.into_iter().map(Some).collect())
}
}
impl From<&[u8]> for Signature {
fn from(bytes: &[u8]) -> Self {
Self(bytes.iter().map(|byte| Some(*byte)).collect())
}
}
impl std::ops::Deref for Signature {
type Target = Vec<SigByte>;
#[inline(always)]
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl std::ops::DerefMut for Signature {
#[inline(always)]
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl std::fmt::Debug for Signature {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
if !self.is_empty() {
write!(f, "{:?}", self[0])?;
for byte in self.iter().skip(1) {
write!(f, " {:?}", byte)?;
}
}
Ok(())
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum SignatureParseError {
InvalidByte,
Empty,
OnlyAny,
}
impl std::str::FromStr for Signature {
type Err = SignatureParseError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut added_byte = false;
let mut signature = Signature::with_capacity(f32::ceil(s.len() as f32 / 2.) as usize);
let trimmed = s.trim();
if trimmed.is_empty() {
return Err(SignatureParseError::Empty);
}
for byte in trimmed.split(' ') {
match (byte.len(), byte) {
(1, "?") | (2, "??") => signature.push_any(),
(2, _) => {
added_byte = true;
signature.push_byte(u8::from_str_radix(byte, 16).map_err(|_| SignatureParseError::InvalidByte)?);
},
_ => return Err(SignatureParseError::InvalidByte)
}
}
if signature.is_empty() {
Err(SignatureParseError::Empty)
} else if !added_byte {
Err(SignatureParseError::OnlyAny)
} else {
signature.shrink_to_fit();
Ok(signature)
}
}
}