@@ -2,25 +2,50 @@ module pem
2
2
3
3
import encoding.base64
4
4
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
+
5
16
// decode reads `data` and returns the first parsed PEM Block along with the rest of
6
17
// 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]
8
22
pub 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`
9
34
mut rest := data[data.index (pem_begin)? ..]
10
35
mut block := Block.new (rest[pem_begin.len..].all_before (pem_eol))
11
36
block.headers , rest = parse_headers (rest[pem_begin.len..].all_after (pem_eol).trim_left (' \n\t\v\f\r ' ))?
12
37
13
38
block_end_index := rest.index (pem_end)?
14
39
b64_data := rest[..block_end_index].replace_each (['\r ' , '' , '\n ' , '' , '\t ' , '' , ' ' , '' ])
15
-
16
40
block_data_len := block_end_index / 4 * 3
17
41
block.data = []u8 {len: block_data_len, cap: block_data_len + 3 , init: 0 }
18
42
decoded_len := base64 .decode_in_buffer (& b64_ data, & block.data[0 ])
19
43
block.data = block.data[..decoded_len]
20
44
21
- return block, rest[rest. index (pem_end) ? + pem_end.len..]. all_after_first (pem_eol)
45
+ return block, rest
22
46
}
23
47
48
+ [direct_array_access ]
24
49
fn parse_headers (block string ) ? (map [string ][]string , string ) {
25
50
headers_str := block.all_before (pem_end).all_before ('\n\n ' )
26
51
0 commit comments