blob: 4b798b9736663b2700746917357108059097fffa [file] [log] [blame]
// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.
use core::cmp::min;
use pw_status::Result;
use pw_stream::{Cursor, Write};
pub fn encode_string(cursor: &mut Cursor<&mut [u8]>, value: &str) -> Result<()> {
const MAX_STRING_LENGTH: usize = 0x7f;
let string_bytes = value.as_bytes();
// Limit the encoding to the lesser of 127 or the available space in the buffer.
let max_len = min(MAX_STRING_LENGTH, cursor.remaining() - 1);
let overflow = max_len < string_bytes.len();
let len = min(max_len, string_bytes.len());
// First byte of an encoded string is it's length.
let mut header = len as u8;
// The high bit of the first byte is used to indicate if the string was
// truncated.
if overflow {
header |= 0x80;
}
cursor.write_all(&[header as u8])?;
cursor.write_all(&string_bytes[..len])
}
#[cfg(test)]
mod test {
use pw_stream::{Cursor, Seek};
use super::encode_string;
fn do_string_encode_test<const BUFFER_LEN: usize>(value: &str, expected: &[u8]) {
let mut buffer = [0u8; BUFFER_LEN];
let mut cursor = Cursor::new(&mut buffer[..]);
encode_string(&mut cursor, value).unwrap();
let len = cursor.stream_position().unwrap() as usize;
let buffer = cursor.into_inner();
assert_eq!(len, expected.len());
assert_eq!(&buffer[..len], expected);
}
#[test]
fn test_string_encode() {
do_string_encode_test::<64>("test", b"\x04test");
do_string_encode_test::<4>("test", b"\x83tes");
do_string_encode_test::<1>("test", b"\x80");
// Truncates when the string does not fit.
do_string_encode_test::<64>(
"testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttest",
b"\xbftesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttes",
);
// Truncates when string is over 127 bytes.
do_string_encode_test::<1024>(
"testtesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttest",
b"\xfftesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttesttes",
);
}
}