1use std::borrow::{Borrow, Cow};
2use std::fmt::{Debug, Display, Formatter, Write};
3use std::hash::{Hash, Hasher};
4use std::ops::Deref;
5
6use crate::Expr;
7use crate::generated::ExprName;
8
9#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[cfg_attr(feature = "cache", derive(ruff_macros::CacheKey))]
12#[cfg_attr(feature = "salsa", derive(salsa::Update))]
13#[cfg_attr(feature = "get-size", derive(get_size2::GetSize))]
14#[cfg_attr(
15 feature = "schemars",
16 derive(schemars::JsonSchema),
17 schemars(with = "String")
18)]
19pub struct Name(compact_str::CompactString);
20
21impl Name {
22 #[inline]
23 pub fn empty() -> Self {
24 Self(compact_str::CompactString::default())
25 }
26
27 #[inline]
28 pub fn new(name: impl AsRef<str>) -> Self {
29 Self(compact_str::CompactString::new(name))
30 }
31
32 #[inline]
33 pub const fn new_static(name: &'static str) -> Self {
34 Self(compact_str::CompactString::const_new(name))
35 }
36
37 pub fn shrink_to_fit(&mut self) {
38 self.0.shrink_to_fit();
39 }
40
41 pub fn as_str(&self) -> &str {
42 self.0.as_str()
43 }
44
45 pub fn push_str(&mut self, s: &str) {
46 self.0.push_str(s);
47 }
48}
49
50impl Debug for Name {
51 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
52 write!(f, "Name({:?})", self.as_str())
53 }
54}
55
56impl std::fmt::Write for Name {
57 fn write_str(&mut self, s: &str) -> std::fmt::Result {
58 self.0.push_str(s);
59 Ok(())
60 }
61}
62
63impl AsRef<str> for Name {
64 #[inline]
65 fn as_ref(&self) -> &str {
66 self.as_str()
67 }
68}
69
70impl Deref for Name {
71 type Target = str;
72
73 #[inline]
74 fn deref(&self) -> &Self::Target {
75 self.as_str()
76 }
77}
78
79impl Borrow<str> for Name {
80 #[inline]
81 fn borrow(&self) -> &str {
82 self.as_str()
83 }
84}
85
86impl<'a> From<&'a str> for Name {
87 #[inline]
88 fn from(s: &'a str) -> Self {
89 Name(s.into())
90 }
91}
92
93impl From<String> for Name {
94 #[inline]
95 fn from(s: String) -> Self {
96 Name(s.into())
97 }
98}
99
100impl<'a> From<&'a String> for Name {
101 #[inline]
102 fn from(s: &'a String) -> Self {
103 Name(s.into())
104 }
105}
106
107impl<'a> From<Cow<'a, str>> for Name {
108 #[inline]
109 fn from(cow: Cow<'a, str>) -> Self {
110 Name(cow.into())
111 }
112}
113
114impl From<Box<str>> for Name {
115 #[inline]
116 fn from(b: Box<str>) -> Self {
117 Name(b.into())
118 }
119}
120
121impl From<compact_str::CompactString> for Name {
122 #[inline]
123 fn from(value: compact_str::CompactString) -> Self {
124 Self(value)
125 }
126}
127
128impl From<Name> for compact_str::CompactString {
129 #[inline]
130 fn from(name: Name) -> Self {
131 name.0
132 }
133}
134
135impl From<Name> for String {
136 #[inline]
137 fn from(name: Name) -> Self {
138 name.as_str().into()
139 }
140}
141
142impl FromIterator<char> for Name {
143 fn from_iter<I: IntoIterator<Item = char>>(iter: I) -> Self {
144 Self(iter.into_iter().collect())
145 }
146}
147
148impl std::fmt::Display for Name {
149 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
150 f.write_str(self.as_str())
151 }
152}
153
154impl PartialEq<str> for Name {
155 #[inline]
156 fn eq(&self, other: &str) -> bool {
157 self.as_str() == other
158 }
159}
160
161impl PartialEq<Name> for str {
162 #[inline]
163 fn eq(&self, other: &Name) -> bool {
164 other == self
165 }
166}
167
168impl PartialEq<&str> for Name {
169 #[inline]
170 fn eq(&self, other: &&str) -> bool {
171 self.as_str() == *other
172 }
173}
174
175impl PartialEq<Name> for &str {
176 #[inline]
177 fn eq(&self, other: &Name) -> bool {
178 other == self
179 }
180}
181
182impl PartialEq<String> for Name {
183 fn eq(&self, other: &String) -> bool {
184 self == other.as_str()
185 }
186}
187
188impl PartialEq<Name> for String {
189 #[inline]
190 fn eq(&self, other: &Name) -> bool {
191 other == self
192 }
193}
194
195impl PartialEq<&String> for Name {
196 #[inline]
197 fn eq(&self, other: &&String) -> bool {
198 self.as_str() == *other
199 }
200}
201
202impl PartialEq<Name> for &String {
203 #[inline]
204 fn eq(&self, other: &Name) -> bool {
205 other == self
206 }
207}
208
209#[derive(Debug, Clone, PartialEq, Eq, Hash)]
211pub struct QualifiedName<'a>(SegmentsVec<'a>);
212
213impl<'a> QualifiedName<'a> {
214 #[inline]
223 pub fn from_dotted_name(name: &'a str) -> Self {
224 if let Some(dot) = name.find('.') {
225 let mut builder = QualifiedNameBuilder::default();
226 builder.push(&name[..dot]);
227 builder.extend(name[dot + 1..].split('.'));
228 builder.build()
229 } else {
230 Self::builtin(name)
231 }
232 }
233
234 #[inline]
236 pub fn user_defined(name: &'a str) -> Self {
237 name.split('.').collect()
238 }
239
240 #[inline]
242 pub fn builtin(name: &'a str) -> Self {
243 debug_assert!(!name.contains('.'));
244 Self(SegmentsVec::Stack(SegmentsStack::from_slice(&["", name])))
245 }
246
247 #[inline]
248 pub fn segments(&self) -> &[&'a str] {
249 self.0.as_slice()
250 }
251
252 fn is_builtin(&self) -> bool {
261 matches!(self.segments(), ["", ..])
262 }
263
264 pub fn is_unresolved_import(&self) -> bool {
267 matches!(self.segments(), [".", ..])
268 }
269
270 pub fn starts_with(&self, other: &QualifiedName<'_>) -> bool {
271 self.segments().starts_with(other.segments())
272 }
273
274 #[must_use]
276 pub fn append_member(self, member: &'a str) -> Self {
277 let mut inner = self.0;
278 inner.push(member);
279 Self(inner)
280 }
281
282 #[must_use]
284 pub fn extend_members<T: IntoIterator<Item = &'a str>>(self, members: T) -> Self {
285 let mut inner = self.0;
286 inner.extend(members);
287 Self(inner)
288 }
289}
290
291impl Display for QualifiedName<'_> {
292 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
293 let segments = self.segments();
294
295 if self.is_unresolved_import() {
296 let mut iter = segments.iter();
297 for segment in iter.by_ref() {
298 if *segment == "." {
299 f.write_char('.')?;
300 } else {
301 f.write_str(segment)?;
302 break;
303 }
304 }
305 for segment in iter {
306 f.write_char('.')?;
307 f.write_str(segment)?;
308 }
309 } else {
310 let segments = if self.is_builtin() {
311 &segments[1..]
312 } else {
313 segments
314 };
315
316 let mut first = true;
317 for segment in segments {
318 if !first {
319 f.write_char('.')?;
320 }
321
322 f.write_str(segment)?;
323 first = false;
324 }
325 }
326
327 Ok(())
328 }
329}
330
331impl<'a> FromIterator<&'a str> for QualifiedName<'a> {
332 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
333 Self(SegmentsVec::from_iter(iter))
334 }
335}
336
337#[derive(Debug, Clone, Default)]
338pub struct QualifiedNameBuilder<'a> {
339 segments: SegmentsVec<'a>,
340}
341
342impl<'a> QualifiedNameBuilder<'a> {
343 pub fn with_capacity(capacity: usize) -> Self {
344 Self {
345 segments: SegmentsVec::with_capacity(capacity),
346 }
347 }
348
349 #[inline]
350 pub fn is_empty(&self) -> bool {
351 self.segments.is_empty()
352 }
353
354 #[inline]
355 pub fn push(&mut self, segment: &'a str) {
356 self.segments.push(segment);
357 }
358
359 #[inline]
360 pub fn pop(&mut self) {
361 self.segments.pop();
362 }
363
364 #[inline]
365 pub fn extend(&mut self, segments: impl IntoIterator<Item = &'a str>) {
366 self.segments.extend(segments);
367 }
368
369 #[inline]
370 pub fn extend_from_slice(&mut self, segments: &[&'a str]) {
371 self.segments.extend_from_slice(segments);
372 }
373
374 pub fn build(self) -> QualifiedName<'a> {
375 QualifiedName(self.segments)
376 }
377}
378
379#[derive(Debug, Clone, PartialEq, Eq, Hash)]
380pub struct UnqualifiedName<'a>(SegmentsVec<'a>);
381
382impl<'a> UnqualifiedName<'a> {
383 pub fn from_expr(expr: &'a Expr) -> Option<Self> {
385 let attr1 = match expr {
388 Expr::Attribute(attr1) => attr1,
389 Expr::Name(ExprName { id, .. }) => return Some(Self::from_slice(&[id.as_str()])),
391 _ => return None,
392 };
393
394 let attr2 = match attr1.value.as_ref() {
395 Expr::Attribute(attr2) => attr2,
396 Expr::Name(ExprName { id, .. }) => {
398 return Some(Self::from_slice(&[id.as_str(), attr1.attr.as_str()]));
399 }
400 _ => return None,
401 };
402
403 let attr3 = match attr2.value.as_ref() {
404 Expr::Attribute(attr3) => attr3,
405 Expr::Name(ExprName { id, .. }) => {
407 return Some(Self::from_slice(&[
408 id.as_str(),
409 attr2.attr.as_str(),
410 attr1.attr.as_str(),
411 ]));
412 }
413 _ => return None,
414 };
415
416 let attr4 = match attr3.value.as_ref() {
417 Expr::Attribute(attr4) => attr4,
418 Expr::Name(ExprName { id, .. }) => {
420 return Some(Self::from_slice(&[
421 id.as_str(),
422 attr3.attr.as_str(),
423 attr2.attr.as_str(),
424 attr1.attr.as_str(),
425 ]));
426 }
427 _ => return None,
428 };
429
430 let attr5 = match attr4.value.as_ref() {
431 Expr::Attribute(attr5) => attr5,
432 Expr::Name(ExprName { id, .. }) => {
434 return Some(Self::from_slice(&[
435 id.as_str(),
436 attr4.attr.as_str(),
437 attr3.attr.as_str(),
438 attr2.attr.as_str(),
439 attr1.attr.as_str(),
440 ]));
441 }
442 _ => return None,
443 };
444
445 let attr6 = match attr5.value.as_ref() {
446 Expr::Attribute(attr6) => attr6,
447 Expr::Name(ExprName { id, .. }) => {
449 return Some(Self::from_slice(&[
450 id.as_str(),
451 attr5.attr.as_str(),
452 attr4.attr.as_str(),
453 attr3.attr.as_str(),
454 attr2.attr.as_str(),
455 attr1.attr.as_str(),
456 ]));
457 }
458 _ => return None,
459 };
460
461 let attr7 = match attr6.value.as_ref() {
462 Expr::Attribute(attr7) => attr7,
463 Expr::Name(ExprName { id, .. }) => {
465 return Some(Self::from_slice(&[
466 id.as_str(),
467 attr6.attr.as_str(),
468 attr5.attr.as_str(),
469 attr4.attr.as_str(),
470 attr3.attr.as_str(),
471 attr2.attr.as_str(),
472 attr1.attr.as_str(),
473 ]));
474 }
475 _ => return None,
476 };
477
478 let attr8 = match attr7.value.as_ref() {
479 Expr::Attribute(attr8) => attr8,
480 Expr::Name(ExprName { id, .. }) => {
482 return Some(Self(SegmentsVec::from([
483 id.as_str(),
484 attr7.attr.as_str(),
485 attr6.attr.as_str(),
486 attr5.attr.as_str(),
487 attr4.attr.as_str(),
488 attr3.attr.as_str(),
489 attr2.attr.as_str(),
490 attr1.attr.as_str(),
491 ])));
492 }
493 _ => return None,
494 };
495
496 let mut segments = Vec::with_capacity(SMALL_LEN * 2);
497
498 let mut current = &*attr8.value;
499
500 loop {
501 current = match current {
502 Expr::Attribute(attr) => {
503 segments.push(attr.attr.as_str());
504 &*attr.value
505 }
506 Expr::Name(ExprName { id, .. }) => {
507 segments.push(id.as_str());
508 break;
509 }
510 _ => {
511 return None;
512 }
513 }
514 }
515
516 segments.reverse();
517
518 segments.extend_from_slice(&[
520 attr8.attr.as_str(),
521 attr7.attr.as_str(),
522 attr6.attr.as_str(),
523 attr5.attr.as_str(),
524 attr4.attr.as_str(),
525 attr3.attr.as_str(),
526 attr2.attr.as_str(),
527 attr1.attr.as_str(),
528 ]);
529
530 Some(Self(SegmentsVec::from(segments)))
531 }
532
533 #[inline]
534 pub fn from_slice(segments: &[&'a str]) -> Self {
535 Self(SegmentsVec::from_slice(segments))
536 }
537
538 pub fn segments(&self) -> &[&'a str] {
539 self.0.as_slice()
540 }
541}
542
543impl Display for UnqualifiedName<'_> {
544 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
545 let mut first = true;
546 for segment in self.segments() {
547 if !first {
548 f.write_char('.')?;
549 }
550
551 f.write_str(segment)?;
552 first = false;
553 }
554
555 Ok(())
556 }
557}
558
559impl<'a> FromIterator<&'a str> for UnqualifiedName<'a> {
560 #[inline]
561 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
562 Self(iter.into_iter().collect())
563 }
564}
565
566#[derive(Clone)]
575enum SegmentsVec<'a> {
576 Stack(SegmentsStack<'a>),
577 Heap(Vec<&'a str>),
578}
579
580impl<'a> SegmentsVec<'a> {
581 fn new() -> Self {
583 Self::Stack(SegmentsStack::default())
584 }
585
586 fn with_capacity(capacity: usize) -> Self {
588 if capacity <= SMALL_LEN {
589 Self::new()
590 } else {
591 Self::Heap(Vec::with_capacity(capacity))
592 }
593 }
594
595 #[cfg(test)]
596 const fn is_spilled(&self) -> bool {
597 matches!(self, SegmentsVec::Heap(_))
598 }
599
600 #[inline]
602 fn from_slice(slice: &[&'a str]) -> Self {
603 if slice.len() <= SMALL_LEN {
604 SegmentsVec::Stack(SegmentsStack::from_slice(slice))
605 } else {
606 SegmentsVec::Heap(slice.to_vec())
607 }
608 }
609
610 #[inline]
612 fn as_slice(&self) -> &[&'a str] {
613 match self {
614 Self::Stack(stack) => stack.as_slice(),
615 Self::Heap(heap) => heap.as_slice(),
616 }
617 }
618
619 #[inline]
623 fn push(&mut self, name: &'a str) {
624 match self {
625 SegmentsVec::Stack(stack) => {
626 if let Err(segments) = stack.push(name) {
627 *self = SegmentsVec::Heap(segments);
628 }
629 }
630 SegmentsVec::Heap(heap) => {
631 heap.push(name);
632 }
633 }
634 }
635
636 #[inline]
640 fn pop(&mut self) -> Option<&'a str> {
641 match self {
642 SegmentsVec::Stack(stack) => stack.pop(),
643 SegmentsVec::Heap(heap) => heap.pop(),
644 }
645 }
646
647 #[inline]
648 fn extend_from_slice(&mut self, slice: &[&'a str]) {
649 match self {
650 SegmentsVec::Stack(stack) => {
651 if let Err(segments) = stack.extend_from_slice(slice) {
652 *self = SegmentsVec::Heap(segments);
653 }
654 }
655 SegmentsVec::Heap(heap) => heap.extend_from_slice(slice),
656 }
657 }
658}
659
660impl Default for SegmentsVec<'_> {
661 fn default() -> Self {
662 Self::new()
663 }
664}
665
666impl Debug for SegmentsVec<'_> {
667 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
668 f.debug_list().entries(self.as_slice()).finish()
669 }
670}
671
672impl<'a> Deref for SegmentsVec<'a> {
673 type Target = [&'a str];
674 fn deref(&self) -> &Self::Target {
675 self.as_slice()
676 }
677}
678
679impl<'b> PartialEq<SegmentsVec<'b>> for SegmentsVec<'_> {
680 fn eq(&self, other: &SegmentsVec<'b>) -> bool {
681 self.as_slice() == other.as_slice()
682 }
683}
684
685impl Eq for SegmentsVec<'_> {}
686
687impl Hash for SegmentsVec<'_> {
688 fn hash<H: Hasher>(&self, state: &mut H) {
689 self.as_slice().hash(state);
690 }
691}
692
693impl<'a> FromIterator<&'a str> for SegmentsVec<'a> {
694 #[inline]
695 fn from_iter<T: IntoIterator<Item = &'a str>>(iter: T) -> Self {
696 let mut segments = SegmentsVec::default();
697 segments.extend(iter);
698 segments
699 }
700}
701
702impl<'a> From<[&'a str; 8]> for SegmentsVec<'a> {
703 #[inline]
704 fn from(segments: [&'a str; 8]) -> Self {
705 SegmentsVec::Stack(SegmentsStack {
706 segments,
707 len: segments.len(),
708 })
709 }
710}
711
712impl<'a> From<Vec<&'a str>> for SegmentsVec<'a> {
713 #[inline]
714 fn from(segments: Vec<&'a str>) -> Self {
715 SegmentsVec::Heap(segments)
716 }
717}
718
719impl<'a> Extend<&'a str> for SegmentsVec<'a> {
720 #[inline]
721 fn extend<T: IntoIterator<Item = &'a str>>(&mut self, iter: T) {
722 match self {
723 SegmentsVec::Stack(stack) => {
724 if let Err(segments) = stack.extend(iter) {
725 *self = SegmentsVec::Heap(segments);
726 }
727 }
728 SegmentsVec::Heap(heap) => {
729 heap.extend(iter);
730 }
731 }
732 }
733}
734
735const SMALL_LEN: usize = 8;
736
737#[derive(Debug, Clone, Default)]
738struct SegmentsStack<'a> {
739 segments: [&'a str; SMALL_LEN],
740 len: usize,
741}
742
743impl<'a> SegmentsStack<'a> {
744 #[inline]
745 fn from_slice(slice: &[&'a str]) -> Self {
746 assert!(slice.len() <= SMALL_LEN);
747
748 let mut segments: [&'a str; SMALL_LEN] = Default::default();
749 segments[..slice.len()].copy_from_slice(slice);
750 SegmentsStack {
751 segments,
752 len: slice.len(),
753 }
754 }
755
756 const fn capacity(&self) -> usize {
757 SMALL_LEN - self.len
758 }
759
760 #[inline]
761 fn as_slice(&self) -> &[&'a str] {
762 &self.segments[..self.len]
763 }
764
765 #[inline]
769 fn push(&mut self, name: &'a str) -> Result<(), Vec<&'a str>> {
770 if self.len < self.segments.len() {
771 self.segments[self.len] = name;
772 self.len += 1;
773 Ok(())
774 } else {
775 let mut segments = Vec::with_capacity(self.len * 2);
776 segments.extend_from_slice(&self.segments);
777 segments.push(name);
778 Err(segments)
779 }
780 }
781
782 #[inline]
787 fn reserve(&mut self, additional: usize) -> Result<(), Vec<&'a str>> {
788 if self.capacity() >= additional {
789 Ok(())
790 } else {
791 let mut segments = Vec::with_capacity(self.len + additional);
792 segments.extend_from_slice(self.as_slice());
793 Err(segments)
794 }
795 }
796
797 #[inline]
798 fn pop(&mut self) -> Option<&'a str> {
799 if self.len > 0 {
800 self.len -= 1;
801 Some(self.segments[self.len])
802 } else {
803 None
804 }
805 }
806
807 #[inline]
811 fn extend_from_slice(&mut self, slice: &[&'a str]) -> Result<(), Vec<&'a str>> {
812 let new_len = self.len + slice.len();
813 if slice.len() <= self.capacity() {
814 self.segments[self.len..new_len].copy_from_slice(slice);
815 self.len = new_len;
816 Ok(())
817 } else {
818 let mut segments = Vec::with_capacity(new_len);
819 segments.extend_from_slice(self.as_slice());
820 segments.extend_from_slice(slice);
821 Err(segments)
822 }
823 }
824
825 #[inline]
826 fn extend<I>(&mut self, iter: I) -> Result<(), Vec<&'a str>>
827 where
828 I: IntoIterator<Item = &'a str>,
829 {
830 let mut iter = iter.into_iter();
831 let (lower, _) = iter.size_hint();
832
833 if let Err(mut segments) = self.reserve(lower) {
835 segments.extend(iter);
836 return Err(segments);
837 }
838
839 for name in iter.by_ref().take(self.capacity()) {
841 self.segments[self.len] = name;
842 self.len += 1;
843 }
844
845 let Some(item) = iter.next() else {
846 return Ok(());
848 };
849
850 let mut segments = Vec::with_capacity(self.len * 2);
853 segments.extend_from_slice(self.as_slice());
854 segments.push(item);
855 segments.extend(iter);
856 Err(segments)
857 }
858}
859
860#[cfg(test)]
861mod tests {
862 use crate::name::SegmentsVec;
863
864 #[test]
865 fn empty_vec() {
866 let empty = SegmentsVec::new();
867 assert_eq!(empty.as_slice(), &[] as &[&str]);
868 assert!(!empty.is_spilled());
869 }
870
871 #[test]
872 fn from_slice_stack() {
873 let stack = SegmentsVec::from_slice(&["a", "b", "c"]);
874
875 assert_eq!(stack.as_slice(), &["a", "b", "c"]);
876 assert!(!stack.is_spilled());
877 }
878
879 #[test]
880 fn from_slice_stack_capacity() {
881 let stack = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h"]);
882
883 assert_eq!(stack.as_slice(), &["a", "b", "c", "d", "e", "f", "g", "h"]);
884 assert!(!stack.is_spilled());
885 }
886
887 #[test]
888 fn from_slice_heap() {
889 let heap = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h", "i"]);
890
891 assert_eq!(
892 heap.as_slice(),
893 &["a", "b", "c", "d", "e", "f", "g", "h", "i"]
894 );
895 assert!(heap.is_spilled());
896 }
897
898 #[test]
899 fn push_stack() {
900 let mut stack = SegmentsVec::from_slice(&["a", "b", "c"]);
901 stack.push("d");
902 stack.push("e");
903
904 assert_eq!(stack.as_slice(), &["a", "b", "c", "d", "e"]);
905 assert!(!stack.is_spilled());
906 }
907
908 #[test]
909 fn push_stack_spill() {
910 let mut stack = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g"]);
911 stack.push("h");
912
913 assert!(!stack.is_spilled());
914
915 stack.push("i");
916
917 assert_eq!(
918 stack.as_slice(),
919 &["a", "b", "c", "d", "e", "f", "g", "h", "i"]
920 );
921 assert!(stack.is_spilled());
922 }
923
924 #[test]
925 fn pop_stack() {
926 let mut stack = SegmentsVec::from_slice(&["a", "b", "c", "d", "e"]);
927 assert_eq!(stack.pop(), Some("e"));
928 assert_eq!(stack.pop(), Some("d"));
929 assert_eq!(stack.pop(), Some("c"));
930 assert_eq!(stack.pop(), Some("b"));
931 assert_eq!(stack.pop(), Some("a"));
932 assert_eq!(stack.pop(), None);
933
934 assert!(!stack.is_spilled());
935 }
936
937 #[test]
938 fn pop_heap() {
939 let mut heap = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h", "i"]);
940
941 assert_eq!(heap.pop(), Some("i"));
942 assert_eq!(heap.pop(), Some("h"));
943 assert_eq!(heap.pop(), Some("g"));
944
945 assert!(heap.is_spilled());
946 }
947
948 #[test]
949 fn extend_from_slice_stack() {
950 let mut stack = SegmentsVec::from_slice(&["a", "b", "c"]);
951 stack.extend_from_slice(&["d", "e", "f"]);
952
953 assert_eq!(stack.as_slice(), &["a", "b", "c", "d", "e", "f"]);
954 assert!(!stack.is_spilled());
955 }
956
957 #[test]
958 fn extend_from_slice_stack_spill() {
959 let mut spilled = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f"]);
960 spilled.extend_from_slice(&["g", "h", "i", "j"]);
961
962 assert_eq!(
963 spilled.as_slice(),
964 &["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
965 );
966 assert!(spilled.is_spilled());
967 }
968
969 #[test]
970 fn extend_from_slice_heap() {
971 let mut heap = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h", "i"]);
972 assert!(heap.is_spilled());
973
974 heap.extend_from_slice(&["j", "k", "l"]);
975
976 assert_eq!(
977 heap.as_slice(),
978 &["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]
979 );
980 }
981
982 #[test]
983 fn extend_stack() {
984 let mut stack = SegmentsVec::from_slice(&["a", "b", "c"]);
985 stack.extend(["d", "e", "f"]);
986
987 assert_eq!(stack.as_slice(), &["a", "b", "c", "d", "e", "f"]);
988 assert!(!stack.is_spilled());
989 }
990
991 #[test]
992 fn extend_stack_spilled() {
993 let mut stack = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f"]);
994 stack.extend(["g", "h", "i", "j"]);
995
996 assert_eq!(
997 stack.as_slice(),
998 &["a", "b", "c", "d", "e", "f", "g", "h", "i", "j"]
999 );
1000 assert!(stack.is_spilled());
1001 }
1002
1003 #[test]
1004 fn extend_heap() {
1005 let mut heap = SegmentsVec::from_slice(&["a", "b", "c", "d", "e", "f", "g", "h", "i"]);
1006 assert!(heap.is_spilled());
1007
1008 heap.extend(["j", "k", "l"]);
1009
1010 assert_eq!(
1011 heap.as_slice(),
1012 &["a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l"]
1013 );
1014 }
1015}