-
Notifications
You must be signed in to change notification settings - Fork 744
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
Fix identifier deserialization from non-u32 #963
Conversation
Maybe @dtolnay can talk about why |
This looks good to me. If I recall correctly, I think the compiler represents c-like variants as u32, so we just were expecting that. I'm not sure if there's any real cost here to casting up to u64. If we really wanted to be fancy we could generate methods without the cast, but I bet the compiler can optimize all this away. |
(Responding jointly to this and #961.) I don't have a strong opinion on these, but there are some downsides.
pyfisch/cbor#37 is unfortunate but is that a real use case? I would just say packed CBOR does not support |
serde_yaml can already deserialize It's also gross for deserializers to have to remember that The only reason to use a map for the packed encoding is so that you can skip fields. Otherwise you'd just serialize the fields into an array. |
The behavior here is also equivalent to how the deserializers for every numeric type work, right? |
There are binary formats that do not keep the size of an int. |
@dtolnay ping - again, this is just making the behavior for identifiers match that of other integer types. |
This is what's required to work around this in the case of CBOR, for reference: macro_rules! forward_visit {
($name:ident, bound $bound:path) => {
fn $name<A>(self, a: A) -> result::Result<V::Value, A::Error>
where
A: $bound,
{
(self.0).$name(a)
}
};
($name:ident, $ty:ty) => {
fn $name<E>(self, v: $ty) -> result::Result<V::Value, E>
where
E: de::Error,
{
(self.0).$name(v)
}
};
($name:ident) => {
fn $name<E>(self) -> result::Result<V::Value, E>
where
E: de::Error,
{
(self.0).$name()
}
}
}
macro_rules! cast_visit {
($name:ident, $ty:ty) => {
fn $name<E>(self, v: $ty) -> result::Result<V::Value, E>
where E: de::Error
{
self.visit_u32(v as u32)
}
}
}
// identifiers only deserialize from u32, but we compact down to u8/u16 during
// serialization
struct IdentifierVisitor<V>(V);
impl<'de, V> de::Visitor<'de> for IdentifierVisitor<V>
where
V: de::Visitor<'de>,
{
type Value = V::Value;
fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
self.0.expecting(fmt)
}
forward_visit!(visit_bool, bool);
forward_visit!(visit_i8, i8);
forward_visit!(visit_i16, i16);
forward_visit!(visit_i32, i32);
forward_visit!(visit_i64, i64);
cast_visit!(visit_u8, u8);
cast_visit!(visit_u16, u16);
forward_visit!(visit_u32, u32);
forward_visit!(visit_u64, u64);
forward_visit!(visit_f32, f32);
forward_visit!(visit_f64, f64);
forward_visit!(visit_char, char);
forward_visit!(visit_str, &str);
forward_visit!(visit_borrowed_str, &'de str);
forward_visit!(visit_string, String);
forward_visit!(visit_bytes, &[u8]);
forward_visit!(visit_borrowed_bytes, &'de [u8]);
forward_visit!(visit_byte_buf, Vec<u8>);
forward_visit!(visit_none);
forward_visit!(visit_some, bound de::Deserializer<'de>);
forward_visit!(visit_unit);
forward_visit!(visit_newtype_struct, bound de::Deserializer<'de>);
forward_visit!(visit_seq, bound de::SeqAccess<'de>);
forward_visit!(visit_map, bound de::MapAccess<'de>);
forward_visit!(visit_enum, bound de::EnumAccess<'de>);
} |
Closes #962