Skip to content

Commit

Permalink
truncate long slices instead of panicking
Browse files Browse the repository at this point in the history
  • Loading branch information
JoJoJet committed Jul 20, 2022
1 parent aed9ed6 commit 6b57afc
Showing 1 changed file with 35 additions and 10 deletions.
45 changes: 35 additions & 10 deletions crates/bevy_utils/src/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,23 +66,33 @@ pub struct StuffedStr<'a> {
unsafe impl<'a> Send for StuffedStr<'a> {}
unsafe impl<'a> Sync for StuffedStr<'a> {}

/// Truncates the passed string slice to be of length `len`, or shorter.
#[cold]
#[inline(never)]
fn truncate(str: &str, mut len: usize) -> &str {
// Just keep lowering the expected length until we hit a unicode boundary.
// This is messy but if the string is long enough that we need to truncate it,
// it's too long for anyone to notice what the end looks like.
loop {
if let Some(str) = str.get(..len) {
break str;
}
// In practice this won't be able to underflow, since `str.get(..0)` will always succeed.
len -= 1;
}
}

impl<'a> StuffedStr<'a> {
const DATA_MASK: usize = !Self::LEN_MASK;
const LEN_MASK: usize = !0 << 16;

pub fn new(str: &'a str, data: u16) -> Self {
#[cold]
#[inline(never)]
fn panic() -> ! {
// needs a better message but its late
panic!("string exceeds {} bytes", StuffedStr::LEN_MASK >> 16);
}

let ptr = str.as_ptr();
pub fn new(mut str: &'a str, data: u16) -> Self {
// Make sure there's enough room to store the data.
if str.len().leading_zeros() < 16 {
panic();
str = truncate(str, Self::LEN_MASK >> 16);
debug_assert!(str.len().leading_zeros() < 16);
}
let ptr = str.as_ptr();
let meta = data as usize | str.len() << 16;
Self {
ptr,
Expand Down Expand Up @@ -202,3 +212,18 @@ macro_rules! define_label {
}
};
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn test_truncate() {
// Slice at byte '4'
assert_eq!(truncate("Hello, World!", 4), "Hell");

// Slicing off at byte '3' would be inside of the emoji,
// so instead the whole emoji gets sliced off.
assert_eq!(truncate("x😂", 3), "x");
}
}

0 comments on commit 6b57afc

Please sign in to comment.