Skip to content

Commit 3184f03

Browse files
committed
refactor(frontmatter): Switch to winnow
1 parent a9e120f commit 3184f03

File tree

3 files changed

+28
-19
lines changed

3 files changed

+28
-19
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ url = "2.5.4"
118118
varisat = "0.2.2"
119119
walkdir = "2.5.0"
120120
windows-sys = "0.60"
121+
winnow = "0.7.13"
121122

122123
[workspace.lints.rust]
123124
rust_2018_idioms = "warn" # TODO: could this be removed?
@@ -220,6 +221,7 @@ unicode-width.workspace = true
220221
unicode-xid.workspace = true
221222
url.workspace = true
222223
walkdir.workspace = true
224+
winnow.workspace = true
223225

224226
[target.'cfg(target_has_atomic = "64")'.dependencies]
225227
tracing-chrome.workspace = true

src/cargo/util/frontmatter.rs

Lines changed: 25 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,35 @@ pub struct ScriptSource<'s> {
1010

1111
impl<'s> ScriptSource<'s> {
1212
pub fn parse(input: &'s str) -> CargoResult<Self> {
13+
use winnow::stream::FindSlice as _;
14+
use winnow::stream::Stream as _;
15+
1316
let mut source = Self {
1417
shebang: None,
1518
info: None,
1619
frontmatter: None,
1720
content: input,
1821
};
1922

20-
if let Some(shebang_end) = strip_shebang(source.content) {
21-
let (shebang, content) = source.content.split_at(shebang_end);
22-
source.shebang = Some(shebang);
23-
source.content = content;
24-
}
23+
let mut input = winnow::stream::LocatingSlice::new(input);
2524

26-
let mut rest = source.content;
25+
if let Some(shebang_end) = strip_shebang(input.as_ref()) {
26+
source.shebang = Some(input.next_slice(shebang_end));
27+
source.content = input.as_ref();
28+
}
2729

2830
// Whitespace may precede a frontmatter but must end with a newline
29-
if let Some(nl_end) = strip_ws_lines(rest) {
30-
rest = &rest[nl_end..];
31+
if let Some(nl_end) = strip_ws_lines(input.as_ref()) {
32+
let _ = input.next_slice(nl_end);
3133
}
3234

3335
// Opens with a line that starts with 3 or more `-` followed by an optional identifier
3436
const FENCE_CHAR: char = '-';
35-
let fence_length = rest
37+
let fence_length = input
38+
.as_ref()
3639
.char_indices()
3740
.find_map(|(i, c)| (c != FENCE_CHAR).then_some(i))
38-
.unwrap_or(rest.len());
41+
.unwrap_or_else(|| input.eof_offset());
3942
match fence_length {
4043
0 => {
4144
return Ok(source);
@@ -48,37 +51,40 @@ impl<'s> ScriptSource<'s> {
4851
}
4952
_ => {}
5053
}
51-
let (fence_pattern, rest) = rest.split_at(fence_length);
52-
let Some(info_end_index) = rest.find('\n') else {
54+
let fence_pattern = input.next_slice(fence_length);
55+
let Some(info_nl) = input.find_slice("\n") else {
5356
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
5457
};
55-
let (info, rest) = rest.split_at(info_end_index);
58+
let info = input.next_slice(info_nl.start);
5659
let info = info.trim_matches(is_whitespace);
5760
if !info.is_empty() {
5861
source.info = Some(info);
5962
}
6063

6164
// Ends with a line that starts with a matching number of `-` only followed by whitespace
6265
let nl_fence_pattern = format!("\n{fence_pattern}");
63-
let Some(frontmatter_nl) = rest.find(&nl_fence_pattern) else {
66+
let Some(frontmatter_nl) = input.find_slice(nl_fence_pattern.as_str()) else {
6467
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
6568
};
66-
let frontmatter = &rest[..frontmatter_nl + 1];
69+
let frontmatter = input.next_slice(frontmatter_nl.start + 1);
6770
let frontmatter = frontmatter
6871
.strip_prefix('\n')
6972
.expect("earlier `found` + `split_at` left us here");
7073
source.frontmatter = Some(frontmatter);
71-
let rest = &rest[frontmatter_nl + nl_fence_pattern.len()..];
74+
let _ = input.next_slice(fence_length);
7275

73-
let (after_closing_fence, rest) = rest.split_once("\n").unwrap_or((rest, ""));
76+
let nl = input.find_slice("\n");
77+
let after_closing_fence = input.next_slice(
78+
nl.map(|span| span.end)
79+
.unwrap_or_else(|| input.eof_offset()),
80+
);
7481
let after_closing_fence = after_closing_fence.trim_matches(is_whitespace);
7582
if !after_closing_fence.is_empty() {
7683
// extra characters beyond the original fence pattern, even if they are extra `-`
7784
anyhow::bail!("trailing characters found after frontmatter close");
7885
}
7986

80-
let frontmatter_len = input.len() - rest.len();
81-
source.content = &input[frontmatter_len..];
87+
source.content = input.finish();
8288

8389
let repeat = Self::parse(source.content)?;
8490
if repeat.frontmatter.is_some() {

0 commit comments

Comments
 (0)