diff --git a/src/ffi.rs b/src/ffi.rs index 42062f7..f5a4a98 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -16,7 +16,7 @@ //! # FFI bindings //! Direct bindings to the underlying C library functions. These should //! not be needed for most users. -use core::{mem, hash}; +use core::{mem, hash, slice}; use types::*; /// Flag for context to enable no precomputation @@ -260,6 +260,50 @@ extern "C" { } +#[cfg(feature = "std")] +#[no_mangle] +/// A reimplementation of the C function `secp256k1_context_create` in rust. +/// +/// This function allocates memory, the pointer should be deallocated using `secp256k1_context_destroy` +/// A failure to do so will result in a memory leak. +/// +/// This will create a secp256k1 raw context. +// Returns: a newly created context object. +// In: flags: which parts of the context to initialize. +pub unsafe extern "C" fn secp256k1_context_create(flags: c_uint) -> *mut Context { + assert!(mem::align_of::() >= mem::align_of::()); + assert_eq!(mem::size_of::(), mem::size_of::<&usize>()); + + let word_size = mem::size_of::(); + let n_words = (secp256k1_context_preallocated_size(flags) + word_size - 1) / word_size; + + let buf = vec![0usize; n_words + 1].into_boxed_slice(); + let ptr = Box::into_raw(buf) as *mut usize; + ::core::ptr::write(ptr, n_words); + let ptr: *mut usize = ptr.offset(1); + + secp256k1_context_preallocated_create(ptr as *mut c_void, flags) +} + +#[cfg(feature = "std")] +#[no_mangle] +/// A reimplementation of the C function `secp256k1_context_destroy` in rust. +/// +/// This function destroys and deallcates the context created by `secp256k1_context_create`. +/// +/// The pointer shouldn't be used after passing to this function, consider it as passing it to `free()`. +/// +pub unsafe extern "C" fn secp256k1_context_destroy(ctx: *mut Context) { + secp256k1_context_preallocated_destroy(ctx); + let ctx: *mut usize = ctx as *mut usize; + + let n_words_ptr: *mut usize = ctx.offset(-1); + let n_words: usize = ::core::ptr::read(n_words_ptr); + let slice: &mut [usize] = slice::from_raw_parts_mut(n_words_ptr , n_words+1); + let _ = Box::from_raw(slice as *mut [usize]); +} + + #[no_mangle] /// **This function is an override for the C function, this is the an edited version of the original description:** /// @@ -280,7 +324,7 @@ extern "C" { /// See also secp256k1_default_error_callback_fn. /// pub unsafe extern "C" fn secp256k1_default_illegal_callback_fn(message: *const c_char, _data: *mut c_void) { - use core::{str, slice}; + use core::str; let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); let msg = str::from_utf8_unchecked(msg_slice); panic!("[libsecp256k1] illegal argument. {}", msg); @@ -302,7 +346,7 @@ pub unsafe extern "C" fn secp256k1_default_illegal_callback_fn(message: *const c /// See also secp256k1_default_illegal_callback_fn. /// pub unsafe extern "C" fn secp256k1_default_error_callback_fn(message: *const c_char, _data: *mut c_void) { - use core::{str, slice}; + use core::str; let msg_slice = slice::from_raw_parts(message as *const u8, strlen(message)); let msg = str::from_utf8_unchecked(msg_slice); panic!("[libsecp256k1] internal consistency check failed {}", msg);