1use std::fmt::Debug;
2
3use crate::context::AnyValue;
4
5pub trait Converter: Debug + Send + Sync + 'static {}
17
18#[derive(Debug)]
20pub struct DebugConverter;
21
22impl Converter for DebugConverter {}
23
24#[derive(Debug)]
27pub struct IntoConverter;
28
29impl Converter for IntoConverter {}
30
31#[derive(Debug)]
34pub struct BoxConverter;
35
36impl Converter for BoxConverter {}
37
38pub trait Convertable<C: Converter, T>: Sized {
44 fn to(self) -> T;
56}
57
58impl<S: Debug, T: From<String>> Convertable<DebugConverter, T> for S {
59 fn to(self) -> T {
60 format!("{self:?}").into()
61 }
62}
63
64impl<S: Into<T>, T> Convertable<IntoConverter, T> for S {
65 fn to(self) -> T {
66 self.into()
67 }
68}
69
70impl<S, T> Convertable<BoxConverter, T> for S
71where
72 S: AnyValue,
73 T: From<Box<dyn AnyValue + Send + Sync + 'static>>,
74{
75 fn to(self) -> T {
76 let res: Box<dyn AnyValue + Send + Sync + 'static> = Box::new(self);
77 res.into()
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use super::*;
84
85 type BoxAnyValue = Box<dyn AnyValue + Send + Sync + 'static>;
86
87 #[test]
88 fn converter_convert_succeeds() {
89 assert_eq!(<_ as Convertable<DebugConverter, String>>::to(1), "1");
90 assert_eq!(
91 <_ as Convertable<DebugConverter, String>>::to("1"),
92 r#""1""#
93 );
94
95 assert_eq!(
96 <_ as Convertable<IntoConverter, String>>::to("str"),
97 String::from("str")
98 );
99
100 let res = <_ as Convertable<BoxConverter, BoxAnyValue>>::to("1");
101 assert_eq!(format!("{res:?}"), "\"1\"");
102 }
103
104 #[test]
105 fn converter_convert_succeeds_when_delegated_by_function() {
106 fn do_with<C: Converter, S: Convertable<C, T>, T>(source: S) -> T {
107 source.to()
108 }
109
110 assert_eq!(do_with::<DebugConverter, _, String>(1), "1");
111 assert_eq!(do_with::<DebugConverter, _, String>("1"), "\"1\"");
112
113 assert_eq!(
114 do_with::<IntoConverter, _, String>("str"),
115 String::from("str")
116 );
117
118 let res = do_with::<BoxConverter, _, BoxAnyValue>("1");
119 assert_eq!(format!("{res:?}"), "\"1\"");
120 }
121}