Skip to main content

musli_core/
expecting.rs

1//! Internal helpers for generating nice expectation messages.
2
3use core::fmt::{self, Display};
4
5use crate::de::SizeHint;
6
7pub trait Expecting {
8    /// Generated the actual message of what we expected.
9    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result;
10
11    /// Return a type that can be formatted from `self`.
12    #[doc(hidden)]
13    fn format(&self) -> &dyn Expecting
14    where
15        Self: Sized,
16    {
17        self
18    }
19}
20
21impl Expecting for str {
22    #[inline]
23    fn expecting(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
24        self.fmt(f)
25    }
26}
27
28impl fmt::Display for &dyn Expecting {
29    #[inline]
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        self.expecting(f)
32    }
33}
34
35struct FormatFn<T>(T);
36
37impl<T> fmt::Display for FormatFn<T>
38where
39    T: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
40{
41    #[inline]
42    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
43        (self.0)(f)
44    }
45}
46
47#[inline]
48fn format_fn<T>(function: T) -> FormatFn<T>
49where
50    T: Fn(&mut fmt::Formatter<'_>) -> fmt::Result,
51{
52    FormatFn(function)
53}
54
55/// Format an invalid type message.
56pub(crate) fn unsupported_type<'a>(
57    actual: &'a dyn fmt::Display,
58    expected: &'a dyn Expecting,
59) -> impl fmt::Display + 'a {
60    format_fn(move |f| {
61        write!(
62            f,
63            "Got unsupported type `{actual}`, but expected {expected}"
64        )
65    })
66}
67
68/// Format a bad visitor type message.
69pub(crate) fn bad_visitor_type<'a>(
70    actual: &'a dyn fmt::Display,
71    expected: &'a dyn Expecting,
72) -> impl fmt::Display + 'a {
73    format_fn(move |f| write!(f, "Bad reference type {actual}, expected {expected}",))
74}
75
76macro_rules! expect_with {
77    ($($vis:vis $ident:ident($string:literal, $ty:ty);)*) => {
78        $(
79            $vis struct $ident($vis $ty);
80
81            impl fmt::Display for $ident {
82                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
83                    write!(f, $string, self.0)
84                }
85            }
86        )*
87    }
88}
89
90macro_rules! expect {
91    ($($vis:vis $ident:ident($string:literal);)*) => {
92        $(
93            $vis struct $ident;
94
95            impl fmt::Display for $ident {
96                fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
97                    write!(f, $string)
98                }
99            }
100        )*
101    }
102}
103
104expect_with! {
105    pub(crate) SequenceWith("sequence with {0}", SizeHint);
106    pub(crate) MapWith("map with {0}", SizeHint);
107    pub(crate) BytesWith("bytes with {0}", SizeHint);
108    pub(crate) StringWith("string with {0}", SizeHint);
109}
110
111expect! {
112    pub(crate) Any("a dynamic value");
113    pub(crate) Empty("empty");
114    pub(crate) Option("option");
115    pub(crate) Pack("pack");
116    pub(crate) Bool("boolean");
117    pub(crate) Char("character");
118    pub(crate) Number("arbitrary precision number");
119    pub(crate) Unsigned8("8-bit unsigned integer");
120    pub(crate) Unsigned16("16-bit unsigned integer");
121    pub(crate) Unsigned32("32-bit unsigned integer");
122    pub(crate) Unsigned64("64-bit unsigned integer");
123    pub(crate) Unsigned128("128-bit unsigned integer");
124    pub(crate) Signed8("8-bit signed integer");
125    pub(crate) Signed16("16-bit signed integer");
126    pub(crate) Signed32("32-bit signed integer");
127    pub(crate) Signed64("64-bit signed integer");
128    pub(crate) Signed128("128-bit signed integer");
129    pub(crate) Float32("32-bit float");
130    pub(crate) Float64("64-bit float");
131    pub(crate) Isize("isize");
132    pub(crate) Usize("usize");
133    pub(crate) String("string");
134    pub(crate) Bytes("bytes");
135    pub(crate) Array("array");
136    pub(crate) Map("map");
137    pub(crate) MapEntries("map entries");
138    pub(crate) UnsizedMap("unsized map");
139    pub(crate) MapVariant("map variant");
140    pub(crate) UnsizedSequence("unsized sequence");
141    pub(crate) SequenceVariant("sequence variant");
142    pub(crate) Variant("variant");
143    pub(crate) AnyValue("a value");
144}