use crate::{
Color, CrateType, Emit, ErrorFormat, Flag, LibraryKind, LinkKind, LinkModifier,
LinkModifierPrefix, LintLevel, RustFlags,
};
use std::ffi::OsString;
use std::path::PathBuf;
#[track_caller]
fn test(encoded: &str, expected: &[Flag]) {
let mut iterator = RustFlags {
encoded: encoded.to_owned(),
pos: 0,
repeat: None,
short: false,
};
let mut flags = Vec::new();
for expected in expected {
let next = iterator.next();
assert_eq!(Some(expected), next.as_ref());
for flag in next.unwrap() {
flags.push(flag.to_string_lossy().into_owned());
}
}
assert_eq!(None, iterator.next());
let mut iterator = RustFlags {
encoded: flags.join("\x1F"),
pos: 0,
repeat: None,
short: false,
};
for expected in expected {
assert_eq!(Some(expected), iterator.next().as_ref());
}
assert_eq!(None, iterator.next());
}
macro_rules! assert_flags {
($string:literal $($more_string:literal)* $(, $expected:expr)* $(,)?) => {{
let encoded = concat!($string $(, '\x1F', $more_string)*);
test(encoded, &[$($expected),*]);
}};
}
#[test]
fn test_empty() {
assert_flags!("");
}
#[test]
fn test_individual() {
assert_flags!("-h", Flag::Help);
assert_flags!("--help", Flag::Help);
assert_flags!(
"--cfg=semver_exempt",
Flag::Cfg {
name: "semver_exempt".to_owned(),
value: None,
},
);
assert_flags!(
"--cfg=feature=\"std\"",
Flag::Cfg {
name: "feature".to_owned(),
value: Some("std".to_owned()),
},
);
assert_flags!(
"--cfg" "semver_exempt",
Flag::Cfg {
name: "semver_exempt".to_owned(),
value: None,
},
);
assert_flags!(
"--cfg" "feature=\"std\"",
Flag::Cfg {
name: "feature".to_owned(),
value: Some("std".to_owned()),
},
);
assert_flags!(
"-L" "PATH",
Flag::LibrarySearchPath {
kind: LibraryKind::All,
path: PathBuf::from("PATH"),
},
);
assert_flags!(
"-L" "native=PATH",
Flag::LibrarySearchPath {
kind: LibraryKind::Native,
path: PathBuf::from("PATH"),
},
);
assert_flags!(
"-l" "NAME",
Flag::Link {
kind: LinkKind::Dylib,
modifiers: Vec::new(),
name: "NAME".to_owned(),
rename: None,
},
);
assert_flags!(
"-l" "static=NAME",
Flag::Link {
kind: LinkKind::Static,
modifiers: Vec::new(),
name: "NAME".to_owned(),
rename: None,
},
);
assert_flags!(
"-l" "static:+bundle,-whole-archive=NAME",
Flag::Link {
kind: LinkKind::Static,
modifiers: vec![
(LinkModifierPrefix::Enable, LinkModifier::Bundle),
(LinkModifierPrefix::Disable, LinkModifier::WholeArchive),
],
name: "NAME".to_owned(),
rename: None,
},
);
assert_flags!(
"-l" "NAME:RENAME",
Flag::Link {
kind: LinkKind::Dylib,
modifiers: Vec::new(),
name: "NAME".to_owned(),
rename: Some("RENAME".to_owned()),
},
);
assert_flags!("--crate-type" "bin", Flag::CrateType(CrateType::Bin));
assert_flags!(
"--crate-type" "lib,staticlib",
Flag::CrateType(CrateType::Lib),
Flag::CrateType(CrateType::Staticlib),
);
assert_flags!("--crate-name" "core", Flag::CrateName("core".to_owned()));
assert_flags!("--edition" "2021", Flag::Edition(2021));
assert_flags!("--emit" "asm", Flag::Emit(Emit::Asm));
assert_flags!(
"--emit" "asm,mir",
Flag::Emit(Emit::Asm),
Flag::Emit(Emit::Mir),
);
assert_flags!("--emit" "unrecognized,mir", Flag::Emit(Emit::Mir));
assert_flags!("--print" "cfg", Flag::Print("cfg".to_owned()));
assert_flags!("-o" "FILENAME", Flag::Out(PathBuf::from("FILENAME")));
assert_flags!("--out-dir" "DIR", Flag::OutDir(PathBuf::from("DIR")));
assert_flags!("--explain" "E0282", Flag::Explain("E0282".to_owned()));
assert_flags!("--test", Flag::Test);
assert_flags!(
"--target" "x86_64-unknown-linux-gnu",
Flag::Target("x86_64-unknown-linux-gnu".to_owned()),
);
assert_flags!("-A" "dead_code", Flag::Allow("dead_code".to_owned()));
assert_flags!("--allow" "dead_code", Flag::Allow("dead_code".to_owned()));
assert_flags!("-W" "dead_code", Flag::Warn("dead_code".to_owned()));
assert_flags!("--warn" "dead_code", Flag::Warn("dead_code".to_owned()));
assert_flags!(
"--force-warn" "dead_code",
Flag::ForceWarn("dead_code".to_owned()),
);
assert_flags!("-D" "dead_code", Flag::Deny("dead_code".to_owned()));
assert_flags!("--deny" "dead_code", Flag::Deny("dead_code".to_owned()));
assert_flags!("-F" "dead_code", Flag::Forbid("dead_code".to_owned()));
assert_flags!("--forbid" "dead_code", Flag::Forbid("dead_code".to_owned()));
assert_flags!("--cap-lints=allow", Flag::CapLints(LintLevel::Allow));
assert_flags!(
"-C" "embed-bitcode",
Flag::Codegen {
opt: "embed-bitcode".to_owned(),
value: None,
},
);
assert_flags!(
"-C" "debuginfo=2",
Flag::Codegen {
opt: "debuginfo".to_owned(),
value: Some("2".to_owned()),
},
);
assert_flags!(
"-g",
Flag::Codegen {
opt: "debuginfo".to_owned(),
value: Some("2".to_owned()),
},
);
assert_flags!(
"-O",
Flag::Codegen {
opt: "opt-level".to_owned(),
value: Some("2".to_owned()),
},
);
assert_flags!("-V", Flag::Version);
assert_flags!("--version", Flag::Version);
assert_flags!("-v", Flag::Verbose);
assert_flags!("--verbose", Flag::Verbose);
assert_flags!(
"--extern" "serde",
Flag::Extern {
name: "serde".to_owned(),
path: None,
},
);
assert_flags!(
"--extern" "serde=target/debug/deps/libserde.rmeta",
Flag::Extern {
name: "serde".to_owned(),
path: Some(PathBuf::from("target/debug/deps/libserde.rmeta")),
},
);
assert_flags!(
"--extern-location" r#"serde=json:{"target":"//third-party:serde"}"#,
Flag::ExternLocation {
name: "serde".to_owned(),
location: OsString::from(r#"json:{"target":"//third-party:serde"}"#),
},
);
assert_flags!(
"--sysroot" ".rustup/toolchains/nightly",
Flag::Sysroot(PathBuf::from(".rustup/toolchains/nightly")),
);
assert_flags!(
"-Z" "unstable-options",
Flag::Z("unstable-options".to_owned()),
);
assert_flags!("--error-format=json", Flag::ErrorFormat(ErrorFormat::Json));
assert_flags!(
"--json" "diagnostic-rendered-ansi",
Flag::Json("diagnostic-rendered-ansi".to_owned()),
);
assert_flags!("--color=always", Flag::Color(Color::Always));
assert_flags!(
"--remap-path-prefix" "FROM=TO",
Flag::RemapPathPrefix {
from: PathBuf::from("FROM"),
to: PathBuf::from("TO"),
},
);
}