1use std::fmt;
65use std::str::from_utf8_unchecked;
66
67mod iter;
68mod str_list;
69mod str_list_ref;
70#[cfg(feature = "serde")]
71mod with_serde;
72
73pub use iter::StrStackIter;
74pub use str_list::StrList;
75pub use str_list::StrListIter;
76pub use str_list_ref::StrListRef;
77pub use str_list_ref::StrListValidationError;
78
79#[derive(Copy, Clone, Debug, PartialEq, Eq)]
85pub struct Checkpoint {
86 items: u32,
87 bytes: u32,
88}
89
90#[derive(Debug, Clone)]
92pub struct StrStackOverflow {
93 attempted: usize,
94}
95
96impl fmt::Display for StrStackOverflow {
97 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
98 write!(
99 f,
100 "StrStack overflow: attempted total byte length {} exceeds u32::MAX",
101 self.attempted
102 )
103 }
104}
105
106#[derive(Clone, Default, PartialEq, Eq)]
107pub struct StrStack {
108 data: Vec<u8>,
109 ends: Vec<u32>,
110}
111
112impl StrStack {
113 #[inline]
114 pub fn new() -> Self {
115 Self::default()
116 }
117
118 #[inline]
121 pub fn with_capacity(items: usize, bytes: usize) -> Self {
122 Self {
123 data: Vec::with_capacity(bytes),
124 ends: Vec::with_capacity(items),
125 }
126 }
127
128 #[inline]
129 pub fn len(&self) -> usize {
130 self.ends.len()
131 }
132
133 #[inline]
134 pub fn is_empty(&self) -> bool {
135 self.ends.is_empty()
136 }
137
138 #[inline]
143 pub fn bytes_len(&self) -> u32 {
144 self.data.len() as u32
146 }
147
148 #[inline]
150 pub fn reserve_items(&mut self, additional: usize) {
151 self.ends.reserve(additional);
152 }
153
154 #[inline]
156 pub fn reserve_bytes(&mut self, additional: usize) {
157 self.data.reserve(additional);
158 }
159
160 #[inline]
161 pub fn as_str(&self) -> &str {
162 unsafe { from_utf8_unchecked(&self.data) }
165 }
166
167 #[inline]
168 pub fn get(&self, index: usize) -> Option<&str> {
169 let (begin, end) = self.get_bounds(index)?;
170 Some(unsafe { self.get_unchecked_internal(begin as usize, end as usize) })
173 }
174
175 #[inline]
176 #[deprecated(note = "Use `get()` instead. This will be removed in a future version.")]
184 pub unsafe fn get_unchecked(&self, begin: usize, end: usize) -> &str {
185 unsafe {
187 let slice = self.data.get_unchecked(begin..end);
188 from_utf8_unchecked(slice)
189 }
190 }
191
192 #[inline]
195 pub(crate) unsafe fn get_unchecked_internal(&self, begin: usize, end: usize) -> &str {
196 unsafe {
198 let slice = self.data.get_unchecked(begin..end);
199 from_utf8_unchecked(slice)
200 }
201 }
202
203 #[inline]
204 pub fn get_bounds(&self, index: usize) -> Option<(u32, u32)> {
205 if index + 1 > self.ends.len() {
206 return None;
207 }
208 let (start, end) = if index > 0 {
209 (self.ends[index - 1], self.ends[index])
210 } else {
211 (0, self.ends[0])
212 };
213 debug_assert!(start <= end);
214 debug_assert!((end as usize) <= self.data.len());
215 Some((start, end))
216 }
217
218 #[inline]
219 pub fn get_top(&self) -> Option<&str> {
220 match self.ends.len() {
221 0 => None,
222 len => self.get(len - 1),
223 }
224 }
225
226 #[inline]
230 pub fn last(&self) -> Option<&str> {
231 self.get_top()
232 }
233
234 #[inline]
235 pub fn remove_top(&mut self) -> Option<()> {
236 self.ends.pop()?;
237 let end = self.ends.last().copied().unwrap_or(0) as usize;
238 self.data.truncate(end);
239 Some(())
240 }
241
242 #[inline]
243 pub fn pop_owned<T>(&mut self) -> Option<T>
244 where
245 T: for<'a> From<&'a str>,
246 {
247 let s = self.get_top()?.into();
248 self.remove_top();
249 Some(s)
250 }
251
252 #[inline]
253 pub fn push(&mut self, s: &str) {
254 self.data.extend_from_slice(s.as_bytes());
255 let new_end: u32 = self
256 .data
257 .len()
258 .try_into()
259 .expect("StrStack: total byte length exceeds u32::MAX");
260 self.ends.push(new_end);
261 }
262
263 #[inline]
266 pub fn try_push(&mut self, s: &str) -> Result<(), StrStackOverflow> {
267 let new_len = self.data.len() + s.len();
268 let new_end: u32 = new_len
269 .try_into()
270 .map_err(|_| StrStackOverflow { attempted: new_len })?;
271 self.data.extend_from_slice(s.as_bytes());
272 self.ends.push(new_end);
273 Ok(())
274 }
275
276 #[inline]
281 pub fn clear(&mut self) {
282 self.data.clear();
283 self.ends.clear();
284 }
285
286 #[inline]
290 pub fn truncate(&mut self, len: usize) {
291 if len >= self.ends.len() {
292 return;
293 }
294 self.ends.truncate(len);
295 let byte_end = self.ends.last().copied().unwrap_or(0) as usize;
296 self.data.truncate(byte_end);
297 }
298
299 #[inline]
306 pub fn checkpoint(&self) -> Checkpoint {
307 Checkpoint {
308 items: self.ends.len() as u32,
309 bytes: self.data.len() as u32,
310 }
311 }
312
313 #[inline]
324 pub fn reset(&mut self, cp: Checkpoint) {
325 assert!(
326 cp.items as usize <= self.ends.len() && cp.bytes as usize <= self.data.len(),
327 "StrStack::reset: invalid checkpoint (items: {}, bytes: {}) for stack (items: {}, bytes: {})",
328 cp.items, cp.bytes, self.ends.len(), self.data.len()
329 );
330 self.ends.truncate(cp.items as usize);
331 self.data.truncate(cp.bytes as usize);
332 }
333
334 #[inline]
335 pub fn iter(&self) -> StrStackIter<'_> {
336 StrStackIter::new(self)
337 }
338
339 #[inline]
341 pub(crate) fn data_as_slice(&self) -> &[u8] {
342 &self.data
343 }
344
345 #[inline]
347 pub(crate) fn ends_as_slice(&self) -> &[u32] {
348 &self.ends
349 }
350}
351
352#[cfg(test)]
353mod tests {
354 use std::rc::Rc;
355
356 use super::*;
357 use crate::SmartString;
358
359 #[test]
360 fn test_create() {
361 let stack = StrStack::new();
362 assert_eq!(stack.len(), 0);
363 assert!(stack.is_empty());
364 assert_eq!(stack.get_top(), None);
365 assert_eq!(stack.get(0), None);
366 assert_eq!(stack.get_bounds(0), None);
367 }
368
369 #[test]
370 fn test_push() {
371 let mut stack = StrStack::new();
372
373 stack.push("123");
374 assert_eq!(stack.len(), 1);
375 assert!(!stack.is_empty());
376 assert_eq!(stack.get_top(), Some("123"));
377 assert_eq!(stack.get(0), Some("123"));
378 assert_eq!(stack.get_bounds(0), Some((0u32, 3u32)));
379 assert_eq!(stack.get(1), None);
380 assert_eq!(stack.get_bounds(1), None);
381
382 stack.push("456");
383 assert_eq!(stack.len(), 2);
384 assert!(!stack.is_empty());
385 assert_eq!(stack.get_top(), Some("456"));
386 assert_eq!(stack.get(0), Some("123"));
387 assert_eq!(stack.get_bounds(0), Some((0u32, 3u32)));
388 assert_eq!(stack.get(1), Some("456"));
389 assert_eq!(stack.get_bounds(1), Some((3u32, 6u32)));
390 assert_eq!(stack.get(2), None);
391 assert_eq!(stack.get_bounds(2), None);
392 }
393
394 #[test]
395 fn test_remove_top() {
396 let mut stack = StrStack::new();
397
398 stack.push("123");
399 stack.push("456");
400 stack.push("789");
401 assert_eq!(stack.len(), 3);
402
403 assert!(stack.remove_top().is_some());
404 assert_eq!(stack.len(), 2);
405 assert!(!stack.is_empty());
406 assert_eq!(stack.get_top(), Some("456"));
407 assert_eq!(stack.get(0), Some("123"));
408 assert_eq!(stack.get(1), Some("456"));
409 assert!(stack.get(2).is_none());
410 assert!(stack.get_bounds(2).is_none());
411
412 assert!(stack.remove_top().is_some());
413 assert_eq!(stack.len(), 1);
414 assert!(!stack.is_empty());
415 assert_eq!(stack.get_top(), Some("123"));
416 assert_eq!(stack.get(0), Some("123"));
417 assert!(stack.get(1).is_none());
418 assert!(stack.get_bounds(1).is_none());
419
420 assert!(stack.remove_top().is_some());
421 assert_eq!(stack.len(), 0);
422 assert!(stack.is_empty());
423 assert!(stack.get_top().is_none());
424 assert!(stack.get(0).is_none());
425 assert!(stack.get_bounds(0).is_none());
426
427 assert!(stack.remove_top().is_none());
428 }
429
430 #[test]
431 fn test_pop_owned() {
432 let mut stack = StrStack::new();
433
434 stack.push("123");
435 stack.push("456");
436 stack.push("789");
437 assert_eq!(stack.len(), 3);
438
439 assert_eq!(stack.pop_owned::<String>(), Some("789".into()));
440 assert_eq!(stack.len(), 2);
441 assert_eq!(stack.get_top(), Some("456"));
442 assert_eq!(stack.get(0), Some("123"));
443 assert_eq!(stack.get(1), Some("456"));
444 assert!(stack.get(2).is_none());
445 assert!(stack.get_bounds(2).is_none());
446
447 assert_eq!(stack.pop_owned::<SmartString>(), Some("456".into()));
448 assert_eq!(stack.len(), 1);
449 assert_eq!(stack.get_top(), Some("123"));
450 assert_eq!(stack.get(0), Some("123"));
451 assert!(stack.get(1).is_none());
452 assert!(stack.get_bounds(1).is_none());
453
454 assert_eq!(stack.pop_owned::<Rc<str>>(), Some("123".into()));
455 assert_eq!(stack.len(), 0);
456 assert!(stack.get_top().is_none());
457 assert!(stack.get(0).is_none());
458 assert!(stack.get_bounds(0).is_none());
459
460 assert!(stack.pop_owned::<Box<str>>().is_none());
461 }
462
463 #[test]
464 fn test_iter() {
465 let mut stack = StrStack::new();
466
467 stack.push("123");
468 stack.push("456");
469 stack.push("789");
470
471 let mut iter = stack.iter();
472 assert_eq!(iter.next(), Some("123"));
473 assert_eq!(iter.next(), Some("456"));
474 assert_eq!(iter.next(), Some("789"));
475 assert_eq!(iter.next(), None);
476 assert_eq!(iter.next(), None);
477 }
478
479 #[test]
480 fn test_unicode_push_get_bounds_and_as_str() {
481 let mut stack = StrStack::new();
482 stack.push("β¬"); stack.push("a"); stack.push("π"); assert_eq!(stack.as_str(), "β¬aπ");
487
488 assert_eq!(stack.get(0), Some("β¬"));
489 assert_eq!(stack.get(1), Some("a"));
490 assert_eq!(stack.get(2), Some("π"));
491
492 assert_eq!(stack.get_bounds(0), Some((0u32, 3u32)));
493 assert_eq!(stack.get_bounds(1), Some((3u32, 4u32)));
494 assert_eq!(stack.get_bounds(2), Some((4u32, 8u32)));
495 }
496
497 #[test]
498 fn test_unicode_remove_top_truncates_byte_buffer() {
499 let mut stack = StrStack::new();
500 stack.push("β¬"); stack.push("π"); stack.push("a"); assert_eq!(stack.as_str(), "β¬πa");
505 assert_eq!(stack.len(), 3);
506
507 stack.remove_top().unwrap();
508 assert_eq!(stack.as_str(), "β¬π");
509 assert_eq!(stack.len(), 2);
510 assert_eq!(stack.get_top(), Some("π"));
511
512 stack.remove_top().unwrap();
513 assert_eq!(stack.as_str(), "β¬");
514 assert_eq!(stack.len(), 1);
515 assert_eq!(stack.get_top(), Some("β¬"));
516 }
517
518 #[test]
521 fn test_push_remove_push_sequence() {
522 let mut stack = StrStack::new();
523 stack.push("aaa");
524 stack.push("bbb");
525 stack.push("ccc");
526 assert_eq!(stack.len(), 3);
527
528 stack.remove_top();
530 stack.remove_top();
531 assert_eq!(stack.len(), 1);
532 assert_eq!(stack.as_str(), "aaa");
533 assert_eq!(stack.get(0), Some("aaa"));
534
535 stack.push("ddd");
537 stack.push("eee");
538 assert_eq!(stack.len(), 3);
539 assert_eq!(stack.as_str(), "aaadddeee");
540 assert_eq!(stack.get(0), Some("aaa"));
541 assert_eq!(stack.get(1), Some("ddd"));
542 assert_eq!(stack.get(2), Some("eee"));
543
544 let collected: Vec<&str> = stack.iter().collect();
546 assert_eq!(collected, vec!["aaa", "ddd", "eee"]);
547 }
548
549 #[test]
550 fn test_push_remove_all_push_again() {
551 let mut stack = StrStack::new();
552 stack.push("first");
553 stack.push("second");
554
555 stack.remove_top();
556 stack.remove_top();
557 assert!(stack.is_empty());
558 assert_eq!(stack.as_str(), "");
559
560 stack.push("third");
561 assert_eq!(stack.len(), 1);
562 assert_eq!(stack.get(0), Some("third"));
563 assert_eq!(stack.as_str(), "third");
564 }
565
566 #[test]
567 fn test_push_remove_push_unicode() {
568 let mut stack = StrStack::new();
569 stack.push("δ½ ε₯½"); stack.push("δΈη"); assert_eq!(stack.as_str(), "δ½ ε₯½δΈη");
572
573 stack.remove_top();
574 assert_eq!(stack.as_str(), "δ½ ε₯½");
575
576 stack.push("π¦"); assert_eq!(stack.as_str(), "δ½ ε₯½π¦");
578 assert_eq!(stack.get(0), Some("δ½ ε₯½"));
579 assert_eq!(stack.get(1), Some("π¦"));
580
581 let collected: Vec<&str> = stack.iter().collect();
582 assert_eq!(collected, vec!["δ½ ε₯½", "π¦"]);
583 }
584
585 #[test]
586 fn test_as_str_equals_iter_concatenation() {
587 let mut stack = StrStack::new();
588 stack.push("abc");
589 stack.push("β¬");
590 stack.push("def");
591 stack.remove_top();
592 stack.push("ghi");
593 stack.push("π");
594
595 let concatenated: String = stack.iter().collect();
596 assert_eq!(stack.as_str(), concatenated.as_str());
597 }
598
599 #[test]
602 fn test_clear() {
603 let mut stack = StrStack::new();
604 stack.push("hello");
605 stack.push("world");
606 assert_eq!(stack.len(), 2);
607
608 stack.remove_top();
612 stack.remove_top();
613 assert!(stack.is_empty());
614 assert_eq!(stack.len(), 0);
615 assert_eq!(stack.as_str(), "");
616 assert!(stack.iter().next().is_none());
617
618 stack.push("new");
620 assert_eq!(stack.len(), 1);
621 assert_eq!(stack.get(0), Some("new"));
622 }
623
624 #[test]
627 fn test_push_empty_strings() {
628 let mut stack = StrStack::new();
629 stack.push("");
630 stack.push("abc");
631 stack.push("");
632
633 assert_eq!(stack.len(), 3);
634 assert_eq!(stack.get(0), Some(""));
635 assert_eq!(stack.get(1), Some("abc"));
636 assert_eq!(stack.get(2), Some(""));
637 assert_eq!(stack.as_str(), "abc");
638
639 let collected: Vec<&str> = stack.iter().collect();
640 assert_eq!(collected, vec!["", "abc", ""]);
641 }
642
643 #[test]
646 fn test_with_capacity() {
647 let stack = StrStack::with_capacity(10, 100);
648 assert_eq!(stack.len(), 0);
649 assert!(stack.is_empty());
650 }
651
652 #[test]
653 fn test_bytes_len() {
654 let mut stack = StrStack::new();
655 assert_eq!(stack.bytes_len(), 0);
656 stack.push("abc"); assert_eq!(stack.bytes_len(), 3);
658 stack.push("β¬"); assert_eq!(stack.bytes_len(), 6);
660 stack.push("π"); assert_eq!(stack.bytes_len(), 10);
662 }
663
664 #[test]
665 fn test_last() {
666 let mut stack = StrStack::new();
667 assert_eq!(stack.last(), None);
668 stack.push("first");
669 assert_eq!(stack.last(), Some("first"));
670 stack.push("second");
671 assert_eq!(stack.last(), Some("second"));
672 assert_eq!(stack.last(), stack.get_top());
674 }
675
676 #[test]
677 fn test_clear_public() {
678 let mut stack = StrStack::new();
679 stack.push("hello");
680 stack.push("world");
681 assert_eq!(stack.len(), 2);
682 assert_eq!(stack.bytes_len(), 10);
683
684 stack.clear();
685 assert!(stack.is_empty());
686 assert_eq!(stack.len(), 0);
687 assert_eq!(stack.bytes_len(), 0);
688 assert_eq!(stack.as_str(), "");
689
690 stack.push("new");
692 assert_eq!(stack.len(), 1);
693 assert_eq!(stack.get(0), Some("new"));
694 }
695
696 #[test]
697 fn test_truncate() {
698 let mut stack = StrStack::new();
699 stack.push("aaa");
700 stack.push("bbb");
701 stack.push("ccc");
702 stack.push("ddd");
703 assert_eq!(stack.len(), 4);
704
705 stack.truncate(2);
707 assert_eq!(stack.len(), 2);
708 assert_eq!(stack.get(0), Some("aaa"));
709 assert_eq!(stack.get(1), Some("bbb"));
710 assert_eq!(stack.get(2), None);
711 assert_eq!(stack.as_str(), "aaabbb");
712 }
713
714 #[test]
715 fn test_truncate_noop() {
716 let mut stack = StrStack::new();
717 stack.push("aaa");
718 stack.push("bbb");
719
720 stack.truncate(5);
722 assert_eq!(stack.len(), 2);
723 stack.truncate(2);
724 assert_eq!(stack.len(), 2);
725 }
726
727 #[test]
728 fn test_truncate_to_zero() {
729 let mut stack = StrStack::new();
730 stack.push("aaa");
731 stack.push("bbb");
732
733 stack.truncate(0);
734 assert!(stack.is_empty());
735 assert_eq!(stack.as_str(), "");
736 }
737
738 #[test]
739 fn test_truncate_unicode() {
740 let mut stack = StrStack::new();
741 stack.push("δ½ ε₯½"); stack.push("δΈη"); stack.push("π¦"); stack.truncate(1);
746 assert_eq!(stack.len(), 1);
747 assert_eq!(stack.get(0), Some("δ½ ε₯½"));
748 assert_eq!(stack.bytes_len(), 6);
749 }
750
751 #[test]
752 fn test_try_push_success() {
753 let mut stack = StrStack::new();
754 assert!(stack.try_push("hello").is_ok());
755 assert_eq!(stack.len(), 1);
756 assert_eq!(stack.get(0), Some("hello"));
757 }
758
759 #[test]
760 fn test_reserve() {
761 let mut stack = StrStack::new();
762 stack.reserve_items(10);
763 stack.reserve_bytes(100);
764 assert_eq!(stack.len(), 0);
766 assert!(stack.is_empty());
767 for i in 0..10 {
769 stack.push(&format!("{}", i));
770 }
771 assert_eq!(stack.len(), 10);
772 }
773
774 #[test]
777 fn test_checkpoint_basic() {
778 let mut stack = StrStack::new();
779 stack.push("aaa");
780 stack.push("bbb");
781 let cp = stack.checkpoint();
782
783 stack.push("ccc");
784 stack.push("ddd");
785 assert_eq!(stack.len(), 4);
786
787 stack.reset(cp);
788 assert_eq!(stack.len(), 2);
789 assert_eq!(stack.get(0), Some("aaa"));
790 assert_eq!(stack.get(1), Some("bbb"));
791 assert_eq!(stack.get(2), None);
792 assert_eq!(stack.as_str(), "aaabbb");
793 }
794
795 #[test]
796 fn test_checkpoint_empty_stack() {
797 let mut stack = StrStack::new();
798 let cp = stack.checkpoint();
799
800 stack.push("aaa");
801 stack.push("bbb");
802 assert_eq!(stack.len(), 2);
803
804 stack.reset(cp);
805 assert!(stack.is_empty());
806 assert_eq!(stack.as_str(), "");
807 }
808
809 #[test]
810 fn test_checkpoint_at_end_is_noop() {
811 let mut stack = StrStack::new();
812 stack.push("aaa");
813 stack.push("bbb");
814 let cp = stack.checkpoint();
815
816 stack.reset(cp);
818 assert_eq!(stack.len(), 2);
819 assert_eq!(stack.get(0), Some("aaa"));
820 assert_eq!(stack.get(1), Some("bbb"));
821 }
822
823 #[test]
824 fn test_checkpoint_nested() {
825 let mut stack = StrStack::new();
826 stack.push("aaa");
827 let cp1 = stack.checkpoint();
828
829 stack.push("bbb");
830 let cp2 = stack.checkpoint();
831
832 stack.push("ccc");
833 assert_eq!(stack.len(), 3);
834
835 stack.reset(cp2);
837 assert_eq!(stack.len(), 2);
838 assert_eq!(stack.last(), Some("bbb"));
839
840 stack.reset(cp1);
842 assert_eq!(stack.len(), 1);
843 assert_eq!(stack.last(), Some("aaa"));
844 }
845
846 #[test]
847 fn test_checkpoint_unicode() {
848 let mut stack = StrStack::new();
849 stack.push("δ½ ε₯½"); let cp = stack.checkpoint();
851
852 stack.push("π"); stack.push("π¦"); assert_eq!(stack.bytes_len(), 14);
855
856 stack.reset(cp);
857 assert_eq!(stack.len(), 1);
858 assert_eq!(stack.get(0), Some("δ½ ε₯½"));
859 assert_eq!(stack.bytes_len(), 6);
860 }
861
862 #[test]
863 fn test_checkpoint_then_push_after_reset() {
864 let mut stack = StrStack::new();
865 stack.push("aaa");
866 let cp = stack.checkpoint();
867
868 stack.push("bbb");
869 stack.reset(cp);
870
871 stack.push("ccc");
873 assert_eq!(stack.len(), 2);
874 assert_eq!(stack.get(0), Some("aaa"));
875 assert_eq!(stack.get(1), Some("ccc"));
876 assert_eq!(stack.as_str(), "aaaccc");
877 }
878
879 #[test]
880 fn test_truncate_preserves_earlier_checkpoint() {
881 let mut stack = StrStack::new();
882 stack.push("aaa");
883 let cp = stack.checkpoint();
884
885 stack.push("bbb");
886 stack.push("ccc");
887 stack.push("ddd");
888
889 stack.truncate(3);
891 assert_eq!(stack.len(), 3);
892
893 stack.reset(cp);
895 assert_eq!(stack.len(), 1);
896 assert_eq!(stack.get(0), Some("aaa"));
897 }
898
899 #[test]
900 #[should_panic(expected = "invalid checkpoint")]
901 fn test_reset_stale_checkpoint_panics() {
902 let mut stack = StrStack::new();
903 stack.push("aaa");
904 stack.push("bbb");
905 stack.push("ccc");
906 let cp_late = stack.checkpoint(); stack.truncate(0);
910 assert!(stack.is_empty());
911
912 stack.reset(cp_late);
914 }
915}