1use std::fmt::{Debug, Display, Formatter};
30
31#[derive(Debug)]
32pub enum FieldValue<'a> {
33 Int(i64),
34 UInt(u64),
35 Float(f32),
36 Double(f64),
37 String(&'a str),
38 Debug(&'a dyn Debug),
39 Boolean(bool),
40}
41
42impl Display for FieldValue<'_> {
43 fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
44 match self {
45 FieldValue::Int(v) => write!(f, "{}", v),
46 FieldValue::UInt(v) => write!(f, "{}", v),
47 FieldValue::Float(v) => write!(f, "{}", v),
48 FieldValue::Double(v) => write!(f, "{}", v),
49 FieldValue::String(v) => f.write_str(v),
50 FieldValue::Debug(v) => write!(f, "{:?}", v),
51 FieldValue::Boolean(v) => write!(f, "{:?}", v),
52 }
53 }
54}
55
56pub struct Field<'a> {
57 name: &'a str,
58 value: FieldValue<'a>,
59}
60
61impl<'a> Field<'a> {
62 pub fn new(name: &'a str, value: impl Into<FieldValue<'a>>) -> Self {
63 Self {
64 name,
65 value: value.into(),
66 }
67 }
68
69 pub fn new_debug(name: &'a str, value: &'a dyn Debug) -> Self {
70 Self {
71 name,
72 value: FieldValue::Debug(value),
73 }
74 }
75
76 pub fn name(&self) -> &str {
77 self.name
78 }
79
80 pub fn value(&self) -> &FieldValue<'a> {
81 &self.value
82 }
83}
84
85macro_rules! impl_into_field_value {
86 ($($t: ty => $func: ident),*) => {
88 $(
89 impl<'a> From<$t> for FieldValue<'a> {
90 fn from(value: $t) -> Self {
91 FieldValue::$func(value as _)
92 }
93 }
94 )*
95 };
96}
97
98impl_into_field_value! {
99 u8 => UInt,
100 u16 => UInt,
101 u32 => UInt,
102 u64 => UInt,
103 usize => UInt,
104 i8 => Int,
105 i16 => Int,
106 i32 => Int,
107 i64 => Int,
108 isize => Int,
109 f32 => Float,
110 f64 => Double,
111 bool => Boolean
112}
113
114impl<'a> From<&'a str> for FieldValue<'a> {
115 fn from(value: &'a str) -> Self {
116 Self::String(value)
117 }
118}
119
120pub struct FieldSet<'a, const N: usize>([Field<'a>; N]);
121
122impl<'a, const N: usize> FieldSet<'a, N> {
123 pub fn new(fields: [Field<'a>; N]) -> Self {
124 Self(fields)
125 }
126}
127
128impl<'a, const N: usize> AsRef<[Field<'a>]> for FieldSet<'a, N> {
129 fn as_ref(&self) -> &[Field<'a>] {
130 &self.0
131 }
132}
133
134#[macro_export]
135macro_rules! field {
136 ($name: ident) => {
137 $crate::field::Field::new(stringify!($name), $name)
138 };
139 (?$name: ident) => {
140 $crate::field::Field::new_debug(stringify!($name), &$name)
141 };
142 ($name: ident = $value: expr) => {
143 $crate::field::Field::new(stringify!($name), $value)
144 };
145 ($name: ident = ?$value: expr) => {
146 $crate::field::Field::new_debug(stringify!($name), &$value)
147 };
148}
149
150#[macro_export]
151macro_rules! fields {
152 ($({$($field: tt)*})*) => {
153 [$(
154 $crate::field!($($field)*),
155 )*]
156 };
157}