use {
crate::{Error, Result},
std::{
fs::{self, File, OpenOptions},
path::{Path, PathBuf},
},
};
pub const MAIN_RS: &str = "src/main.rs";
pub const LIB_RS: &str = "src/lib.rs";
const ROOT_FILE: [&str; 2] = [LIB_RS, MAIN_RS];
pub const MOD_RS: &str = "mod.rs";
pub fn get_root_file_name() -> Result<&'static str> {
let is_lib = Path::new(LIB_RS).is_file();
let is_bin = Path::new(MAIN_RS).is_file();
if is_bin && is_lib {
Err(Error::Other("Current package contains both `lib.rs` and `main.rs`. Unable to determine package type".to_owned()))
} else {
Ok(ROOT_FILE[is_bin as usize])
}
}
pub fn add_mod_rs(path: impl Into<PathBuf>) -> PathBuf {
suffix(path, MOD_RS)
}
pub fn suffix(path: impl Into<PathBuf>, ext: impl AsRef<Path>) -> PathBuf {
let mut p = path.into();
p.push(ext);
p
}
pub fn cowfile(orig: &str, with_open: impl FnOnce(&mut File, &str) -> Result<()>) -> Result<()> {
let old_file_contents = fs::read_to_string(orig)?;
let new = format!("{}_", orig);
let mut new_file = OpenOptions::new().write(true).create_new(true).open(&new)?;
with_open(&mut new_file, &old_file_contents)?;
new_file.sync_all()?;
fs::rename(new, orig)?;
Ok(())
}
pub fn validate_module_name(name: &str) -> Result<()> {
if name.is_empty() {
return Error::bad_module_name();
}
let first_byte = name.as_bytes()[0];
let mut valid_name: bool = true;
valid_name &= first_byte.is_ascii_alphabetic() || (
first_byte == b'_' && name.len() != 1 );
valid_name &= name
.bytes()
.all(|b| u8::is_ascii_alphanumeric(&b) || b == b'_');
if valid_name {
Ok(())
} else {
Error::bad_module_name()
}
}