use dynstr::DynamicString; #[test] fn basic() { let str = "Hello World!"; let ec = DynamicString::new(str); assert_eq!(ec.len(), 12); assert_eq!(ec.has_one_byte_char(), true); assert_eq!(&String::from(ec), str); } #[test] fn unicode() { let str = "😴"; let ec = DynamicString::new(str); assert_eq!(ec.len(), 2); assert_eq!(ec.has_one_byte_char(), false); assert_eq!(&String::from(ec), str); let str = "😴😄😃⛔🎠🚓🚇"; let ec = DynamicString::new(str); assert_eq!(ec.len(), 13); assert_eq!(ec.has_one_byte_char(), false); assert_eq!(&String::from(ec), str); } #[test] fn iter_cons() { let simple = Box::new(DynamicString::new("012345")); let cons = DynamicString::ConsString { first: simple.clone(), second: simple.clone(), }; assert_eq!(&String::from(cons), "012345012345"); } #[test] fn iter_slice() { let simple = Box::new(DynamicString::new("0123456789")); let slice = DynamicString::SlicedString { root: simple.clone(), start: 0, length: 3, }; assert_eq!(&String::from(slice), "012"); let slice = DynamicString::SlicedString { root: simple.clone(), start: 1, length: 3, }; assert_eq!(&String::from(slice), "123"); let slice = DynamicString::SlicedString { root: simple.clone(), start: 7, length: 15, }; assert_eq!(&String::from(slice), "789"); } #[test] fn iter_cons_slice() { let cons = Box::new(DynamicString::ConsString { first: Box::new(DynamicString::new("012345")), second: Box::new(DynamicString::new("6789a")), }); // All in first half. let slice = DynamicString::SlicedString { root: cons.clone(), start: 2, length: 3, }; assert_eq!(&String::from(slice), "234"); // All in first half - edge. let slice = DynamicString::SlicedString { root: cons.clone(), start: 2, length: 4, }; assert_eq!(&String::from(slice), "2345"); // All in second part. let slice = DynamicString::SlicedString { root: cons.clone(), start: 6, length: 3, }; assert_eq!(&String::from(slice), "678"); // All in second part. let slice = DynamicString::SlicedString { root: cons.clone(), start: 7, length: 3, }; assert_eq!(&String::from(slice), "789"); let slice = DynamicString::SlicedString { root: cons.clone(), start: 5, length: 1, }; assert_eq!(&String::from(slice), "5"); let slice = DynamicString::SlicedString { root: cons.clone(), start: 6, length: 1, }; assert_eq!(&String::from(slice), "6"); let slice = DynamicString::SlicedString { root: cons.clone(), start: 5, length: 2, }; assert_eq!(&String::from(slice), "56"); let slice = DynamicString::SlicedString { root: cons.clone(), start: 2, length: 7, }; assert_eq!(&String::from(slice), "2345678"); } #[test] fn iter_cons_cons_slice() { let cons = DynamicString::ConsString { first: Box::new(DynamicString::new("012")), second: Box::new(DynamicString::ConsString { first: Box::new(DynamicString::new("345")), second: Box::new(DynamicString::new("678")), }), }; assert_eq!(&String::from(cons.clone()), "012345678"); let root = Box::new(cons); let slice = DynamicString::SlicedString { root: root.clone(), start: 0, length: 2, }; assert_eq!(&String::from(slice), "01"); let slice = DynamicString::SlicedString { root: root.clone(), start: 2, length: 2, }; assert_eq!(&String::from(slice), "23"); let slice = DynamicString::SlicedString { root: root.clone(), start: 4, length: 4, }; assert_eq!(&String::from(slice), "4567"); } #[test] fn iter_slice_slice() { // 2345678 let root = Box::new(DynamicString::SlicedString { root: Box::new(DynamicString::new("0123456789")), start: 2, length: 7, }); let slice = DynamicString::SlicedString { root: root.clone(), start: 1, length: 3, }; // 0123456789 <- root // |------ // (0123456) // |-- // 01[345]789 assert_eq!(&String::from(slice), "345"); let slice = DynamicString::SlicedString { root: root.clone(), start: 2, length: 5, }; assert_eq!(&String::from(slice), "45678"); let slice = DynamicString::SlicedString { root: root.clone(), start: 3, length: 5, }; // 0123456789 <- root // |------ // (0123456789) // |---x // 0123[5678] assert_eq!(&String::from(slice), "5678"); } #[test] fn iter_slice_slice_slice() { let root = Box::new(DynamicString::SlicedString { // 0123456789 root: Box::new(DynamicString::SlicedString { root: Box::new(DynamicString::new("abc0123456789def")), start: 3, length: 10, }), start: 2, length: 7, }); let slice = DynamicString::SlicedString { root: root.clone(), start: 1, length: 3, }; assert_eq!(&String::from(slice), "345"); let slice = DynamicString::SlicedString { root: root.clone(), start: 2, length: 5, }; assert_eq!(&String::from(slice), "45678"); let slice = DynamicString::SlicedString { root: root.clone(), start: 3, length: 5, }; assert_eq!(&String::from(slice), "5678"); } #[test] fn nth() { let sentence = { let str = "In formal language theory and computer programming, string concatenation is the operation of joining character strings end-to-end. For example, the concatenation of \"snow\" and \"ball\" is \"snowball\". Wikipedia"; let long = Box::new(DynamicString::new(str)); let computer = Box::new(DynamicString::SlicedString { root: long.clone(), start: 30, length: 8, }); let is = Box::new(DynamicString::SlicedString { root: long.clone(), start: 73, length: 2, }); let theory = Box::new(DynamicString::SlicedString { root: long.clone(), start: 19, length: 6, }); let space = Box::new(DynamicString::new(" ")); DynamicString::ConsString { first: computer, second: Box::new(DynamicString::ConsString { first: space.clone(), second: Box::new(DynamicString::ConsString { first: is, second: Box::new(DynamicString::ConsString { first: space.clone(), second: theory, }), }), }), } }; assert_eq!(&String::from(sentence.clone()), "computer is theory"); assert_eq!(sentence.iter().nth(0), Some(99)); assert_eq!(sentence.iter().nth(8), Some(32)); assert_eq!(sentence.iter().nth(11), Some(32)); assert_eq!(sentence.iter().nth(12), Some(116)); assert_eq!(sentence.iter().nth(15), Some(111)); assert_eq!(sentence.iter().nth(17), Some(121)); { let mut iter = sentence.iter(); // i = i-prev + nth + 1 assert_eq!(iter.nth(0), Some('c' as u16)); // i = 0 assert_eq!(iter.nth(0), Some('o' as u16)); // i = 0 + 0 + 1 = 1 assert_eq!(iter.nth(1), Some('p' as u16)); // i = 1 + 1 + 1 = 3 assert_eq!(iter.nth(3), Some('r' as u16)); // i = 3 + 3 + 1 = 7 assert_eq!(iter.nth(2), Some('s' as u16)); // i = 7 + 2 + 1 = 10 } { let ec = DynamicString::new("0123456789abcdef"); let mut iter = ec.iter(); assert_eq!(iter.nth(1), Some('1' as u16)); // i = 1 assert_eq!(iter.nth(1), Some('3' as u16)); // i = 1 + 1 + 1 = 3 assert_eq!(iter.nth(2), Some('6' as u16)); // i = 3 + 2 + 1 = 6 assert_eq!(iter.nth(3), Some('a' as u16)); // i = 6 + 3 + 1 = 10 } } #[test] fn hash() { use std::collections::hash_map::DefaultHasher; use std::hash::{Hash, Hasher}; fn hash(ec: &DynamicString) -> u64 { let mut hasher = DefaultHasher::new(); ec.hash(&mut hasher); hasher.finish() } assert_eq!( hash(&DynamicString::new("Hello")), hash(&DynamicString::new("Hello")) ); assert_eq!( hash(&DynamicString::new("World")), hash(&DynamicString::new("World")) ); assert_eq!( hash(&DynamicString::SlicedString { root: Box::new(DynamicString::new("Hello 😴")), start: 0, length: 5 }), hash(&DynamicString::new("Hello")) ); assert_eq!( hash(&DynamicString::SlicedString { root: Box::new(DynamicString::new("Hello 😴")), start: 0, length: 1 }), hash(&DynamicString::new("H")) ); assert_eq!( hash(&DynamicString::SlicedString { root: Box::new(DynamicString::new("Hello 😴")), start: 6, length: 2 }), hash(&DynamicString::new("😴")) ); } #[test] fn eq() { assert_eq!(DynamicString::new("Hello"), DynamicString::new("Hello")); assert_ne!(DynamicString::new("Hello"), DynamicString::new("World")); assert_eq!( DynamicString::SlicedString { root: Box::new(DynamicString::new("Hello 😴")), start: 0, length: 5 }, DynamicString::new("Hello") ); assert_eq!( DynamicString::SlicedString { root: Box::new(DynamicString::new("Hello 😴")), start: 0, length: 1 }, DynamicString::new("H") ); assert_eq!( DynamicString::SlicedString { root: Box::new(DynamicString::new("Hello 😴")), start: 6, length: 2 }, DynamicString::new("😴") ); }