musli_core/de/
unsized_visitor.rs

1use core::borrow::Borrow;
2use core::fmt;
3use core::marker::PhantomData;
4
5use crate::alloc::ToOwned;
6use crate::expecting::{self, Expecting};
7use crate::{Allocator, Context};
8
9/// A visitor for data where we might need to borrow without copying from the
10/// underlying [`Decoder`].
11///
12/// A visitor is needed with [`Decoder::decode_bytes`] and
13/// [`Decoder::decode_string`] because the caller doesn't know if the encoding
14/// format is capable of producing references to the underlying data directly or
15/// if it needs to be processed first.
16///
17/// If all you want is to decode a value by reference, use the
18/// [`Decoder::decode_unsized`] method.
19///
20/// By requiring a visitor we ensure that the caller has to handle both
21/// scenarios, even if one involves erroring. A type like [Cow] is an example of
22/// a type which can comfortably handle both.
23///
24/// [Cow]: std::borrow::Cow
25/// [`Decoder`]: crate::de::Decoder
26/// [`Decoder::decode_bytes`]: crate::de::Decoder::decode_bytes
27/// [`Decoder::decode_string`]: crate::de::Decoder::decode_string
28/// [`Decoder::decode_unsized`]: crate::de::Decoder::decode_unsized
29#[allow(unused_variables)]
30pub trait UnsizedVisitor<'de, C, T>: Sized
31where
32    C: Context<Error = Self::Error, Allocator = Self::Allocator>,
33    T: ?Sized + ToOwned,
34{
35    /// The value produced by the visitor.
36    type Ok;
37    /// The error produced by the visitor.
38    type Error;
39    /// The allocator associated with the visitor.
40    type Allocator: Allocator;
41
42    /// This is a type argument used to hint to any future implementor that they
43    /// should be using the
44    /// [`#[musli::de::unsized_visitor]`][musli::de::unsized_visitor] attribute
45    /// macro when implementing [`UnsizedVisitor`].
46    #[doc(hidden)]
47    type __UseMusliUnsizedVisitorAttributeMacro;
48
49    /// Format an error indicating what was expected by this visitor.
50    ///
51    /// Override to be more specific about the type that failed.
52    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
53
54    /// Visit an owned value.
55    #[inline]
56    fn visit_owned(self, cx: C, value: T::Owned<Self::Allocator>) -> Result<Self::Ok, Self::Error> {
57        self.visit_ref(cx, value.borrow())
58    }
59
60    /// Visit a string that is borrowed directly from the source data.
61    #[inline]
62    fn visit_borrowed(self, cx: C, value: &'de T) -> Result<Self::Ok, Self::Error> {
63        self.visit_ref(cx, value)
64    }
65
66    /// Visit a value reference that is provided from the decoder in any manner
67    /// possible. Which might require additional decoding work.
68    #[inline]
69    fn visit_ref(self, cx: C, value: &T) -> Result<Self::Ok, Self::Error> {
70        Err(cx.message(expecting::bad_visitor_type(
71            &expecting::AnyValue,
72            ExpectingWrapper::new(&self),
73        )))
74    }
75}
76
77#[repr(transparent)]
78struct ExpectingWrapper<'a, T, C, I>
79where
80    I: ?Sized,
81{
82    inner: T,
83    _marker: PhantomData<(C, &'a I)>,
84}
85
86impl<T, C, U> ExpectingWrapper<'_, T, C, U>
87where
88    U: ?Sized,
89{
90    #[inline]
91    fn new(value: &T) -> &Self {
92        // SAFETY: `ExpectingWrapper` is repr(transparent) over `T`.
93        unsafe { &*(value as *const T as *const Self) }
94    }
95}
96
97impl<'de, T, C, U> Expecting for ExpectingWrapper<'_, T, C, U>
98where
99    T: UnsizedVisitor<'de, C, U, Error = C::Error, Allocator = C::Allocator>,
100    C: Context,
101    U: ?Sized + ToOwned,
102{
103    #[inline]
104    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
105        self.inner.expecting(f)
106    }
107}