Coverage Report

Created: 2026-02-14 06:22

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
140M
fn inline_tag(len: u32) -> NonZeroUsize {
34
140M
    debug_assert!(len <= MAX_INLINE_LEN as u32);
35
140M
    unsafe { NonZeroUsize::new_unchecked(if len == 0 { EMPTY_TAG } else { len as usize }) }
36
140M
}
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
2.35M
    fn new() -> Self {
76
2.35M
        NonAtomic(Cell::new(1))
77
2.35M
    }
<tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::new
Line
Count
Source
75
53.4k
    fn new() -> Self {
76
53.4k
        NonAtomic(Cell::new(1))
77
53.4k
    }
<tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::new
Line
Count
Source
75
2.30M
    fn new() -> Self {
76
2.30M
        NonAtomic(Cell::new(1))
77
2.30M
    }
Unexecuted instantiation: <tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::new
78
79
    #[inline]
80
2.34M
    fn increment(&self) -> usize {
81
2.34M
        let value = self.0.get();
82
2.34M
        self.0.set(value.checked_add(1).expect(OFLOW));
83
2.34M
        value
84
2.34M
    }
<tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::increment
Line
Count
Source
80
1.38M
    fn increment(&self) -> usize {
81
1.38M
        let value = self.0.get();
82
1.38M
        self.0.set(value.checked_add(1).expect(OFLOW));
83
1.38M
        value
84
1.38M
    }
<tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::increment
Line
Count
Source
80
964k
    fn increment(&self) -> usize {
81
964k
        let value = self.0.get();
82
964k
        self.0.set(value.checked_add(1).expect(OFLOW));
83
964k
        value
84
964k
    }
Unexecuted instantiation: <tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::increment
85
86
    #[inline]
87
3.11M
    fn decrement(&self) -> usize {
88
3.11M
        let value = self.0.get();
89
3.11M
        self.0.set(value - 1);
90
3.11M
        value
91
3.11M
    }
<tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::decrement
Line
Count
Source
87
17.5k
    fn decrement(&self) -> usize {
88
17.5k
        let value = self.0.get();
89
17.5k
        self.0.set(value - 1);
90
17.5k
        value
91
17.5k
    }
<tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::decrement
Line
Count
Source
87
3.09M
    fn decrement(&self) -> usize {
88
3.09M
        let value = self.0.get();
89
3.09M
        self.0.set(value - 1);
90
3.09M
        value
91
3.09M
    }
Unexecuted instantiation: <tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::decrement
92
93
    #[inline]
94
768k
    fn fence_acquire() {}
<tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::fence_acquire
Line
Count
Source
94
15.9k
    fn fence_acquire() {}
<tendril::tendril::NonAtomic as tendril::tendril::Atomicity>::fence_acquire
Line
Count
Source
94
752k
    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
2.35M
    unsafe fn new() -> Header<A> {
140
2.35M
        Header {
141
2.35M
            refcount: A::new(),
142
2.35M
            cap: 0,
143
2.35M
        }
144
2.35M
    }
<tendril::tendril::Header<tendril::tendril::NonAtomic>>::new
Line
Count
Source
139
53.4k
    unsafe fn new() -> Header<A> {
140
53.4k
        Header {
141
53.4k
            refcount: A::new(),
142
53.4k
            cap: 0,
143
53.4k
        }
144
53.4k
    }
<tendril::tendril::Header<tendril::tendril::NonAtomic>>::new
Line
Count
Source
139
2.30M
    unsafe fn new() -> Header<A> {
140
2.30M
        Header {
141
2.30M
            refcount: A::new(),
142
2.30M
            cap: 0,
143
2.30M
        }
144
2.30M
    }
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
2.44M
    fn clone(&self) -> Tendril<F, A> {
227
        unsafe {
228
2.44M
            if self.ptr.get().get() > MAX_INLINE_TAG {
229
71.0k
                self.make_buf_shared();
230
71.0k
                self.incref();
231
2.37M
            }
232
233
2.44M
            ptr::read(self)
234
        }
235
2.44M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8> as core::clone::Clone>::clone
Line
Count
Source
226
2.44M
    fn clone(&self) -> Tendril<F, A> {
227
        unsafe {
228
2.44M
            if self.ptr.get().get() > MAX_INLINE_TAG {
229
71.0k
                self.make_buf_shared();
230
71.0k
                self.incref();
231
2.37M
            }
232
233
2.44M
            ptr::read(self)
234
        }
235
2.44M
    }
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
147M
    fn drop(&mut self) {
245
        unsafe {
246
147M
            let p = self.ptr.get().get();
247
147M
            if p <= MAX_INLINE_TAG {
248
142M
                return;
249
4.70M
            }
250
251
4.70M
            let (buf, shared, _) = self.assume_buf();
252
4.70M
            if shared {
253
3.11M
                let header = self.header();
254
3.11M
                if (*header).refcount.decrement() == 1 {
255
768k
                    A::fence_acquire();
256
768k
                    buf.destroy();
257
2.34M
                }
258
1.58M
            } else {
259
1.58M
                buf.destroy();
260
1.58M
            }
261
        }
262
147M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes> as core::ops::drop::Drop>::drop
Line
Count
Source
244
158k
    fn drop(&mut self) {
245
        unsafe {
246
158k
            let p = self.ptr.get().get();
247
158k
            if p <= MAX_INLINE_TAG {
248
125k
                return;
249
33.7k
            }
250
251
33.7k
            let (buf, shared, _) = self.assume_buf();
252
33.7k
            if shared {
253
17.5k
                let header = self.header();
254
17.5k
                if (*header).refcount.decrement() == 1 {
255
15.9k
                    A::fence_acquire();
256
15.9k
                    buf.destroy();
257
15.9k
                }
258
16.2k
            } else {
259
16.2k
                buf.destroy();
260
16.2k
            }
261
        }
262
158k
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8> as core::ops::drop::Drop>::drop
Line
Count
Source
244
147M
    fn drop(&mut self) {
245
        unsafe {
246
147M
            let p = self.ptr.get().get();
247
147M
            if p <= MAX_INLINE_TAG {
248
142M
                return;
249
4.66M
            }
250
251
4.66M
            let (buf, shared, _) = self.assume_buf();
252
4.66M
            if shared {
253
3.09M
                let header = self.header();
254
3.09M
                if (*header).refcount.decrement() == 1 {
255
752k
                    A::fence_acquire();
256
752k
                    buf.destroy();
257
2.34M
                }
258
1.57M
            } else {
259
1.57M
                buf.destroy();
260
1.57M
            }
261
        }
262
147M
    }
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
297M
    fn deref(&self) -> &F::Slice {
428
297M
        unsafe { F::Slice::from_bytes(self.as_byte_slice()) }
429
297M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes> as core::ops::deref::Deref>::deref
Line
Count
Source
427
79.4M
    fn deref(&self) -> &F::Slice {
428
79.4M
        unsafe { F::Slice::from_bytes(self.as_byte_slice()) }
429
79.4M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8> as core::ops::deref::Deref>::deref
Line
Count
Source
427
218M
    fn deref(&self) -> &F::Slice {
428
218M
        unsafe { F::Slice::from_bytes(self.as_byte_slice()) }
429
218M
    }
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
53.4k
    fn deref_mut(&mut self) -> &mut F::Slice {
439
53.4k
        unsafe { F::Slice::from_mut_bytes(self.as_mut_byte_slice()) }
440
53.4k
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes> as core::ops::deref::DerefMut>::deref_mut
Line
Count
Source
438
53.4k
    fn deref_mut(&mut self) -> &mut F::Slice {
439
53.4k
        unsafe { F::Slice::from_mut_bytes(self.as_mut_byte_slice()) }
440
53.4k
    }
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
4.73M
    fn default() -> Tendril<F, A> {
520
4.73M
        Tendril::new()
521
4.73M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8> as core::default::Default>::default
Line
Count
Source
519
4.73M
    fn default() -> Tendril<F, A> {
520
4.73M
        Tendril::new()
521
4.73M
    }
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.9M
    pub fn new() -> Tendril<F, A> {
563
31.9M
        unsafe { Tendril::inline(&[]) }
564
31.9M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::new
Line
Count
Source
562
29.1M
    pub fn new() -> Tendril<F, A> {
563
29.1M
        unsafe { Tendril::inline(&[]) }
564
29.1M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::new
Line
Count
Source
562
53.4k
    pub fn new() -> Tendril<F, A> {
563
53.4k
        unsafe { Tendril::inline(&[]) }
564
53.4k
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::new
Line
Count
Source
562
2.82M
    pub fn new() -> Tendril<F, A> {
563
2.82M
        unsafe { Tendril::inline(&[]) }
564
2.82M
    }
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
981M
    pub fn len32(&self) -> u32 {
608
981M
        match self.ptr.get().get() {
609
23.7M
            EMPTY_TAG => 0,
610
957M
            n if n <= MAX_INLINE_LEN => n as u32,
611
866M
            _ => unsafe { self.raw_len() },
612
        }
613
981M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::len32
Line
Count
Source
607
20.7M
    pub fn len32(&self) -> u32 {
608
20.7M
        match self.ptr.get().get() {
609
15.2k
            EMPTY_TAG => 0,
610
20.7M
            n if n <= MAX_INLINE_LEN => n as u32,
611
10.4M
            _ => unsafe { self.raw_len() },
612
        }
613
20.7M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::len32
Line
Count
Source
607
302M
    pub fn len32(&self) -> u32 {
608
302M
        match self.ptr.get().get() {
609
53.4k
            EMPTY_TAG => 0,
610
302M
            n if n <= MAX_INLINE_LEN => n as u32,
611
302M
            _ => unsafe { self.raw_len() },
612
        }
613
302M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::len32
Line
Count
Source
607
75.3M
    pub fn len32(&self) -> u32 {
608
75.3M
        match self.ptr.get().get() {
609
8.51M
            EMPTY_TAG => 0,
610
66.8M
            n if n <= MAX_INLINE_LEN => n as u32,
611
46.3M
            _ => unsafe { self.raw_len() },
612
        }
613
75.3M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::len32
Line
Count
Source
607
583M
    pub fn len32(&self) -> u32 {
608
583M
        match self.ptr.get().get() {
609
15.1M
            EMPTY_TAG => 0,
610
568M
            n if n <= MAX_INLINE_LEN => n as u32,
611
507M
            _ => unsafe { self.raw_len() },
612
        }
613
583M
    }
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
23.8M
    pub fn clear(&mut self) {
634
23.8M
        if self.ptr.get().get() <= MAX_INLINE_TAG {
635
23.7M
            self.ptr
636
23.7M
                .set(unsafe { NonZeroUsize::new_unchecked(EMPTY_TAG) });
637
23.7M
        } else {
638
105k
            let (_, shared, _) = unsafe { self.assume_buf() };
639
105k
            if shared {
640
0
                // No need to keep a reference alive for a 0-size slice.
641
0
                *self = Tendril::new();
642
105k
            } else {
643
105k
                unsafe { self.set_len(0) };
644
105k
            }
645
        }
646
23.8M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::clear
Line
Count
Source
633
23.8M
    pub fn clear(&mut self) {
634
23.8M
        if self.ptr.get().get() <= MAX_INLINE_TAG {
635
23.7M
            self.ptr
636
23.7M
                .set(unsafe { NonZeroUsize::new_unchecked(EMPTY_TAG) });
637
23.7M
        } else {
638
105k
            let (_, shared, _) = unsafe { self.assume_buf() };
639
105k
            if shared {
640
0
                // No need to keep a reference alive for a 0-size slice.
641
0
                *self = Tendril::new();
642
105k
            } else {
643
105k
                unsafe { self.set_len(0) };
644
105k
            }
645
        }
646
23.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
17.3M
    pub fn as_bytes(&self) -> &Tendril<fmt::Bytes, A> {
660
17.3M
        unsafe { mem::transmute(self) }
661
17.3M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::as_bytes
Line
Count
Source
659
17.3M
    pub fn as_bytes(&self) -> &Tendril<fmt::Bytes, A> {
660
17.3M
        unsafe { mem::transmute(self) }
661
17.3M
    }
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
152k
                let (self_buf, self_shared, _) = self.assume_buf();
778
152k
                let (other_buf, other_shared, _) = other.assume_buf();
779
780
152k
                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
152k
                }
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
152k
                let (self_buf, self_shared, _) = self.assume_buf();
778
152k
                let (other_buf, other_shared, _) = other.assume_buf();
779
780
152k
                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
152k
                }
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
9.40M
    pub fn try_subtendril(
804
9.40M
        &self,
805
9.40M
        offset: u32,
806
9.40M
        length: u32,
807
9.40M
    ) -> Result<Tendril<F, A>, SubtendrilError> {
808
9.40M
        let self_len = self.len32();
809
9.40M
        if offset > self_len || length > (self_len - offset) {
810
0
            return Err(SubtendrilError::OutOfBounds);
811
9.40M
        }
812
813
        unsafe {
814
9.40M
            let byte_slice = unsafe_slice(self.as_byte_slice(), offset as usize, length as usize);
815
9.40M
            if !F::validate_subseq(byte_slice) {
816
0
                return Err(SubtendrilError::ValidationFailed);
817
9.40M
            }
818
819
9.40M
            Ok(self.unsafe_subtendril(offset, length))
820
        }
821
9.40M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::try_subtendril
Line
Count
Source
803
4.76M
    pub fn try_subtendril(
804
4.76M
        &self,
805
4.76M
        offset: u32,
806
4.76M
        length: u32,
807
4.76M
    ) -> Result<Tendril<F, A>, SubtendrilError> {
808
4.76M
        let self_len = self.len32();
809
4.76M
        if offset > self_len || length > (self_len - offset) {
810
0
            return Err(SubtendrilError::OutOfBounds);
811
4.76M
        }
812
813
        unsafe {
814
4.76M
            let byte_slice = unsafe_slice(self.as_byte_slice(), offset as usize, length as usize);
815
4.76M
            if !F::validate_subseq(byte_slice) {
816
0
                return Err(SubtendrilError::ValidationFailed);
817
4.76M
            }
818
819
4.76M
            Ok(self.unsafe_subtendril(offset, length))
820
        }
821
4.76M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::try_subtendril
Line
Count
Source
803
4.63M
    pub fn try_subtendril(
804
4.63M
        &self,
805
4.63M
        offset: u32,
806
4.63M
        length: u32,
807
4.63M
    ) -> Result<Tendril<F, A>, SubtendrilError> {
808
4.63M
        let self_len = self.len32();
809
4.63M
        if offset > self_len || length > (self_len - offset) {
810
0
            return Err(SubtendrilError::OutOfBounds);
811
4.63M
        }
812
813
        unsafe {
814
4.63M
            let byte_slice = unsafe_slice(self.as_byte_slice(), offset as usize, length as usize);
815
4.63M
            if !F::validate_subseq(byte_slice) {
816
0
                return Err(SubtendrilError::ValidationFailed);
817
4.63M
            }
818
819
4.63M
            Ok(self.unsafe_subtendril(offset, length))
820
        }
821
4.63M
    }
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
9.40M
    pub fn subtendril(&self, offset: u32, length: u32) -> Tendril<F, A> {
828
9.40M
        self.try_subtendril(offset, length).unwrap()
829
9.40M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::subtendril
Line
Count
Source
827
4.76M
    pub fn subtendril(&self, offset: u32, length: u32) -> Tendril<F, A> {
828
4.76M
        self.try_subtendril(offset, length).unwrap()
829
4.76M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::subtendril
Line
Count
Source
827
4.63M
    pub fn subtendril(&self, offset: u32, length: u32) -> Tendril<F, A> {
828
4.63M
        self.try_subtendril(offset, length).unwrap()
829
4.63M
    }
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
31.2M
    pub fn try_pop_front(&mut self, n: u32) -> Result<(), SubtendrilError> {
837
31.2M
        if n == 0 {
838
2.95k
            return Ok(());
839
31.2M
        }
840
31.2M
        let old_len = self.len32();
841
31.2M
        if n > old_len {
842
0
            return Err(SubtendrilError::OutOfBounds);
843
31.2M
        }
844
31.2M
        let new_len = old_len - n;
845
846
        unsafe {
847
31.2M
            if !F::validate_suffix(unsafe_slice(
848
31.2M
                self.as_byte_slice(),
849
31.2M
                n as usize,
850
31.2M
                new_len as usize,
851
31.2M
            )) {
852
0
                return Err(SubtendrilError::ValidationFailed);
853
31.2M
            }
854
855
31.2M
            self.unsafe_pop_front(n);
856
31.2M
            Ok(())
857
        }
858
31.2M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::try_pop_front
Line
Count
Source
836
281k
    pub fn try_pop_front(&mut self, n: u32) -> Result<(), SubtendrilError> {
837
281k
        if n == 0 {
838
0
            return Ok(());
839
281k
        }
840
281k
        let old_len = self.len32();
841
281k
        if n > old_len {
842
0
            return Err(SubtendrilError::OutOfBounds);
843
281k
        }
844
281k
        let new_len = old_len - n;
845
846
        unsafe {
847
281k
            if !F::validate_suffix(unsafe_slice(
848
281k
                self.as_byte_slice(),
849
281k
                n as usize,
850
281k
                new_len as usize,
851
281k
            )) {
852
0
                return Err(SubtendrilError::ValidationFailed);
853
281k
            }
854
855
281k
            self.unsafe_pop_front(n);
856
281k
            Ok(())
857
        }
858
281k
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::try_pop_front
Line
Count
Source
836
30.9M
    pub fn try_pop_front(&mut self, n: u32) -> Result<(), SubtendrilError> {
837
30.9M
        if n == 0 {
838
2.95k
            return Ok(());
839
30.9M
        }
840
30.9M
        let old_len = self.len32();
841
30.9M
        if n > old_len {
842
0
            return Err(SubtendrilError::OutOfBounds);
843
30.9M
        }
844
30.9M
        let new_len = old_len - n;
845
846
        unsafe {
847
30.9M
            if !F::validate_suffix(unsafe_slice(
848
30.9M
                self.as_byte_slice(),
849
30.9M
                n as usize,
850
30.9M
                new_len as usize,
851
30.9M
            )) {
852
0
                return Err(SubtendrilError::ValidationFailed);
853
30.9M
            }
854
855
30.9M
            self.unsafe_pop_front(n);
856
30.9M
            Ok(())
857
        }
858
30.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
31.2M
    pub fn pop_front(&mut self, n: u32) {
866
31.2M
        self.try_pop_front(n).unwrap()
867
31.2M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::pop_front
Line
Count
Source
865
281k
    pub fn pop_front(&mut self, n: u32) {
866
281k
        self.try_pop_front(n).unwrap()
867
281k
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::pop_front
Line
Count
Source
865
30.9M
    pub fn pop_front(&mut self, n: u32) {
866
30.9M
        self.try_pop_front(n).unwrap()
867
30.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
40.5k
    pub fn try_pop_back(&mut self, n: u32) -> Result<(), SubtendrilError> {
875
40.5k
        if n == 0 {
876
27.6k
            return Ok(());
877
12.9k
        }
878
12.9k
        let old_len = self.len32();
879
12.9k
        if n > old_len {
880
0
            return Err(SubtendrilError::OutOfBounds);
881
12.9k
        }
882
12.9k
        let new_len = old_len - n;
883
884
        unsafe {
885
12.9k
            if !F::validate_prefix(unsafe_slice(self.as_byte_slice(), 0, new_len as usize)) {
886
0
                return Err(SubtendrilError::ValidationFailed);
887
12.9k
            }
888
889
12.9k
            self.unsafe_pop_back(n);
890
12.9k
            Ok(())
891
        }
892
40.5k
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::try_pop_back
Line
Count
Source
874
40.5k
    pub fn try_pop_back(&mut self, n: u32) -> Result<(), SubtendrilError> {
875
40.5k
        if n == 0 {
876
27.6k
            return Ok(());
877
12.9k
        }
878
12.9k
        let old_len = self.len32();
879
12.9k
        if n > old_len {
880
0
            return Err(SubtendrilError::OutOfBounds);
881
12.9k
        }
882
12.9k
        let new_len = old_len - n;
883
884
        unsafe {
885
12.9k
            if !F::validate_prefix(unsafe_slice(self.as_byte_slice(), 0, new_len as usize)) {
886
0
                return Err(SubtendrilError::ValidationFailed);
887
12.9k
            }
888
889
12.9k
            self.unsafe_pop_back(n);
890
12.9k
            Ok(())
891
        }
892
40.5k
    }
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
40.5k
    pub fn pop_back(&mut self, n: u32) {
900
40.5k
        self.try_pop_back(n).unwrap()
901
40.5k
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::pop_back
Line
Count
Source
899
40.5k
    pub fn pop_back(&mut self, n: u32) {
900
40.5k
        self.try_pop_back(n).unwrap()
901
40.5k
    }
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
4.79M
    pub unsafe fn reinterpret_without_validating<Other>(self) -> Tendril<Other, A>
915
4.79M
    where
916
4.79M
        Other: fmt::Format,
917
    {
918
4.79M
        mem::transmute(self)
919
4.79M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::reinterpret_without_validating::<tendril::fmt::UTF8>
Line
Count
Source
914
4.79M
    pub unsafe fn reinterpret_without_validating<Other>(self) -> Tendril<Other, A>
915
4.79M
    where
916
4.79M
        Other: fmt::Format,
917
    {
918
4.79M
        mem::transmute(self)
919
4.79M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::reinterpret_without_validating::<_>
920
921
    /// Build a `Tendril` by copying a byte slice, without validating.
922
    #[inline]
923
31.2M
    pub unsafe fn from_byte_slice_without_validating(x: &[u8]) -> Tendril<F, A> {
924
31.2M
        assert!(x.len() <= buf32::MAX_LEN);
925
31.2M
        if x.len() <= MAX_INLINE_LEN {
926
31.0M
            Tendril::inline(x)
927
        } else {
928
198k
            Tendril::owned_copy(x)
929
        }
930
31.2M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::from_byte_slice_without_validating
Line
Count
Source
923
31.2M
    pub unsafe fn from_byte_slice_without_validating(x: &[u8]) -> Tendril<F, A> {
924
31.2M
        assert!(x.len() <= buf32::MAX_LEN);
925
31.2M
        if x.len() <= MAX_INLINE_LEN {
926
31.0M
            Tendril::inline(x)
927
        } else {
928
198k
            Tendril::owned_copy(x)
929
        }
930
31.2M
    }
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
70.7M
    pub unsafe fn push_bytes_without_validating(&mut self, buf: &[u8]) {
935
70.7M
        assert!(buf.len() <= buf32::MAX_LEN);
936
937
        let Fixup {
938
70.7M
            drop_left,
939
70.7M
            drop_right,
940
70.7M
            insert_len,
941
70.7M
            insert_bytes,
942
70.7M
        } = F::fixup(self.as_byte_slice(), buf);
943
944
        // FIXME: think more about overflow
945
70.7M
        let adj_len = self.len32() + insert_len - drop_left;
946
947
70.7M
        let new_len = adj_len.checked_add(buf.len() as u32).expect(OFLOW) - drop_right;
948
949
70.7M
        let drop_left = drop_left as usize;
950
70.7M
        let drop_right = drop_right as usize;
951
952
70.7M
        if new_len <= MAX_INLINE_LEN as u32 {
953
24.1M
            let mut tmp = [0_u8; MAX_INLINE_LEN];
954
24.1M
            {
955
24.1M
                let old = self.as_byte_slice();
956
24.1M
                let mut dest = tmp.as_mut_ptr();
957
24.1M
                copy_and_advance(&mut dest, unsafe_slice(old, 0, old.len() - drop_left));
958
24.1M
                copy_and_advance(
959
24.1M
                    &mut dest,
960
24.1M
                    unsafe_slice(&insert_bytes, 0, insert_len as usize),
961
24.1M
                );
962
24.1M
                copy_and_advance(
963
24.1M
                    &mut dest,
964
24.1M
                    unsafe_slice(buf, drop_right, buf.len() - drop_right),
965
24.1M
                );
966
24.1M
            }
967
24.1M
            *self = Tendril::inline(&tmp[..new_len as usize]);
968
46.5M
        } else {
969
46.5M
            self.make_owned_with_capacity(new_len);
970
46.5M
            let (owned, _, _) = self.assume_buf();
971
46.5M
            let mut dest = owned.data_ptr().add(owned.len as usize - drop_left);
972
46.5M
            copy_and_advance(
973
46.5M
                &mut dest,
974
46.5M
                unsafe_slice(&insert_bytes, 0, insert_len as usize),
975
46.5M
            );
976
46.5M
            copy_and_advance(
977
46.5M
                &mut dest,
978
46.5M
                unsafe_slice(buf, drop_right, buf.len() - drop_right),
979
46.5M
            );
980
46.5M
            self.set_len(new_len);
981
46.5M
        }
982
70.7M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::push_bytes_without_validating
Line
Count
Source
934
70.7M
    pub unsafe fn push_bytes_without_validating(&mut self, buf: &[u8]) {
935
70.7M
        assert!(buf.len() <= buf32::MAX_LEN);
936
937
        let Fixup {
938
70.7M
            drop_left,
939
70.7M
            drop_right,
940
70.7M
            insert_len,
941
70.7M
            insert_bytes,
942
70.7M
        } = F::fixup(self.as_byte_slice(), buf);
943
944
        // FIXME: think more about overflow
945
70.7M
        let adj_len = self.len32() + insert_len - drop_left;
946
947
70.7M
        let new_len = adj_len.checked_add(buf.len() as u32).expect(OFLOW) - drop_right;
948
949
70.7M
        let drop_left = drop_left as usize;
950
70.7M
        let drop_right = drop_right as usize;
951
952
70.7M
        if new_len <= MAX_INLINE_LEN as u32 {
953
24.1M
            let mut tmp = [0_u8; MAX_INLINE_LEN];
954
24.1M
            {
955
24.1M
                let old = self.as_byte_slice();
956
24.1M
                let mut dest = tmp.as_mut_ptr();
957
24.1M
                copy_and_advance(&mut dest, unsafe_slice(old, 0, old.len() - drop_left));
958
24.1M
                copy_and_advance(
959
24.1M
                    &mut dest,
960
24.1M
                    unsafe_slice(&insert_bytes, 0, insert_len as usize),
961
24.1M
                );
962
24.1M
                copy_and_advance(
963
24.1M
                    &mut dest,
964
24.1M
                    unsafe_slice(buf, drop_right, buf.len() - drop_right),
965
24.1M
                );
966
24.1M
            }
967
24.1M
            *self = Tendril::inline(&tmp[..new_len as usize]);
968
46.5M
        } else {
969
46.5M
            self.make_owned_with_capacity(new_len);
970
46.5M
            let (owned, _, _) = self.assume_buf();
971
46.5M
            let mut dest = owned.data_ptr().add(owned.len as usize - drop_left);
972
46.5M
            copy_and_advance(
973
46.5M
                &mut dest,
974
46.5M
                unsafe_slice(&insert_bytes, 0, insert_len as usize),
975
46.5M
            );
976
46.5M
            copy_and_advance(
977
46.5M
                &mut dest,
978
46.5M
                unsafe_slice(buf, drop_right, buf.len() - drop_right),
979
46.5M
            );
980
46.5M
            self.set_len(new_len);
981
46.5M
        }
982
70.7M
    }
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
27.9M
    pub unsafe fn unsafe_subtendril(&self, offset: u32, length: u32) -> Tendril<F, A> {
989
27.9M
        if length <= MAX_INLINE_LEN as u32 {
990
25.6M
            Tendril::inline(unsafe_slice(
991
25.6M
                self.as_byte_slice(),
992
25.6M
                offset as usize,
993
25.6M
                length as usize,
994
25.6M
            ))
995
        } else {
996
2.27M
            self.make_buf_shared();
997
2.27M
            self.incref();
998
2.27M
            let (buf, _, _) = self.assume_buf();
999
2.27M
            Tendril::shared(buf, self.aux() + offset, length)
1000
        }
1001
27.9M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::unsafe_subtendril
Line
Count
Source
988
4.76M
    pub unsafe fn unsafe_subtendril(&self, offset: u32, length: u32) -> Tendril<F, A> {
989
4.76M
        if length <= MAX_INLINE_LEN as u32 {
990
3.38M
            Tendril::inline(unsafe_slice(
991
3.38M
                self.as_byte_slice(),
992
3.38M
                offset as usize,
993
3.38M
                length as usize,
994
3.38M
            ))
995
        } else {
996
1.38M
            self.make_buf_shared();
997
1.38M
            self.incref();
998
1.38M
            let (buf, _, _) = self.assume_buf();
999
1.38M
            Tendril::shared(buf, self.aux() + offset, length)
1000
        }
1001
4.76M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::unsafe_subtendril
Line
Count
Source
988
23.1M
    pub unsafe fn unsafe_subtendril(&self, offset: u32, length: u32) -> Tendril<F, A> {
989
23.1M
        if length <= MAX_INLINE_LEN as u32 {
990
22.2M
            Tendril::inline(unsafe_slice(
991
22.2M
                self.as_byte_slice(),
992
22.2M
                offset as usize,
993
22.2M
                length as usize,
994
22.2M
            ))
995
        } else {
996
893k
            self.make_buf_shared();
997
893k
            self.incref();
998
893k
            let (buf, _, _) = self.assume_buf();
999
893k
            Tendril::shared(buf, self.aux() + offset, length)
1000
        }
1001
23.1M
    }
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
108M
    pub unsafe fn unsafe_pop_front(&mut self, n: u32) {
1008
108M
        let new_len = self.len32() - n;
1009
108M
        if new_len <= MAX_INLINE_LEN as u32 {
1010
27.3M
            *self = Tendril::inline(unsafe_slice(
1011
27.3M
                self.as_byte_slice(),
1012
27.3M
                n as usize,
1013
27.3M
                new_len as usize,
1014
27.3M
            ));
1015
81.4M
        } else {
1016
81.4M
            self.make_buf_shared();
1017
81.4M
            self.set_aux(self.aux() + n);
1018
81.4M
            let len = self.raw_len();
1019
81.4M
            self.set_len(len - n);
1020
81.4M
        }
1021
108M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::unsafe_pop_front
Line
Count
Source
1007
30.9M
    pub unsafe fn unsafe_pop_front(&mut self, n: u32) {
1008
30.9M
        let new_len = self.len32() - n;
1009
30.9M
        if new_len <= MAX_INLINE_LEN as u32 {
1010
78.1k
            *self = Tendril::inline(unsafe_slice(
1011
78.1k
                self.as_byte_slice(),
1012
78.1k
                n as usize,
1013
78.1k
                new_len as usize,
1014
78.1k
            ));
1015
30.9M
        } else {
1016
30.9M
            self.make_buf_shared();
1017
30.9M
            self.set_aux(self.aux() + n);
1018
30.9M
            let len = self.raw_len();
1019
30.9M
            self.set_len(len - n);
1020
30.9M
        }
1021
30.9M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::unsafe_pop_front
Line
Count
Source
1007
77.8M
    pub unsafe fn unsafe_pop_front(&mut self, n: u32) {
1008
77.8M
        let new_len = self.len32() - n;
1009
77.8M
        if new_len <= MAX_INLINE_LEN as u32 {
1010
27.3M
            *self = Tendril::inline(unsafe_slice(
1011
27.3M
                self.as_byte_slice(),
1012
27.3M
                n as usize,
1013
27.3M
                new_len as usize,
1014
27.3M
            ));
1015
50.5M
        } else {
1016
50.5M
            self.make_buf_shared();
1017
50.5M
            self.set_aux(self.aux() + n);
1018
50.5M
            let len = self.raw_len();
1019
50.5M
            self.set_len(len - n);
1020
50.5M
        }
1021
77.8M
    }
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.9k
    pub unsafe fn unsafe_pop_back(&mut self, n: u32) {
1028
12.9k
        let new_len = self.len32() - n;
1029
12.9k
        if new_len <= MAX_INLINE_LEN as u32 {
1030
3.30k
            *self = Tendril::inline(unsafe_slice(self.as_byte_slice(), 0, new_len as usize));
1031
9.62k
        } else {
1032
9.62k
            self.make_buf_shared();
1033
9.62k
            let len = self.raw_len();
1034
9.62k
            self.set_len(len - n);
1035
9.62k
        }
1036
12.9k
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::unsafe_pop_back
Line
Count
Source
1027
12.9k
    pub unsafe fn unsafe_pop_back(&mut self, n: u32) {
1028
12.9k
        let new_len = self.len32() - n;
1029
12.9k
        if new_len <= MAX_INLINE_LEN as u32 {
1030
3.30k
            *self = Tendril::inline(unsafe_slice(self.as_byte_slice(), 0, new_len as usize));
1031
9.62k
        } else {
1032
9.62k
            self.make_buf_shared();
1033
9.62k
            let len = self.raw_len();
1034
9.62k
            self.set_len(len - n);
1035
9.62k
        }
1036
12.9k
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::unsafe_pop_back
1037
1038
    #[inline]
1039
2.34M
    unsafe fn incref(&self) {
1040
2.34M
        (*self.header()).refcount.increment();
1041
2.34M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::incref
Line
Count
Source
1039
1.38M
    unsafe fn incref(&self) {
1040
1.38M
        (*self.header()).refcount.increment();
1041
1.38M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::incref
Line
Count
Source
1039
964k
    unsafe fn incref(&self) {
1040
964k
        (*self.header()).refcount.increment();
1041
964k
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::incref
1042
1043
    #[inline]
1044
83.8M
    unsafe fn make_buf_shared(&self) {
1045
83.8M
        let p = self.ptr.get().get();
1046
83.8M
        if p & 1 == 0 {
1047
768k
            let header = p as *mut Header<A>;
1048
768k
            (*header).cap = self.aux();
1049
768k
1050
768k
            self.ptr.set(NonZeroUsize::new_unchecked(p | 1));
1051
768k
            self.set_aux(0);
1052
83.0M
        }
1053
83.8M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::make_buf_shared
Line
Count
Source
1044
32.2M
    unsafe fn make_buf_shared(&self) {
1045
32.2M
        let p = self.ptr.get().get();
1046
32.2M
        if p & 1 == 0 {
1047
30.1k
            let header = p as *mut Header<A>;
1048
30.1k
            (*header).cap = self.aux();
1049
30.1k
1050
30.1k
            self.ptr.set(NonZeroUsize::new_unchecked(p | 1));
1051
30.1k
            self.set_aux(0);
1052
32.2M
        }
1053
32.2M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::make_buf_shared
Line
Count
Source
1044
51.5M
    unsafe fn make_buf_shared(&self) {
1045
51.5M
        let p = self.ptr.get().get();
1046
51.5M
        if p & 1 == 0 {
1047
738k
            let header = p as *mut Header<A>;
1048
738k
            (*header).cap = self.aux();
1049
738k
1050
738k
            self.ptr.set(NonZeroUsize::new_unchecked(p | 1));
1051
738k
            self.set_aux(0);
1052
50.7M
        }
1053
51.5M
    }
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
46.6M
    fn make_owned(&mut self) {
1060
        unsafe {
1061
46.6M
            let ptr = self.ptr.get().get();
1062
46.6M
            if ptr <= MAX_INLINE_TAG || (ptr & 1) == 1 {
1063
2.15M
                *self = Tendril::owned_copy(self.as_byte_slice());
1064
44.4M
            }
1065
        }
1066
46.6M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::make_owned
Line
Count
Source
1059
106k
    fn make_owned(&mut self) {
1060
        unsafe {
1061
106k
            let ptr = self.ptr.get().get();
1062
106k
            if ptr <= MAX_INLINE_TAG || (ptr & 1) == 1 {
1063
53.4k
                *self = Tendril::owned_copy(self.as_byte_slice());
1064
53.4k
            }
1065
        }
1066
106k
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::make_owned
Line
Count
Source
1059
46.5M
    fn make_owned(&mut self) {
1060
        unsafe {
1061
46.5M
            let ptr = self.ptr.get().get();
1062
46.5M
            if ptr <= MAX_INLINE_TAG || (ptr & 1) == 1 {
1063
2.10M
                *self = Tendril::owned_copy(self.as_byte_slice());
1064
44.4M
            }
1065
        }
1066
46.5M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::make_owned
1067
1068
    #[inline]
1069
46.5M
    unsafe fn make_owned_with_capacity(&mut self, cap: u32) {
1070
46.5M
        self.make_owned();
1071
46.5M
        let mut buf = self.assume_buf().0;
1072
46.5M
        buf.grow(cap);
1073
46.5M
        self.ptr.set(NonZeroUsize::new_unchecked(buf.ptr as usize));
1074
46.5M
        self.set_aux(buf.cap);
1075
46.5M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::make_owned_with_capacity
Line
Count
Source
1069
53.4k
    unsafe fn make_owned_with_capacity(&mut self, cap: u32) {
1070
53.4k
        self.make_owned();
1071
53.4k
        let mut buf = self.assume_buf().0;
1072
53.4k
        buf.grow(cap);
1073
53.4k
        self.ptr.set(NonZeroUsize::new_unchecked(buf.ptr as usize));
1074
53.4k
        self.set_aux(buf.cap);
1075
53.4k
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::make_owned_with_capacity
Line
Count
Source
1069
46.5M
    unsafe fn make_owned_with_capacity(&mut self, cap: u32) {
1070
46.5M
        self.make_owned();
1071
46.5M
        let mut buf = self.assume_buf().0;
1072
46.5M
        buf.grow(cap);
1073
46.5M
        self.ptr.set(NonZeroUsize::new_unchecked(buf.ptr as usize));
1074
46.5M
        self.set_aux(buf.cap);
1075
46.5M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::make_owned_with_capacity
1076
1077
    #[inline(always)]
1078
400M
    unsafe fn header(&self) -> *mut Header<A> {
1079
400M
        (self.ptr.get().get() & !1) as *mut Header<A>
1080
400M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::header
Line
Count
Source
1078
119M
    unsafe fn header(&self) -> *mut Header<A> {
1079
119M
        (self.ptr.get().get() & !1) as *mut Header<A>
1080
119M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::header
Line
Count
Source
1078
280M
    unsafe fn header(&self) -> *mut Header<A> {
1079
280M
        (self.ptr.get().get() & !1) as *mut Header<A>
1080
280M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::header
1081
1082
    #[inline]
1083
394M
    unsafe fn assume_buf(&self) -> (Buf32<Header<A>>, bool, u32) {
1084
394M
        let ptr = self.ptr.get().get();
1085
394M
        let header = self.header();
1086
394M
        let shared = (ptr & 1) == 1;
1087
394M
        let (cap, offset) = match shared {
1088
243M
            true => ((*header).cap, self.aux()),
1089
151M
            false => (self.aux(), 0),
1090
        };
1091
1092
394M
        (
1093
394M
            Buf32 {
1094
394M
                ptr: header,
1095
394M
                len: offset + self.len32(),
1096
394M
                cap,
1097
394M
            },
1098
394M
            shared,
1099
394M
            offset,
1100
394M
        )
1101
394M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::assume_buf
Line
Count
Source
1083
118M
    unsafe fn assume_buf(&self) -> (Buf32<Header<A>>, bool, u32) {
1084
118M
        let ptr = self.ptr.get().get();
1085
118M
        let header = self.header();
1086
118M
        let shared = (ptr & 1) == 1;
1087
118M
        let (cap, offset) = match shared {
1088
118M
            true => ((*header).cap, self.aux()),
1089
234k
            false => (self.aux(), 0),
1090
        };
1091
1092
118M
        (
1093
118M
            Buf32 {
1094
118M
                ptr: header,
1095
118M
                len: offset + self.len32(),
1096
118M
                cap,
1097
118M
            },
1098
118M
            shared,
1099
118M
            offset,
1100
118M
        )
1101
118M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::assume_buf
Line
Count
Source
1083
276M
    unsafe fn assume_buf(&self) -> (Buf32<Header<A>>, bool, u32) {
1084
276M
        let ptr = self.ptr.get().get();
1085
276M
        let header = self.header();
1086
276M
        let shared = (ptr & 1) == 1;
1087
276M
        let (cap, offset) = match shared {
1088
125M
            true => ((*header).cap, self.aux()),
1089
150M
            false => (self.aux(), 0),
1090
        };
1091
1092
276M
        (
1093
276M
            Buf32 {
1094
276M
                ptr: header,
1095
276M
                len: offset + self.len32(),
1096
276M
                cap,
1097
276M
            },
1098
276M
            shared,
1099
276M
            offset,
1100
276M
        )
1101
276M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::assume_buf
1102
1103
    #[inline]
1104
140M
    unsafe fn inline(x: &[u8]) -> Tendril<F, A> {
1105
140M
        let len = x.len();
1106
140M
        let t = Tendril {
1107
140M
            ptr: Cell::new(inline_tag(len as u32)),
1108
140M
            buf: UnsafeCell::new(Buffer { inline: [0; 8] }),
1109
140M
            marker: PhantomData,
1110
140M
            refcount_marker: PhantomData,
1111
140M
        };
1112
140M
        ptr::copy_nonoverlapping(x.as_ptr(), (*t.buf.get()).inline.as_mut_ptr(), len);
1113
140M
        t
1114
140M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::inline
Line
Count
Source
1104
3.52M
    unsafe fn inline(x: &[u8]) -> Tendril<F, A> {
1105
3.52M
        let len = x.len();
1106
3.52M
        let t = Tendril {
1107
3.52M
            ptr: Cell::new(inline_tag(len as u32)),
1108
3.52M
            buf: UnsafeCell::new(Buffer { inline: [0; 8] }),
1109
3.52M
            marker: PhantomData,
1110
3.52M
            refcount_marker: PhantomData,
1111
3.52M
        };
1112
3.52M
        ptr::copy_nonoverlapping(x.as_ptr(), (*t.buf.get()).inline.as_mut_ptr(), len);
1113
3.52M
        t
1114
3.52M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::inline
Line
Count
Source
1104
136M
    unsafe fn inline(x: &[u8]) -> Tendril<F, A> {
1105
136M
        let len = x.len();
1106
136M
        let t = Tendril {
1107
136M
            ptr: Cell::new(inline_tag(len as u32)),
1108
136M
            buf: UnsafeCell::new(Buffer { inline: [0; 8] }),
1109
136M
            marker: PhantomData,
1110
136M
            refcount_marker: PhantomData,
1111
136M
        };
1112
136M
        ptr::copy_nonoverlapping(x.as_ptr(), (*t.buf.get()).inline.as_mut_ptr(), len);
1113
136M
        t
1114
136M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::inline
1115
1116
    #[inline]
1117
2.35M
    unsafe fn owned(x: Buf32<Header<A>>) -> Tendril<F, A> {
1118
2.35M
        Tendril {
1119
2.35M
            ptr: Cell::new(NonZeroUsize::new_unchecked(x.ptr as usize)),
1120
2.35M
            buf: UnsafeCell::new(Buffer {
1121
2.35M
                heap: Heap {
1122
2.35M
                    len: x.len,
1123
2.35M
                    aux: x.cap,
1124
2.35M
                },
1125
2.35M
            }),
1126
2.35M
            marker: PhantomData,
1127
2.35M
            refcount_marker: PhantomData,
1128
2.35M
        }
1129
2.35M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::owned
Line
Count
Source
1117
53.4k
    unsafe fn owned(x: Buf32<Header<A>>) -> Tendril<F, A> {
1118
53.4k
        Tendril {
1119
53.4k
            ptr: Cell::new(NonZeroUsize::new_unchecked(x.ptr as usize)),
1120
53.4k
            buf: UnsafeCell::new(Buffer {
1121
53.4k
                heap: Heap {
1122
53.4k
                    len: x.len,
1123
53.4k
                    aux: x.cap,
1124
53.4k
                },
1125
53.4k
            }),
1126
53.4k
            marker: PhantomData,
1127
53.4k
            refcount_marker: PhantomData,
1128
53.4k
        }
1129
53.4k
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::owned
Line
Count
Source
1117
2.30M
    unsafe fn owned(x: Buf32<Header<A>>) -> Tendril<F, A> {
1118
2.30M
        Tendril {
1119
2.30M
            ptr: Cell::new(NonZeroUsize::new_unchecked(x.ptr as usize)),
1120
2.30M
            buf: UnsafeCell::new(Buffer {
1121
2.30M
                heap: Heap {
1122
2.30M
                    len: x.len,
1123
2.30M
                    aux: x.cap,
1124
2.30M
                },
1125
2.30M
            }),
1126
2.30M
            marker: PhantomData,
1127
2.30M
            refcount_marker: PhantomData,
1128
2.30M
        }
1129
2.30M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::owned
1130
1131
    #[inline]
1132
2.35M
    unsafe fn owned_copy(x: &[u8]) -> Tendril<F, A> {
1133
2.35M
        let len32 = x.len() as u32;
1134
2.35M
        let mut b = Buf32::with_capacity(len32, Header::new());
1135
2.35M
        ptr::copy_nonoverlapping(x.as_ptr(), b.data_ptr(), x.len());
1136
2.35M
        b.len = len32;
1137
2.35M
        Tendril::owned(b)
1138
2.35M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::owned_copy
Line
Count
Source
1132
53.4k
    unsafe fn owned_copy(x: &[u8]) -> Tendril<F, A> {
1133
53.4k
        let len32 = x.len() as u32;
1134
53.4k
        let mut b = Buf32::with_capacity(len32, Header::new());
1135
53.4k
        ptr::copy_nonoverlapping(x.as_ptr(), b.data_ptr(), x.len());
1136
53.4k
        b.len = len32;
1137
53.4k
        Tendril::owned(b)
1138
53.4k
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::owned_copy
Line
Count
Source
1132
2.30M
    unsafe fn owned_copy(x: &[u8]) -> Tendril<F, A> {
1133
2.30M
        let len32 = x.len() as u32;
1134
2.30M
        let mut b = Buf32::with_capacity(len32, Header::new());
1135
2.30M
        ptr::copy_nonoverlapping(x.as_ptr(), b.data_ptr(), x.len());
1136
2.30M
        b.len = len32;
1137
2.30M
        Tendril::owned(b)
1138
2.30M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::owned_copy
1139
1140
    #[inline]
1141
2.27M
    unsafe fn shared(buf: Buf32<Header<A>>, off: u32, len: u32) -> Tendril<F, A> {
1142
2.27M
        Tendril {
1143
2.27M
            ptr: Cell::new(NonZeroUsize::new_unchecked((buf.ptr as usize) | 1)),
1144
2.27M
            buf: UnsafeCell::new(Buffer {
1145
2.27M
                heap: Heap { len, aux: off },
1146
2.27M
            }),
1147
2.27M
            marker: PhantomData,
1148
2.27M
            refcount_marker: PhantomData,
1149
2.27M
        }
1150
2.27M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::shared
Line
Count
Source
1141
1.38M
    unsafe fn shared(buf: Buf32<Header<A>>, off: u32, len: u32) -> Tendril<F, A> {
1142
1.38M
        Tendril {
1143
1.38M
            ptr: Cell::new(NonZeroUsize::new_unchecked((buf.ptr as usize) | 1)),
1144
1.38M
            buf: UnsafeCell::new(Buffer {
1145
1.38M
                heap: Heap { len, aux: off },
1146
1.38M
            }),
1147
1.38M
            marker: PhantomData,
1148
1.38M
            refcount_marker: PhantomData,
1149
1.38M
        }
1150
1.38M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::shared
Line
Count
Source
1141
893k
    unsafe fn shared(buf: Buf32<Header<A>>, off: u32, len: u32) -> Tendril<F, A> {
1142
893k
        Tendril {
1143
893k
            ptr: Cell::new(NonZeroUsize::new_unchecked((buf.ptr as usize) | 1)),
1144
893k
            buf: UnsafeCell::new(Buffer {
1145
893k
                heap: Heap { len, aux: off },
1146
893k
            }),
1147
893k
            marker: PhantomData,
1148
893k
            refcount_marker: PhantomData,
1149
893k
        }
1150
893k
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::shared
1151
1152
    #[inline]
1153
581M
    fn as_byte_slice(&self) -> &[u8] {
1154
        unsafe {
1155
581M
            match self.ptr.get().get() {
1156
61.8M
                EMPTY_TAG => &[],
1157
519M
                n if n <= MAX_INLINE_LEN => (*self.buf.get()).inline.get_unchecked(..n),
1158
                _ => {
1159
294M
                    let (buf, _, offset) = self.assume_buf();
1160
294M
                    copy_lifetime(
1161
294M
                        self,
1162
294M
                        unsafe_slice(buf.data(), offset as usize, self.len32() as usize),
1163
294M
                    )
1164
                },
1165
            }
1166
        }
1167
581M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::as_byte_slice
Line
Count
Source
1153
118M
    fn as_byte_slice(&self) -> &[u8] {
1154
        unsafe {
1155
118M
            match self.ptr.get().get() {
1156
59.6k
                EMPTY_TAG => &[],
1157
118M
                n if n <= MAX_INLINE_LEN => (*self.buf.get()).inline.get_unchecked(..n),
1158
                _ => {
1159
116M
                    let (buf, _, offset) = self.assume_buf();
1160
116M
                    copy_lifetime(
1161
116M
                        self,
1162
116M
                        unsafe_slice(buf.data(), offset as usize, self.len32() as usize),
1163
116M
                    )
1164
                },
1165
            }
1166
        }
1167
118M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::as_byte_slice
Line
Count
Source
1153
462M
    fn as_byte_slice(&self) -> &[u8] {
1154
        unsafe {
1155
462M
            match self.ptr.get().get() {
1156
61.7M
                EMPTY_TAG => &[],
1157
400M
                n if n <= MAX_INLINE_LEN => (*self.buf.get()).inline.get_unchecked(..n),
1158
                _ => {
1159
177M
                    let (buf, _, offset) = self.assume_buf();
1160
177M
                    copy_lifetime(
1161
177M
                        self,
1162
177M
                        unsafe_slice(buf.data(), offset as usize, self.len32() as usize),
1163
177M
                    )
1164
                },
1165
            }
1166
        }
1167
462M
    }
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
53.4k
    fn as_mut_byte_slice(&mut self) -> &mut [u8] {
1173
        unsafe {
1174
53.4k
            match self.ptr.get().get() {
1175
0
                EMPTY_TAG => &mut [],
1176
53.4k
                n if n <= MAX_INLINE_LEN => (*self.buf.get()).inline.get_unchecked_mut(..n),
1177
                _ => {
1178
53.4k
                    self.make_owned();
1179
53.4k
                    let (mut buf, _, offset) = self.assume_buf();
1180
53.4k
                    let len = self.len32() as usize;
1181
53.4k
                    copy_lifetime_mut(self, unsafe_slice_mut(buf.data_mut(), offset as usize, len))
1182
                },
1183
            }
1184
        }
1185
53.4k
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::as_mut_byte_slice
Line
Count
Source
1172
53.4k
    fn as_mut_byte_slice(&mut self) -> &mut [u8] {
1173
        unsafe {
1174
53.4k
            match self.ptr.get().get() {
1175
0
                EMPTY_TAG => &mut [],
1176
53.4k
                n if n <= MAX_INLINE_LEN => (*self.buf.get()).inline.get_unchecked_mut(..n),
1177
                _ => {
1178
53.4k
                    self.make_owned();
1179
53.4k
                    let (mut buf, _, offset) = self.assume_buf();
1180
53.4k
                    let len = self.len32() as usize;
1181
53.4k
                    copy_lifetime_mut(self, unsafe_slice_mut(buf.data_mut(), offset as usize, len))
1182
                },
1183
            }
1184
        }
1185
53.4k
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::as_mut_byte_slice
1186
1187
948M
    unsafe fn raw_len(&self) -> u32 {
1188
948M
        (*self.buf.get()).heap.len
1189
948M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::raw_len
Line
Count
Source
1187
332M
    unsafe fn raw_len(&self) -> u32 {
1188
332M
        (*self.buf.get()).heap.len
1189
332M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::raw_len
Line
Count
Source
1187
615M
    unsafe fn raw_len(&self) -> u32 {
1188
615M
        (*self.buf.get()).heap.len
1189
615M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::raw_len
1190
1191
128M
    unsafe fn set_len(&mut self, len: u32) {
1192
128M
        (*self.buf.get()).heap.len = len;
1193
128M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::set_len
Line
Count
Source
1191
30.9M
    unsafe fn set_len(&mut self, len: u32) {
1192
30.9M
        (*self.buf.get()).heap.len = len;
1193
30.9M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::set_len
Line
Count
Source
1191
97.1M
    unsafe fn set_len(&mut self, len: u32) {
1192
97.1M
        (*self.buf.get()).heap.len = len;
1193
97.1M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::set_len
1194
1195
479M
    unsafe fn aux(&self) -> u32 {
1196
479M
        (*self.buf.get()).heap.aux
1197
479M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::aux
Line
Count
Source
1195
150M
    unsafe fn aux(&self) -> u32 {
1196
150M
        (*self.buf.get()).heap.aux
1197
150M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::aux
Line
Count
Source
1195
328M
    unsafe fn aux(&self) -> u32 {
1196
328M
        (*self.buf.get()).heap.aux
1197
328M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::aux
1198
1199
128M
    unsafe fn set_aux(&self, aux: u32) {
1200
128M
        (*self.buf.get()).heap.aux = aux;
1201
128M
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::set_aux
Line
Count
Source
1199
30.9M
    unsafe fn set_aux(&self, aux: u32) {
1200
30.9M
        (*self.buf.get()).heap.aux = aux;
1201
30.9M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::set_aux
Line
Count
Source
1199
97.8M
    unsafe fn set_aux(&self, aux: u32) {
1200
97.8M
        (*self.buf.get()).heap.aux = aux;
1201
97.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
31.2M
    pub fn from_slice(x: &F::Slice) -> Tendril<F, A> {
1212
31.2M
        unsafe { Tendril::from_byte_slice_without_validating(x.as_bytes()) }
1213
31.2M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::from_slice
Line
Count
Source
1211
31.2M
    pub fn from_slice(x: &F::Slice) -> Tendril<F, A> {
1212
31.2M
        unsafe { Tendril::from_byte_slice_without_validating(x.as_bytes()) }
1213
31.2M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<_, _>>::from_slice
1214
1215
    /// Push a slice onto the end of the `Tendril`.
1216
    #[inline]
1217
2.90M
    pub fn push_slice(&mut self, x: &F::Slice) {
1218
2.90M
        unsafe { self.push_bytes_without_validating(x.as_bytes()) }
1219
2.90M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::push_slice
Line
Count
Source
1217
2.90M
    pub fn push_slice(&mut self, x: &F::Slice) {
1218
2.90M
        unsafe { self.push_bytes_without_validating(x.as_bytes()) }
1219
2.90M
    }
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
82.2M
    pub fn pop_front_char(&mut self) -> Option<char> {
1293
        unsafe {
1294
            let next_char; // first char in iterator
1295
82.2M
            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
82.2M
                let mut iter = F::char_indices(self.as_byte_slice());
1304
82.2M
                match iter.next() {
1305
82.2M
                    Some((_, c)) => {
1306
82.2M
                        next_char = Some(c);
1307
82.2M
                        if let Some((n, _)) = iter.next() {
1308
59.0M
                            skip = n as u32;
1309
59.0M
                        }
1310
                    },
1311
0
                    None => {
1312
0
                        next_char = None;
1313
0
                    },
1314
                }
1315
            }
1316
1317
82.2M
            if skip != 0 {
1318
59.0M
                self.unsafe_pop_front(skip);
1319
59.0M
            } else {
1320
23.1M
                self.clear();
1321
23.1M
            }
1322
1323
82.2M
            next_char
1324
        }
1325
82.2M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::pop_front_char
Line
Count
Source
1292
82.2M
    pub fn pop_front_char(&mut self) -> Option<char> {
1293
        unsafe {
1294
            let next_char; // first char in iterator
1295
82.2M
            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
82.2M
                let mut iter = F::char_indices(self.as_byte_slice());
1304
82.2M
                match iter.next() {
1305
82.2M
                    Some((_, c)) => {
1306
82.2M
                        next_char = Some(c);
1307
82.2M
                        if let Some((n, _)) = iter.next() {
1308
59.0M
                            skip = n as u32;
1309
59.0M
                        }
1310
                    },
1311
0
                    None => {
1312
0
                        next_char = None;
1313
0
                    },
1314
                }
1315
            }
1316
1317
82.2M
            if skip != 0 {
1318
59.0M
                self.unsafe_pop_front(skip);
1319
59.0M
            } else {
1320
23.1M
                self.clear();
1321
23.1M
            }
1322
1323
82.2M
            next_char
1324
        }
1325
82.2M
    }
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
53.4k
    pub unsafe fn push_uninitialized(&mut self, n: u32) {
1459
53.4k
        let new_len = self.len32().checked_add(n).expect(OFLOW);
1460
53.4k
        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
53.4k
        } else {
1463
53.4k
            self.make_owned_with_capacity(new_len);
1464
53.4k
            self.set_len(new_len);
1465
53.4k
        }
1466
53.4k
    }
<tendril::tendril::Tendril<tendril::fmt::Bytes>>::push_uninitialized
Line
Count
Source
1458
53.4k
    pub unsafe fn push_uninitialized(&mut self, n: u32) {
1459
53.4k
        let new_len = self.len32().checked_add(n).expect(OFLOW);
1460
53.4k
        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
53.4k
        } else {
1463
53.4k
            self.make_owned_with_capacity(new_len);
1464
53.4k
            self.set_len(new_len);
1465
53.4k
        }
1466
53.4k
    }
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
57.5M
    pub fn push_char(&mut self, c: char) {
1509
57.5M
        unsafe {
1510
57.5M
            self.push_bytes_without_validating(c.encode_utf8(&mut [0_u8; 4]).as_bytes());
1511
57.5M
        }
1512
57.5M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::push_char
Line
Count
Source
1508
57.5M
    pub fn push_char(&mut self, c: char) {
1509
57.5M
        unsafe {
1510
57.5M
            self.push_bytes_without_validating(c.encode_utf8(&mut [0_u8; 4]).as_bytes());
1511
57.5M
        }
1512
57.5M
    }
Unexecuted instantiation: <tendril::tendril::Tendril<tendril::fmt::UTF8, _>>::push_char
1513
1514
    /// Create a `Tendril` from a single character.
1515
    #[inline]
1516
2.77M
    pub fn from_char(c: char) -> Tendril<fmt::UTF8, A> {
1517
2.77M
        let mut t: Tendril<fmt::UTF8, A> = Tendril::new();
1518
2.77M
        t.push_char(c);
1519
2.77M
        t
1520
2.77M
    }
<tendril::tendril::Tendril<tendril::fmt::UTF8>>::from_char
Line
Count
Source
1516
2.77M
    pub fn from_char(c: char) -> Tendril<fmt::UTF8, A> {
1517
2.77M
        let mut t: Tendril<fmt::UTF8, A> = Tendril::new();
1518
2.77M
        t.push_char(c);
1519
2.77M
        t
1520
2.77M
    }
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
}