1use crate::{Slice, Value, Visit};
2
3use core::fmt;
4use core::num::Wrapping;
5
6pub trait Valuable {
31 fn as_value(&self) -> Value<'_>;
41
42 fn visit(&self, visit: &mut dyn Visit);
58
59 fn visit_slice(slice: &[Self], visit: &mut dyn Visit)
66 where
67 Self: Sized,
68 {
69 for item in slice {
70 visit.visit_value(item.as_value());
71 }
72 }
73}
74
75macro_rules! deref {
76 (
77 $(
78 $(#[$attrs:meta])*
79 $ty:ty,
80 )*
81 ) => {
82 $(
83 $(#[$attrs])*
84 impl<T: ?Sized + Valuable> Valuable for $ty {
85 fn as_value(&self) -> Value<'_> {
86 T::as_value(&**self)
87 }
88
89 fn visit(&self, visit: &mut dyn Visit) {
90 T::visit(&**self, visit);
91 }
92 }
93 )*
94 };
95}
96
97deref! {
98 &T,
99 &mut T,
100 #[cfg(feature = "alloc")]
101 alloc::boxed::Box<T>,
102 #[cfg(feature = "alloc")]
103 alloc::rc::Rc<T>,
104 #[cfg(not(valuable_no_atomic_cas))]
105 #[cfg(feature = "alloc")]
106 alloc::sync::Arc<T>,
107}
108
109macro_rules! valuable {
110 (
111 $(
112 $variant:ident($ty:ty),
113 )*
114 ) => {
115 $(
116 impl Valuable for $ty {
117 fn as_value(&self) -> Value<'_> {
118 Value::$variant(*self)
119 }
120
121 fn visit(&self, visit: &mut dyn Visit) {
122 visit.visit_value(self.as_value());
123 }
124
125 fn visit_slice(slice: &[Self], visit: &mut dyn Visit)
126 where
127 Self: Sized,
128 {
129 visit.visit_primitive_slice(Slice::$variant(slice));
130 }
131 }
132 )*
133 };
134}
135
136valuable! {
137 Bool(bool),
138 Char(char),
139 F32(f32),
140 F64(f64),
141 I8(i8),
142 I16(i16),
143 I32(i32),
144 I64(i64),
145 I128(i128),
146 Isize(isize),
147 U8(u8),
148 U16(u16),
149 U32(u32),
150 U64(u64),
151 U128(u128),
152 Usize(usize),
153}
154
155macro_rules! nonzero {
156 (
157 $(
158 $variant:ident($ty:ident),
159 )*
160 ) => {
161 $(
162 impl Valuable for core::num::$ty {
163 fn as_value(&self) -> Value<'_> {
164 Value::$variant(self.get())
165 }
166
167 fn visit(&self, visit: &mut dyn Visit) {
168 visit.visit_value(self.as_value());
169 }
170 }
171 )*
172 };
173}
174
175nonzero! {
176 I8(NonZeroI8),
177 I16(NonZeroI16),
178 I32(NonZeroI32),
179 I64(NonZeroI64),
180 I128(NonZeroI128),
181 Isize(NonZeroIsize),
182 U8(NonZeroU8),
183 U16(NonZeroU16),
184 U32(NonZeroU32),
185 U64(NonZeroU64),
186 U128(NonZeroU128),
187 Usize(NonZeroUsize),
188}
189
190#[cfg(not(valuable_no_atomic))]
191macro_rules! atomic {
192 (
193 $(
194 $(#[$attrs:meta])*
195 $variant:ident($ty:ident),
196 )*
197 ) => {
198 $(
199 $(#[$attrs])*
200 impl Valuable for core::sync::atomic::$ty {
201 fn as_value(&self) -> Value<'_> {
202 Value::$variant(self.load(core::sync::atomic::Ordering::SeqCst))
206 }
207
208 fn visit(&self, visit: &mut dyn Visit) {
209 visit.visit_value(self.as_value());
210 }
211 }
212 )*
213 };
214}
215
216#[cfg(not(valuable_no_atomic))]
217atomic! {
218 Bool(AtomicBool),
219 I8(AtomicI8),
220 I16(AtomicI16),
221 I32(AtomicI32),
222 #[cfg(not(valuable_no_atomic_64))]
223 I64(AtomicI64),
224 Isize(AtomicIsize),
225 U8(AtomicU8),
226 U16(AtomicU16),
227 U32(AtomicU32),
228 #[cfg(not(valuable_no_atomic_64))]
229 U64(AtomicU64),
230 Usize(AtomicUsize),
231}
232
233impl<T: Valuable> Valuable for Wrapping<T> {
234 fn as_value(&self) -> Value<'_> {
235 self.0.as_value()
236 }
237
238 fn visit(&self, visit: &mut dyn Visit) {
239 self.0.visit(visit);
240 }
241}
242
243impl Valuable for () {
244 fn as_value(&self) -> Value<'_> {
245 Value::Tuplable(self)
246 }
247
248 fn visit(&self, visit: &mut dyn Visit) {
249 visit.visit_unnamed_fields(&[]);
250 }
251}
252
253impl<T: Valuable> Valuable for Option<T> {
254 fn as_value(&self) -> Value<'_> {
255 match self {
256 Some(v) => v.as_value(),
257 None => Value::Unit,
258 }
259 }
260
261 fn visit(&self, visit: &mut dyn Visit) {
262 visit.visit_value(self.as_value());
263 }
264}
265
266impl Valuable for &'_ str {
267 fn as_value(&self) -> Value<'_> {
268 Value::String(self)
269 }
270
271 fn visit(&self, visit: &mut dyn Visit) {
272 visit.visit_value(Value::String(self));
273 }
274
275 fn visit_slice(slice: &[Self], visit: &mut dyn Visit)
276 where
277 Self: Sized,
278 {
279 visit.visit_primitive_slice(Slice::Str(slice));
280 }
281}
282
283#[cfg(feature = "alloc")]
284impl Valuable for alloc::string::String {
285 fn as_value(&self) -> Value<'_> {
286 Value::String(&self[..])
287 }
288
289 fn visit(&self, visit: &mut dyn Visit) {
290 visit.visit_value(Value::String(self));
291 }
292
293 fn visit_slice(slice: &[Self], visit: &mut dyn Visit)
294 where
295 Self: Sized,
296 {
297 visit.visit_primitive_slice(Slice::String(slice));
298 }
299}
300
301#[cfg(feature = "std")]
302impl Valuable for &std::path::Path {
303 fn as_value(&self) -> Value<'_> {
304 Value::Path(self)
305 }
306
307 fn visit(&self, visit: &mut dyn Visit) {
308 visit.visit_value(Value::Path(self));
309 }
310}
311
312#[cfg(feature = "std")]
313impl Valuable for std::path::PathBuf {
314 fn as_value(&self) -> Value<'_> {
315 Value::Path(self)
316 }
317
318 fn visit(&self, visit: &mut dyn Visit) {
319 visit.visit_value(Value::Path(self));
320 }
321}
322
323#[cfg(feature = "std")]
324impl Valuable for dyn std::error::Error + 'static {
325 fn as_value(&self) -> Value<'_> {
326 Value::Error(self)
327 }
328
329 fn visit(&self, visit: &mut dyn Visit) {
330 visit.visit_value(self.as_value());
331 }
332}
333
334impl fmt::Debug for dyn Valuable + '_ {
335 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
336 let value = self.as_value();
337 value.fmt(fmt)
338 }
339}