|
3 | 3 | use crate::errors::InvalidValue; |
4 | 4 | use crate::{ |
5 | 5 | value::{Decimal, Value}, |
6 | | - Error, Ident, Result, |
| 6 | + Encoding, Error, Ident, Result, |
7 | 7 | }; |
8 | 8 | use core::{ |
9 | 9 | convert::{TryFrom, TryInto}, |
@@ -50,22 +50,51 @@ impl ParamsString { |
50 | 50 | Self::default() |
51 | 51 | } |
52 | 52 |
|
| 53 | + /// Add the given byte value to the [`ParamsString`], encoding it as "B64". |
| 54 | + pub fn add_b64_bytes<'a>(&mut self, name: impl TryInto<Ident<'a>>, bytes: &[u8]) -> Result<()> { |
| 55 | + if !self.is_empty() { |
| 56 | + self.0 |
| 57 | + .write_char(PARAMS_DELIMITER) |
| 58 | + .map_err(|_| Error::ParamsMaxExceeded)? |
| 59 | + } |
| 60 | + |
| 61 | + let name = name.try_into().map_err(|_| Error::ParamNameInvalid)?; |
| 62 | + |
| 63 | + // Add param name |
| 64 | + let offset = self.0.length; |
| 65 | + if write!(self.0, "{}=", name).is_err() { |
| 66 | + self.0.length = offset; |
| 67 | + return Err(Error::ParamsMaxExceeded); |
| 68 | + } |
| 69 | + |
| 70 | + // Encode B64 value |
| 71 | + let offset = self.0.length as usize; |
| 72 | + let written = Encoding::B64 |
| 73 | + .encode(bytes, &mut self.0.bytes[offset..])? |
| 74 | + .len(); |
| 75 | + |
| 76 | + self.0.length += written as u8; |
| 77 | + Ok(()) |
| 78 | + } |
| 79 | + |
| 80 | + /// Add a key/value pair with a decimal value to the [`ParamsString`]. |
| 81 | + pub fn add_decimal<'a>(&mut self, name: impl TryInto<Ident<'a>>, value: Decimal) -> Result<()> { |
| 82 | + let name = name.try_into().map_err(|_| Error::ParamNameInvalid)?; |
| 83 | + self.add(name, value) |
| 84 | + } |
| 85 | + |
53 | 86 | /// Add a key/value pair with a string value to the [`ParamsString`]. |
54 | 87 | pub fn add_str<'a>( |
55 | 88 | &mut self, |
56 | 89 | name: impl TryInto<Ident<'a>>, |
57 | 90 | value: impl TryInto<Value<'a>>, |
58 | 91 | ) -> Result<()> { |
59 | 92 | let name = name.try_into().map_err(|_| Error::ParamNameInvalid)?; |
| 93 | + |
60 | 94 | let value = value |
61 | 95 | .try_into() |
62 | 96 | .map_err(|_| Error::ParamValueInvalid(InvalidValue::InvalidFormat))?; |
63 | | - self.add(name, value) |
64 | | - } |
65 | 97 |
|
66 | | - /// Add a key/value pair with a decimal value to the [`ParamsString`]. |
67 | | - pub fn add_decimal<'a>(&mut self, name: impl TryInto<Ident<'a>>, value: Decimal) -> Result<()> { |
68 | | - let name = name.try_into().map_err(|_| Error::ParamNameInvalid)?; |
69 | 98 | self.add(name, value) |
70 | 99 | } |
71 | 100 |
|
@@ -311,6 +340,16 @@ mod tests { |
311 | 340 | assert_eq!(params.get_decimal("c").unwrap(), 3); |
312 | 341 | } |
313 | 342 |
|
| 343 | + #[test] |
| 344 | + #[cfg(feature = "alloc")] |
| 345 | + fn add_b64_bytes() { |
| 346 | + let mut params = ParamsString::new(); |
| 347 | + params.add_b64_bytes("a", &[1]).unwrap(); |
| 348 | + params.add_b64_bytes("b", &[2, 3]).unwrap(); |
| 349 | + params.add_b64_bytes("c", &[4, 5, 6]).unwrap(); |
| 350 | + assert_eq!(params.to_string(), "a=AQ,b=AgM,c=BAUG"); |
| 351 | + } |
| 352 | + |
314 | 353 | #[test] |
315 | 354 | fn duplicate_names() { |
316 | 355 | let name = Ident::new("a"); |
|
0 commit comments