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