relative_path/musli02.rs
1//! Implementations of the [`musli` 0.2] traits, with the same string
2//! representation as the `serde` implementations.
3//!
4//! [`musli` 0.2]: https://docs.rs/musli/0.2
5
6#[cfg(feature = "alloc")]
7use alloc::boxed::Box;
8
9use musli_core02::de::DecodeUnsized;
10use musli_core02::{Allocator, Decode, Decoder, Encode, Encoder};
11
12use crate::RelativePath;
13#[cfg(feature = "alloc")]
14use crate::RelativePathBuf;
15
16/// [`Encode`] implementation for [`RelativePath`], encoding it as a string.
17///
18/// ```
19/// use musli::Encode;
20/// use relative_path::RelativePath;
21///
22/// #[derive(Encode)]
23/// struct Document<'a> {
24/// path: &'a RelativePath,
25/// }
26/// ```
27#[cfg_attr(relative_path_docsrs, doc(cfg(feature = "musli02")))]
28impl<M> Encode<M> for RelativePath {
29 type Encode = Self;
30
31 #[inline]
32 fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
33 where
34 E: Encoder<Mode = M>,
35 {
36 encoder.encode_string(self.as_str())
37 }
38
39 #[inline]
40 fn as_encode(&self) -> &Self::Encode {
41 self
42 }
43}
44
45/// [`Decode`] implementation for a [`RelativePath`] reference borrowed from
46/// the decoded input.
47///
48/// Decoding fails if the format cannot borrow the string from its input. Use
49/// [`RelativePathBuf`] or [`Box<RelativePath>`] when that is not possible.
50///
51/// ```
52/// use musli::Decode;
53/// use relative_path::RelativePath;
54///
55/// #[derive(Decode)]
56/// struct Document<'a> {
57/// path: &'a RelativePath,
58/// }
59/// ```
60#[cfg_attr(relative_path_docsrs, doc(cfg(feature = "musli02")))]
61impl<'de, M, A> Decode<'de, M, A> for &'de RelativePath
62where
63 A: Allocator,
64{
65 #[inline]
66 fn decode<D>(decoder: D) -> Result<Self, D::Error>
67 where
68 D: Decoder<'de, Mode = M, Allocator = A>,
69 {
70 Ok(RelativePath::new(decoder.decode::<&'de str>()?))
71 }
72}
73
74/// [`DecodeUnsized`] implementation for [`RelativePath`], which visits the
75/// decoded path by reference without requiring it to be borrowed from the
76/// input or allocated.
77///
78/// ```
79/// use musli::{Decode, Decoder};
80/// use musli::mode::Binary;
81/// use relative_path::RelativePath;
82///
83/// struct Depth(usize);
84///
85/// impl<'de, A> Decode<'de, Binary, A> for Depth
86/// where
87/// A: musli::Allocator,
88/// {
89/// fn decode<D>(decoder: D) -> Result<Self, D::Error>
90/// where
91/// D: Decoder<'de, Mode = Binary, Allocator = A>,
92/// {
93/// decoder.decode_unsized(|path: &RelativePath| Ok(Depth(path.components().count())))
94/// }
95/// }
96/// ```
97#[cfg_attr(relative_path_docsrs, doc(cfg(feature = "musli02")))]
98impl<'de, M> DecodeUnsized<'de, M> for RelativePath {
99 #[inline]
100 fn decode_unsized<D, F, O>(decoder: D, f: F) -> Result<O, D::Error>
101 where
102 D: Decoder<'de, Mode = M>,
103 F: FnOnce(&Self) -> Result<O, D::Error>,
104 {
105 decoder.decode_unsized(|string: &str| f(RelativePath::new(string)))
106 }
107}
108
109/// [`Encode`] implementation for [`RelativePathBuf`], encoding it as a string.
110///
111/// ```
112/// use musli::Encode;
113/// use relative_path::RelativePathBuf;
114///
115/// #[derive(Encode)]
116/// struct Document {
117/// path: RelativePathBuf,
118/// }
119/// ```
120#[cfg(feature = "alloc")]
121#[cfg_attr(
122 relative_path_docsrs,
123 doc(cfg(all(feature = "alloc", feature = "musli02")))
124)]
125impl<M> Encode<M> for RelativePathBuf {
126 type Encode = RelativePath;
127
128 #[inline]
129 fn encode<E>(&self, encoder: E) -> Result<(), E::Error>
130 where
131 E: Encoder<Mode = M>,
132 {
133 encoder.encode_string(self.as_str())
134 }
135
136 #[inline]
137 fn as_encode(&self) -> &Self::Encode {
138 self
139 }
140}
141
142/// [`Decode`] implementation for [`RelativePathBuf`].
143///
144/// ```
145/// use musli::Decode;
146/// use relative_path::RelativePathBuf;
147///
148/// #[derive(Decode)]
149/// struct Document {
150/// path: RelativePathBuf,
151/// }
152/// ```
153#[cfg(feature = "alloc")]
154#[cfg_attr(
155 relative_path_docsrs,
156 doc(cfg(all(feature = "alloc", feature = "musli02")))
157)]
158impl<'de, M, A> Decode<'de, M, A> for RelativePathBuf
159where
160 A: Allocator,
161{
162 #[inline]
163 fn decode<D>(decoder: D) -> Result<Self, D::Error>
164 where
165 D: Decoder<'de, Mode = M, Allocator = A>,
166 {
167 decoder.decode_unsized(|path: &RelativePath| Ok(path.to_relative_path_buf()))
168 }
169}
170
171/// [`Decode`] implementation for [`Box<RelativePath>`].
172///
173/// Encoding uses musli's implementation for [`Box`], which requires musli's
174/// `alloc` feature.
175///
176/// ```
177/// use musli::{Decode, Encode};
178/// use relative_path::RelativePath;
179///
180/// #[derive(Encode, Decode)]
181/// struct Document {
182/// path: Box<RelativePath>,
183/// }
184/// ```
185#[cfg(feature = "alloc")]
186#[cfg_attr(
187 relative_path_docsrs,
188 doc(cfg(all(feature = "alloc", feature = "musli02")))
189)]
190impl<'de, M, A> Decode<'de, M, A> for Box<RelativePath>
191where
192 A: Allocator,
193{
194 #[inline]
195 fn decode<D>(decoder: D) -> Result<Self, D::Error>
196 where
197 D: Decoder<'de, Mode = M, Allocator = A>,
198 {
199 decoder.decode_unsized(|path: &RelativePath| Ok(Box::<RelativePath>::from(path)))
200 }
201}