@@ -482,6 +482,30 @@ mod conversion_impls {
482482 #[ cfg( feature = "std" ) ]
483483 impl < T > std:: error:: Error for ScalarTooLarge < T > { }
484484
485+ /// Error returned when trying to convert a zero value into a NonZero scalar
486+ pub struct ZeroScalar < T > ( PhantomData < T > ) ;
487+
488+ impl < T > core:: fmt:: Display for ZeroScalar < T > {
489+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
490+ write ! (
491+ f,
492+ "cannot convert zero {} to NonZero scalar" ,
493+ type_name:: <T >( )
494+ )
495+ }
496+ }
497+
498+ impl < T > core:: fmt:: Debug for ZeroScalar < T > {
499+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
500+ f. debug_tuple ( "ZeroScalar" )
501+ . field ( & type_name :: < T > ( ) )
502+ . finish ( )
503+ }
504+ }
505+
506+ #[ cfg( feature = "std" ) ]
507+ impl < T > std:: error:: Error for ZeroScalar < T > { }
508+
485509 /// Implements `From<$t> for $scalar` **and**
486510 /// `TryFrom<$scalar> for $t` for every `$t` supplied.
487511 macro_rules! impl_scalar_conversions {
@@ -497,6 +521,27 @@ mod conversion_impls {
497521 }
498522 }
499523
524+ impl <S > TryFrom <$t> for Scalar <S , NonZero > {
525+ type Error = ZeroScalar <$t>;
526+
527+ fn try_from( value: $t) -> Result <Self , Self :: Error > {
528+ // big-endian integer → 32-byte array
529+ let mut bytes = [ 0u8 ; 32 ] ;
530+ let int_bytes = value. to_be_bytes( ) ;
531+ bytes[ 32 - int_bytes. len( ) ..] . copy_from_slice( & int_bytes) ;
532+ let scalar = Scalar :: <S , Zero >:: from_bytes( bytes) . unwrap( ) ;
533+
534+ // Check if value is zero
535+ if value == 0 {
536+ Err ( ZeroScalar ( PhantomData ) )
537+ } else {
538+ Ok ( scalar. non_zero( ) . unwrap( ) )
539+ }
540+ }
541+ }
542+
543+
544+
500545 impl <S , Z > TryFrom <Scalar <S , Z >> for $t {
501546 type Error = ScalarTooLarge <$t>;
502547
@@ -759,4 +804,34 @@ mod test {
759804 assert ! ( Scalar :: <Public , _>:: from( 41u32 ) < Scalar :: <Public , _>:: from( 42u32 ) ) ;
760805 assert ! ( Scalar :: <Public , _>:: from( 42u32 ) <= Scalar :: <Public , _>:: from( 42u32 ) ) ;
761806 }
807+
808+ #[ test]
809+ fn try_from_zero_to_nonzero ( ) {
810+ use core:: convert:: TryFrom ;
811+
812+ // Test that converting zero to NonZero fails
813+ let result = Scalar :: < Secret , NonZero > :: try_from ( 0u32 ) ;
814+ assert ! ( result. is_err( ) ) ;
815+
816+ // Test that converting non-zero to NonZero succeeds
817+ let result = Scalar :: < Secret , NonZero > :: try_from ( 42u32 ) ;
818+ assert ! ( result. is_ok( ) ) ;
819+ assert_eq ! (
820+ result. unwrap( ) ,
821+ Scalar :: <Secret , Zero >:: from( 42u32 ) . non_zero( ) . unwrap( )
822+ ) ;
823+
824+ // Test with different integer types
825+ assert ! ( Scalar :: <Public , NonZero >:: try_from( 0u8 ) . is_err( ) ) ;
826+ assert ! ( Scalar :: <Public , NonZero >:: try_from( 0u16 ) . is_err( ) ) ;
827+ assert ! ( Scalar :: <Public , NonZero >:: try_from( 0u64 ) . is_err( ) ) ;
828+
829+ assert ! ( Scalar :: <Public , NonZero >:: try_from( 1u8 ) . is_ok( ) ) ;
830+ assert ! ( Scalar :: <Public , NonZero >:: try_from( 1u16 ) . is_ok( ) ) ;
831+ assert ! ( Scalar :: <Public , NonZero >:: try_from( 1u64 ) . is_ok( ) ) ;
832+
833+ // Test that infallible From still works for Zero
834+ let _zero_scalar: Scalar < Secret , Zero > = 0u32 . into ( ) ;
835+ let _nonzero_scalar: Scalar < Secret , Zero > = 42u32 . into ( ) ;
836+ }
762837}
0 commit comments