use serde_json::Value;
pub(crate) fn lenient_table<'de, D, T>(d: D) -> std::result::Result<Vec<(String, T)>, D::Error>
where
D: serde::Deserializer<'de>,
T: serde::Deserialize<'de>,
{
struct TableVisitor<T>(std::marker::PhantomData<T>);
impl<'de, T: serde::Deserialize<'de>> serde::de::Visitor<'de> for TableVisitor<T> {
type Value = Vec<(String, T)>;
fn expecting(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str("a table object")
}
fn visit_map<M: serde::de::MapAccess<'de>>(
self,
mut access: M,
) -> std::result::Result<Self::Value, M::Error> {
let mut rows = Vec::new();
while let Some((key, row)) = access.next_entry::<String, T>()? {
rows.push((key, row));
}
Ok(rows)
}
fn visit_seq<S: serde::de::SeqAccess<'de>>(
self,
mut access: S,
) -> std::result::Result<Self::Value, S::Error> {
while access.next_element::<serde::de::IgnoredAny>()?.is_some() {}
Ok(Vec::new())
}
fn visit_unit<E>(self) -> std::result::Result<Self::Value, E> {
Ok(Vec::new())
}
fn visit_bool<E>(self, _: bool) -> std::result::Result<Self::Value, E> {
Ok(Vec::new())
}
fn visit_i64<E>(self, _: i64) -> std::result::Result<Self::Value, E> {
Ok(Vec::new())
}
fn visit_u64<E>(self, _: u64) -> std::result::Result<Self::Value, E> {
Ok(Vec::new())
}
fn visit_f64<E>(self, _: f64) -> std::result::Result<Self::Value, E> {
Ok(Vec::new())
}
fn visit_str<E>(self, _: &str) -> std::result::Result<Self::Value, E> {
Ok(Vec::new())
}
}
d.deserialize_any(TableVisitor(std::marker::PhantomData))
}
pub(crate) fn sorted_rows<T>(
mut rows: Vec<(String, T)>,
index: impl Fn(&T) -> Option<i64>,
) -> Vec<(String, T)> {
rows.sort_by_key(|(_, row)| index(row).unwrap_or(0));
rows
}
pub(crate) fn lenient_f64<'de, D: serde::Deserializer<'de>>(
d: D,
) -> std::result::Result<Option<f64>, D::Error> {
use serde::Deserialize;
Ok(Option::<Value>::deserialize(d)?
.as_ref()
.and_then(Value::as_f64))
}
pub(crate) fn lenient_u64<'de, D: serde::Deserializer<'de>>(
d: D,
) -> std::result::Result<Option<u64>, D::Error> {
use serde::Deserialize;
Ok(Option::<Value>::deserialize(d)?
.as_ref()
.and_then(Value::as_u64))
}
pub(crate) fn lenient_i64<'de, D: serde::Deserializer<'de>>(
d: D,
) -> std::result::Result<Option<i64>, D::Error> {
use serde::Deserialize;
Ok(Option::<Value>::deserialize(d)?
.as_ref()
.and_then(Value::as_i64))
}
pub(crate) fn lenient_bool<'de, D: serde::Deserializer<'de>>(
d: D,
) -> std::result::Result<Option<bool>, D::Error> {
use serde::Deserialize;
Ok(Option::<Value>::deserialize(d)?
.as_ref()
.and_then(Value::as_bool))
}
pub(crate) fn lenient_string<'de, D: serde::Deserializer<'de>>(
d: D,
) -> std::result::Result<Option<String>, D::Error> {
use serde::Deserialize;
Ok(Option::<Value>::deserialize(d)?
.as_ref()
.and_then(Value::as_str)
.map(str::to_string))
}
pub(crate) fn lenient_flag<'de, D: serde::Deserializer<'de>>(
d: D,
) -> std::result::Result<Option<bool>, D::Error> {
use serde::Deserialize;
Ok(Option::<Value>::deserialize(d)?.map(|value| match value {
Value::Bool(b) => b,
other => other.as_f64() != Some(0.0),
}))
}