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