refactored client, added reports
This commit is contained in:
parent
bb015561c1
commit
6cc927031a
22 changed files with 9091 additions and 1 deletions
|
|
@ -1,2 +1,5 @@
|
|||
mod vec_log_err;
|
||||
pub mod range;
|
||||
pub mod text;
|
||||
|
||||
pub use vec_log_err::VecLogError;
|
||||
|
|
|
|||
132
src/serializer/vec_log_err.rs
Normal file
132
src/serializer/vec_log_err.rs
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
use std::{fmt, marker::PhantomData};
|
||||
|
||||
use serde::{
|
||||
de::{SeqAccess, Visitor},
|
||||
Deserialize,
|
||||
};
|
||||
use serde_with::{de::DeserializeAsWrap, DeserializeAs};
|
||||
|
||||
use crate::client2::MapResult;
|
||||
|
||||
pub struct VecLogError<T>(PhantomData<T>);
|
||||
|
||||
impl<'de, T, U> DeserializeAs<'de, MapResult<Vec<T>>> for VecLogError<U>
|
||||
where
|
||||
U: DeserializeAs<'de, T>,
|
||||
{
|
||||
fn deserialize_as<D>(deserializer: D) -> Result<MapResult<Vec<T>>, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
#[derive(serde::Deserialize)]
|
||||
#[serde(
|
||||
untagged,
|
||||
bound(deserialize = "DeserializeAsWrap<T, TAs>: Deserialize<'de>")
|
||||
)]
|
||||
enum GoodOrError<'a, T, TAs>
|
||||
where
|
||||
TAs: DeserializeAs<'a, T>,
|
||||
{
|
||||
Good(DeserializeAsWrap<T, TAs>),
|
||||
Error(serde_json::value::Value),
|
||||
#[serde(skip)]
|
||||
_JustAMarkerForTheLifetime(PhantomData<&'a u32>),
|
||||
}
|
||||
|
||||
struct SeqVisitor<T, U> {
|
||||
marker: PhantomData<T>,
|
||||
marker2: PhantomData<U>,
|
||||
}
|
||||
|
||||
impl<'de, T, U> Visitor<'de> for SeqVisitor<T, U>
|
||||
where
|
||||
U: DeserializeAs<'de, T>,
|
||||
{
|
||||
type Value = MapResult<Vec<T>>;
|
||||
|
||||
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
formatter.write_str("a sequence")
|
||||
}
|
||||
|
||||
fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
|
||||
where
|
||||
A: SeqAccess<'de>,
|
||||
{
|
||||
let mut values = Vec::with_capacity(seq.size_hint().unwrap_or_default());
|
||||
let mut warnings = Vec::new();
|
||||
|
||||
while let Some(value) = seq.next_element()? {
|
||||
match value {
|
||||
GoodOrError::<T, U>::Good(value) => {
|
||||
values.push(value.into_inner());
|
||||
}
|
||||
GoodOrError::<T, U>::Error(value) => {
|
||||
warnings.push(format!(
|
||||
"error deserializing item: {}",
|
||||
serde_json::to_string(&value).unwrap_or_default()
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(MapResult {
|
||||
c: values,
|
||||
warnings,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
let visitor = SeqVisitor::<T, U> {
|
||||
marker: PhantomData,
|
||||
marker2: PhantomData,
|
||||
};
|
||||
deserializer.deserialize_seq(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use serde::Deserialize;
|
||||
use serde_with::serde_as;
|
||||
|
||||
use crate::client2::MapResult;
|
||||
|
||||
#[serde_as]
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct S {
|
||||
#[serde_as(as = "crate::serializer::VecLogError<_>")]
|
||||
items: MapResult<Vec<Item>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
struct Item {
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test() {
|
||||
let json = r#"{"items": [{"name": "i1"}, {"xyz": "i2"}, {"name": "i3"}, {"namra": "i4"}]}"#;
|
||||
|
||||
let res = serde_json::from_str::<S>(json).unwrap();
|
||||
|
||||
insta::assert_debug_snapshot!(res, @r###"
|
||||
S {
|
||||
items: [
|
||||
Item {
|
||||
name: "i1",
|
||||
},
|
||||
Item {
|
||||
name: "i3",
|
||||
},
|
||||
],
|
||||
}
|
||||
"###);
|
||||
|
||||
insta::assert_debug_snapshot!(res.items.warnings, @r###"
|
||||
[
|
||||
"error deserializing item: {\"xyz\":\"i2\"}",
|
||||
"error deserializing item: {\"namra\":\"i4\"}",
|
||||
]
|
||||
"###);
|
||||
}
|
||||
}
|
||||
Reference in a new issue