mirror of
https://github.com/lennart-k/rustical.git
synced 2025-12-13 20:32:48 +00:00
xml: Differentiate between ValueSerialize and ValueDeserialize to prevent unwraps
This commit is contained in:
@@ -9,7 +9,7 @@ use rustical_store::{
|
||||
synctoken::{format_synctoken, parse_synctoken},
|
||||
CalendarStore,
|
||||
};
|
||||
use rustical_xml::{Value, XmlDeserialize};
|
||||
use rustical_xml::{ValueDeserialize, ValueSerialize, XmlDeserialize};
|
||||
|
||||
use crate::{
|
||||
calendar_object::resource::{CalendarObjectProp, CalendarObjectResource},
|
||||
@@ -22,7 +22,7 @@ pub(crate) enum SyncLevel {
|
||||
Infinity,
|
||||
}
|
||||
|
||||
impl Value for SyncLevel {
|
||||
impl ValueDeserialize for SyncLevel {
|
||||
fn deserialize(val: &str) -> Result<Self, rustical_xml::XmlDeError> {
|
||||
Ok(match val {
|
||||
"1" => Self::One,
|
||||
@@ -34,6 +34,9 @@ impl Value for SyncLevel {
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueSerialize for SyncLevel {
|
||||
fn serialize(&self) -> String {
|
||||
match self {
|
||||
SyncLevel::One => "1",
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
use derive_more::derive::From;
|
||||
use rustical_xml::{XmlDeserialize, XmlSerialize};
|
||||
use rustical_xml::XmlSerialize;
|
||||
|
||||
#[derive(Debug, Clone, XmlDeserialize, XmlSerialize, PartialEq, From)]
|
||||
#[derive(Debug, Clone, XmlSerialize, PartialEq, From)]
|
||||
pub struct SupportedCalendarComponent {
|
||||
#[xml(ty = "attr")]
|
||||
pub name: &'static str,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, XmlDeserialize, XmlSerialize, PartialEq)]
|
||||
#[derive(Debug, Clone, XmlSerialize, PartialEq)]
|
||||
pub struct SupportedCalendarComponentSet {
|
||||
#[xml(ns = "rustical_dav::namespace::NS_CALDAV", flatten)]
|
||||
pub comp: Vec<SupportedCalendarComponent>,
|
||||
|
||||
@@ -29,7 +29,7 @@ pub enum PrincipalProp {
|
||||
Displayname(String),
|
||||
|
||||
// Scheduling Extensions to CalDAV (RFC 6638)
|
||||
#[xml(ns = "rustical_dav::namespace::NS_CALDAV")]
|
||||
#[xml(ns = "rustical_dav::namespace::NS_CALDAV", skip_deserializing)]
|
||||
CalendarUserType(&'static str),
|
||||
#[xml(ns = "rustical_dav::namespace::NS_CALDAV")]
|
||||
CalendarUserAddressSet(HrefElement),
|
||||
|
||||
@@ -13,7 +13,7 @@ use rustical_store::{
|
||||
synctoken::{format_synctoken, parse_synctoken},
|
||||
AddressbookStore,
|
||||
};
|
||||
use rustical_xml::{Value, XmlDeserialize};
|
||||
use rustical_xml::{ValueDeserialize, ValueSerialize, XmlDeserialize};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub(crate) enum SyncLevel {
|
||||
@@ -21,7 +21,7 @@ pub(crate) enum SyncLevel {
|
||||
Infinity,
|
||||
}
|
||||
|
||||
impl Value for SyncLevel {
|
||||
impl ValueDeserialize for SyncLevel {
|
||||
fn deserialize(val: &str) -> Result<Self, rustical_xml::XmlDeError> {
|
||||
Ok(match val {
|
||||
"1" => Self::One,
|
||||
@@ -33,6 +33,8 @@ impl Value for SyncLevel {
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
impl ValueSerialize for SyncLevel {
|
||||
fn serialize(&self) -> String {
|
||||
match self {
|
||||
SyncLevel::One => "1",
|
||||
|
||||
@@ -7,7 +7,7 @@ use ical::{
|
||||
property::Property,
|
||||
};
|
||||
use lazy_static::lazy_static;
|
||||
use rustical_xml::Value;
|
||||
use rustical_xml::{ValueDeserialize, ValueSerialize};
|
||||
use std::{collections::HashMap, ops::Add};
|
||||
|
||||
lazy_static! {
|
||||
@@ -21,9 +21,9 @@ pub const LOCAL_DATE: &str = "%Y%m%d";
|
||||
#[derive(Debug, Clone, Deref, PartialEq)]
|
||||
pub struct UtcDateTime(DateTime<Utc>);
|
||||
|
||||
impl Value for UtcDateTime {
|
||||
impl ValueDeserialize for UtcDateTime {
|
||||
fn deserialize(val: &str) -> Result<Self, rustical_xml::XmlDeError> {
|
||||
let input = <String as Value>::deserialize(val)?;
|
||||
let input = <String as ValueDeserialize>::deserialize(val)?;
|
||||
Ok(Self(
|
||||
NaiveDateTime::parse_from_str(&input, UTC_DATE_TIME)
|
||||
.map_err(|_| {
|
||||
@@ -32,6 +32,8 @@ impl Value for UtcDateTime {
|
||||
.and_utc(),
|
||||
))
|
||||
}
|
||||
}
|
||||
impl ValueSerialize for UtcDateTime {
|
||||
fn serialize(&self) -> String {
|
||||
format!("{}", self.0.format(UTC_DATE_TIME))
|
||||
}
|
||||
|
||||
@@ -232,7 +232,7 @@ impl Field {
|
||||
let builder_field_ident = self.builder_field_ident();
|
||||
let value = wrap_option_if_no_default(
|
||||
quote! {
|
||||
rustical_xml::Value::deserialize(text.as_ref())?
|
||||
::rustical_xml::ValueDeserialize::deserialize(text.as_ref())?
|
||||
},
|
||||
self.attrs.default.is_some(),
|
||||
);
|
||||
@@ -250,8 +250,8 @@ impl Field {
|
||||
|
||||
let value = wrap_option_if_no_default(
|
||||
quote! {
|
||||
rustical_xml::Value::deserialize(attr.unescape_value()?.as_ref())?
|
||||
},
|
||||
::rustical_xml::ValueDeserialize::deserialize(attr.unescape_value()?.as_ref())?
|
||||
},
|
||||
self.attrs.default.is_some(),
|
||||
);
|
||||
|
||||
@@ -270,7 +270,7 @@ impl Field {
|
||||
|
||||
let value = wrap_option_if_no_default(
|
||||
quote! {
|
||||
rustical_xml::Value::deserialize(&String::from_utf8_lossy(name.as_ref()))?
|
||||
rustical_xml::ValueDeserialize::deserialize(&String::from_utf8_lossy(name.as_ref()))?
|
||||
},
|
||||
self.attrs.default.is_some(),
|
||||
);
|
||||
|
||||
@@ -239,7 +239,7 @@ impl NamedStruct {
|
||||
quote! {
|
||||
::quick_xml::events::attributes::Attribute {
|
||||
key: ::quick_xml::name::QName(#field_name),
|
||||
value: ::std::borrow::Cow::from(::rustical_xml::Value::serialize(&self.#field_index).into_bytes())
|
||||
value: ::std::borrow::Cow::from(::rustical_xml::ValueSerialize::serialize(&self.#field_index).into_bytes())
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -13,7 +13,7 @@ pub use de::XmlDocument;
|
||||
pub use error::XmlDeError;
|
||||
pub use se::XmlSerialize;
|
||||
pub use se::XmlSerializeRoot;
|
||||
pub use value::Value;
|
||||
pub use value::{ParseValueError, ValueDeserialize, ValueSerialize};
|
||||
pub use xml_derive::XmlRootTag;
|
||||
|
||||
impl XmlDeserialize for () {
|
||||
|
||||
@@ -17,18 +17,23 @@ pub enum ParseValueError {
|
||||
ParseFloatError(#[from] ParseFloatError),
|
||||
}
|
||||
|
||||
pub trait Value: Sized {
|
||||
pub trait ValueSerialize: Sized {
|
||||
fn serialize(&self) -> String;
|
||||
}
|
||||
|
||||
pub trait ValueDeserialize: Sized {
|
||||
fn deserialize(val: &str) -> Result<Self, XmlDeError>;
|
||||
}
|
||||
|
||||
macro_rules! impl_value_parse {
|
||||
($t:ty) => {
|
||||
impl Value for $t {
|
||||
impl ValueSerialize for $t {
|
||||
fn serialize(&self) -> String {
|
||||
self.to_string()
|
||||
}
|
||||
}
|
||||
|
||||
impl ValueDeserialize for $t {
|
||||
fn deserialize(val: &str) -> Result<Self, XmlDeError> {
|
||||
val.parse()
|
||||
.map_err(ParseValueError::from)
|
||||
@@ -52,17 +57,13 @@ impl_value_parse!(u64);
|
||||
impl_value_parse!(isize);
|
||||
impl_value_parse!(usize);
|
||||
|
||||
impl Value for &str {
|
||||
impl ValueSerialize for &str {
|
||||
fn serialize(&self) -> String {
|
||||
self.to_string()
|
||||
}
|
||||
|
||||
fn deserialize(_val: &str) -> Result<Self, XmlDeError> {
|
||||
Err(XmlDeError::Other("TODO: Handle this error".to_owned()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Value> XmlDeserialize for T {
|
||||
impl<T: ValueDeserialize> XmlDeserialize for T {
|
||||
fn deserialize<R: BufRead>(
|
||||
reader: &mut quick_xml::NsReader<R>,
|
||||
_start: &BytesStart,
|
||||
@@ -88,11 +89,11 @@ impl<T: Value> XmlDeserialize for T {
|
||||
}
|
||||
}
|
||||
|
||||
Value::deserialize(&string)
|
||||
ValueDeserialize::deserialize(&string)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Value> XmlSerialize for T {
|
||||
impl<T: ValueSerialize> XmlSerialize for T {
|
||||
fn serialize<W: std::io::Write>(
|
||||
&self,
|
||||
ns: Option<Namespace>,
|
||||
|
||||
Reference in New Issue
Block a user