use crate::backend::Backend;
use crate::error::{BarretenbergError, Result};
use std::ptr;
extern "C" {
fn bbapi(
input_in: *const u8,
input_len_in: usize,
output_out: *mut *mut u8,
output_len_out: *mut usize,
);
}
pub struct FfiBackend {
_initialized: bool,
}
impl FfiBackend {
pub fn new() -> Result<Self> {
Ok(Self { _initialized: true })
}
}
impl Backend for FfiBackend {
fn call(&mut self, input: &[u8]) -> Result<Vec<u8>> {
let mut output_ptr: *mut u8 = ptr::null_mut();
let mut output_len: usize = 0;
unsafe {
bbapi(
input.as_ptr(),
input.len(),
&mut output_ptr,
&mut output_len,
);
}
if output_ptr.is_null() {
return Err(BarretenbergError::Backend(
"bbapi returned null pointer".to_string(),
));
}
if output_len == 0 {
unsafe {
libc::free(output_ptr as *mut libc::c_void);
}
return Err(BarretenbergError::Backend(
"bbapi returned empty response".to_string(),
));
}
let output = unsafe { std::slice::from_raw_parts(output_ptr, output_len).to_vec() };
unsafe {
libc::free(output_ptr as *mut libc::c_void);
}
Ok(output)
}
fn destroy(&mut self) -> Result<()> {
self._initialized = false;
Ok(())
}
}
impl Drop for FfiBackend {
fn drop(&mut self) {
let _ = self.destroy();
}
}
impl Default for FfiBackend {
fn default() -> Self {
Self::new().expect("Failed to initialize FfiBackend")
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::api::BarretenbergApi;
#[test]
fn test_ffi_backend_creation() {
let backend = FfiBackend::new();
assert!(backend.is_ok());
}
#[test]
fn test_ffi_blake2s() {
let backend = FfiBackend::new().unwrap();
let mut api = BarretenbergApi::new(backend);
let response = api.blake2s(b"hello world").unwrap();
assert_eq!(response.hash.len(), 32);
let response2 = api.blake2s(b"hello world").unwrap();
assert_eq!(response.hash, response2.hash);
}
}