Skip to content

Commit e82a4be

Browse files
committed
refactor(toml): Move the parse fn onto ScriptSource
1 parent 7ec1867 commit e82a4be

File tree

1 file changed

+78
-76
lines changed

1 file changed

+78
-76
lines changed

src/cargo/util/toml/embedded.rs

Lines changed: 78 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ pub(super) fn expand_manifest(
2121
path: &std::path::Path,
2222
gctx: &GlobalContext,
2323
) -> CargoResult<String> {
24-
let source = split_source(content)?;
24+
let source = ScriptSource::parse(content)?;
2525
if let Some(frontmatter) = source.frontmatter {
2626
match source.info {
2727
Some("cargo") | None => {}
@@ -196,87 +196,89 @@ struct ScriptSource<'s> {
196196
content: &'s str,
197197
}
198198

199-
fn split_source(input: &str) -> CargoResult<ScriptSource<'_>> {
200-
let mut source = ScriptSource {
201-
shebang: None,
202-
info: None,
203-
frontmatter: None,
204-
content: input,
205-
};
199+
impl<'s> ScriptSource<'s> {
200+
fn parse(input: &'s str) -> CargoResult<Self> {
201+
let mut source = Self {
202+
shebang: None,
203+
info: None,
204+
frontmatter: None,
205+
content: input,
206+
};
207+
208+
// See rust-lang/rust's compiler/rustc_lexer/src/lib.rs's `strip_shebang`
209+
// Shebang must start with `#!` literally, without any preceding whitespace.
210+
// For simplicity we consider any line starting with `#!` a shebang,
211+
// regardless of restrictions put on shebangs by specific platforms.
212+
if let Some(rest) = source.content.strip_prefix("#!") {
213+
// Ok, this is a shebang but if the next non-whitespace token is `[`,
214+
// then it may be valid Rust code, so consider it Rust code.
215+
if rest.trim_start().starts_with('[') {
216+
return Ok(source);
217+
}
206218

207-
// See rust-lang/rust's compiler/rustc_lexer/src/lib.rs's `strip_shebang`
208-
// Shebang must start with `#!` literally, without any preceding whitespace.
209-
// For simplicity we consider any line starting with `#!` a shebang,
210-
// regardless of restrictions put on shebangs by specific platforms.
211-
if let Some(rest) = source.content.strip_prefix("#!") {
212-
// Ok, this is a shebang but if the next non-whitespace token is `[`,
213-
// then it may be valid Rust code, so consider it Rust code.
214-
if rest.trim_start().starts_with('[') {
215-
return Ok(source);
219+
// No other choice than to consider this a shebang.
220+
let newline_end = source
221+
.content
222+
.find('\n')
223+
.map(|pos| pos + 1)
224+
.unwrap_or(source.content.len());
225+
let (shebang, content) = source.content.split_at(newline_end);
226+
source.shebang = Some(shebang);
227+
source.content = content;
216228
}
217229

218-
// No other choice than to consider this a shebang.
219-
let newline_end = source
220-
.content
221-
.find('\n')
222-
.map(|pos| pos + 1)
230+
const FENCE_CHAR: char = '-';
231+
232+
let mut trimmed_content = source.content;
233+
while !trimmed_content.is_empty() {
234+
let c = trimmed_content;
235+
let c = c.trim_start_matches([' ', '\t']);
236+
let c = c.trim_start_matches(['\r', '\n']);
237+
if c == trimmed_content {
238+
break;
239+
}
240+
trimmed_content = c;
241+
}
242+
let fence_end = trimmed_content
243+
.char_indices()
244+
.find_map(|(i, c)| (c != FENCE_CHAR).then_some(i))
223245
.unwrap_or(source.content.len());
224-
let (shebang, content) = source.content.split_at(newline_end);
225-
source.shebang = Some(shebang);
246+
let (fence_pattern, rest) = match fence_end {
247+
0 => {
248+
return Ok(source);
249+
}
250+
1 | 2 => {
251+
anyhow::bail!(
252+
"found {fence_end} `{FENCE_CHAR}` in rust frontmatter, expected at least 3"
253+
)
254+
}
255+
_ => trimmed_content.split_at(fence_end),
256+
};
257+
let (info, content) = rest.split_once("\n").unwrap_or((rest, ""));
258+
let info = info.trim();
259+
if !info.is_empty() {
260+
source.info = Some(info);
261+
}
226262
source.content = content;
227-
}
228263

229-
const FENCE_CHAR: char = '-';
264+
let Some((frontmatter, content)) = source.content.split_once(fence_pattern) else {
265+
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
266+
};
267+
source.frontmatter = Some(frontmatter);
268+
source.content = content;
230269

231-
let mut trimmed_content = source.content;
232-
while !trimmed_content.is_empty() {
233-
let c = trimmed_content;
234-
let c = c.trim_start_matches([' ', '\t']);
235-
let c = c.trim_start_matches(['\r', '\n']);
236-
if c == trimmed_content {
237-
break;
238-
}
239-
trimmed_content = c;
240-
}
241-
let fence_end = trimmed_content
242-
.char_indices()
243-
.find_map(|(i, c)| (c != FENCE_CHAR).then_some(i))
244-
.unwrap_or(source.content.len());
245-
let (fence_pattern, rest) = match fence_end {
246-
0 => {
247-
return Ok(source);
248-
}
249-
1 | 2 => {
250-
anyhow::bail!(
251-
"found {fence_end} `{FENCE_CHAR}` in rust frontmatter, expected at least 3"
252-
)
270+
let (line, content) = source
271+
.content
272+
.split_once("\n")
273+
.unwrap_or((source.content, ""));
274+
let line = line.trim();
275+
if !line.is_empty() {
276+
anyhow::bail!("unexpected trailing content on closing fence: `{line}`");
253277
}
254-
_ => trimmed_content.split_at(fence_end),
255-
};
256-
let (info, content) = rest.split_once("\n").unwrap_or((rest, ""));
257-
let info = info.trim();
258-
if !info.is_empty() {
259-
source.info = Some(info);
260-
}
261-
source.content = content;
278+
source.content = content;
262279

263-
let Some((frontmatter, content)) = source.content.split_once(fence_pattern) else {
264-
anyhow::bail!("no closing `{fence_pattern}` found for frontmatter");
265-
};
266-
source.frontmatter = Some(frontmatter);
267-
source.content = content;
268-
269-
let (line, content) = source
270-
.content
271-
.split_once("\n")
272-
.unwrap_or((source.content, ""));
273-
let line = line.trim();
274-
if !line.is_empty() {
275-
anyhow::bail!("unexpected trailing content on closing fence: `{line}`");
280+
Ok(source)
276281
}
277-
source.content = content;
278-
279-
Ok(source)
280282
}
281283

282284
#[cfg(test)]
@@ -291,7 +293,7 @@ mod test_expand {
291293
fn assert_source(source: &str, expected: impl IntoData) {
292294
use std::fmt::Write as _;
293295

294-
let actual = match split_source(source) {
296+
let actual = match ScriptSource::parse(source) {
295297
Ok(actual) => actual,
296298
Err(err) => panic!("unexpected err: {err}"),
297299
};
@@ -497,7 +499,7 @@ content: "\nfn main() {}"
497499
#[test]
498500
fn split_too_few_dashes() {
499501
assert_err(
500-
split_source(
502+
ScriptSource::parse(
501503
r#"#!/usr/bin/env cargo
502504
--
503505
[dependencies]
@@ -513,7 +515,7 @@ fn main() {}
513515
#[test]
514516
fn split_mismatched_dashes() {
515517
assert_err(
516-
split_source(
518+
ScriptSource::parse(
517519
r#"#!/usr/bin/env cargo
518520
---
519521
[dependencies]
@@ -529,7 +531,7 @@ fn main() {}
529531
#[test]
530532
fn split_missing_close() {
531533
assert_err(
532-
split_source(
534+
ScriptSource::parse(
533535
r#"#!/usr/bin/env cargo
534536
---
535537
[dependencies]

0 commit comments

Comments
 (0)