use lean_string::LeanStr;
use std::borrow::Cow;
const INLINE_LIMIT: usize = size_of::<LeanStr>();
#[test]
fn new_empty() {
assert_eq!(LeanStr::new(), "");
let s = LeanStr::new();
assert_eq!(s.as_str(), "");
assert!(s.is_empty());
assert_eq!(s.len(), 0);
assert!(!s.is_heap_allocated());
assert_eq!(LeanStr::default(), "");
}
#[test]
fn from_char() {
assert_eq!(LeanStr::from('a'), "a");
assert_eq!(LeanStr::from('👍'), "👍");
assert_eq!(LeanStr::from(''), "");
}
#[test]
fn from_char_utf8_length_boundaries() {
let chars = [
'\0',
'a',
'\u{7F}',
'\u{80}',
'é',
'\u{7FF}',
'\u{800}',
'あ',
'\u{FFFF}',
'\u{10000}',
'🦀',
'\u{10FFFF}',
];
for ch in chars {
let s = LeanStr::from(ch);
assert_eq!(s, String::from(ch));
assert_eq!(s.len(), ch.len_utf8());
assert!(!s.is_heap_allocated());
}
}
#[test]
fn from_around_inline_limit() {
let s = &String::from("0123456789abcdefg");
let inline = LeanStr::from(&s[..INLINE_LIMIT - 1]);
assert_eq!(inline, s[..INLINE_LIMIT - 1]);
assert_eq!(inline.len(), INLINE_LIMIT - 1);
assert!(!inline.is_heap_allocated());
let inline = LeanStr::from(&s[..INLINE_LIMIT]);
assert_eq!(inline, s[..INLINE_LIMIT]);
assert_eq!(inline.len(), INLINE_LIMIT);
assert!(!inline.is_heap_allocated());
let heap = LeanStr::from(&s[..INLINE_LIMIT + 1]);
assert_eq!(heap, s[..INLINE_LIMIT + 1]);
assert_eq!(heap.len(), INLINE_LIMIT + 1);
assert!(heap.is_heap_allocated());
}
#[test]
fn from_static_str_around_inline_limit() {
let s: &'static str = "0123456789abcdefg";
let inline = LeanStr::from_static_str(&s[..INLINE_LIMIT - 1]);
assert_eq!(inline, s[..INLINE_LIMIT - 1]);
assert!(!inline.is_heap_allocated());
let inline = LeanStr::from_static_str(&s[..INLINE_LIMIT]);
assert_eq!(inline, s[..INLINE_LIMIT]);
assert!(!inline.is_heap_allocated());
let static_ = LeanStr::from_static_str(&s[..INLINE_LIMIT + 1]);
assert_eq!(static_, s[..INLINE_LIMIT + 1]);
assert!(!static_.is_heap_allocated());
}
#[test]
fn into_cow_borrows_static() {
let s = LeanStr::from_static_str("A static str that is longer than inline limit");
assert!(matches!(Cow::from(s), Cow::Borrowed(_)));
}
#[test]
fn clone_shares_heap_buffer() {
let s = LeanStr::from("abcdefghijklmnopqrstuvwxyz");
let cloned = s.clone();
assert_eq!(s.as_ptr(), cloned.as_ptr());
drop(s);
assert_eq!(cloned, "abcdefghijklmnopqrstuvwxyz");
}
#[test]
fn repeat_around_inline() {
let s = LeanStr::from("a");
assert!(!s.is_heap_allocated());
assert_eq!(s.repeat(1), "a");
let inline = s.repeat(INLINE_LIMIT);
assert_eq!(inline, "a".repeat(INLINE_LIMIT));
assert!(!inline.is_heap_allocated());
let heap = s.repeat(INLINE_LIMIT + 1);
assert_eq!(heap, "a".repeat(INLINE_LIMIT + 1));
assert!(heap.is_heap_allocated());
}
#[test]
fn repeat_zero_or_empty() {
let inline = LeanStr::from("ab");
assert!(!inline.is_heap_allocated());
assert_eq!(inline.repeat(0), "");
assert!(!inline.repeat(0).is_heap_allocated());
let heap = LeanStr::from("a".repeat(INLINE_LIMIT + 1).as_str());
assert!(heap.is_heap_allocated());
assert_eq!(heap.repeat(0), "");
assert!(!heap.repeat(0).is_heap_allocated());
let empty = LeanStr::new();
assert_eq!(empty.repeat(0), "");
assert_eq!(empty.repeat(1), "");
assert_eq!(empty.repeat(100), "");
}
#[test]
fn repeat_heap() {
let s = LeanStr::from("a".repeat(INLINE_LIMIT + 1).as_str());
assert!(s.is_heap_allocated());
let r1 = s.repeat(1);
assert_eq!(r1, s);
assert_eq!(r1.as_ptr(), s.as_ptr());
let r2 = s.repeat(2);
assert_eq!(r2.len(), s.len() * 2);
assert!(r2.is_heap_allocated());
let r5 = s.repeat(5);
assert_eq!(r5.len(), s.len() * 5);
assert!(r5.is_heap_allocated());
}
#[test]
fn repeat_static() {
let s = LeanStr::from_static_str("0123456789abcdefghijklmnopqrstuvwxyz");
assert!(!s.is_heap_allocated());
assert!(s.as_static_str().is_some());
let r1 = s.repeat(1);
assert!(!r1.is_heap_allocated());
assert_eq!(r1.as_static_str(), s.as_static_str());
let r2 = s.repeat(2);
assert!(r2.is_heap_allocated());
assert_eq!(r2, s.as_str().repeat(2))
}
#[test]
fn try_repeat_overflow_is_err() {
let s = LeanStr::from("ab");
assert!(s.try_repeat(usize::MAX).is_err());
}
#[test]
fn case_conversion_around_inline() {
let inline = "a".repeat(INLINE_LIMIT - 1) + "A";
let inline = LeanStr::from(inline.as_str()).to_lowercase();
assert_eq!(inline, "a".repeat(INLINE_LIMIT));
assert!(!inline.is_heap_allocated());
let heap = "A".repeat(INLINE_LIMIT) + "a";
let heap = LeanStr::from(heap.as_str()).to_uppercase();
assert_eq!(heap, "A".repeat(INLINE_LIMIT + 1));
assert!(heap.is_heap_allocated());
}
#[test]
fn case_conversion_without_change_shares_buffer() {
let non_ascii = LeanStr::from("déjà lowercase and heap allocated");
assert!(non_ascii.is_heap_allocated());
assert_eq!(non_ascii.to_lowercase().as_ptr(), non_ascii.as_ptr());
let static_ = LeanStr::from_static_str("DÉJÀ UPPERCASE AND STATIC");
assert!(static_.to_uppercase().as_static_str().is_some());
}
#[test]
fn case_conversion_static() {
let static_ = LeanStr::from_static_str("Déjà Mixed Case And Static");
let upper = static_.to_uppercase();
assert_eq!(upper, "DÉJÀ MIXED CASE AND STATIC");
assert!(upper.as_static_str().is_none());
assert_eq!(static_, "Déjà Mixed Case And Static");
}
#[test]
fn ascii_case_conversion_around_inline() {
let inline = "a".repeat(INLINE_LIMIT - 1) + "A";
let inline = LeanStr::from(inline.as_str()).to_ascii_lowercase();
assert_eq!(inline, "a".repeat(INLINE_LIMIT));
assert!(!inline.is_heap_allocated());
let heap = "A".repeat(INLINE_LIMIT) + "a";
let heap = LeanStr::from(heap.as_str()).to_ascii_uppercase();
assert_eq!(heap, "A".repeat(INLINE_LIMIT + 1));
assert!(heap.is_heap_allocated());
}
#[test]
fn ascii_case_conversion_without_change_shares_buffer() {
let heap = LeanStr::from("already lowercase and heap allocated");
assert!(heap.is_heap_allocated());
assert_eq!(heap.to_ascii_lowercase().as_ptr(), heap.as_ptr());
let static_ = LeanStr::from_static_str("ALREADY UPPERCASE AND STATIC");
assert!(static_.to_ascii_uppercase().as_static_str().is_some());
}
#[test]
fn ascii_case_conversion_static() {
let static_ = LeanStr::from_static_str("Mixed Case And Static");
let upper = static_.to_ascii_uppercase();
assert_eq!(upper, "MIXED CASE AND STATIC");
assert!(upper.as_static_str().is_none());
assert_eq!(static_, "Mixed Case And Static");
}