crux_cli/codegen/serde_generate/
error.rs1#![allow(dead_code)]
5
6use serde::{de, ser};
7use std::fmt;
8use thiserror::Error;
9
10use super::format::ContainerFormat;
11
12pub type Result<T, E = Error> = std::result::Result<T, E>;
14
15#[derive(Clone, Debug, Error, PartialEq)]
17pub enum Error {
18 #[error("{0}")]
19 Custom(String),
20 #[error("Not supported: {0}")]
21 NotSupported(&'static str),
22 #[error("Failed to deserialize {0}")]
23 Deserialization(&'static str),
24 #[error("In container {0}, recorded value for serialization format {1:?} failed to deserialize into {2}")]
25 UnexpectedDeserializationFormat(&'static str, ContainerFormat, &'static str),
26 #[error("Incompatible formats detected: {0} {1}")]
27 Incompatible(String, String),
28 #[error("Incomplete tracing detected")]
29 UnknownFormat,
30 #[error("Incomplete tracing detected inside container: {0}")]
31 UnknownFormatInContainer(String),
32 #[error("Missing variants detected for specific enums: {0:?}")]
33 MissingVariants(Vec<String>),
34}
35
36impl ser::Error for Error {
37 fn custom<T: fmt::Display>(msg: T) -> Self {
38 Error::Custom(format!("Failed to serialize value: \"{msg}\""))
39 }
40}
41
42impl de::Error for Error {
43 fn custom<T: fmt::Display>(msg: T) -> Self {
44 Error::Custom(format!("Failed to deserialize value: \"{msg}\""))
45 }
46}
47
48impl Error {
49 pub fn explanation(&self) -> String {
51 use Error::{
52 Custom, Deserialization, Incompatible, MissingVariants, NotSupported,
53 UnexpectedDeserializationFormat, UnknownFormat, UnknownFormatInContainer,
54 };
55
56 match self {
57 Custom(_) => {
58 r"
59An error was returned by a Serde trait during (de)serialization tracing. In practice, this happens when
60user-provided code 'impl<'de> Deserialize<'de> for Foo { .. }' rejects a candidate value of type `Foo`
61provided by serde-reflection.
62
63To fix this, add a call `tracer.trace_value(foo, &mut samples)` so that a correct value `foo` is
64recorded *before* `tracer.trace_type` is called.
65".to_string()
66 }
67 NotSupported(_) => {
68 r#"
69An unsupported callback was called during (de)serialization tracing. In practice, this happens when an
70unsupported Serde attribute is used. Attributes specific to self-describing formats (JSON, YAML, TOML)
71are generally not supported. This includes: `#[serde(flatten)]`, `#[serde(tag = "type")]`,
72`#[serde(tag = "t", content = "c")]`, and `#[serde(untagged)]`.
73
74To fix this, avoid unsupported Serde attributes or use custom (de)serialize implementations with different
75behaviors depending on the Serde callback `(De)Serializer::is_human_readable()`.
76"#.to_string()
77 }
78 Deserialization(_) => {
79 r"
80This internal error should not be surfaced during tracing.
81".to_string()
82 }
83 UnexpectedDeserializationFormat(_, _, _) => {
84 r"
85A value recorded by `trace_value` fails to deserialize as expected during a `trace_type` call. This can
86happen if custom implementations of the Serialize and Deserialize traits do not agree.
87
88Verify the implementations of Serialize and Deserialize for the given format.
89".to_string()
90 }
91
92 Incompatible(_, _) => {
93 r"
94Two formats computed for the same entity do not match. This can happen if custom implementations of
95the Serialize and Deserialize traits do not agree, e.g. if one uses `Vec<u8>` and the other one uses `&[u8]`
96(implying bytes) --- see the crate `serde_bytes` for more context in this particular example.
97
98Verify the implementations of Serialize and Deserialize for the given format.
99".to_string()
100 }
101 UnknownFormat => {
102 r"
103This internal error is returned should not be surfaced during tracing.
104".to_string()
105 }
106 UnknownFormatInContainer(name) => {
107 format!(r"
108A final registry was requested but some formats are still unknown within the container {name}. This can
109happen if `tracer.trace_value` was called on a value `foo` which does not reveal some of the underlying
110formats. E.g. if a field `x` of struct `Foo` has type `Option<String>` and `foo` is value of type
111`Foo` such that `foo.x == None`, then tracing the value `foo` may result in a format `Option<Unknown>`
112for the field `x`. The same applies to empty vectors and empty maps.
113
114To fix this, avoid `trace_value` and prefer `trace_type` when possible, or make sure to trace at
115least one value `foo` such that `foo.x` is not empty.
116")
117 }
118 MissingVariants(names) => {
119 format!(r"
120A registry was requested with `tracer.registry()` but some variants have not been analyzed yet
121inside the given enums {names:?}.
122
123To fix this, make sure to call `tracer.trace_type<T>(..)` at least once for each enum type `T` in the
124corpus of definitions. You may also use `tracer.registry_unchecked()` for debugging.
125")
126 }
127 }
128 }
129}