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