@@ -20,32 +20,42 @@ use crate::{
2020use base64ct:: { Base64 , Encoding } ;
2121use core:: { convert:: TryFrom , str} ;
2222
23- /// Decode a PEM document according to RFC 7468's "Strict" grammar.
24- ///
25- /// On success, writes the decoded document into the provided buffer, returning
26- /// the decoded label and the portion of the provided buffer containing the
27- /// decoded message.
28- pub fn decode < ' i , ' o > ( pem : & ' i [ u8 ] , buf : & ' o mut [ u8 ] ) -> Result < ( & ' i str , & ' o [ u8 ] ) > {
29- let encapsulation = Encapsulation :: try_from ( pem) ?;
30- let label = encapsulation. label ( ) ;
31- let mut out_len = 0 ;
32-
23+ fn decode_encapsulated_text < ' i , ' o > (
24+ encapsulation : & Encapsulation < ' i > ,
25+ buf : & ' o mut [ u8 ] ,
26+ out_len : & mut usize ,
27+ ) -> Result < ( ) > {
3328 for line in encapsulation. encapsulated_text ( ) {
3429 let line = line?;
35- match Base64 :: decode ( line, & mut buf[ out_len..] ) {
30+
31+ match Base64 :: decode ( line, & mut buf[ * out_len..] ) {
3632 Err ( error) => {
3733 // in the case that we are decoding the first line
3834 // and we error, then attribute the error to an unsupported header
3935 // if a colon char is present in the line
40- if out_len == 0 && line. iter ( ) . any ( |& b| b == grammar:: CHAR_COLON ) {
36+ if * out_len == 0 && line. iter ( ) . any ( |& b| b == grammar:: CHAR_COLON ) {
4137 return Err ( Error :: HeaderDetected ) ;
4238 } else {
4339 return Err ( error. into ( ) ) ;
4440 }
4541 }
46- Ok ( out) => out_len += out. len ( ) ,
42+ Ok ( out) => * out_len += out. len ( ) ,
4743 }
4844 }
45+ Ok ( ( ) )
46+ }
47+
48+ /// Decode a PEM document according to RFC 7468's "Strict" grammar.
49+ ///
50+ /// On success, writes the decoded document into the provided buffer, returning
51+ /// the decoded label and the portion of the provided buffer containing the
52+ /// decoded message.
53+ pub fn decode < ' i , ' o > ( pem : & ' i [ u8 ] , buf : & ' o mut [ u8 ] ) -> Result < ( & ' i str , & ' o [ u8 ] ) > {
54+ let encapsulation = Encapsulation :: try_from ( pem) ?;
55+ let label = encapsulation. label ( ) ;
56+ let mut out_len = 0 ;
57+
58+ decode_encapsulated_text ( & encapsulation, buf, & mut out_len) ?;
4959
5060 Ok ( ( label, & buf[ ..out_len] ) )
5161}
@@ -57,17 +67,12 @@ pub fn decode<'i, 'o>(pem: &'i [u8], buf: &'o mut [u8]) -> Result<(&'i str, &'o
5767pub fn decode_vec ( pem : & [ u8 ] ) -> Result < ( & str , Vec < u8 > ) > {
5868 let encapsulation = Encapsulation :: try_from ( pem) ?;
5969 let label = encapsulation. label ( ) ;
60- let mut max_len = 0 ;
61-
62- for line in encapsulation. encapsulated_text ( ) {
63- max_len += line?. len ( ) * 3 / 4 ;
64- }
65-
70+ // count all chars (gives over-estimation, due to whitespace)
71+ let max_len = encapsulation. encapsulated_text . len ( ) * 3 / 4 ;
6672 let mut result = vec ! [ 0u8 ; max_len] ;
6773 let mut actual_len = 0 ;
68- for line in encapsulation. encapsulated_text ( ) {
69- actual_len += Base64 :: decode ( line?, & mut result[ actual_len..] ) ?. len ( ) ;
70- }
74+
75+ decode_encapsulated_text ( & encapsulation, & mut result, & mut actual_len) ?;
7176
7277 // Actual encoded length can be slightly shorter than estimated
7378 // TODO(tarcieri): more reliable length estimation
0 commit comments