1use anyhow::bail;
4use std::path::Path;
5
6use crate::util::SubstrateResult;
7
8pub fn is_non_ascii_name(name: &str) -> bool {
10 name.chars().any(|ch| ch > '\x7f')
11}
12
13pub fn is_keyword(name: &str) -> bool {
15 [
17 "Self", "abstract", "as", "async", "await", "become", "box", "break", "const", "continue",
18 "crate", "do", "dyn", "else", "enum", "extern", "false", "final", "fn", "for", "if",
19 "impl", "in", "let", "loop", "macro", "match", "mod", "move", "mut", "override", "priv",
20 "pub", "ref", "return", "self", "static", "struct", "super", "trait", "true", "try",
21 "type", "typeof", "unsafe", "unsized", "use", "virtual", "where", "while", "yield",
22 ]
23 .contains(&name)
24}
25
26pub fn is_windows_reserved(name: &str) -> bool {
28 [
29 "con", "prn", "aux", "nul", "com1", "com2", "com3", "com4", "com5", "com6", "com7", "com8",
30 "com9", "lpt1", "lpt2", "lpt3", "lpt4", "lpt5", "lpt6", "lpt7", "lpt8", "lpt9",
31 ]
32 .contains(&name.to_ascii_lowercase().as_str())
33}
34
35pub fn is_conflicting_artifact_name(name: &str) -> bool {
37 ["deps", "examples", "build", "incremental"].contains(&name)
38}
39
40pub fn validate_package_name(name: &str, what: &str, help: &str) -> SubstrateResult<()> {
47 let mut chars = name.chars();
48 if let Some(ch) = chars.next() {
49 if ch.is_digit(10) {
50 bail!(
52 "the name `{}` cannot be used as a {}, \
53 the name cannot start with a digit{}",
54 name,
55 what,
56 help
57 );
58 }
59 if !(unicode_xid::UnicodeXID::is_xid_start(ch) || ch == '_') {
60 bail!(
61 "invalid character `{}` in {}: `{}`, \
62 the first character must be a Unicode XID start character \
63 (most letters or `_`){}",
64 ch,
65 what,
66 name,
67 help
68 );
69 }
70 }
71 for ch in chars {
72 if !(unicode_xid::UnicodeXID::is_xid_continue(ch) || ch == '-') {
73 bail!(
74 "invalid character `{}` in {}: `{}`, \
75 characters must be Unicode XID characters \
76 (numbers, `-`, `_`, or most letters){}",
77 ch,
78 what,
79 name,
80 help
81 );
82 }
83 }
84 Ok(())
85}
86
87pub fn is_windows_reserved_path(path: &Path) -> bool {
89 path.iter()
90 .filter_map(|component| component.to_str())
91 .any(|component| {
92 let stem = component.split('.').next().unwrap();
93 is_windows_reserved(stem)
94 })
95}
96
97pub fn is_glob_pattern<T: AsRef<str>>(name: T) -> bool {
99 name.as_ref().contains(&['*', '?', '[', ']'][..])
100}