/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 | | } |