Skip to content

Commit b4c9684

Browse files
committed
refactor(embedded): Pull in parser from rust-lang/rust#137193
1 parent 02bcb61 commit b4c9684

File tree

1 file changed

+46
-35
lines changed

1 file changed

+46
-35
lines changed

src/cargo/util/toml/embedded.rs

Lines changed: 46 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -78,59 +78,70 @@ impl<'s> ScriptSource<'s> {
7878
source.content = content;
7979
}
8080

81-
const FENCE_CHAR: char = '-';
82-
8381
let mut rest = source.content;
84-
while !rest.is_empty() {
85-
let without_spaces = rest.trim_start_matches([' ', '\t']);
86-
let without_nl = without_spaces.trim_start_matches(['\r', '\n']);
87-
if without_nl == rest {
88-
// nothing trimmed
89-
break;
90-
} else if without_nl == without_spaces {
91-
// frontmatter must come after a newline
82+
83+
// Whitespace may precede a frontmatter but must end with a newline
84+
const WHITESPACE: [char; 4] = [' ', '\t', '\r', '\n'];
85+
let trimmed = rest.trim_start_matches(WHITESPACE);
86+
if trimmed.len() != rest.len() {
87+
let trimmed_len = rest.len() - trimmed.len();
88+
let last_trimmed_index = trimmed_len - 1;
89+
if rest.as_bytes()[last_trimmed_index] != b'\n' {
90+
// either not a frontmatter or invalid opening
9291
return Ok(source);
9392
}
94-
rest = without_nl;
9593
}
96-
let fence_end = rest
94+
rest = trimmed;
95+
96+
// Opens with a line that starts with 3 or more `-` followed by an optional identifier
97+
const FENCE_CHAR: char = '-';
98+
let fence_length = rest
9799
.char_indices()
98100
.find_map(|(i, c)| (c != FENCE_CHAR).then_some(i))
99-
.unwrap_or(source.content.len());
100-
let (fence_pattern, rest) = match fence_end {
101+
.unwrap_or(rest.len());
102+
match fence_length {
101103
0 => {
102104
return Ok(source);
103105
}
104106
1 | 2 => {
107+
// either not a frontmatter or invalid frontmatter opening
105108
anyhow::bail!(
106-
"found {fence_end} `{FENCE_CHAR}` in rust frontmatter, expected at least 3"
109+
"found {fence_length} `{FENCE_CHAR}` in rust frontmatter, expected at least 3"
107110
)
108111
}
109-
_ => rest.split_at(fence_end),
112+
_ => {}
113+
}
114+
let (fence_pattern, rest) = rest.split_at(fence_length);
115+
let Some(info_end_index) = rest.find('\n') else {
116+
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
110117
};
111-
let nl_fence_pattern = format!("\n{fence_pattern}");
112-
let (info, content) = rest.split_once("\n").unwrap_or((rest, ""));
113-
let info = info.trim();
118+
let (info, rest) = rest.split_at(info_end_index);
119+
let info = info.trim_matches(WHITESPACE);
114120
if !info.is_empty() {
115121
source.info = Some(info);
116122
}
117-
source.content = content;
123+
let rest = rest
124+
.strip_prefix('\n')
125+
.expect("earlier `found` + `split_at` left us here");
118126

119-
let Some(frontmatter_nl) = source.content.find(&nl_fence_pattern) else {
127+
// Ends with a line that starts with a matching number of `-` only followed by whitespace
128+
let nl_fence_pattern = format!("\n{fence_pattern}");
129+
let Some(frontmatter_nl) = rest.find(&nl_fence_pattern) else {
120130
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
121131
};
122-
source.frontmatter = Some(&source.content[..frontmatter_nl + 1]);
123-
source.content = &source.content[frontmatter_nl + nl_fence_pattern.len()..];
124-
125-
let (line, content) = source
126-
.content
127-
.split_once("\n")
128-
.unwrap_or((source.content, ""));
129-
let line = line.trim();
130-
if !line.is_empty() {
131-
anyhow::bail!("unexpected trailing content on closing fence: `{line}`");
132+
let frontmatter = &rest[..frontmatter_nl + 1];
133+
let rest = &rest[frontmatter_nl + nl_fence_pattern.len()..];
134+
source.frontmatter = Some(frontmatter);
135+
136+
let (after_closing_fence, rest) = rest.split_once("\n").unwrap_or((rest, ""));
137+
let after_closing_fence = after_closing_fence.trim_matches(WHITESPACE);
138+
if !after_closing_fence.is_empty() {
139+
// extra characters beyond the original fence pattern, even if they are extra `-`
140+
anyhow::bail!("trailing characters found after frontmatter close");
132141
}
133-
source.content = content;
142+
143+
let frontmatter_len = input.len() - rest.len();
144+
source.content = &input[frontmatter_len..];
134145

135146
Ok(source)
136147
}
@@ -466,7 +477,7 @@ content: "\n// infostrings can only be a single identifier.\n\nfn main() {}\n"
466477
fn main() {}
467478
"#,
468479
),
469-
str!["unexpected trailing content on closing fence: `-`"],
480+
str!["trailing characters found after frontmatter close"],
470481
);
471482
}
472483

@@ -905,7 +916,7 @@ content: "\nfn main() {}\n"
905916
fn main() {}
906917
"#,
907918
),
908-
str!["unexpected trailing content on closing fence: `--`"],
919+
str!["trailing characters found after frontmatter close"],
909920
);
910921
}
911922

@@ -942,7 +953,7 @@ time="0.1.25"
942953
fn main() {}
943954
"#,
944955
),
945-
str!["unexpected trailing content on closing fence: `-`"],
956+
str!["trailing characters found after frontmatter close"],
946957
);
947958
}
948959

0 commit comments

Comments
 (0)