Skip to content

Commit b2bcdc9

Browse files
authored
Update CLI machinery to use &[u8] (#841)
1 parent f9fdbf1 commit b2bcdc9

3 files changed

Lines changed: 25 additions & 36 deletions

File tree

benches/formatting.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
22
use std::fs;
33
use std::path::Path;
44

5-
fn format_with_prism(source: &str) {
5+
fn format_with_prism(source: &[u8]) {
66
rubyfmt::format_buffer(source).expect("formatting failed");
77
}
88

9-
fn collect_fixtures(dir: &Path) -> Vec<(String, String)> {
9+
fn collect_fixtures(dir: &Path) -> Vec<(String, Vec<u8>)> {
1010
let mut fixtures = Vec::new();
1111
let base = Path::new("fixtures/large");
1212

@@ -23,7 +23,7 @@ fn collect_fixtures(dir: &Path) -> Vec<(String, String)> {
2323
.to_string_lossy()
2424
.trim_end_matches("_actual.rb")
2525
.to_string();
26-
let source = fs::read_to_string(&path).expect("failed to read file");
26+
let source = fs::read(&path).expect("failed to read file");
2727
fixtures.push((name, source));
2828
}
2929
}
@@ -41,7 +41,7 @@ fn bench_stress_tests(c: &mut Criterion) {
4141
];
4242

4343
for (name, path) in files {
44-
let source = fs::read_to_string(path).expect("failed to read file");
44+
let source = fs::read(path).expect("failed to read file");
4545
group.bench_with_input(BenchmarkId::new("prism", name), &source, |b, source| {
4646
b.iter(|| format_with_prism(source));
4747
});

librubyfmt/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22
#![allow(clippy::upper_case_acronyms, clippy::enum_variant_names)]
33

44
use std::io::{Cursor, Write};
5-
use std::str;
65

76
#[cfg(all(feature = "use_jemalloc", not(target_env = "msvc")))]
87
#[global_allocator]
@@ -61,11 +60,11 @@ pub enum FormatError {
6160
DiffDetected = 5,
6261
}
6362

64-
pub fn format_buffer(buf: &str) -> Result<Vec<u8>, RichFormatError> {
63+
pub fn format_buffer(buf: &[u8]) -> Result<Vec<u8>, RichFormatError> {
6564
let out_data = vec![];
6665
let mut output = Cursor::new(out_data);
6766

68-
let parse_result = ruby_prism::parse(buf.as_bytes());
67+
let parse_result = ruby_prism::parse(buf);
6968
if parse_result.errors().next().is_some() {
7069
return Err(RichFormatError::SyntaxError);
7170
}
@@ -75,7 +74,7 @@ pub fn format_buffer(buf: &str) -> Result<Vec<u8>, RichFormatError> {
7574
&mut output,
7675
parse_result.node(),
7776
parse_result.comments(),
78-
buf.as_bytes(),
77+
buf,
7978
end_data,
8079
)?;
8180

src/main.rs

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use regex::Regex;
77
use rubyfmt::init_logger;
88
use similar::TextDiff;
99
use std::ffi::OsStr;
10-
use std::fs::{File, OpenOptions, read_to_string};
10+
use std::fs::{File, OpenOptions, read};
1111
use std::io::{self, BufRead, BufReader, IsTerminal, Read, Write};
1212
use std::path::Path;
1313
use std::process::{Command, exit};
@@ -155,24 +155,17 @@ fn rubyfmt_string(
155155
header_opt_out,
156156
..
157157
}: &CommandlineOpts,
158-
buffer: &str,
158+
buffer: &[u8],
159159
) -> Result<Option<Vec<u8>>, rubyfmt::RichFormatError> {
160160
if header_opt_in || header_opt_out {
161161
// Only look at the first 500 bytes for the magic header.
162-
// This is for performance
163-
let mut slice = buffer;
164-
let mut slice_size = 500;
165-
let blength = buffer.len();
166-
167-
if blength > slice_size {
168-
while !buffer.is_char_boundary(slice_size) && slice_size < blength {
169-
slice_size += 1;
170-
}
171-
slice = &buffer[..slice_size]
172-
}
162+
// This is for performance. Use lossy UTF-8 conversion since the
163+
// magic comment is always ASCII.
164+
let slice_size = buffer.len().min(500);
165+
let slice = String::from_utf8_lossy(&buffer[..slice_size]);
173166

174167
let matched = MAGIC_COMMENT_REGEX
175-
.captures(slice)
168+
.captures(&slice)
176169
.and_then(|c| c.name("enabled"))
177170
.map(|s| s.as_str());
178171

@@ -260,10 +253,10 @@ fn get_command_line_options() -> CommandlineOpts {
260253
}
261254
}
262255

263-
fn iterate_input_files(opts: &CommandlineOpts, f: &dyn Fn((&Path, &String))) {
256+
fn iterate_input_files(opts: &CommandlineOpts, f: InputFunc) {
264257
if opts.include_paths.is_empty() {
265258
// If not include paths are present, assume user is passing via STDIN
266-
let mut buffer = String::new();
259+
let mut buffer = Vec::new();
267260

268261
if io::stdin().is_terminal() {
269262
// Call executable with `--help` args to print help statement
@@ -274,15 +267,15 @@ fn iterate_input_files(opts: &CommandlineOpts, f: &dyn Fn((&Path, &String))) {
274267
}
275268

276269
io::stdin()
277-
.read_to_string(&mut buffer)
270+
.read_to_end(&mut buffer)
278271
.expect("reading from stdin to not fail");
279272

280273
let path = if let Some(stdin_filepath) = &opts.stdin_filepath {
281274
let path = Path::new(stdin_filepath);
282275
if is_path_ignored(path, opts.include_gitignored) {
283276
// Print unchanged output for ignored files unless we're in check mode
284277
if !opts.check {
285-
puts_stdout(buffer.as_bytes());
278+
puts_stdout(&buffer);
286279
}
287280
return;
288281
}
@@ -308,9 +301,7 @@ fn iterate_input_files(opts: &CommandlineOpts, f: &dyn Fn((&Path, &String))) {
308301
match result {
309302
Ok(pp) => {
310303
let file_path = pp.path();
311-
let buffer_res = read_to_string(file_path);
312-
313-
match buffer_res {
304+
match read(file_path) {
314305
Ok(buffer) => f((file_path, &buffer)),
315306
Err(e) => handle_execution_error(
316307
opts,
@@ -332,9 +323,7 @@ fn iterate_input_files(opts: &CommandlineOpts, f: &dyn Fn((&Path, &String))) {
332323
if file_path.is_file()
333324
&& file_path.extension().and_then(OsStr::to_str) == Some("rb")
334325
{
335-
let buffer_res = read_to_string(file_path);
336-
337-
match buffer_res {
326+
match read(file_path) {
338327
Ok(buffer) => f((file_path, &buffer)),
339328
Err(e) => handle_execution_error(
340329
opts,
@@ -350,7 +339,8 @@ fn iterate_input_files(opts: &CommandlineOpts, f: &dyn Fn((&Path, &String))) {
350339
}
351340
}
352341

353-
type FormattingFunc<'a> = &'a dyn Fn((&Path, &String, Option<Vec<u8>>));
342+
type InputFunc<'a> = &'a dyn Fn((&Path, &[u8]));
343+
type FormattingFunc<'a> = &'a dyn Fn((&Path, &[u8], Option<Vec<u8>>));
354344

355345
fn iterate_formatted(opts: &CommandlineOpts, f: FormattingFunc) {
356346
iterate_input_files(
@@ -392,7 +382,7 @@ fn main() {
392382
&|(file_path, before)| match rubyfmt_string(&opts, before) {
393383
Ok(None) => {}
394384
Ok(Some(fmtted)) => {
395-
let diff = TextDiff::from_lines(before.as_bytes(), &fmtted);
385+
let diff = TextDiff::from_lines(before, &fmtted);
396386
let path_string = file_path.to_str().unwrap();
397387
text_diffs.lock().unwrap().push(format!(
398388
"{}",
@@ -434,7 +424,7 @@ fn main() {
434424
iterate_formatted(&opts, &|(file_path, before, after)| match after {
435425
None => {}
436426
Some(fmtted) => {
437-
if fmtted.ne(before.as_bytes()) {
427+
if fmtted.ne(before) {
438428
let file_write = OpenOptions::new()
439429
.write(true)
440430
.truncate(true)
@@ -455,7 +445,7 @@ fn main() {
455445

456446
_ => iterate_formatted(&opts, &|(_, before, after)| match after {
457447
Some(fmtted) => puts_stdout(&fmtted),
458-
None => puts_stdout(before.as_bytes()),
448+
None => puts_stdout(before),
459449
}),
460450
}
461451
}

0 commit comments

Comments
 (0)