Skip to main content

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