Skip to main content

mx20022_model/common/
builder.rs

1//! Builder error type for generated builder pattern implementations.
2
3/// Error returned when a builder cannot construct a valid type because one or
4/// more required fields were not set.
5///
6/// # Example
7///
8/// ```
9/// use mx20022_model::common::BuilderError;
10///
11/// let err = BuilderError {
12///     type_name: "BusinessApplicationHeaderV04".to_owned(),
13///     missing_fields: vec!["fr".to_owned(), "biz_msg_idr".to_owned()],
14/// };
15/// assert!(err.to_string().contains("BusinessApplicationHeaderV04"));
16/// assert!(err.to_string().contains("fr"));
17/// ```
18#[derive(Debug, Clone, PartialEq, Eq)]
19pub struct BuilderError {
20    /// The type being built (e.g. `"BusinessApplicationHeaderV04"`).
21    pub type_name: String,
22    /// Names of required fields that were not set before calling `.build()`.
23    pub missing_fields: Vec<String>,
24}
25
26impl std::fmt::Display for BuilderError {
27    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
28        write!(
29            f,
30            "cannot build `{}`: missing required fields: [{}]",
31            self.type_name,
32            self.missing_fields.join(", ")
33        )
34    }
35}
36
37impl std::error::Error for BuilderError {}
38
39#[cfg(test)]
40mod tests {
41    use super::*;
42
43    #[test]
44    fn display_single_field() {
45        let err = BuilderError {
46            type_name: "Foo".to_owned(),
47            missing_fields: vec!["bar".to_owned()],
48        };
49        let s = err.to_string();
50        assert!(s.contains("Foo"), "type name in message: {s}");
51        assert!(s.contains("bar"), "field name in message: {s}");
52    }
53
54    #[test]
55    fn display_multiple_fields() {
56        let err = BuilderError {
57            type_name: "Foo".to_owned(),
58            missing_fields: vec!["a".to_owned(), "b".to_owned(), "c".to_owned()],
59        };
60        let s = err.to_string();
61        assert!(s.contains("a"), "{s}");
62        assert!(s.contains("b"), "{s}");
63        assert!(s.contains("c"), "{s}");
64    }
65
66    #[test]
67    fn error_trait_implemented() {
68        let err = BuilderError {
69            type_name: "T".to_owned(),
70            missing_fields: vec![],
71        };
72        // std::error::Error is object-safe and the impl compiles
73        let _: &dyn std::error::Error = &err;
74    }
75
76    #[test]
77    fn clone_and_eq() {
78        let err = BuilderError {
79            type_name: "T".to_owned(),
80            missing_fields: vec!["x".to_owned()],
81        };
82        assert_eq!(err.clone(), err);
83    }
84}