1use super::{
4 ordinary::OneShotError,
5 specifications::{Base64, Codec},
6};
7
8#[derive(Clone, Copy, Debug, Eq, PartialEq)]
10pub struct BufferLengthError {
11 length: usize,
12 capacity: usize,
13}
14
15impl BufferLengthError {
16 pub(super) const fn new(length: usize, capacity: usize) -> Self {
17 Self { length, capacity }
18 }
19
20 #[must_use]
22 pub const fn length(self) -> usize {
23 self.length
24 }
25
26 #[must_use]
28 pub const fn capacity(self) -> usize {
29 self.capacity
30 }
31}
32
33impl core::fmt::Display for BufferLengthError {
34 fn fmt(&self, formatter: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
35 write!(
36 formatter,
37 "visible buffer length {} exceeds capacity {}",
38 self.length, self.capacity
39 )
40 }
41}
42
43#[cfg(feature = "std")]
44impl std::error::Error for BufferLengthError {}
45
46#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
51pub struct EncodedArray<const CAP: usize> {
52 bytes: [u8; CAP],
53 len: usize,
54}
55
56#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
61pub struct DecodedArray<const CAP: usize> {
62 bytes: [u8; CAP],
63 len: usize,
64}
65
66macro_rules! ordinary_array {
67 ($name:ident, $description:literal) => {
68 impl<const CAP: usize> $name<CAP> {
69 #[doc = $description]
70 pub const fn from_array(
71 bytes: [u8; CAP],
72 len: usize,
73 ) -> Result<Self, BufferLengthError> {
74 if len > CAP {
75 Err(BufferLengthError::new(len, CAP))
76 } else {
77 Ok(Self { bytes, len })
78 }
79 }
80
81 pub(crate) const fn from_initialized(
82 bytes: [u8; CAP],
83 len: usize,
84 ) -> Result<Self, BufferLengthError> {
85 Self::from_array(bytes, len)
86 }
87
88 #[must_use]
90 pub fn as_bytes(&self) -> &[u8] {
91 &self.bytes[..self.len]
92 }
93
94 #[must_use]
96 pub const fn len(&self) -> usize {
97 self.len
98 }
99
100 #[must_use]
102 pub const fn is_empty(&self) -> bool {
103 self.len == 0
104 }
105
106 #[must_use]
108 pub const fn capacity(&self) -> usize {
109 CAP
110 }
111
112 #[must_use]
114 pub const fn remaining_capacity(&self) -> usize {
115 CAP - self.len
116 }
117
118 #[must_use]
120 pub const fn into_parts(self) -> ([u8; CAP], usize) {
121 (self.bytes, self.len)
122 }
123 }
124 };
125}
126
127ordinary_array!(
128 EncodedArray,
129 "Constructs ordinary encoded storage with a checked visible prefix."
130);
131ordinary_array!(
132 DecodedArray,
133 "Constructs ordinary decoded storage with a checked visible prefix."
134);
135
136impl<S: Codec> Base64<S> {
137 pub fn encode_bounded<const CAP: usize>(
139 &self,
140 input: &[u8],
141 ) -> Result<EncodedArray<CAP>, OneShotError> {
142 let mut bytes = [0u8; CAP];
143 let len = self.encode_into(input, &mut bytes)?;
144 EncodedArray::from_initialized(bytes, len)
145 .map_err(|_| OneShotError::Backend(super::contracts::BackendFault::ImpossibleState))
146 }
147
148 pub fn decode_bounded<const CAP: usize>(
150 &self,
151 input: &[u8],
152 ) -> Result<DecodedArray<CAP>, OneShotError> {
153 let mut bytes = [0u8; CAP];
154 let len = self.decode_into(input, &mut bytes)?;
155 DecodedArray::from_initialized(bytes, len)
156 .map_err(|_| OneShotError::Backend(super::contracts::BackendFault::ImpossibleState))
157 }
158}