rust/bt-common: Add LtvValue::encode_all
Encodes multiple LtvValue items.
Change-Id: If675fa08fc2ac3a0e131e2faf13c6c062bf5c59e
Reviewed-on: https://bluetooth-review.git.corp.google.com/c/bluetooth/+/1980
Reviewed-by: Ani Ramakrishnan <aniramakri@google.com>
diff --git a/rust/bt-common/src/core/ltv.rs b/rust/bt-common/src/core/ltv.rs
index d8923e2..6a1083a 100644
--- a/rust/bt-common/src/core/ltv.rs
+++ b/rust/bt-common/src/core/ltv.rs
@@ -73,6 +73,21 @@
}
}
}
+
+ /// Encode a collection of LtValue structures into a buffer.
+ /// Even if the encoding fails, `buf` may still be modified by
+ /// previous encoding successes.
+ fn encode_all(
+ iter: impl Iterator<Item = Self>,
+ buf: &mut [u8],
+ ) -> Result<(), crate::packet_encoding::Error> {
+ let mut idx = 0;
+ for item in iter {
+ item.encode(&mut buf[idx..])?;
+ idx += item.encoded_len();
+ }
+ Ok(())
+ }
}
#[derive(Error, Debug, PartialEq)]
@@ -246,6 +261,9 @@
}
fn encode_value(&self, buf: &mut [u8]) -> Result<(), crate::packet_encoding::Error> {
+ if buf.len() < self.value_encoded_len() as usize {
+ return Err(crate::packet_encoding::Error::BufferTooSmall);
+ }
match self {
TestValues::TwoBytes(x) => {
[buf[0], buf[1]] = x.to_be_bytes();
@@ -253,7 +271,9 @@
TestValues::TwoBytesLittleEndian(x) => {
[buf[0], buf[1]] = x.to_le_bytes();
}
- TestValues::OneByte(x) => buf[0] = *x,
+ TestValues::OneByte(x) => {
+ buf[0] = *x;
+ }
TestValues::UnicodeString(s) => {
buf.copy_from_slice(s.as_bytes());
}
@@ -283,6 +303,26 @@
assert_eq!(decoded[1], Err(Error::UnrecognizedType("TestValues".to_owned(), 6)));
}
+ #[test]
+ fn encode_twobytes() {
+ let value = TestValues::TwoBytes(0x0A0B);
+ let mut buf = [0; 4];
+ value.encode(&mut buf[..]).expect("should succeed");
+ assert_eq!(buf, [0x03, 0x02, 0x0A, 0x0B]);
+ }
+
+ #[test]
+ fn encode_all() {
+ let value1 = TestValues::OneByte(0x0A);
+ let value2 = TestValues::UnicodeString("Bluetooth".to_string());
+ let mut buf = [0; 14];
+ LtValue::encode_all(vec![value1, value2].into_iter(), &mut buf).expect("should succeed");
+ assert_eq!(
+ buf,
+ [0x02, 0x01, 0x0a, 0x0a, 0x04, 0x42, 0x6c, 0x75, 0x65, 0x74, 0x6f, 0x6f, 0x74, 0x68]
+ );
+ }
+
#[track_caller]
fn u8char(c: char) -> u8 {
c.try_into().unwrap()
@@ -335,11 +375,16 @@
#[test]
fn encode_with_error() {
- let mut buf = [0; 10];
let value = TestValues::AlwaysError;
+ let mut buf = [0; 10];
assert!(matches!(
value.encode(&mut buf),
Err(crate::packet_encoding::Error::InvalidParameter(_)),
));
+
+ let value1 = TestValues::TwoBytes(0x0A0B);
+ let value2 = TestValues::OneByte(0x0A);
+ let mut buf = [0; 2]; // not enough buffer space.
+ LtValue::encode_all(vec![value1, value2].into_iter(), &mut buf).expect_err("should fail");
}
}