Skip to main content

turbo_tasks_fs/
rope.rs

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