Skip to content

Commit e85b408

Browse files
authored
Store comments as u8s instead of Strings (#839)
1 parent 05afb6d commit e85b408

File tree

6 files changed

+41
-34
lines changed

6 files changed

+41
-34
lines changed

librubyfmt/src/comment_block.rs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::borrow::Cow;
2+
use std::io::BufRead;
13
use std::ops::Range;
24

35
use crate::line_tokens::ConcreteLineToken;
@@ -7,19 +9,19 @@ use crate::util::get_indent;
79
#[derive(Clone, Debug)]
810
pub struct CommentBlock {
911
span: Range<LineNumber>,
10-
comments: Vec<String>,
12+
comments: Vec<Cow<'static, [u8]>>,
1113
}
1214

1315
impl CommentBlock {
14-
pub fn new(span: Range<LineNumber>, comments: Vec<String>) -> Self {
16+
pub fn new(span: Range<LineNumber>, comments: Vec<Cow<'static, [u8]>>) -> Self {
1517
CommentBlock { span, comments }
1618
}
1719

1820
pub fn following_line_number(&self) -> LineNumber {
1921
self.span.end
2022
}
2123

22-
pub fn add_line(&mut self, line: String) {
24+
pub fn add_line(&mut self, line: Cow<'static, [u8]>) {
2325
self.span.end += 1;
2426
self.comments.push(line);
2527
}
@@ -30,7 +32,7 @@ impl CommentBlock {
3032

3133
comments.into_iter().enumerate().flat_map(move |(i, c)| {
3234
if c.is_empty() {
33-
// Empty strings represent blank lines
35+
// Empty vecs represent blank lines
3436
// If this is a trailing empty comment (at the end), keep it as an empty Comment token
3537
// to bypass the HardNewLine deduplication logic. Otherwise convert to just HardNewLine.
3638
if i == len - 1 {
@@ -53,12 +55,18 @@ impl CommentBlock {
5355
}
5456

5557
pub fn apply_spaces(mut self, indent_depth: ColNumber) -> Self {
58+
if indent_depth == 0 {
59+
return self;
60+
}
61+
5662
let indent = get_indent(indent_depth as usize);
5763
for comment in &mut self.comments {
58-
// Ignore empty strings -- these represent blank lines between
64+
// Ignore empty vecs -- these represent blank lines between
5965
// groups of comments
60-
if !comment.is_empty() && !comment.starts_with("=begin") {
61-
comment.insert_str(0, &indent);
66+
if !comment.is_empty() && !comment.starts_with(b"=begin") {
67+
comment
68+
.to_mut()
69+
.splice(0..0, indent.as_bytes().iter().copied());
6270
}
6371
}
6472
self

librubyfmt/src/file_comments.rs

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1+
use std::borrow::Cow;
2+
use std::io::BufRead;
3+
14
use memchr::memchr_iter;
25

36
use crate::comment_block::CommentBlock;
47
use crate::parser_state::line_difference_requires_newline;
58
use crate::types::{LineNumber, SourceOffset};
6-
use crate::util::u8_to_string;
79

810
/// A vector of offsets in the source code where lines start, which
911
/// we use to detect what line a given offset is one.
@@ -51,7 +53,7 @@ impl LineIndex {
5153
pub struct FileComments {
5254
start_of_file_contiguous_comment_lines: Option<CommentBlock>,
5355
/// A list of comments, sorted in order by `LineNumber`
54-
other_comments: Vec<(LineNumber, String)>,
56+
other_comments: Vec<(LineNumber, Vec<u8>)>,
5557
/// Sorted list of line numbers that contain Ruby code (not comments/blank)
5658
lines_with_ruby: Vec<LineNumber>,
5759
last_lineno: LineNumber,
@@ -96,7 +98,7 @@ impl FileComments {
9698
for comment in comments {
9799
file_comments.push_comment(
98100
line_index.get_line_number(comment.location().start_offset()) as u64,
99-
u8_to_string(comment.text().trim_ascii_end()),
101+
comment.text().trim_ascii_end().to_vec(),
100102
);
101103
file_comments
102104
.comment_start_offsets
@@ -146,7 +148,7 @@ impl FileComments {
146148
/// Add a new comment. If the beginning of this file is a comment block,
147149
/// each of those comment lines must be pushed before any other line, or
148150
/// the end of the block from the start of the file will be incorrectly calculated.
149-
fn push_comment(&mut self, line_number: u64, l: String) {
151+
fn push_comment(&mut self, line_number: u64, l: Vec<u8>) {
150152
match (
151153
&mut self.start_of_file_contiguous_comment_lines,
152154
line_number,
@@ -158,10 +160,10 @@ impl FileComments {
158160
otherwise we won't know where the last line is",
159161
);
160162
self.start_of_file_contiguous_comment_lines =
161-
Some(CommentBlock::new(1..2, vec![l]));
163+
Some(CommentBlock::new(1..2, vec![l.into()]));
162164
}
163165
(Some(sled), _) if sled.following_line_number() == line_number => {
164-
sled.add_line(l);
166+
sled.add_line(l.into());
165167
}
166168
_ => {
167169
debug_assert!(
@@ -220,21 +222,22 @@ impl FileComments {
220222
.other_comments
221223
.partition_point(|(ln, _)| *ln <= line_number);
222224

223-
let mut comment_block_with_spaces: Vec<String> = Vec::new();
225+
let mut comment_block_with_spaces = Vec::new();
224226
let mut last_line = None;
225227

226228
if line_difference_requires_newline(
227229
self.other_comments.first().unwrap().0,
228230
starting_line_number,
229231
) {
230-
comment_block_with_spaces.push(String::new());
232+
comment_block_with_spaces.push(b"".into());
231233
}
232234

233235
for (index, comment_contents) in self.other_comments.drain(..split_point) {
236+
let comment_contents: Cow<'_, [u8]> = Cow::Owned(comment_contents);
234237
if let Some(last_line) = last_line
235238
&& line_difference_requires_newline(index, last_line)
236239
{
237-
comment_block_with_spaces.push(String::new());
240+
comment_block_with_spaces.push(b"".into());
238241
}
239242
let line_count = comment_contents.lines().count() as u64;
240243
last_line = Some(index + line_count - 1);
@@ -243,7 +246,7 @@ impl FileComments {
243246

244247
if line_number > last_line.unwrap() + 1 {
245248
last_line = Some(line_number);
246-
comment_block_with_spaces.push(String::new());
249+
comment_block_with_spaces.push(b"".into());
247250
}
248251

249252
Some((

librubyfmt/src/line_tokens.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub enum ConcreteLineToken<'src> {
6969
},
7070
SingleSlash,
7171
Comment {
72-
contents: String,
72+
contents: Cow<'src, [u8]>,
7373
},
7474
Delim {
7575
contents: &'static str,
@@ -127,7 +127,7 @@ impl<'src> ConcreteLineToken<'src> {
127127
Cow::Owned(s) => Cow::Owned(s.into_bytes()),
128128
},
129129
Self::SingleSlash => Cow::Borrowed(b"\\"),
130-
Self::Comment { contents } => Cow::Owned(contents.into()),
130+
Self::Comment { contents } => contents,
131131
Self::Delim { contents } => Cow::Borrowed(contents.as_bytes()),
132132
Self::End => Cow::Borrowed(b"end"),
133133
Self::HeredocClose { symbol } => Cow::Owned(symbol.into()),
@@ -157,9 +157,11 @@ impl<'src> ConcreteLineToken<'src> {
157157
MethodName { name: op } => op.len(),
158158
DirectPart { part } => part.len(),
159159
LTStringContent { content } => content.len(),
160-
Comment { contents }
161-
| HeredocClose { symbol: contents }
162-
| RawHeredocContent { content: contents } => contents.len(),
160+
Comment { contents } => contents.len(),
161+
HeredocClose { symbol: contents } | RawHeredocContent { content: contents } => {
162+
contents.len()
163+
}
164+
163165
HardNewLine | Comma | Space | Dot | OpenSquareBracket | CloseSquareBracket
164166
| OpenCurlyBracket | CloseCurlyBracket | OpenParen | CloseParen | SingleSlash
165167
| DoubleQuote => 1,

librubyfmt/src/parser_state.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -471,7 +471,7 @@ impl<'src> ParserState<'src> {
471471
&& let Some(comments) = self.comments_to_insert.as_mut()
472472
&& comments.line_count() > 0
473473
{
474-
comments.add_line("".to_string());
474+
comments.add_line(b"".into());
475475
}
476476
self.on_line(self.current_orig_line_number + 1);
477477
}

librubyfmt/src/render_queue_writer.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -65,14 +65,12 @@ impl<'src> RenderQueueWriter<'src> {
6565
contents,
6666
}) => {
6767
if !contents.is_empty() {
68-
let new_contents = format!(
69-
"{}{}",
70-
get_indent(accum.additional_indent as usize * 2),
71-
contents
72-
);
68+
let indent = get_indent(accum.additional_indent as usize * 2);
69+
let mut new_contents = indent.as_bytes().to_vec();
70+
new_contents.extend_from_slice(contents);
7371
next_token = ConcreteLineTokenAndTargets::ConcreteLineToken(
7472
ConcreteLineToken::Comment {
75-
contents: new_contents,
73+
contents: new_contents.into(),
7674
},
7775
)
7876
}

librubyfmt/src/util.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,10 @@ pub fn get_indent(depth: usize) -> Cow<'static, str> {
1717
}
1818
}
1919

20-
pub fn u8_to_str(arr: &[u8]) -> &str {
20+
fn u8_to_str(arr: &[u8]) -> &str {
2121
std::str::from_utf8(arr).unwrap()
2222
}
2323

24-
pub fn u8_to_string(arr: &[u8]) -> String {
25-
u8_to_str(arr).to_string()
26-
}
27-
2824
pub fn loc_to_str(loc: Location<'_>) -> &str {
2925
u8_to_str(loc.as_slice())
3026
}

0 commit comments

Comments
 (0)