tendril/
tendril.rs

1// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
2// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
3// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
4// option. This file may not be copied, modified, or distributed
5// except according to those terms.
6
7use std::borrow::Borrow;
8use std::cell::{Cell, UnsafeCell};
9use std::cmp::Ordering;
10use std::default::Default;
11use std::fmt as strfmt;
12use std::iter::FromIterator;
13use std::marker::PhantomData;
14use std::num::NonZeroUsize;
15use std::ops::{Deref, DerefMut};
16use std::sync::atomic::Ordering as AtomicOrdering;
17use std::sync::atomic::{self, AtomicUsize};
18use std::{hash, io, mem, ptr, str};
19
20use crate::buf32::{self, Buf32};
21use crate::fmt::imp::Fixup;
22use crate::fmt::{self, Slice, ASCII, UTF8};
23use crate::util::{
24    copy_and_advance, copy_lifetime, copy_lifetime_mut, unsafe_slice, unsafe_slice_mut,
25};
26use crate::OFLOW;
27
28const MAX_INLINE_LEN: usize = 8;
29const MAX_INLINE_TAG: usize = 0xF;
30const EMPTY_TAG: usize = 0xF;
31
32#[inline(always)]
33fn inline_tag(len: u32) -> NonZeroUsize {
34    debug_assert!(len <= MAX_INLINE_LEN as u32);
35    unsafe { NonZeroUsize::new_unchecked(if len == 0 { EMPTY_TAG } else { len as usize }) }
36}
37
38/// The multithreadedness of a tendril.
39///
40/// Exactly two types implement this trait:
41///
42/// - `Atomic`: use this in your tendril and you will have a `Send` tendril which works
43///   across threads; this is akin to `Arc`.
44///
45/// - `NonAtomic`: use this in your tendril and you will have a tendril which is neither
46///   `Send` nor `Sync` but should be a tad faster; this is akin to `Rc`.
47///
48/// The layout of this trait is also mandated to be that of a `usize`,
49/// for it is used for reference counting.
50pub unsafe trait Atomicity: 'static {
51    #[doc(hidden)]
52    fn new() -> Self;
53
54    #[doc(hidden)]
55    fn increment(&self) -> usize;
56
57    #[doc(hidden)]
58    fn decrement(&self) -> usize;
59
60    #[doc(hidden)]
61    fn fence_acquire();
62}
63
64/// A marker of a non-atomic tendril.
65///
66/// This is the default for the second type parameter of a `Tendril`
67/// and so doesn't typically need to be written.
68///
69/// This is akin to using `Rc` for reference counting.
70#[repr(C)]
71pub struct NonAtomic(Cell<usize>);
72
73unsafe impl Atomicity for NonAtomic {
74    #[inline]
75    fn new() -> Self {
76        NonAtomic(Cell::new(1))
77    }
78
79    #[inline]
80    fn increment(&self) -> usize {
81        let value = self.0.get();
82        self.0.set(value.checked_add(1).expect(OFLOW));
83        value
84    }
85
86    #[inline]
87    fn decrement(&self) -> usize {
88        let value = self.0.get();
89        self.0.set(value - 1);
90        value
91    }
92
93    #[inline]
94    fn fence_acquire() {}
95}
96
97/// A marker of an atomic (and hence concurrent) tendril.
98///
99/// This is used as the second, optional type parameter of a `Tendril`;
100/// `Tendril<F, Atomic>` thus implements`Send`.
101///
102/// This is akin to using `Arc` for reference counting.
103pub struct Atomic(AtomicUsize);
104
105unsafe impl Atomicity for Atomic {
106    #[inline]
107    fn new() -> Self {
108        Atomic(AtomicUsize::new(1))
109    }
110
111    #[inline]
112    fn increment(&self) -> usize {
113        // Relaxed is OK because we have a reference already.
114        self.0.fetch_add(1, AtomicOrdering::Relaxed)
115    }
116
117    #[inline]
118    fn decrement(&self) -> usize {
119        self.0.fetch_sub(1, AtomicOrdering::Release)
120    }
121
122    #[inline]
123    fn fence_acquire() {
124        atomic::fence(AtomicOrdering::Acquire);
125    }
126}
127
128#[repr(C)] // Preserve field order for cross-atomicity transmutes
129struct Header<A: Atomicity> {
130    refcount: A,
131    cap: u32,
132}
133
134impl<A> Header<A>
135where
136    A: Atomicity,
137{
138    #[inline(always)]
139    unsafe fn new() -> Header<A> {
140        Header {
141            refcount: A::new(),
142            cap: 0,
143        }
144    }
145}
146
147/// Errors that can occur when slicing a `Tendril`.
148#[derive(Copy, Clone, Hash, Debug, PartialEq, Eq)]
149pub enum SubtendrilError {
150    OutOfBounds,
151    ValidationFailed,
152}
153
154/// Compact string type for zero-copy parsing.
155///
156/// `Tendril`s have the semantics of owned strings, but are sometimes views
157/// into shared buffers. When you mutate a `Tendril`, an owned copy is made
158/// if necessary. Further mutations occur in-place until the string becomes
159/// shared, e.g. with `clone()` or `subtendril()`.
160///
161/// Buffer sharing is accomplished through thread-local (non-atomic) reference
162/// counting, which has very low overhead. The Rust type system will prevent
163/// you at compile time from sending a `Tendril` between threads. We plan to
164/// relax this restriction in the future; see `README.md`.
165///
166/// Whereas `String` allocates in the heap for any non-empty string, `Tendril`
167/// can store small strings (up to 8 bytes) in-line, without a heap allocation.
168/// `Tendril` is also smaller than `String` on 64-bit platforms — 16 bytes
169/// versus 24.
170///
171/// The type parameter `F` specifies the format of the tendril, for example
172/// UTF-8 text or uninterpreted bytes. The parameter will be instantiated
173/// with one of the marker types from `tendril::fmt`. See the `StrTendril`
174/// and `ByteTendril` type aliases for two examples.
175///
176/// The type parameter `A` indicates the atomicity of the tendril; it is by
177/// default `NonAtomic`, but can be specified as `Atomic` to get a tendril
178/// which implements `Send` (viz. a thread-safe tendril).
179///
180/// The maximum length of a `Tendril` is 4 GB. The library will panic if
181/// you attempt to go over the limit.
182#[repr(C)]
183pub struct Tendril<F, A = NonAtomic>
184where
185    F: fmt::Format,
186    A: Atomicity,
187{
188    ptr: Cell<NonZeroUsize>,
189    buf: UnsafeCell<Buffer>,
190    marker: PhantomData<*mut F>,
191    refcount_marker: PhantomData<A>,
192}
193
194#[repr(C)]
195union Buffer {
196    heap: Heap,
197    inline: [u8; 8],
198}
199
200#[derive(Copy, Clone)]
201#[repr(C)]
202struct Heap {
203    len: u32,
204    aux: u32,
205}
206
207unsafe impl<F, A> Send for Tendril<F, A>
208where
209    F: fmt::Format,
210    A: Atomicity + Sync,
211{
212}
213
214/// `Tendril` for storing native Rust strings.
215pub type StrTendril = Tendril<fmt::UTF8>;
216
217/// `Tendril` for storing binary data.
218pub type ByteTendril = Tendril<fmt::Bytes>;
219
220impl<F, A> Clone for Tendril<F, A>
221where
222    F: fmt::Format,
223    A: Atomicity,
224{
225    #[inline]
226    fn clone(&self) -> Tendril<F, A> {
227        unsafe {
228            if self.ptr.get().get() > MAX_INLINE_TAG {
229                self.make_buf_shared();
230                self.incref();
231            }
232
233            ptr::read(self)
234        }
235    }
236}
237
238impl<F, A> Drop for Tendril<F, A>
239where
240    F: fmt::Format,
241    A: Atomicity,
242{
243    #[inline]
244    fn drop(&mut self) {
245        unsafe {
246            let p = self.ptr.get().get();
247            if p <= MAX_INLINE_TAG {
248                return;
249            }
250
251            let (buf, shared, _) = self.assume_buf();
252            if shared {
253                let header = self.header();
254                if (*header).refcount.decrement() == 1 {
255                    A::fence_acquire();
256                    buf.destroy();
257                }
258            } else {
259                buf.destroy();
260            }
261        }
262    }
263}
264
265macro_rules! from_iter_method {
266    ($ty:ty) => {
267        #[inline]
268        fn from_iter<I>(iterable: I) -> Self
269        where
270            I: IntoIterator<Item = $ty>,
271        {
272            let mut output = Self::new();
273            output.extend(iterable);
274            output
275        }
276    };
277}
278
279impl<A> Extend<char> for Tendril<fmt::UTF8, A>
280where
281    A: Atomicity,
282{
283    #[inline]
284    fn extend<I>(&mut self, iterable: I)
285    where
286        I: IntoIterator<Item = char>,
287    {
288        let iterator = iterable.into_iter();
289        self.force_reserve(iterator.size_hint().0 as u32);
290        for c in iterator {
291            self.push_char(c);
292        }
293    }
294}
295
296impl<A> FromIterator<char> for Tendril<fmt::UTF8, A>
297where
298    A: Atomicity,
299{
300    from_iter_method!(char);
301}
302
303impl<A> Extend<u8> for Tendril<fmt::Bytes, A>
304where
305    A: Atomicity,
306{
307    #[inline]
308    fn extend<I>(&mut self, iterable: I)
309    where
310        I: IntoIterator<Item = u8>,
311    {
312        let iterator = iterable.into_iter();
313        self.force_reserve(iterator.size_hint().0 as u32);
314        for b in iterator {
315            self.push_slice(&[b]);
316        }
317    }
318}
319
320impl<A> FromIterator<u8> for Tendril<fmt::Bytes, A>
321where
322    A: Atomicity,
323{
324    from_iter_method!(u8);
325}
326
327impl<'a, A> Extend<&'a u8> for Tendril<fmt::Bytes, A>
328where
329    A: Atomicity,
330{
331    #[inline]
332    fn extend<I>(&mut self, iterable: I)
333    where
334        I: IntoIterator<Item = &'a u8>,
335    {
336        let iterator = iterable.into_iter();
337        self.force_reserve(iterator.size_hint().0 as u32);
338        for &b in iterator {
339            self.push_slice(&[b]);
340        }
341    }
342}
343
344impl<'a, A> FromIterator<&'a u8> for Tendril<fmt::Bytes, A>
345where
346    A: Atomicity,
347{
348    from_iter_method!(&'a u8);
349}
350
351impl<'a, A> Extend<&'a str> for Tendril<fmt::UTF8, A>
352where
353    A: Atomicity,
354{
355    #[inline]
356    fn extend<I>(&mut self, iterable: I)
357    where
358        I: IntoIterator<Item = &'a str>,
359    {
360        for s in iterable {
361            self.push_slice(s);
362        }
363    }
364}
365
366impl<'a, A> FromIterator<&'a str> for Tendril<fmt::UTF8, A>
367where
368    A: Atomicity,
369{
370    from_iter_method!(&'a str);
371}
372
373impl<'a, A> Extend<&'a [u8]> for Tendril<fmt::Bytes, A>
374where
375    A: Atomicity,
376{
377    #[inline]
378    fn extend<I>(&mut self, iterable: I)
379    where
380        I: IntoIterator<Item = &'a [u8]>,
381    {
382        for s in iterable {
383            self.push_slice(s);
384        }
385    }
386}
387
388impl<'a, A> FromIterator<&'a [u8]> for Tendril<fmt::Bytes, A>
389where
390    A: Atomicity,
391{
392    from_iter_method!(&'a [u8]);
393}
394
395impl<'a, F, A> Extend<&'a Tendril<F, A>> for Tendril<F, A>
396where
397    F: fmt::Format + 'a,
398    A: Atomicity,
399{
400    #[inline]
401    fn extend<I>(&mut self, iterable: I)
402    where
403        I: IntoIterator<Item = &'a Tendril<F, A>>,
404    {
405        for t in iterable {
406            self.push_tendril(t);
407        }
408    }
409}
410
411impl<'a, F, A> FromIterator<&'a Tendril<F, A>> for Tendril<F, A>
412where
413    F: fmt::Format + 'a,
414    A: Atomicity,
415{
416    from_iter_method!(&'a Tendril<F, A>);
417}
418
419impl<F, A> Deref for Tendril<F, A>
420where
421    F: fmt::SliceFormat,
422    A: Atomicity,
423{
424    type Target = F::Slice;
425
426    #[inline]
427    fn deref(&self) -> &F::Slice {
428        unsafe { F::Slice::from_bytes(self.as_byte_slice()) }
429    }
430}
431
432impl<F, A> DerefMut for Tendril<F, A>
433where
434    F: fmt::SliceFormat,
435    A: Atomicity,
436{
437    #[inline]
438    fn deref_mut(&mut self) -> &mut F::Slice {
439        unsafe { F::Slice::from_mut_bytes(self.as_mut_byte_slice()) }
440    }
441}
442
443impl<F, A> Borrow<[u8]> for Tendril<F, A>
444where
445    F: fmt::SliceFormat,
446    A: Atomicity,
447{
448    fn borrow(&self) -> &[u8] {
449        self.as_byte_slice()
450    }
451}
452
453// Why not impl Borrow<str> for Tendril<fmt::UTF8>? str and [u8] hash differently,
454// and so a HashMap<StrTendril, _> would silently break if we indexed by str. Ick.
455// https://github.com/rust-lang/rust/issues/27108
456
457impl<F, A> PartialEq for Tendril<F, A>
458where
459    F: fmt::Format,
460    A: Atomicity,
461{
462    #[inline]
463    fn eq(&self, other: &Self) -> bool {
464        self.as_byte_slice() == other.as_byte_slice()
465    }
466}
467
468impl<A: Atomicity> PartialEq<str> for Tendril<ASCII, A> {
469    #[inline]
470    fn eq(&self, other: &str) -> bool {
471        self.as_byte_slice() == other.as_bytes()
472    }
473}
474
475impl<A: Atomicity> PartialEq<str> for Tendril<UTF8, A> {
476    #[inline]
477    fn eq(&self, other: &str) -> bool {
478        self.as_byte_slice() == other.as_bytes()
479    }
480}
481
482impl<F, A> Eq for Tendril<F, A>
483where
484    F: fmt::Format,
485    A: Atomicity,
486{
487}
488
489impl<F, A> PartialOrd for Tendril<F, A>
490where
491    F: fmt::SliceFormat,
492    <F as fmt::SliceFormat>::Slice: PartialOrd,
493    A: Atomicity,
494{
495    #[inline]
496    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
497        PartialOrd::partial_cmp(&**self, &**other)
498    }
499}
500
501impl<F, A> Ord for Tendril<F, A>
502where
503    F: fmt::SliceFormat,
504    <F as fmt::SliceFormat>::Slice: Ord,
505    A: Atomicity,
506{
507    #[inline]
508    fn cmp(&self, other: &Self) -> Ordering {
509        Ord::cmp(&**self, &**other)
510    }
511}
512
513impl<F, A> Default for Tendril<F, A>
514where
515    F: fmt::Format,
516    A: Atomicity,
517{
518    #[inline(always)]
519    fn default() -> Tendril<F, A> {
520        Tendril::new()
521    }
522}
523
524impl<F, A> strfmt::Debug for Tendril<F, A>
525where
526    F: fmt::SliceFormat + Default + strfmt::Debug,
527    <F as fmt::SliceFormat>::Slice: strfmt::Debug,
528    A: Atomicity,
529{
530    #[inline]
531    fn fmt(&self, f: &mut strfmt::Formatter) -> strfmt::Result {
532        let kind = match self.ptr.get().get() {
533            p if p <= MAX_INLINE_TAG => "inline",
534            p if p & 1 == 1 => "shared",
535            _ => "owned",
536        };
537
538        write!(f, "Tendril<{:?}>({}: ", <F as Default>::default(), kind)?;
539        <<F as fmt::SliceFormat>::Slice as strfmt::Debug>::fmt(&**self, f)?;
540        write!(f, ")")
541    }
542}
543
544impl<F, A> hash::Hash for Tendril<F, A>
545where
546    F: fmt::Format,
547    A: Atomicity,
548{
549    #[inline]
550    fn hash<H: hash::Hasher>(&self, hasher: &mut H) {
551        self.as_byte_slice().hash(hasher)
552    }
553}
554
555impl<F, A> Tendril<F, A>
556where
557    F: fmt::Format,
558    A: Atomicity,
559{
560    /// Create a new, empty `Tendril` in any format.
561    #[inline(always)]
562    pub fn new() -> Tendril<F, A> {
563        unsafe { Tendril::inline(&[]) }
564    }
565
566    /// Create a new, empty `Tendril` with a specified capacity.
567    #[inline]
568    pub fn with_capacity(capacity: u32) -> Tendril<F, A> {
569        let mut t: Tendril<F, A> = Tendril::new();
570        if capacity > MAX_INLINE_LEN as u32 {
571            unsafe {
572                t.make_owned_with_capacity(capacity);
573            }
574        }
575        t
576    }
577
578    /// Reserve space for additional bytes.
579    ///
580    /// This is only a suggestion. There are cases where `Tendril` will
581    /// decline to allocate until the buffer is actually modified.
582    #[inline]
583    pub fn reserve(&mut self, additional: u32) {
584        if !self.is_shared() {
585            // Don't grow a shared tendril because we'd have to copy
586            // right away.
587            self.force_reserve(additional);
588        }
589    }
590
591    /// Reserve space for additional bytes, even for shared buffers.
592    #[inline]
593    fn force_reserve(&mut self, additional: u32) {
594        let new_len = self.len32().checked_add(additional).expect(OFLOW);
595        if new_len > MAX_INLINE_LEN as u32 {
596            unsafe {
597                self.make_owned_with_capacity(new_len);
598            }
599        }
600    }
601
602    /// Get the length of the `Tendril`.
603    ///
604    /// This is named not to conflict with `len()` on the underlying
605    /// slice, if any.
606    #[inline(always)]
607    pub fn len32(&self) -> u32 {
608        match self.ptr.get().get() {
609            EMPTY_TAG => 0,
610            n if n <= MAX_INLINE_LEN => n as u32,
611            _ => unsafe { self.raw_len() },
612        }
613    }
614
615    /// Is the backing buffer shared?
616    #[inline]
617    pub fn is_shared(&self) -> bool {
618        let n = self.ptr.get().get();
619
620        (n > MAX_INLINE_TAG) && ((n & 1) == 1)
621    }
622
623    /// Is the backing buffer shared with this other `Tendril`?
624    #[inline]
625    pub fn is_shared_with(&self, other: &Tendril<F, A>) -> bool {
626        let n = self.ptr.get().get();
627
628        (n > MAX_INLINE_TAG) && (n == other.ptr.get().get())
629    }
630
631    /// Truncate to length 0 without discarding any owned storage.
632    #[inline]
633    pub fn clear(&mut self) {
634        if self.ptr.get().get() <= MAX_INLINE_TAG {
635            self.ptr
636                .set(unsafe { NonZeroUsize::new_unchecked(EMPTY_TAG) });
637        } else {
638            let (_, shared, _) = unsafe { self.assume_buf() };
639            if shared {
640                // No need to keep a reference alive for a 0-size slice.
641                *self = Tendril::new();
642            } else {
643                unsafe { self.set_len(0) };
644            }
645        }
646    }
647
648    /// Build a `Tendril` by copying a byte slice, if it conforms to the format.
649    #[inline]
650    pub fn try_from_byte_slice(x: &[u8]) -> Result<Tendril<F, A>, ()> {
651        match F::validate(x) {
652            true => Ok(unsafe { Tendril::from_byte_slice_without_validating(x) }),
653            false => Err(()),
654        }
655    }
656
657    /// View as uninterpreted bytes.
658    #[inline(always)]
659    pub fn as_bytes(&self) -> &Tendril<fmt::Bytes, A> {
660        unsafe { mem::transmute(self) }
661    }
662
663    /// Convert into uninterpreted bytes.
664    #[inline(always)]
665    pub fn into_bytes(self) -> Tendril<fmt::Bytes, A> {
666        unsafe { mem::transmute(self) }
667    }
668
669    /// Convert `self` into a type which is `Send`.
670    ///
671    /// If the tendril is owned or inline, this is free,
672    /// but if it's shared this will entail a copy of the contents.
673    #[inline]
674    pub fn into_send(mut self) -> SendTendril<F> {
675        self.make_owned();
676        SendTendril {
677            // This changes the header.refcount from A to NonAtomic, but that's
678            // OK because we have defined the format of A as a usize.
679            tendril: unsafe { mem::transmute(self) },
680        }
681    }
682
683    /// View as a superset format, for free.
684    #[inline(always)]
685    pub fn as_superset<Super>(&self) -> &Tendril<Super, A>
686    where
687        F: fmt::SubsetOf<Super>,
688        Super: fmt::Format,
689    {
690        unsafe { mem::transmute(self) }
691    }
692
693    /// Convert into a superset format, for free.
694    #[inline(always)]
695    pub fn into_superset<Super>(self) -> Tendril<Super, A>
696    where
697        F: fmt::SubsetOf<Super>,
698        Super: fmt::Format,
699    {
700        unsafe { mem::transmute(self) }
701    }
702
703    /// View as a subset format, if the `Tendril` conforms to that subset.
704    #[inline]
705    pub fn try_as_subset<Sub>(&self) -> Result<&Tendril<Sub, A>, ()>
706    where
707        Sub: fmt::SubsetOf<F>,
708    {
709        match Sub::revalidate_subset(self.as_byte_slice()) {
710            true => Ok(unsafe { mem::transmute(self) }),
711            false => Err(()),
712        }
713    }
714
715    /// Convert into a subset format, if the `Tendril` conforms to that subset.
716    #[inline]
717    pub fn try_into_subset<Sub>(self) -> Result<Tendril<Sub, A>, Self>
718    where
719        Sub: fmt::SubsetOf<F>,
720    {
721        match Sub::revalidate_subset(self.as_byte_slice()) {
722            true => Ok(unsafe { mem::transmute(self) }),
723            false => Err(self),
724        }
725    }
726
727    /// View as another format, if the bytes of the `Tendril` are valid for
728    /// that format.
729    #[inline]
730    pub fn try_reinterpret_view<Other>(&self) -> Result<&Tendril<Other, A>, ()>
731    where
732        Other: fmt::Format,
733    {
734        match Other::validate(self.as_byte_slice()) {
735            true => Ok(unsafe { mem::transmute(self) }),
736            false => Err(()),
737        }
738    }
739
740    /// Convert into another format, if the `Tendril` conforms to that format.
741    ///
742    /// This only re-validates the existing bytes under the new format. It
743    /// will *not* change the byte content of the tendril!
744    ///
745    /// See the `encode` and `decode` methods for character encoding conversion.
746    #[inline]
747    pub fn try_reinterpret<Other>(self) -> Result<Tendril<Other, A>, Self>
748    where
749        Other: fmt::Format,
750    {
751        match Other::validate(self.as_byte_slice()) {
752            true => Ok(unsafe { mem::transmute(self) }),
753            false => Err(self),
754        }
755    }
756
757    /// Push some bytes onto the end of the `Tendril`, if they conform to the
758    /// format.
759    #[inline]
760    pub fn try_push_bytes(&mut self, buf: &[u8]) -> Result<(), ()> {
761        match F::validate(buf) {
762            true => unsafe {
763                self.push_bytes_without_validating(buf);
764                Ok(())
765            },
766            false => Err(()),
767        }
768    }
769
770    /// Push another `Tendril` onto the end of this one.
771    #[inline]
772    pub fn push_tendril(&mut self, other: &Tendril<F, A>) {
773        let new_len = self.len32().checked_add(other.len32()).expect(OFLOW);
774
775        unsafe {
776            if (self.ptr.get().get() > MAX_INLINE_TAG) && (other.ptr.get().get() > MAX_INLINE_TAG) {
777                let (self_buf, self_shared, _) = self.assume_buf();
778                let (other_buf, other_shared, _) = other.assume_buf();
779
780                if self_shared
781                    && other_shared
782                    && (self_buf.data_ptr() == other_buf.data_ptr())
783                    && other.aux() == self.aux() + self.raw_len()
784                {
785                    self.set_len(new_len);
786                    return;
787                }
788            }
789
790            self.push_bytes_without_validating(other.as_byte_slice())
791        }
792    }
793
794    /// Attempt to slice this `Tendril` as a new `Tendril`.
795    ///
796    /// This will share the buffer when possible. Mutating a shared buffer
797    /// will copy the contents.
798    ///
799    /// The offset and length are in bytes. The function will return
800    /// `Err` if these are out of bounds, or if the resulting slice
801    /// does not conform to the format.
802    #[inline]
803    pub fn try_subtendril(
804        &self,
805        offset: u32,
806        length: u32,
807    ) -> Result<Tendril<F, A>, SubtendrilError> {
808        let self_len = self.len32();
809        if offset > self_len || length > (self_len - offset) {
810            return Err(SubtendrilError::OutOfBounds);
811        }
812
813        unsafe {
814            let byte_slice = unsafe_slice(self.as_byte_slice(), offset as usize, length as usize);
815            if !F::validate_subseq(byte_slice) {
816                return Err(SubtendrilError::ValidationFailed);
817            }
818
819            Ok(self.unsafe_subtendril(offset, length))
820        }
821    }
822
823    /// Slice this `Tendril` as a new `Tendril`.
824    ///
825    /// Panics on bounds or validity check failure.
826    #[inline]
827    pub fn subtendril(&self, offset: u32, length: u32) -> Tendril<F, A> {
828        self.try_subtendril(offset, length).unwrap()
829    }
830
831    /// Try to drop `n` bytes from the front.
832    ///
833    /// Returns `Err` if the bytes are not available, or the suffix fails
834    /// validation.
835    #[inline]
836    pub fn try_pop_front(&mut self, n: u32) -> Result<(), SubtendrilError> {
837        if n == 0 {
838            return Ok(());
839        }
840        let old_len = self.len32();
841        if n > old_len {
842            return Err(SubtendrilError::OutOfBounds);
843        }
844        let new_len = old_len - n;
845
846        unsafe {
847            if !F::validate_suffix(unsafe_slice(
848                self.as_byte_slice(),
849                n as usize,
850                new_len as usize,
851            )) {
852                return Err(SubtendrilError::ValidationFailed);
853            }
854
855            self.unsafe_pop_front(n);
856            Ok(())
857        }
858    }
859
860    /// Drop `n` bytes from the front.
861    ///
862    /// Panics if the bytes are not available, or the suffix fails
863    /// validation.
864    #[inline]
865    pub fn pop_front(&mut self, n: u32) {
866        self.try_pop_front(n).unwrap()
867    }
868
869    /// Drop `n` bytes from the back.
870    ///
871    /// Returns `Err` if the bytes are not available, or the prefix fails
872    /// validation.
873    #[inline]
874    pub fn try_pop_back(&mut self, n: u32) -> Result<(), SubtendrilError> {
875        if n == 0 {
876            return Ok(());
877        }
878        let old_len = self.len32();
879        if n > old_len {
880            return Err(SubtendrilError::OutOfBounds);
881        }
882        let new_len = old_len - n;
883
884        unsafe {
885            if !F::validate_prefix(unsafe_slice(self.as_byte_slice(), 0, new_len as usize)) {
886                return Err(SubtendrilError::ValidationFailed);
887            }
888
889            self.unsafe_pop_back(n);
890            Ok(())
891        }
892    }
893
894    /// Drop `n` bytes from the back.
895    ///
896    /// Panics if the bytes are not available, or the prefix fails
897    /// validation.
898    #[inline]
899    pub fn pop_back(&mut self, n: u32) {
900        self.try_pop_back(n).unwrap()
901    }
902
903    /// View as another format, without validating.
904    #[inline(always)]
905    pub unsafe fn reinterpret_view_without_validating<Other>(&self) -> &Tendril<Other, A>
906    where
907        Other: fmt::Format,
908    {
909        mem::transmute(self)
910    }
911
912    /// Convert into another format, without validating.
913    #[inline(always)]
914    pub unsafe fn reinterpret_without_validating<Other>(self) -> Tendril<Other, A>
915    where
916        Other: fmt::Format,
917    {
918        mem::transmute(self)
919    }
920
921    /// Build a `Tendril` by copying a byte slice, without validating.
922    #[inline]
923    pub unsafe fn from_byte_slice_without_validating(x: &[u8]) -> Tendril<F, A> {
924        assert!(x.len() <= buf32::MAX_LEN);
925        if x.len() <= MAX_INLINE_LEN {
926            Tendril::inline(x)
927        } else {
928            Tendril::owned_copy(x)
929        }
930    }
931
932    /// Push some bytes onto the end of the `Tendril`, without validating.
933    #[inline]
934    pub unsafe fn push_bytes_without_validating(&mut self, buf: &[u8]) {
935        assert!(buf.len() <= buf32::MAX_LEN);
936
937        let Fixup {
938            drop_left,
939            drop_right,
940            insert_len,
941            insert_bytes,
942        } = F::fixup(self.as_byte_slice(), buf);
943
944        // FIXME: think more about overflow
945        let adj_len = self.len32() + insert_len - drop_left;
946
947        let new_len = adj_len.checked_add(buf.len() as u32).expect(OFLOW) - drop_right;
948
949        let drop_left = drop_left as usize;
950        let drop_right = drop_right as usize;
951
952        if new_len <= MAX_INLINE_LEN as u32 {
953            let mut tmp = [0_u8; MAX_INLINE_LEN];
954            {
955                let old = self.as_byte_slice();
956                let mut dest = tmp.as_mut_ptr();
957                copy_and_advance(&mut dest, unsafe_slice(old, 0, old.len() - drop_left));
958                copy_and_advance(
959                    &mut dest,
960                    unsafe_slice(&insert_bytes, 0, insert_len as usize),
961                );
962                copy_and_advance(
963                    &mut dest,
964                    unsafe_slice(buf, drop_right, buf.len() - drop_right),
965                );
966            }
967            *self = Tendril::inline(&tmp[..new_len as usize]);
968        } else {
969            self.make_owned_with_capacity(new_len);
970            let (owned, _, _) = self.assume_buf();
971            let mut dest = owned.data_ptr().add(owned.len as usize - drop_left);
972            copy_and_advance(
973                &mut dest,
974                unsafe_slice(&insert_bytes, 0, insert_len as usize),
975            );
976            copy_and_advance(
977                &mut dest,
978                unsafe_slice(buf, drop_right, buf.len() - drop_right),
979            );
980            self.set_len(new_len);
981        }
982    }
983
984    /// Slice this `Tendril` as a new `Tendril`.
985    ///
986    /// Does not check validity or bounds!
987    #[inline]
988    pub unsafe fn unsafe_subtendril(&self, offset: u32, length: u32) -> Tendril<F, A> {
989        if length <= MAX_INLINE_LEN as u32 {
990            Tendril::inline(unsafe_slice(
991                self.as_byte_slice(),
992                offset as usize,
993                length as usize,
994            ))
995        } else {
996            self.make_buf_shared();
997            self.incref();
998            let (buf, _, _) = self.assume_buf();
999            Tendril::shared(buf, self.aux() + offset, length)
1000        }
1001    }
1002
1003    /// Drop `n` bytes from the front.
1004    ///
1005    /// Does not check validity or bounds!
1006    #[inline]
1007    pub unsafe fn unsafe_pop_front(&mut self, n: u32) {
1008        let new_len = self.len32() - n;
1009        if new_len <= MAX_INLINE_LEN as u32 {
1010            *self = Tendril::inline(unsafe_slice(
1011                self.as_byte_slice(),
1012                n as usize,
1013                new_len as usize,
1014            ));
1015        } else {
1016            self.make_buf_shared();
1017            self.set_aux(self.aux() + n);
1018            let len = self.raw_len();
1019            self.set_len(len - n);
1020        }
1021    }
1022
1023    /// Drop `n` bytes from the back.
1024    ///
1025    /// Does not check validity or bounds!
1026    #[inline]
1027    pub unsafe fn unsafe_pop_back(&mut self, n: u32) {
1028        let new_len = self.len32() - n;
1029        if new_len <= MAX_INLINE_LEN as u32 {
1030            *self = Tendril::inline(unsafe_slice(self.as_byte_slice(), 0, new_len as usize));
1031        } else {
1032            self.make_buf_shared();
1033            let len = self.raw_len();
1034            self.set_len(len - n);
1035        }
1036    }
1037
1038    #[inline]
1039    unsafe fn incref(&self) {
1040        (*self.header()).refcount.increment();
1041    }
1042
1043    #[inline]
1044    unsafe fn make_buf_shared(&self) {
1045        let p = self.ptr.get().get();
1046        if p & 1 == 0 {
1047            let header = p as *mut Header<A>;
1048            (*header).cap = self.aux();
1049
1050            self.ptr.set(NonZeroUsize::new_unchecked(p | 1));
1051            self.set_aux(0);
1052        }
1053    }
1054
1055    // This is not public as it is of no practical value to users.
1056    // By and large they shouldn't need to worry about the distinction at all,
1057    // and going out of your way to make it owned is pointless.
1058    #[inline]
1059    fn make_owned(&mut self) {
1060        unsafe {
1061            let ptr = self.ptr.get().get();
1062            if ptr <= MAX_INLINE_TAG || (ptr & 1) == 1 {
1063                *self = Tendril::owned_copy(self.as_byte_slice());
1064            }
1065        }
1066    }
1067
1068    #[inline]
1069    unsafe fn make_owned_with_capacity(&mut self, cap: u32) {
1070        self.make_owned();
1071        let mut buf = self.assume_buf().0;
1072        buf.grow(cap);
1073        self.ptr.set(NonZeroUsize::new_unchecked(buf.ptr as usize));
1074        self.set_aux(buf.cap);
1075    }
1076
1077    #[inline(always)]
1078    unsafe fn header(&self) -> *mut Header<A> {
1079        (self.ptr.get().get() & !1) as *mut Header<A>
1080    }
1081
1082    #[inline]
1083    unsafe fn assume_buf(&self) -> (Buf32<Header<A>>, bool, u32) {
1084        let ptr = self.ptr.get().get();
1085        let header = self.header();
1086        let shared = (ptr & 1) == 1;
1087        let (cap, offset) = match shared {
1088            true => ((*header).cap, self.aux()),
1089            false => (self.aux(), 0),
1090        };
1091
1092        (
1093            Buf32 {
1094                ptr: header,
1095                len: offset + self.len32(),
1096                cap,
1097            },
1098            shared,
1099            offset,
1100        )
1101    }
1102
1103    #[inline]
1104    unsafe fn inline(x: &[u8]) -> Tendril<F, A> {
1105        let len = x.len();
1106        let t = Tendril {
1107            ptr: Cell::new(inline_tag(len as u32)),
1108            buf: UnsafeCell::new(Buffer { inline: [0; 8] }),
1109            marker: PhantomData,
1110            refcount_marker: PhantomData,
1111        };
1112        ptr::copy_nonoverlapping(x.as_ptr(), (*t.buf.get()).inline.as_mut_ptr(), len);
1113        t
1114    }
1115
1116    #[inline]
1117    unsafe fn owned(x: Buf32<Header<A>>) -> Tendril<F, A> {
1118        Tendril {
1119            ptr: Cell::new(NonZeroUsize::new_unchecked(x.ptr as usize)),
1120            buf: UnsafeCell::new(Buffer {
1121                heap: Heap {
1122                    len: x.len,
1123                    aux: x.cap,
1124                },
1125            }),
1126            marker: PhantomData,
1127            refcount_marker: PhantomData,
1128        }
1129    }
1130
1131    #[inline]
1132    unsafe fn owned_copy(x: &[u8]) -> Tendril<F, A> {
1133        let len32 = x.len() as u32;
1134        let mut b = Buf32::with_capacity(len32, Header::new());
1135        ptr::copy_nonoverlapping(x.as_ptr(), b.data_ptr(), x.len());
1136        b.len = len32;
1137        Tendril::owned(b)
1138    }
1139
1140    #[inline]
1141    unsafe fn shared(buf: Buf32<Header<A>>, off: u32, len: u32) -> Tendril<F, A> {
1142        Tendril {
1143            ptr: Cell::new(NonZeroUsize::new_unchecked((buf.ptr as usize) | 1)),
1144            buf: UnsafeCell::new(Buffer {
1145                heap: Heap { len, aux: off },
1146            }),
1147            marker: PhantomData,
1148            refcount_marker: PhantomData,
1149        }
1150    }
1151
1152    #[inline]
1153    fn as_byte_slice(&self) -> &[u8] {
1154        unsafe {
1155            match self.ptr.get().get() {
1156                EMPTY_TAG => &[],
1157                n if n <= MAX_INLINE_LEN => (*self.buf.get()).inline.get_unchecked(..n),
1158                _ => {
1159                    let (buf, _, offset) = self.assume_buf();
1160                    copy_lifetime(
1161                        self,
1162                        unsafe_slice(buf.data(), offset as usize, self.len32() as usize),
1163                    )
1164                },
1165            }
1166        }
1167    }
1168
1169    // There's no need to worry about locking on an atomic Tendril, because it makes it unique as
1170    // soon as you do that.
1171    #[inline]
1172    fn as_mut_byte_slice(&mut self) -> &mut [u8] {
1173        unsafe {
1174            match self.ptr.get().get() {
1175                EMPTY_TAG => &mut [],
1176                n if n <= MAX_INLINE_LEN => (*self.buf.get()).inline.get_unchecked_mut(..n),
1177                _ => {
1178                    self.make_owned();
1179                    let (mut buf, _, offset) = self.assume_buf();
1180                    let len = self.len32() as usize;
1181                    copy_lifetime_mut(self, unsafe_slice_mut(buf.data_mut(), offset as usize, len))
1182                },
1183            }
1184        }
1185    }
1186
1187    unsafe fn raw_len(&self) -> u32 {
1188        (*self.buf.get()).heap.len
1189    }
1190
1191    unsafe fn set_len(&mut self, len: u32) {
1192        (*self.buf.get()).heap.len = len;
1193    }
1194
1195    unsafe fn aux(&self) -> u32 {
1196        (*self.buf.get()).heap.aux
1197    }
1198
1199    unsafe fn set_aux(&self, aux: u32) {
1200        (*self.buf.get()).heap.aux = aux;
1201    }
1202}
1203
1204impl<F, A> Tendril<F, A>
1205where
1206    F: fmt::SliceFormat,
1207    A: Atomicity,
1208{
1209    /// Build a `Tendril` by copying a slice.
1210    #[inline]
1211    pub fn from_slice(x: &F::Slice) -> Tendril<F, A> {
1212        unsafe { Tendril::from_byte_slice_without_validating(x.as_bytes()) }
1213    }
1214
1215    /// Push a slice onto the end of the `Tendril`.
1216    #[inline]
1217    pub fn push_slice(&mut self, x: &F::Slice) {
1218        unsafe { self.push_bytes_without_validating(x.as_bytes()) }
1219    }
1220}
1221
1222/// A simple wrapper to make `Tendril` `Send`.
1223///
1224/// Although there is a certain subset of the operations on a `Tendril` that a `SendTendril` could
1225/// reasonably implement, in order to clearly separate concerns this type is deliberately
1226/// minimalist, acting as a safe encapsulation around the invariants which permit `Send`ness and
1227/// behaving as an opaque object.
1228///
1229/// A `SendTendril` may be produced by `Tendril.into_send()` or `SendTendril::from(tendril)`,
1230/// and may be returned to a `Tendril` by `Tendril::from(self)`.
1231#[derive(Clone)]
1232pub struct SendTendril<F>
1233where
1234    F: fmt::Format,
1235{
1236    tendril: Tendril<F>,
1237}
1238
1239unsafe impl<F> Send for SendTendril<F> where F: fmt::Format {}
1240
1241impl<F, A> From<Tendril<F, A>> for SendTendril<F>
1242where
1243    F: fmt::Format,
1244    A: Atomicity,
1245{
1246    #[inline]
1247    fn from(tendril: Tendril<F, A>) -> SendTendril<F> {
1248        tendril.into_send()
1249    }
1250}
1251
1252impl<F, A> From<SendTendril<F>> for Tendril<F, A>
1253where
1254    F: fmt::Format,
1255    A: Atomicity,
1256{
1257    #[inline]
1258    fn from(send: SendTendril<F>) -> Tendril<F, A> {
1259        unsafe { mem::transmute(send.tendril) }
1260        // header.refcount may have been initialised as an Atomic or a NonAtomic, but the value
1261        // will be the same (1) regardless, because the layout is defined.
1262        // Thus we don't need to fiddle about resetting it or anything like that.
1263    }
1264}
1265
1266/// `Tendril`-related methods for Rust slices.
1267pub trait SliceExt<F>: fmt::Slice
1268where
1269    F: fmt::SliceFormat<Slice = Self>,
1270{
1271    /// Make a `Tendril` from this slice.
1272    #[inline]
1273    fn to_tendril(&self) -> Tendril<F> {
1274        // It should be done thusly, but at the time of writing the defaults don't help inference:
1275        //fn to_tendril<A = NonAtomic>(&self) -> Tendril<Self::Format, A>
1276        //    where A: Atomicity,
1277        //{
1278        Tendril::from_slice(self)
1279    }
1280}
1281
1282impl SliceExt<fmt::UTF8> for str {}
1283impl SliceExt<fmt::Bytes> for [u8] {}
1284
1285impl<F, A> Tendril<F, A>
1286where
1287    F: for<'a> fmt::CharFormat<'a>,
1288    A: Atomicity,
1289{
1290    /// Remove and return the first character, if any.
1291    #[inline]
1292    pub fn pop_front_char(&mut self) -> Option<char> {
1293        unsafe {
1294            let next_char; // first char in iterator
1295            let mut skip = 0; // number of bytes to skip, or 0 to clear
1296
1297            {
1298                // <--+
1299                //  |  Creating an iterator borrows self, so introduce a
1300                //  +- scope to contain the borrow (that way we can mutate
1301                //     self below, after this scope exits).
1302
1303                let mut iter = F::char_indices(self.as_byte_slice());
1304                match iter.next() {
1305                    Some((_, c)) => {
1306                        next_char = Some(c);
1307                        if let Some((n, _)) = iter.next() {
1308                            skip = n as u32;
1309                        }
1310                    },
1311                    None => {
1312                        next_char = None;
1313                    },
1314                }
1315            }
1316
1317            if skip != 0 {
1318                self.unsafe_pop_front(skip);
1319            } else {
1320                self.clear();
1321            }
1322
1323            next_char
1324        }
1325    }
1326
1327    /// Remove and return a run of characters at the front of the `Tendril`
1328    /// which are classified the same according to the function `classify`.
1329    ///
1330    /// Returns `None` on an empty string.
1331    #[inline]
1332    pub fn pop_front_char_run<C, R>(&mut self, mut classify: C) -> Option<(Tendril<F, A>, R)>
1333    where
1334        C: FnMut(char) -> R,
1335        R: PartialEq,
1336    {
1337        let (class, first_mismatch);
1338        {
1339            let mut chars = unsafe { F::char_indices(self.as_byte_slice()) };
1340            let (_, first) = chars.next()?;
1341            class = classify(first);
1342            first_mismatch = chars.find(|&(_, ch)| classify(ch) != class);
1343        }
1344
1345        match first_mismatch {
1346            Some((idx, _)) => unsafe {
1347                let t = self.unsafe_subtendril(0, idx as u32);
1348                self.unsafe_pop_front(idx as u32);
1349                Some((t, class))
1350            },
1351            None => {
1352                let t = self.clone();
1353                self.clear();
1354                Some((t, class))
1355            },
1356        }
1357    }
1358
1359    /// Push a character, if it can be represented in this format.
1360    #[inline]
1361    pub fn try_push_char(&mut self, c: char) -> Result<(), ()> {
1362        F::encode_char(c, |b| unsafe {
1363            self.push_bytes_without_validating(b);
1364        })
1365    }
1366}
1367
1368/// Extension trait for `io::Read`.
1369pub trait ReadExt: io::Read {
1370    fn read_to_tendril<A>(&mut self, buf: &mut Tendril<fmt::Bytes, A>) -> io::Result<usize>
1371    where
1372        A: Atomicity;
1373}
1374
1375impl<T> ReadExt for T
1376where
1377    T: io::Read,
1378{
1379    /// Read all bytes until EOF.
1380    fn read_to_tendril<A>(&mut self, buf: &mut Tendril<fmt::Bytes, A>) -> io::Result<usize>
1381    where
1382        A: Atomicity,
1383    {
1384        // Adapted from libstd/io/mod.rs.
1385        const DEFAULT_BUF_SIZE: u32 = 64 * 1024;
1386
1387        let start_len = buf.len();
1388        let mut len = start_len;
1389        let mut new_write_size = 16;
1390        let ret;
1391        loop {
1392            if len == buf.len() {
1393                if new_write_size < DEFAULT_BUF_SIZE {
1394                    new_write_size *= 2;
1395                }
1396                // FIXME: this exposes uninitialized bytes to a generic R type
1397                // this is fine for R=File which never reads these bytes,
1398                // but user-defined types might.
1399                // The standard library pushes zeros to `Vec<u8>` for that reason.
1400                unsafe {
1401                    buf.push_uninitialized(new_write_size);
1402                }
1403            }
1404
1405            match self.read(&mut buf[len..]) {
1406                Ok(0) => {
1407                    ret = Ok(len - start_len);
1408                    break;
1409                },
1410                Ok(n) => len += n,
1411                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {},
1412                Err(e) => {
1413                    ret = Err(e);
1414                    break;
1415                },
1416            }
1417        }
1418
1419        let buf_len = buf.len32();
1420        buf.pop_back(buf_len - (len as u32));
1421        ret
1422    }
1423}
1424
1425impl<A> io::Write for Tendril<fmt::Bytes, A>
1426where
1427    A: Atomicity,
1428{
1429    #[inline]
1430    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
1431        self.push_slice(buf);
1432        Ok(buf.len())
1433    }
1434
1435    #[inline]
1436    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
1437        self.push_slice(buf);
1438        Ok(())
1439    }
1440
1441    #[inline(always)]
1442    fn flush(&mut self) -> io::Result<()> {
1443        Ok(())
1444    }
1445}
1446
1447impl<F, A> Tendril<F, A>
1448where
1449    A: Atomicity,
1450    F: fmt::SliceFormat<Slice = [u8]>,
1451{
1452    /// Push "uninitialized bytes" onto the end.
1453    ///
1454    /// Really, this grows the tendril without writing anything to the new area.
1455    /// It's only defined for byte tendrils because it's only useful if you
1456    /// plan to then mutate the buffer.
1457    #[inline]
1458    pub unsafe fn push_uninitialized(&mut self, n: u32) {
1459        let new_len = self.len32().checked_add(n).expect(OFLOW);
1460        if new_len <= MAX_INLINE_LEN as u32 && self.ptr.get().get() <= MAX_INLINE_TAG {
1461            self.ptr.set(inline_tag(new_len))
1462        } else {
1463            self.make_owned_with_capacity(new_len);
1464            self.set_len(new_len);
1465        }
1466    }
1467}
1468
1469impl<A> strfmt::Display for Tendril<fmt::UTF8, A>
1470where
1471    A: Atomicity,
1472{
1473    #[inline]
1474    fn fmt(&self, f: &mut strfmt::Formatter) -> strfmt::Result {
1475        <str as strfmt::Display>::fmt(&**self, f)
1476    }
1477}
1478
1479impl<A> str::FromStr for Tendril<fmt::UTF8, A>
1480where
1481    A: Atomicity,
1482{
1483    type Err = ();
1484
1485    #[inline]
1486    fn from_str(s: &str) -> Result<Self, ()> {
1487        Ok(Tendril::from_slice(s))
1488    }
1489}
1490
1491impl<A> strfmt::Write for Tendril<fmt::UTF8, A>
1492where
1493    A: Atomicity,
1494{
1495    #[inline]
1496    fn write_str(&mut self, s: &str) -> strfmt::Result {
1497        self.push_slice(s);
1498        Ok(())
1499    }
1500}
1501
1502impl<A> Tendril<fmt::UTF8, A>
1503where
1504    A: Atomicity,
1505{
1506    /// Push a character onto the end.
1507    #[inline]
1508    pub fn push_char(&mut self, c: char) {
1509        unsafe {
1510            self.push_bytes_without_validating(c.encode_utf8(&mut [0_u8; 4]).as_bytes());
1511        }
1512    }
1513
1514    /// Create a `Tendril` from a single character.
1515    #[inline]
1516    pub fn from_char(c: char) -> Tendril<fmt::UTF8, A> {
1517        let mut t: Tendril<fmt::UTF8, A> = Tendril::new();
1518        t.push_char(c);
1519        t
1520    }
1521
1522    /// Helper for the `format_tendril!` macro.
1523    #[inline]
1524    pub fn format(args: strfmt::Arguments) -> Tendril<fmt::UTF8, A> {
1525        use std::fmt::Write;
1526        let mut output: Tendril<fmt::UTF8, A> = Tendril::new();
1527        let _ = write!(&mut output, "{}", args);
1528        output
1529    }
1530}
1531
1532/// Create a `StrTendril` through string formatting.
1533///
1534/// Works just like the standard `format!` macro.
1535#[macro_export]
1536macro_rules! format_tendril {
1537    ($($arg:tt)*) => ($crate::StrTendril::format(format_args!($($arg)*)))
1538}
1539
1540impl<F, A> From<&F::Slice> for Tendril<F, A>
1541where
1542    F: fmt::SliceFormat,
1543    A: Atomicity,
1544{
1545    #[inline]
1546    fn from(input: &F::Slice) -> Tendril<F, A> {
1547        Tendril::from_slice(input)
1548    }
1549}
1550
1551impl<A> From<String> for Tendril<fmt::UTF8, A>
1552where
1553    A: Atomicity,
1554{
1555    #[inline]
1556    fn from(input: String) -> Tendril<fmt::UTF8, A> {
1557        Tendril::from_slice(&*input)
1558    }
1559}
1560
1561impl<F, A> AsRef<F::Slice> for Tendril<F, A>
1562where
1563    F: fmt::SliceFormat,
1564    A: Atomicity,
1565{
1566    #[inline]
1567    fn as_ref(&self) -> &F::Slice {
1568        self
1569    }
1570}
1571
1572impl<A> From<Tendril<fmt::UTF8, A>> for String
1573where
1574    A: Atomicity,
1575{
1576    #[inline]
1577    fn from(input: Tendril<fmt::UTF8, A>) -> String {
1578        String::from(&*input)
1579    }
1580}
1581
1582impl<'a, A> From<&'a Tendril<fmt::UTF8, A>> for String
1583where
1584    A: Atomicity,
1585{
1586    #[inline]
1587    fn from(input: &'a Tendril<fmt::UTF8, A>) -> String {
1588        String::from(&**input)
1589    }
1590}
1591
1592#[cfg(test)]
1593mod test {
1594    use super::{
1595        Atomic, ByteTendril, Header, NonAtomic, ReadExt, SendTendril, SliceExt, StrTendril, Tendril,
1596    };
1597    use crate::fmt;
1598    use std::iter;
1599    use std::thread;
1600
1601    fn assert_send<T: Send>() {}
1602
1603    #[test]
1604    fn smoke_test() {
1605        assert_eq!("", &*"".to_tendril());
1606        assert_eq!("abc", &*"abc".to_tendril());
1607        assert_eq!("Hello, world!", &*"Hello, world!".to_tendril());
1608
1609        assert_eq!(b"", &*b"".to_tendril());
1610        assert_eq!(b"abc", &*b"abc".to_tendril());
1611        assert_eq!(b"Hello, world!", &*b"Hello, world!".to_tendril());
1612    }
1613
1614    #[test]
1615    fn assert_sizes() {
1616        use std::mem;
1617        struct EmptyWithDrop;
1618        impl Drop for EmptyWithDrop {
1619            fn drop(&mut self) {}
1620        }
1621        let compiler_uses_inline_drop_flags = mem::size_of::<EmptyWithDrop>() > 0;
1622
1623        let correct = mem::size_of::<*const ()>()
1624            + 8
1625            + if compiler_uses_inline_drop_flags {
1626                1
1627            } else {
1628                0
1629            };
1630
1631        assert_eq!(correct, mem::size_of::<ByteTendril>());
1632        assert_eq!(correct, mem::size_of::<StrTendril>());
1633
1634        // This is no longer true. See https://github.com/servo/tendril/issues/66
1635        // assert_eq!(correct, mem::size_of::<Option<ByteTendril>>());
1636        // assert_eq!(correct, mem::size_of::<Option<StrTendril>>());
1637
1638        assert_eq!(
1639            mem::size_of::<*const ()>() * 2,
1640            mem::size_of::<Header<Atomic>>(),
1641        );
1642        assert_eq!(
1643            mem::size_of::<Header<Atomic>>(),
1644            mem::size_of::<Header<NonAtomic>>(),
1645        );
1646    }
1647
1648    #[test]
1649    fn validate_utf8() {
1650        assert!(ByteTendril::try_from_byte_slice(b"\xFF").is_ok());
1651        assert!(StrTendril::try_from_byte_slice(b"\xFF").is_err());
1652        assert!(StrTendril::try_from_byte_slice(b"\xEA\x99\xFF").is_err());
1653        assert!(StrTendril::try_from_byte_slice(b"\xEA\x99").is_err());
1654        assert!(StrTendril::try_from_byte_slice(b"\xEA\x99\xAE\xEA").is_err());
1655        assert_eq!(
1656            "\u{a66e}",
1657            &*StrTendril::try_from_byte_slice(b"\xEA\x99\xAE").unwrap()
1658        );
1659
1660        let mut t = StrTendril::new();
1661        assert!(t.try_push_bytes(b"\xEA\x99").is_err());
1662        assert!(t.try_push_bytes(b"\xAE").is_err());
1663        assert!(t.try_push_bytes(b"\xEA\x99\xAE").is_ok());
1664        assert_eq!("\u{a66e}", &*t);
1665    }
1666
1667    #[test]
1668    fn share_and_unshare() {
1669        let s = b"foobarbaz".to_tendril();
1670        assert_eq!(b"foobarbaz", &*s);
1671        assert!(!s.is_shared());
1672
1673        let mut t = s.clone();
1674        assert_eq!(s.as_ptr(), t.as_ptr());
1675        assert!(s.is_shared());
1676        assert!(t.is_shared());
1677
1678        t.push_slice(b"quux");
1679        assert_eq!(b"foobarbaz", &*s);
1680        assert_eq!(b"foobarbazquux", &*t);
1681        assert!(s.as_ptr() != t.as_ptr());
1682        assert!(!t.is_shared());
1683    }
1684
1685    #[test]
1686    fn format_display() {
1687        assert_eq!("foobar", &*format!("{}", "foobar".to_tendril()));
1688
1689        let mut s = "foo".to_tendril();
1690        assert_eq!("foo", &*format!("{}", s));
1691
1692        let t = s.clone();
1693        assert_eq!("foo", &*format!("{}", s));
1694        assert_eq!("foo", &*format!("{}", t));
1695
1696        s.push_slice("barbaz!");
1697        assert_eq!("foobarbaz!", &*format!("{}", s));
1698        assert_eq!("foo", &*format!("{}", t));
1699    }
1700
1701    #[test]
1702    fn format_debug() {
1703        assert_eq!(
1704            r#"Tendril<UTF8>(inline: "foobar")"#,
1705            &*format!("{:?}", "foobar".to_tendril())
1706        );
1707        assert_eq!(
1708            r#"Tendril<Bytes>(inline: [102, 111, 111, 98, 97, 114])"#,
1709            &*format!("{:?}", b"foobar".to_tendril())
1710        );
1711
1712        let t = "anextralongstring".to_tendril();
1713        assert_eq!(
1714            r#"Tendril<UTF8>(owned: "anextralongstring")"#,
1715            &*format!("{:?}", t)
1716        );
1717        let _ = t.clone();
1718        assert_eq!(
1719            r#"Tendril<UTF8>(shared: "anextralongstring")"#,
1720            &*format!("{:?}", t)
1721        );
1722    }
1723
1724    #[test]
1725    fn subtendril() {
1726        assert_eq!("foo".to_tendril(), "foo-bar".to_tendril().subtendril(0, 3));
1727        assert_eq!("bar".to_tendril(), "foo-bar".to_tendril().subtendril(4, 3));
1728
1729        let mut t = "foo-bar".to_tendril();
1730        t.pop_front(2);
1731        assert_eq!("o-bar".to_tendril(), t);
1732        t.pop_back(1);
1733        assert_eq!("o-ba".to_tendril(), t);
1734
1735        assert_eq!(
1736            "foo".to_tendril(),
1737            "foo-a-longer-string-bar-baz".to_tendril().subtendril(0, 3)
1738        );
1739        assert_eq!(
1740            "oo-a-".to_tendril(),
1741            "foo-a-longer-string-bar-baz".to_tendril().subtendril(1, 5)
1742        );
1743        assert_eq!(
1744            "bar".to_tendril(),
1745            "foo-a-longer-string-bar-baz".to_tendril().subtendril(20, 3)
1746        );
1747
1748        let mut t = "another rather long string".to_tendril();
1749        t.pop_front(2);
1750        assert!(t.starts_with("other rather"));
1751        t.pop_back(1);
1752        assert_eq!("other rather long strin".to_tendril(), t);
1753        assert!(t.is_shared());
1754    }
1755
1756    #[test]
1757    fn subtendril_invalid() {
1758        assert!("\u{a66e}".to_tendril().try_subtendril(0, 2).is_err());
1759        assert!("\u{a66e}".to_tendril().try_subtendril(1, 2).is_err());
1760
1761        assert!("\u{1f4a9}".to_tendril().try_subtendril(0, 3).is_err());
1762        assert!("\u{1f4a9}".to_tendril().try_subtendril(0, 2).is_err());
1763        assert!("\u{1f4a9}".to_tendril().try_subtendril(0, 1).is_err());
1764        assert!("\u{1f4a9}".to_tendril().try_subtendril(1, 3).is_err());
1765        assert!("\u{1f4a9}".to_tendril().try_subtendril(1, 2).is_err());
1766        assert!("\u{1f4a9}".to_tendril().try_subtendril(1, 1).is_err());
1767        assert!("\u{1f4a9}".to_tendril().try_subtendril(2, 2).is_err());
1768        assert!("\u{1f4a9}".to_tendril().try_subtendril(2, 1).is_err());
1769        assert!("\u{1f4a9}".to_tendril().try_subtendril(3, 1).is_err());
1770
1771        let mut t = "\u{1f4a9}zzzzzz".to_tendril();
1772        assert!(t.try_pop_front(1).is_err());
1773        assert!(t.try_pop_front(2).is_err());
1774        assert!(t.try_pop_front(3).is_err());
1775        assert!(t.try_pop_front(4).is_ok());
1776        assert_eq!("zzzzzz", &*t);
1777
1778        let mut t = "zzzzzz\u{1f4a9}".to_tendril();
1779        assert!(t.try_pop_back(1).is_err());
1780        assert!(t.try_pop_back(2).is_err());
1781        assert!(t.try_pop_back(3).is_err());
1782        assert!(t.try_pop_back(4).is_ok());
1783        assert_eq!("zzzzzz", &*t);
1784    }
1785
1786    #[test]
1787    fn conversion() {
1788        assert_eq!(
1789            &[0x66, 0x6F, 0x6F].to_tendril(),
1790            "foo".to_tendril().as_bytes()
1791        );
1792        assert_eq!(
1793            [0x66, 0x6F, 0x6F].to_tendril(),
1794            "foo".to_tendril().into_bytes()
1795        );
1796
1797        let ascii: Tendril<fmt::ASCII> = b"hello".to_tendril().try_reinterpret().unwrap();
1798        assert_eq!(&"hello".to_tendril(), ascii.as_superset());
1799        assert_eq!("hello".to_tendril(), ascii.clone().into_superset());
1800
1801        assert!(b"\xFF"
1802            .to_tendril()
1803            .try_reinterpret::<fmt::ASCII>()
1804            .is_err());
1805
1806        let t = "hello".to_tendril();
1807        let ascii: &Tendril<fmt::ASCII> = t.try_as_subset().unwrap();
1808        assert_eq!(b"hello", &**ascii.as_bytes());
1809
1810        assert!("ő"
1811            .to_tendril()
1812            .try_reinterpret_view::<fmt::ASCII>()
1813            .is_err());
1814        assert!("ő".to_tendril().try_as_subset::<fmt::ASCII>().is_err());
1815
1816        let ascii: Tendril<fmt::ASCII> = "hello".to_tendril().try_into_subset().unwrap();
1817        assert_eq!(b"hello", &**ascii.as_bytes());
1818
1819        assert!("ő".to_tendril().try_reinterpret::<fmt::ASCII>().is_err());
1820        assert!("ő".to_tendril().try_into_subset::<fmt::ASCII>().is_err());
1821    }
1822
1823    #[test]
1824    fn clear() {
1825        let mut t = "foo-".to_tendril();
1826        t.clear();
1827        assert_eq!(t.len(), 0);
1828        assert_eq!(t.len32(), 0);
1829        assert_eq!(&*t, "");
1830
1831        let mut t = "much longer".to_tendril();
1832        let s = t.clone();
1833        t.clear();
1834        assert_eq!(t.len(), 0);
1835        assert_eq!(t.len32(), 0);
1836        assert_eq!(&*t, "");
1837        assert_eq!(&*s, "much longer");
1838    }
1839
1840    #[test]
1841    fn push_tendril() {
1842        let mut t = "abc".to_tendril();
1843        t.push_tendril(&"xyz".to_tendril());
1844        assert_eq!("abcxyz", &*t);
1845    }
1846
1847    #[test]
1848    fn wtf8() {
1849        assert!(Tendril::<fmt::WTF8>::try_from_byte_slice(b"\xED\xA0\xBD").is_ok());
1850        assert!(Tendril::<fmt::WTF8>::try_from_byte_slice(b"\xED\xB2\xA9").is_ok());
1851        assert!(Tendril::<fmt::WTF8>::try_from_byte_slice(b"\xED\xA0\xBD\xED\xB2\xA9").is_err());
1852
1853        let t: Tendril<fmt::WTF8> =
1854            Tendril::try_from_byte_slice(b"\xED\xA0\xBD\xEA\x99\xAE").unwrap();
1855        assert!(b"\xED\xA0\xBD".to_tendril().try_reinterpret().unwrap() == t.subtendril(0, 3));
1856        assert!(b"\xEA\x99\xAE".to_tendril().try_reinterpret().unwrap() == t.subtendril(3, 3));
1857        assert!(t.try_reinterpret_view::<fmt::UTF8>().is_err());
1858
1859        assert!(t.try_subtendril(0, 1).is_err());
1860        assert!(t.try_subtendril(0, 2).is_err());
1861        assert!(t.try_subtendril(1, 1).is_err());
1862
1863        assert!(t.try_subtendril(3, 1).is_err());
1864        assert!(t.try_subtendril(3, 2).is_err());
1865        assert!(t.try_subtendril(4, 1).is_err());
1866
1867        // paired surrogates
1868        let mut t: Tendril<fmt::WTF8> = Tendril::try_from_byte_slice(b"\xED\xA0\xBD").unwrap();
1869        assert!(t.try_push_bytes(b"\xED\xB2\xA9").is_ok());
1870        assert_eq!(b"\xF0\x9F\x92\xA9", t.as_byte_slice());
1871        assert!(t.try_reinterpret_view::<fmt::UTF8>().is_ok());
1872
1873        // unpaired surrogates
1874        let mut t: Tendril<fmt::WTF8> = Tendril::try_from_byte_slice(b"\xED\xA0\xBB").unwrap();
1875        assert!(t.try_push_bytes(b"\xED\xA0").is_err());
1876        assert!(t.try_push_bytes(b"\xED").is_err());
1877        assert!(t.try_push_bytes(b"\xA0").is_err());
1878        assert!(t.try_push_bytes(b"\xED\xA0\xBD").is_ok());
1879        assert_eq!(b"\xED\xA0\xBB\xED\xA0\xBD", t.as_byte_slice());
1880        assert!(t.try_push_bytes(b"\xED\xB2\xA9").is_ok());
1881        assert_eq!(b"\xED\xA0\xBB\xF0\x9F\x92\xA9", t.as_byte_slice());
1882        assert!(t.try_reinterpret_view::<fmt::UTF8>().is_err());
1883    }
1884
1885    #[test]
1886    fn front_char() {
1887        let mut t = "".to_tendril();
1888        assert_eq!(None, t.pop_front_char());
1889        assert_eq!(None, t.pop_front_char());
1890
1891        let mut t = "abc".to_tendril();
1892        assert_eq!(Some('a'), t.pop_front_char());
1893        assert_eq!(Some('b'), t.pop_front_char());
1894        assert_eq!(Some('c'), t.pop_front_char());
1895        assert_eq!(None, t.pop_front_char());
1896        assert_eq!(None, t.pop_front_char());
1897
1898        let mut t = "főo-a-longer-string-bar-baz".to_tendril();
1899        assert_eq!(28, t.len());
1900        assert_eq!(Some('f'), t.pop_front_char());
1901        assert_eq!(Some('ő'), t.pop_front_char());
1902        assert_eq!(Some('o'), t.pop_front_char());
1903        assert_eq!(Some('-'), t.pop_front_char());
1904        assert_eq!(23, t.len());
1905    }
1906
1907    #[test]
1908    fn char_run() {
1909        for &(s, exp) in &[
1910            ("", None),
1911            (" ", Some((" ", true))),
1912            ("x", Some(("x", false))),
1913            ("  \t  \n", Some(("  \t  \n", true))),
1914            ("xyzzy", Some(("xyzzy", false))),
1915            ("   xyzzy", Some(("   ", true))),
1916            ("xyzzy   ", Some(("xyzzy", false))),
1917            ("   xyzzy  ", Some(("   ", true))),
1918            ("xyzzy   hi", Some(("xyzzy", false))),
1919            ("中 ", Some(("中", false))),
1920            (" 中 ", Some((" ", true))),
1921            ("  中 ", Some(("  ", true))),
1922            ("   中 ", Some(("   ", true))),
1923        ] {
1924            let mut t = s.to_tendril();
1925            let res = t.pop_front_char_run(char::is_whitespace);
1926            match exp {
1927                None => assert!(res.is_none()),
1928                Some((es, ec)) => {
1929                    let (rt, rc) = res.unwrap();
1930                    assert_eq!(es, &*rt);
1931                    assert_eq!(ec, rc);
1932                },
1933            }
1934        }
1935    }
1936
1937    #[test]
1938    fn deref_mut_inline() {
1939        let mut t = "xyő".to_tendril().into_bytes();
1940        t[3] = 0xff;
1941        assert_eq!(b"xy\xC5\xFF", &*t);
1942        assert!(t.try_reinterpret_view::<fmt::UTF8>().is_err());
1943        t[3] = 0x8b;
1944        assert_eq!("xyŋ", &**t.try_reinterpret_view::<fmt::UTF8>().unwrap());
1945
1946        unsafe {
1947            t.push_uninitialized(3);
1948            t[4] = 0xEA;
1949            t[5] = 0x99;
1950            t[6] = 0xAE;
1951            assert_eq!(
1952                "xyŋ\u{a66e}",
1953                &**t.try_reinterpret_view::<fmt::UTF8>().unwrap()
1954            );
1955            t.push_uninitialized(20);
1956            t.pop_back(20);
1957            assert_eq!(
1958                "xyŋ\u{a66e}",
1959                &**t.try_reinterpret_view::<fmt::UTF8>().unwrap()
1960            );
1961        }
1962    }
1963
1964    #[test]
1965    fn deref_mut() {
1966        let mut t = b"0123456789".to_tendril();
1967        let u = t.clone();
1968        assert!(t.is_shared());
1969        t[9] = 0xff;
1970        assert!(!t.is_shared());
1971        assert_eq!(b"0123456789", &*u);
1972        assert_eq!(b"012345678\xff", &*t);
1973    }
1974
1975    #[test]
1976    fn push_char() {
1977        let mut t = "xyz".to_tendril();
1978        t.push_char('o');
1979        assert_eq!("xyzo", &*t);
1980        t.push_char('ő');
1981        assert_eq!("xyzoő", &*t);
1982        t.push_char('\u{a66e}');
1983        assert_eq!("xyzoő\u{a66e}", &*t);
1984        t.push_char('\u{1f4a9}');
1985        assert_eq!("xyzoő\u{a66e}\u{1f4a9}", &*t);
1986        assert_eq!(t.len(), 13);
1987    }
1988
1989    #[test]
1990    fn ascii() {
1991        fn mk(x: &[u8]) -> Tendril<fmt::ASCII> {
1992            x.to_tendril().try_reinterpret().unwrap()
1993        }
1994
1995        let mut t = mk(b"xyz");
1996        assert_eq!(Some('x'), t.pop_front_char());
1997        assert_eq!(Some('y'), t.pop_front_char());
1998        assert_eq!(Some('z'), t.pop_front_char());
1999        assert_eq!(None, t.pop_front_char());
2000
2001        let mut t = mk(b" \t xyz");
2002        assert!(Some((mk(b" \t "), true)) == t.pop_front_char_run(char::is_whitespace));
2003        assert!(Some((mk(b"xyz"), false)) == t.pop_front_char_run(char::is_whitespace));
2004        assert!(t.pop_front_char_run(char::is_whitespace).is_none());
2005
2006        let mut t = Tendril::<fmt::ASCII>::new();
2007        assert!(t.try_push_char('x').is_ok());
2008        assert!(t.try_push_char('\0').is_ok());
2009        assert!(t.try_push_char('\u{a0}').is_err());
2010        assert_eq!(b"x\0", t.as_byte_slice());
2011    }
2012
2013    #[test]
2014    fn latin1() {
2015        fn mk(x: &[u8]) -> Tendril<fmt::Latin1> {
2016            x.to_tendril().try_reinterpret().unwrap()
2017        }
2018
2019        let mut t = mk(b"\xd8_\xd8");
2020        assert_eq!(Some('Ø'), t.pop_front_char());
2021        assert_eq!(Some('_'), t.pop_front_char());
2022        assert_eq!(Some('Ø'), t.pop_front_char());
2023        assert_eq!(None, t.pop_front_char());
2024
2025        let mut t = mk(b" \t \xfe\xa7z");
2026        assert!(Some((mk(b" \t "), true)) == t.pop_front_char_run(char::is_whitespace));
2027        assert!(Some((mk(b"\xfe\xa7z"), false)) == t.pop_front_char_run(char::is_whitespace));
2028        assert!(t.pop_front_char_run(char::is_whitespace).is_none());
2029
2030        let mut t = Tendril::<fmt::Latin1>::new();
2031        assert!(t.try_push_char('x').is_ok());
2032        assert!(t.try_push_char('\0').is_ok());
2033        assert!(t.try_push_char('\u{a0}').is_ok());
2034        assert!(t.try_push_char('ő').is_err());
2035        assert!(t.try_push_char('я').is_err());
2036        assert!(t.try_push_char('\u{a66e}').is_err());
2037        assert!(t.try_push_char('\u{1f4a9}').is_err());
2038        assert_eq!(b"x\0\xa0", t.as_byte_slice());
2039    }
2040
2041    #[test]
2042    fn format() {
2043        assert_eq!("", &*format_tendril!(""));
2044        assert_eq!(
2045            "two and two make 4",
2046            &*format_tendril!("two and two make {}", 2 + 2)
2047        );
2048    }
2049
2050    #[test]
2051    fn merge_shared() {
2052        let t = "012345678901234567890123456789".to_tendril();
2053        let a = t.subtendril(10, 20);
2054        assert!(a.is_shared());
2055        assert_eq!("01234567890123456789", &*a);
2056        let mut b = t.subtendril(0, 10);
2057        assert!(b.is_shared());
2058        assert_eq!("0123456789", &*b);
2059
2060        b.push_tendril(&a);
2061        assert!(b.is_shared());
2062        assert!(a.is_shared());
2063        assert!(a.is_shared_with(&b));
2064        assert!(b.is_shared_with(&a));
2065        assert_eq!("012345678901234567890123456789", &*b);
2066
2067        assert!(t.is_shared());
2068        assert!(t.is_shared_with(&a));
2069        assert!(t.is_shared_with(&b));
2070    }
2071
2072    #[test]
2073    fn merge_cant_share() {
2074        let t = "012345678901234567890123456789".to_tendril();
2075        let mut b = t.subtendril(0, 10);
2076        assert!(b.is_shared());
2077        assert_eq!("0123456789", &*b);
2078
2079        b.push_tendril(&"abcd".to_tendril());
2080        assert!(!b.is_shared());
2081        assert_eq!("0123456789abcd", &*b);
2082    }
2083
2084    #[test]
2085    fn shared_doesnt_reserve() {
2086        let mut t = "012345678901234567890123456789".to_tendril();
2087        let a = t.subtendril(1, 10);
2088
2089        assert!(t.is_shared());
2090        t.reserve(10);
2091        assert!(t.is_shared());
2092
2093        let _ = a;
2094    }
2095
2096    #[test]
2097    fn out_of_bounds() {
2098        assert!("".to_tendril().try_subtendril(0, 1).is_err());
2099        assert!("abc".to_tendril().try_subtendril(0, 4).is_err());
2100        assert!("abc".to_tendril().try_subtendril(3, 1).is_err());
2101        assert!("abc".to_tendril().try_subtendril(7, 1).is_err());
2102
2103        let mut t = "".to_tendril();
2104        assert!(t.try_pop_front(1).is_err());
2105        assert!(t.try_pop_front(5).is_err());
2106        assert!(t.try_pop_front(500).is_err());
2107        assert!(t.try_pop_back(1).is_err());
2108        assert!(t.try_pop_back(5).is_err());
2109        assert!(t.try_pop_back(500).is_err());
2110
2111        let mut t = "abcd".to_tendril();
2112        assert!(t.try_pop_front(1).is_ok());
2113        assert!(t.try_pop_front(4).is_err());
2114        assert!(t.try_pop_front(500).is_err());
2115        assert!(t.try_pop_back(1).is_ok());
2116        assert!(t.try_pop_back(3).is_err());
2117        assert!(t.try_pop_back(500).is_err());
2118    }
2119
2120    #[test]
2121    fn compare() {
2122        for &a in &[
2123            "indiscretions",
2124            "validity",
2125            "hallucinogenics",
2126            "timelessness",
2127            "original",
2128            "microcosms",
2129            "boilers",
2130            "mammoth",
2131        ] {
2132            for &b in &[
2133                "intrepidly",
2134                "frigid",
2135                "spa",
2136                "cardigans",
2137                "guileful",
2138                "evaporated",
2139                "unenthusiastic",
2140                "legitimate",
2141            ] {
2142                let ta = a.to_tendril();
2143                let tb = b.to_tendril();
2144
2145                assert_eq!(a.eq(b), ta.eq(&tb));
2146                assert_eq!(a.ne(b), ta.ne(&tb));
2147                assert_eq!(a.lt(b), ta.lt(&tb));
2148                assert_eq!(a.le(b), ta.le(&tb));
2149                assert_eq!(a.gt(b), ta.gt(&tb));
2150                assert_eq!(a.ge(b), ta.ge(&tb));
2151                assert_eq!(a.partial_cmp(b), ta.partial_cmp(&tb));
2152                assert_eq!(a.cmp(b), ta.cmp(&tb));
2153            }
2154        }
2155    }
2156
2157    #[test]
2158    fn extend_and_from_iterator() {
2159        // Testing Extend<T> and FromIterator<T> for the various Ts.
2160
2161        // Tendril<F>
2162        let mut t = "Hello".to_tendril();
2163        t.extend(None::<&Tendril<_>>);
2164        assert_eq!("Hello", &*t);
2165        t.extend(&[", ".to_tendril(), "world".to_tendril(), "!".to_tendril()]);
2166        assert_eq!("Hello, world!", &*t);
2167        assert_eq!(
2168            "Hello, world!",
2169            &*[
2170                "Hello".to_tendril(),
2171                ", ".to_tendril(),
2172                "world".to_tendril(),
2173                "!".to_tendril()
2174            ]
2175            .iter()
2176            .collect::<StrTendril>()
2177        );
2178
2179        // &str
2180        let mut t = "Hello".to_tendril();
2181        t.extend(None::<&str>);
2182        assert_eq!("Hello", &*t);
2183        t.extend([", ", "world", "!"].iter().copied());
2184        assert_eq!("Hello, world!", &*t);
2185        assert_eq!(
2186            "Hello, world!",
2187            &*["Hello", ", ", "world", "!"]
2188                .iter()
2189                .copied()
2190                .collect::<StrTendril>()
2191        );
2192
2193        // &[u8]
2194        let mut t = b"Hello".to_tendril();
2195        t.extend(None::<&[u8]>);
2196        assert_eq!(b"Hello", &*t);
2197        t.extend(
2198            [b", ".as_ref(), b"world".as_ref(), b"!".as_ref()]
2199                .iter()
2200                .copied(),
2201        );
2202        assert_eq!(b"Hello, world!", &*t);
2203        assert_eq!(
2204            b"Hello, world!",
2205            &*[
2206                b"Hello".as_ref(),
2207                b", ".as_ref(),
2208                b"world".as_ref(),
2209                b"!".as_ref()
2210            ]
2211            .iter()
2212            .copied()
2213            .collect::<ByteTendril>()
2214        );
2215
2216        let string = "the quick brown fox jumps over the lazy dog";
2217        let string_expected = string.to_tendril();
2218        let bytes = string.as_bytes();
2219        let bytes_expected = bytes.to_tendril();
2220
2221        // char
2222        assert_eq!(string_expected, string.chars().collect::<Tendril<_>>());
2223        let mut tendril = StrTendril::new();
2224        tendril.extend(string.chars());
2225        assert_eq!(string_expected, tendril);
2226
2227        // &u8
2228        assert_eq!(bytes_expected, bytes.iter().collect::<Tendril<_>>());
2229        let mut tendril = ByteTendril::new();
2230        tendril.extend(bytes);
2231        assert_eq!(bytes_expected, tendril);
2232
2233        // u8
2234        assert_eq!(
2235            bytes_expected,
2236            bytes.iter().copied().collect::<Tendril<_>>()
2237        );
2238        let mut tendril = ByteTendril::new();
2239        tendril.extend(bytes.iter().copied());
2240        assert_eq!(bytes_expected, tendril);
2241    }
2242
2243    #[test]
2244    fn from_str() {
2245        use std::str::FromStr;
2246        let t: Tendril<_> = FromStr::from_str("foo bar baz").unwrap();
2247        assert_eq!("foo bar baz", &*t);
2248    }
2249
2250    #[test]
2251    fn from_char() {
2252        assert_eq!("o", &*StrTendril::from_char('o'));
2253        assert_eq!("ő", &*StrTendril::from_char('ő'));
2254        assert_eq!("\u{a66e}", &*StrTendril::from_char('\u{a66e}'));
2255        assert_eq!("\u{1f4a9}", &*StrTendril::from_char('\u{1f4a9}'));
2256    }
2257
2258    #[test]
2259    #[cfg_attr(miri, ignore)] // slow
2260    fn read() {
2261        fn check(x: &[u8]) {
2262            use std::io::Cursor;
2263            let mut t = ByteTendril::new();
2264            assert_eq!(x.len(), Cursor::new(x).read_to_tendril(&mut t).unwrap());
2265            assert_eq!(x, &*t);
2266        }
2267
2268        check(b"");
2269        check(b"abcd");
2270
2271        let long: Vec<u8> = iter::repeat(b'x').take(1_000_000).collect();
2272        check(&long);
2273    }
2274
2275    #[test]
2276    fn hash_map_key() {
2277        use std::collections::HashMap;
2278
2279        // As noted with Borrow, indexing on HashMap<StrTendril, _> is byte-based because of
2280        // https://github.com/rust-lang/rust/issues/27108.
2281        let mut map = HashMap::new();
2282        map.insert("foo".to_tendril(), 1);
2283        assert_eq!(map.get(b"foo".as_ref()), Some(&1));
2284        assert_eq!(map.get(b"bar".as_ref()), None);
2285
2286        let mut map = HashMap::new();
2287        map.insert(b"foo".to_tendril(), 1);
2288        assert_eq!(map.get(b"foo".as_ref()), Some(&1));
2289        assert_eq!(map.get(b"bar".as_ref()), None);
2290    }
2291
2292    #[test]
2293    fn atomic() {
2294        assert_send::<Tendril<fmt::UTF8, Atomic>>();
2295        let s: Tendril<fmt::UTF8, Atomic> = Tendril::from_slice("this is a string");
2296        assert!(!s.is_shared());
2297        let mut t = s.clone();
2298        assert!(s.is_shared());
2299        let sp = s.as_ptr() as usize;
2300        thread::spawn(move || {
2301            assert!(t.is_shared());
2302            t.push_slice(" extended");
2303            assert_eq!("this is a string extended", &*t);
2304            assert!(t.as_ptr() as usize != sp);
2305            assert!(!t.is_shared());
2306        })
2307        .join()
2308        .unwrap();
2309        assert!(s.is_shared());
2310        assert_eq!("this is a string", &*s);
2311    }
2312
2313    #[test]
2314    fn send() {
2315        assert_send::<SendTendril<fmt::UTF8>>();
2316        let s = "this is a string".to_tendril();
2317        let t = s.clone();
2318        let s2 = s.into_send();
2319        thread::spawn(move || {
2320            let s = StrTendril::from(s2);
2321            assert!(!s.is_shared());
2322            assert_eq!("this is a string", &*s);
2323        })
2324        .join()
2325        .unwrap();
2326        assert_eq!("this is a string", &*t);
2327    }
2328
2329    /// https://github.com/servo/tendril/issues/58
2330    #[test]
2331    fn issue_58() {
2332        let data = "<p><i>Hello!</p>, World!</i>";
2333        let s: Tendril<fmt::UTF8, NonAtomic> = data.into();
2334        assert_eq!(&*s, data);
2335        let s: Tendril<fmt::UTF8, Atomic> = s.into_send().into();
2336        assert_eq!(&*s, data);
2337    }
2338
2339    #[test]
2340    fn inline_send() {
2341        let s = "x".to_tendril();
2342        let t = s.clone();
2343        let s2 = s.into_send();
2344        thread::spawn(move || {
2345            let s = StrTendril::from(s2);
2346            assert!(!s.is_shared());
2347            assert_eq!("x", &*s);
2348        })
2349        .join()
2350        .unwrap();
2351        assert_eq!("x", &*t);
2352    }
2353}