1use crate::{
62 internal::{self, InternalVisitor},
63 Error, ValueBag,
64};
65
66pub trait Visit<'v> {
68 fn visit_any(&mut self, value: ValueBag) -> Result<(), Error>;
75
76 #[inline]
78 fn visit_empty(&mut self) -> Result<(), Error> {
79 self.visit_any(ValueBag::empty())
80 }
81
82 #[inline]
84 fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
85 self.visit_any(value.into())
86 }
87
88 #[inline]
90 fn visit_i64(&mut self, value: i64) -> Result<(), Error> {
91 self.visit_any(value.into())
92 }
93
94 #[inline]
96 fn visit_u128(&mut self, value: u128) -> Result<(), Error> {
97 self.visit_any((&value).into())
98 }
99
100 #[inline]
102 fn visit_i128(&mut self, value: i128) -> Result<(), Error> {
103 self.visit_any((&value).into())
104 }
105
106 #[inline]
108 fn visit_f64(&mut self, value: f64) -> Result<(), Error> {
109 self.visit_any(value.into())
110 }
111
112 #[inline]
114 fn visit_bool(&mut self, value: bool) -> Result<(), Error> {
115 self.visit_any(value.into())
116 }
117
118 #[inline]
120 fn visit_str(&mut self, value: &str) -> Result<(), Error> {
121 self.visit_any(value.into())
122 }
123
124 #[inline]
126 fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
127 self.visit_str(value)
128 }
129
130 #[inline]
132 fn visit_char(&mut self, value: char) -> Result<(), Error> {
133 let mut b = [0; 4];
134 self.visit_str(&*value.encode_utf8(&mut b))
135 }
136
137 #[inline]
139 #[cfg(feature = "error")]
140 fn visit_error(&mut self, err: &(dyn crate::std::error::Error + 'static)) -> Result<(), Error> {
141 self.visit_any(ValueBag::from_dyn_error(err))
142 }
143
144 #[inline]
146 #[cfg(feature = "error")]
147 fn visit_borrowed_error(
148 &mut self,
149 err: &'v (dyn crate::std::error::Error + 'static),
150 ) -> Result<(), Error> {
151 self.visit_any(ValueBag::from_dyn_error(err))
152 }
153}
154
155impl<'a, 'v, T: ?Sized> Visit<'v> for &'a mut T
156where
157 T: Visit<'v>,
158{
159 #[inline]
160 fn visit_any(&mut self, value: ValueBag) -> Result<(), Error> {
161 (**self).visit_any(value)
162 }
163
164 #[inline]
165 fn visit_empty(&mut self) -> Result<(), Error> {
166 (**self).visit_empty()
167 }
168
169 #[inline]
170 fn visit_u64(&mut self, value: u64) -> Result<(), Error> {
171 (**self).visit_u64(value)
172 }
173
174 #[inline]
175 fn visit_i64(&mut self, value: i64) -> Result<(), Error> {
176 (**self).visit_i64(value)
177 }
178
179 #[inline]
180 fn visit_u128(&mut self, value: u128) -> Result<(), Error> {
181 (**self).visit_u128(value)
182 }
183
184 #[inline]
185 fn visit_i128(&mut self, value: i128) -> Result<(), Error> {
186 (**self).visit_i128(value)
187 }
188
189 #[inline]
190 fn visit_f64(&mut self, value: f64) -> Result<(), Error> {
191 (**self).visit_f64(value)
192 }
193
194 #[inline]
195 fn visit_bool(&mut self, value: bool) -> Result<(), Error> {
196 (**self).visit_bool(value)
197 }
198
199 #[inline]
200 fn visit_str(&mut self, value: &str) -> Result<(), Error> {
201 (**self).visit_str(value)
202 }
203
204 #[inline]
205 fn visit_borrowed_str(&mut self, value: &'v str) -> Result<(), Error> {
206 (**self).visit_borrowed_str(value)
207 }
208
209 #[inline]
210 fn visit_char(&mut self, value: char) -> Result<(), Error> {
211 (**self).visit_char(value)
212 }
213
214 #[inline]
215 #[cfg(feature = "error")]
216 fn visit_error(&mut self, err: &(dyn crate::std::error::Error + 'static)) -> Result<(), Error> {
217 (**self).visit_error(err)
218 }
219
220 #[inline]
221 #[cfg(feature = "error")]
222 fn visit_borrowed_error(
223 &mut self,
224 err: &'v (dyn crate::std::error::Error + 'static),
225 ) -> Result<(), Error> {
226 (**self).visit_borrowed_error(err)
227 }
228}
229
230impl<'v> ValueBag<'v> {
231 pub fn visit(&self, visitor: impl Visit<'v>) -> Result<(), Error> {
237 struct Visitor<V>(V);
238
239 impl<'v, V> InternalVisitor<'v> for Visitor<V>
240 where
241 V: Visit<'v>,
242 {
243 fn fill(&mut self, v: &dyn crate::fill::Fill) -> Result<(), Error> {
244 v.fill(crate::fill::Slot::new(self))
245 }
246
247 fn debug(&mut self, v: &dyn internal::fmt::Debug) -> Result<(), Error> {
248 self.0.visit_any(ValueBag::from_dyn_debug(v))
249 }
250
251 fn display(&mut self, v: &dyn internal::fmt::Display) -> Result<(), Error> {
252 self.0.visit_any(ValueBag::from_dyn_display(v))
253 }
254
255 fn u64(&mut self, v: u64) -> Result<(), Error> {
256 self.0.visit_u64(v)
257 }
258
259 fn i64(&mut self, v: i64) -> Result<(), Error> {
260 self.0.visit_i64(v)
261 }
262
263 fn u128(&mut self, v: &u128) -> Result<(), Error> {
264 self.0.visit_u128(*v)
265 }
266
267 fn i128(&mut self, v: &i128) -> Result<(), Error> {
268 self.0.visit_i128(*v)
269 }
270
271 fn f64(&mut self, v: f64) -> Result<(), Error> {
272 self.0.visit_f64(v)
273 }
274
275 fn bool(&mut self, v: bool) -> Result<(), Error> {
276 self.0.visit_bool(v)
277 }
278
279 fn char(&mut self, v: char) -> Result<(), Error> {
280 self.0.visit_char(v)
281 }
282
283 fn str(&mut self, v: &str) -> Result<(), Error> {
284 self.0.visit_str(v)
285 }
286
287 fn borrowed_str(&mut self, v: &'v str) -> Result<(), Error> {
288 self.0.visit_borrowed_str(v)
289 }
290
291 fn none(&mut self) -> Result<(), Error> {
292 self.0.visit_empty()
293 }
294
295 #[cfg(feature = "error")]
296 fn error(&mut self, v: &(dyn internal::error::Error + 'static)) -> Result<(), Error> {
297 self.0.visit_error(v)
298 }
299
300 #[cfg(feature = "error")]
301 fn borrowed_error(
302 &mut self,
303 v: &'v (dyn internal::error::Error + 'static),
304 ) -> Result<(), Error> {
305 self.0.visit_borrowed_error(v)
306 }
307
308 #[cfg(feature = "sval2")]
309 fn sval2(&mut self, v: &dyn internal::sval::v2::Value) -> Result<(), Error> {
310 if internal::sval::v2::internal_visit(v, self) {
311 Ok(())
312 } else {
313 self.0.visit_any(ValueBag::from_dyn_sval2(v))
314 }
315 }
316
317 #[cfg(feature = "sval2")]
318 fn borrowed_sval2(
319 &mut self,
320 v: &'v dyn internal::sval::v2::Value,
321 ) -> Result<(), Error> {
322 if internal::sval::v2::borrowed_internal_visit(v, self) {
323 Ok(())
324 } else {
325 self.0.visit_any(ValueBag::from_dyn_sval2(v))
326 }
327 }
328
329 #[cfg(feature = "serde1")]
330 fn serde1(&mut self, v: &dyn internal::serde::v1::Serialize) -> Result<(), Error> {
331 if internal::serde::v1::internal_visit(v, self) {
332 Ok(())
333 } else {
334 self.0.visit_any(ValueBag::from_dyn_serde1(v))
335 }
336 }
337
338 #[cfg(feature = "seq")]
339 fn seq(&mut self, v: &dyn internal::seq::Seq) -> Result<(), Error> {
340 self.0.visit_any(ValueBag::from_dyn_seq(v))
341 }
342
343 fn poisoned(&mut self, msg: &'static str) -> Result<(), Error> {
344 Err(Error::msg(msg))
345 }
346 }
347
348 self.internal_visit(&mut Visitor(visitor))
349 }
350}
351
352#[cfg(test)]
353mod tests {
354 use super::*;
355 use crate::test::*;
356
357 #[cfg(target_arch = "wasm32")]
358 use wasm_bindgen_test::*;
359
360 #[test]
361 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
362 fn visit_structured() {
363 ValueBag::from(42u64)
364 .visit(TestVisit::default())
365 .expect("failed to visit value");
366 ValueBag::from(-42i64)
367 .visit(TestVisit::default())
368 .expect("failed to visit value");
369 ValueBag::from(&42u128)
370 .visit(TestVisit::default())
371 .expect("failed to visit value");
372 ValueBag::from(&-42i128)
373 .visit(TestVisit::default())
374 .expect("failed to visit value");
375 ValueBag::from(11f64)
376 .visit(TestVisit::default())
377 .expect("failed to visit value");
378 ValueBag::from(true)
379 .visit(TestVisit::default())
380 .expect("failed to visit value");
381 ValueBag::from("some borrowed string")
382 .visit(TestVisit::default())
383 .expect("failed to visit value");
384 ValueBag::from('n')
385 .visit(TestVisit::default())
386 .expect("failed to visit value");
387 }
388
389 #[test]
390 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
391 fn visit_empty() {
392 struct Visitor(bool);
393
394 impl<'v> Visit<'v> for Visitor {
395 fn visit_any(&mut self, _: ValueBag) -> Result<(), Error> {
396 Ok(())
397 }
398
399 fn visit_empty(&mut self) -> Result<(), Error> {
400 self.0 = true;
401 Ok(())
402 }
403 }
404
405 let mut visitor = Visitor(false);
406 ValueBag::empty().visit(&mut visitor).unwrap();
407
408 assert!(visitor.0);
409 }
410
411 #[test]
412 #[cfg(feature = "serde1")]
413 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
414 fn visit_serde1() {
415 use crate::std::string::{String, ToString};
416
417 struct Data;
418
419 impl value_bag_serde1::lib::Serialize for Data {
420 fn serialize<S: value_bag_serde1::lib::Serializer>(
421 &self,
422 serializer: S,
423 ) -> Result<S::Ok, S::Error> {
424 use value_bag_serde1::lib::ser::SerializeStruct;
425
426 let mut s = serializer.serialize_struct("Data", 3)?;
427 s.serialize_field("a", &1)?;
428 s.serialize_field("b", &2)?;
429 s.serialize_field("c", &3)?;
430 s.end()
431 }
432 }
433
434 struct Visitor(String);
435
436 impl<'v> Visit<'v> for Visitor {
437 fn visit_any(&mut self, v: ValueBag) -> Result<(), Error> {
438 self.0 = v.to_string();
439
440 Ok(())
441 }
442 }
443
444 let mut visitor = Visitor("".into());
445 ValueBag::from_serde1(&Data).visit(&mut visitor).unwrap();
446
447 assert_eq!("Data { a: 1, b: 2, c: 3 }", visitor.0);
448 }
449
450 #[test]
451 #[cfg(feature = "sval2")]
452 #[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
453 fn visit_sval2() {
454 use crate::std::string::{String, ToString};
455
456 struct Data;
457
458 impl value_bag_sval2::lib::Value for Data {
459 fn stream<'sval, S: value_bag_sval2::lib::Stream<'sval> + ?Sized>(
460 &'sval self,
461 stream: &mut S,
462 ) -> value_bag_sval2::lib::Result {
463 stream.map_begin(Some(3))?;
464
465 stream.map_key_begin()?;
466 stream.value("a")?;
467 stream.map_key_end()?;
468
469 stream.map_value_begin()?;
470 stream.value(&1)?;
471 stream.map_value_end()?;
472
473 stream.map_key_begin()?;
474 stream.value("b")?;
475 stream.map_key_end()?;
476
477 stream.map_value_begin()?;
478 stream.value(&2)?;
479 stream.map_value_end()?;
480
481 stream.map_key_begin()?;
482 stream.value("c")?;
483 stream.map_key_end()?;
484
485 stream.map_value_begin()?;
486 stream.value(&3)?;
487 stream.map_value_end()?;
488
489 stream.map_end()
490 }
491 }
492
493 struct Visitor(String);
494
495 impl<'v> Visit<'v> for Visitor {
496 fn visit_any(&mut self, v: ValueBag) -> Result<(), Error> {
497 self.0 = v.to_string();
498
499 Ok(())
500 }
501 }
502
503 let mut visitor = Visitor("".into());
504 ValueBag::from_sval2(&Data).visit(&mut visitor).unwrap();
505
506 assert_eq!("{ \"a\": 1, \"b\": 2, \"c\": 3 }", visitor.0);
507 }
508}