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