use serde_json::Value;
use sqlx::{ColumnIndex, Decode, Row, Type, ValueRef};
macro_rules! first_decoded {
($row:expr, $name:expr, $($ty:ty),+ $(,)?) => {{
$(
if let Ok(value) = $row.try_get::<$ty, _>($name) {
return serde_json::json!(value);
}
)+
Value::String("<unprintable>".to_string())
}};
}
pub trait DecodableRow {
fn decode_value(&self, name: &str) -> Value;
fn decode_display(&self, name: &str) -> String {
match self.decode_value(name) {
Value::Null => "NULL".to_string(),
Value::String(text) => text,
other => other.to_string(),
}
}
}
impl<R> DecodableRow for R
where
R: Row,
for<'a> &'a str: ColumnIndex<R>,
for<'a> String: Decode<'a, R::Database> + Type<R::Database>,
for<'a> i32: Decode<'a, R::Database> + Type<R::Database>,
for<'a> i64: Decode<'a, R::Database> + Type<R::Database>,
for<'a> f64: Decode<'a, R::Database> + Type<R::Database>,
for<'a> bool: Decode<'a, R::Database> + Type<R::Database>,
{
fn decode_value(&self, name: &str) -> Value {
match self.try_get_raw(name) {
Ok(raw) if raw.is_null() => return Value::Null,
Ok(_) => {}
Err(_) => return Value::String("<error>".to_string()),
}
first_decoded!(self, name, String, bool, i32, i64, f64)
}
}