1use super::tag;
4use alloc::vec::Vec;
5
6fn encode_length(len: usize, out: &mut Vec<u8>) {
8 if len < 0x80 {
9 out.push(len as u8);
10 return;
11 }
12 let mut bytes = [0u8; core::mem::size_of::<usize>()];
13 let mut n = 0;
14 let mut l = len;
15 while l > 0 {
16 bytes[n] = (l & 0xff) as u8;
17 l >>= 8;
18 n += 1;
19 }
20 out.push(0x80 | n as u8);
21 for i in (0..n).rev() {
22 out.push(bytes[i]);
23 }
24}
25
26pub fn encode_tlv(tag: u8, content: &[u8]) -> Vec<u8> {
28 let mut out = Vec::with_capacity(content.len() + 4);
29 out.push(tag);
30 encode_length(content.len(), &mut out);
31 out.extend_from_slice(content);
32 out
33}
34
35pub fn encode_sequence(content: &[u8]) -> Vec<u8> {
37 encode_tlv(tag::SEQUENCE, content)
38}
39
40pub fn encode_integer(unsigned_be: &[u8]) -> Vec<u8> {
44 if unsigned_be.is_empty() {
45 return encode_tlv(tag::INTEGER, &[0u8]);
47 }
48 let mut start = 0;
50 while start + 1 < unsigned_be.len() && unsigned_be[start] == 0 {
51 start += 1;
52 }
53 let trimmed = &unsigned_be[start..];
54
55 let mut content = Vec::with_capacity(trimmed.len() + 1);
56 if trimmed[0] & 0x80 != 0 {
57 content.push(0x00);
58 }
59 content.extend_from_slice(trimmed);
60 encode_tlv(tag::INTEGER, &content)
61}
62
63pub fn encode_octet_string(content: &[u8]) -> Vec<u8> {
65 encode_tlv(tag::OCTET_STRING, content)
66}
67
68pub fn encode_bit_string(bits: &[u8]) -> Vec<u8> {
70 let mut content = Vec::with_capacity(bits.len() + 1);
71 content.push(0x00); content.extend_from_slice(bits);
73 encode_tlv(tag::BIT_STRING, &content)
74}
75
76pub fn encode_oid(body: &[u8]) -> Vec<u8> {
78 encode_tlv(tag::OID, body)
79}
80
81pub fn encode_null() -> Vec<u8> {
83 encode_tlv(tag::NULL, &[])
84}
85
86pub fn encode_boolean(value: bool) -> Vec<u8> {
88 encode_tlv(tag::BOOLEAN, &[if value { 0xff } else { 0x00 }])
89}
90
91pub fn encode_string(tag: u8, s: &str) -> Vec<u8> {
94 encode_tlv(tag, s.as_bytes())
95}
96
97pub fn encode_context(n: u8, content: &[u8]) -> Vec<u8> {
99 encode_tlv(tag::context(n), content)
100}