use crate::error::{Error, Result};
use blueprint_core::warn;
use sha2::Digest;
use std::net::{Ipv4Addr, SocketAddrV4, TcpListener};
use std::path::{Path, PathBuf};
pub fn hash_bytes_to_hex<T: AsRef<[u8]>>(input: T) -> String {
let mut hasher = sha2::Sha256::default();
hasher.update(input);
hex::encode(hasher.finalize())
}
pub async fn valid_file_exists(path: impl AsRef<Path>) -> bool {
if let Ok(_file) = tokio::fs::read(path).await {
true
} else {
false
}
}
#[must_use]
pub fn get_formatted_os_string() -> String {
let os = std::env::consts::OS;
match os {
"macos" => "apple-darwin".to_string(),
"windows" => "pc-windows-msvc".to_string(),
"linux" => "unknown-linux-gnu".to_string(),
_ => os.to_string(),
}
}
pub fn make_executable<P: AsRef<Path>>(path: P) -> Result<PathBuf> {
#[cfg(target_family = "unix")]
fn unix(path: &Path) -> Result<()> {
use std::os::unix::fs::PermissionsExt;
let f = std::fs::File::open(path)?;
let mut perms = f.metadata()?.permissions();
perms.set_mode(perms.mode() | 0o111);
f.set_permissions(perms)?;
Ok(())
}
let mut path = path.as_ref().to_path_buf();
if cfg!(target_family = "windows") {
if path.extension().is_none() {
path.set_extension("exe");
}
} else if let Err(err) = unix(&path) {
let msg = format!("Failed to make the binary executable: {err}");
warn!("{}", msg);
return Err(Error::Other(msg));
}
Ok(path)
}
#[must_use]
pub fn slice_32_to_sha_hex_string(hash: [u8; 32]) -> String {
use std::fmt::Write;
hash.iter().fold(String::new(), |mut acc, byte| {
write!(&mut acc, "{:02x}", byte).expect("Should be able to write");
acc
})
}
pub enum PortLock {
Locked(TcpListener),
Unlocked(u16),
}
impl PortLock {
pub fn lock(port: u16) -> Result<Self> {
let addr = SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port);
let listener = TcpListener::bind(addr)?;
Ok(Self::Locked(listener))
}
#[allow(clippy::missing_panics_doc)]
pub fn unlock(&mut self) -> u16 {
match self {
PortLock::Locked(listener) => {
let port = listener.local_addr().unwrap().port();
*self = Self::Unlocked(port);
port
}
PortLock::Unlocked(port) => *port,
}
}
}