Improve from_json implementation for options response

Signed-off-by: trivernis <trivernis@protonmail.com>
main
trivernis 2 years ago
parent 3cb1aa0496
commit cb7f8e4194
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -5,13 +5,6 @@ use std::fmt::Debug;
pub use options::*;
#[macro_export]
macro_rules! fix {
($opt:expr) => {
$opt.ok_or_else(|| crate::Error::Malformed)?
};
}
pub trait Endpoint {
fn path() -> &'static str;
}

@ -1,7 +1,7 @@
use crate::hydrus_serializable::dictionary::HydrusDictionary;
use crate::hydrus_serializable::wrapper::HydrusSerWrapper;
use crate::Result;
use crate::{fix, Endpoint, FromJson, GetEndpoint};
use crate::{Endpoint, FromJson, GetEndpoint};
use serde_json::Value;
pub struct Options;
@ -18,26 +18,23 @@ impl GetEndpoint for Options {
#[derive(Clone, Debug)]
pub struct OptionsResponse {
server_message: String,
update_period: u64,
nullification_period: u64,
tag_filter: Value,
pub server_message: String,
pub update_period: u64,
pub nullification_period: u64,
pub tag_filter: Value,
}
impl FromJson for OptionsResponse {
fn from_json(value: serde_json::Value) -> Result<Self> {
let response = serde_json::from_value::<HydrusSerWrapper<HydrusDictionary>>(value)?;
let options_value = fix!(response.inner.get_one(&"service_options".into()));
let options_value =
serde_json::from_value::<HydrusSerWrapper<HydrusDictionary>>(options_value.clone())?
.inner;
let mut response = HydrusDictionary::from_json(value)?;
let mut service_options = response
.take_by_str::<HydrusSerWrapper<HydrusDictionary>>("service_options")?
.inner;
let server_message =
fix!(fix!(options_value.get_one(&"server_message".into())).as_str()).to_string();
let update_period = fix!(fix!(options_value.get_one(&"update_period".into())).as_u64());
let nullification_period =
fix!(fix!(options_value.get_one(&"nullification_period".into())).as_u64());
let tag_filter = fix!(options_value.get_one(&"tag_filter".into())).clone();
let server_message = service_options.take_by_str::<String>("server_message")?;
let update_period = service_options.take_by_str::<u64>("update_period")?;
let nullification_period = service_options.take_by_str::<u64>("nullification_period")?;
let tag_filter = service_options.take_by_str::<Value>(&"tag_filter")?;
Ok(Self {
server_message,

@ -21,4 +21,7 @@ pub enum Error {
#[error("malformed response")]
Malformed,
#[error("Missing property {0}")]
MissingProperty(String),
}

@ -1,5 +1,7 @@
use crate::constants::HYDRUS_TYPE_DICTIONARY;
use crate::hydrus_serializable::HydrusSerializable;
use crate::{Error, Result};
use serde::de::DeserializeOwned;
use serde::Deserialize;
use serde_json::Value;
@ -19,12 +21,31 @@ impl HydrusSerializable for HydrusDictionary {
impl HydrusDictionary {
/// Returns the first value for a given key
pub fn get_one(&self, key: &Value) -> Option<&Value> {
self.get(key).into_iter().next()
pub fn get(&self, key: &Value) -> Option<&Value> {
self._get(key).into_iter().next()
}
/// Returns a single value by using a string as a key
pub fn get_by_str<K: AsRef<str>>(&self, key: K) -> Option<&Value> {
self.get(&key.as_ref().into())
}
/// Removes an element deserialized as the given type from the dictionary
pub fn take<D: DeserializeOwned>(&mut self, key: &Value) -> Result<D> {
let value = self
._take(key)
.ok_or_else(|| Error::MissingProperty(key.to_string()))?;
serde_json::from_value::<D>(value).map_err(Error::from)
}
/// Removes an element with the given string key deserialized as the requested type from the dictionary
pub fn take_by_str<D: DeserializeOwned>(&mut self, key: &str) -> Result<D> {
self.take(&key.into())
}
/// Returns all values for a given key
pub fn get(&self, key: &Value) -> Vec<&Value> {
fn _get(&self, key: &Value) -> Vec<&Value> {
self.list_sim_sim
.iter()
.chain(self.list_sim_ser.iter())
@ -34,4 +55,21 @@ impl HydrusDictionary {
.map(|(_, v)| v)
.collect()
}
fn _take(&mut self, key: &Value) -> Option<Value> {
for list in [
&mut self.list_sim_sim,
&mut self.list_sim_ser,
&mut self.list_ser_sim,
&mut self.list_ser_ser,
] {
let index = list.iter().position(|(k, _)| k == key);
if let Some(index) = index {
return Some(list.swap_remove(index).1);
}
}
None
}
}

@ -1,12 +1,10 @@
use crate::hydrus_serializable::dictionary::HydrusDictionary;
use serde::de::{DeserializeOwned, EnumAccess, Error, MapAccess, SeqAccess, Visitor};
use serde::{Deserialize, Deserializer, Serialize};
use crate::hydrus_serializable::wrapper::HydrusSerWrapper;
use crate::FromJson;
use serde::de::{DeserializeOwned, Error, Visitor};
use serde::{Deserialize, Deserializer};
use serde_json::Value;
use std::cmp::Ordering;
use std::fmt::Formatter;
use std::hash::{Hash, Hasher};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
pub mod dictionary;
pub mod wrapper;
@ -15,6 +13,20 @@ pub trait HydrusSerializable: DeserializeOwned {
fn type_id() -> u64;
}
impl<T> FromJson for T
where
T: HydrusSerializable,
{
fn from_json(value: Value) -> crate::Result<Self>
where
Self: Sized,
{
let wrapper = serde_json::from_value::<HydrusSerWrapper<T>>(value)?;
Ok(wrapper.inner)
}
}
pub trait ConstNumberTrait {
fn value() -> u64;
}

Loading…
Cancel
Save