use crate::MaybePath;
use serde::{Deserialize, Serialize};
use std::{
borrow::{Borrow, Cow},
ffi::OsStr,
ops::Deref,
path::{Path, PathBuf},
};
#[derive(Debug, Serialize, Eq, PartialEq, PartialOrd, Ord, Hash)]
pub enum MaybePathBuf<'a> {
Borrowed(MaybePath<'a>),
Owned(PathBuf),
}
impl Default for MaybePathBuf<'_> {
fn default() -> Self {
Self::Borrowed(MaybePath::new_str(""))
}
}
impl Clone for MaybePathBuf<'_> {
#[inline]
fn clone(&self) -> Self {
match *self {
Self::Borrowed(b) => Self::Borrowed(b),
Self::Owned(ref o) => {
let b = MaybePath::new_path(o);
Self::Owned(b.to_owned())
}
}
}
#[inline]
fn clone_from(&mut self, source: &Self) {
match (self, source) {
(&mut Self::Owned(ref mut dest), Self::Owned(o)) => {
MaybePath::new_path(o).as_path().clone_into(dest)
}
(t, s) => *t = s.clone(),
}
}
}
impl<'a> MaybePathBuf<'a> {
pub fn new_path<P: AsRef<OsStr> + ?Sized>(path: &'a P) -> Self {
Self::Borrowed(MaybePath::new_path(path))
}
pub const fn new_str(s: &'a str) -> Self {
Self::Borrowed(MaybePath::new_str(s))
}
pub const fn new_pathbuf(path: PathBuf) -> Self {
Self::Owned(path)
}
pub fn is_borrowed(&self) -> bool {
matches!(self, Self::Borrowed(_))
}
pub fn to_mut(&mut self) -> &mut PathBuf {
match self {
Self::Borrowed(b) => {
let b = b.to_owned();
*self = Self::Owned(b);
match self {
Self::Owned(ref mut o) => o,
_ => unreachable!(),
}
}
Self::Owned(ref mut o) => o,
}
}
pub fn into_owned(self) -> PathBuf {
match self {
Self::Borrowed(b) => b.to_owned(),
Self::Owned(o) => o,
}
}
pub fn into_cow(self) -> Cow<'a, Path> {
match self {
Self::Borrowed(b) => Cow::Borrowed(b.as_path()),
Self::Owned(o) => Cow::Owned(o),
}
}
}
impl<'a> Borrow<Path> for MaybePathBuf<'a> {
fn borrow(&self) -> &Path {
self
}
}
impl Deref for MaybePathBuf<'_> {
type Target = Path;
#[inline]
fn deref(&self) -> &Self::Target {
match self {
Self::Borrowed(b) => b.as_path(),
Self::Owned(o) => o.as_path(),
}
}
}
impl AsRef<Path> for MaybePathBuf<'_> {
#[inline]
fn as_ref(&self) -> &Path {
self
}
}
impl<'de> Deserialize<'de> for MaybePathBuf<'de> {
fn deserialize<D>(deserializer: D) -> Result<MaybePathBuf<'de>, D::Error>
where
D: serde::Deserializer<'de>,
{
let path = PathBuf::deserialize(deserializer)?;
Ok(MaybePathBuf::Owned(path))
}
}