-
Notifications
You must be signed in to change notification settings - Fork 46
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Serde Deserialize and Serialize impls #149
Comments
I'm not necessarily opposed to it, but curious what your use case is, and what that would look like in practice. Since type annotations would be required for deserialization, would the deserializer try to parse a number, and just check whether it's the expected value for the type? For serialization, do we just go to the number? In that case, is it really more convenient than serializing the associated constant? De/serializing zero-sized types seems pretty strange to me, but I'm open to it if you have a use case that can't otherwise be ergonomically handled. |
My use case was essentially something like this which would allow deserializing from a sequence such as a JSON array #[derive(Deserialize)]
#[serde(untagged)]
enum Msg {
Subscribe { _op: U0, path: String, oneshot: bool },
Unsubscribe { _op: U1, path: String },
}
// ...
// Msg::Subscribe { _op: Default::default(), path: "/somewhere/something".to_string(), oneshot: true }
let _: Msg = from_str("[0, \"/somewhere/something\", true]")?;
let _: Msg = from_str("[1, \"/somewhere_else/something_else\"]")?; ideally this would be supported by renaming variants to a number but this currently isn't supported. #[derive(Deserialize)]
#[serde(tag = "_op")]
enum Msg {
#[rename = 0]
Subscribe { path: String, oneshot: bool },
#[rename = 1]
Unsubscribe { path: String },
} Unfortunately as far as I know there is no way to specify that serde should serialize as a sequence but this at least gets half of the way there by deriving a Deserialize impl and as I mentioned before is useful for map based data.
Yes: assert!(from_str::<U0>("0").is_ok());
assert!(from_str::<U1>("0").is_err());
Yes also and this allows for the example I showed with enum variants with the constant number being defined as part of the type for that specific variant.
I admit this is an extremely strange idea but it seems to kind of make sense as a way to represent this, I'd be open for any suggestions of how to handle this otherwise without a handwritten deserialize impl. |
I also made a simple implementation for a newtype wrapper of just unsigned ints to show what it could look like. (This probably could be optimized for (de)serializing to smaller sized ints with a Le trait bound but I haven't tried that) use core::fmt;
use serde::{
de::{self, Deserializer, Visitor},
ser::Serializer,
Deserialize, Serialize,
};
use typenum::marker_traits::Unsigned;
#[derive(Default)]
pub struct Wrapper<T>(pub T);
#[derive(Default)]
struct UnsignedVisitor<T>(T);
impl<'de, U: Unsigned> Visitor<'de> for UnsignedVisitor<U> {
type Value = U;
fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
formatter.write_fmt(format_args!("{}", Self::Value::U64))
}
fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
where
E: de::Error,
{
if v == Self::Value::U64 {
Ok(self.0)
} else {
Err(E::custom(format!(
"expected {} but got {}",
Self::Value::U64,
v
)))
}
}
}
impl<'de, U: Unsigned> Deserialize<'de> for Wrapper<U> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
deserializer
.deserialize_u64(UnsignedVisitor::default())
.map(Wrapper)
}
}
impl<U: Unsigned> Serialize for Wrapper<U> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_u64(U::U64)
}
} |
Hi - my use case for this feature is attempting to use serde to serialize/deserialize constants in the Neptune library. I get the following error: the trait `Serialize` is not implemented for `UInt<UInt<UTerm, B1>, B0>` Is this a valid use case? generic-array serializes and deserializes generic arrays that use UInts but they serialize/derserialize outside of the typenum library. Is that what you recommend is done? |
Would you accept a PR that added serde Deserialize and Serialize implementations (behind a feature gate)?
The text was updated successfully, but these errors were encountered: