You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I have some data format for which I had implemented Deserializer. It has deserialize_struct, where I have if name == "SOME_STRUCT", then I calling visitor.visit_map() with very specific MapAccess.
All was perfectly fine, until I put this struct inside untagged enum.
My struct have Deserialize implementation, which calls deserializer.deserialize_struct("SOME_STRUCT", &["SOME_FIELDS"], MyVisitor). And as I see, serde does not try to call corresponding method in my deserializer, but uses deserialize_any and then sends first value which he found to MyVisitor. But this value is from my general MapAccess implementation, not custom one for SOME_STRUCT.
Is there some workarounds to fix this issue, or maybe possibility to implement some attribute to alter mechanic of untagged enum?
I'll try to describe my original problem, maybe it will give some context and we can to do something more useful than continue to complicate untagged enums.
I actually parsing yaml, but I need to be able report line:column of errors, and even if it was parsed successfully, I need to have line:column markers, because after parsing I processing parsed data and there still can be semantic errors, which I want to report too, pointing to specific lines/columns.
But actually, I think that there should be possibility to access internals of specific Deserializer instance from Deserialize, or ability to ask him somehow to return specific type even if this type do not implements Deserialize. I'll be happy, if I there will be Deserializer method like inspect_custom(&self, name: &str) -> Result<*const sometype, Error>, which I can call from Deserialize implementation and unsafely do my dark deeds if I needed to and current deserializer supports it. Maybe it possible to make more clean with some traits, but nothing comes to mind.
Thanks.
UPD: took a look at the sources, looks like all of this is impossible for untagged/internally tagged enums because of deserialization to Content which erases all information that has specific Deserializer :(
The text was updated successfully, but these errors were encountered:
After taking a sleep got idea for my case. Since I parsing already not a string/bytes, but my Deserializer works already on my type YamlNode, I can just avoid of using #[derive(Deserialize] for all my enums and write their implementations by hand, like:
enum EnumWithRaw {
Variant(String),
Raw(YamlNode),
}
impl<'de> Deserialize<'de> for EnumWithRaw {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>,
{
let raw: &YamlNode = Deserialize::deserialize(deserializer)?;
if let Ok(value) = decode_yaml(raw) {
return Ok(EnumWithRaw::Variant(value));
}
if let Ok(value) = decode_yaml(raw) {
return Ok(EnumWithRaw::Raw(value));
}
Err(D::Error::custom("bad news"))
}
}
And now I have enum that tries to parse to String, if it fails, then just returns underlying YamlNode for which I can print nice error, that in this context on specific line&column no suitable variant found.
But impl<'de> serde::de::Deserialize<'de> for &'de YamlNode is very scary, since currently it can be implemented only by very unsafe code:
MapAccess part:
let value = {
let node = self.node;
let ptr = node as *const YamlNode;
let ptr = ptr as u64;
ptr
}
let de = U64Deserializer::new(value);
seed.deserialize(de)
Visitor part:
if key != RAW_YAML_NODE_VALUE {
return Err(A::Error::custom("YamlNodeVisitor: key order missmatch"));
}
let node = unsafe {
let ptr = ptr as (*const YamlNode);
&*ptr
};
Ok(node)
Hello.
I have some data format for which I had implemented
Deserializer
. It hasdeserialize_struct
, where I haveif name == "SOME_STRUCT"
, then I callingvisitor.visit_map()
with very specificMapAccess
.All was perfectly fine, until I put this struct inside untagged enum.
My struct have
Deserialize
implementation, which callsdeserializer.deserialize_struct("SOME_STRUCT", &["SOME_FIELDS"], MyVisitor)
. And as I see, serde does not try to call corresponding method in my deserializer, but usesdeserialize_any
and then sends first value which he found toMyVisitor
. But this value is from my generalMapAccess
implementation, not custom one forSOME_STRUCT
.Is there some workarounds to fix this issue, or maybe possibility to implement some attribute to alter mechanic of untagged enum?
I'll try to describe my original problem, maybe it will give some context and we can to do something more useful than continue to complicate untagged enums.
I actually parsing yaml, but I need to be able report line:column of errors, and even if it was parsed successfully, I need to have line:column markers, because after parsing I processing parsed data and there still can be semantic errors, which I want to report too, pointing to specific lines/columns.
I found this solution in
toml
crate: https://docs.rs/toml/0.5.6/src/toml/spanned.rs.html#35-42 (which I think will fail too if you will putSpanned<String>
inside a untagged enum) and made mine in this style.But actually, I think that there should be possibility to access internals of specific
Deserializer
instance fromDeserialize
, or ability to ask him somehow to return specific type even if this type do not implementsDeserialize
. I'll be happy, if I there will beDeserializer
method likeinspect_custom(&self, name: &str) -> Result<*const sometype
, Error>, which I can call fromDeserialize
implementation and unsafely do my dark deeds if I needed to and current deserializer supports it. Maybe it possible to make more clean with some traits, but nothing comes to mind.Thanks.
UPD: took a look at the sources, looks like all of this is impossible for untagged/internally tagged enums because of deserialization to
Content
which erases all information that has specificDeserializer
:(The text was updated successfully, but these errors were encountered: