libbfio-rs 0.2.5

Rust bindings for libbfio (https://github.com/libyal/libbfio)
use crate::error::Error;
use crate::ffi_error::LibbfioErrorRefMut;
use libbfio_sys::{size64_t, SEEK_CUR, SEEK_END, SEEK_SET};
use log::trace;

use libcerror_sys::*;
use std::ffi::CString;
use std::fs::File;
use std::io::{Read, Seek, SeekFrom, Write};
use std::os::raw::c_int;
use std::path::Path;
use std::slice;

pub trait RwSeek: Read + Write + Seek {}
impl<T: Read + Write + Seek> RwSeek for T {}

pub struct IoHandle {
    inner: Box<dyn RwSeek>,
    is_open: bool,
}

impl IoHandle {
    pub fn file(inner: File) -> Self {
        IoHandle {
            inner: Box::new(inner) as Box<dyn RwSeek>,
            is_open: true
        }
    }
}

pub const IO_ERR: i32 = LIBCERROR_ERROR_DOMAINS_LIBCERROR_ERROR_DOMAIN_IO as i32;
pub const ARGUMENT_ERR: i32 = LIBCERROR_ERROR_DOMAINS_LIBCERROR_ERROR_DOMAIN_ARGUMENTS as i32;

#[no_mangle]
pub unsafe extern "C" fn io_handle_free(
    io_handle: *mut *mut IoHandle,
    _error: *mut LibbfioErrorRefMut,
) -> c_int {
    trace!("io_handle_free");
    Box::from_raw(*io_handle);

    1 as c_int
}

#[no_mangle]
pub unsafe extern "C" fn io_handle_read(
    io_handle: *mut IoHandle,
    buffer: *mut u8,
    size: usize,
    error: *mut LibbfioErrorRefMut,
) -> isize {
    trace!("io_handle_read");

    let s = slice::from_raw_parts_mut(buffer, size);
    match (*io_handle).inner.read(s) {
        Ok(cnt) => cnt as isize,
        Err(e) => {
            libcerror_error_set(
                error as _,
                IO_ERR,
                LIBCERROR_IO_ERROR_LIBCERROR_IO_ERROR_READ_FAILED as i32,
                CString::new("%s.").unwrap().into_raw(),
                CString::new(format!("io_handle_read: {:?}", e))
                    .unwrap()
                    .into_raw(),
            );
            return -1;
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn io_handle_write(
    io_handle: *mut IoHandle,
    buffer: *const u8,
    size: usize,
    error: *mut LibbfioErrorRefMut,
) -> isize {
    trace!("io_handle_write");

    let s = slice::from_raw_parts(buffer, size);
    match (*io_handle).inner.write(s) {
        Ok(cnt) => cnt as isize,
        Err(e) => {
            libcerror_error_set(
                error as _,
                IO_ERR,
                LIBCERROR_IO_ERROR_LIBCERROR_IO_ERROR_WRITE_FAILED as i32,
                CString::new("%s.").unwrap().into_raw(),
                CString::new(format!("io_handle_write: {:?}", e))
                    .unwrap()
                    .into_raw(),
            );
            return -1;
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn io_handle_is_open(
    io_handle: *mut IoHandle,
    error: *mut LibbfioErrorRefMut,
) -> c_int {
    trace!("io_handle_is_open");
    match (*io_handle).is_open {
        true => 1,
        false => 0,
    }
}

#[no_mangle]
pub unsafe extern "C" fn io_handle_seek(
    io_handle: *mut IoHandle,
    offset: u64,
    whence: c_int,
    error: *mut LibbfioErrorRefMut,
) -> u64 {
    trace!("io_handle_seek");

    let seek_from = match whence as u32 {
        SEEK_SET => SeekFrom::Start(offset),
        SEEK_END => SeekFrom::End(offset as i64),
        SEEK_CUR => SeekFrom::Current(offset as i64),
        _ => {
            libcerror_error_set(
                error as _,
                ARGUMENT_ERR,
                LIBCERROR_ARGUMENT_ERROR_LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE as i32,
                CString::new("%s: invalid whence.").unwrap().into_raw(),
                CString::new("io_handle_seek").unwrap().into_raw(),
            );
            return 0;
        }
    };

    match (*io_handle).inner.seek(seek_from) {
        Ok(count) => count,
        Err(e) => {
            libcerror_error_set(
                error as _,
                IO_ERR,
                LIBCERROR_IO_ERROR_LIBCERROR_IO_ERROR_SEEK_FAILED as i32,
                CString::new("%s.").unwrap().into_raw(),
                CString::new(format!("io_handle_seek: {:?}", e))
                    .unwrap()
                    .into_raw(),
            );
            return 0;
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn io_handle_get_size(
    io_handle: *mut IoHandle,
    size: *mut size64_t,
    error: *mut LibbfioErrorRefMut,
) -> c_int {
    trace!("io_handle_get_size");
    match (*io_handle).inner.stream_len() {
        Ok(count) => {
            *size = count;
            return 1;
        }
        Err(e) => {
            libcerror_error_set(
                error as _,
                IO_ERR,
                LIBCERROR_IO_ERROR_LIBCERROR_IO_ERROR_SEEK_FAILED as i32,
                CString::new("%s.").unwrap().into_raw(),
                CString::new(format!("io_handle_get_size: {:?}", e))
                    .unwrap()
                    .into_raw(),
            );
            return 0;
        }
    }
}