fe_common/utils/
ron.rs

1use difference::{Changeset, Difference};
2use serde::Serialize;
3use std::fmt;
4
5/// Return the lines of text in the string `lines` prefixed with the prefix in
6/// the string `prefix`.
7fn prefix_lines(prefix: &str, lines: &str) -> String {
8    lines
9        .lines()
10        .map(|i| [prefix, i].concat())
11        .collect::<Vec<String>>()
12        .join("\n")
13}
14
15/// Wrapper struct for formatting changesets from the `difference` package.
16pub struct Diff(Changeset);
17
18impl Diff {
19    pub fn new(left: &str, right: &str) -> Self {
20        Self(Changeset::new(left, right, "\n"))
21    }
22}
23
24impl fmt::Display for Diff {
25    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
26        for d in &self.0.diffs {
27            match *d {
28                Difference::Same(ref x) => {
29                    write!(f, "{}{}", prefix_lines(" ", x), self.0.split)?;
30                }
31                Difference::Add(ref x) => {
32                    write!(f, "\x1b[92m{}\x1b[0m{}", prefix_lines("+", x), self.0.split)?;
33                }
34                Difference::Rem(ref x) => {
35                    write!(f, "\x1b[91m{}\x1b[0m{}", prefix_lines("-", x), self.0.split)?;
36                }
37            }
38        }
39        Ok(())
40    }
41}
42
43/// Compare the given strings and panic when not equal with a colorized line
44/// diff.
45#[macro_export]
46macro_rules! assert_strings_eq {
47    ($left:expr, $right:expr,) => {{
48        assert_strings_eq!($left, $right)
49    }};
50    ($left:expr, $right:expr) => {{
51        match (&($left), &($right)) {
52            (left_val, right_val) => {
53                if *left_val != *right_val {
54                    panic!(
55                        "assertion failed: `(left == right)`\ndiff:\n{}",
56                        Diff::new(left_val, right_val),
57                    )
58                }
59            }
60        }
61    }};
62    ($left:expr, $right:expr, $($args:tt)*) => {{
63        match (&($left), &($right)) {
64            (left_val, right_val) => {
65                if *left_val != *right_val {
66                    panic!(
67                        "assertion failed: `(left == right)`: {}\ndiff:\n{}",
68                        format_args!($($args)*),
69                        Diff::new(left_val, right_val),
70                    )
71                }
72            }
73        }
74    }};
75}
76
77/// Convenience function to serialize objects in RON format with custom pretty
78/// printing config and struct names.
79pub fn to_ron_string_pretty<T>(value: &T) -> ron::ser::Result<String>
80where
81    T: Serialize,
82{
83    let config = ron::ser::PrettyConfig {
84        indentor: "  ".to_string(),
85        ..Default::default()
86    };
87
88    let mut serializer = ron::ser::Serializer::new(Some(config), true);
89    value.serialize(&mut serializer)?;
90
91    Ok(serializer.into_output_string())
92}