Coverage Report

Created: 2026-03-31 06:51

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