#![allow(missing_docs)]
#[allow(unused_imports)]
use crate::error::{Error, Result};
#[allow(unused_imports)]
use firkin_types::{ContainerId, InvalidContainerId};
#[allow(unused_imports)]
use firkin_types::{InvalidProcessId, ProcessId};
pub trait IntoContainerId {
fn into_container_id(self) -> std::result::Result<ContainerId, InvalidContainerId>;
}
impl IntoContainerId for ContainerId {
fn into_container_id(self) -> std::result::Result<ContainerId, InvalidContainerId> {
Ok(self)
}
}
impl IntoContainerId for &str {
fn into_container_id(self) -> std::result::Result<ContainerId, InvalidContainerId> {
ContainerId::new(self)
}
}
impl IntoContainerId for String {
fn into_container_id(self) -> std::result::Result<ContainerId, InvalidContainerId> {
ContainerId::new(self)
}
}
pub trait IntoProcessId {
fn into_process_id(self) -> std::result::Result<ProcessId, InvalidProcessId>;
}
impl IntoProcessId for ProcessId {
fn into_process_id(self) -> std::result::Result<ProcessId, InvalidProcessId> {
Ok(self)
}
}
impl IntoProcessId for &str {
fn into_process_id(self) -> std::result::Result<ProcessId, InvalidProcessId> {
ProcessId::new(self)
}
}
impl IntoProcessId for String {
fn into_process_id(self) -> std::result::Result<ProcessId, InvalidProcessId> {
ProcessId::new(self)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct GuestPath(String);
impl GuestPath {
pub fn new(path: impl Into<String>) -> Result<Self> {
let path = path.into();
validate_guest_path(&path)?;
Ok(Self(path))
}
#[must_use]
pub fn as_str(&self) -> &str {
&self.0
}
}
impl std::fmt::Display for GuestPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
fn validate_guest_path(path: &str) -> Result<()> {
if path.is_empty() {
return invalid_guest_path(path, "path cannot be empty");
}
if path.contains('\0') {
return invalid_guest_path(path, "path cannot contain NUL");
}
if path == "/" {
return invalid_guest_path(path, "path cannot be root");
}
if !path.starts_with('/') {
return invalid_guest_path(path, "path must be absolute");
}
if path
.split('/')
.skip(1)
.any(|component| component == ".." || component.is_empty())
{
return invalid_guest_path(path, "path must be normalized");
}
Ok(())
}
fn invalid_guest_path<T>(path: &str, reason: &'static str) -> Result<T> {
Err(Error::InvalidGuestPath {
path: path.to_owned(),
reason,
})
}