use std::borrow::Cow;
use std::ffi::OsStr;
use std::fs::read;
#[cfg(unix)]
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
use std::path::PathBuf;
use crate::error::DatabaseError;
use crate::file::File;
use crate::file::FileType;
pub(crate) fn bytes_to_os_str(bytes: &[u8]) -> Cow<'_, OsStr> {
#[cfg(unix)]
{
Cow::Borrowed(OsStr::from_bytes(bytes))
}
#[cfg(not(unix))]
{
match std::str::from_utf8(bytes) {
Ok(s) => Cow::Borrowed(OsStr::new(s)),
Err(_) => Cow::Owned(String::from_utf8_lossy(bytes).into_owned().into()),
}
}
}
pub(crate) fn bytes_to_path(bytes: &[u8]) -> Cow<'_, Path> {
match bytes_to_os_str(bytes) {
Cow::Borrowed(s) => Cow::Borrowed(Path::new(s)),
Cow::Owned(s) => Cow::Owned(PathBuf::from(s)),
}
}
#[inline]
pub(crate) fn bytes_to_string_lossy(bytes: &[u8]) -> Cow<'_, str> {
String::from_utf8_lossy(bytes)
}
const MAXIMUM_FILE_SIZE: usize = 256 * 1024 * 1024;
pub(crate) fn read_file(workspace: &Path, path: &Path, file_type: FileType) -> Result<File, DatabaseError> {
let bytes = read(path)?;
if bytes.len() > MAXIMUM_FILE_SIZE {
return Err(DatabaseError::FileTooLarge(path.to_path_buf(), bytes.len(), MAXIMUM_FILE_SIZE));
}
#[cfg(windows)]
let logical_name = path
.strip_prefix(workspace)
.unwrap_or(path)
.as_os_str()
.as_encoded_bytes()
.iter()
.map(|i| if *i == b'\\' { b'/' } else { *i })
.collect::<Vec<_>>();
#[cfg(not(windows))]
let logical_name = path.strip_prefix(workspace).unwrap_or(path).as_os_str().as_encoded_bytes().to_owned();
Ok(File::new(Cow::Owned(logical_name), file_type, Some(path.to_path_buf()), Cow::Owned(bytes)))
}