Coverage Report

Created: 2025-11-28 06:44

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