atlas_bincode/
lib.rs

1//! Contains a single utility function for deserializing from [bincode].
2//!
3//! [bincode]: https://docs.rs/bincode
4#![cfg_attr(docsrs, feature(doc_cfg))]
5
6use {bincode::config::Options, atlas_instruction_error::InstructionError};
7
8/// Deserialize with a limit based the maximum amount of data a program can expect to get.
9/// This function should be used in place of direct deserialization to help prevent OOM errors
10pub fn limited_deserialize<T>(instruction_data: &[u8], limit: u64) -> Result<T, InstructionError>
11where
12    T: serde_core::de::DeserializeOwned,
13{
14    bincode::options()
15        .with_limit(limit)
16        .with_fixint_encoding() // As per https://github.com/servo/bincode/issues/333, these two options are needed
17        .allow_trailing_bytes() // to retain the behavior of bincode::deserialize with the new `options()` method
18        .deserialize_from(instruction_data)
19        .map_err(|_| InstructionError::InvalidInstructionData)
20}
21
22#[cfg(test)]
23pub mod tests {
24    use {super::*, atlas_system_interface::instruction::SystemInstruction};
25
26    #[test]
27    fn test_limited_deserialize_advance_nonce_account() {
28        let item = SystemInstruction::AdvanceNonceAccount;
29        let mut serialized = bincode::serialize(&item).unwrap();
30
31        assert_eq!(
32            serialized.len(),
33            4,
34            "`SanitizedMessage::get_durable_nonce()` may need a change"
35        );
36
37        assert_eq!(
38            limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
39            Ok(&item)
40        );
41        assert!(limited_deserialize::<SystemInstruction>(&serialized, 3).is_err());
42
43        serialized.push(0);
44        assert_eq!(
45            limited_deserialize::<SystemInstruction>(&serialized, 4).as_ref(),
46            Ok(&item)
47        );
48    }
49}