base64_ng/v2/
ordinary_alloc.rs1use alloc::{string::String, vec::Vec};
4
5use super::{
6 ordinary::OneShotError,
7 specifications::{Base64, Codec},
8};
9
10impl<S: Codec> Base64<S> {
11 pub fn encode_to_string(&self, input: &[u8]) -> Result<String, OneShotError> {
17 self.encode_to_string_with_limit(input, usize::MAX)
18 }
19
20 pub fn encode_to_string_with_limit(
22 &self,
23 input: &[u8],
24 max_output_len: usize,
25 ) -> Result<String, OneShotError> {
26 self.encode_to_string_with_reserver(input, max_output_len, |output, required| {
27 output
28 .try_reserve_exact(required)
29 .map_err(|_| OneShotError::AllocationFailed {
30 requested: required,
31 })
32 })
33 }
34
35 fn encode_to_string_with_reserver<F>(
36 &self,
37 input: &[u8],
38 max_output_len: usize,
39 reserve: F,
40 ) -> Result<String, OneShotError>
41 where
42 F: FnOnce(&mut Vec<u8>, usize) -> Result<(), OneShotError>,
43 {
44 let required = self.encoded_len(input.len())?;
45 require_allocation_limit(required, max_output_len)?;
46 let mut output = Vec::new();
47 reserve(&mut output, required)?;
48 output.resize(required, 0);
49 self.encode_into(input, &mut output)?;
50 String::from_utf8(output)
51 .map_err(|_| OneShotError::Backend(super::contracts::BackendFault::ImpossibleState))
52 }
53
54 pub fn decode_to_vec(&self, input: &[u8]) -> Result<Vec<u8>, OneShotError> {
59 self.decode_to_vec_with_limit(input, usize::MAX)
60 }
61
62 pub fn decode_to_vec_with_limit(
64 &self,
65 input: &[u8],
66 max_output_len: usize,
67 ) -> Result<Vec<u8>, OneShotError> {
68 self.decode_to_vec_with_reserver(input, max_output_len, |output, required| {
69 output
70 .try_reserve_exact(required)
71 .map_err(|_| OneShotError::AllocationFailed {
72 requested: required,
73 })
74 })
75 }
76
77 fn decode_to_vec_with_reserver<F>(
78 &self,
79 input: &[u8],
80 max_output_len: usize,
81 reserve: F,
82 ) -> Result<Vec<u8>, OneShotError>
83 where
84 F: FnOnce(&mut Vec<u8>, usize) -> Result<(), OneShotError>,
85 {
86 let required = self.decoded_len(input)?;
87 require_allocation_limit(required, max_output_len)?;
88 let mut output = Vec::new();
89 reserve(&mut output, required)?;
90 output.resize(required, 0);
91 self.decode_into(input, &mut output)?;
92 Ok(output)
93 }
94
95 #[cfg(test)]
96 pub(super) fn decode_to_vec_with_injected_reserver<F>(
97 &self,
98 input: &[u8],
99 max_output_len: usize,
100 reserve: F,
101 ) -> Result<Vec<u8>, OneShotError>
102 where
103 F: FnOnce(&mut Vec<u8>, usize) -> Result<(), OneShotError>,
104 {
105 self.decode_to_vec_with_reserver(input, max_output_len, reserve)
106 }
107
108 #[cfg(test)]
109 pub(super) fn encode_to_string_with_injected_reserver<F>(
110 &self,
111 input: &[u8],
112 max_output_len: usize,
113 reserve: F,
114 ) -> Result<String, OneShotError>
115 where
116 F: FnOnce(&mut Vec<u8>, usize) -> Result<(), OneShotError>,
117 {
118 self.encode_to_string_with_reserver(input, max_output_len, reserve)
119 }
120}
121
122fn require_allocation_limit(required: usize, limit: usize) -> Result<(), OneShotError> {
123 if required > limit {
124 Err(OneShotError::AllocationLimitExceeded { required, limit })
125 } else {
126 Ok(())
127 }
128}