// Copyright 2015-2020 Parity Technologies (UK) Ltd. // This file is part of OpenEthereum. // OpenEthereum is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // OpenEthereum is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // You should have received a copy of the GNU General Public License // along with OpenEthereum. If not, see . //! Trie test input deserialization. use crate::bytes::Bytes; use serde::{ de::{Error as ErrorTrait, MapAccess, SeqAccess, Visitor}, Deserialize, Deserializer, }; use std::{collections::BTreeMap, fmt, str::FromStr}; /// Trie test input. #[derive(Debug, PartialEq)] pub struct Input { /// Input params. pub data: BTreeMap>, } impl<'a> Deserialize<'a> for Input { fn deserialize(deserializer: D) -> Result where D: Deserializer<'a>, { deserializer.deserialize_any(InputVisitor) } } struct InputVisitor; impl<'a> Visitor<'a> for InputVisitor { type Value = Input; fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!(formatter, "a map of bytes into bytes") } fn visit_map(self, mut visitor: V) -> Result where V: MapAccess<'a>, { let mut result = BTreeMap::new(); loop { let key_str: Option = visitor.next_key()?; let key = match key_str { Some(ref k) if k.starts_with("0x") => { Bytes::from_str(k).map_err(V::Error::custom)? } Some(k) => Bytes::new(k.into_bytes()), None => { break; } }; let val_str: Option = visitor.next_value()?; let val = match val_str { Some(ref v) if v.starts_with("0x") => { Some(Bytes::from_str(v).map_err(V::Error::custom)?) } Some(v) => Some(Bytes::new(v.into_bytes())), None => None, }; result.insert(key, val); } let input = Input { data: result }; Ok(input) } fn visit_seq(self, mut visitor: V) -> Result where V: SeqAccess<'a>, { let mut result = BTreeMap::new(); loop { let keyval: Option>> = visitor.next_element()?; let keyval = match keyval { Some(k) => k, _ => { break; } }; if keyval.len() != 2 { return Err(V::Error::custom("Invalid key value pair.")); } let ref key_str: Option = keyval[0]; let ref val_str: Option = keyval[1]; let key = match *key_str { Some(ref k) if k.starts_with("0x") => { Bytes::from_str(k).map_err(V::Error::custom)? } Some(ref k) => Bytes::new(k.clone().into_bytes()), None => { break; } }; let val = match *val_str { Some(ref v) if v.starts_with("0x") => { Some(Bytes::from_str(v).map_err(V::Error::custom)?) } Some(ref v) => Some(Bytes::new(v.clone().into_bytes())), None => None, }; result.insert(key, val); } let input = Input { data: result }; Ok(input) } } #[cfg(test)] mod tests { use super::Input; use crate::bytes::Bytes; use serde_json; use std::collections::BTreeMap; #[test] fn input_deserialization_from_map() { let s = r#"{ "0x0045" : "0x0123456789", "be" : "e", "0x0a" : null }"#; let input: Input = serde_json::from_str(s).unwrap(); let mut map = BTreeMap::new(); map.insert( Bytes::new(vec![0, 0x45]), Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])), ); map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65]))); map.insert(Bytes::new(vec![0x0a]), None); assert_eq!(input.data, map); } #[test] fn input_deserialization_from_array() { let s = r#"[ ["0x0045", "0x0123456789"], ["be", "e"], ["0x0a", null] ]"#; let input: Input = serde_json::from_str(s).unwrap(); let mut map = BTreeMap::new(); map.insert( Bytes::new(vec![0, 0x45]), Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])), ); map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65]))); map.insert(Bytes::new(vec![0x0a]), None); assert_eq!(input.data, map); } }