zenops_safe_relative_path/
buf.rs1use std::{fmt, sync::Arc};
2
3use relative_path::{RelativePath, RelativePathBuf};
4use serde::{de, ser};
5
6use crate::{SafeRelativePath, error::Error};
7
8#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
34pub struct SafeRelativePathBuf(RelativePathBuf);
35
36impl SafeRelativePathBuf {
37 pub fn from_relative_path<P>(v: &P) -> Result<Self, Error>
43 where
44 P: AsRef<RelativePath> + ?Sized,
45 {
46 SafeRelativePath::from_relative_path(v).map(|p| p.to_safe_relative_path_buf())
47 }
48
49 fn as_safe_rel_path(&self) -> &SafeRelativePath {
50 unsafe { SafeRelativePath::new_unchecked(&self.0) }
51 }
52}
53
54impl ser::Serialize for SafeRelativePathBuf {
55 fn serialize<S: ser::Serializer>(&self, s: S) -> Result<S::Ok, S::Error> {
56 s.serialize_str(self.as_str())
57 }
58}
59
60#[cfg(feature = "schemars")]
61impl schemars::JsonSchema for SafeRelativePathBuf {
62 fn schema_name() -> std::borrow::Cow<'static, str> {
63 "SafeRelativePath".into()
64 }
65
66 fn json_schema(generator: &mut schemars::SchemaGenerator) -> schemars::Schema {
67 <SafeRelativePath as schemars::JsonSchema>::json_schema(generator)
68 }
69}
70
71impl<'de> de::Deserialize<'de> for SafeRelativePathBuf {
72 fn deserialize<D: de::Deserializer<'de>>(d: D) -> Result<Self, D::Error> {
73 struct Visitor;
74 impl<'de> de::Visitor<'de> for Visitor {
75 type Value = SafeRelativePathBuf;
76
77 fn expecting(&self, f: &mut fmt::Formatter) -> fmt::Result {
78 write!(f, "path")
79 }
80
81 fn visit_str<E: de::Error>(self, v: &str) -> Result<Self::Value, E> {
82 SafeRelativePathBuf::from_relative_path(v).map_err(de::Error::custom)
83 }
84 }
85 d.deserialize_str(Visitor)
86 }
87}
88
89impl std::str::FromStr for SafeRelativePathBuf {
90 type Err = Error;
91
92 fn from_str(s: &str) -> Result<Self, Self::Err> {
93 Self::from_relative_path(s)
94 }
95}
96
97impl AsRef<SafeRelativePath> for SafeRelativePathBuf {
98 fn as_ref(&self) -> &SafeRelativePath {
99 self.as_safe_rel_path()
100 }
101}
102
103impl std::ops::Deref for SafeRelativePathBuf {
104 type Target = SafeRelativePath;
105
106 fn deref(&self) -> &Self::Target {
107 unsafe { SafeRelativePath::new_unchecked(&self.0) }
108 }
109}
110
111impl AsRef<RelativePath> for SafeRelativePathBuf {
112 fn as_ref(&self) -> &RelativePath {
113 &self.0
114 }
115}
116
117impl AsRef<std::ffi::OsStr> for SafeRelativePathBuf {
118 fn as_ref(&self) -> &std::ffi::OsStr {
119 self.as_safe_rel_path().as_ref()
120 }
121}
122
123impl fmt::Debug for SafeRelativePathBuf {
124 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
125 fmt::Debug::fmt(&self.0, f)
126 }
127}
128
129impl fmt::Display for SafeRelativePathBuf {
130 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
131 fmt::Display::fmt(&self.0, f)
132 }
133}
134
135impl From<SafeRelativePathBuf> for Arc<SafeRelativePath> {
136 fn from(value: SafeRelativePathBuf) -> Self {
137 let arc_rel: Arc<RelativePath> = Arc::from(value.0);
138 unsafe { Arc::from_raw(Arc::into_raw(arc_rel) as *const SafeRelativePath) }
139 }
140}
141
142impl SafeRelativePath {
143 pub fn to_safe_relative_path_buf(&self) -> SafeRelativePathBuf {
145 SafeRelativePathBuf(self.0.to_relative_path_buf())
146 }
147
148 pub fn normalize_safe(&self) -> SafeRelativePathBuf {
165 SafeRelativePathBuf(self.0.normalize())
166 }
167
168 pub fn safe_join(&self, path: impl AsRef<SafeRelativePath>) -> SafeRelativePathBuf {
183 SafeRelativePathBuf(self.0.join(&path.as_ref().0))
184 }
185}