Imports name this capability’s declared dependencies, which fune builds next to it in your project; each one links to its page.
use super::funejson::Value; ← the fune runtime: the JSON value the test vectors use; fune build keeps it only where a signature takes one
/// The Unicode White_Space property, spelled out so all three languages agree.
/// It happens to match `char::is_whitespace`, but JavaScript's \s and Python's
/// str.isspace draw the line differently, so the list is explicit everywhere.
fn is_whitespace(ch: char) -> bool {
let cp = ch as u32;
(0x09..=0x0d).contains(&cp)
|| cp == 0x20
|| cp == 0x85
|| cp == 0xa0
|| cp == 0x1680
|| (0x2000..=0x200a).contains(&cp)
|| cp == 0x2028
|| cp == 0x2029
|| cp == 0x202f
|| cp == 0x205f
|| cp == 0x3000
}
/// Punctuation that reads badly directly before an ellipsis.
fn is_trailing_punctuation(ch: char) -> bool {
matches!(ch, ',' | ';' | ':' | '-' | '.')
}
/// Shorten `value` to at most `max_length` code points, ellipsis included,
/// cutting at a word boundary where there is one.
///
/// # Panics
/// Panics if `max_length` is negative or shorter than the ellipsis.
pub fn truncate(value: &str, max_length: i64, ellipsis: &str) -> String {
if max_length < 0 {
panic!("maxLength must be 0 or greater, received {}", max_length);
}
let chars: Vec<char> = value.chars().collect();
let mark_len = ellipsis.chars().count() as i64;
if mark_len > max_length {
panic!(
"maxLength must be at least the length of the ellipsis, received {}",
max_length
);
}
if chars.len() as i64 <= max_length {
return value.to_string();
}
let budget = (max_length - mark_len) as usize;
let mut end = budget;
// A cut just before whitespace is already a clean boundary.
if !is_whitespace(chars[budget]) {
// No boundary to move back to (none, or only at position 0): one long
// word is cut hard rather than reduced to a bare ellipsis.
if let Some(last_space) = (0..budget).rev().find(|&i| is_whitespace(chars[i])) {
if last_space > 0 {
end = last_space;
}
}
}
while end > 0 && (is_whitespace(chars[end - 1]) || is_trailing_punctuation(chars[end - 1])) {
end -= 1;
}
let mut out: String = chars[..end].iter().collect();
out.push_str(ellipsis);
out
}
pub fn fune_vector(args: &[Value]) -> Value {
Value::Str(truncate(args[0].as_str(), args[1].as_i64(), args[2].as_str()))
}