Skip to main content

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}