Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin' into cached-source
Browse files Browse the repository at this point in the history
  • Loading branch information
SyMind committed Dec 16, 2024
2 parents 80881bf + 261f6b9 commit f17702f
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 18 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ ouroboros = "0.18.4"

codspeed-criterion-compat = { version = "2.7.2", default-features = false, optional = true }
static_assertions = "1.1.0"
simd-json = "=0.14.3"
simd-json = "0.14.3"

[dev-dependencies]
twox-hash = "2.1.0"
Expand Down
14 changes: 14 additions & 0 deletions src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1260,6 +1260,10 @@ pub trait SourceText<'a>: Default + Clone + ToString {
/// Returns a slice of the text specified by the byte range.
fn byte_slice(&self, range: Range<usize>) -> Self;

/// Returns a slice of the text specified by the byte range without bounds checking.
#[allow(unsafe_code)]
unsafe fn byte_slice_unchecked(&self, range: Range<usize>) -> Self;

/// Returns true if the text is empty.
fn is_empty(&self) -> bool;

Expand Down Expand Up @@ -1293,6 +1297,11 @@ impl<'a> SourceText<'a> for Rope<'a> {
self.byte_slice(range)
}

#[allow(unsafe_code)]
unsafe fn byte_slice_unchecked(&self, range: Range<usize>) -> Self {
self.byte_slice_unchecked(range)
}

#[inline]
fn is_empty(&self) -> bool {
self.is_empty()
Expand Down Expand Up @@ -1330,6 +1339,11 @@ impl<'a> SourceText<'a> for &'a str {
self.get(range).unwrap_or_default()
}

#[allow(unsafe_code)]
unsafe fn byte_slice_unchecked(&self, range: Range<usize>) -> Self {
self.get_unchecked(range)
}

#[inline]
fn is_empty(&self) -> bool {
(*self).is_empty()
Expand Down
94 changes: 78 additions & 16 deletions src/rope.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use std::{
borrow::Cow,
cell::RefCell,
collections::VecDeque,
hash::Hash,
ops::{Bound, RangeBounds},
Expand Down Expand Up @@ -733,6 +732,18 @@ impl PartialEq<Rope<'_>> for Rope<'_> {
return false;
}

if let (
Rope {
repr: Repr::Light(s),
},
Rope {
repr: Repr::Light(other),
},
) = (self, other)
{
return s == other;
}

let chunks = match &self.repr {
Repr::Light(s) => &[(*s, 0)][..],
Repr::Full(data) => &data[..],
Expand All @@ -742,22 +753,63 @@ impl PartialEq<Rope<'_>> for Rope<'_> {
Repr::Full(data) => &data[..],
};

let mut cur = 0;
let other_chunk_index = RefCell::new(0);
let mut other_chunk_byte_index = 0;
let other_chunk = || other_chunks[*other_chunk_index.borrow()].0.as_bytes();
for (chunk, start_pos) in chunks.iter() {
let chunk = chunk.as_bytes();
while (cur - start_pos) < chunk.len() {
if other_chunk_byte_index >= other_chunk().len() {
other_chunk_byte_index = 0;
*other_chunk_index.borrow_mut() += 1;
let total_bytes = self.len();
let mut byte_idx = 0;

let mut chunks_idx = 0;
let mut in_chunk_byte_idx = 0;

let mut other_chunks_idx = 0;
let mut in_other_chunk_byte_idx = 0;

loop {
if byte_idx == total_bytes {
break;
}

let &(chunk, _) = &chunks[chunks_idx];
let chunk_len = chunk.len();
let &(other_chunk, _) = &other_chunks[other_chunks_idx];
let other_chunk_len = other_chunk.len();

let chunk_remaining = chunk_len - in_chunk_byte_idx;
let other_chunk_remaining = other_chunk_len - in_other_chunk_byte_idx;

match chunk_remaining.cmp(&other_chunk_remaining) {
std::cmp::Ordering::Less => {
if other_chunk
[in_other_chunk_byte_idx..in_other_chunk_byte_idx + chunk_remaining]
!= chunk[in_chunk_byte_idx..]
{
return false;
}
in_other_chunk_byte_idx += chunk_remaining;
chunks_idx += 1;
in_chunk_byte_idx = 0;
byte_idx += chunk_remaining;
}
if chunk[cur - start_pos] == other_chunk()[other_chunk_byte_index] {
cur += 1;
other_chunk_byte_index += 1;
} else {
return false;
std::cmp::Ordering::Equal => {
if chunk[in_chunk_byte_idx..]
!= other_chunk[in_other_chunk_byte_idx..]
{
return false;
}
chunks_idx += 1;
other_chunks_idx += 1;
in_chunk_byte_idx = 0;
in_other_chunk_byte_idx = 0;
byte_idx += chunk_remaining;
}
std::cmp::Ordering::Greater => {
if chunk[in_chunk_byte_idx..in_chunk_byte_idx + other_chunk_remaining]
!= other_chunk[in_other_chunk_byte_idx..]
{
return false;
}
in_chunk_byte_idx += other_chunk_remaining;
other_chunks_idx += 1;
in_other_chunk_byte_idx = 0;
byte_idx += other_chunk_remaining;
}
}
}
Expand Down Expand Up @@ -1058,6 +1110,16 @@ mod tests {
b.add("fghi");

assert_eq!(a, b);

let mut a = Rope::new();
a.add("abc");

let mut b = Rope::new();
b.add("a");
b.add("b");
b.add("c");

assert_eq!(a, b);
}

#[test]
Expand Down
9 changes: 8 additions & 1 deletion src/with_indices.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,14 @@ where
let str_len = self.line.len();
let start = *indices_indexes.get(start_index).unwrap_or(&str_len);
let end = *indices_indexes.get(end_index).unwrap_or(&str_len);
self.line.byte_slice(start..end)

#[allow(unsafe_code)]
unsafe {
// SAFETY: Since `indices` iterates over the `CharIndices` of `self`, we can guarantee
// that the indices obtained from it will always be within the bounds of `self` and they
// will always lie on UTF-8 sequence boundaries.
self.line.byte_slice_unchecked(start..end)
}
}
}

Expand Down

0 comments on commit f17702f

Please sign in to comment.