add serde forwarding convenience macros

* forward_deserialize_to_from_str
* forward_serialize_to_display

Signed-off-by: Wolfgang Bumiller <w.bumiller@proxmox.com>
This commit is contained in:
Wolfgang Bumiller 2020-08-06 11:16:04 +02:00
parent 6da4dd5bbb
commit 6cd1aac558
3 changed files with 49 additions and 26 deletions

View File

@ -1,6 +1,9 @@
//! Proxmox "tools" package containing some generic tools along with the schema, API and CLI
//! helpers.
#[macro_use]
pub mod serde_macros;
pub mod api;
pub mod sys;
pub mod tools;

View File

@ -0,0 +1,44 @@
#[macro_export]
macro_rules! forward_deserialize_to_from_str {
($typename:ty) => {
impl<'de> serde::Deserialize<'de> for $typename {
fn deserialize<D>(deserializer: D) -> Result<$typename, D::Error>
where
D: serde::Deserializer<'de>,
{
use serde::de::Error;
struct ForwardToStrVisitor;
impl<'a> serde::de::Visitor<'a> for ForwardToStrVisitor {
type Value = $typename;
fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
formatter.write_str(concat!("a ", stringify!($typename)))
}
fn visit_str<E: Error>(self, v: &str) -> Result<$typename, E> {
v.parse::<$typename>()
.map_err(|err| Error::custom(err.to_string()))
}
}
deserializer.deserialize_str(ForwardToStrVisitor)
}
}
}
}
#[macro_export]
macro_rules! forward_serialize_to_display {
($typename:ty) => {
impl serde::Serialize for $typename {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::ser::Serializer,
{
serializer.serialize_str(&ToString::to_string(self))
}
}
}
}

View File

@ -4,7 +4,7 @@ use std::borrow::{Borrow, BorrowMut};
use std::fmt;
use anyhow::{bail, Error};
use serde::{Deserialize, Serialize, Serializer, Deserializer};
use serde::{Serialize, Serializer};
use crate::tools::parse::hex_nibble;
@ -207,31 +207,7 @@ impl Serialize for Uuid {
}
}
impl<'de> Deserialize<'de> for Uuid {
fn deserialize<D>(deserializer: D) -> Result<Uuid, D::Error>
where
D: Deserializer<'de>,
{
use serde::de::{Error, Visitor};
struct UuidVisitor;
impl<'a> Visitor<'a> for UuidVisitor {
type Value = Uuid;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("a uuid")
}
fn visit_str<E: Error>(self, v: &str) -> Result<Uuid, E> {
v.parse::<Uuid>()
.map_err(|err| Error::custom(err.to_string()))
}
}
deserializer.deserialize_str(UuidVisitor)
}
}
forward_deserialize_to_from_str!(Uuid);
#[test]
fn test_uuid() {