minicbor-serde: add support for serializing / deserializing custom CBOR tags#49
minicbor-serde: add support for serializing / deserializing custom CBOR tags#49mpanav wants to merge 4 commits intotwittner:developfrom
Conversation
Patch introduces wrapper tag types to enable deserialization and serialization of tagged values. Signed-off-by: Panav Munshi <mpanav@amazon.com>
Signed-off-by: Panav Munshi <mpanav@amazon.com>
Signed-off-by: Panav Munshi <mpanav@amazon.com>
Signed-off-by: Panav Munshi <mpanav@amazon.com>
twittner
left a comment
There was a problem hiding this comment.
Thanks! Overall this looks good to me. Just left some minor comments.
| match self.tagged { | ||
| true => { |
| } | ||
|
|
||
| enum State { | ||
| Tag(u64), |
There was a problem hiding this comment.
Why not a minicbor::data::Tag?
| Tag(u64), | |
| Tag(Tag), |
|
|
||
| struct EnumTagAccess<'a, 'de: 'a> { | ||
| deserializer: &'a mut Deserializer<'de>, | ||
| tag: Option<u64>, |
There was a problem hiding this comment.
| tag: Option<u64>, | |
| tag: Option<Tag>, |
| { | ||
| match self.state { | ||
| State::Tag(tag) => { | ||
| self.state = State::Value; |
There was a problem hiding this comment.
Perhaps the state should change after the tag was successfully deserialised? Probably does not make much of a difference in practice.
| /// custom aliases to ensure that [`crate::de::Deserializer`] is able to drive | ||
| /// the [`minicbor::Decoder`] correctly. | ||
| enum TagContainer<T> { | ||
| Tag(u64, T), |
There was a problem hiding this comment.
| Tag(u64, T), | |
| Tag(Tag, T), |
| found: u64, | ||
| expected: u64, |
There was a problem hiding this comment.
| found: u64, | |
| expected: u64, | |
| found: Tag, | |
| expected: Tag, |
| } | ||
|
|
||
| impl TagMismatchError { | ||
| fn new(found: u64, expected: u64) -> Self { |
There was a problem hiding this comment.
| fn new(found: u64, expected: u64) -> Self { | |
| fn new<A: Into<Tag>, B: Into<Tag>>(found: A, expected: B) -> Self { |
| /// | ||
| /// Tags will always be emitted during serialization | ||
| #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] | ||
| pub struct Required<const TAG: u64, T>(pub T); |
There was a problem hiding this comment.
| pub struct Required<const TAG: u64, T>(pub T); | |
| pub struct Required<const TAG: u64, T>(T); |
I would prefer not to expose the field publicly. Required is essentially Tagged, so the impl blocks from Tagged could be copied over here.
| /// | ||
| /// Tag will be emitted during serialization, if present | ||
| #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] | ||
| pub struct Optional<const TAG: u64, T>(pub Option<u64>, pub T); |
There was a problem hiding this comment.
| pub struct Optional<const TAG: u64, T>(pub Option<u64>, pub T); | |
| pub struct Optional<const TAG: u64, T>(Option<Tag>, T); | |
| impl<const TAG: u64, T> Optional<TAG, T> { | |
| pub fn tagged(val: T) -> Self { | |
| Self(Some(Tag::new(TAG)), val) | |
| } | |
| pub fn untagged(val: T) -> Self { | |
| Self(None, val) | |
| } | |
| pub fn tag(&self) -> Option<Tag> { | |
| self.0 | |
| } | |
| pub fn into_value(self) -> T { | |
| self.1 | |
| } | |
| } | |
| impl<const TAG: u64, T> Deref for Optional<TAG, T> { | |
| type Target = T; | |
| fn deref(&self) -> &Self::Target { | |
| &self.1 | |
| } | |
| } | |
| impl<const TAG: u64, T> DerefMut for Optional<TAG, T> { | |
| fn deref_mut(&mut self) -> &mut Self::Target { | |
| &mut self.1 | |
| } | |
| } |
Optional::tagged guarantees that the tag value matches the const TAG.
| /// | ||
| /// Tag will be emitted during serialization, if present | ||
| #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] | ||
| pub struct Any<T>(pub Option<u64>, pub T); |
There was a problem hiding this comment.
| pub struct Any<T>(pub Option<u64>, pub T); | |
| pub struct Any<T>(Option<Tag>, T); | |
| impl<T> Any<T> { | |
| pub fn tagged<N: Into<Tag>>(t: N, v: T) -> Self { | |
| Self(Some(t.into()), v) | |
| } | |
| pub fn untagged(v: T) -> Self { | |
| Self(None, v) | |
| } | |
| pub fn tag(&self) -> Option<Tag> { | |
| self.0 | |
| } | |
| pub fn into_value(self) -> T { | |
| self.1 | |
| } | |
| } | |
| impl<T> Deref for Any<T> { | |
| type Target = T; | |
| fn deref(&self) -> &Self::Target { | |
| &self.1 | |
| } | |
| } | |
| impl<T> DerefMut for Any<T> { | |
| fn deref_mut(&mut self) -> &mut Self::Target { | |
| &mut self.1 | |
| } | |
| } |
|
Thanks for the comments! I'll work through these and have a revision out soon :) |
Patch series adds support to deserialize / serialize custom tags in minicbor-serde.
See #44 for more details