1use std::borrow::Cow;
2use std::fmt::Debug;
3
4pub trait StringRepr: AsRef<str> {}
5
6impl StringRepr for str {}
7impl StringRepr for String {}
8impl<'a> StringRepr for Cow<'a, str> {}
9impl<T: StringRepr + ?Sized> StringRepr for &T {}
10
11pub enum PrintMode {
13 Default,
16 Expanded,
18}
19
20pub trait PrintObject<'a> {
21 fn print_object(self, mode: PrintMode) -> Option<Cow<'a, str>>;
22}
23
24impl<'a, 'b: 'a, T: StringRepr + ?Sized + 'a> PrintObject<'a> for (&'b T,) {
25 fn print_object(self, mode: PrintMode) -> Option<Cow<'a, str>> {
26 match mode {
27 PrintMode::Default => Some(Cow::Borrowed(self.0.as_ref())),
28 PrintMode::Expanded => None,
29 }
30 }
31}
32
33impl<'a, 'b: 'a, T: Debug + 'a> PrintObject<'a> for &'b (T,) {
34 fn print_object(self, mode: PrintMode) -> Option<Cow<'a, str>> {
35 Some(
36 match mode {
37 PrintMode::Default => format!("{:?}", self.0),
38 PrintMode::Expanded => format!("{:#?}", self.0),
39 }
40 .into(),
41 )
42 }
43}
44
45impl<'a, 'b: 'a, T: 'a> PrintObject<'a> for &'b mut (T,) {
46 fn print_object(self, _mode: PrintMode) -> Option<Cow<'a, str>> {
47 fn type_name_of_val<T>(_: T) -> &'static str {
48 std::any::type_name::<T>()
49 }
50 let s = type_name_of_val(&self.0).trim_start_matches('&');
51 if s.is_empty() {
52 None
53 } else {
54 Some(Cow::Borrowed(s))
55 }
56 }
57}
58
59#[test]
60fn test_object() {
61 macro_rules! print_object {
62 ($expr:expr, $mode:ident) => {{
63 use $crate::print::PrintObject;
64 #[allow(unused_mut)]
65 let mut _tmp = ($expr,);
66 _tmp.print_object($crate::print::PrintMode::$mode)
67 .map(|x| x.to_string())
68 }};
69 }
70
71 struct NoDebugNoString;
72
73 struct DoNotCallMe;
74
75 impl DoNotCallMe {
76 #[allow(unused)]
77 fn print_object(&self, mode: PrintMode) {
78 panic!("never call me");
79 }
80 }
81
82 assert_eq!(
83 print_object!(&DoNotCallMe, Default).as_deref(),
84 Some("similar_asserts::print::test_object::DoNotCallMe")
85 );
86 assert_eq!(
87 print_object!(&NoDebugNoString, Default).as_deref(),
88 Some("similar_asserts::print::test_object::NoDebugNoString")
89 );
90 assert_eq!(
91 print_object!(vec![1, 2, 3], Default).as_deref(),
92 Some("[1, 2, 3]")
93 );
94 assert_eq!(
95 print_object!(vec![1, 2, 3], Expanded).as_deref(),
96 Some("[\n 1,\n 2,\n 3,\n]")
97 );
98 assert_eq!(print_object!(&"Hello", Default).as_deref(), Some("Hello"));
99 assert_eq!(print_object!(&"Hello", Expanded).as_deref(), None);
100}