use alloc::{borrow::ToOwned, rc::Rc, string::String, vec::Vec};
use core::{
cell::RefCell,
convert::From,
hash::{BuildHasher, Hasher},
};
#[cfg(feature = "std")]
use std::{fs::File, io::Read, path::Path};
use ahash::RandomState;
#[cfg(feature = "std")]
use libafl_bolts::{fs::write_file_atomic, Error};
use libafl_bolts::{ownedref::OwnedSlice, HasLen};
use serde::{Deserialize, Serialize};
use crate::inputs::{HasBytesVec, HasTargetBytes, Input};
#[derive(Serialize, Deserialize, Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct BytesInput {
pub(crate) bytes: Vec<u8>,
}
impl Input for BytesInput {
#[cfg(feature = "std")]
fn to_file<P>(&self, path: P) -> Result<(), Error>
where
P: AsRef<Path>,
{
write_file_atomic(path, &self.bytes)
}
#[cfg(feature = "std")]
fn from_file<P>(path: P) -> Result<Self, Error>
where
P: AsRef<Path>,
{
let mut file = File::open(path)?;
let mut bytes: Vec<u8> = vec![];
file.read_to_end(&mut bytes)?;
Ok(BytesInput::new(bytes))
}
fn generate_name(&self, _idx: usize) -> String {
let mut hasher = RandomState::with_seeds(0, 0, 0, 0).build_hasher();
hasher.write(self.bytes());
format!("{:016x}", hasher.finish())
}
}
impl From<BytesInput> for Rc<RefCell<BytesInput>> {
fn from(input: BytesInput) -> Self {
Rc::new(RefCell::new(input))
}
}
impl HasBytesVec for BytesInput {
#[inline]
fn bytes(&self) -> &[u8] {
&self.bytes
}
#[inline]
fn bytes_mut(&mut self) -> &mut Vec<u8> {
&mut self.bytes
}
}
impl HasTargetBytes for BytesInput {
#[inline]
fn target_bytes(&self) -> OwnedSlice<u8> {
OwnedSlice::from(&self.bytes)
}
}
impl HasLen for BytesInput {
#[inline]
fn len(&self) -> usize {
self.bytes.len()
}
}
impl From<Vec<u8>> for BytesInput {
fn from(bytes: Vec<u8>) -> Self {
Self::new(bytes)
}
}
impl From<&[u8]> for BytesInput {
fn from(bytes: &[u8]) -> Self {
Self::new(bytes.to_owned())
}
}
impl From<BytesInput> for Vec<u8> {
fn from(value: BytesInput) -> Vec<u8> {
value.bytes
}
}
impl BytesInput {
#[must_use]
pub const fn new(bytes: Vec<u8>) -> Self {
Self { bytes }
}
}