mirror of
https://github.com/rust-lang/cargo.git
synced 2025-10-01 11:30:39 +00:00
refactor(frontmatter): Switch to winnow
This commit is contained in:
parent
a9e120f95e
commit
3184f03ef3
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -399,6 +399,7 @@ dependencies = [
|
|||||||
"url",
|
"url",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"windows-sys 0.60.2",
|
"windows-sys 0.60.2",
|
||||||
|
"winnow",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -118,6 +118,7 @@ url = "2.5.4"
|
|||||||
varisat = "0.2.2"
|
varisat = "0.2.2"
|
||||||
walkdir = "2.5.0"
|
walkdir = "2.5.0"
|
||||||
windows-sys = "0.60"
|
windows-sys = "0.60"
|
||||||
|
winnow = "0.7.13"
|
||||||
|
|
||||||
[workspace.lints.rust]
|
[workspace.lints.rust]
|
||||||
rust_2018_idioms = "warn" # TODO: could this be removed?
|
rust_2018_idioms = "warn" # TODO: could this be removed?
|
||||||
@ -220,6 +221,7 @@ unicode-width.workspace = true
|
|||||||
unicode-xid.workspace = true
|
unicode-xid.workspace = true
|
||||||
url.workspace = true
|
url.workspace = true
|
||||||
walkdir.workspace = true
|
walkdir.workspace = true
|
||||||
|
winnow.workspace = true
|
||||||
|
|
||||||
[target.'cfg(target_has_atomic = "64")'.dependencies]
|
[target.'cfg(target_has_atomic = "64")'.dependencies]
|
||||||
tracing-chrome.workspace = true
|
tracing-chrome.workspace = true
|
||||||
|
@ -10,6 +10,9 @@ pub struct ScriptSource<'s> {
|
|||||||
|
|
||||||
impl<'s> ScriptSource<'s> {
|
impl<'s> ScriptSource<'s> {
|
||||||
pub fn parse(input: &'s str) -> CargoResult<Self> {
|
pub fn parse(input: &'s str) -> CargoResult<Self> {
|
||||||
|
use winnow::stream::FindSlice as _;
|
||||||
|
use winnow::stream::Stream as _;
|
||||||
|
|
||||||
let mut source = Self {
|
let mut source = Self {
|
||||||
shebang: None,
|
shebang: None,
|
||||||
info: None,
|
info: None,
|
||||||
@ -17,25 +20,25 @@ impl<'s> ScriptSource<'s> {
|
|||||||
content: input,
|
content: input,
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(shebang_end) = strip_shebang(source.content) {
|
let mut input = winnow::stream::LocatingSlice::new(input);
|
||||||
let (shebang, content) = source.content.split_at(shebang_end);
|
|
||||||
source.shebang = Some(shebang);
|
if let Some(shebang_end) = strip_shebang(input.as_ref()) {
|
||||||
source.content = content;
|
source.shebang = Some(input.next_slice(shebang_end));
|
||||||
|
source.content = input.as_ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut rest = source.content;
|
|
||||||
|
|
||||||
// Whitespace may precede a frontmatter but must end with a newline
|
// Whitespace may precede a frontmatter but must end with a newline
|
||||||
if let Some(nl_end) = strip_ws_lines(rest) {
|
if let Some(nl_end) = strip_ws_lines(input.as_ref()) {
|
||||||
rest = &rest[nl_end..];
|
let _ = input.next_slice(nl_end);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opens with a line that starts with 3 or more `-` followed by an optional identifier
|
// Opens with a line that starts with 3 or more `-` followed by an optional identifier
|
||||||
const FENCE_CHAR: char = '-';
|
const FENCE_CHAR: char = '-';
|
||||||
let fence_length = rest
|
let fence_length = input
|
||||||
|
.as_ref()
|
||||||
.char_indices()
|
.char_indices()
|
||||||
.find_map(|(i, c)| (c != FENCE_CHAR).then_some(i))
|
.find_map(|(i, c)| (c != FENCE_CHAR).then_some(i))
|
||||||
.unwrap_or(rest.len());
|
.unwrap_or_else(|| input.eof_offset());
|
||||||
match fence_length {
|
match fence_length {
|
||||||
0 => {
|
0 => {
|
||||||
return Ok(source);
|
return Ok(source);
|
||||||
@ -48,11 +51,11 @@ impl<'s> ScriptSource<'s> {
|
|||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
let (fence_pattern, rest) = rest.split_at(fence_length);
|
let fence_pattern = input.next_slice(fence_length);
|
||||||
let Some(info_end_index) = rest.find('\n') else {
|
let Some(info_nl) = input.find_slice("\n") else {
|
||||||
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
|
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
|
||||||
};
|
};
|
||||||
let (info, rest) = rest.split_at(info_end_index);
|
let info = input.next_slice(info_nl.start);
|
||||||
let info = info.trim_matches(is_whitespace);
|
let info = info.trim_matches(is_whitespace);
|
||||||
if !info.is_empty() {
|
if !info.is_empty() {
|
||||||
source.info = Some(info);
|
source.info = Some(info);
|
||||||
@ -60,25 +63,28 @@ impl<'s> ScriptSource<'s> {
|
|||||||
|
|
||||||
// Ends with a line that starts with a matching number of `-` only followed by whitespace
|
// Ends with a line that starts with a matching number of `-` only followed by whitespace
|
||||||
let nl_fence_pattern = format!("\n{fence_pattern}");
|
let nl_fence_pattern = format!("\n{fence_pattern}");
|
||||||
let Some(frontmatter_nl) = rest.find(&nl_fence_pattern) else {
|
let Some(frontmatter_nl) = input.find_slice(nl_fence_pattern.as_str()) else {
|
||||||
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
|
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
|
||||||
};
|
};
|
||||||
let frontmatter = &rest[..frontmatter_nl + 1];
|
let frontmatter = input.next_slice(frontmatter_nl.start + 1);
|
||||||
let frontmatter = frontmatter
|
let frontmatter = frontmatter
|
||||||
.strip_prefix('\n')
|
.strip_prefix('\n')
|
||||||
.expect("earlier `found` + `split_at` left us here");
|
.expect("earlier `found` + `split_at` left us here");
|
||||||
source.frontmatter = Some(frontmatter);
|
source.frontmatter = Some(frontmatter);
|
||||||
let rest = &rest[frontmatter_nl + nl_fence_pattern.len()..];
|
let _ = input.next_slice(fence_length);
|
||||||
|
|
||||||
let (after_closing_fence, rest) = rest.split_once("\n").unwrap_or((rest, ""));
|
let nl = input.find_slice("\n");
|
||||||
|
let after_closing_fence = input.next_slice(
|
||||||
|
nl.map(|span| span.end)
|
||||||
|
.unwrap_or_else(|| input.eof_offset()),
|
||||||
|
);
|
||||||
let after_closing_fence = after_closing_fence.trim_matches(is_whitespace);
|
let after_closing_fence = after_closing_fence.trim_matches(is_whitespace);
|
||||||
if !after_closing_fence.is_empty() {
|
if !after_closing_fence.is_empty() {
|
||||||
// extra characters beyond the original fence pattern, even if they are extra `-`
|
// extra characters beyond the original fence pattern, even if they are extra `-`
|
||||||
anyhow::bail!("trailing characters found after frontmatter close");
|
anyhow::bail!("trailing characters found after frontmatter close");
|
||||||
}
|
}
|
||||||
|
|
||||||
let frontmatter_len = input.len() - rest.len();
|
source.content = input.finish();
|
||||||
source.content = &input[frontmatter_len..];
|
|
||||||
|
|
||||||
let repeat = Self::parse(source.content)?;
|
let repeat = Self::parse(source.content)?;
|
||||||
if repeat.frontmatter.is_some() {
|
if repeat.frontmatter.is_some() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user