use alloc::string::{String, ToString};
#[must_use]
pub fn encode_composite_key(fields: &[&str]) -> String {
let capacity = fields
.iter()
.map(|field| field.len().saturating_add(8))
.sum();
let mut key = String::with_capacity(capacity);
for field in fields {
key.push_str(&field.len().to_string());
key.push(':');
key.push_str(field);
}
key
}
#[cfg(test)]
mod tests {
use super::encode_composite_key;
#[test]
fn distinct_field_boundaries_do_not_collide() {
assert_ne!(
encode_composite_key(&["a", "b:c"]),
encode_composite_key(&["a:b", "c"]),
);
}
#[test]
fn equal_inputs_encode_equally_and_arity_matters() {
assert_eq!(
encode_composite_key(&["x", "y"]),
encode_composite_key(&["x", "y"]),
);
assert_ne!(
encode_composite_key(&["xy"]),
encode_composite_key(&["x", "y"]),
);
}
#[test]
fn empty_digit_and_separator_fields_stay_injective() {
assert_ne!(encode_composite_key(&[]), encode_composite_key(&[""]));
assert_ne!(encode_composite_key(&[""]), encode_composite_key(&["", ""]));
assert_ne!(
encode_composite_key(&["5abc"]),
encode_composite_key(&["5", "abc"]),
);
assert_ne!(
encode_composite_key(&["1:1", "a"]),
encode_composite_key(&["1", "1:a"]),
);
}
}