use core::ops::Deref;
use crate::Result;
use crate::Error;
use crate::FlipsMemory;
#[derive(Clone, Debug, PartialEq)]
pub struct BpsPatch<B: AsRef<[u8]>> {
buffer: B,
}
impl<B: AsRef<[u8]>> BpsPatch<B> {
pub fn new(buffer: B) -> Self {
Self { buffer }
}
#[must_use]
pub fn apply<S: AsRef<[u8]>>(&self, source: S) -> Result<BpsOutput> {
let slice_p = self.buffer.as_ref();
let slice_s = source.as_ref();
let mut mem_m = flips_sys::mem::default();
let mut mem_o = flips_sys::mem::default();
let result = unsafe {
let mem_i = flips_sys::mem::new(slice_s.as_ptr() as *mut _, slice_s.len());
let mem_p = flips_sys::mem::new(slice_p.as_ptr() as *mut _, slice_p.len());
flips_sys::bps::bps_apply(mem_p, mem_i, &mut mem_o as *mut _, &mut mem_m as *mut _, false)
};
match Error::from_bps(result) {
None if mem_m.ptr.is_null() => Ok(BpsOutput::from(FlipsMemory::new(mem_o))),
None => Ok(BpsOutput::with_metadata(FlipsMemory::new(mem_o), FlipsMemory::new(mem_m))),
Some(error) => Err(error),
}
}
}
impl<B: AsRef<[u8]>> AsRef<[u8]> for BpsPatch<B> {
fn as_ref(&self) -> &[u8] {
self.buffer.as_ref()
}
}
#[derive(Debug)]
pub struct BpsOutput {
mem: FlipsMemory,
metadata: Option<FlipsMemory>,
}
impl BpsOutput {
fn with_metadata(output: FlipsMemory, metadata: FlipsMemory) -> Self {
Self {
mem: output,
metadata: Some(metadata),
}
}
}
impl From<FlipsMemory> for BpsOutput {
fn from(mem: FlipsMemory) -> Self {
Self {
mem,
metadata: None
}
}
}
impl AsRef<[u8]> for BpsOutput {
fn as_ref(&self) -> &[u8] {
self.mem.as_ref()
}
}
impl Deref for BpsOutput {
type Target = FlipsMemory;
fn deref(&self) -> &Self::Target {
&self.mem
}
}
#[derive(Clone, Debug, Default)]
pub struct BpsLinearBuilder<S: AsRef<[u8]>, T: AsRef<[u8]>, M: AsRef<[u8]> = &'static [u8]> {
source: Option<S>,
target: Option<T>,
metadata: Option<M>,
}
impl<S: AsRef<[u8]>, T: AsRef<[u8]>> BpsLinearBuilder<S, T, &'static [u8]> {
pub fn new() -> Self {
Self {
source: None,
target: None,
metadata: None,
}
}
pub fn metadata<M: AsRef<[u8]>, B: Into<Option<M>>>(&mut self, buffer: B) -> BpsLinearBuilder<S, T, M> {
BpsLinearBuilder {
source: self.source.take(),
target: self.target.take(),
metadata: buffer.into(),
}
}
}
impl<S: AsRef<[u8]>, T: AsRef<[u8]>, M: AsRef<[u8]>> BpsLinearBuilder<S, T, M> {
pub fn source(&mut self, source: S) -> &mut Self {
self.source = Some(source);
self
}
pub fn target(&mut self, target: T) -> &mut Self {
self.target = Some(target);
self
}
#[must_use]
pub fn build(&mut self) -> Result<BpsPatch<FlipsMemory>> {
if self.source.is_none() || self.target.is_none() {
return Err(Error::Canceled);
}
let (source, target) = (self.source.take().unwrap(), self.target.take().unwrap());
let (slice_s, slice_t) = (source.as_ref(), target.as_ref());
let mut mem_patch = flips_sys::mem::default();
let result = unsafe {
let mem_metadata = match self.metadata.take() {
Some(m) => flips_sys::mem::new(m.as_ref().as_ptr() as *mut _, m.as_ref().len()),
None => flips_sys::mem::default(),
};
let mem_s = flips_sys::mem::new(slice_s.as_ptr() as *mut _, slice_s.len());
let mem_t = flips_sys::mem::new(slice_t.as_ptr() as *mut _, slice_t.len());
flips_sys::bps::bps_create_linear(
mem_s,
mem_t,
mem_metadata,
&mut mem_patch as *mut _
)
};
match Error::from_bps(result) {
None => Ok(BpsPatch::new(FlipsMemory::new(mem_patch))),
Some(error) => Err(error),
}
}
}
#[derive(Clone, Debug, Default)]
pub struct BpsDeltaBuilder<S: AsRef<[u8]>, T: AsRef<[u8]>, M: AsRef<[u8]> = &'static [u8]> {
source: Option<S>,
target: Option<T>,
metadata: Option<M>,
moremem: bool,
}
impl<S: AsRef<[u8]>, T: AsRef<[u8]>> BpsDeltaBuilder<S, T, &'static [u8]> {
pub fn new() -> Self {
Self {
source: None,
target: None,
metadata: None,
moremem: false,
}
}
pub fn metadata<M: AsRef<[u8]>, B: Into<Option<M>>>(&mut self, buffer: B) -> BpsDeltaBuilder<S, T, M> {
BpsDeltaBuilder {
source: self.source.take(),
target: self.target.take(),
metadata: buffer.into(),
moremem: self.moremem,
}
}
}
impl<S: AsRef<[u8]>, T: AsRef<[u8]>, M: AsRef<[u8]>> BpsDeltaBuilder<S, T, M> {
pub fn source(&mut self, source: S) -> &mut Self {
self.source = Some(source);
self
}
pub fn more_memory(&mut self, moremem: bool) -> &mut Self {
self.moremem = moremem;
self
}
pub fn target(&mut self, target: T) -> &mut Self {
self.target = Some(target);
self
}
#[must_use]
pub fn build(&mut self) -> Result<BpsPatch<FlipsMemory>> {
if self.source.is_none() || self.target.is_none() {
return Err(Error::Canceled);
}
let (source, target) = (self.source.take().unwrap(), self.target.take().unwrap());
let (slice_s, slice_t) = (source.as_ref(), target.as_ref());
let mut mem_patch = flips_sys::mem::default();
let result = unsafe {
let mem_metadata = match self.metadata.take() {
Some(m) => flips_sys::mem::new(m.as_ref().as_ptr() as *mut _, m.as_ref().len()),
None => flips_sys::mem::default(),
};
let mem_s = flips_sys::mem::new(slice_s.as_ptr() as *mut _, slice_s.len());
let mem_t = flips_sys::mem::new(slice_t.as_ptr() as *mut _, slice_t.len());
flips_sys::bps::bps_create_delta_inmem(
mem_s,
mem_t,
mem_metadata,
&mut mem_patch as *mut _,
core::ptr::null(),
core::ptr::null(),
self.moremem,
)
};
match Error::from_bps(result) {
None => Ok(BpsPatch::new(FlipsMemory::new(mem_patch))),
Some(error) => Err(error),
}
}
}