turbo_tasks_fs/
rope.rs

1use std::{
2    borrow::Cow,
3    cmp::{Ordering, min},
4    fmt,
5    io::{BufRead, Read, Result as IoResult, Write},
6    mem,
7    ops::{AddAssign, Deref},
8    pin::Pin,
9    task::{Context as TaskContext, Poll},
10};
11
12use RopeElem::{Local, Shared};
13use anyhow::{Context, Result};
14use bytes::{Buf, Bytes};
15use futures::Stream;
16use serde::{Deserialize, Deserializer, Serialize, Serializer};
17use serde_bytes::ByteBuf;
18use tokio::io::{AsyncRead, ReadBuf};
19use triomphe::Arc;
20use turbo_tasks_hash::{DeterministicHash, DeterministicHasher};
21use unsize::{CoerceUnsize, Coercion};
22
23static EMPTY_BUF: &[u8] = &[];
24
25/// An efficient structure for sharing bytes/strings between multiple sources.
26///
27/// Cloning a Rope is extremely cheap (Arc and usize), and
28/// sharing the contents of one Rope can be done by just cloning an Arc.
29///
30/// Ropes are immutable, in order to construct one see [RopeBuilder].
31#[turbo_tasks::value(shared, serialization = "custom", eq = "manual", operation)]
32#[derive(Clone, Debug, Default)]
33pub struct Rope {
34    /// Total length of all held bytes.
35    length: usize,
36
37    /// A shareable container holding the rope's bytes.
38    #[turbo_tasks(debug_ignore, trace_ignore)]
39    data: InnerRope,
40}
41
42/// An Arc container for ropes. This indirection allows for easily sharing the
43/// contents between Ropes (and also RopeBuilders/RopeReaders).
44#[derive(Clone, Debug)]
45struct InnerRope(Arc<[RopeElem]>);
46
47/// Differentiates the types of stored bytes in a rope.
48#[derive(Clone, Debug)]
49enum RopeElem {
50    /// Local bytes are owned directly by this rope.
51    Local(Bytes),
52
53    /// Shared holds the Arc container of another rope.
54    Shared(InnerRope),
55}
56
57/// RopeBuilder provides a mutable container to append bytes/strings. This can
58/// also append _other_ Rope instances cheaply, allowing efficient sharing of
59/// the contents without a full clone of the bytes.
60#[derive(Default, Debug)]
61pub struct RopeBuilder {
62    /// Total length of all previously committed bytes.
63    length: usize,
64
65    /// Immutable bytes references that have been appended to this builder. The
66    /// rope is the combination of all these committed bytes.
67    committed: Vec<RopeElem>,
68
69    /// Stores bytes that have been pushed, but are not yet committed. This is
70    /// either an attempt to push a static lifetime, or a push of owned bytes.
71    /// When the builder is flushed, we will commit these bytes into a real
72    /// Bytes instance.
73    uncommitted: Uncommitted,
74}
75
76/// Stores any bytes which have been pushed, but we haven't decided to commit
77/// yet. Uncommitted bytes allow us to build larger buffers out of possibly
78/// small pushes.
79#[derive(Default)]
80enum Uncommitted {
81    #[default]
82    None,
83
84    /// Stores our attempt to push static lifetime bytes into the rope. If we
85    /// build the Rope or concatenate another Rope, we can commit a static
86    /// Bytes reference and save memory. If not, we'll concatenate this into
87    /// writable bytes to be committed later.
88    Static(&'static [u8]),
89
90    /// Mutable bytes collection where non-static/non-shared bytes are written.
91    /// This builds until the next time a static or shared bytes is
92    /// appended, in which case we split the buffer and commit. Finishing
93    /// the builder also commits these bytes.
94    Owned(Vec<u8>),
95}
96
97impl Rope {
98    pub fn len(&self) -> usize {
99        self.length
100    }
101
102    pub fn is_empty(&self) -> bool {
103        self.length == 0
104    }
105
106    /// Returns a [Read]/[AsyncRead]/[Iterator] instance over all bytes.
107    pub fn read(&self) -> RopeReader {
108        RopeReader::new(&self.data, 0)
109    }
110
111    /// Returns a String instance of all bytes.
112    pub fn to_str(&self) -> Result<Cow<'_, str>> {
113        self.data.to_str(self.length)
114    }
115
116    /// Returns a slice of all bytes
117    pub fn to_bytes(&self) -> Result<Cow<'_, [u8]>> {
118        self.data.to_bytes(self.length)
119    }
120}
121
122impl From<Vec<u8>> for Rope {
123    fn from(mut bytes: Vec<u8>) -> Self {
124        bytes.shrink_to_fit();
125        Rope::from(Bytes::from(bytes))
126    }
127}
128
129impl From<String> for Rope {
130    fn from(mut bytes: String) -> Self {
131        bytes.shrink_to_fit();
132        Rope::from(Bytes::from(bytes))
133    }
134}
135
136impl<T: Into<Bytes>> From<T> for Rope {
137    default fn from(bytes: T) -> Self {
138        let bytes = bytes.into();
139        // We can't have an InnerRope which contains an empty Local section.
140        if bytes.is_empty() {
141            Default::default()
142        } else {
143            Rope {
144                length: bytes.len(),
145                data: InnerRope(Arc::from([Local(bytes)]).unsize(Coercion::to_slice())),
146            }
147        }
148    }
149}
150
151impl RopeBuilder {
152    /// Push owned bytes into the Rope.
153    ///
154    /// If possible use [push_static_bytes] or `+=` operation instead, as they
155    /// will create a reference to shared memory instead of cloning the bytes.
156    pub fn push_bytes(&mut self, bytes: &[u8]) {
157        if bytes.is_empty() {
158            return;
159        }
160
161        self.uncommitted.push_bytes(bytes);
162    }
163
164    /// Push static lifetime bytes into the Rope.
165    ///
166    /// This is more efficient than pushing owned bytes, because the internal
167    /// data does not need to be copied when the rope is read.
168    pub fn push_static_bytes(&mut self, bytes: &'static [u8]) {
169        if bytes.is_empty() {
170            return;
171        }
172
173        // If the string is smaller than the cost of a Bytes reference (4 usizes), then
174        // it's more efficient to own the bytes in a new buffer. We may be able to reuse
175        // that buffer when more bytes are pushed.
176        if bytes.len() < mem::size_of::<Bytes>() {
177            return self.uncommitted.push_static_bytes(bytes);
178        }
179
180        // We may have pending bytes from a prior push.
181        self.finish();
182
183        self.length += bytes.len();
184        self.committed.push(Local(Bytes::from_static(bytes)));
185    }
186
187    /// Concatenate another Rope instance into our builder.
188    ///
189    /// This is much more efficient than pushing actual bytes, since we can
190    /// share the other Rope's references without copying the underlying data.
191    pub fn concat(&mut self, other: &Rope) {
192        if other.is_empty() {
193            return;
194        }
195
196        // We may have pending bytes from a prior push.
197        self.finish();
198
199        self.length += other.len();
200        self.committed.push(Shared(other.data.clone()));
201    }
202
203    /// Writes any pending bytes into our committed queue. This is called automatically by other
204    /// `RopeBuilder` methods.
205    ///
206    /// This may be called multiple times without issue.
207    fn finish(&mut self) {
208        if let Some(b) = self.uncommitted.finish() {
209            debug_assert!(!b.is_empty(), "must not have empty uncommitted bytes");
210            self.length += b.len();
211            self.committed.push(Local(b));
212        }
213    }
214
215    pub fn len(&self) -> usize {
216        self.length + self.uncommitted.len()
217    }
218
219    pub fn is_empty(&self) -> bool {
220        self.len() == 0
221    }
222
223    /// Constructs our final, immutable Rope instance.
224    pub fn build(mut self) -> Rope {
225        self.finish();
226        Rope {
227            length: self.length,
228            data: InnerRope::from(self.committed),
229        }
230    }
231}
232
233impl From<&'static str> for RopeBuilder {
234    default fn from(bytes: &'static str) -> Self {
235        let mut r = RopeBuilder::default();
236        r += bytes;
237        r
238    }
239}
240
241impl From<Vec<u8>> for RopeBuilder {
242    fn from(bytes: Vec<u8>) -> Self {
243        RopeBuilder {
244            // Directly constructing the Uncommitted allows us to skip copying the bytes.
245            uncommitted: Uncommitted::from(bytes),
246            ..Default::default()
247        }
248    }
249}
250
251impl Write for RopeBuilder {
252    fn write(&mut self, bytes: &[u8]) -> IoResult<usize> {
253        self.push_bytes(bytes);
254        Ok(bytes.len())
255    }
256
257    fn flush(&mut self) -> IoResult<()> {
258        self.finish();
259        Ok(())
260    }
261}
262
263impl AddAssign<&'static str> for RopeBuilder {
264    /// Pushes a reference to static memory onto the rope.
265    ///
266    /// This is more efficient than pushing owned bytes, because the internal
267    /// data does not need to be copied when the rope is read.
268    fn add_assign(&mut self, rhs: &'static str) {
269        self.push_static_bytes(rhs.as_bytes());
270    }
271}
272
273impl AddAssign<&Rope> for RopeBuilder {
274    fn add_assign(&mut self, rhs: &Rope) {
275        self.concat(rhs);
276    }
277}
278
279impl Uncommitted {
280    fn len(&self) -> usize {
281        match self {
282            Uncommitted::None => 0,
283            Uncommitted::Static(s) => s.len(),
284            Uncommitted::Owned(v) => v.len(),
285        }
286    }
287
288    /// Pushes owned bytes, converting the current representation to an Owned if
289    /// it's not already.
290    fn push_bytes(&mut self, bytes: &[u8]) {
291        debug_assert!(!bytes.is_empty(), "must not push empty uncommitted bytes");
292        match self {
293            Self::None => *self = Self::Owned(bytes.to_vec()),
294            Self::Static(s) => {
295                // If we'd previously pushed static bytes, we instead concatenate those bytes
296                // with the new bytes in an attempt to use less memory rather than committing 2
297                // Bytes references (2 * 4 usizes).
298                let v = [s, bytes].concat();
299                *self = Self::Owned(v);
300            }
301            Self::Owned(v) => v.extend(bytes),
302        }
303    }
304
305    /// Pushes static lifetime bytes, but only if the current representation is
306    /// None. Else, it coverts to an Owned.
307    fn push_static_bytes(&mut self, bytes: &'static [u8]) {
308        debug_assert!(!bytes.is_empty(), "must not push empty uncommitted bytes");
309        match self {
310            // If we've not already pushed static bytes, we attempt to store the bytes for later. If
311            // we push owned bytes or another static bytes, then this attempt will fail and we'll
312            // instead concatenate into a single owned Bytes. But if we don't push anything (build
313            // the Rope), or concatenate another Rope (we can't join our bytes with the InnerRope of
314            // another Rope), we'll be able to commit a static Bytes reference and save overall
315            // memory (a small static Bytes reference is better than a small owned Bytes reference).
316            Self::None => *self = Self::Static(bytes),
317            _ => self.push_bytes(bytes),
318        }
319    }
320
321    /// Converts the current uncommitted bytes into a Bytes, resetting our
322    /// representation to None.
323    fn finish(&mut self) -> Option<Bytes> {
324        match mem::take(self) {
325            Self::None => None,
326            Self::Static(s) => Some(Bytes::from_static(s)),
327            Self::Owned(mut v) => {
328                v.shrink_to_fit();
329                Some(v.into())
330            }
331        }
332    }
333}
334
335impl fmt::Debug for Uncommitted {
336    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
337        match self {
338            Uncommitted::None => f.write_str("None"),
339            Uncommitted::Static(s) => f
340                .debug_tuple("Static")
341                .field(&Bytes::from_static(s))
342                .finish(),
343            Uncommitted::Owned(v) => f
344                .debug_tuple("Owned")
345                .field(&Bytes::from(v.clone()))
346                .finish(),
347        }
348    }
349}
350
351impl DeterministicHash for Rope {
352    /// Ropes with similar contents hash the same, regardless of their
353    /// structure.
354    fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
355        state.write_usize(self.len());
356        self.data.deterministic_hash(state);
357    }
358}
359
360impl Serialize for Rope {
361    /// Ropes are always serialized into contiguous strings, because
362    /// deserialization won't deduplicate and share the Arcs (being the only
363    /// possible owner of a individual "shared" data doesn't make sense).
364    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
365        use serde::ser::Error;
366        let bytes = self.to_bytes().map_err(Error::custom)?;
367        match bytes {
368            Cow::Borrowed(b) => serde_bytes::Bytes::new(b).serialize(serializer),
369            Cow::Owned(b) => ByteBuf::from(b).serialize(serializer),
370        }
371    }
372}
373
374impl<'de> Deserialize<'de> for Rope {
375    /// Deserializes strings into a contiguous, immutable Rope.
376    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
377        let bytes = ByteBuf::deserialize(deserializer)?.into_vec();
378        Ok(Rope::from(bytes))
379    }
380}
381
382pub mod ser_as_string {
383    use serde::{Serializer, ser::Error};
384
385    use super::Rope;
386
387    /// Serializes a Rope into a string.
388    pub fn serialize<S: Serializer>(rope: &Rope, serializer: S) -> Result<S::Ok, S::Error> {
389        let s = rope.to_str().map_err(Error::custom)?;
390        serializer.serialize_str(&s)
391    }
392}
393
394pub mod ser_option_as_string {
395    use serde::{Serializer, ser::Error};
396
397    use super::Rope;
398
399    /// Serializes a Rope into a string.
400    pub fn serialize<S: Serializer>(rope: &Option<Rope>, serializer: S) -> Result<S::Ok, S::Error> {
401        if let Some(rope) = rope {
402            let s = rope.to_str().map_err(Error::custom)?;
403            serializer.serialize_some(&s)
404        } else {
405            serializer.serialize_none()
406        }
407    }
408}
409
410impl PartialEq for Rope {
411    // Ropes with similar contents are equals, regardless of their structure.
412    fn eq(&self, other: &Self) -> bool {
413        if self.len() != other.len() {
414            return false;
415        }
416        self.cmp(other) == Ordering::Equal
417    }
418}
419
420impl Eq for Rope {}
421
422impl Ord for Rope {
423    fn cmp(&self, other: &Self) -> Ordering {
424        if Arc::ptr_eq(&self.data, &other.data) {
425            return Ordering::Equal;
426        }
427
428        // Fast path for structurally equal Ropes. With this, we can do memory reference
429        // checks and skip some contents equality.
430        let left = &self.data;
431        let right = &other.data;
432        let len = min(left.len(), right.len());
433        let mut index = 0;
434        while index < len {
435            let a = &left[index];
436            let b = &right[index];
437
438            match a.maybe_cmp(b) {
439                // Bytes or InnerRope point to the same memory, or Bytes are contents equal.
440                Some(Ordering::Equal) => index += 1,
441                // Bytes are not contents equal.
442                Some(ordering) => return ordering,
443                // InnerRopes point to different memory, or the Ropes weren't structurally equal.
444                None => break,
445            }
446        }
447        // If we reach the end of iteration without finding a mismatch (or early
448        // breaking), then we know the ropes are either equal or not equal.
449        if index == len {
450            // We know that any remaining RopeElem in the InnerRope must contain content, so
451            // if either one contains more RopeElem than they cannot be equal.
452            return left.len().cmp(&right.len());
453        }
454
455        // At this point, we need to do slower contents equality. It's possible we'll
456        // still get some memory reference equality for Bytes.
457        let mut left = RopeReader::new(left, index);
458        let mut right = RopeReader::new(right, index);
459        loop {
460            match (left.fill_buf(), right.fill_buf()) {
461                // fill_buf should always return Ok, with either some number of bytes or 0 bytes
462                // when consumed.
463                (Ok(a), Ok(b)) => {
464                    let len = min(a.len(), b.len());
465
466                    // When one buffer is consumed, both must be consumed.
467                    if len == 0 {
468                        return a.len().cmp(&b.len());
469                    }
470
471                    match a[0..len].cmp(&b[0..len]) {
472                        Ordering::Equal => {
473                            left.consume(len);
474                            right.consume(len);
475                        }
476                        ordering => return ordering,
477                    }
478                }
479
480                // If an error is ever returned (which shouldn't happen for us) for either/both,
481                // then we can't prove equality.
482                _ => unreachable!(),
483            }
484        }
485    }
486}
487
488impl PartialOrd for Rope {
489    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
490        Some(self.cmp(other))
491    }
492}
493
494impl From<Vec<u8>> for Uncommitted {
495    fn from(bytes: Vec<u8>) -> Self {
496        if bytes.is_empty() {
497            Uncommitted::None
498        } else {
499            Uncommitted::Owned(bytes)
500        }
501    }
502}
503
504impl InnerRope {
505    /// Returns a String instance of all bytes.
506    fn to_str(&self, len: usize) -> Result<Cow<'_, str>> {
507        match &self[..] {
508            [] => Ok(Cow::Borrowed("")),
509            [Shared(inner)] => inner.to_str(len),
510            [Local(bytes)] => {
511                let utf8 = std::str::from_utf8(bytes);
512                utf8.context("failed to convert rope into string")
513                    .map(Cow::Borrowed)
514            }
515            _ => {
516                let mut read = RopeReader::new(self, 0);
517                let mut string = String::with_capacity(len);
518                let res = read.read_to_string(&mut string);
519                res.context("failed to convert rope into string")?;
520                Ok(Cow::Owned(string))
521            }
522        }
523    }
524
525    /// Returns a slice of all bytes.
526    fn to_bytes(&self, len: usize) -> Result<Cow<'_, [u8]>> {
527        match &self[..] {
528            [] => Ok(Cow::Borrowed(EMPTY_BUF)),
529            [Shared(inner)] => inner.to_bytes(len),
530            [Local(bytes)] => Ok(Cow::Borrowed(bytes)),
531            _ => {
532                let mut read = RopeReader::new(self, 0);
533                let mut buf = Vec::with_capacity(len);
534                read.read_to_end(&mut buf)?;
535                Ok(Cow::Owned(buf))
536            }
537        }
538    }
539}
540
541impl Default for InnerRope {
542    fn default() -> Self {
543        InnerRope(Arc::new([]).unsize(Coercion::to_slice()))
544    }
545}
546
547impl DeterministicHash for InnerRope {
548    /// Ropes with similar contents hash the same, regardless of their
549    /// structure. Notice the InnerRope does not contain a length (and any
550    /// shared InnerRopes won't either), so the exact structure isn't
551    /// relevant at this point.
552    fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
553        for v in self.0.iter() {
554            v.deterministic_hash(state);
555        }
556    }
557}
558
559impl From<Vec<RopeElem>> for InnerRope {
560    fn from(mut els: Vec<RopeElem>) -> Self {
561        if cfg!(debug_assertions) {
562            // It's important that an InnerRope never contain an empty Bytes section.
563            for el in els.iter() {
564                match el {
565                    Local(b) => debug_assert!(!b.is_empty(), "must not have empty Bytes"),
566                    Shared(s) => {
567                        // We check whether the shared slice is empty, and not its elements. The
568                        // only way to construct the Shared's InnerRope is
569                        // in this mod, and we have already checked that
570                        // none of its elements are empty.
571                        debug_assert!(!s.is_empty(), "must not have empty InnerRope");
572                    }
573                }
574            }
575        }
576        els.shrink_to_fit();
577        InnerRope(Arc::from(els))
578    }
579}
580
581impl Deref for InnerRope {
582    type Target = Arc<[RopeElem]>;
583
584    fn deref(&self) -> &Self::Target {
585        &self.0
586    }
587}
588
589impl RopeElem {
590    fn maybe_cmp(&self, other: &Self) -> Option<Ordering> {
591        match (self, other) {
592            (Local(a), Local(b)) => {
593                if a.len() == b.len() {
594                    return Some(a.cmp(b));
595                }
596
597                // But if not, the rope may still be contents equal if a following section
598                // contains the missing bytes.
599                None
600            }
601            (Shared(a), Shared(b)) => {
602                if Arc::ptr_eq(&a.0, &b.0) {
603                    return Some(Ordering::Equal);
604                }
605
606                // But if not, they might still be equal and we need to fallback to slower
607                // equality.
608                None
609            }
610            _ => None,
611        }
612    }
613}
614
615impl DeterministicHash for RopeElem {
616    /// Ropes with similar contents hash the same, regardless of their
617    /// structure. Notice the Bytes length is not hashed, and shared InnerRopes
618    /// do not contain a length.
619    fn deterministic_hash<H: DeterministicHasher>(&self, state: &mut H) {
620        match self {
621            Local(bytes) => state.write_bytes(bytes),
622            Shared(inner) => inner.deterministic_hash(state),
623        }
624    }
625}
626
627#[derive(Debug, Default)]
628/// Implements the [Read]/[AsyncRead]/[Iterator] trait over a [Rope].
629pub struct RopeReader {
630    /// The Rope's tree is kept as a cloned stack, allowing us to accomplish
631    /// incremental yielding.
632    stack: Vec<StackElem>,
633}
634
635/// A StackElem holds the current index into either a Bytes or a shared Rope.
636/// When the index reaches the end of the associated data, it is removed and we
637/// continue onto the next item in the stack.
638#[derive(Debug)]
639enum StackElem {
640    Local(Bytes),
641    Shared(InnerRope, usize),
642}
643
644impl RopeReader {
645    fn new(inner: &InnerRope, index: usize) -> Self {
646        if index >= inner.len() {
647            Default::default()
648        } else {
649            RopeReader {
650                stack: vec![StackElem::Shared(inner.clone(), index)],
651            }
652        }
653    }
654
655    /// A shared implementation for reading bytes. This takes the basic
656    /// operations needed for both Read and AsyncRead.
657    fn read_internal(&mut self, want: usize, buf: &mut ReadBuf<'_>) -> usize {
658        let mut remaining = want;
659
660        while remaining > 0 {
661            let mut bytes = match self.next() {
662                None => break,
663                Some(b) => b,
664            };
665
666            let amount = min(bytes.len(), remaining);
667
668            buf.put_slice(&bytes[0..amount]);
669
670            if amount < bytes.len() {
671                bytes.advance(amount);
672                self.stack.push(StackElem::Local(bytes))
673            }
674            remaining -= amount;
675        }
676
677        want - remaining
678    }
679}
680
681impl Iterator for RopeReader {
682    type Item = Bytes;
683
684    fn next(&mut self) -> Option<Self::Item> {
685        // Iterates the rope's elements recursively until we find the next Local
686        // section, returning its Bytes.
687        loop {
688            let (inner, mut index) = match self.stack.pop() {
689                None => return None,
690                Some(StackElem::Local(b)) => {
691                    debug_assert!(!b.is_empty(), "must not have empty Bytes section");
692                    return Some(b);
693                }
694                Some(StackElem::Shared(r, i)) => (r, i),
695            };
696
697            let el = inner[index].clone();
698            index += 1;
699            if index < inner.len() {
700                self.stack.push(StackElem::Shared(inner, index));
701            }
702
703            self.stack.push(StackElem::from(el));
704        }
705    }
706}
707
708impl Read for RopeReader {
709    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
710        Ok(self.read_internal(buf.len(), &mut ReadBuf::new(buf)))
711    }
712}
713
714impl AsyncRead for RopeReader {
715    fn poll_read(
716        self: Pin<&mut Self>,
717        _cx: &mut TaskContext<'_>,
718        buf: &mut ReadBuf<'_>,
719    ) -> Poll<IoResult<()>> {
720        let this = self.get_mut();
721        this.read_internal(buf.remaining(), buf);
722        Poll::Ready(Ok(()))
723    }
724}
725
726impl BufRead for RopeReader {
727    fn fill_buf(&mut self) -> IoResult<&[u8]> {
728        // Returns the full buffer without coping any data. The same bytes will
729        // continue to be returned until [consume] is called.
730        let bytes = match self.next() {
731            None => return Ok(EMPTY_BUF),
732            Some(b) => b,
733        };
734
735        // This is just so we can get a reference to the asset that is kept alive by the
736        // RopeReader itself. We can then auto-convert that reference into the needed u8
737        // slice reference.
738        self.stack.push(StackElem::Local(bytes));
739        let Some(StackElem::Local(bytes)) = self.stack.last() else {
740            unreachable!()
741        };
742
743        Ok(bytes)
744    }
745
746    fn consume(&mut self, amt: usize) {
747        if let Some(StackElem::Local(b)) = self.stack.last_mut() {
748            if amt == b.len() {
749                self.stack.pop();
750            } else {
751                // Consume some amount of bytes from the current Bytes instance, ensuring
752                // those bytes are not returned on the next call to [fill_buf].
753                b.advance(amt);
754            }
755        }
756    }
757}
758
759impl Stream for RopeReader {
760    // The Result<Bytes> item type is required for this to be streamable into a
761    // [Hyper::Body].
762    type Item = Result<Bytes>;
763
764    // Returns a "result" of reading the next shared bytes reference. This
765    // differs from [Read::read] by not copying any memory.
766    fn poll_next(self: Pin<&mut Self>, _cx: &mut TaskContext<'_>) -> Poll<Option<Self::Item>> {
767        let this = self.get_mut();
768        Poll::Ready(this.next().map(Ok))
769    }
770}
771
772impl From<RopeElem> for StackElem {
773    fn from(el: RopeElem) -> Self {
774        match el {
775            Local(bytes) => Self::Local(bytes),
776            Shared(inner) => Self::Shared(inner, 0),
777        }
778    }
779}
780
781#[cfg(test)]
782mod test {
783    use std::{
784        borrow::Cow,
785        cmp::min,
786        io::{BufRead, Read},
787    };
788
789    use anyhow::Result;
790
791    use super::{InnerRope, Rope, RopeBuilder, RopeElem};
792
793    // These are intentionally not exposed, because they do inefficient conversions
794    // in order to fully test cases.
795    impl From<&str> for RopeElem {
796        fn from(value: &str) -> Self {
797            RopeElem::Local(value.to_string().into())
798        }
799    }
800    impl From<Vec<RopeElem>> for RopeElem {
801        fn from(value: Vec<RopeElem>) -> Self {
802            RopeElem::Shared(InnerRope::from(value))
803        }
804    }
805    impl From<Rope> for RopeElem {
806        fn from(value: Rope) -> Self {
807            RopeElem::Shared(value.data)
808        }
809    }
810    impl Rope {
811        fn new(value: Vec<RopeElem>) -> Self {
812            let data = InnerRope::from(value);
813            Rope {
814                length: data.len(),
815                data,
816            }
817        }
818    }
819    impl InnerRope {
820        fn len(&self) -> usize {
821            self.iter().map(|v| v.len()).sum()
822        }
823    }
824    impl RopeElem {
825        fn len(&self) -> usize {
826            match self {
827                RopeElem::Local(b) => b.len(),
828                RopeElem::Shared(r) => r.len(),
829            }
830        }
831    }
832
833    #[test]
834    fn empty_build_without_pushes() {
835        let empty = RopeBuilder::default().build();
836        let mut reader = empty.read();
837        assert!(reader.next().is_none());
838    }
839
840    #[test]
841    fn empty_build_with_empty_static_push() {
842        let mut builder = RopeBuilder::default();
843        builder += "";
844
845        let empty = builder.build();
846        let mut reader = empty.read();
847        assert!(reader.next().is_none());
848    }
849
850    #[test]
851    fn empty_build_with_empty_bytes_push() {
852        let mut builder = RopeBuilder::default();
853        builder.push_bytes(&[]);
854
855        let empty = builder.build();
856        let mut reader = empty.read();
857        assert!(reader.next().is_none());
858    }
859
860    #[test]
861    fn empty_build_with_empty_concat() {
862        let mut builder = RopeBuilder::default();
863        builder += &RopeBuilder::default().build();
864
865        let empty = builder.build();
866        let mut reader = empty.read();
867        assert!(reader.next().is_none());
868    }
869
870    #[test]
871    fn empty_from_empty_static_str() {
872        let empty = Rope::from("");
873        let mut reader = empty.read();
874        assert!(reader.next().is_none());
875    }
876
877    #[test]
878    fn empty_from_empty_string() {
879        let empty = Rope::from("".to_string());
880        let mut reader = empty.read();
881        assert!(reader.next().is_none());
882    }
883
884    #[test]
885    fn empty_equality() {
886        let a = Rope::from("");
887        let b = Rope::from("");
888
889        assert_eq!(a, b);
890    }
891
892    #[test]
893    fn cloned_equality() {
894        let a = Rope::from("abc");
895        let b = a.clone();
896
897        assert_eq!(a, b);
898    }
899
900    #[test]
901    fn value_equality() {
902        let a = Rope::from("abc".to_string());
903        let b = Rope::from("abc".to_string());
904
905        assert_eq!(a, b);
906    }
907
908    #[test]
909    fn value_inequality() {
910        let a = Rope::from("abc".to_string());
911        let b = Rope::from("def".to_string());
912
913        assert_ne!(a, b);
914    }
915
916    #[test]
917    fn value_equality_shared_1() {
918        let shared = Rope::from("def");
919        let a = Rope::new(vec!["abc".into(), shared.clone().into(), "ghi".into()]);
920        let b = Rope::new(vec!["abc".into(), shared.into(), "ghi".into()]);
921
922        assert_eq!(a, b);
923    }
924
925    #[test]
926    fn value_equality_shared_2() {
927        let a = Rope::new(vec!["abc".into(), vec!["def".into()].into(), "ghi".into()]);
928        let b = Rope::new(vec!["abc".into(), vec!["def".into()].into(), "ghi".into()]);
929
930        assert_eq!(a, b);
931    }
932
933    #[test]
934    fn value_equality_splits_1() {
935        let a = Rope::new(vec!["a".into(), "aa".into()]);
936        let b = Rope::new(vec!["aa".into(), "a".into()]);
937
938        assert_eq!(a, b);
939    }
940
941    #[test]
942    fn value_equality_splits_2() {
943        let a = Rope::new(vec![vec!["a".into()].into(), "aa".into()]);
944        let b = Rope::new(vec![vec!["aa".into()].into(), "a".into()]);
945
946        assert_eq!(a, b);
947    }
948
949    #[test]
950    fn value_inequality_shared_1() {
951        let shared = Rope::from("def");
952        let a = Rope::new(vec!["aaa".into(), shared.clone().into(), "ghi".into()]);
953        let b = Rope::new(vec!["bbb".into(), shared.into(), "ghi".into()]);
954
955        assert_ne!(a, b);
956    }
957
958    #[test]
959    fn value_inequality_shared_2() {
960        let a = Rope::new(vec!["abc".into(), vec!["ddd".into()].into(), "ghi".into()]);
961        let b = Rope::new(vec!["abc".into(), vec!["eee".into()].into(), "ghi".into()]);
962
963        assert_ne!(a, b);
964    }
965
966    #[test]
967    fn value_inequality_shared_3() {
968        let shared = Rope::from("def");
969        let a = Rope::new(vec!["abc".into(), shared.clone().into(), "ggg".into()]);
970        let b = Rope::new(vec!["abc".into(), shared.into(), "hhh".into()]);
971
972        assert_ne!(a, b);
973    }
974
975    #[test]
976    fn iteration() {
977        let shared = Rope::from("def");
978        let rope = Rope::new(vec!["abc".into(), shared.into(), "ghi".into()]);
979
980        let chunks = rope.read().collect::<Vec<_>>();
981
982        assert_eq!(chunks, vec!["abc", "def", "ghi"]);
983    }
984
985    #[test]
986    fn read() {
987        let shared = Rope::from("def");
988        let rope = Rope::new(vec!["abc".into(), shared.into(), "ghi".into()]);
989
990        let mut chunks = vec![];
991        let mut buf = [0_u8; 2];
992        let mut reader = rope.read();
993        loop {
994            let amt = reader.read(&mut buf).unwrap();
995            if amt == 0 {
996                break;
997            }
998            chunks.push(Vec::from(&buf[0..amt]));
999        }
1000
1001        assert_eq!(
1002            chunks,
1003            vec![
1004                Vec::from(*b"ab"),
1005                Vec::from(*b"cd"),
1006                Vec::from(*b"ef"),
1007                Vec::from(*b"gh"),
1008                Vec::from(*b"i")
1009            ]
1010        );
1011    }
1012
1013    #[test]
1014    fn fill_buf() {
1015        let shared = Rope::from("def");
1016        let rope = Rope::new(vec!["abc".into(), shared.into(), "ghi".into()]);
1017
1018        let mut chunks = vec![];
1019        let mut reader = rope.read();
1020        loop {
1021            let buf = reader.fill_buf().unwrap();
1022            if buf.is_empty() {
1023                break;
1024            }
1025            let c = min(2, buf.len());
1026            chunks.push(Vec::from(buf));
1027            reader.consume(c);
1028        }
1029
1030        assert_eq!(
1031            chunks,
1032            // We're receiving a full buf, then only consuming 2 bytes, so we'll still get the
1033            // third.
1034            vec![
1035                Vec::from(*b"abc"),
1036                Vec::from(*b"c"),
1037                Vec::from(*b"def"),
1038                Vec::from(*b"f"),
1039                Vec::from(*b"ghi"),
1040                Vec::from(*b"i")
1041            ]
1042        );
1043    }
1044
1045    #[test]
1046    fn test_to_bytes() -> Result<()> {
1047        let rope = Rope::from("abc");
1048        assert_eq!(rope.to_bytes()?, Cow::Borrowed::<[u8]>(&[0x61, 0x62, 0x63]));
1049        Ok(())
1050    }
1051}