Skip to content

Commit c90f574

Browse files
committed
rope add len
1 parent d1e19a4 commit c90f574

File tree

7 files changed

+50
-39
lines changed

7 files changed

+50
-39
lines changed

src/cached_source.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use crate::{
2121
struct CachedData {
2222
hash: OnceLock<u64>,
2323
size: OnceLock<usize>,
24-
source: OnceLock<Vec<&'static str>>,
24+
source: OnceLock<(Vec<&'static str>, usize)>,
2525
columns_map: OnceLock<Option<SourceMap>>,
2626
line_only_map: OnceLock<Option<SourceMap>>,
2727
}
@@ -84,23 +84,23 @@ impl CachedSource {
8484

8585
impl Source for CachedSource {
8686
fn source(&self) -> SourceValue {
87-
let rope = self.cache.source.get_or_init(|| {
87+
let (chunks, len) = self.cache.source.get_or_init(|| {
8888
#[allow(unsafe_code)]
8989
// SAFETY: CachedSource guarantees that the underlying source outlives the cache,
9090
// so transmuting Vec<&str> to Vec<&'static str> is safe in this context.
9191
// This allows us to store string slices in the cache without additional allocations.
9292
unsafe {
93-
std::mem::transmute::<Vec<&str>, Vec<&'static str>>(self.rope())
93+
std::mem::transmute::<(Vec<&str>, usize), (Vec<&'static str>, usize)>(self.rope())
9494
}
9595
});
96-
let mut string = String::with_capacity(self.size());
97-
for segment in rope {
98-
string.push_str(segment);
96+
let mut string = String::with_capacity(*len);
97+
for chunk in chunks {
98+
string.push_str(chunk);
9999
}
100100
SourceValue::String(Cow::Owned(string))
101101
}
102102

103-
fn rope(&self) -> Vec<&str> {
103+
fn rope(&self) -> (Vec<&str>, usize) {
104104
self.inner.rope()
105105
}
106106

src/concat_source.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,15 +175,19 @@ impl Source for ConcatSource {
175175
}
176176
}
177177

178-
fn rope(&self) -> Vec<&str> {
178+
fn rope(&self) -> (Vec<&str>, usize) {
179179
let children = self.optimized_children();
180180
if children.len() == 1 {
181181
children[0].rope()
182182
} else {
183-
children
184-
.iter()
185-
.flat_map(|child| child.rope())
186-
.collect::<Vec<_>>()
183+
let mut merged_chunks = vec![];
184+
let mut merged_len = 0;
185+
for child in children {
186+
let (chunks, len) = child.rope();
187+
merged_chunks.extend(chunks);
188+
merged_len += len;
189+
}
190+
(merged_chunks, merged_len)
187191
}
188192
}
189193

src/original_source.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ impl Source for OriginalSource {
5656
SourceValue::String(Cow::Borrowed(&self.value))
5757
}
5858

59-
fn rope(&self) -> Vec<&str> {
60-
vec![self.value.as_ref()]
59+
fn rope(&self) -> (Vec<&str>, usize) {
60+
(vec![self.value.as_ref()], self.value.len())
6161
}
6262

6363
fn buffer(&self) -> Cow<[u8]> {

src/raw_source.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ impl Source for RawStringSource {
6464
SourceValue::String(Cow::Borrowed(&self.0))
6565
}
6666

67-
fn rope(&self) -> Vec<&str> {
68-
vec![self.0.as_ref()]
67+
fn rope(&self) -> (Vec<&str>, usize) {
68+
(vec![self.0.as_ref()], self.0.len())
6969
}
7070

7171
fn buffer(&self) -> Cow<[u8]> {
@@ -214,8 +214,9 @@ impl Source for RawBufferSource {
214214
SourceValue::Buffer(Cow::Borrowed(&self.value))
215215
}
216216

217-
fn rope(&self) -> Vec<&str> {
218-
vec![self.get_or_init_value_as_string()]
217+
fn rope(&self) -> (Vec<&str>, usize) {
218+
let s = self.get_or_init_value_as_string();
219+
(vec![s], s.len())
219220
}
220221

221222
fn buffer(&self) -> Cow<[u8]> {

src/replace_source.rs

Lines changed: 23 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -161,23 +161,24 @@ impl ReplaceSource {
161161

162162
impl Source for ReplaceSource {
163163
fn source(&self) -> SourceValue {
164-
let rope = self.rope();
165-
if rope.len() == 1 {
166-
SourceValue::String(Cow::Borrowed(rope[0]))
164+
let (chunks, len) = self.rope();
165+
if chunks.len() == 1 {
166+
SourceValue::String(Cow::Borrowed(chunks[0]))
167167
} else {
168-
let mut string = String::with_capacity(rope.iter().map(|c| c.len()).sum());
169-
for chunk in rope {
168+
let mut string = String::with_capacity(len);
169+
for chunk in chunks {
170170
string.push_str(chunk);
171171
}
172172
SourceValue::String(Cow::Owned(string))
173173
}
174174
}
175175

176176
#[allow(unsafe_code)]
177-
fn rope(&self) -> Vec<&str> {
178-
let inner_rope = self.inner.rope();
179-
let mut rope: Vec<&str> =
180-
Vec::with_capacity(inner_rope.len() + self.replacements.len() * 2);
177+
fn rope(&self) -> (Vec<&str>, usize) {
178+
let (inner_chunks, _) = self.inner.rope();
179+
let mut chunks: Vec<&str> =
180+
Vec::with_capacity(inner_chunks.len() + self.replacements.len() * 2);
181+
let mut len: usize = 0;
181182

182183
let mut pos: usize = 0;
183184
let mut replacement_idx: usize = 0;
@@ -186,7 +187,7 @@ impl Source for ReplaceSource {
186187
< self.replacements.len())
187188
.then(|| self.replacements[replacement_idx].start as usize);
188189

189-
'chunk_loop: for chunk in inner_rope {
190+
'chunk_loop: for chunk in inner_chunks {
190191
let mut chunk_pos = 0;
191192
let end_pos = pos + chunk.len();
192193

@@ -213,14 +214,16 @@ impl Source for ReplaceSource {
213214
let offset = next_replacement_pos - pos;
214215
let chunk_slice =
215216
unsafe { &chunk.get_unchecked(chunk_pos..(chunk_pos + offset)) };
216-
rope.push(chunk_slice);
217+
chunks.push(chunk_slice);
218+
len += chunk_slice.len();
217219
chunk_pos += offset;
218220
pos = next_replacement_pos;
219221
}
220222
// Insert replacement content split into chunks by lines
221223
let replacement =
222224
unsafe { &self.replacements.get_unchecked(replacement_idx) };
223-
rope.push(&replacement.content);
225+
chunks.push(&replacement.content);
226+
len += replacement.content.len();
224227

225228
// Remove replaced content by settings this variable
226229
replacement_end = if let Some(replacement_end) = replacement_end {
@@ -260,7 +263,9 @@ impl Source for ReplaceSource {
260263

261264
// Emit remaining chunk
262265
if chunk_pos < chunk.len() {
263-
rope.push(unsafe { &chunk.get_unchecked(chunk_pos..) });
266+
let chunk = unsafe { &chunk.get_unchecked(chunk_pos..) };
267+
chunks.push(chunk);
268+
len += chunk.len();
264269
}
265270
pos = end_pos;
266271
}
@@ -269,11 +274,12 @@ impl Source for ReplaceSource {
269274
while replacement_idx < self.replacements.len() {
270275
let content =
271276
unsafe { &self.replacements.get_unchecked(replacement_idx).content };
272-
rope.push(content);
277+
chunks.push(content);
278+
len += content.len();
273279
replacement_idx += 1;
274280
}
275281

276-
rope
282+
(chunks, len)
277283
}
278284

279285
fn buffer(&self) -> Cow<[u8]> {
@@ -334,13 +340,13 @@ impl Source for ReplaceSource {
334340
}
335341

336342
fn write_to_string(&self, string: &mut String) {
337-
for chunk in self.rope() {
343+
for chunk in self.rope().0 {
338344
string.push_str(chunk);
339345
}
340346
}
341347

342348
fn to_writer(&self, writer: &mut dyn std::io::Write) -> std::io::Result<()> {
343-
for text in self.rope() {
349+
for text in self.rope().0 {
344350
writer.write_all(text.as_bytes())?;
345351
}
346352
Ok(())

src/source.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ pub trait Source:
115115
fn source(&self) -> SourceValue;
116116

117117
/// Return a lightweight "rope" view of the source as borrowed string slices.
118-
fn rope(&self) -> Vec<&str>;
118+
fn rope(&self) -> (Vec<&str>, usize);
119119

120120
/// Get the source buffer.
121121
fn buffer(&self) -> Cow<[u8]>;
@@ -152,7 +152,7 @@ impl Source for BoxSource {
152152
self.as_ref().source()
153153
}
154154

155-
fn rope(&self) -> Vec<&str> {
155+
fn rope(&self) -> (Vec<&str>, usize) {
156156
self.as_ref().rope()
157157
}
158158

src/source_map_source.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,8 +94,8 @@ impl Source for SourceMapSource {
9494
SourceValue::String(Cow::Borrowed(&self.value))
9595
}
9696

97-
fn rope(&self) -> Vec<&str> {
98-
vec![self.value.as_ref()]
97+
fn rope(&self) -> (Vec<&str>, usize) {
98+
(vec![self.value.as_ref()], self.value.len())
9999
}
100100

101101
fn buffer(&self) -> Cow<[u8]> {

0 commit comments

Comments
 (0)