use std::borrow::Borrow;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
#[derive(Debug, Clone, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize), serde(transparent))]
pub struct AssetPath {
pub authored_path: String,
#[cfg_attr(feature = "serde", serde(skip))]
evaluated_path: Option<String>,
#[cfg_attr(feature = "serde", serde(skip))]
resolved_path: Option<String>,
}
impl AssetPath {
pub fn new(authored_path: impl Into<String>) -> Self {
Self {
authored_path: authored_path.into(),
evaluated_path: None,
resolved_path: None,
}
}
pub fn with_resolved_path(authored_path: impl Into<String>, resolved_path: impl Into<String>) -> Self {
Self {
authored_path: authored_path.into(),
evaluated_path: None,
resolved_path: Some(resolved_path.into()),
}
}
pub fn as_str(&self) -> &str {
&self.authored_path
}
pub fn asset_path(&self) -> &str {
self.evaluated_path.as_deref().unwrap_or(&self.authored_path)
}
pub fn evaluated_path(&self) -> Option<&str> {
self.evaluated_path.as_deref()
}
pub fn set_evaluated_path(&mut self, evaluated_path: impl Into<String>) {
self.evaluated_path = Some(evaluated_path.into());
}
pub fn resolved_path(&self) -> Option<&str> {
self.resolved_path.as_deref()
}
pub fn set_resolved_path(&mut self, resolved_path: impl Into<String>) {
self.resolved_path = Some(resolved_path.into());
}
pub fn is_empty(&self) -> bool {
self.authored_path.is_empty()
}
pub fn into_string(self) -> String {
self.authored_path
}
}
impl PartialEq for AssetPath {
fn eq(&self, other: &Self) -> bool {
self.authored_path == other.authored_path
}
}
impl Eq for AssetPath {}
impl Hash for AssetPath {
fn hash<H: Hasher>(&self, state: &mut H) {
self.authored_path.hash(state);
}
}
impl PartialOrd for AssetPath {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl Ord for AssetPath {
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.authored_path.cmp(&other.authored_path)
}
}
impl Deref for AssetPath {
type Target = str;
fn deref(&self) -> &str {
&self.authored_path
}
}
impl AsRef<str> for AssetPath {
fn as_ref(&self) -> &str {
&self.authored_path
}
}
impl Borrow<str> for AssetPath {
fn borrow(&self) -> &str {
&self.authored_path
}
}
impl std::fmt::Display for AssetPath {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(&self.authored_path)
}
}
impl From<String> for AssetPath {
fn from(authored_path: String) -> Self {
Self::new(authored_path)
}
}
impl From<&str> for AssetPath {
fn from(authored_path: &str) -> Self {
Self::new(authored_path)
}
}
impl From<AssetPath> for String {
fn from(asset: AssetPath) -> Self {
asset.authored_path
}
}
impl PartialEq<str> for AssetPath {
fn eq(&self, other: &str) -> bool {
self.authored_path == other
}
}
impl PartialEq<&str> for AssetPath {
fn eq(&self, other: &&str) -> bool {
self.authored_path == *other
}
}
impl PartialEq<String> for AssetPath {
fn eq(&self, other: &String) -> bool {
self.authored_path == *other
}
}
impl PartialEq<AssetPath> for str {
fn eq(&self, other: &AssetPath) -> bool {
other.authored_path == *self
}
}
impl PartialEq<AssetPath> for &str {
fn eq(&self, other: &AssetPath) -> bool {
other.authored_path == *self
}
}
impl PartialEq<AssetPath> for String {
fn eq(&self, other: &AssetPath) -> bool {
other.authored_path == *self
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn string_like() {
let asset = AssetPath::new("./tex.png");
assert_eq!(asset.len(), "./tex.png".len());
assert!(asset.ends_with(".png"));
assert_eq!(asset.as_ref() as &str, "./tex.png");
assert_eq!(asset, "./tex.png");
assert_eq!("./tex.png", asset);
assert_eq!(asset, String::from("./tex.png"));
assert_eq!(asset.to_string(), "./tex.png");
assert_eq!(String::from(asset), "./tex.png");
assert!(!AssetPath::new("./tex.png").is_empty());
assert!(AssetPath::default().is_empty());
}
}