From 47d08df69d76300c6d01327261d1fa7dba895752 Mon Sep 17 00:00:00 2001 From: Weicao-CatilGrass <1992414357@qq.com> Date: Mon, 9 Mar 2026 20:03:27 +0800 Subject: Rename FFIButckContext to ButckContext and add comprehensive documentation --- src/chunker/context/ffi.rs | 278 ++++++++++++++++++++++++++++++++++----------- 1 file changed, 214 insertions(+), 64 deletions(-) (limited to 'src/chunker/context/ffi.rs') diff --git a/src/chunker/context/ffi.rs b/src/chunker/context/ffi.rs index c169c18..9447e9e 100644 --- a/src/chunker/context/ffi.rs +++ b/src/chunker/context/ffi.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, env::current_dir, path::PathBuf}; use crate::chunker::{ - context::{ButckContext, ButckMethod}, + context::{ButckContext as RustButckContext, ButckMethod}, rw::storage::hash::ChunkWriteHash, }; @@ -57,33 +57,60 @@ macro_rules! cstr_to_path_or_current_dir { }; } +/// FFI representation of ButckContext for C interoperability +/// This struct mirrors ButckContext but uses C-compatible types #[repr(C)] -pub struct FFIButckContext { +pub struct ButckContext { + /// Operation mode (0=None, 1=Write, 2=Build) method: u8, + /// Array of input file paths (C strings) file_paths: *mut *mut std::os::raw::c_char, + /// Number of file paths in the array file_paths_len: usize, + /// Storage repository path (C string) storage_path: *mut std::os::raw::c_char, + /// Display chunk boundaries without executing chunking/building logic display_boundaries: bool, + /// Stream reading size (if stream_read_set is true) stream_read: u32, + /// Whether stream_read is set stream_read_set: bool, + /// Use memory mapping for file reading memmap_read: bool, + /// Registration name for bidx files (C string) register_name: *mut std::os::raw::c_char, + /// Chunking policy name (C string) policy_name: *mut std::os::raw::c_char, + /// Chunk hash algorithm (0=Blake3, 1=SHA256) chunk_hash: u8, + /// Output directory path (C string) output_dir: *mut std::os::raw::c_char, + /// Output file name (C string) output_file: *mut std::os::raw::c_char, + /// Parameter keys array (C strings) params_keys: *mut *mut std::os::raw::c_char, + /// Parameter values array (C strings) params_values: *mut *mut std::os::raw::c_char, + /// Number of parameters in the arrays params_len: usize, } +/// Create a new ButckContext for write operation +/// +/// # Arguments +/// * `files` - Array of C string pointers to input files +/// * `files_len` - Number of files in the array +/// * `storage` - C string pointer to storage repository path +/// +/// # Returns +/// * Pointer to newly created ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_Write( files: *mut *mut std::os::raw::c_char, files_len: usize, storage: *mut std::os::raw::c_char, -) -> *mut FFIButckContext { +) -> *mut ButckContext { let mut file_paths = Vec::new(); if !files.is_null() && files_len > 0 { for i in 0..files_len { @@ -112,21 +139,30 @@ pub extern "C" fn Butck_Write( PathBuf::new() }; - let ctx = ButckContext::default() + let ctx = RustButckContext::default() .with_file_paths(file_paths) .with_storage_path(storage_path) .with_write_mode(); - Box::into_raw(Box::new(FFIButckContext::from(ctx))) + Box::into_raw(Box::new(ButckContext::from(ctx))) } +/// Create a new ButckContext for build operation +/// +/// # Arguments +/// * `index_files` - Array of C string pointers to *.bidx files +/// * `index_files_len` - Number of index files in the array +/// * `storage` - C string pointer to storage repository path +/// +/// # Returns +/// * Pointer to newly created ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_Build( index_files: *mut *mut std::os::raw::c_char, index_files_len: usize, storage: *mut std::os::raw::c_char, -) -> *mut FFIButckContext { +) -> *mut ButckContext { let mut file_paths = Vec::new(); if !index_files.is_null() && index_files_len > 0 { for i in 0..index_files_len { @@ -155,24 +191,35 @@ pub extern "C" fn Butck_Build( PathBuf::new() }; - let ctx = ButckContext::default() + let ctx = RustButckContext::default() .with_file_paths(file_paths) .with_storage_path(storage_path) .with_build_mode(); - Box::into_raw(Box::new(FFIButckContext::from(ctx))) + Box::into_raw(Box::new(ButckContext::from(ctx))) } +/// Execute the operation specified in the context +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// +/// # Returns +/// * true if execution succeeded, false otherwise +/// +/// # Note +/// The context pointer is consumed and freed during execution. +/// Callers must not free it afterward. #[unsafe(no_mangle)] #[allow(nonstandard_style)] -pub extern "C" fn Butck_Exec(ctx: *mut FFIButckContext) -> bool { +pub extern "C" fn Butck_Exec(ctx: *mut ButckContext) -> bool { if ctx.is_null() { return false; } unsafe { let ffi_ctx = Box::from_raw(ctx); - let butck_ctx = ButckContext::from(*ffi_ctx); + let butck_ctx = RustButckContext::from(*ffi_ctx); // ffi_ctx is consumed by the dereference above, Box will be dropped automatically let runtime = tokio::runtime::Runtime::new().unwrap(); @@ -183,138 +230,195 @@ pub extern "C" fn Butck_Exec(ctx: *mut FFIButckContext) -> bool { } } +/// Set storage repository path +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `storage` - C string pointer to storage repository path +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_WithStoragePath( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, storage: *mut std::os::raw::c_char, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); let storage_path = cstr_to_path!(storage); butck_ctx = butck_ctx.with_storage_path(storage_path); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Set display boundaries flag +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `display` - Whether to display chunk boundaries +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_WithDisplayBoundaries( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, display: bool, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); butck_ctx = butck_ctx.with_display_boundaries(display); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Set stream reading configuration +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `size` - Stream reading size in bytes +/// * `set` - Whether to enable stream reading +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_WithStreamRead( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, size: u32, set: bool, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); let stream_read = if set { Some(size) } else { None }; butck_ctx = butck_ctx.with_stream_read(stream_read); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Set memory map reading flag +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `use_memmap` - Whether to use memory mapping for file reading +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_WithMemmapRead( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, use_memmap: bool, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); butck_ctx = butck_ctx.with_memmap_read(use_memmap); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Set registration name for bidx files +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `name` - C string pointer to registration name +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_WithRegisterName( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, name: *mut std::os::raw::c_char, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); let register_name = cstr_to_opt_string!(name); butck_ctx = butck_ctx.with_register_name(register_name); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Set chunking policy name +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `name` - C string pointer to policy name +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_WithPolicyName( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, name: *mut std::os::raw::c_char, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); let policy_name = cstr_to_opt_string!(name); butck_ctx = butck_ctx.with_policy_name(policy_name); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Set chunk hash algorithm +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `hash` - Hash algorithm (0=Blake3, 1=SHA256) +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] -pub extern "C" fn Butck_WithChunkHash(ctx: *mut FFIButckContext, hash: u8) -> *mut FFIButckContext { +pub extern "C" fn Butck_WithChunkHash(ctx: *mut ButckContext, hash: u8) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); let chunk_hash = match hash { 0 => ChunkWriteHash::Blake3, @@ -323,66 +427,91 @@ pub extern "C" fn Butck_WithChunkHash(ctx: *mut FFIButckContext, hash: u8) -> *m }; butck_ctx = butck_ctx.with_chunk_hash(chunk_hash); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Set output directory path +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `dir` - C string pointer to output directory path +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_WithOutputDir( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, dir: *mut std::os::raw::c_char, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); let output_dir = cstr_to_path_or_current_dir!(dir); butck_ctx = butck_ctx.with_output_dir(output_dir); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Set output file name +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `file` - C string pointer to output file name +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_WithOutputFile( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, file: *mut std::os::raw::c_char, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); let output_file = cstr_to_opt_string!(file).map(PathBuf::from); butck_ctx = butck_ctx.with_output_file(output_file); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Set input file paths +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `files` - Array of C string pointers to input files +/// * `files_len` - Number of files in the array +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_WithFilePaths( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, files: *mut *mut std::os::raw::c_char, files_len: usize, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); let mut file_paths = Vec::new(); if !files.is_null() && files_len > 0 { @@ -398,23 +527,31 @@ pub extern "C" fn Butck_WithFilePaths( } butck_ctx = butck_ctx.with_file_paths(file_paths); - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Add a single input file path +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `file` - C string pointer to input file path +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_AddFile( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, file: *mut std::os::raw::c_char, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); if !file.is_null() { let c_str = std::ffi::CStr::from_ptr(file); @@ -423,24 +560,33 @@ pub extern "C" fn Butck_AddFile( } } - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Add a parameter to the context +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext +/// * `key` - C string pointer to parameter key +/// * `value` - C string pointer to parameter value +/// +/// # Returns +/// * Pointer to updated ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] pub extern "C" fn Butck_Param( - ctx: *mut FFIButckContext, + ctx: *mut ButckContext, key: *mut std::os::raw::c_char, value: *mut std::os::raw::c_char, -) -> *mut FFIButckContext { +) -> *mut ButckContext { if ctx.is_null() { return std::ptr::null_mut(); } unsafe { let ffi_ctx = Box::from_raw(ctx); - let mut butck_ctx = ButckContext::from(*ffi_ctx); + let mut butck_ctx = RustButckContext::from(*ffi_ctx); if !key.is_null() && !value.is_null() { let key_cstr = std::ffi::CStr::from_ptr(key); @@ -451,13 +597,17 @@ pub extern "C" fn Butck_Param( } } - Box::into_raw(Box::new(FFIButckContext::from(butck_ctx))) + Box::into_raw(Box::new(ButckContext::from(butck_ctx))) } } +/// Free the ButckContext and all associated C strings +/// +/// # Arguments +/// * `ctx` - Pointer to ButckContext #[unsafe(no_mangle)] #[allow(nonstandard_style)] -pub extern "C" fn Butck_FreeButckContext(ctx: *mut FFIButckContext) { +pub extern "C" fn Butck_FreeButckContext(ctx: *mut ButckContext) { if ctx.is_null() { return; } @@ -536,8 +686,8 @@ pub extern "C" fn Butck_FreeButckContext(ctx: *mut FFIButckContext) { } } -impl From for FFIButckContext { - fn from(ctx: ButckContext) -> Self { +impl From for ButckContext { + fn from(ctx: RustButckContext) -> Self { // Convert method enum let method = match ctx.method { ButckMethod::None => 0, @@ -655,7 +805,7 @@ impl From for FFIButckContext { std::ptr::null_mut() }; - FFIButckContext { + ButckContext { method, file_paths, file_paths_len, @@ -676,8 +826,8 @@ impl From for FFIButckContext { } } -impl From for ButckContext { - fn from(ffi_ctx: FFIButckContext) -> Self { +impl From for RustButckContext { + fn from(ffi_ctx: ButckContext) -> Self { // Convert method enum let method = match ffi_ctx.method { 0 => ButckMethod::None, @@ -776,7 +926,7 @@ impl From for ButckContext { } } - ButckContext { + RustButckContext { method, file_paths, storage_path, -- cgit