@@ -76,9 +76,28 @@ mod sealed {
76
76
77
77
/// Parses the input string as an integer returning an error carrying rich context.
78
78
///
79
- /// If the caller owns `String` or `Box<str>` which is not used later it's better to pass it as
80
- /// owned since it avoids allocation in error case.
81
- pub fn int < T : Integer , S : AsRef < str > + Into < InputString > > ( s : S ) -> Result < T , ParseIntError > {
79
+ /// On error this function allocates to copy the input string into the error return. If the caller
80
+ /// has a `String` or `Box<str>` which is not used later it's better to call
81
+ /// [`parse::int_from_string`] or [`parse::int_from_box`] respectively.
82
+ ///
83
+ /// [`parse::int_from_string`]: crate::parse::int_from_string
84
+ /// [`parse::int_from_box`]: crate::parse::int_from_box
85
+ pub fn int_from_str < T : Integer > ( s : & str ) -> Result < T , ParseIntError > { int ( s) }
86
+
87
+ /// Parses the input string as an integer returning an error carrying rich context.
88
+ ///
89
+ /// On error the input string is moved into the error return without allocating.
90
+ #[ cfg( feature = "alloc" ) ]
91
+ pub fn int_from_string < T : Integer > ( s : alloc:: string:: String ) -> Result < T , ParseIntError > { int ( s) }
92
+
93
+ /// Parses the input string as an integer returning an error carrying rich context.
94
+ ///
95
+ /// On error the input string is converted into the error return without allocating.
96
+ #[ cfg( feature = "alloc" ) ]
97
+ pub fn int_from_box < T : Integer > ( s : alloc:: boxed:: Box < str > ) -> Result < T , ParseIntError > { int ( s) }
98
+
99
+ // This must be private because we do not want `InputString` to appear in the public API.
100
+ fn int < T : Integer , S : AsRef < str > + Into < InputString > > ( s : S ) -> Result < T , ParseIntError > {
82
101
s. as_ref ( ) . parse ( ) . map_err ( |error| {
83
102
ParseIntError {
84
103
input : s. into ( ) ,
@@ -120,37 +139,44 @@ pub fn int<T: Integer, S: AsRef<str> + Into<InputString>>(s: S) -> Result<T, Par
120
139
#[ doc( hidden) ] // This is an 'internal' macro that should not be used outside of the `rust-bitcoin` crate.
121
140
macro_rules! impl_parse_str_from_int_infallible {
122
141
( $to: ident, $inner: ident, $fn: ident) => {
123
- $crate:: impl_tryfrom_str_from_int_infallible!( & str , $to, $inner, $fn) ;
124
- #[ cfg( feature = "alloc" ) ]
125
- $crate:: impl_tryfrom_str_from_int_infallible!( alloc:: string:: String , $to, $inner, $fn; alloc:: boxed:: Box <str >, $to, $inner, $fn) ;
126
-
127
142
impl $crate:: _export:: _core:: str :: FromStr for $to {
128
143
type Err = $crate:: parse:: ParseIntError ;
129
144
130
145
fn from_str( s: & str ) -> $crate:: _export:: _core:: result:: Result <Self , Self :: Err > {
131
- $crate:: parse :: int :: <$inner , & str > ( s ) . map ( $to :: $fn )
146
+ $crate:: _export :: _core :: convert :: TryFrom :: try_from ( s )
132
147
}
133
148
}
134
149
135
- }
136
- }
150
+ impl $crate :: _export :: _core :: convert :: TryFrom < & str > for $to {
151
+ type Error = $crate :: parse :: ParseIntError ;
137
152
138
- /// Implements `TryFrom<$from> for $to` using `parse::int`, mapping the output using infallible
139
- /// conversion function `fn`.
140
- #[ macro_export]
141
- #[ doc( hidden) ] // Helper macro called by `impl_parse_str_from_int_infallible`.
142
- macro_rules! impl_tryfrom_str_from_int_infallible {
143
- ( $( $from: ty, $to: ident, $inner: ident, $fn: ident) ;* ) => {
144
- $(
145
- impl $crate:: _export:: _core:: convert:: TryFrom <$from> for $to {
153
+ fn try_from( s: & str ) -> $crate:: _export:: _core:: result:: Result <Self , Self :: Error > {
154
+ $crate:: parse:: int_from_str:: <$inner>( s) . map( $to:: $fn)
155
+ }
156
+ }
157
+
158
+ #[ cfg( feature = "alloc" ) ]
159
+ impl $crate:: _export:: _core:: convert:: TryFrom <alloc:: string:: String > for $to {
146
160
type Error = $crate:: parse:: ParseIntError ;
147
161
148
- fn try_from( s: $from) -> $crate:: _export:: _core:: result:: Result <Self , Self :: Error > {
149
- $crate:: parse:: int:: <$inner, $from>( s) . map( $to:: $fn)
162
+ fn try_from(
163
+ s: alloc:: string:: String ,
164
+ ) -> $crate:: _export:: _core:: result:: Result <Self , Self :: Error > {
165
+ $crate:: parse:: int_from_string:: <$inner>( s) . map( $to:: $fn)
150
166
}
151
167
}
152
- ) *
153
- }
168
+
169
+ #[ cfg( feature = "alloc" ) ]
170
+ impl $crate:: _export:: _core:: convert:: TryFrom <alloc:: boxed:: Box <str >> for $to {
171
+ type Error = $crate:: parse:: ParseIntError ;
172
+
173
+ fn try_from(
174
+ s: alloc:: boxed:: Box <str >,
175
+ ) -> $crate:: _export:: _core:: result:: Result <Self , Self :: Error > {
176
+ $crate:: parse:: int_from_box:: <$inner>( s) . map( $to:: $fn)
177
+ }
178
+ }
179
+ } ;
154
180
}
155
181
156
182
/// Implements standard parsing traits for `$type` by calling through to `$inner_fn`.
@@ -497,9 +523,9 @@ mod tests {
497
523
498
524
#[ test]
499
525
fn parse_int ( ) {
500
- assert ! ( int :: <u8 , _ >( "1" ) . is_ok( ) ) ;
501
- let _ = int :: < i8 , _ > ( "not a number" ) . map_err ( |e| assert ! ( e. is_signed) ) ;
502
- let _ = int :: < u8 , _ > ( "not a number" ) . map_err ( |e| assert ! ( !e. is_signed) ) ;
526
+ assert ! ( int_from_str :: <u8 >( "1" ) . is_ok( ) ) ;
527
+ let _ = int_from_str :: < i8 > ( "not a number" ) . map_err ( |e| assert ! ( e. is_signed) ) ;
528
+ let _ = int_from_str :: < u8 > ( "not a number" ) . map_err ( |e| assert ! ( !e. is_signed) ) ;
503
529
}
504
530
505
531
#[ test]
@@ -520,7 +546,7 @@ mod tests {
520
546
fn from ( _: i8 ) -> Self { TestTypeLargerThanU128 ( 0 , 0 ) }
521
547
}
522
548
523
- let result = panic:: catch_unwind ( || int :: < TestTypeLargerThanU128 , _ > ( "not a number" ) ) ;
549
+ let result = panic:: catch_unwind ( || int_from_str :: < TestTypeLargerThanU128 > ( "not a number" ) ) ;
524
550
assert ! ( result. is_err( ) ) ;
525
551
}
526
552
0 commit comments