11// SPDX-License-Identifier: CC0-1.0
22
3+ use core:: fmt;
34use core:: marker:: PhantomData ;
45use core:: mem:: ManuallyDrop ;
56use core:: ptr:: NonNull ;
@@ -8,7 +9,7 @@ use core::ptr::NonNull;
89pub use self :: alloc_only:: * ;
910use crate :: ffi:: types:: { c_uint, c_void, AlignedType } ;
1011use crate :: ffi:: { self , CPtr } ;
11- use crate :: { Error , Secp256k1 } ;
12+ use crate :: Secp256k1 ;
1213
1314#[ cfg( all( feature = "global-context" , feature = "std" ) ) ]
1415/// Module implementing a singleton pattern for a global `Secp256k1` context.
@@ -320,30 +321,51 @@ unsafe impl<'buf> PreallocatedContext<'buf> for AllPreallocated<'buf> {}
320321unsafe impl < ' buf > PreallocatedContext < ' buf > for SignOnlyPreallocated < ' buf > { }
321322unsafe impl < ' buf > PreallocatedContext < ' buf > for VerifyOnlyPreallocated < ' buf > { }
322323
324+ /// A preallocated buffer, enforces the invariant that the buffer is big enough.
325+ #[ allow( missing_debug_implementations) ]
326+ pub struct PreallocatedBuffer < ' buf > ( & ' buf [ AlignedType ] ) ;
327+
328+ impl < ' buf > ffi:: CPtr for PreallocatedBuffer < ' buf > {
329+ type Target = AlignedType ;
330+ fn as_c_ptr ( & self ) -> * const Self :: Target { self . 0 . as_c_ptr ( ) }
331+ fn as_mut_c_ptr ( & mut self ) -> * mut Self :: Target { self . 0 . as_mut_c_ptr ( ) }
332+ }
333+
323334impl < ' buf , C : Context + PreallocatedContext < ' buf > > Secp256k1 < C > {
335+ /// Wraps `buf` in a `PreallocatedBuffer`.
336+ ///
337+ /// # Errors
338+ ///
339+ /// Returns `NotEnoughMemoryError` if the buffer is too small.
340+ pub fn buffer (
341+ buf : & ' buf mut [ AlignedType ] ,
342+ ) -> Result < PreallocatedBuffer , NotEnoughMemoryError > {
343+ if buf. len ( ) < Self :: preallocate_size_gen ( ) {
344+ return Err ( NotEnoughMemoryError ) ;
345+ }
346+ Ok ( PreallocatedBuffer ( buf) )
347+ }
348+
324349 /// Lets you create a context with a preallocated buffer in a generic manner (sign/verify/all).
325- pub fn preallocated_gen_new ( buf : & ' buf mut [ AlignedType ] ) -> Result < Secp256k1 < C > , Error > {
350+ pub fn preallocated_gen_new ( buf : & ' buf mut PreallocatedBuffer ) -> Secp256k1 < C > {
326351 #[ cfg( target_arch = "wasm32" ) ]
327352 ffi:: types:: sanity_checks_for_wasm ( ) ;
328353
329- if buf. len ( ) < Self :: preallocate_size_gen ( ) {
330- return Err ( Error :: NotEnoughMemory ) ;
331- }
332354 // Safe because buf is not null since it is not empty.
333355 let buf = unsafe { NonNull :: new_unchecked ( buf. as_mut_c_ptr ( ) as * mut c_void ) } ;
334356
335- Ok ( Secp256k1 {
357+ Secp256k1 {
336358 ctx : unsafe { ffi:: secp256k1_context_preallocated_create ( buf, AllPreallocated :: FLAGS ) } ,
337359 phantom : PhantomData ,
338- } )
360+ }
339361 }
340362}
341363
342364impl < ' buf > Secp256k1 < AllPreallocated < ' buf > > {
343365 /// Creates a new Secp256k1 context with all capabilities.
344366 pub fn preallocated_new (
345- buf : & ' buf mut [ AlignedType ] ,
346- ) -> Result < Secp256k1 < AllPreallocated < ' buf > > , Error > {
367+ buf : & ' buf mut PreallocatedBuffer < ' buf > ,
368+ ) -> Secp256k1 < AllPreallocated < ' buf > > {
347369 Secp256k1 :: preallocated_gen_new ( buf)
348370 }
349371 /// Uses the ffi `secp256k1_context_preallocated_size` to check the memory size needed for a context.
@@ -377,8 +399,8 @@ impl<'buf> Secp256k1<AllPreallocated<'buf>> {
377399impl < ' buf > Secp256k1 < SignOnlyPreallocated < ' buf > > {
378400 /// Creates a new Secp256k1 context that can only be used for signing.
379401 pub fn preallocated_signing_only (
380- buf : & ' buf mut [ AlignedType ] ,
381- ) -> Result < Secp256k1 < SignOnlyPreallocated < ' buf > > , Error > {
402+ buf : & ' buf mut PreallocatedBuffer < ' buf > ,
403+ ) -> Secp256k1 < SignOnlyPreallocated < ' buf > > {
382404 Secp256k1 :: preallocated_gen_new ( buf)
383405 }
384406
@@ -401,8 +423,8 @@ impl<'buf> Secp256k1<SignOnlyPreallocated<'buf>> {
401423impl < ' buf > Secp256k1 < VerifyOnlyPreallocated < ' buf > > {
402424 /// Creates a new Secp256k1 context that can only be used for verification
403425 pub fn preallocated_verification_only (
404- buf : & ' buf mut [ AlignedType ] ,
405- ) -> Result < Secp256k1 < VerifyOnlyPreallocated < ' buf > > , Error > {
426+ buf : & ' buf mut PreallocatedBuffer < ' buf > ,
427+ ) -> Secp256k1 < VerifyOnlyPreallocated < ' buf > > {
406428 Secp256k1 :: preallocated_gen_new ( buf)
407429 }
408430
@@ -421,3 +443,20 @@ impl<'buf> Secp256k1<VerifyOnlyPreallocated<'buf>> {
421443 ManuallyDrop :: new ( Secp256k1 { ctx : raw_ctx, phantom : PhantomData } )
422444 }
423445}
446+
447+ /// Not enough memory for a preallocated buffer.
448+ #[ derive( Debug , Clone , PartialEq , Eq ) ]
449+ #[ non_exhaustive]
450+ #[ allow( missing_copy_implementations) ] // Don't implement Copy when we use non_exhaustive.
451+ pub struct NotEnoughMemoryError ;
452+
453+ impl fmt:: Display for NotEnoughMemoryError {
454+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
455+ f. write_str ( "not enough memory to use as a preallocated buffer" )
456+ }
457+ }
458+
459+ #[ cfg( feature = "std" ) ]
460+ impl std:: error:: Error for NotEnoughMemoryError {
461+ fn source ( & self ) -> Option < & ( dyn std:: error:: Error + ' static ) > { None }
462+ }
0 commit comments