├── .github ├── dependabot.yml └── workflows │ ├── check_streams.yml │ └── ci.yml ├── .gitignore ├── .mergify.yml ├── Cargo.toml ├── LICENSE ├── Makefile.toml ├── README.md ├── example ├── Cargo.toml └── src │ └── main.rs ├── release.toml ├── src ├── common │ └── mod.rs ├── dynamodb │ ├── de.rs │ ├── mod.rs │ └── ser.rs ├── dynamodbstreams │ ├── de.rs │ ├── mod.rs │ └── ser.rs ├── error.rs └── lib.rs ├── tests ├── dynamodb.rs └── dynamodbstreams.rs └── update_streams.sh /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: cargo 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | time: "04:00" 8 | open-pull-requests-limit: 10 9 | -------------------------------------------------------------------------------- /.github/workflows/check_streams.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | 6 | name: Check dynamodb streams implementation has been updated 7 | 8 | jobs: 9 | check_streams: 10 | # macos because script use macos syntax for sed... 11 | runs-on: macos-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Update dynamodb streams 17 | run: ./update_streams.sh 18 | 19 | - name: Check for changes 20 | run: if [[ -z "$(git status --porcelain)" ]]; then exit 0; else exit 1; fi 21 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | on: 2 | pull_request: 3 | push: 4 | 5 | name: Continuous integration 6 | 7 | jobs: 8 | ci: 9 | runs-on: ubuntu-latest 10 | strategy: 11 | matrix: 12 | rust: 13 | - stable 14 | - beta 15 | - nightly 16 | 17 | steps: 18 | - uses: actions/checkout@v2 19 | 20 | - name: Setup Rust 21 | uses: actions-rs/toolchain@v1 22 | with: 23 | profile: minimal 24 | toolchain: ${{ matrix.rust }} 25 | override: true 26 | components: rustfmt, clippy 27 | 28 | - name: Build 29 | uses: actions-rs/cargo@v1 30 | with: 31 | command: build 32 | args: --features streams-rustls 33 | 34 | - name: Test 35 | uses: actions-rs/cargo@v1 36 | with: 37 | command: test 38 | args: --features streams-rustls 39 | 40 | - name: Format 41 | uses: actions-rs/cargo@v1 42 | with: 43 | command: fmt 44 | args: --all -- --check 45 | 46 | - name: Clippy 47 | uses: actions-rs/cargo@v1 48 | with: 49 | command: clippy 50 | args: --features streams-rustls -- -D warnings 51 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # rust 2 | target/ 3 | *.rs.bk 4 | Cargo.lock 5 | .idea/ 6 | serde_dynamodb.iml 7 | -------------------------------------------------------------------------------- /.mergify.yml: -------------------------------------------------------------------------------- 1 | pull_request_rules: 2 | - name: automatic merge for Dependabot pull requests 3 | conditions: 4 | - author=dependabot[bot] 5 | - status-success=Travis CI - Pull Request 6 | actions: 7 | merge: 8 | method: merge 9 | - name: automatic merge for Dependabot/travis with actual conditions pull requests 10 | conditions: 11 | - author=dependabot-preview[bot] 12 | - status-success=continuous-integration/travis-ci/pr 13 | actions: 14 | merge: 15 | method: merge 16 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde_dynamodb" 3 | version = "0.9.1-dev" 4 | authors = ["François Mockers "] 5 | description = "de/serialize struct to HashMap with Serde to use with Rusoto DynamoDB" 6 | repository = "https://github.com/mockersf/serde_dynamodb" 7 | homepage = "https://github.com/mockersf/serde_dynamodb" 8 | documentation = "https://docs.rs/serde_dynamodb" 9 | keywords = ["serde", "dynamodb", "rusoto"] 10 | license = "MIT" 11 | readme = "README.md" 12 | edition = "2018" 13 | 14 | [dependencies] 15 | serde = "1.0" 16 | rusoto_dynamodb = { version = "0.47.0", default-features = false, optional = true } 17 | rusoto_dynamodbstreams = { version = "0.47.0", default-features = false, optional = true } 18 | bytes = "1.0" 19 | 20 | [dev-dependencies] 21 | serde = { version = "1.0", features = [ "derive" ] } 22 | rusoto_core = { version = "0.47.0", default-features = false } 23 | rusoto_dynamodb = { version = "0.47.0", default-features = false } 24 | 25 | [features] 26 | default = ["rusoto_dynamodb", "rusoto_dynamodb/rustls"] 27 | 28 | rustls = ["rusoto_dynamodb", "rusoto_dynamodb/rustls"] 29 | native-tls = ["rusoto_dynamodb", "rusoto_dynamodb/native-tls"] 30 | 31 | streams = ["rusoto_dynamodbstreams", "rusoto_dynamodbstreams/rustls"] 32 | streams-rustls = ["rusoto_dynamodbstreams", "rusoto_dynamodbstreams/rustls"] 33 | streams-native-tls = ["rusoto_dynamodbstreams", "rusoto_dynamodbstreams/native-tls"] 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 François Mockers 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile.toml: -------------------------------------------------------------------------------- 1 | [env] 2 | CARGO_MAKE_EXTEND_WORKSPACE_MAKEFILE = "true" 3 | 4 | [tasks.check-rusoto-versions] 5 | ignore_errors = true 6 | script = [ 7 | "pwd", 8 | "find . -name Cargo.toml | xargs -I % grep 'rusoto.* = \"' %" 9 | ] 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # serde_dynamodb [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Release Doc](https://docs.rs/serde_dynamodb/badge.svg)](https://docs.rs/serde_dynamodb) [![Crate](https://img.shields.io/crates/v/serde_dynamodb.svg)](https://crates.io/crates/serde_dynamodb) 2 | 3 | > **Warning** 4 | > 5 | > This repository is archived as there is now an official SDK for dynamodb, which this crate doesn't use. 6 | 7 | Library to de/serialize an object to an `HashMap` of `AttributeValue`s used by [rusoto_dynamodb](https://crates.io/crates/rusoto_dynamodb) to manipulate objects saved in dynamodb using [serde](https://serde.rs) 8 | 9 | ## Example 10 | 11 | ```rust 12 | #[derive(Serialize, Deserialize)] 13 | struct Todo { 14 | id: uuid::Uuid, 15 | title: &'static str, 16 | done: bool, 17 | } 18 | 19 | let todo = Todo { 20 | id: uuid::Uuid::new_v4(), 21 | title: "publish crate", 22 | done: false, 23 | }; 24 | 25 | let put_item = PutItemInput { 26 | item: serde_dynamodb::to_hashmap(&todo).unwrap(), 27 | table_name: "todos".to_string(), 28 | ..Default::default() 29 | }; 30 | 31 | let client = DynamoDbClient::simple(Region::UsEast1); 32 | client.put_item(&put_item).unwrap(); 33 | ``` 34 | 35 | -------------------------------------------------------------------------------- /example/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "example" 3 | version = "0.1.0" 4 | authors = ["François Mockers "] 5 | edition = "2018" 6 | 7 | [dependencies] 8 | serde = "*" 9 | serde_derive = "*" 10 | serde_dynamodb = { path = "../serde_dynamodb" } 11 | serde_dynamodb_derive = { path = "../serde_dynamodb_derive" } 12 | 13 | rusoto_core = "0.47.0" 14 | rusoto_dynamodb = "0.47.0" 15 | 16 | uuid = { version = "0.8", features = ["serde", "v4"] } 17 | 18 | futures = "0.3" 19 | -------------------------------------------------------------------------------- /example/src/main.rs: -------------------------------------------------------------------------------- 1 | #![allow(clippy::redundant_closure)] 2 | 3 | use futures::executor::block_on; 4 | 5 | use serde::{Deserialize, Serialize}; 6 | 7 | use rusoto_core::Region; 8 | use rusoto_dynamodb::{DynamoDb, DynamoDbClient, PutItemInput, QueryInput}; 9 | 10 | use serde_dynamodb::ToQueryInput; 11 | use serde_dynamodb_derive::ToQueryInput; 12 | 13 | #[derive(Serialize, Deserialize, ToQueryInput)] 14 | struct Task { 15 | id: String, 16 | #[serde(rename = "mystatus")] 17 | status: Option, 18 | } 19 | 20 | fn main() { 21 | let client = DynamoDbClient::new(Region::UsEast1); 22 | 23 | let task = Task { 24 | id: String::from("Entry ID"), 25 | status: Some(String::from("some status")), 26 | }; 27 | 28 | let _query_params = PutItemInput { 29 | table_name: String::from("TableName"), 30 | item: serde_dynamodb::to_hashmap(&task).unwrap(), 31 | ..Default::default() 32 | }; 33 | 34 | let task_query_input = TaskQueryInput { 35 | id: Some("Entry Id".to_string()), 36 | ..Default::default() 37 | }; 38 | 39 | let _my_tasks: Vec = 40 | block_on(client.query(task_query_input.to_query_input(String::from("tableName")))) 41 | .unwrap() 42 | .items 43 | .unwrap_or_else(|| vec![]) 44 | .into_iter() 45 | .map(|item| serde_dynamodb::from_hashmap(item).unwrap()) 46 | .collect(); 47 | } 48 | -------------------------------------------------------------------------------- /release.toml: -------------------------------------------------------------------------------- 1 | pre-release-commit-message="chore: version {{version}}" 2 | post-release-commit-message="chore: start next development iteration {{next_version}}" 3 | tag-prefix="" 4 | tag-name="{{prefix}}{{version}}" 5 | tag-message="chore: {{version}}" 6 | dev-version-ext="dev" 7 | -------------------------------------------------------------------------------- /src/common/mod.rs: -------------------------------------------------------------------------------- 1 | use crate::error::{Error, Result}; 2 | 3 | macro_rules! impl_serialize_to_string { 4 | ($type:ty, $method:ident) => { 5 | fn $method(self, value: $type) -> Result<()> { 6 | self.result = Some(format!("{}", value)); 7 | Ok(()) 8 | } 9 | }; 10 | } 11 | 12 | #[derive(Debug)] 13 | pub(crate) struct SimpleKeySerializer { 14 | result: Option, 15 | } 16 | 17 | impl SimpleKeySerializer { 18 | #[allow(clippy::new_without_default)] 19 | pub fn new() -> Self { 20 | SimpleKeySerializer { result: None } 21 | } 22 | 23 | pub fn get_result(self) -> String { 24 | self.result.expect("error serializing key") 25 | } 26 | } 27 | impl<'a> serde::Serializer for &'a mut SimpleKeySerializer { 28 | type Ok = (); 29 | type Error = Error; 30 | 31 | type SerializeSeq = Compound; 32 | type SerializeTuple = Compound; 33 | type SerializeTupleStruct = Compound; 34 | type SerializeTupleVariant = Compound; 35 | type SerializeMap = Compound; 36 | type SerializeStruct = Compound; 37 | type SerializeStructVariant = Compound; 38 | 39 | impl_serialize_to_string!(bool, serialize_bool); 40 | impl_serialize_to_string!(i8, serialize_i8); 41 | impl_serialize_to_string!(i16, serialize_i16); 42 | impl_serialize_to_string!(i32, serialize_i32); 43 | impl_serialize_to_string!(i64, serialize_i64); 44 | impl_serialize_to_string!(u8, serialize_u8); 45 | impl_serialize_to_string!(u16, serialize_u16); 46 | impl_serialize_to_string!(u32, serialize_u32); 47 | impl_serialize_to_string!(u64, serialize_u64); 48 | impl_serialize_to_string!(f32, serialize_f32); 49 | impl_serialize_to_string!(f64, serialize_f64); 50 | impl_serialize_to_string!(char, serialize_char); 51 | impl_serialize_to_string!(&str, serialize_str); 52 | 53 | fn serialize_bytes(self, _value: &[u8]) -> Result<()> { 54 | Err(Error { 55 | message: String::from("can't serialize as a key as it's of type bytes"), 56 | }) 57 | } 58 | 59 | fn serialize_unit(self) -> Result<()> { 60 | Err(Error { 61 | message: String::from("can't serialize as a key as it's of type unit"), 62 | }) 63 | } 64 | 65 | fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { 66 | Err(Error { 67 | message: String::from("can't serialize as a key as it's of type unit struct"), 68 | }) 69 | } 70 | 71 | fn serialize_unit_variant( 72 | self, 73 | _name: &'static str, 74 | _variant_index: u32, 75 | _variant: &'static str, 76 | ) -> Result<()> { 77 | Err(Error { 78 | message: String::from("can't serialize as a key as it's of type unit variant"), 79 | }) 80 | } 81 | 82 | fn serialize_newtype_struct(self, _name: &'static str, _value: &T) -> Result<()> 83 | where 84 | T: serde::ser::Serialize, 85 | { 86 | Err(Error { 87 | message: String::from("can't serialize as a key as it's of type newtype struct"), 88 | }) 89 | } 90 | 91 | #[inline] 92 | fn serialize_newtype_variant( 93 | self, 94 | _name: &'static str, 95 | _variant_index: u32, 96 | _variant: &'static str, 97 | _value: &T, 98 | ) -> Result<()> 99 | where 100 | T: serde::ser::Serialize, 101 | { 102 | Err(Error { 103 | message: String::from("can't serialize as a key as it's of type newtype variant"), 104 | }) 105 | } 106 | 107 | fn serialize_none(self) -> Result<()> { 108 | Err(Error { 109 | message: String::from("can't serialize as a key as it's of type none"), 110 | }) 111 | } 112 | 113 | fn serialize_some(self, _value: &T) -> Result<()> 114 | where 115 | T: serde::ser::Serialize, 116 | { 117 | Err(Error { 118 | message: String::from("can't serialize as a key as it's of type unit option"), 119 | }) 120 | } 121 | 122 | fn serialize_seq(self, _len: Option) -> Result { 123 | Err(Error { 124 | message: String::from("can't serialize as a key as it's of type seq"), 125 | }) 126 | } 127 | 128 | fn serialize_tuple(self, _len: usize) -> Result { 129 | Err(Error { 130 | message: String::from("can't serialize as a key as it's of type tuple"), 131 | }) 132 | } 133 | 134 | fn serialize_tuple_struct( 135 | self, 136 | _name: &'static str, 137 | _len: usize, 138 | ) -> Result { 139 | Err(Error { 140 | message: String::from("can't serialize as a key as it's of type tuple struct"), 141 | }) 142 | } 143 | 144 | fn serialize_tuple_variant( 145 | self, 146 | _name: &'static str, 147 | _variant_index: u32, 148 | _variant: &'static str, 149 | _len: usize, 150 | ) -> Result { 151 | Err(Error { 152 | message: String::from("can't serialize as a key as it's of type tuple variant"), 153 | }) 154 | } 155 | 156 | fn serialize_map(self, _len: Option) -> Result { 157 | Err(Error { 158 | message: String::from("can't serialize as a key as it's of type map"), 159 | }) 160 | } 161 | 162 | fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { 163 | Err(Error { 164 | message: String::from("can't serialize as a key as it's of type struct"), 165 | }) 166 | } 167 | 168 | fn serialize_struct_variant( 169 | self, 170 | _name: &'static str, 171 | _variant_index: u32, 172 | _variant: &'static str, 173 | _len: usize, 174 | ) -> Result { 175 | Err(Error { 176 | message: String::from("can't serialize as a key as it's of type struct variant"), 177 | }) 178 | } 179 | } 180 | 181 | impl serde::ser::SerializeSeq for Compound { 182 | type Ok = (); 183 | type Error = Error; 184 | 185 | fn serialize_element(&mut self, _value: &T) -> Result<()> 186 | where 187 | T: serde::ser::Serialize, 188 | { 189 | unreachable!() 190 | } 191 | 192 | fn end(self) -> Result<()> { 193 | unreachable!() 194 | } 195 | } 196 | 197 | #[derive(Clone, Copy, Debug)] 198 | pub(crate) struct Compound; 199 | impl serde::ser::SerializeTuple for Compound { 200 | type Ok = (); 201 | type Error = Error; 202 | 203 | fn serialize_element(&mut self, _value: &T) -> Result<()> 204 | where 205 | T: serde::ser::Serialize, 206 | { 207 | unreachable!() 208 | } 209 | 210 | #[inline] 211 | fn end(self) -> Result<()> { 212 | unreachable!() 213 | } 214 | } 215 | 216 | impl serde::ser::SerializeTupleStruct for Compound { 217 | type Ok = (); 218 | type Error = Error; 219 | 220 | fn serialize_field(&mut self, _value: &T) -> Result<()> 221 | where 222 | T: serde::ser::Serialize, 223 | { 224 | unreachable!() 225 | } 226 | 227 | fn end(self) -> Result<()> { 228 | unreachable!() 229 | } 230 | } 231 | 232 | impl serde::ser::SerializeTupleVariant for Compound { 233 | type Ok = (); 234 | type Error = Error; 235 | 236 | fn serialize_field(&mut self, _value: &T) -> Result<()> 237 | where 238 | T: serde::ser::Serialize, 239 | { 240 | unreachable!() 241 | } 242 | 243 | fn end(self) -> Result<()> { 244 | unreachable!() 245 | } 246 | } 247 | 248 | impl serde::ser::SerializeMap for Compound { 249 | type Ok = (); 250 | type Error = Error; 251 | 252 | fn serialize_key(&mut self, _key: &T) -> Result<()> 253 | where 254 | T: serde::ser::Serialize, 255 | { 256 | unreachable!() 257 | } 258 | 259 | fn serialize_value(&mut self, _value: &T) -> Result<()> 260 | where 261 | T: serde::ser::Serialize, 262 | { 263 | unreachable!() 264 | } 265 | 266 | fn end(self) -> Result<()> { 267 | unreachable!() 268 | } 269 | } 270 | 271 | impl serde::ser::SerializeStruct for Compound { 272 | type Ok = (); 273 | type Error = Error; 274 | 275 | fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<()> 276 | where 277 | T: serde::ser::Serialize, 278 | { 279 | unreachable!() 280 | } 281 | 282 | fn end(self) -> Result<()> { 283 | unreachable!() 284 | } 285 | } 286 | 287 | impl serde::ser::SerializeStructVariant for Compound { 288 | type Ok = (); 289 | type Error = Error; 290 | 291 | fn serialize_field(&mut self, _key: &'static str, _value: &T) -> Result<()> 292 | where 293 | T: serde::ser::Serialize, 294 | { 295 | unreachable!() 296 | } 297 | 298 | fn end(self) -> Result<()> { 299 | unreachable!() 300 | } 301 | } 302 | -------------------------------------------------------------------------------- /src/dynamodb/de.rs: -------------------------------------------------------------------------------- 1 | //! Deserialize an HashMap into a Rust data structure. 2 | 3 | use std::collections::HashMap; 4 | 5 | use rusoto_dynamodb::AttributeValue; 6 | 7 | use serde::de::IntoDeserializer; 8 | 9 | use crate::error::{Error, Result}; 10 | 11 | macro_rules! impl_deserialize_n { 12 | ($type:ty, $method:ident, $visit:ident) => { 13 | fn $method(self, visitor: V) -> Result 14 | where 15 | V: serde::de::Visitor<'de>, 16 | { 17 | visitor.$visit( 18 | self.read 19 | .get_attribute_value(&self.current_field) 20 | .ok_or_else(|| Error { 21 | message: format!("missing integer for field {:?}", &self.current_field), 22 | })? 23 | .clone() 24 | .n 25 | .ok_or_else(|| Error { 26 | message: format!("missing integer for field {:?}", &self.current_field), 27 | })? 28 | .parse::<$type>() 29 | .map_err(|_| Error { 30 | message: "Invalid type".to_owned(), 31 | })?, 32 | ) 33 | } 34 | }; 35 | } 36 | 37 | #[derive(Debug)] 38 | enum Index { 39 | String(String), 40 | Number(usize), 41 | None, 42 | } 43 | 44 | trait Read: Clone { 45 | fn get_attribute_value(&self, index: &Index) -> Option<&AttributeValue>; 46 | fn get_keys(&self) -> Vec; 47 | } 48 | 49 | #[derive(Clone)] 50 | struct HashMapRead { 51 | hashmap: HashMap, 52 | } 53 | impl HashMapRead { 54 | fn new(hm: HashMap) -> Self { 55 | HashMapRead { hashmap: hm } 56 | } 57 | } 58 | impl Read for HashMapRead { 59 | fn get_attribute_value(&self, index: &Index) -> Option<&AttributeValue> { 60 | match *index { 61 | Index::String(ref key) => self.hashmap.get(key), 62 | _ => None, 63 | } 64 | } 65 | fn get_keys(&self) -> Vec { 66 | self.hashmap.keys().cloned().collect() 67 | } 68 | } 69 | 70 | #[derive(Clone)] 71 | struct VecRead { 72 | vec: Vec, 73 | } 74 | 75 | impl Read for VecRead { 76 | fn get_attribute_value(&self, index: &Index) -> Option<&AttributeValue> { 77 | match *index { 78 | Index::Number(key) => self.vec.get(key), 79 | _ => None, 80 | } 81 | } 82 | fn get_keys(&self) -> Vec { 83 | return vec![]; 84 | } 85 | } 86 | 87 | #[derive(Debug)] 88 | struct Deserializer { 89 | read: R, 90 | current_field: Index, 91 | as_key: bool, 92 | } 93 | impl<'de, R> Deserializer 94 | where 95 | R: Read, 96 | { 97 | pub fn new(read: R) -> Self { 98 | Deserializer { 99 | read, 100 | current_field: Index::None, 101 | as_key: false, 102 | } 103 | } 104 | } 105 | 106 | impl<'de, 'a, R: Read> serde::de::Deserializer<'de> for &'a mut Deserializer { 107 | type Error = Error; 108 | 109 | fn deserialize_any(self, visitor: V) -> Result 110 | where 111 | V: serde::de::Visitor<'de>, 112 | { 113 | let f = self 114 | .read 115 | .get_attribute_value(&self.current_field) 116 | .ok_or_else(|| Error { 117 | message: format!("missing for field {:?}", &self.current_field), 118 | })? 119 | .clone(); 120 | 121 | if f.b.is_some() { 122 | self.deserialize_bytes(visitor) 123 | } else if f.bool.is_some() { 124 | self.deserialize_bool(visitor) 125 | } else if f.l.is_some() || f.ns.is_some() || f.ss.is_some() || f.bs.is_some() { 126 | self.deserialize_seq(visitor) 127 | } else if f.m.is_some() { 128 | self.deserialize_map(visitor) 129 | } else if f.n.is_some() { 130 | self.deserialize_f64(visitor) 131 | } else if f.null.is_some() { 132 | self.deserialize_unit(visitor) 133 | } else if f.s.is_some() { 134 | self.deserialize_str(visitor) 135 | } else { 136 | // This part should be unreachable as all possibilities are tested before 137 | unreachable!() 138 | } 139 | } 140 | 141 | fn deserialize_bool(self, visitor: V) -> Result 142 | where 143 | V: serde::de::Visitor<'de>, 144 | { 145 | visitor.visit_bool( 146 | self.read 147 | .get_attribute_value(&self.current_field) 148 | .ok_or_else(|| Error { 149 | message: "Missing field".to_owned(), 150 | })? 151 | .clone() 152 | .bool 153 | .ok_or_else(|| Error { 154 | message: "Invalid type".to_owned(), 155 | })?, 156 | ) 157 | } 158 | 159 | impl_deserialize_n!(i8, deserialize_i8, visit_i8); 160 | impl_deserialize_n!(i16, deserialize_i16, visit_i16); 161 | impl_deserialize_n!(i32, deserialize_i32, visit_i32); 162 | impl_deserialize_n!(i64, deserialize_i64, visit_i64); 163 | 164 | impl_deserialize_n!(u8, deserialize_u8, visit_u8); 165 | impl_deserialize_n!(u16, deserialize_u16, visit_u16); 166 | impl_deserialize_n!(u32, deserialize_u32, visit_u32); 167 | impl_deserialize_n!(u64, deserialize_u64, visit_u64); 168 | 169 | impl_deserialize_n!(f32, deserialize_f32, visit_f32); 170 | impl_deserialize_n!(f64, deserialize_f64, visit_f64); 171 | 172 | fn deserialize_char(self, visitor: V) -> Result 173 | where 174 | V: serde::de::Visitor<'de>, 175 | { 176 | visitor.visit_char( 177 | self.read 178 | .get_attribute_value(&self.current_field) 179 | .ok_or_else(|| Error { 180 | message: format!("missing char for field {:?}", &self.current_field), 181 | })? 182 | .clone() 183 | .s 184 | .ok_or_else(|| Error { 185 | message: format!("missing char for field {:?}", &self.current_field), 186 | })? 187 | .parse::() 188 | .map_err(|_| Error { 189 | message: "Invalid type".to_owned(), 190 | })?, 191 | ) 192 | } 193 | 194 | fn deserialize_str(self, visitor: V) -> Result 195 | where 196 | V: serde::de::Visitor<'de>, 197 | { 198 | if self.as_key { 199 | match &self.current_field { 200 | Index::String(ref key) => visitor.visit_str(key), 201 | _ => visitor.visit_str(""), 202 | } 203 | } else if let Some(field) = self.read.get_attribute_value(&self.current_field) { 204 | field 205 | .clone() 206 | .s 207 | .ok_or_else(|| Error { 208 | message: format!("missing string for field {:?}", &self.current_field), 209 | }) 210 | .and_then(|string_field| visitor.visit_str(&string_field)) 211 | } else { 212 | visitor.visit_str("") 213 | } 214 | } 215 | 216 | fn deserialize_string(self, visitor: V) -> Result 217 | where 218 | V: serde::de::Visitor<'de>, 219 | { 220 | self.deserialize_str(visitor) 221 | } 222 | 223 | fn deserialize_bytes(self, visitor: V) -> Result 224 | where 225 | V: serde::de::Visitor<'de>, 226 | { 227 | if let Some(field) = self.read.get_attribute_value(&self.current_field) { 228 | field 229 | .clone() 230 | .b 231 | .ok_or_else(|| Error { 232 | message: format!("missing bytes for field {:?}", &self.current_field), 233 | }) 234 | .and_then(|bytes_field| visitor.visit_bytes(&bytes_field)) 235 | } else { 236 | visitor.visit_bytes(b"") 237 | } 238 | } 239 | 240 | fn deserialize_byte_buf(self, visitor: V) -> Result 241 | where 242 | V: serde::de::Visitor<'de>, 243 | { 244 | self.deserialize_bytes(visitor) 245 | } 246 | 247 | fn deserialize_option(self, visitor: V) -> Result 248 | where 249 | V: serde::de::Visitor<'de>, 250 | { 251 | if self.read.get_attribute_value(&self.current_field).is_none() { 252 | return visitor.visit_none(); 253 | } 254 | match self 255 | .read 256 | .get_attribute_value(&self.current_field) 257 | .ok_or_else(|| Error { 258 | message: format!("missing option for field {:?}", &self.current_field), 259 | })? 260 | .null 261 | { 262 | Some(true) => visitor.visit_none(), 263 | _ => visitor.visit_some(self), 264 | } 265 | } 266 | 267 | fn deserialize_unit(self, visitor: V) -> Result 268 | where 269 | V: serde::de::Visitor<'de>, 270 | { 271 | self.read 272 | .get_attribute_value(&self.current_field) 273 | .ok_or_else(|| Error { 274 | message: "Missing field".to_owned(), 275 | })? 276 | .null 277 | .ok_or_else(|| Error { 278 | message: format!("Missing null for field {:?}", &self.current_field), 279 | }) 280 | .and_then(|_| visitor.visit_unit()) 281 | } 282 | 283 | fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result 284 | where 285 | V: serde::de::Visitor<'de>, 286 | { 287 | self.deserialize_unit(visitor) 288 | } 289 | 290 | fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result 291 | where 292 | V: serde::de::Visitor<'de>, 293 | { 294 | visitor.visit_newtype_struct(self) 295 | } 296 | 297 | fn deserialize_seq(self, visitor: V) -> Result 298 | where 299 | V: serde::de::Visitor<'de>, 300 | { 301 | let list = self 302 | .read 303 | .get_attribute_value(&self.current_field) 304 | .ok_or_else(|| Error { 305 | message: format!("missing sequence for field {:?}", &self.current_field), 306 | })? 307 | .clone(); 308 | let read = if let Some(alist) = list.l { 309 | VecRead { vec: alist } 310 | } else if let Some(numlist) = list.ns { 311 | VecRead { 312 | vec: numlist 313 | .into_iter() 314 | .map(|n| AttributeValue { 315 | n: Some(n), 316 | ..Default::default() 317 | }) 318 | .collect(), 319 | } 320 | } else if let Some(slist) = list.ss { 321 | VecRead { 322 | vec: slist 323 | .into_iter() 324 | .map(|s| AttributeValue { 325 | s: Some(s), 326 | ..Default::default() 327 | }) 328 | .collect(), 329 | } 330 | } else if let Some(blist) = list.bs { 331 | VecRead { 332 | vec: blist 333 | .into_iter() 334 | .map(|s| AttributeValue { 335 | b: Some(s), 336 | ..Default::default() 337 | }) 338 | .collect(), 339 | } 340 | } else { 341 | return Err(Error { 342 | message: "No sequence input found".to_owned(), 343 | }); 344 | }; 345 | let mut des = Deserializer::new(read); 346 | visitor.visit_seq(SeqAccess::new(&mut des)) 347 | } 348 | 349 | fn deserialize_tuple(self, _len: usize, visitor: V) -> Result 350 | where 351 | V: serde::de::Visitor<'de>, 352 | { 353 | match self.current_field { 354 | Index::None => { 355 | let mut des = Deserializer::new(self.read.clone()); 356 | visitor.visit_seq(TupleAccess::new(&mut des)) 357 | } 358 | _ => { 359 | let subread = HashMapRead { 360 | hashmap: self 361 | .read 362 | .get_attribute_value(&self.current_field) 363 | .ok_or_else(|| Error { 364 | message: format!("missing hashmap for field {:?}", &self.current_field), 365 | })? 366 | .m 367 | .clone() 368 | .unwrap(), 369 | }; 370 | let mut des = Deserializer::new(subread); 371 | visitor.visit_seq(TupleAccess::new(&mut des)) 372 | } 373 | } 374 | } 375 | 376 | fn deserialize_tuple_struct( 377 | self, 378 | _name: &'static str, 379 | _len: usize, 380 | visitor: V, 381 | ) -> Result 382 | where 383 | V: serde::de::Visitor<'de>, 384 | { 385 | match self.current_field { 386 | Index::None => { 387 | let mut des = Deserializer::new(self.read.clone()); 388 | visitor.visit_seq(TupleAccess::new(&mut des)) 389 | } 390 | _ => { 391 | let subread = HashMapRead { 392 | hashmap: self 393 | .read 394 | .get_attribute_value(&self.current_field) 395 | .ok_or_else(|| Error { 396 | message: format!("missing hashmap for field {:?}", &self.current_field), 397 | })? 398 | .m 399 | .clone() 400 | .unwrap(), 401 | }; 402 | let mut des = Deserializer::new(subread); 403 | visitor.visit_seq(TupleAccess::new(&mut des)) 404 | } 405 | } 406 | } 407 | 408 | fn deserialize_map(self, visitor: V) -> Result 409 | where 410 | V: serde::de::Visitor<'de>, 411 | { 412 | match self.current_field { 413 | Index::None => visitor.visit_map(MapAccess::new(self, self.read.get_keys())), 414 | _ => { 415 | let map = self 416 | .read 417 | .get_attribute_value(&self.current_field) 418 | .ok_or_else(|| Error { 419 | message: format!("missing struct for field {:?}", &self.current_field), 420 | })?; 421 | let hm = map.clone().m.unwrap_or_else(HashMap::new); 422 | let keys = hm.keys().cloned().collect(); 423 | let mut des = Deserializer::new(HashMapRead::new(hm)); 424 | visitor.visit_map(MapAccess::new(&mut des, keys)) 425 | } 426 | } 427 | } 428 | 429 | fn deserialize_struct( 430 | self, 431 | _name: &'static str, 432 | _fields: &'static [&'static str], 433 | visitor: V, 434 | ) -> Result 435 | where 436 | V: serde::de::Visitor<'de>, 437 | { 438 | match self.current_field { 439 | Index::None => visitor.visit_map(MapAccess::new(self, self.read.get_keys())), 440 | _ => { 441 | let map = self 442 | .read 443 | .get_attribute_value(&self.current_field) 444 | .ok_or_else(|| Error { 445 | message: format!("missing struct for field {:?}", &self.current_field), 446 | })?; 447 | let hm = map.clone().m.ok_or_else(|| Error { 448 | message: "Missing struct fields".to_owned(), 449 | })?; 450 | let keys = hm.keys().cloned().collect(); 451 | let mut des = Deserializer::new(HashMapRead::new(hm)); 452 | visitor.visit_map(MapAccess::new(&mut des, keys)) 453 | } 454 | } 455 | } 456 | 457 | fn deserialize_enum( 458 | self, 459 | _name: &str, 460 | _variants: &'static [&'static str], 461 | visitor: V, 462 | ) -> Result 463 | where 464 | V: serde::de::Visitor<'de>, 465 | { 466 | let (variant, values) = if let Index::None = self.current_field { 467 | let variant = self 468 | .read 469 | .get_attribute_value(&Index::String(String::from("___enum_tag"))) 470 | .ok_or_else(|| Error { 471 | message: "Missing enum tag field".to_owned(), 472 | })? 473 | .clone() 474 | .s 475 | .ok_or_else(|| Error { 476 | message: "Missing enum tag value".to_owned(), 477 | })?; 478 | let values = self 479 | .read 480 | .get_attribute_value(&Index::String(String::from("___enum_values"))) 481 | .and_then(|v| v.m.clone()); 482 | (variant, values) 483 | } else { 484 | let enum_field = self 485 | .read 486 | .get_attribute_value(&self.current_field) 487 | .ok_or_else(|| Error { 488 | message: format!("missing enum for field {:?}", &self.current_field), 489 | })?; 490 | if let Some(shortstyle) = enum_field.s.clone() { 491 | return visitor.visit_enum(shortstyle.into_deserializer()); 492 | } 493 | let base = enum_field.m.clone().ok_or_else(|| Error { 494 | message: "Missing enum data".to_owned(), 495 | })?; 496 | ( 497 | base.get("___enum_tag") 498 | .unwrap() 499 | .s 500 | .clone() 501 | .ok_or_else(|| Error { 502 | message: "Missing enum tag value".to_owned(), 503 | })?, 504 | base.get("___enum_values").and_then(|v| v.m.clone()), 505 | ) 506 | }; 507 | let mut des = Deserializer::new(HashMapRead::new(values.unwrap_or_else(HashMap::new))); 508 | visitor.visit_enum(EnumAccess::new(&mut des, variant)) 509 | } 510 | 511 | fn deserialize_identifier(self, visitor: V) -> Result 512 | where 513 | V: serde::de::Visitor<'de>, 514 | { 515 | match self.current_field { 516 | Index::String(ref value) => visitor.visit_str(&value.clone()), 517 | _ => Err(Error { 518 | message: "indentifier should be a string".to_string(), 519 | }), 520 | } 521 | } 522 | 523 | fn deserialize_ignored_any(self, visitor: V) -> Result 524 | where 525 | V: serde::de::Visitor<'de>, 526 | { 527 | visitor.visit_unit() 528 | } 529 | } 530 | 531 | struct EnumAccess<'a, R: 'a> { 532 | de: &'a mut Deserializer, 533 | variant_name: String, 534 | } 535 | impl<'a, R: 'a> EnumAccess<'a, R> { 536 | fn new(de: &'a mut Deserializer, variant_name: String) -> Self { 537 | EnumAccess { de, variant_name } 538 | } 539 | } 540 | impl<'de, 'a, R: Read + 'a> serde::de::EnumAccess<'de> for EnumAccess<'a, R> { 541 | type Error = Error; 542 | type Variant = VariantAccess<'a, R>; 543 | 544 | fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> 545 | where 546 | V: serde::de::DeserializeSeed<'de>, 547 | { 548 | let value = seed.deserialize(self.variant_name.into_deserializer())?; 549 | Ok((value, VariantAccess::new(self.de))) 550 | } 551 | } 552 | 553 | struct VariantAccess<'a, R: 'a> { 554 | de: &'a mut Deserializer, 555 | } 556 | impl<'a, R: 'a> VariantAccess<'a, R> { 557 | fn new(de: &'a mut Deserializer) -> Self { 558 | VariantAccess { de } 559 | } 560 | } 561 | impl<'de, 'a, R: Read + 'a> serde::de::VariantAccess<'de> for VariantAccess<'a, R> { 562 | type Error = Error; 563 | 564 | fn unit_variant(self) -> Result<()> { 565 | Ok(()) 566 | } 567 | 568 | fn newtype_variant_seed(self, seed: T) -> Result 569 | where 570 | T: serde::de::DeserializeSeed<'de>, 571 | { 572 | self.de.current_field = Index::String(String::from("_0")); 573 | seed.deserialize(&mut *self.de) 574 | } 575 | 576 | fn tuple_variant(self, _len: usize, visitor: V) -> Result 577 | where 578 | V: serde::de::Visitor<'de>, 579 | { 580 | visitor.visit_seq(TupleAccess::new(self.de)) 581 | } 582 | 583 | fn struct_variant(self, _fields: &'static [&'static str], visitor: V) -> Result 584 | where 585 | V: serde::de::Visitor<'de>, 586 | { 587 | visitor.visit_map(MapAccess::new(self.de, self.de.read.get_keys())) 588 | } 589 | } 590 | 591 | struct TupleAccess<'a, R: 'a> { 592 | de: &'a mut Deserializer, 593 | current: usize, 594 | } 595 | impl<'a, R: 'a> TupleAccess<'a, R> { 596 | fn new(de: &'a mut Deserializer) -> Self { 597 | TupleAccess { de, current: 0 } 598 | } 599 | } 600 | impl<'de, 'a, R: Read + 'a> serde::de::SeqAccess<'de> for TupleAccess<'a, R> { 601 | type Error = Error; 602 | 603 | fn next_element_seed(&mut self, seed: T) -> Result> 604 | where 605 | T: serde::de::DeserializeSeed<'de>, 606 | { 607 | self.de.current_field = Index::String(format!("_{}", self.current)); 608 | self.current += 1; 609 | if self 610 | .de 611 | .read 612 | .get_attribute_value(&self.de.current_field) 613 | .is_none() 614 | { 615 | return Ok(None); 616 | } 617 | seed.deserialize(&mut *self.de).map(Some) 618 | } 619 | } 620 | 621 | struct SeqAccess<'a, R: 'a> { 622 | de: &'a mut Deserializer, 623 | current: usize, 624 | } 625 | 626 | impl<'a, R: 'a> SeqAccess<'a, R> { 627 | fn new(de: &'a mut Deserializer) -> Self { 628 | SeqAccess { de, current: 0 } 629 | } 630 | } 631 | 632 | impl<'de, 'a, R: Read + 'a> serde::de::SeqAccess<'de> for SeqAccess<'a, R> { 633 | type Error = Error; 634 | 635 | fn next_element_seed(&mut self, seed: T) -> Result> 636 | where 637 | T: serde::de::DeserializeSeed<'de>, 638 | { 639 | self.de.current_field = Index::Number(self.current); 640 | self.current += 1; 641 | if self 642 | .de 643 | .read 644 | .get_attribute_value(&self.de.current_field) 645 | .is_none() 646 | { 647 | return Ok(None); 648 | } 649 | seed.deserialize(&mut *self.de).map(Some) 650 | } 651 | } 652 | 653 | struct MapAccess<'a, R: 'a> { 654 | de: &'a mut Deserializer, 655 | keys: Vec, 656 | current: usize, 657 | } 658 | 659 | impl<'a, R: 'a> MapAccess<'a, R> { 660 | fn new(de: &'a mut Deserializer, keys: Vec) -> Self { 661 | MapAccess { 662 | de, 663 | keys, 664 | current: 0, 665 | } 666 | } 667 | } 668 | 669 | impl<'de, 'a, R: Read + 'a> serde::de::MapAccess<'de> for MapAccess<'a, R> { 670 | type Error = Error; 671 | 672 | fn next_key_seed(&mut self, seed: K) -> Result> 673 | where 674 | K: serde::de::DeserializeSeed<'de>, 675 | { 676 | if self.current >= self.keys.len() { 677 | Ok(None) 678 | } else { 679 | self.de.current_field = Index::String(self.keys[self.current].to_string()); 680 | self.de.as_key = true; 681 | self.current += 1; 682 | seed.deserialize(&mut *self.de).map(Some) 683 | } 684 | } 685 | 686 | fn next_value_seed(&mut self, seed: V) -> Result 687 | where 688 | V: serde::de::DeserializeSeed<'de>, 689 | { 690 | self.de.as_key = false; 691 | seed.deserialize(&mut *self.de) 692 | } 693 | } 694 | 695 | fn from_trait<'de, R, T>(read: R) -> Result 696 | where 697 | R: Read, 698 | T: serde::de::Deserialize<'de>, 699 | { 700 | let mut de = Deserializer::new(read); 701 | let value = serde::de::Deserialize::deserialize(&mut de)?; 702 | 703 | Ok(value) 704 | } 705 | 706 | /// Deserialize an instance of type `T` from an `HashMap`. 707 | /// 708 | /// # Errors 709 | /// 710 | /// This conversion can fail if the structure of the input does not match the 711 | /// structure expected by `T`, for example if `T` is a struct type but the input 712 | /// contains something other than a JSON map. It can also fail if the structure 713 | /// is correct but `T`'s implementation of `Deserialize` decides that something 714 | /// is wrong with the data, for example required struct fields are missing from 715 | /// the JSON map or some number is too big to fit in the expected primitive 716 | /// type. 717 | pub fn from_hashmap<'a, T, S: ::std::hash::BuildHasher + Clone>( 718 | hm: HashMap, 719 | ) -> Result 720 | where 721 | T: serde::de::Deserialize<'a>, 722 | { 723 | from_trait(HashMapRead::new(hm)) 724 | } 725 | -------------------------------------------------------------------------------- /src/dynamodb/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod de; 2 | pub mod ser; 3 | -------------------------------------------------------------------------------- /src/dynamodb/ser.rs: -------------------------------------------------------------------------------- 1 | //! Serialize a Rust data structure into HashMap. 2 | 3 | use std::collections::HashMap; 4 | 5 | use rusoto_dynamodb::AttributeValue; 6 | 7 | use crate::common::SimpleKeySerializer; 8 | use crate::error::{Error, Result}; 9 | 10 | macro_rules! impl_serialize_n { 11 | ($type:ty, $method:ident) => { 12 | fn $method(self, value: $type) -> Result<()> { 13 | self.writer.insert_value(AttributeValue { 14 | n: Some(value.to_string()), 15 | ..Default::default() 16 | }); 17 | Ok(()) 18 | } 19 | }; 20 | } 21 | 22 | #[derive(Debug)] 23 | struct HashMapWriter { 24 | current_key: String, 25 | root: HashMap, 26 | } 27 | trait WriterTrait { 28 | fn set_key(&mut self, key: String); 29 | fn is_in_object(&self) -> bool; 30 | fn insert_value(&mut self, value: AttributeValue); 31 | } 32 | impl<'a> WriterTrait for &'a mut HashMapWriter { 33 | fn set_key(&mut self, key: String) { 34 | self.current_key = key; 35 | } 36 | fn is_in_object(&self) -> bool { 37 | !self.current_key.is_empty() 38 | } 39 | fn insert_value(&mut self, value: AttributeValue) { 40 | self.root.insert(self.current_key.clone(), value); 41 | } 42 | } 43 | 44 | #[derive(Debug)] 45 | struct VecWriter { 46 | list: Vec, 47 | } 48 | 49 | impl<'a> WriterTrait for &'a mut VecWriter { 50 | fn set_key(&mut self, _key: String) {} 51 | fn is_in_object(&self) -> bool { 52 | true 53 | } 54 | fn insert_value(&mut self, value: AttributeValue) { 55 | self.list.push(value); 56 | } 57 | } 58 | 59 | #[derive(Debug)] 60 | struct Serializer { 61 | writer: W, 62 | } 63 | impl Serializer 64 | where 65 | W: WriterTrait, 66 | { 67 | pub fn new(writer: W) -> Self { 68 | Serializer { writer } 69 | } 70 | } 71 | impl<'a, W> serde::Serializer for &'a mut Serializer 72 | where 73 | W: WriterTrait, 74 | { 75 | type Ok = (); 76 | type Error = Error; 77 | 78 | type SerializeSeq = SeqWriter<'a, W>; 79 | type SerializeTuple = Compound<'a, W>; 80 | type SerializeTupleStruct = Compound<'a, W>; 81 | type SerializeTupleVariant = EnumCompound<'a, W>; 82 | type SerializeMap = Compound<'a, W>; 83 | type SerializeStruct = Compound<'a, W>; 84 | type SerializeStructVariant = EnumCompound<'a, W>; 85 | 86 | fn serialize_bool(self, value: bool) -> Result<()> { 87 | self.writer.insert_value(AttributeValue { 88 | bool: Some(value), 89 | ..Default::default() 90 | }); 91 | Ok(()) 92 | } 93 | 94 | impl_serialize_n!(i8, serialize_i8); 95 | impl_serialize_n!(i16, serialize_i16); 96 | impl_serialize_n!(i32, serialize_i32); 97 | impl_serialize_n!(i64, serialize_i64); 98 | impl_serialize_n!(u8, serialize_u8); 99 | impl_serialize_n!(u16, serialize_u16); 100 | impl_serialize_n!(u32, serialize_u32); 101 | impl_serialize_n!(u64, serialize_u64); 102 | impl_serialize_n!(f32, serialize_f32); 103 | impl_serialize_n!(f64, serialize_f64); 104 | 105 | fn serialize_char(self, value: char) -> Result<()> { 106 | self.writer.insert_value(AttributeValue { 107 | s: Some(value.to_string()), 108 | ..Default::default() 109 | }); 110 | Ok(()) 111 | } 112 | 113 | fn serialize_str(self, value: &str) -> Result<()> { 114 | self.writer.insert_value(AttributeValue { 115 | s: Some(value.to_string()), 116 | ..Default::default() 117 | }); 118 | Ok(()) 119 | } 120 | 121 | fn serialize_bytes(self, value: &[u8]) -> Result<()> { 122 | self.writer.insert_value(AttributeValue { 123 | b: Some(bytes::Bytes::copy_from_slice(value)), 124 | ..Default::default() 125 | }); 126 | Ok(()) 127 | } 128 | 129 | fn serialize_unit(self) -> Result<()> { 130 | self.writer.insert_value(AttributeValue { 131 | null: Some(true), 132 | ..Default::default() 133 | }); 134 | Ok(()) 135 | } 136 | 137 | fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { 138 | self.serialize_unit() 139 | } 140 | 141 | fn serialize_unit_variant( 142 | self, 143 | _name: &'static str, 144 | _variant_index: u32, 145 | variant: &'static str, 146 | ) -> Result<()> { 147 | EnumCompound::new(self, variant, false).end_wrapper(); 148 | Ok(()) 149 | } 150 | 151 | fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> 152 | where 153 | T: serde::ser::Serialize, 154 | { 155 | value.serialize(self)?; 156 | Ok(()) 157 | } 158 | 159 | #[inline] 160 | fn serialize_newtype_variant( 161 | self, 162 | _name: &'static str, 163 | _variant_index: u32, 164 | variant: &'static str, 165 | value: &T, 166 | ) -> Result<()> 167 | where 168 | T: serde::ser::Serialize, 169 | { 170 | use serde::ser::SerializeTupleVariant; 171 | let mut compound = EnumCompound::new(self, variant, true); 172 | compound.serialize_field(value)?; 173 | compound.end() 174 | } 175 | 176 | fn serialize_none(self) -> Result<()> { 177 | self.writer.insert_value(AttributeValue { 178 | null: Some(true), 179 | ..Default::default() 180 | }); 181 | Ok(()) 182 | } 183 | 184 | fn serialize_some(self, value: &T) -> Result<()> 185 | where 186 | T: serde::ser::Serialize, 187 | { 188 | value.serialize(self) 189 | } 190 | 191 | fn serialize_seq(self, _len: Option) -> Result { 192 | Ok(SeqWriter::new(self)) 193 | } 194 | 195 | fn serialize_tuple(self, _len: usize) -> Result { 196 | Ok(Compound::new(self)) 197 | } 198 | 199 | fn serialize_tuple_struct( 200 | self, 201 | _name: &'static str, 202 | _len: usize, 203 | ) -> Result { 204 | Ok(Compound::new(self)) 205 | } 206 | 207 | fn serialize_tuple_variant( 208 | self, 209 | _name: &'static str, 210 | _variant_index: u32, 211 | variant: &'static str, 212 | _len: usize, 213 | ) -> Result { 214 | Ok(EnumCompound::new(self, variant, true)) 215 | } 216 | 217 | fn serialize_map(self, _len: Option) -> Result { 218 | Ok(Compound::new(self)) 219 | } 220 | 221 | fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { 222 | Ok(Compound::new(self)) 223 | } 224 | 225 | fn serialize_struct_variant( 226 | self, 227 | _name: &'static str, 228 | _variant_index: u32, 229 | variant: &'static str, 230 | _len: usize, 231 | ) -> Result { 232 | Ok(EnumCompound::new(self, variant, true)) 233 | } 234 | } 235 | 236 | #[derive(Debug)] 237 | struct SeqWriter<'a, W: 'a> { 238 | ser: &'a mut Serializer, 239 | current: VecWriter, 240 | } 241 | 242 | impl<'a, W> SeqWriter<'a, W> { 243 | fn new(ser: &'a mut Serializer) -> SeqWriter<'a, W> { 244 | let writer = VecWriter { list: Vec::new() }; 245 | SeqWriter { 246 | ser, 247 | current: writer, 248 | } 249 | } 250 | } 251 | 252 | impl<'a, W> serde::ser::SerializeSeq for SeqWriter<'a, W> 253 | where 254 | W: WriterTrait, 255 | { 256 | type Ok = (); 257 | type Error = Error; 258 | 259 | fn serialize_element(&mut self, value: &T) -> Result<()> 260 | where 261 | T: serde::ser::Serialize, 262 | { 263 | let mut ser = Serializer::new(&mut self.current); 264 | value.serialize(&mut ser) 265 | } 266 | 267 | fn end(self) -> Result<()> { 268 | self.ser.writer.insert_value(AttributeValue { 269 | l: Some(self.current.list.clone()), 270 | ..Default::default() 271 | }); 272 | Ok(()) 273 | } 274 | } 275 | 276 | #[derive(Debug)] 277 | enum Key { 278 | Index(usize), 279 | Key(String), 280 | None, 281 | } 282 | 283 | #[derive(Debug)] 284 | struct EnumCompound<'a, W: 'a> { 285 | ser: &'a mut Serializer, 286 | is_root: bool, 287 | values_writer: HashMapWriter, 288 | wrapper_to_close: Option, 289 | current_item: Key, 290 | } 291 | 292 | impl<'a, W> EnumCompound<'a, W> 293 | where 294 | W: WriterTrait, 295 | { 296 | fn new( 297 | ser: &'a mut Serializer, 298 | variant: &'static str, 299 | has_values: bool, 300 | ) -> EnumCompound<'a, W> { 301 | let wrapper_to_close = if ser.writer.is_in_object() { 302 | let mut writer = HashMapWriter { 303 | root: HashMap::new(), 304 | current_key: String::new(), 305 | }; 306 | 307 | (&mut writer).set_key(String::from("___enum_tag")); 308 | (&mut writer).insert_value(AttributeValue { 309 | s: Some(variant.to_string()), 310 | ..Default::default() 311 | }); 312 | if has_values { 313 | (&mut writer).set_key(String::from("___enum_values")); 314 | } 315 | Some(writer) 316 | } else { 317 | ser.writer.set_key(String::from("___enum_tag")); 318 | ser.writer.insert_value(AttributeValue { 319 | s: Some(variant.to_string()), 320 | ..Default::default() 321 | }); 322 | if has_values { 323 | ser.writer.set_key(String::from("___enum_values")); 324 | } 325 | 326 | None 327 | }; 328 | let values_writer = HashMapWriter { 329 | root: HashMap::new(), 330 | current_key: String::new(), 331 | }; 332 | let is_root = !ser.writer.is_in_object(); 333 | EnumCompound { 334 | ser, 335 | is_root, 336 | values_writer, 337 | wrapper_to_close, 338 | current_item: Key::None, 339 | } 340 | } 341 | 342 | fn end_wrapper(self) { 343 | if let Some(wrapper) = self.wrapper_to_close { 344 | self.ser.writer.insert_value(AttributeValue { 345 | m: Some(wrapper.root), 346 | ..Default::default() 347 | }); 348 | } 349 | } 350 | } 351 | impl<'a, W> serde::ser::SerializeTupleVariant for EnumCompound<'a, W> 352 | where 353 | W: WriterTrait, 354 | { 355 | type Ok = (); 356 | type Error = Error; 357 | 358 | fn serialize_field(&mut self, value: &T) -> Result<()> 359 | where 360 | T: serde::ser::Serialize, 361 | { 362 | if let Key::None = self.current_item { 363 | self.current_item = Key::Index(0); 364 | } 365 | if let Key::Index(idx) = self.current_item { 366 | let key = format!("_{}", idx); 367 | self.current_item = Key::Index(idx + 1); 368 | if self.is_root { 369 | self.ser.writer.set_key(key); 370 | value.serialize(&mut *self.ser)?; 371 | Ok(()) 372 | } else { 373 | (&mut self.values_writer).set_key(key); 374 | to_writer(&mut self.values_writer, value) 375 | } 376 | } else { 377 | Err(Error { 378 | message: String::from( 379 | "trying to serialize something that is not a tuple as a tuple", 380 | ), 381 | }) 382 | } 383 | } 384 | 385 | #[inline] 386 | fn end(self) -> Result<()> { 387 | if let Some(mut wrapper) = self.wrapper_to_close { 388 | (&mut wrapper).insert_value(AttributeValue { 389 | m: Some(self.values_writer.root.clone()), 390 | ..Default::default() 391 | }); 392 | if !self.is_root { 393 | self.ser.writer.insert_value(AttributeValue { 394 | m: Some(wrapper.root), 395 | ..Default::default() 396 | }); 397 | } 398 | } else if !self.is_root { 399 | self.ser.writer.insert_value(AttributeValue { 400 | m: Some(self.values_writer.root.clone()), 401 | ..Default::default() 402 | }); 403 | } 404 | Ok(()) 405 | } 406 | } 407 | 408 | impl<'a, W> serde::ser::SerializeStructVariant for EnumCompound<'a, W> 409 | where 410 | W: WriterTrait, 411 | { 412 | type Ok = (); 413 | type Error = Error; 414 | 415 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> 416 | where 417 | T: serde::ser::Serialize, 418 | { 419 | if self.is_root { 420 | self.ser.writer.set_key(String::from(key)); 421 | value.serialize(&mut *self.ser)?; 422 | Ok(()) 423 | } else { 424 | (&mut self.values_writer).set_key(String::from(key)); 425 | to_writer(&mut self.values_writer, value) 426 | } 427 | } 428 | 429 | fn end(self) -> Result<()> { 430 | if let Some(mut wrapper) = self.wrapper_to_close { 431 | (&mut wrapper).insert_value(AttributeValue { 432 | m: Some(self.values_writer.root.clone()), 433 | ..Default::default() 434 | }); 435 | if !self.is_root { 436 | self.ser.writer.insert_value(AttributeValue { 437 | m: Some(wrapper.root), 438 | ..Default::default() 439 | }); 440 | } 441 | } else if !self.is_root { 442 | self.ser.writer.insert_value(AttributeValue { 443 | m: Some(self.values_writer.root.clone()), 444 | ..Default::default() 445 | }); 446 | } 447 | Ok(()) 448 | } 449 | } 450 | 451 | #[derive(Debug)] 452 | struct Compound<'a, W: 'a> { 453 | ser: &'a mut Serializer, 454 | is_root: bool, 455 | current: HashMapWriter, 456 | current_item: Key, 457 | } 458 | 459 | impl<'a, W> Compound<'a, W> 460 | where 461 | W: WriterTrait, 462 | { 463 | fn new(ser: &'a mut Serializer) -> Compound<'a, W> { 464 | let writer = HashMapWriter { 465 | root: HashMap::new(), 466 | current_key: String::new(), 467 | }; 468 | let is_root = !ser.writer.is_in_object(); 469 | Compound { 470 | ser, 471 | is_root, 472 | current: writer, 473 | current_item: Key::None, 474 | } 475 | } 476 | } 477 | 478 | impl<'a, W> serde::ser::SerializeTuple for Compound<'a, W> 479 | where 480 | W: WriterTrait, 481 | { 482 | type Ok = (); 483 | type Error = Error; 484 | 485 | fn serialize_element(&mut self, value: &T) -> Result<()> 486 | where 487 | T: serde::ser::Serialize, 488 | { 489 | if let Key::None = self.current_item { 490 | self.current_item = Key::Index(0); 491 | } 492 | if let Key::Index(idx) = self.current_item { 493 | let key = format!("_{}", idx); 494 | self.current_item = Key::Index(idx + 1); 495 | if self.is_root { 496 | self.ser.writer.set_key(key); 497 | value.serialize(&mut *self.ser)?; 498 | Ok(()) 499 | } else { 500 | (&mut self.current).set_key(key); 501 | to_writer(&mut self.current, value) 502 | } 503 | } else { 504 | Err(Error { 505 | message: String::from( 506 | "trying to serialize something that is not a tuple as a tuple", 507 | ), 508 | }) 509 | } 510 | } 511 | 512 | #[inline] 513 | fn end(self) -> Result<()> { 514 | if !self.is_root { 515 | self.ser.writer.insert_value(AttributeValue { 516 | m: Some(self.current.root.clone()), 517 | ..Default::default() 518 | }); 519 | } 520 | Ok(()) 521 | } 522 | } 523 | 524 | impl<'a, W> serde::ser::SerializeTupleStruct for Compound<'a, W> 525 | where 526 | W: WriterTrait, 527 | { 528 | type Ok = (); 529 | type Error = Error; 530 | 531 | fn serialize_field(&mut self, value: &T) -> Result<()> 532 | where 533 | T: serde::ser::Serialize, 534 | { 535 | if let Key::None = self.current_item { 536 | self.current_item = Key::Index(0); 537 | } 538 | if let Key::Index(idx) = self.current_item { 539 | let key = format!("_{}", idx); 540 | self.current_item = Key::Index(idx + 1); 541 | if self.is_root { 542 | self.ser.writer.set_key(key); 543 | value.serialize(&mut *self.ser)?; 544 | Ok(()) 545 | } else { 546 | (&mut self.current).set_key(key); 547 | to_writer(&mut self.current, value) 548 | } 549 | } else { 550 | Err(Error { 551 | message: String::from( 552 | "trying to serialize something that is not a tuple as a tuple", 553 | ), 554 | }) 555 | } 556 | } 557 | 558 | fn end(self) -> Result<()> { 559 | if !self.is_root { 560 | self.ser.writer.insert_value(AttributeValue { 561 | m: Some(self.current.root.clone()), 562 | ..Default::default() 563 | }); 564 | } 565 | Ok(()) 566 | } 567 | } 568 | 569 | impl<'a, W> serde::ser::SerializeMap for Compound<'a, W> 570 | where 571 | W: WriterTrait, 572 | { 573 | type Ok = (); 574 | type Error = Error; 575 | 576 | fn serialize_key(&mut self, key: &T) -> Result<()> 577 | where 578 | T: serde::ser::Serialize, 579 | { 580 | let mut serializer = SimpleKeySerializer::new(); 581 | key.serialize(&mut serializer)?; 582 | self.current_item = Key::Key(serializer.get_result()); 583 | Ok(()) 584 | } 585 | 586 | fn serialize_value(&mut self, value: &T) -> Result<()> 587 | where 588 | T: serde::ser::Serialize, 589 | { 590 | if let Key::Key(key) = &self.current_item { 591 | if self.is_root { 592 | self.ser.writer.set_key(key.clone()); 593 | value.serialize(&mut *self.ser)?; 594 | Ok(()) 595 | } else { 596 | (&mut self.current).set_key(key.clone()); 597 | to_writer(&mut self.current, value) 598 | } 599 | } else { 600 | Err(Error { 601 | message: String::from( 602 | "trying to deserialize something that is not a struct as a struct", 603 | ), 604 | }) 605 | } 606 | } 607 | 608 | fn end(self) -> Result<()> { 609 | if !self.is_root { 610 | self.ser.writer.insert_value(AttributeValue { 611 | m: Some(self.current.root.clone()), 612 | ..Default::default() 613 | }); 614 | } 615 | Ok(()) 616 | } 617 | } 618 | 619 | impl<'a, W> serde::ser::SerializeStruct for Compound<'a, W> 620 | where 621 | W: WriterTrait, 622 | { 623 | type Ok = (); 624 | type Error = Error; 625 | 626 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> 627 | where 628 | T: serde::ser::Serialize, 629 | { 630 | if self.is_root { 631 | self.ser.writer.set_key(key.to_string()); 632 | value.serialize(&mut *self.ser)?; 633 | Ok(()) 634 | } else { 635 | (&mut self.current).set_key(key.to_string()); 636 | to_writer(&mut self.current, value) 637 | } 638 | } 639 | 640 | fn end(self) -> Result<()> { 641 | if !self.is_root { 642 | self.ser.writer.insert_value(AttributeValue { 643 | m: Some(self.current.root.clone()), 644 | ..Default::default() 645 | }); 646 | } 647 | Ok(()) 648 | } 649 | } 650 | 651 | fn to_writer(writer: &mut HashMapWriter, value: &T) -> Result<()> 652 | where 653 | T: serde::ser::Serialize, 654 | { 655 | let mut ser = Serializer::new(writer); 656 | value.serialize(&mut ser)?; 657 | Ok(()) 658 | } 659 | 660 | /// Serialize the given data structure as an `HashMap`. 661 | /// 662 | /// # Errors 663 | /// 664 | /// Serialization can fail if `T`'s implementation of `Serialize` decides to 665 | /// fail, or if `T` contains a map with non-string keys. 666 | pub fn to_hashmap(value: &T) -> Result> 667 | where 668 | T: serde::ser::Serialize, 669 | { 670 | let mut writer = HashMapWriter { 671 | root: HashMap::new(), 672 | current_key: String::new(), 673 | }; 674 | to_writer(&mut writer, value)?; 675 | Ok(writer.root) 676 | } 677 | -------------------------------------------------------------------------------- /src/dynamodbstreams/de.rs: -------------------------------------------------------------------------------- 1 | // generated file, see update_streams.sh 2 | 3 | //! Deserialize an HashMap into a Rust data structure. 4 | 5 | use std::collections::HashMap; 6 | 7 | use rusoto_dynamodbstreams::AttributeValue; 8 | 9 | use serde::de::IntoDeserializer; 10 | 11 | use crate::error::{Error, Result}; 12 | 13 | macro_rules! impl_deserialize_n { 14 | ($type:ty, $method:ident, $visit:ident) => { 15 | fn $method(self, visitor: V) -> Result 16 | where 17 | V: serde::de::Visitor<'de>, 18 | { 19 | visitor.$visit( 20 | self.read 21 | .get_attribute_value(&self.current_field) 22 | .ok_or_else(|| Error { 23 | message: format!("missing integer for field {:?}", &self.current_field), 24 | })? 25 | .clone() 26 | .n 27 | .ok_or_else(|| Error { 28 | message: format!("missing integer for field {:?}", &self.current_field), 29 | })? 30 | .parse::<$type>() 31 | .map_err(|_| Error { 32 | message: "Invalid type".to_owned(), 33 | })?, 34 | ) 35 | } 36 | }; 37 | } 38 | 39 | #[derive(Debug)] 40 | enum Index { 41 | String(String), 42 | Number(usize), 43 | None, 44 | } 45 | 46 | trait Read: Clone { 47 | fn get_attribute_value(&self, index: &Index) -> Option<&AttributeValue>; 48 | fn get_keys(&self) -> Vec; 49 | } 50 | 51 | #[derive(Clone)] 52 | struct HashMapRead { 53 | hashmap: HashMap, 54 | } 55 | impl HashMapRead { 56 | fn new(hm: HashMap) -> Self { 57 | HashMapRead { hashmap: hm } 58 | } 59 | } 60 | impl Read for HashMapRead { 61 | fn get_attribute_value(&self, index: &Index) -> Option<&AttributeValue> { 62 | match *index { 63 | Index::String(ref key) => self.hashmap.get(key), 64 | _ => None, 65 | } 66 | } 67 | fn get_keys(&self) -> Vec { 68 | self.hashmap.keys().cloned().collect() 69 | } 70 | } 71 | 72 | #[derive(Clone)] 73 | struct VecRead { 74 | vec: Vec, 75 | } 76 | 77 | impl Read for VecRead { 78 | fn get_attribute_value(&self, index: &Index) -> Option<&AttributeValue> { 79 | match *index { 80 | Index::Number(key) => self.vec.get(key), 81 | _ => None, 82 | } 83 | } 84 | fn get_keys(&self) -> Vec { 85 | return vec![]; 86 | } 87 | } 88 | 89 | #[derive(Debug)] 90 | struct Deserializer { 91 | read: R, 92 | current_field: Index, 93 | as_key: bool, 94 | } 95 | impl<'de, R> Deserializer 96 | where 97 | R: Read, 98 | { 99 | pub fn new(read: R) -> Self { 100 | Deserializer { 101 | read, 102 | current_field: Index::None, 103 | as_key: false, 104 | } 105 | } 106 | } 107 | 108 | impl<'de, 'a, R: Read> serde::de::Deserializer<'de> for &'a mut Deserializer { 109 | type Error = Error; 110 | 111 | fn deserialize_any(self, visitor: V) -> Result 112 | where 113 | V: serde::de::Visitor<'de>, 114 | { 115 | let f = self 116 | .read 117 | .get_attribute_value(&self.current_field) 118 | .ok_or_else(|| Error { 119 | message: format!("missing for field {:?}", &self.current_field), 120 | })? 121 | .clone(); 122 | 123 | if f.b.is_some() { 124 | self.deserialize_bytes(visitor) 125 | } else if f.bool.is_some() { 126 | self.deserialize_bool(visitor) 127 | } else if f.l.is_some() || f.ns.is_some() || f.ss.is_some() || f.bs.is_some() { 128 | self.deserialize_seq(visitor) 129 | } else if f.m.is_some() { 130 | self.deserialize_map(visitor) 131 | } else if f.n.is_some() { 132 | self.deserialize_f64(visitor) 133 | } else if f.null.is_some() { 134 | self.deserialize_unit(visitor) 135 | } else if f.s.is_some() { 136 | self.deserialize_str(visitor) 137 | } else { 138 | // This part should be unreachable as all possibilities are tested before 139 | unreachable!() 140 | } 141 | } 142 | 143 | fn deserialize_bool(self, visitor: V) -> Result 144 | where 145 | V: serde::de::Visitor<'de>, 146 | { 147 | visitor.visit_bool( 148 | self.read 149 | .get_attribute_value(&self.current_field) 150 | .ok_or_else(|| Error { 151 | message: "Missing field".to_owned(), 152 | })? 153 | .clone() 154 | .bool 155 | .ok_or_else(|| Error { 156 | message: "Invalid type".to_owned(), 157 | })?, 158 | ) 159 | } 160 | 161 | impl_deserialize_n!(i8, deserialize_i8, visit_i8); 162 | impl_deserialize_n!(i16, deserialize_i16, visit_i16); 163 | impl_deserialize_n!(i32, deserialize_i32, visit_i32); 164 | impl_deserialize_n!(i64, deserialize_i64, visit_i64); 165 | 166 | impl_deserialize_n!(u8, deserialize_u8, visit_u8); 167 | impl_deserialize_n!(u16, deserialize_u16, visit_u16); 168 | impl_deserialize_n!(u32, deserialize_u32, visit_u32); 169 | impl_deserialize_n!(u64, deserialize_u64, visit_u64); 170 | 171 | impl_deserialize_n!(f32, deserialize_f32, visit_f32); 172 | impl_deserialize_n!(f64, deserialize_f64, visit_f64); 173 | 174 | fn deserialize_char(self, visitor: V) -> Result 175 | where 176 | V: serde::de::Visitor<'de>, 177 | { 178 | visitor.visit_char( 179 | self.read 180 | .get_attribute_value(&self.current_field) 181 | .ok_or_else(|| Error { 182 | message: format!("missing char for field {:?}", &self.current_field), 183 | })? 184 | .clone() 185 | .s 186 | .ok_or_else(|| Error { 187 | message: format!("missing char for field {:?}", &self.current_field), 188 | })? 189 | .parse::() 190 | .map_err(|_| Error { 191 | message: "Invalid type".to_owned(), 192 | })?, 193 | ) 194 | } 195 | 196 | fn deserialize_str(self, visitor: V) -> Result 197 | where 198 | V: serde::de::Visitor<'de>, 199 | { 200 | if self.as_key { 201 | match &self.current_field { 202 | Index::String(ref key) => visitor.visit_str(key), 203 | _ => visitor.visit_str(""), 204 | } 205 | } else if let Some(field) = self.read.get_attribute_value(&self.current_field) { 206 | field 207 | .clone() 208 | .s 209 | .ok_or_else(|| Error { 210 | message: format!("missing string for field {:?}", &self.current_field), 211 | }) 212 | .and_then(|string_field| visitor.visit_str(&string_field)) 213 | } else { 214 | visitor.visit_str("") 215 | } 216 | } 217 | 218 | fn deserialize_string(self, visitor: V) -> Result 219 | where 220 | V: serde::de::Visitor<'de>, 221 | { 222 | self.deserialize_str(visitor) 223 | } 224 | 225 | fn deserialize_bytes(self, visitor: V) -> Result 226 | where 227 | V: serde::de::Visitor<'de>, 228 | { 229 | if let Some(field) = self.read.get_attribute_value(&self.current_field) { 230 | field 231 | .clone() 232 | .b 233 | .ok_or_else(|| Error { 234 | message: format!("missing bytes for field {:?}", &self.current_field), 235 | }) 236 | .and_then(|bytes_field| visitor.visit_bytes(&bytes_field)) 237 | } else { 238 | visitor.visit_bytes(b"") 239 | } 240 | } 241 | 242 | fn deserialize_byte_buf(self, visitor: V) -> Result 243 | where 244 | V: serde::de::Visitor<'de>, 245 | { 246 | self.deserialize_bytes(visitor) 247 | } 248 | 249 | fn deserialize_option(self, visitor: V) -> Result 250 | where 251 | V: serde::de::Visitor<'de>, 252 | { 253 | if self.read.get_attribute_value(&self.current_field).is_none() { 254 | return visitor.visit_none(); 255 | } 256 | match self 257 | .read 258 | .get_attribute_value(&self.current_field) 259 | .ok_or_else(|| Error { 260 | message: format!("missing option for field {:?}", &self.current_field), 261 | })? 262 | .null 263 | { 264 | Some(true) => visitor.visit_none(), 265 | _ => visitor.visit_some(self), 266 | } 267 | } 268 | 269 | fn deserialize_unit(self, visitor: V) -> Result 270 | where 271 | V: serde::de::Visitor<'de>, 272 | { 273 | self.read 274 | .get_attribute_value(&self.current_field) 275 | .ok_or_else(|| Error { 276 | message: "Missing field".to_owned(), 277 | })? 278 | .null 279 | .ok_or_else(|| Error { 280 | message: format!("Missing null for field {:?}", &self.current_field), 281 | }) 282 | .and_then(|_| visitor.visit_unit()) 283 | } 284 | 285 | fn deserialize_unit_struct(self, _name: &'static str, visitor: V) -> Result 286 | where 287 | V: serde::de::Visitor<'de>, 288 | { 289 | self.deserialize_unit(visitor) 290 | } 291 | 292 | fn deserialize_newtype_struct(self, _name: &str, visitor: V) -> Result 293 | where 294 | V: serde::de::Visitor<'de>, 295 | { 296 | visitor.visit_newtype_struct(self) 297 | } 298 | 299 | fn deserialize_seq(self, visitor: V) -> Result 300 | where 301 | V: serde::de::Visitor<'de>, 302 | { 303 | let list = self 304 | .read 305 | .get_attribute_value(&self.current_field) 306 | .ok_or_else(|| Error { 307 | message: format!("missing sequence for field {:?}", &self.current_field), 308 | })? 309 | .clone(); 310 | let read = if let Some(alist) = list.l { 311 | VecRead { vec: alist } 312 | } else if let Some(numlist) = list.ns { 313 | VecRead { 314 | vec: numlist 315 | .into_iter() 316 | .map(|n| AttributeValue { 317 | n: Some(n), 318 | ..Default::default() 319 | }) 320 | .collect(), 321 | } 322 | } else if let Some(slist) = list.ss { 323 | VecRead { 324 | vec: slist 325 | .into_iter() 326 | .map(|s| AttributeValue { 327 | s: Some(s), 328 | ..Default::default() 329 | }) 330 | .collect(), 331 | } 332 | } else if let Some(blist) = list.bs { 333 | VecRead { 334 | vec: blist 335 | .into_iter() 336 | .map(|s| AttributeValue { 337 | b: Some(s), 338 | ..Default::default() 339 | }) 340 | .collect(), 341 | } 342 | } else { 343 | return Err(Error { 344 | message: "No sequence input found".to_owned(), 345 | }); 346 | }; 347 | let mut des = Deserializer::new(read); 348 | visitor.visit_seq(SeqAccess::new(&mut des)) 349 | } 350 | 351 | fn deserialize_tuple(self, _len: usize, visitor: V) -> Result 352 | where 353 | V: serde::de::Visitor<'de>, 354 | { 355 | match self.current_field { 356 | Index::None => { 357 | let mut des = Deserializer::new(self.read.clone()); 358 | visitor.visit_seq(TupleAccess::new(&mut des)) 359 | } 360 | _ => { 361 | let subread = HashMapRead { 362 | hashmap: self 363 | .read 364 | .get_attribute_value(&self.current_field) 365 | .ok_or_else(|| Error { 366 | message: format!("missing hashmap for field {:?}", &self.current_field), 367 | })? 368 | .m 369 | .clone() 370 | .unwrap(), 371 | }; 372 | let mut des = Deserializer::new(subread); 373 | visitor.visit_seq(TupleAccess::new(&mut des)) 374 | } 375 | } 376 | } 377 | 378 | fn deserialize_tuple_struct( 379 | self, 380 | _name: &'static str, 381 | _len: usize, 382 | visitor: V, 383 | ) -> Result 384 | where 385 | V: serde::de::Visitor<'de>, 386 | { 387 | match self.current_field { 388 | Index::None => { 389 | let mut des = Deserializer::new(self.read.clone()); 390 | visitor.visit_seq(TupleAccess::new(&mut des)) 391 | } 392 | _ => { 393 | let subread = HashMapRead { 394 | hashmap: self 395 | .read 396 | .get_attribute_value(&self.current_field) 397 | .ok_or_else(|| Error { 398 | message: format!("missing hashmap for field {:?}", &self.current_field), 399 | })? 400 | .m 401 | .clone() 402 | .unwrap(), 403 | }; 404 | let mut des = Deserializer::new(subread); 405 | visitor.visit_seq(TupleAccess::new(&mut des)) 406 | } 407 | } 408 | } 409 | 410 | fn deserialize_map(self, visitor: V) -> Result 411 | where 412 | V: serde::de::Visitor<'de>, 413 | { 414 | match self.current_field { 415 | Index::None => visitor.visit_map(MapAccess::new(self, self.read.get_keys())), 416 | _ => { 417 | let map = self 418 | .read 419 | .get_attribute_value(&self.current_field) 420 | .ok_or_else(|| Error { 421 | message: format!("missing struct for field {:?}", &self.current_field), 422 | })?; 423 | let hm = map.clone().m.unwrap_or_else(HashMap::new); 424 | let keys = hm.keys().cloned().collect(); 425 | let mut des = Deserializer::new(HashMapRead::new(hm)); 426 | visitor.visit_map(MapAccess::new(&mut des, keys)) 427 | } 428 | } 429 | } 430 | 431 | fn deserialize_struct( 432 | self, 433 | _name: &'static str, 434 | _fields: &'static [&'static str], 435 | visitor: V, 436 | ) -> Result 437 | where 438 | V: serde::de::Visitor<'de>, 439 | { 440 | match self.current_field { 441 | Index::None => visitor.visit_map(MapAccess::new(self, self.read.get_keys())), 442 | _ => { 443 | let map = self 444 | .read 445 | .get_attribute_value(&self.current_field) 446 | .ok_or_else(|| Error { 447 | message: format!("missing struct for field {:?}", &self.current_field), 448 | })?; 449 | let hm = map.clone().m.ok_or_else(|| Error { 450 | message: "Missing struct fields".to_owned(), 451 | })?; 452 | let keys = hm.keys().cloned().collect(); 453 | let mut des = Deserializer::new(HashMapRead::new(hm)); 454 | visitor.visit_map(MapAccess::new(&mut des, keys)) 455 | } 456 | } 457 | } 458 | 459 | fn deserialize_enum( 460 | self, 461 | _name: &str, 462 | _variants: &'static [&'static str], 463 | visitor: V, 464 | ) -> Result 465 | where 466 | V: serde::de::Visitor<'de>, 467 | { 468 | let (variant, values) = if let Index::None = self.current_field { 469 | let variant = self 470 | .read 471 | .get_attribute_value(&Index::String(String::from("___enum_tag"))) 472 | .ok_or_else(|| Error { 473 | message: "Missing enum tag field".to_owned(), 474 | })? 475 | .clone() 476 | .s 477 | .ok_or_else(|| Error { 478 | message: "Missing enum tag value".to_owned(), 479 | })?; 480 | let values = self 481 | .read 482 | .get_attribute_value(&Index::String(String::from("___enum_values"))) 483 | .and_then(|v| v.m.clone()); 484 | (variant, values) 485 | } else { 486 | let enum_field = self 487 | .read 488 | .get_attribute_value(&self.current_field) 489 | .ok_or_else(|| Error { 490 | message: format!("missing enum for field {:?}", &self.current_field), 491 | })?; 492 | if let Some(shortstyle) = enum_field.s.clone() { 493 | return visitor.visit_enum(shortstyle.into_deserializer()); 494 | } 495 | let base = enum_field.m.clone().ok_or_else(|| Error { 496 | message: "Missing enum data".to_owned(), 497 | })?; 498 | ( 499 | base.get("___enum_tag") 500 | .unwrap() 501 | .s 502 | .clone() 503 | .ok_or_else(|| Error { 504 | message: "Missing enum tag value".to_owned(), 505 | })?, 506 | base.get("___enum_values").and_then(|v| v.m.clone()), 507 | ) 508 | }; 509 | let mut des = Deserializer::new(HashMapRead::new(values.unwrap_or_else(HashMap::new))); 510 | visitor.visit_enum(EnumAccess::new(&mut des, variant)) 511 | } 512 | 513 | fn deserialize_identifier(self, visitor: V) -> Result 514 | where 515 | V: serde::de::Visitor<'de>, 516 | { 517 | match self.current_field { 518 | Index::String(ref value) => visitor.visit_str(&value.clone()), 519 | _ => Err(Error { 520 | message: "indentifier should be a string".to_string(), 521 | }), 522 | } 523 | } 524 | 525 | fn deserialize_ignored_any(self, visitor: V) -> Result 526 | where 527 | V: serde::de::Visitor<'de>, 528 | { 529 | visitor.visit_unit() 530 | } 531 | } 532 | 533 | struct EnumAccess<'a, R: 'a> { 534 | de: &'a mut Deserializer, 535 | variant_name: String, 536 | } 537 | impl<'a, R: 'a> EnumAccess<'a, R> { 538 | fn new(de: &'a mut Deserializer, variant_name: String) -> Self { 539 | EnumAccess { de, variant_name } 540 | } 541 | } 542 | impl<'de, 'a, R: Read + 'a> serde::de::EnumAccess<'de> for EnumAccess<'a, R> { 543 | type Error = Error; 544 | type Variant = VariantAccess<'a, R>; 545 | 546 | fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant)> 547 | where 548 | V: serde::de::DeserializeSeed<'de>, 549 | { 550 | let value = seed.deserialize(self.variant_name.into_deserializer())?; 551 | Ok((value, VariantAccess::new(self.de))) 552 | } 553 | } 554 | 555 | struct VariantAccess<'a, R: 'a> { 556 | de: &'a mut Deserializer, 557 | } 558 | impl<'a, R: 'a> VariantAccess<'a, R> { 559 | fn new(de: &'a mut Deserializer) -> Self { 560 | VariantAccess { de } 561 | } 562 | } 563 | impl<'de, 'a, R: Read + 'a> serde::de::VariantAccess<'de> for VariantAccess<'a, R> { 564 | type Error = Error; 565 | 566 | fn unit_variant(self) -> Result<()> { 567 | Ok(()) 568 | } 569 | 570 | fn newtype_variant_seed(self, seed: T) -> Result 571 | where 572 | T: serde::de::DeserializeSeed<'de>, 573 | { 574 | self.de.current_field = Index::String(String::from("_0")); 575 | seed.deserialize(&mut *self.de) 576 | } 577 | 578 | fn tuple_variant(self, _len: usize, visitor: V) -> Result 579 | where 580 | V: serde::de::Visitor<'de>, 581 | { 582 | visitor.visit_seq(TupleAccess::new(self.de)) 583 | } 584 | 585 | fn struct_variant(self, _fields: &'static [&'static str], visitor: V) -> Result 586 | where 587 | V: serde::de::Visitor<'de>, 588 | { 589 | visitor.visit_map(MapAccess::new(self.de, self.de.read.get_keys())) 590 | } 591 | } 592 | 593 | struct TupleAccess<'a, R: 'a> { 594 | de: &'a mut Deserializer, 595 | current: usize, 596 | } 597 | impl<'a, R: 'a> TupleAccess<'a, R> { 598 | fn new(de: &'a mut Deserializer) -> Self { 599 | TupleAccess { de, current: 0 } 600 | } 601 | } 602 | impl<'de, 'a, R: Read + 'a> serde::de::SeqAccess<'de> for TupleAccess<'a, R> { 603 | type Error = Error; 604 | 605 | fn next_element_seed(&mut self, seed: T) -> Result> 606 | where 607 | T: serde::de::DeserializeSeed<'de>, 608 | { 609 | self.de.current_field = Index::String(format!("_{}", self.current)); 610 | self.current += 1; 611 | if self 612 | .de 613 | .read 614 | .get_attribute_value(&self.de.current_field) 615 | .is_none() 616 | { 617 | return Ok(None); 618 | } 619 | seed.deserialize(&mut *self.de).map(Some) 620 | } 621 | } 622 | 623 | struct SeqAccess<'a, R: 'a> { 624 | de: &'a mut Deserializer, 625 | current: usize, 626 | } 627 | 628 | impl<'a, R: 'a> SeqAccess<'a, R> { 629 | fn new(de: &'a mut Deserializer) -> Self { 630 | SeqAccess { de, current: 0 } 631 | } 632 | } 633 | 634 | impl<'de, 'a, R: Read + 'a> serde::de::SeqAccess<'de> for SeqAccess<'a, R> { 635 | type Error = Error; 636 | 637 | fn next_element_seed(&mut self, seed: T) -> Result> 638 | where 639 | T: serde::de::DeserializeSeed<'de>, 640 | { 641 | self.de.current_field = Index::Number(self.current); 642 | self.current += 1; 643 | if self 644 | .de 645 | .read 646 | .get_attribute_value(&self.de.current_field) 647 | .is_none() 648 | { 649 | return Ok(None); 650 | } 651 | seed.deserialize(&mut *self.de).map(Some) 652 | } 653 | } 654 | 655 | struct MapAccess<'a, R: 'a> { 656 | de: &'a mut Deserializer, 657 | keys: Vec, 658 | current: usize, 659 | } 660 | 661 | impl<'a, R: 'a> MapAccess<'a, R> { 662 | fn new(de: &'a mut Deserializer, keys: Vec) -> Self { 663 | MapAccess { 664 | de, 665 | keys, 666 | current: 0, 667 | } 668 | } 669 | } 670 | 671 | impl<'de, 'a, R: Read + 'a> serde::de::MapAccess<'de> for MapAccess<'a, R> { 672 | type Error = Error; 673 | 674 | fn next_key_seed(&mut self, seed: K) -> Result> 675 | where 676 | K: serde::de::DeserializeSeed<'de>, 677 | { 678 | if self.current >= self.keys.len() { 679 | Ok(None) 680 | } else { 681 | self.de.current_field = Index::String(self.keys[self.current].to_string()); 682 | self.de.as_key = true; 683 | self.current += 1; 684 | seed.deserialize(&mut *self.de).map(Some) 685 | } 686 | } 687 | 688 | fn next_value_seed(&mut self, seed: V) -> Result 689 | where 690 | V: serde::de::DeserializeSeed<'de>, 691 | { 692 | self.de.as_key = false; 693 | seed.deserialize(&mut *self.de) 694 | } 695 | } 696 | 697 | fn from_trait<'de, R, T>(read: R) -> Result 698 | where 699 | R: Read, 700 | T: serde::de::Deserialize<'de>, 701 | { 702 | let mut de = Deserializer::new(read); 703 | let value = serde::de::Deserialize::deserialize(&mut de)?; 704 | 705 | Ok(value) 706 | } 707 | 708 | /// Deserialize an instance of type `T` from an `HashMap`. 709 | /// 710 | /// # Errors 711 | /// 712 | /// This conversion can fail if the structure of the input does not match the 713 | /// structure expected by `T`, for example if `T` is a struct type but the input 714 | /// contains something other than a JSON map. It can also fail if the structure 715 | /// is correct but `T`'s implementation of `Deserialize` decides that something 716 | /// is wrong with the data, for example required struct fields are missing from 717 | /// the JSON map or some number is too big to fit in the expected primitive 718 | /// type. 719 | pub fn from_hashmap<'a, T, S: ::std::hash::BuildHasher + Clone>( 720 | hm: HashMap, 721 | ) -> Result 722 | where 723 | T: serde::de::Deserialize<'a>, 724 | { 725 | from_trait(HashMapRead::new(hm)) 726 | } 727 | -------------------------------------------------------------------------------- /src/dynamodbstreams/mod.rs: -------------------------------------------------------------------------------- 1 | // generated file, see update_streams.sh 2 | 3 | pub mod de; 4 | pub mod ser; 5 | -------------------------------------------------------------------------------- /src/dynamodbstreams/ser.rs: -------------------------------------------------------------------------------- 1 | // generated file, see update_streams.sh 2 | 3 | //! Serialize a Rust data structure into HashMap. 4 | 5 | use std::collections::HashMap; 6 | 7 | use rusoto_dynamodbstreams::AttributeValue; 8 | 9 | use crate::common::SimpleKeySerializer; 10 | use crate::error::{Error, Result}; 11 | 12 | macro_rules! impl_serialize_n { 13 | ($type:ty, $method:ident) => { 14 | fn $method(self, value: $type) -> Result<()> { 15 | self.writer.insert_value(AttributeValue { 16 | n: Some(value.to_string()), 17 | ..Default::default() 18 | }); 19 | Ok(()) 20 | } 21 | }; 22 | } 23 | 24 | #[derive(Debug)] 25 | struct HashMapWriter { 26 | current_key: String, 27 | root: HashMap, 28 | } 29 | trait WriterTrait { 30 | fn set_key(&mut self, key: String); 31 | fn is_in_object(&self) -> bool; 32 | fn insert_value(&mut self, value: AttributeValue); 33 | } 34 | impl<'a> WriterTrait for &'a mut HashMapWriter { 35 | fn set_key(&mut self, key: String) { 36 | self.current_key = key; 37 | } 38 | fn is_in_object(&self) -> bool { 39 | !self.current_key.is_empty() 40 | } 41 | fn insert_value(&mut self, value: AttributeValue) { 42 | self.root.insert(self.current_key.clone(), value); 43 | } 44 | } 45 | 46 | #[derive(Debug)] 47 | struct VecWriter { 48 | list: Vec, 49 | } 50 | 51 | impl<'a> WriterTrait for &'a mut VecWriter { 52 | fn set_key(&mut self, _key: String) {} 53 | fn is_in_object(&self) -> bool { 54 | true 55 | } 56 | fn insert_value(&mut self, value: AttributeValue) { 57 | self.list.push(value); 58 | } 59 | } 60 | 61 | #[derive(Debug)] 62 | struct Serializer { 63 | writer: W, 64 | } 65 | impl Serializer 66 | where 67 | W: WriterTrait, 68 | { 69 | pub fn new(writer: W) -> Self { 70 | Serializer { writer } 71 | } 72 | } 73 | impl<'a, W> serde::Serializer for &'a mut Serializer 74 | where 75 | W: WriterTrait, 76 | { 77 | type Ok = (); 78 | type Error = Error; 79 | 80 | type SerializeSeq = SeqWriter<'a, W>; 81 | type SerializeTuple = Compound<'a, W>; 82 | type SerializeTupleStruct = Compound<'a, W>; 83 | type SerializeTupleVariant = EnumCompound<'a, W>; 84 | type SerializeMap = Compound<'a, W>; 85 | type SerializeStruct = Compound<'a, W>; 86 | type SerializeStructVariant = EnumCompound<'a, W>; 87 | 88 | fn serialize_bool(self, value: bool) -> Result<()> { 89 | self.writer.insert_value(AttributeValue { 90 | bool: Some(value), 91 | ..Default::default() 92 | }); 93 | Ok(()) 94 | } 95 | 96 | impl_serialize_n!(i8, serialize_i8); 97 | impl_serialize_n!(i16, serialize_i16); 98 | impl_serialize_n!(i32, serialize_i32); 99 | impl_serialize_n!(i64, serialize_i64); 100 | impl_serialize_n!(u8, serialize_u8); 101 | impl_serialize_n!(u16, serialize_u16); 102 | impl_serialize_n!(u32, serialize_u32); 103 | impl_serialize_n!(u64, serialize_u64); 104 | impl_serialize_n!(f32, serialize_f32); 105 | impl_serialize_n!(f64, serialize_f64); 106 | 107 | fn serialize_char(self, value: char) -> Result<()> { 108 | self.writer.insert_value(AttributeValue { 109 | s: Some(value.to_string()), 110 | ..Default::default() 111 | }); 112 | Ok(()) 113 | } 114 | 115 | fn serialize_str(self, value: &str) -> Result<()> { 116 | self.writer.insert_value(AttributeValue { 117 | s: Some(value.to_string()), 118 | ..Default::default() 119 | }); 120 | Ok(()) 121 | } 122 | 123 | fn serialize_bytes(self, value: &[u8]) -> Result<()> { 124 | self.writer.insert_value(AttributeValue { 125 | b: Some(bytes::Bytes::copy_from_slice(value)), 126 | ..Default::default() 127 | }); 128 | Ok(()) 129 | } 130 | 131 | fn serialize_unit(self) -> Result<()> { 132 | self.writer.insert_value(AttributeValue { 133 | null: Some(true), 134 | ..Default::default() 135 | }); 136 | Ok(()) 137 | } 138 | 139 | fn serialize_unit_struct(self, _name: &'static str) -> Result<()> { 140 | self.serialize_unit() 141 | } 142 | 143 | fn serialize_unit_variant( 144 | self, 145 | _name: &'static str, 146 | _variant_index: u32, 147 | variant: &'static str, 148 | ) -> Result<()> { 149 | EnumCompound::new(self, variant, false).end_wrapper(); 150 | Ok(()) 151 | } 152 | 153 | fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result<()> 154 | where 155 | T: serde::ser::Serialize, 156 | { 157 | value.serialize(self)?; 158 | Ok(()) 159 | } 160 | 161 | #[inline] 162 | fn serialize_newtype_variant( 163 | self, 164 | _name: &'static str, 165 | _variant_index: u32, 166 | variant: &'static str, 167 | value: &T, 168 | ) -> Result<()> 169 | where 170 | T: serde::ser::Serialize, 171 | { 172 | use serde::ser::SerializeTupleVariant; 173 | let mut compound = EnumCompound::new(self, variant, true); 174 | compound.serialize_field(value)?; 175 | compound.end() 176 | } 177 | 178 | fn serialize_none(self) -> Result<()> { 179 | self.writer.insert_value(AttributeValue { 180 | null: Some(true), 181 | ..Default::default() 182 | }); 183 | Ok(()) 184 | } 185 | 186 | fn serialize_some(self, value: &T) -> Result<()> 187 | where 188 | T: serde::ser::Serialize, 189 | { 190 | value.serialize(self) 191 | } 192 | 193 | fn serialize_seq(self, _len: Option) -> Result { 194 | Ok(SeqWriter::new(self)) 195 | } 196 | 197 | fn serialize_tuple(self, _len: usize) -> Result { 198 | Ok(Compound::new(self)) 199 | } 200 | 201 | fn serialize_tuple_struct( 202 | self, 203 | _name: &'static str, 204 | _len: usize, 205 | ) -> Result { 206 | Ok(Compound::new(self)) 207 | } 208 | 209 | fn serialize_tuple_variant( 210 | self, 211 | _name: &'static str, 212 | _variant_index: u32, 213 | variant: &'static str, 214 | _len: usize, 215 | ) -> Result { 216 | Ok(EnumCompound::new(self, variant, true)) 217 | } 218 | 219 | fn serialize_map(self, _len: Option) -> Result { 220 | Ok(Compound::new(self)) 221 | } 222 | 223 | fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { 224 | Ok(Compound::new(self)) 225 | } 226 | 227 | fn serialize_struct_variant( 228 | self, 229 | _name: &'static str, 230 | _variant_index: u32, 231 | variant: &'static str, 232 | _len: usize, 233 | ) -> Result { 234 | Ok(EnumCompound::new(self, variant, true)) 235 | } 236 | } 237 | 238 | #[derive(Debug)] 239 | struct SeqWriter<'a, W: 'a> { 240 | ser: &'a mut Serializer, 241 | current: VecWriter, 242 | } 243 | 244 | impl<'a, W> SeqWriter<'a, W> { 245 | fn new(ser: &'a mut Serializer) -> SeqWriter<'a, W> { 246 | let writer = VecWriter { list: Vec::new() }; 247 | SeqWriter { 248 | ser, 249 | current: writer, 250 | } 251 | } 252 | } 253 | 254 | impl<'a, W> serde::ser::SerializeSeq for SeqWriter<'a, W> 255 | where 256 | W: WriterTrait, 257 | { 258 | type Ok = (); 259 | type Error = Error; 260 | 261 | fn serialize_element(&mut self, value: &T) -> Result<()> 262 | where 263 | T: serde::ser::Serialize, 264 | { 265 | let mut ser = Serializer::new(&mut self.current); 266 | value.serialize(&mut ser) 267 | } 268 | 269 | fn end(self) -> Result<()> { 270 | self.ser.writer.insert_value(AttributeValue { 271 | l: Some(self.current.list.clone()), 272 | ..Default::default() 273 | }); 274 | Ok(()) 275 | } 276 | } 277 | 278 | #[derive(Debug)] 279 | enum Key { 280 | Index(usize), 281 | Key(String), 282 | None, 283 | } 284 | 285 | #[derive(Debug)] 286 | struct EnumCompound<'a, W: 'a> { 287 | ser: &'a mut Serializer, 288 | is_root: bool, 289 | values_writer: HashMapWriter, 290 | wrapper_to_close: Option, 291 | current_item: Key, 292 | } 293 | 294 | impl<'a, W> EnumCompound<'a, W> 295 | where 296 | W: WriterTrait, 297 | { 298 | fn new( 299 | ser: &'a mut Serializer, 300 | variant: &'static str, 301 | has_values: bool, 302 | ) -> EnumCompound<'a, W> { 303 | let wrapper_to_close = if ser.writer.is_in_object() { 304 | let mut writer = HashMapWriter { 305 | root: HashMap::new(), 306 | current_key: String::new(), 307 | }; 308 | 309 | (&mut writer).set_key(String::from("___enum_tag")); 310 | (&mut writer).insert_value(AttributeValue { 311 | s: Some(variant.to_string()), 312 | ..Default::default() 313 | }); 314 | if has_values { 315 | (&mut writer).set_key(String::from("___enum_values")); 316 | } 317 | Some(writer) 318 | } else { 319 | ser.writer.set_key(String::from("___enum_tag")); 320 | ser.writer.insert_value(AttributeValue { 321 | s: Some(variant.to_string()), 322 | ..Default::default() 323 | }); 324 | if has_values { 325 | ser.writer.set_key(String::from("___enum_values")); 326 | } 327 | 328 | None 329 | }; 330 | let values_writer = HashMapWriter { 331 | root: HashMap::new(), 332 | current_key: String::new(), 333 | }; 334 | let is_root = !ser.writer.is_in_object(); 335 | EnumCompound { 336 | ser, 337 | is_root, 338 | values_writer, 339 | wrapper_to_close, 340 | current_item: Key::None, 341 | } 342 | } 343 | 344 | fn end_wrapper(self) { 345 | if let Some(wrapper) = self.wrapper_to_close { 346 | self.ser.writer.insert_value(AttributeValue { 347 | m: Some(wrapper.root), 348 | ..Default::default() 349 | }); 350 | } 351 | } 352 | } 353 | impl<'a, W> serde::ser::SerializeTupleVariant for EnumCompound<'a, W> 354 | where 355 | W: WriterTrait, 356 | { 357 | type Ok = (); 358 | type Error = Error; 359 | 360 | fn serialize_field(&mut self, value: &T) -> Result<()> 361 | where 362 | T: serde::ser::Serialize, 363 | { 364 | if let Key::None = self.current_item { 365 | self.current_item = Key::Index(0); 366 | } 367 | if let Key::Index(idx) = self.current_item { 368 | let key = format!("_{}", idx); 369 | self.current_item = Key::Index(idx + 1); 370 | if self.is_root { 371 | self.ser.writer.set_key(key); 372 | value.serialize(&mut *self.ser)?; 373 | Ok(()) 374 | } else { 375 | (&mut self.values_writer).set_key(key); 376 | to_writer(&mut self.values_writer, value) 377 | } 378 | } else { 379 | Err(Error { 380 | message: String::from( 381 | "trying to serialize something that is not a tuple as a tuple", 382 | ), 383 | }) 384 | } 385 | } 386 | 387 | #[inline] 388 | fn end(self) -> Result<()> { 389 | if let Some(mut wrapper) = self.wrapper_to_close { 390 | (&mut wrapper).insert_value(AttributeValue { 391 | m: Some(self.values_writer.root.clone()), 392 | ..Default::default() 393 | }); 394 | if !self.is_root { 395 | self.ser.writer.insert_value(AttributeValue { 396 | m: Some(wrapper.root), 397 | ..Default::default() 398 | }); 399 | } 400 | } else if !self.is_root { 401 | self.ser.writer.insert_value(AttributeValue { 402 | m: Some(self.values_writer.root.clone()), 403 | ..Default::default() 404 | }); 405 | } 406 | Ok(()) 407 | } 408 | } 409 | 410 | impl<'a, W> serde::ser::SerializeStructVariant for EnumCompound<'a, W> 411 | where 412 | W: WriterTrait, 413 | { 414 | type Ok = (); 415 | type Error = Error; 416 | 417 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> 418 | where 419 | T: serde::ser::Serialize, 420 | { 421 | if self.is_root { 422 | self.ser.writer.set_key(String::from(key)); 423 | value.serialize(&mut *self.ser)?; 424 | Ok(()) 425 | } else { 426 | (&mut self.values_writer).set_key(String::from(key)); 427 | to_writer(&mut self.values_writer, value) 428 | } 429 | } 430 | 431 | fn end(self) -> Result<()> { 432 | if let Some(mut wrapper) = self.wrapper_to_close { 433 | (&mut wrapper).insert_value(AttributeValue { 434 | m: Some(self.values_writer.root.clone()), 435 | ..Default::default() 436 | }); 437 | if !self.is_root { 438 | self.ser.writer.insert_value(AttributeValue { 439 | m: Some(wrapper.root), 440 | ..Default::default() 441 | }); 442 | } 443 | } else if !self.is_root { 444 | self.ser.writer.insert_value(AttributeValue { 445 | m: Some(self.values_writer.root.clone()), 446 | ..Default::default() 447 | }); 448 | } 449 | Ok(()) 450 | } 451 | } 452 | 453 | #[derive(Debug)] 454 | struct Compound<'a, W: 'a> { 455 | ser: &'a mut Serializer, 456 | is_root: bool, 457 | current: HashMapWriter, 458 | current_item: Key, 459 | } 460 | 461 | impl<'a, W> Compound<'a, W> 462 | where 463 | W: WriterTrait, 464 | { 465 | fn new(ser: &'a mut Serializer) -> Compound<'a, W> { 466 | let writer = HashMapWriter { 467 | root: HashMap::new(), 468 | current_key: String::new(), 469 | }; 470 | let is_root = !ser.writer.is_in_object(); 471 | Compound { 472 | ser, 473 | is_root, 474 | current: writer, 475 | current_item: Key::None, 476 | } 477 | } 478 | } 479 | 480 | impl<'a, W> serde::ser::SerializeTuple for Compound<'a, W> 481 | where 482 | W: WriterTrait, 483 | { 484 | type Ok = (); 485 | type Error = Error; 486 | 487 | fn serialize_element(&mut self, value: &T) -> Result<()> 488 | where 489 | T: serde::ser::Serialize, 490 | { 491 | if let Key::None = self.current_item { 492 | self.current_item = Key::Index(0); 493 | } 494 | if let Key::Index(idx) = self.current_item { 495 | let key = format!("_{}", idx); 496 | self.current_item = Key::Index(idx + 1); 497 | if self.is_root { 498 | self.ser.writer.set_key(key); 499 | value.serialize(&mut *self.ser)?; 500 | Ok(()) 501 | } else { 502 | (&mut self.current).set_key(key); 503 | to_writer(&mut self.current, value) 504 | } 505 | } else { 506 | Err(Error { 507 | message: String::from( 508 | "trying to serialize something that is not a tuple as a tuple", 509 | ), 510 | }) 511 | } 512 | } 513 | 514 | #[inline] 515 | fn end(self) -> Result<()> { 516 | if !self.is_root { 517 | self.ser.writer.insert_value(AttributeValue { 518 | m: Some(self.current.root.clone()), 519 | ..Default::default() 520 | }); 521 | } 522 | Ok(()) 523 | } 524 | } 525 | 526 | impl<'a, W> serde::ser::SerializeTupleStruct for Compound<'a, W> 527 | where 528 | W: WriterTrait, 529 | { 530 | type Ok = (); 531 | type Error = Error; 532 | 533 | fn serialize_field(&mut self, value: &T) -> Result<()> 534 | where 535 | T: serde::ser::Serialize, 536 | { 537 | if let Key::None = self.current_item { 538 | self.current_item = Key::Index(0); 539 | } 540 | if let Key::Index(idx) = self.current_item { 541 | let key = format!("_{}", idx); 542 | self.current_item = Key::Index(idx + 1); 543 | if self.is_root { 544 | self.ser.writer.set_key(key); 545 | value.serialize(&mut *self.ser)?; 546 | Ok(()) 547 | } else { 548 | (&mut self.current).set_key(key); 549 | to_writer(&mut self.current, value) 550 | } 551 | } else { 552 | Err(Error { 553 | message: String::from( 554 | "trying to serialize something that is not a tuple as a tuple", 555 | ), 556 | }) 557 | } 558 | } 559 | 560 | fn end(self) -> Result<()> { 561 | if !self.is_root { 562 | self.ser.writer.insert_value(AttributeValue { 563 | m: Some(self.current.root.clone()), 564 | ..Default::default() 565 | }); 566 | } 567 | Ok(()) 568 | } 569 | } 570 | 571 | impl<'a, W> serde::ser::SerializeMap for Compound<'a, W> 572 | where 573 | W: WriterTrait, 574 | { 575 | type Ok = (); 576 | type Error = Error; 577 | 578 | fn serialize_key(&mut self, key: &T) -> Result<()> 579 | where 580 | T: serde::ser::Serialize, 581 | { 582 | let mut serializer = SimpleKeySerializer::new(); 583 | key.serialize(&mut serializer)?; 584 | self.current_item = Key::Key(serializer.get_result()); 585 | Ok(()) 586 | } 587 | 588 | fn serialize_value(&mut self, value: &T) -> Result<()> 589 | where 590 | T: serde::ser::Serialize, 591 | { 592 | if let Key::Key(key) = &self.current_item { 593 | if self.is_root { 594 | self.ser.writer.set_key(key.clone()); 595 | value.serialize(&mut *self.ser)?; 596 | Ok(()) 597 | } else { 598 | (&mut self.current).set_key(key.clone()); 599 | to_writer(&mut self.current, value) 600 | } 601 | } else { 602 | Err(Error { 603 | message: String::from( 604 | "trying to deserialize something that is not a struct as a struct", 605 | ), 606 | }) 607 | } 608 | } 609 | 610 | fn end(self) -> Result<()> { 611 | if !self.is_root { 612 | self.ser.writer.insert_value(AttributeValue { 613 | m: Some(self.current.root.clone()), 614 | ..Default::default() 615 | }); 616 | } 617 | Ok(()) 618 | } 619 | } 620 | 621 | impl<'a, W> serde::ser::SerializeStruct for Compound<'a, W> 622 | where 623 | W: WriterTrait, 624 | { 625 | type Ok = (); 626 | type Error = Error; 627 | 628 | fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> 629 | where 630 | T: serde::ser::Serialize, 631 | { 632 | if self.is_root { 633 | self.ser.writer.set_key(key.to_string()); 634 | value.serialize(&mut *self.ser)?; 635 | Ok(()) 636 | } else { 637 | (&mut self.current).set_key(key.to_string()); 638 | to_writer(&mut self.current, value) 639 | } 640 | } 641 | 642 | fn end(self) -> Result<()> { 643 | if !self.is_root { 644 | self.ser.writer.insert_value(AttributeValue { 645 | m: Some(self.current.root.clone()), 646 | ..Default::default() 647 | }); 648 | } 649 | Ok(()) 650 | } 651 | } 652 | 653 | fn to_writer(writer: &mut HashMapWriter, value: &T) -> Result<()> 654 | where 655 | T: serde::ser::Serialize, 656 | { 657 | let mut ser = Serializer::new(writer); 658 | value.serialize(&mut ser)?; 659 | Ok(()) 660 | } 661 | 662 | /// Serialize the given data structure as an `HashMap`. 663 | /// 664 | /// # Errors 665 | /// 666 | /// Serialization can fail if `T`'s implementation of `Serialize` decides to 667 | /// fail, or if `T` contains a map with non-string keys. 668 | pub fn to_hashmap(value: &T) -> Result> 669 | where 670 | T: serde::ser::Serialize, 671 | { 672 | let mut writer = HashMapWriter { 673 | root: HashMap::new(), 674 | current_key: String::new(), 675 | }; 676 | to_writer(&mut writer, value)?; 677 | Ok(writer.root) 678 | } 679 | -------------------------------------------------------------------------------- /src/error.rs: -------------------------------------------------------------------------------- 1 | //! This type represents all possible errors that can occur when serializing or deserializing DynamoDB data. 2 | 3 | /// Alias for a Result with the error type `serde_dynamodb::Error`. 4 | pub type Result = std::result::Result; 5 | 6 | /// This type represents all possible errors that can occur when serializing to or deserializing from DynamoDB. 7 | #[derive(Debug)] 8 | pub struct Error { 9 | /// Message describing the error 10 | pub message: String, 11 | } 12 | impl serde::ser::Error for Error { 13 | fn custom(msg: T) -> Error { 14 | Error { 15 | message: format!("{}", msg), 16 | } 17 | } 18 | } 19 | impl serde::de::Error for Error { 20 | fn custom(msg: T) -> Error { 21 | Error { 22 | message: format!("{}", msg), 23 | } 24 | } 25 | } 26 | impl std::fmt::Display for Error { 27 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 28 | std::fmt::Display::fmt(&self.message, f) 29 | } 30 | } 31 | impl std::error::Error for Error { 32 | fn description(&self) -> &str { 33 | &self.message 34 | } 35 | 36 | fn cause(&self) -> Option<&dyn std::error::Error> { 37 | None 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny( 2 | warnings, 3 | missing_debug_implementations, 4 | missing_copy_implementations, 5 | trivial_casts, 6 | trivial_numeric_casts, 7 | unsafe_code, 8 | unstable_features, 9 | unused_import_braces, 10 | unused_qualifications, 11 | missing_docs 12 | )] 13 | 14 | //! # DynamoDB 15 | //! 16 | //! In its low level API, DynamoDB works with JSON objects with extra levels to 17 | //! set the type of the values. 18 | //! 19 | //! ```json,ignore 20 | //! { 21 | //! "Item": { 22 | //! "Age": {"N": "8"}, 23 | //! "Colors": { 24 | //! "L": [ 25 | //! {"S": "White"}, 26 | //! {"S": "Brown"}, 27 | //! {"S": "Black"} 28 | //! ] 29 | //! }, 30 | //! "Name": {"S": "Fido"}, 31 | //! "Vaccinations": { 32 | //! "M": { 33 | //! "Rabies": { 34 | //! "L": [ 35 | //! {"S": "2009-03-17"}, 36 | //! {"S": "2011-09-21"}, 37 | //! {"S": "2014-07-08"} 38 | //! ] 39 | //! }, 40 | //! "Distemper": {"S": "2015-10-13"} 41 | //! } 42 | //! }, 43 | //! "Breed": {"S": "Beagle"}, 44 | //! "AnimalType": {"S": "Dog"} 45 | //! } 46 | //! } 47 | //! ``` 48 | //! 49 | //! The allowed type keys are described [here][aws_doc]. 50 | //! 51 | //! # Rusoto DynamoDB 52 | //! 53 | //! Rusoto DynamoDB map those values to [`AttributeValue`][dynamodb_attribute], 54 | //! and functions to get/set/... from DynamoDB use `HashMap` 55 | //! as a way to represent the data. 56 | //! 57 | //! # Parsing HashMap as strongly typed data structures 58 | //! 59 | //! Serde provides a powerful way of mapping HashMap data into Rust data structures 60 | //! largely automatically by using [serde_dynamodb::from_hashmap][from_hashmap] 61 | //! 62 | //! ```rust,ignore 63 | //! extern crate serde; 64 | //! extern crate serde_dynamodb; 65 | //! 66 | //! extern crate rusoto_core; 67 | //! extern crate rusoto_dynamodb; 68 | //! 69 | //! #[macro_use] 70 | //! extern crate serde_derive; 71 | //! 72 | //! use std::collections::HashMap; 73 | //! 74 | //! use rusoto_core::Region; 75 | //! use rusoto_dynamodb::{DynamoDb, DynamoDbClient, QueryInput, AttributeValue}; 76 | //! 77 | //! use serde_dynamodb::Error; 78 | //! 79 | //! #[derive(Serialize, Deserialize, Debug)] 80 | //! struct Person { 81 | //! surname: String, 82 | //! age: u8, 83 | //! phones: Vec, 84 | //! } 85 | //! 86 | //! fn typed_example() -> Result<(), Error> { 87 | //! 88 | //! let client = DynamoDbClient::simple(Region::UsEast1); 89 | //! 90 | //! let mut query = HashMap::new(); 91 | //! query.insert(String::from(":surname"), AttributeValue { 92 | //! s: Some(String::from("Smith")), 93 | //! ..Default::default() 94 | //! }); 95 | //! // get data from DynamoDB 96 | //! let persons: Vec = client 97 | //! .query(&QueryInput { 98 | //! table_name: String::from("person"), 99 | //! key_condition_expression: Some(String::from("surname = :surname")), 100 | //! expression_attribute_values: Some(query), 101 | //! ..Default::default() 102 | //! }) 103 | //! .sync() 104 | //! .unwrap() 105 | //! .items 106 | //! .unwrap_or_else(|| vec![]) 107 | //! .into_iter() 108 | //! .map(|item| serde_dynamodb::from_hashmap(item).unwrap()) 109 | //! .collect(); 110 | //! 111 | //! 112 | //! // Do things just like with any other Rust data structure. 113 | //! for p in persons { 114 | //! println!("Please call {} at the number {}", p.surname, p.phones[0]); 115 | //! } 116 | //! 117 | //! Ok(()) 118 | //! } 119 | //! ``` 120 | //! 121 | //! # Creating an HashMap by serializing data structures 122 | //! 123 | //! A data structure can be converted to an HashMap by 124 | //! [`serde_dynamodb::to_hashmap`][to_hashmap]. 125 | //! 126 | //! ```rust 127 | //! use serde::{Serialize, Deserialize}; 128 | //! use serde_dynamodb::Error; 129 | //! 130 | //! #[derive(Serialize, Deserialize, Debug)] 131 | //! struct Address { 132 | //! street: String, 133 | //! city: String, 134 | //! } 135 | //! 136 | //! # #[cfg(feature = "rusoto_dynamodb")] 137 | //! fn print_an_address() -> Result<(), Error> { 138 | //! // Some data structure. 139 | //! let address = Address { 140 | //! street: "10 Downing Street".to_owned(), 141 | //! city: "London".to_owned(), 142 | //! }; 143 | //! 144 | //! // Serialize it to an HashMap. 145 | //! let dynamodb_object = serde_dynamodb::to_hashmap(&address)?; 146 | //! 147 | //! // Print, write to a file, or send to an HTTP server. 148 | //! println!("{:?}", dynamodb_object); 149 | //! 150 | //! Ok(()) 151 | //! } 152 | //! ``` 153 | //! 154 | //! # Features 155 | //! 156 | //! ## rusoto_dynamodb 157 | //! 158 | //! Feature `rusoto_dynamodb` is enabled by default and add methods 159 | //! [`serde_dynamodb::from_hashmap`][from_hashmap] and 160 | //! [`serde_dynamodb::to_hashmap`][to_hashmap]. Those methods work with 161 | //! [`AttributeValue`][dynamodb_attribute] from [DynamoDB][dynamodb]. 162 | //! 163 | //! ## rusoto_dynamodbstreams 164 | //! 165 | //! Feature `rusoto_dynamodbstreams` is disabled by default and add module 166 | //! [`streams`][streams] with methods 167 | //! [`serde_dynamodb::streams::from_hashmap`][from_hashmap_streams] and 168 | //! [`serde_dynamodb::streams::to_hashmap`][to_hashmap_streams]. Those methods work with 169 | //! [`AttributeValue`][dynamodbstreams_attribute] from [DynamoDB Streams][dynamodbstreams]. 170 | //! 171 | //! [aws_doc]: https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Programming.LowLevelAPI.html#Programming.LowLevelAPI.DataTypeDescriptors 172 | //! [dynamodb]: https://rusoto.github.io/rusoto/rusoto_dynamodb/index.html 173 | //! [dynamodb_attribute]: https://rusoto.github.io/rusoto/rusoto_dynamodb/struct.AttributeValue.html 174 | //! [dynamodbstreams]: https://rusoto.github.io/rusoto/rusoto_dynamodbstreams/index.html 175 | //! [dynamodbstreams_attribute]: https://rusoto.github.io/rusoto/rusoto_dynamodbstreams/struct.AttributeValue.html 176 | //! [to_hashmap]: fn.to_hashmap.html 177 | //! [from_hashmap]: fn.from_hashmap.html 178 | //! [streams]: streams/index.html 179 | //! [to_hashmap_streams]: streams/fn.to_hashmap.html 180 | //! [from_hashmap_streams]: streams/fn.from_hashmap.html 181 | //! 182 | 183 | pub mod error; 184 | 185 | pub use error::Error; 186 | 187 | mod common; 188 | 189 | #[cfg(feature = "rusoto_dynamodb")] 190 | mod dynamodb; 191 | #[cfg(feature = "rusoto_dynamodb")] 192 | pub use dynamodb::de::from_hashmap; 193 | #[cfg(feature = "rusoto_dynamodb")] 194 | pub use dynamodb::ser::to_hashmap; 195 | 196 | #[cfg(feature = "rusoto_dynamodbstreams")] 197 | mod dynamodbstreams; 198 | #[cfg(feature = "rusoto_dynamodbstreams")] 199 | pub mod streams { 200 | //! Methods in this module are generated to work with 201 | //! [`AttributeValue`][dynamodbstreams_attribute] from [DynamoDB Streams][dynamodbstreams] 202 | //! instead of [`AttributeValue`][dynamodb_attribute] from [DynamoDB][dynamodb]. 203 | //! 204 | //! [dynamodb]: https://rusoto.github.io/rusoto/rusoto_dynamodb/index.html 205 | //! [dynamodb_attribute]: https://rusoto.github.io/rusoto/rusoto_dynamodb/struct.AttributeValue.html 206 | //! [dynamodbstreams]: https://rusoto.github.io/rusoto/rusoto_dynamodbstreams/index.html 207 | //! [dynamodbstreams_attribute]: https://rusoto.github.io/rusoto/rusoto_dynamodbstreams/struct.AttributeValue.html 208 | pub use crate::dynamodbstreams::de::from_hashmap; 209 | pub use crate::dynamodbstreams::ser::to_hashmap; 210 | } 211 | 212 | /// A data structure that can be used as a DynamoDB `QueryInput` 213 | #[cfg(feature = "rusoto_dynamodb")] 214 | pub trait ToQueryInput { 215 | /// Transform this structure as a DynamoDB `QueryInput` on the given `table` 216 | fn to_query_input(&self, table: String) -> rusoto_dynamodb::QueryInput; 217 | } 218 | -------------------------------------------------------------------------------- /tests/dynamodb.rs: -------------------------------------------------------------------------------- 1 | #![cfg(feature = "rusoto_dynamodb")] 2 | 3 | use rusoto_dynamodb::AttributeValue; 4 | use serde::de::{MapAccess, Visitor}; 5 | use serde::ser::SerializeStruct; 6 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 7 | use std::collections::{HashMap, HashSet}; 8 | use std::fmt; 9 | 10 | macro_rules! test_with { 11 | ($type:ty, $val:expr) => { 12 | let original = $val; 13 | let serialized = serde_dynamodb::to_hashmap(&original).unwrap(); 14 | let deserialized: std::result::Result<$type, serde_dynamodb::Error> = 15 | serde_dynamodb::from_hashmap(dbg!(serialized)); 16 | assert!(dbg!(&deserialized).is_ok()); 17 | assert_eq!(original, deserialized.unwrap()); 18 | }; 19 | } 20 | 21 | #[test] 22 | fn can_serialize_struct() { 23 | #[derive(Serialize)] 24 | struct Basic { 25 | i: i32, 26 | f: f32, 27 | } 28 | let value = Basic { i: 5, f: 10.2 }; 29 | assert!(serde_dynamodb::to_hashmap(&value).is_ok()) 30 | } 31 | 32 | #[test] 33 | fn can_deserialize_struct() { 34 | #[derive(Deserialize, Debug)] 35 | struct Internal { 36 | k: i32, 37 | } 38 | #[derive(Deserialize, Debug)] 39 | struct Basic { 40 | i: i32, 41 | j: i32, 42 | intern: Internal, 43 | } 44 | let mut value = HashMap::new(); 45 | value.insert( 46 | "i".to_string(), 47 | AttributeValue { 48 | n: Some("5".to_string()), 49 | ..Default::default() 50 | }, 51 | ); 52 | value.insert( 53 | "j".to_string(), 54 | AttributeValue { 55 | n: Some("12".to_string()), 56 | ..Default::default() 57 | }, 58 | ); 59 | let mut intern = HashMap::new(); 60 | intern.insert( 61 | "k".to_string(), 62 | AttributeValue { 63 | n: Some("27".to_string()), 64 | ..Default::default() 65 | }, 66 | ); 67 | value.insert( 68 | "intern".to_string(), 69 | AttributeValue { 70 | m: Some(intern), 71 | ..Default::default() 72 | }, 73 | ); 74 | let res: serde_dynamodb::error::Result = serde_dynamodb::from_hashmap(value); 75 | assert!(res.is_ok()); 76 | } 77 | 78 | #[test] 79 | fn can_go_back_and_forth() { 80 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 81 | enum MyEnum { 82 | Unit, 83 | Newtype(i32), 84 | Tuple(i32, bool), 85 | Struct { f: i32 }, 86 | } 87 | #[derive(Deserialize, Serialize, Debug, PartialEq)] 88 | struct Internal { 89 | k: i32, 90 | f: f64, 91 | } 92 | #[derive(Deserialize, Serialize, Debug, PartialEq)] 93 | struct Unit; 94 | #[derive(Deserialize, Serialize, Debug, PartialEq)] 95 | struct Basic { 96 | i: i32, 97 | j: i32, 98 | f: f32, 99 | d: f64, 100 | b: u8, 101 | u: u32, 102 | c: char, 103 | e1: MyEnum, 104 | e2: MyEnum, 105 | e3: MyEnum, 106 | e4: MyEnum, 107 | intern: Internal, 108 | list: Vec, 109 | some: Option, 110 | none: Option, 111 | complex: Vec>, 112 | unit: (), 113 | unit_struct: Unit, 114 | } 115 | let value = Basic { 116 | i: 18, 117 | j: 74, 118 | f: 21.55, 119 | d: -45206.153, 120 | b: 13, 121 | u: 312, 122 | c: 0 as char, 123 | e1: MyEnum::Unit, 124 | e2: MyEnum::Newtype(5), 125 | e3: MyEnum::Tuple(12, false), 126 | e4: MyEnum::Struct { f: 27 }, 127 | intern: Internal { k: 512, f: 13.54 }, 128 | list: vec![0, 2, 5], 129 | some: Some(Internal { k: 120, f: 144.304 }), 130 | none: None, 131 | complex: vec![None, Some(Internal { k: 10, f: 12.56 })], 132 | unit: (), 133 | unit_struct: Unit, 134 | }; 135 | let hm = serde_dynamodb::to_hashmap(&value).unwrap(); 136 | let out: Basic = serde_dynamodb::from_hashmap(hm).unwrap(); 137 | assert_eq!(value, out); 138 | } 139 | 140 | #[test] 141 | fn can_serialize_struct_leveled() { 142 | #[derive(Serialize)] 143 | struct Internal { 144 | i: i32, 145 | } 146 | #[derive(Serialize)] 147 | struct Basic { 148 | intern: Internal, 149 | } 150 | let value = Basic { 151 | intern: Internal { i: 5 }, 152 | }; 153 | assert!(serde_dynamodb::to_hashmap(&value).is_ok()) 154 | } 155 | 156 | #[test] 157 | fn can_create_struct_custom_serialization() { 158 | #[derive(Debug)] 159 | struct Point { 160 | x_y: u8, 161 | } 162 | 163 | impl Point { 164 | fn from_coor(x: u8, y: u8) -> Point { 165 | Point { x_y: x + y } 166 | } 167 | } 168 | 169 | impl Serialize for Point { 170 | #[allow(unused_must_use)] 171 | fn serialize(&self, serializer: S) -> Result 172 | where 173 | S: Serializer, 174 | { 175 | let mut state = serializer.serialize_struct("Point", 2)?; 176 | let x = &self.x_y / 2 - 1; 177 | let x_str = format!("{}", x); 178 | let y = &self.x_y / 2 + 1; 179 | let y_str = format!("{}", y); 180 | state.serialize_field("x", &x_str); 181 | state.serialize_field("y", &y_str); 182 | state.end() 183 | } 184 | } 185 | 186 | impl<'de> Deserialize<'de> for Point { 187 | fn deserialize(deserializer: D) -> Result 188 | where 189 | D: Deserializer<'de>, 190 | { 191 | let fields = &["x", "y"]; 192 | deserializer.deserialize_struct("Point", fields, PointVisitor) 193 | } 194 | } 195 | 196 | struct PointVisitor; 197 | 198 | impl<'de> Visitor<'de> for PointVisitor { 199 | type Value = Point; 200 | 201 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 202 | formatter.write_str("Point") 203 | } 204 | 205 | fn visit_map>(self, mut map: E) -> Result { 206 | let mut x = String::new(); 207 | let mut y = String::new(); 208 | 209 | while let Some(ref key) = map.next_key::()? { 210 | let v = map.next_value::()?; 211 | if key == "x" { 212 | x = v 213 | } else if key == "y" { 214 | y = v 215 | } else { 216 | panic!("Serialization failed!") 217 | } 218 | } 219 | let num_x: u8 = x.parse::().unwrap(); 220 | let num_y: u8 = y.parse::().unwrap(); 221 | Ok(Point::from_coor(num_x, num_y)) 222 | } 223 | } 224 | 225 | let value = Point { x_y: 100 }; 226 | 227 | let hm = serde_dynamodb::to_hashmap(&value).unwrap(); 228 | let point_result: std::result::Result = 229 | serde_dynamodb::from_hashmap(hm); 230 | assert!(point_result.is_ok()) 231 | } 232 | 233 | #[test] 234 | fn can_deserialize_hashset() { 235 | #[derive(Deserialize, Debug, PartialEq)] 236 | struct Foo { 237 | bar: HashSet, 238 | baz: HashSet, 239 | } 240 | let mut value: HashMap = HashMap::new(); 241 | value.insert( 242 | "bar".to_string(), 243 | AttributeValue { 244 | ss: Some(vec!["foo".to_owned(), "bar".to_owned()]), 245 | ..Default::default() 246 | }, 247 | ); 248 | value.insert( 249 | "baz".to_string(), 250 | AttributeValue { 251 | ns: Some(vec!["3".to_owned(), "4".to_owned(), "5".to_owned()]), 252 | ..Default::default() 253 | }, 254 | ); 255 | 256 | let test_hashes: Foo = serde_dynamodb::from_hashmap(value).unwrap(); 257 | let mut expected = HashSet::new(); 258 | expected.insert("foo".to_owned()); 259 | expected.insert("bar".to_owned()); 260 | assert_eq!(test_hashes.bar, expected); 261 | 262 | let mut expected = HashSet::new(); 263 | expected.insert(3); 264 | expected.insert(4); 265 | expected.insert(5); 266 | assert_eq!(test_hashes.baz, expected); 267 | } 268 | 269 | #[test] 270 | fn can_be_missing_with_default() { 271 | // example from https://serde.rs/attr-default.html 272 | #[derive(Deserialize, Debug)] 273 | struct Request { 274 | #[serde(default = "default_resource")] 275 | resource: String, 276 | #[serde(default)] 277 | timeout: Timeout, 278 | #[serde(default = "Priority::lowest")] 279 | priority: Priority, 280 | } 281 | fn default_resource() -> String { 282 | "/".to_string() 283 | } 284 | #[derive(Deserialize, Debug, PartialEq)] 285 | struct Timeout(u32); 286 | impl Default for Timeout { 287 | fn default() -> Self { 288 | Timeout(30) 289 | } 290 | } 291 | #[derive(Deserialize, Debug, PartialEq)] 292 | enum Priority { 293 | ExtraHigh, 294 | High, 295 | Normal, 296 | Low, 297 | ExtraLow, 298 | } 299 | impl Priority { 300 | fn lowest() -> Self { 301 | Priority::ExtraLow 302 | } 303 | } 304 | 305 | let value: HashMap = HashMap::new(); 306 | 307 | let request: Request = serde_dynamodb::from_hashmap(value).unwrap(); 308 | assert_eq!(request.resource, "/"); 309 | assert_eq!(request.timeout, Timeout(30)); 310 | assert_eq!(request.priority, Priority::ExtraLow); 311 | } 312 | 313 | #[test] 314 | fn can_serialize_bytes() { 315 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 316 | struct WithBytes { 317 | b: Vec, 318 | } 319 | 320 | test_with!( 321 | WithBytes, 322 | WithBytes { 323 | b: vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29], 324 | } 325 | ); 326 | } 327 | 328 | #[test] 329 | fn can_serialize_tuple() { 330 | test_with!((u32, String), (1, String::from("a"))); 331 | } 332 | 333 | #[test] 334 | fn can_serialize_tuple_in_struct() { 335 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 336 | struct WithTuple { 337 | t: (u32, String), 338 | } 339 | 340 | test_with!( 341 | WithTuple, 342 | WithTuple { 343 | t: (1, String::from("a")), 344 | } 345 | ); 346 | } 347 | 348 | #[test] 349 | fn can_serialize_tuple_struct() { 350 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 351 | struct Point(i32, i32, bool); 352 | 353 | test_with!(Point, Point(1, 2, false)); 354 | } 355 | 356 | #[test] 357 | fn can_serialize_hashmap() { 358 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 359 | struct WithHashmap { 360 | hm: HashMap, 361 | } 362 | 363 | let mut value = HashMap::new(); 364 | value.insert("a".to_string(), "hoho".to_string()); 365 | value.insert("b".to_string(), "haha".to_string()); 366 | 367 | test_with!(WithHashmap, WithHashmap { hm: value }); 368 | } 369 | 370 | #[test] 371 | fn can_serialize_enum() { 372 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 373 | enum MyEnum { 374 | Unit, 375 | Newtype(i32), 376 | Tuple(i32, bool), 377 | Struct { f: i32 }, 378 | } 379 | 380 | test_with!(MyEnum, MyEnum::Unit); 381 | test_with!(MyEnum, MyEnum::Newtype(5)); 382 | test_with!(MyEnum, MyEnum::Tuple(5, false)); 383 | test_with!(MyEnum, MyEnum::Struct { f: 7 }); 384 | } 385 | 386 | #[test] 387 | fn can_serialize_enum_in_struct() { 388 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 389 | enum MyEnum { 390 | Unit, 391 | Newtype(i32), 392 | Tuple(i32, bool), 393 | Struct { f: i32 }, 394 | } 395 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 396 | struct WithEnum { 397 | my_enum: MyEnum, 398 | } 399 | 400 | test_with!( 401 | WithEnum, 402 | WithEnum { 403 | my_enum: MyEnum::Unit 404 | } 405 | ); 406 | test_with!( 407 | WithEnum, 408 | WithEnum { 409 | my_enum: MyEnum::Newtype(5) 410 | } 411 | ); 412 | test_with!( 413 | WithEnum, 414 | WithEnum { 415 | my_enum: MyEnum::Tuple(5, false) 416 | } 417 | ); 418 | test_with!( 419 | WithEnum, 420 | WithEnum { 421 | my_enum: MyEnum::Struct { f: 7 } 422 | } 423 | ); 424 | } 425 | 426 | #[test] 427 | fn can_serialize_shortstyle_enum_in_struct() { 428 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 429 | enum MyEnum { 430 | Unit, 431 | Newtype(i32), 432 | Tuple(i32, bool), 433 | Struct { f: i32 }, 434 | } 435 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 436 | struct WithEnum { 437 | my_enum: MyEnum, 438 | } 439 | 440 | let mut value: HashMap = HashMap::new(); 441 | value.insert( 442 | "my_enum".to_string(), 443 | AttributeValue { 444 | s: Some(String::from("Unit")), 445 | ..Default::default() 446 | }, 447 | ); 448 | 449 | let deserialized: std::result::Result = 450 | serde_dynamodb::from_hashmap(value); 451 | assert!(dbg!(&deserialized).is_ok()); 452 | assert_eq!( 453 | WithEnum { 454 | my_enum: MyEnum::Unit 455 | }, 456 | deserialized.unwrap() 457 | ); 458 | } 459 | -------------------------------------------------------------------------------- /tests/dynamodbstreams.rs: -------------------------------------------------------------------------------- 1 | // generated file, see update_streams.sh 2 | 3 | #![cfg(feature = "rusoto_dynamodbstreams")] 4 | 5 | use rusoto_dynamodbstreams::AttributeValue; 6 | use serde::de::{MapAccess, Visitor}; 7 | use serde::ser::SerializeStruct; 8 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 9 | use std::collections::{HashMap, HashSet}; 10 | use std::fmt; 11 | 12 | macro_rules! test_with { 13 | ($type:ty, $val:expr) => { 14 | let original = $val; 15 | let serialized = serde_dynamodb::streams::to_hashmap(&original).unwrap(); 16 | let deserialized: std::result::Result<$type, serde_dynamodb::Error> = 17 | serde_dynamodb::streams::from_hashmap(dbg!(serialized)); 18 | assert!(dbg!(&deserialized).is_ok()); 19 | assert_eq!(original, deserialized.unwrap()); 20 | }; 21 | } 22 | 23 | #[test] 24 | fn can_serialize_struct() { 25 | #[derive(Serialize)] 26 | struct Basic { 27 | i: i32, 28 | f: f32, 29 | } 30 | let value = Basic { i: 5, f: 10.2 }; 31 | assert!(serde_dynamodb::streams::to_hashmap(&value).is_ok()) 32 | } 33 | 34 | #[test] 35 | fn can_deserialize_struct() { 36 | #[derive(Deserialize, Debug)] 37 | struct Internal { 38 | k: i32, 39 | } 40 | #[derive(Deserialize, Debug)] 41 | struct Basic { 42 | i: i32, 43 | j: i32, 44 | intern: Internal, 45 | } 46 | let mut value = HashMap::new(); 47 | value.insert( 48 | "i".to_string(), 49 | AttributeValue { 50 | n: Some("5".to_string()), 51 | ..Default::default() 52 | }, 53 | ); 54 | value.insert( 55 | "j".to_string(), 56 | AttributeValue { 57 | n: Some("12".to_string()), 58 | ..Default::default() 59 | }, 60 | ); 61 | let mut intern = HashMap::new(); 62 | intern.insert( 63 | "k".to_string(), 64 | AttributeValue { 65 | n: Some("27".to_string()), 66 | ..Default::default() 67 | }, 68 | ); 69 | value.insert( 70 | "intern".to_string(), 71 | AttributeValue { 72 | m: Some(intern), 73 | ..Default::default() 74 | }, 75 | ); 76 | let res: serde_dynamodb::error::Result = serde_dynamodb::streams::from_hashmap(value); 77 | assert!(res.is_ok()); 78 | } 79 | 80 | #[test] 81 | fn can_go_back_and_forth() { 82 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 83 | enum MyEnum { 84 | Unit, 85 | Newtype(i32), 86 | Tuple(i32, bool), 87 | Struct { f: i32 }, 88 | } 89 | #[derive(Deserialize, Serialize, Debug, PartialEq)] 90 | struct Internal { 91 | k: i32, 92 | f: f64, 93 | } 94 | #[derive(Deserialize, Serialize, Debug, PartialEq)] 95 | struct Unit; 96 | #[derive(Deserialize, Serialize, Debug, PartialEq)] 97 | struct Basic { 98 | i: i32, 99 | j: i32, 100 | f: f32, 101 | d: f64, 102 | b: u8, 103 | u: u32, 104 | c: char, 105 | e1: MyEnum, 106 | e2: MyEnum, 107 | e3: MyEnum, 108 | e4: MyEnum, 109 | intern: Internal, 110 | list: Vec, 111 | some: Option, 112 | none: Option, 113 | complex: Vec>, 114 | unit: (), 115 | unit_struct: Unit, 116 | } 117 | let value = Basic { 118 | i: 18, 119 | j: 74, 120 | f: 21.55, 121 | d: -45206.153, 122 | b: 13, 123 | u: 312, 124 | c: 0 as char, 125 | e1: MyEnum::Unit, 126 | e2: MyEnum::Newtype(5), 127 | e3: MyEnum::Tuple(12, false), 128 | e4: MyEnum::Struct { f: 27 }, 129 | intern: Internal { k: 512, f: 13.54 }, 130 | list: vec![0, 2, 5], 131 | some: Some(Internal { k: 120, f: 144.304 }), 132 | none: None, 133 | complex: vec![None, Some(Internal { k: 10, f: 12.56 })], 134 | unit: (), 135 | unit_struct: Unit, 136 | }; 137 | let hm = serde_dynamodb::streams::to_hashmap(&value).unwrap(); 138 | let out: Basic = serde_dynamodb::streams::from_hashmap(hm).unwrap(); 139 | assert_eq!(value, out); 140 | } 141 | 142 | #[test] 143 | fn can_serialize_struct_leveled() { 144 | #[derive(Serialize)] 145 | struct Internal { 146 | i: i32, 147 | } 148 | #[derive(Serialize)] 149 | struct Basic { 150 | intern: Internal, 151 | } 152 | let value = Basic { 153 | intern: Internal { i: 5 }, 154 | }; 155 | assert!(serde_dynamodb::streams::to_hashmap(&value).is_ok()) 156 | } 157 | 158 | #[test] 159 | fn can_create_struct_custom_serialization() { 160 | #[derive(Debug)] 161 | struct Point { 162 | x_y: u8, 163 | } 164 | 165 | impl Point { 166 | fn from_coor(x: u8, y: u8) -> Point { 167 | Point { x_y: x + y } 168 | } 169 | } 170 | 171 | impl Serialize for Point { 172 | #[allow(unused_must_use)] 173 | fn serialize(&self, serializer: S) -> Result 174 | where 175 | S: Serializer, 176 | { 177 | let mut state = serializer.serialize_struct("Point", 2)?; 178 | let x = &self.x_y / 2 - 1; 179 | let x_str = format!("{}", x); 180 | let y = &self.x_y / 2 + 1; 181 | let y_str = format!("{}", y); 182 | state.serialize_field("x", &x_str); 183 | state.serialize_field("y", &y_str); 184 | state.end() 185 | } 186 | } 187 | 188 | impl<'de> Deserialize<'de> for Point { 189 | fn deserialize(deserializer: D) -> Result 190 | where 191 | D: Deserializer<'de>, 192 | { 193 | let fields = &["x", "y"]; 194 | deserializer.deserialize_struct("Point", fields, PointVisitor) 195 | } 196 | } 197 | 198 | struct PointVisitor; 199 | 200 | impl<'de> Visitor<'de> for PointVisitor { 201 | type Value = Point; 202 | 203 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 204 | formatter.write_str("Point") 205 | } 206 | 207 | fn visit_map>(self, mut map: E) -> Result { 208 | let mut x = String::new(); 209 | let mut y = String::new(); 210 | 211 | while let Some(ref key) = map.next_key::()? { 212 | let v = map.next_value::()?; 213 | if key == "x" { 214 | x = v 215 | } else if key == "y" { 216 | y = v 217 | } else { 218 | panic!("Serialization failed!") 219 | } 220 | } 221 | let num_x: u8 = x.parse::().unwrap(); 222 | let num_y: u8 = y.parse::().unwrap(); 223 | Ok(Point::from_coor(num_x, num_y)) 224 | } 225 | } 226 | 227 | let value = Point { x_y: 100 }; 228 | 229 | let hm = serde_dynamodb::streams::to_hashmap(&value).unwrap(); 230 | let point_result: std::result::Result = 231 | serde_dynamodb::streams::from_hashmap(hm); 232 | assert!(point_result.is_ok()) 233 | } 234 | 235 | #[test] 236 | fn can_deserialize_hashset() { 237 | #[derive(Deserialize, Debug, PartialEq)] 238 | struct Foo { 239 | bar: HashSet, 240 | baz: HashSet, 241 | } 242 | let mut value: HashMap = HashMap::new(); 243 | value.insert( 244 | "bar".to_string(), 245 | AttributeValue { 246 | ss: Some(vec!["foo".to_owned(), "bar".to_owned()]), 247 | ..Default::default() 248 | }, 249 | ); 250 | value.insert( 251 | "baz".to_string(), 252 | AttributeValue { 253 | ns: Some(vec!["3".to_owned(), "4".to_owned(), "5".to_owned()]), 254 | ..Default::default() 255 | }, 256 | ); 257 | 258 | let test_hashes: Foo = serde_dynamodb::streams::from_hashmap(value).unwrap(); 259 | let mut expected = HashSet::new(); 260 | expected.insert("foo".to_owned()); 261 | expected.insert("bar".to_owned()); 262 | assert_eq!(test_hashes.bar, expected); 263 | 264 | let mut expected = HashSet::new(); 265 | expected.insert(3); 266 | expected.insert(4); 267 | expected.insert(5); 268 | assert_eq!(test_hashes.baz, expected); 269 | } 270 | 271 | #[test] 272 | fn can_be_missing_with_default() { 273 | // example from https://serde.rs/attr-default.html 274 | #[derive(Deserialize, Debug)] 275 | struct Request { 276 | #[serde(default = "default_resource")] 277 | resource: String, 278 | #[serde(default)] 279 | timeout: Timeout, 280 | #[serde(default = "Priority::lowest")] 281 | priority: Priority, 282 | } 283 | fn default_resource() -> String { 284 | "/".to_string() 285 | } 286 | #[derive(Deserialize, Debug, PartialEq)] 287 | struct Timeout(u32); 288 | impl Default for Timeout { 289 | fn default() -> Self { 290 | Timeout(30) 291 | } 292 | } 293 | #[derive(Deserialize, Debug, PartialEq)] 294 | enum Priority { 295 | ExtraHigh, 296 | High, 297 | Normal, 298 | Low, 299 | ExtraLow, 300 | } 301 | impl Priority { 302 | fn lowest() -> Self { 303 | Priority::ExtraLow 304 | } 305 | } 306 | 307 | let value: HashMap = HashMap::new(); 308 | 309 | let request: Request = serde_dynamodb::streams::from_hashmap(value).unwrap(); 310 | assert_eq!(request.resource, "/"); 311 | assert_eq!(request.timeout, Timeout(30)); 312 | assert_eq!(request.priority, Priority::ExtraLow); 313 | } 314 | 315 | #[test] 316 | fn can_serialize_bytes() { 317 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 318 | struct WithBytes { 319 | b: Vec, 320 | } 321 | 322 | test_with!( 323 | WithBytes, 324 | WithBytes { 325 | b: vec![2, 3, 5, 7, 11, 13, 17, 19, 23, 29], 326 | } 327 | ); 328 | } 329 | 330 | #[test] 331 | fn can_serialize_tuple() { 332 | test_with!((u32, String), (1, String::from("a"))); 333 | } 334 | 335 | #[test] 336 | fn can_serialize_tuple_in_struct() { 337 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 338 | struct WithTuple { 339 | t: (u32, String), 340 | } 341 | 342 | test_with!( 343 | WithTuple, 344 | WithTuple { 345 | t: (1, String::from("a")), 346 | } 347 | ); 348 | } 349 | 350 | #[test] 351 | fn can_serialize_tuple_struct() { 352 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 353 | struct Point(i32, i32, bool); 354 | 355 | test_with!(Point, Point(1, 2, false)); 356 | } 357 | 358 | #[test] 359 | fn can_serialize_hashmap() { 360 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 361 | struct WithHashmap { 362 | hm: HashMap, 363 | } 364 | 365 | let mut value = HashMap::new(); 366 | value.insert("a".to_string(), "hoho".to_string()); 367 | value.insert("b".to_string(), "haha".to_string()); 368 | 369 | test_with!(WithHashmap, WithHashmap { hm: value }); 370 | } 371 | 372 | #[test] 373 | fn can_serialize_enum() { 374 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 375 | enum MyEnum { 376 | Unit, 377 | Newtype(i32), 378 | Tuple(i32, bool), 379 | Struct { f: i32 }, 380 | } 381 | 382 | test_with!(MyEnum, MyEnum::Unit); 383 | test_with!(MyEnum, MyEnum::Newtype(5)); 384 | test_with!(MyEnum, MyEnum::Tuple(5, false)); 385 | test_with!(MyEnum, MyEnum::Struct { f: 7 }); 386 | } 387 | 388 | #[test] 389 | fn can_serialize_enum_in_struct() { 390 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 391 | enum MyEnum { 392 | Unit, 393 | Newtype(i32), 394 | Tuple(i32, bool), 395 | Struct { f: i32 }, 396 | } 397 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 398 | struct WithEnum { 399 | my_enum: MyEnum, 400 | } 401 | 402 | test_with!( 403 | WithEnum, 404 | WithEnum { 405 | my_enum: MyEnum::Unit 406 | } 407 | ); 408 | test_with!( 409 | WithEnum, 410 | WithEnum { 411 | my_enum: MyEnum::Newtype(5) 412 | } 413 | ); 414 | test_with!( 415 | WithEnum, 416 | WithEnum { 417 | my_enum: MyEnum::Tuple(5, false) 418 | } 419 | ); 420 | test_with!( 421 | WithEnum, 422 | WithEnum { 423 | my_enum: MyEnum::Struct { f: 7 } 424 | } 425 | ); 426 | } 427 | 428 | #[test] 429 | fn can_serialize_shortstyle_enum_in_struct() { 430 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 431 | enum MyEnum { 432 | Unit, 433 | Newtype(i32), 434 | Tuple(i32, bool), 435 | Struct { f: i32 }, 436 | } 437 | #[derive(Serialize, Deserialize, Debug, PartialEq)] 438 | struct WithEnum { 439 | my_enum: MyEnum, 440 | } 441 | 442 | let mut value: HashMap = HashMap::new(); 443 | value.insert( 444 | "my_enum".to_string(), 445 | AttributeValue { 446 | s: Some(String::from("Unit")), 447 | ..Default::default() 448 | }, 449 | ); 450 | 451 | let deserialized: std::result::Result = 452 | serde_dynamodb::streams::from_hashmap(value); 453 | assert!(dbg!(&deserialized).is_ok()); 454 | assert_eq!( 455 | WithEnum { 456 | my_enum: MyEnum::Unit 457 | }, 458 | deserialized.unwrap() 459 | ); 460 | } 461 | -------------------------------------------------------------------------------- /update_streams.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | set -ex 3 | 4 | echo "Cleanup previous version" 5 | rm -rf src/dynamodbstreams 6 | rm tests/dynamodbstreams.rs 7 | 8 | echo "Copy dynamodb implementation" 9 | cp -r src/dynamodb src/dynamodbstreams 10 | cp tests/dynamodb.rs tests/dynamodbstreams.rs 11 | 12 | echo "Update to use dynamodbstreams" 13 | sed -e 's/rusoto_dynamodb/rusoto_dynamodbstreams/g' -i '' src/dynamodbstreams/* 14 | sed -e 's/rusoto_dynamodb/rusoto_dynamodbstreams/g' -i '' tests/dynamodbstreams.rs 15 | sed -e 's/serde_dynamodb::from_hashmap/serde_dynamodb::streams::from_hashmap'/g -i '' tests/dynamodbstreams.rs 16 | sed -e 's/serde_dynamodb::to_hashmap/serde_dynamodb::streams::to_hashmap'/g -i '' tests/dynamodbstreams.rs 17 | 18 | echo "Put notice on top of generated files" 19 | for file in src/dynamodbstreams/* tests/dynamodbstreams.rs 20 | do 21 | tmpfile=$(mktemp /tmp/rusoto_dynamodb_update.XXXXXX) 22 | echo "// generated file, see update_streams.sh" > $tmpfile 23 | echo "" >> $tmpfile 24 | cat $file >> $tmpfile 25 | mv $tmpfile $file 26 | done 27 | --------------------------------------------------------------------------------