1use std::sync::Arc;
4
5#[derive(Clone)]
9struct SerdeArc(Arc<dyn erased_serde::Serialize + Send + Sync + 'static>);
10
11impl SerdeArc {
12 fn new<T>(value: T) -> Self
13 where
14 T: serde::Serialize + Send + Sync + 'static,
15 {
16 Self(Arc::new(value))
17 }
18}
19
20impl serde::Serialize for SerdeArc {
21 fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
22 erased_serde::serialize(&*self.0, serializer)
23 }
24}
25
26#[derive(Clone)]
46pub struct ContextValue(ContextValueInner);
47
48#[derive(Clone)]
49enum ContextValueInner {
50 Null,
51 String(String),
52 Bool(bool),
53 Char(char),
54 I64(i64),
55 U64(u64),
56 F64(f64),
57 I128(i128),
58 U128(u128),
59 Debug(Arc<dyn std::fmt::Debug + Send + Sync + 'static>),
60 Display(Arc<dyn std::fmt::Display + Send + Sync + 'static>),
61 Error(Arc<dyn std::error::Error + Send + Sync + 'static>),
62 Serde(SerdeArc),
63}
64
65impl From<ContextValueInner> for ContextValue {
66 fn from(inner: ContextValueInner) -> Self {
67 Self(inner)
68 }
69}
70
71impl ContextValue {
72 #[allow(clippy::must_use_candidate)]
74 pub fn null() -> Self {
75 ContextValueInner::Null.into()
76 }
77
78 pub fn serde<S>(value: S) -> Self
80 where
81 S: serde::Serialize + Send + Sync + 'static,
82 {
83 ContextValueInner::Serde(SerdeArc::new(value)).into()
84 }
85
86 pub fn display<T>(value: T) -> Self
88 where
89 T: std::fmt::Display + Send + Sync + 'static,
90 {
91 ContextValueInner::Display(Arc::new(value)).into()
92 }
93
94 pub fn debug<T>(value: T) -> Self
96 where
97 T: std::fmt::Debug + Send + Sync + 'static,
98 {
99 ContextValueInner::Debug(Arc::new(value)).into()
100 }
101
102 pub fn error<T>(value: T) -> Self
104 where
105 T: std::error::Error + Send + Sync + 'static,
106 {
107 ContextValueInner::Error(Arc::new(value)).into()
108 }
109
110 #[must_use]
112 pub fn as_log_value(&self) -> log::kv::Value<'_> {
113 match &self.0 {
114 ContextValueInner::Null => log::kv::Value::null(),
115 ContextValueInner::String(s) => log::kv::Value::from(&**s),
116 ContextValueInner::Bool(b) => log::kv::Value::from(*b),
117 ContextValueInner::Char(c) => log::kv::Value::from(*c),
118 ContextValueInner::I64(i) => log::kv::Value::from(*i),
119 ContextValueInner::U64(u) => log::kv::Value::from(*u),
120 ContextValueInner::F64(f) => log::kv::Value::from(*f),
121 ContextValueInner::I128(i) => log::kv::Value::from(*i),
122 ContextValueInner::U128(u) => log::kv::Value::from(*u),
123 ContextValueInner::Display(value) => log::kv::Value::from_dyn_display(&**value),
124 ContextValueInner::Debug(value) => log::kv::Value::from_dyn_debug(&**value),
125 ContextValueInner::Error(value) => log::kv::Value::from_dyn_error(&**value),
126 ContextValueInner::Serde(value) => log::kv::Value::from_serde(value),
127 }
128 }
129}
130
131macro_rules! impl_context_value_from_primitive {
132 ($($ty:ty => $arm:ident),*) => {
133 $(
134 impl From<$ty> for ContextValue {
135 fn from(value: $ty) -> Self {
136 ContextValue(ContextValueInner::$arm(value.into()))
137 }
138 }
139 )*
140 };
141}
142
143impl_context_value_from_primitive!(
144 bool => Bool,
145 char => Char,
146 &str => String,
147 std::borrow::Cow<'_, str> => String,
148 String => String,
149 i8 => I64,
150 i16 => I64,
151 i32 => I64,
152 i64 => I64,
153 u8 => U64,
154 u16 => U64,
155 u32 => U64,
156 u64 => U64,
157 f32 => F64,
158 f64 => F64,
159 i128 => I128,
160 u128 => U128
161);
162
163impl std::fmt::Display for ContextValue {
164 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
165 self.as_log_value().fmt(f)
166 }
167}
168
169impl std::fmt::Debug for ContextValue {
170 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171 self.as_log_value().fmt(f)
172 }
173}