Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions zerompk/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#![no_std]

#[cfg(test)]
extern crate self as zerompk;

mod consts;
mod error;
mod r#impl;
Expand Down
26 changes: 25 additions & 1 deletion zerompk/src/read.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1477,7 +1477,31 @@ impl<'de, R: std::io::Read> Read<'de> for IOReader<R> {

#[cfg(test)]
mod tests {
use super::*;
use crate::{Error, FromMessagePack, Read, read::IOReader, read::SliceReader};

#[allow(dead_code)]
#[derive(Debug, zerompk_derive::FromMessagePack)]
#[msgpack(map)]
struct DuplicateKeyMap {
x: u8,
y: u8,
}

#[test]
fn derived_map_struct_duplicate_key_restores_reader_depth() {
let data = [
0x82, // fixmap with 2 entries
0xa1, b'x', // fixstr of length 1: "x"
0x01, // positive fixint: 1
0xa1, b'x', // fixstr of length 1: "x" (duplicate key)
0x02, // positive fixint: 2
];
let mut reader = SliceReader::new(&data);

let err = DuplicateKeyMap::read(&mut reader).unwrap_err();

assert!(matches!(err, Error::KeyDuplicated(ref key) if key == "x"));
}

#[test]
fn slice_reader_decrement_depth_at_zero_does_not_underflow() {
Expand Down
12 changes: 8 additions & 4 deletions zerompk_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1128,7 +1128,7 @@ fn expand_map_struct(data: &DataStruct) -> Result<ImplBody> {
quote! {
#idx => {
if #slot.is_some() {
return Err(::zerompk::Error::KeyDuplicated(#key_name.into()));
break '__zerompk_read_map Err(::zerompk::Error::KeyDuplicated(#key_name.into()));
}
#slot = ::core::option::Option::Some(#read_expr);
}
Expand Down Expand Up @@ -1167,6 +1167,7 @@ fn expand_map_struct(data: &DataStruct) -> Result<ImplBody> {
};

let read = quote! {
'__zerompk_read_map: {
reader.check_map_len(#count)?;

#( let mut #slots: ::core::option::Option<#tys> = ::core::option::Option::None; )*
Expand All @@ -1189,7 +1190,8 @@ fn expand_map_struct(data: &DataStruct) -> Result<ImplBody> {
let #names = #slots.ok_or_else(|| ::zerompk::Error::KeyNotFound(#key_lits.into()))?;
)*

Ok(Self { #( #init_fields ),* })
break '__zerompk_read_map Ok(Self { #( #init_fields ),* });
}
};

Ok(ImplBody { write, read })
Expand Down Expand Up @@ -1690,7 +1692,7 @@ fn build_enum_variant_payload(
quote! {
#idx => {
if #slot.is_some() {
return Err(::zerompk::Error::KeyDuplicated(#key_name.into()));
break '__zerompk_read_map Err(::zerompk::Error::KeyDuplicated(#key_name.into()));
}
#slot = ::core::option::Option::Some(#read_expr);
}
Expand Down Expand Up @@ -1734,6 +1736,7 @@ fn build_enum_variant_payload(
};

let read_ctor = quote! {
'__zerompk_read_map: {
reader.check_map_len(#count)?;

#( let mut #slot_vars: ::core::option::Option<#active_tys> = ::core::option::Option::None; )*
Expand All @@ -1756,7 +1759,8 @@ fn build_enum_variant_payload(
let #active_names = #slot_vars.ok_or_else(|| ::zerompk::Error::KeyNotFound(#key_lits.into()))?;
)*

Ok(Self::#v_ident { #( #init_fields ),* })
break '__zerompk_read_map Ok(Self::#v_ident { #( #init_fields ),* });
}
};

Ok((
Expand Down