我想缩短结构体上(调试)显示方法的一些字符串。 在此示例中,user_id 成员是一个很长的 UUID,如果它超过一行,我不想打印全部内容,因此我想将其限制在显示屏上不超过 66 个字符。
我的第一个(未经测试的)想法是在格式函数中使用
write!(f, "{:>12}: {}", "user_id", &self.user_id[..((65..).filter_map(|x| if self.user_id.is_char_boundary(x) { Some(x) } else { None }).nth(0).unwrap())])
。 但如果字符串是 <65 bytes in length. ,这可能是一个无限循环
...尚未测试,但也许
write!(f, "{:>12}: {}", "user_id", if self.user_id.len() < 66 { &self.user_id } else { &self.user_id[..((65..).filter_map(|x| if self.user_id.is_char_boundary(x) { Some(x) } else { None }).nth(0).unwrap())]} )
作为背景,据我所知,当前方案中的 user_id 是 ASCII,因此
write!(f, "{:>12}: {}", "user_id", &self.user_id[..65])
应该可以很好地工作(并且更容易理解)。 然而,我想稍微防御性地编程,并且如果 user_id 将来包含非 ASCII unicode 字符,则不会出现程序恐慌。
我对石墨烯簇不感兴趣,也就是说,如果显示器上有一些复杂的 unicode 值,我对填充显示屏上的所有 66 个空格不感兴趣。
我可能对迭代字符并收集的解决方案感兴趣(如果可以有效地完成)。
到目前为止我有一个解决问题的好方法吗? 有没有更好的办法? 我发现截断字符串是一种乏味且不透明的方法,但 Rust 对我来说并不容易。 (我注意到 https://doc.rust-lang.org/std/primitive.str.html#method.ceil_char_boundary 似乎是我需要的,但它目前仅在夜间可用,而且我不能在我当前的环境。)
按照 Eggyal 的建议,我最终或多或少地将 ceil_char_boundary 代码复制到我的项目中:
/// Returns a slice of the input string truncated to about index bytes on
/// a utf8 character boundary, to ensures the slice is a valid &str.
/// The slice may be up to 4 bytes longer if necessary to match the
/// character boundary. Returns the whole string if the string is
/// shorter than index.
fn truncate_at_char_boundary(input: &str, index: usize) -> &str {
let end = if index > input.len() {
input.len()
} else {
let upper_bound = Ord::min(index + 4, input.len());
input.as_bytes()[index..upper_bound]
.iter()
.position(|b| (*b as i8) >= -0x40) // byte is a char boundary
.map_or(upper_bound, |pos| pos + index)
};
&input[..end]
}
然后
write!(f, "{:>12}: {}", "user_id", truncate_at_char_boundary(&self.use r_id, 66) )