@@ -2,25 +2,50 @@ module pem
22
33import encoding.base64
44
5+ // decode_only reads `data` and returns the first parsed PEM Block. `none` is returned
6+ // when a header is expected, but not present or when a start of '-----BEGIN' or end of '-----END'
7+ // can't be found.
8+ //
9+ // use decode if you still need the unparsed rest of the string.
10+ [inline ]
11+ pub fn decode_only (data string ) ? Block {
12+ block , _ := decode_internal (data)?
13+ return block
14+ }
15+
516// decode reads `data` and returns the first parsed PEM Block along with the rest of
617// the string. `none` is returned when a header is expected, but not present
7- // or when a start of '-----BEGIN' or end of '-----END' can't be found in `data`
18+ // or when a start of '-----BEGIN' or end of '-----END' can't be found.
19+ //
20+ // use decode_only if you do not need the unparsed rest of the string.
21+ [direct_array_access; inline]
822pub fn decode (data string ) ? (Block, string ) {
23+ block , rest := decode_internal (data)?
24+ return block, rest[rest.index (pem_end)? + pem_end.len..].all_after_first (pem_eol)
25+ }
26+
27+ // decode_internal allows `decode` variations to deal with the rest of the data as
28+ // they want to. for example Block.decode could have hindered performance with the final
29+ // indexing into `rest` that `decode_partial` does.
30+ [direct_array_access ]
31+ fn decode_internal (data string ) ? (Block, string ) {
32+ // direct_array_access safety: since we use the string.index method here,
33+ // we won't get an invalid index since it would otherwise return `none`
934 mut rest := data[data.index (pem_begin)? ..]
1035 mut block := Block.new (rest[pem_begin.len..].all_before (pem_eol))
1136 block.headers , rest = parse_headers (rest[pem_begin.len..].all_after (pem_eol).trim_left (' \n\t\v\f\r ' ))?
1237
1338 block_end_index := rest.index (pem_end)?
1439 b64_data := rest[..block_end_index].replace_each (['\r ' , '' , '\n ' , '' , '\t ' , '' , ' ' , '' ])
15-
1640 block_data_len := block_end_index / 4 * 3
1741 block.data = []u8 {len: block_data_len, cap: block_data_len + 3 , init: 0 }
1842 decoded_len := base64 .decode_in_buffer (& b64_ data, & block.data[0 ])
1943 block.data = block.data[..decoded_len]
2044
21- return block, rest[rest. index (pem_end) ? + pem_end.len..]. all_after_first (pem_eol)
45+ return block, rest
2246}
2347
48+ [direct_array_access ]
2449fn parse_headers (block string ) ? (map [string ][]string , string ) {
2550 headers_str := block.all_before (pem_end).all_before ('\n\n ' )
2651
0 commit comments