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