1use crate::aws_lc::{CBB_cleanup, CBB_finish, CBB_init, CBB_init_fixed, CBB};
5use crate::error::Unspecified;
6use crate::ptr::LcPtr;
7use core::marker::PhantomData;
8use core::mem::MaybeUninit;
9use core::ptr::null_mut;
10
11pub(crate) struct LcCBB<'a>(CBB, PhantomData<&'a CBB>);
12
13impl LcCBB<'static> {
14 pub(crate) fn new(initial_capacity: usize) -> LcCBB<'static> {
15 let mut cbb = MaybeUninit::<CBB>::uninit();
16 let cbb = unsafe {
17 CBB_init(cbb.as_mut_ptr(), initial_capacity);
18 cbb.assume_init()
19 };
20 Self(cbb, PhantomData)
21 }
22
23 pub(crate) fn into_vec(mut self) -> Result<Vec<u8>, Unspecified> {
24 let mut out_data = null_mut::<u8>();
25 let mut out_len: usize = 0;
26
27 if 1 != unsafe { CBB_finish(self.as_mut_ptr(), &mut out_data, &mut out_len) } {
28 return Err(Unspecified);
29 }
30
31 let out_data = LcPtr::new(out_data)?;
32 let slice = unsafe { std::slice::from_raw_parts(*out_data.as_const(), out_len) };
33 Ok(slice.to_vec())
35 }
36}
37
38impl<'a> LcCBB<'a> {
39 pub(crate) fn new_from_slice(buffer: &'a mut [u8]) -> LcCBB<'a> {
40 let mut cbb = MaybeUninit::<CBB>::uninit();
41 let cbb = unsafe {
42 CBB_init_fixed(cbb.as_mut_ptr(), buffer.as_mut_ptr(), buffer.len());
43 cbb.assume_init()
44 };
45 Self(cbb, PhantomData)
46 }
47
48 pub(crate) fn finish(mut self) -> Result<usize, Unspecified> {
49 let mut pkcs8_bytes_ptr = null_mut::<u8>();
50 let mut out_len: usize = 0;
51 if 1 != unsafe { CBB_finish(self.as_mut_ptr(), &mut pkcs8_bytes_ptr, &mut out_len) } {
52 return Err(Unspecified);
53 }
54 Ok(out_len)
55 }
56}
57impl LcCBB<'_> {
58 pub(crate) fn as_mut_ptr(&mut self) -> *mut CBB {
59 &mut self.0
60 }
61}
62
63impl Drop for LcCBB<'_> {
64 fn drop(&mut self) {
65 unsafe {
66 CBB_cleanup(&mut self.0);
67 }
68 }
69}
70
71#[cfg(test)]
72mod tests {
73 use super::LcCBB;
74 use crate::aws_lc::CBB_add_asn1_bool;
75
76 #[test]
77 fn dynamic_vec() {
78 let mut cbb = LcCBB::new(4);
79 assert_eq!(1, unsafe { CBB_add_asn1_bool(cbb.as_mut_ptr(), 1) });
80 let vec = cbb.into_vec().expect("be copied to buffer");
81 assert_eq!(vec.as_slice(), &[1, 1, 255]);
82 }
83
84 #[test]
85 fn dynamic_buffer_grows() {
86 let mut cbb = LcCBB::new(1);
87 assert_eq!(1, unsafe { CBB_add_asn1_bool(cbb.as_mut_ptr(), 1) });
88 let vec = cbb.into_vec().expect("be copied to buffer");
89 assert_eq!(vec.as_slice(), &[1, 1, 255]);
90 }
91
92 #[test]
93 fn fixed_buffer() {
94 let mut buffer = [0u8; 4];
95 let mut cbb = LcCBB::new_from_slice(&mut buffer);
96 assert_eq!(1, unsafe { CBB_add_asn1_bool(cbb.as_mut_ptr(), 1) });
97 let out_len = cbb.finish().expect("cbb finishable");
98 assert_eq!(&buffer[..out_len], &[1, 1, 255]);
99 }
100
101 #[test]
102 fn fixed_buffer_no_growth() {
103 let mut buffer = [0u8; 1];
104 let mut cbb = LcCBB::new_from_slice(&mut buffer);
105 assert_ne!(1, unsafe { CBB_add_asn1_bool(cbb.as_mut_ptr(), 1) });
106 }
107}