├── .gitignore ├── .vscode └── settings.json ├── CHANGELOG.md ├── Cargo.toml ├── LICENSE ├── README.md └── src ├── components.rs ├── components ├── command.rs ├── command │ └── length.rs ├── key_value.rs └── string.rs ├── de.rs ├── de ├── parse.rs └── result.rs ├── lib.rs ├── ser.rs └── ser ├── output.rs ├── primitives.rs └── util.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | 5 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 6 | # More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html 7 | Cargo.lock 8 | 9 | # These are backup files generated by rustfmt 10 | **/*.rs.bk 11 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "cSpell.words": [ 3 | "bufs", 4 | "EXAT", 5 | "HGETALL", 6 | "HMSET", 7 | "ilog", 8 | "KEEPTTL", 9 | "PXAT", 10 | "seredies", 11 | "zkey" 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## 1.0.1 4 | 5 | ### Internal 6 | 7 | - Serializing now tries to more proactively reserve space, especially when 8 | serializing arrays. 9 | 10 | ## 1.0.0 11 | 12 | - Initial version 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "seredies" 3 | version = "1.0.1" 4 | authors = ["Nathan West "] 5 | edition = "2021" 6 | 7 | description = "An implementation of the Redis Protocol as a serde (de)serializer" 8 | readme = "README.md" 9 | repository = "https://github.com/Lucretiel/seredies" 10 | license = "MPL-2.0" 11 | keywords = ["serde", "redis"] 12 | categories = ["encoding"] 13 | 14 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 15 | 16 | [dependencies] 17 | arrayvec = "0.7.2" 18 | lazy_format = "2.0.0" 19 | memchr = "2.5.0" 20 | paste = { version = "1.0.12", default-features = false } 21 | serde = { version = "1.0.118", default-features = false, features = ["std"] } 22 | serde_bytes = { version = "0.11.9", default-features = false } 23 | thiserror = "1.0.32" 24 | 25 | [dev-dependencies] 26 | serde = { version = "1.0.118", features = ["derive"], default-features = false } 27 | cool_asserts = "2.0.3" 28 | serde_test = "1.0.163" 29 | itertools = "0.10.3" 30 | tempfile = "3.5.0" 31 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # seredies 2 | Seredies is a Redis Protocol implementation for serde. 3 | -------------------------------------------------------------------------------- /src/components.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Helper components implementing common Redis and Rust patterns. 3 | */ 4 | 5 | mod command; 6 | mod key_value; 7 | mod string; 8 | 9 | pub use command::Command; 10 | pub use key_value::KeyValuePairs; 11 | pub use string::RedisString; 12 | -------------------------------------------------------------------------------- /src/components/command.rs: -------------------------------------------------------------------------------- 1 | mod length; 2 | 3 | use lazy_format::lazy_format; 4 | use serde::ser; 5 | use serde_bytes::Bytes; 6 | 7 | use crate::ser::util::TupleSeqAdapter; 8 | 9 | use super::RedisString; 10 | 11 | /** 12 | Adapter type for serializing redis commands. 13 | 14 | Redis commands are always delivered as a list of strings, regardless of the 15 | structure of the underlying command. This adapter type makes it easier to 16 | implement commands by serializing the underlying type as though it was a redis 17 | command. It uses the following rules & conventions: 18 | 19 | - The type should be a struct or enum. The name of the struct or name of 20 | the enum will be used as the command name. Tuples, lists, and maps cannot 21 | be commands. 22 | - All of the command arguments will be serialized as either strings or bytes 23 | objects (preferring strings). 24 | - The fields in the type will be serialized as arguments, using these rules: 25 | - Fields will be serialized in order, and the field names will be ignored. 26 | - Primitive types like strings and numbers will be serialized as strings. 27 | - Booleans are treated like flags, and will serialize the name of the 28 | field if true. 29 | - Options are treated like arguments. If the value is a primitive type, 30 | like a string or int, it will be serialized in a pair with its field 31 | name (if present); if it's a struct or enum type, the struct name or 32 | variant name will be used as the argument (see examples). 33 | - Enums will serialize the name of the enum, followed by its value (if 34 | present) 35 | - Lists will be flattened one level. Nested lists are an error. 36 | - Maps will be flattened to key-value sequences. Nested maps are an error. 37 | 38 | # Examples 39 | 40 | ## `SET` 41 | 42 | This example shows the Redis [`SET` command](https://redis.io/commands/set/). 43 | 44 | ``` 45 | use seredies::components::{RedisString, Command}; 46 | 47 | use serde::Serialize; 48 | use serde_test::{assert_ser_tokens, Token}; 49 | use serde_bytes::Bytes; 50 | 51 | /// The SET command. It includes a key and a value, as well as some optional 52 | /// behavior flags. Notice the use of `serde(rename)` to match the redis flag 53 | /// names. 54 | #[derive(Serialize)] 55 | #[serde(rename = "SET")] 56 | struct Set { 57 | // The key to set 58 | key: String, 59 | 60 | // The value to set. We use a RedisString to ensure that no matter what 61 | // type we use, it'll be correctly sent as a Redis string 62 | value: RedisString, 63 | 64 | // An optional enum will be serialized using just the variant name itself. 65 | skip: Option, 66 | 67 | // If true, a bool field is serialized as the field name itself 68 | #[serde(rename="GET")] 69 | get: bool, 70 | 71 | // An enum with a value will be serialized as a key-value pair, if present 72 | expiry: Option, 73 | } 74 | 75 | /// The `skip` parameter determines if the `SET` should be skipped 76 | #[derive(Serialize)] 77 | enum Skip { 78 | #[serde(rename="NX")] 79 | IfExists, 80 | 81 | #[serde(rename="XX")] 82 | IfAbsent, 83 | } 84 | 85 | /// The `expiry` parameter sets a time-to-live on the setting 86 | #[derive(Serialize)] 87 | enum Expiry { 88 | #[serde(rename = "EX")] 89 | Seconds(u64), 90 | 91 | #[serde(rename = "PX")] 92 | Millis(u64), 93 | 94 | #[serde(rename = "EXAT")] 95 | Timestamp(u64), 96 | 97 | #[serde(rename = "PXAT")] 98 | TimestampMillis(u64), 99 | 100 | #[serde(rename = "KEEPTTL")] 101 | Keep, 102 | } 103 | 104 | let command = Command(Set{ 105 | key: "my-key".to_owned(), 106 | value: RedisString(36), 107 | 108 | skip: None, 109 | expiry: None, 110 | get: false, 111 | }); 112 | 113 | // This will be serialized as a list of byte arrays, and can therefore be sent 114 | // to the seredies RESP serializer 115 | assert_ser_tokens(&command, &[ 116 | Token::Seq { len: Some(3) }, 117 | Token::Str("SET"), 118 | Token::Str("my-key"), 119 | Token::Str("36"), 120 | Token::SeqEnd, 121 | ]); 122 | 123 | // A more complex example. Notice that we can also send raw bytes data, 124 | // in addition to string data 125 | let command = Command(Set{ 126 | key: "my-key".to_owned(), 127 | value: RedisString(Bytes::new(b"123\xFF")), 128 | 129 | skip: Some(Skip::IfExists), 130 | expiry: Some(Expiry::Seconds(60)), 131 | get: true, 132 | }); 133 | 134 | assert_ser_tokens(&command, &[ 135 | Token::Seq{len: Some(7)}, 136 | Token::Str("SET"), 137 | Token::Str("my-key"), 138 | Token::Bytes(&[b'1', b'2', b'3', 255]), 139 | Token::Str("NX"), 140 | Token::Str("GET"), 141 | Token::Str("EX"), 142 | Token::Str("60"), 143 | Token::SeqEnd, 144 | ]); 145 | 146 | ``` 147 | 148 | ## `SCAN` 149 | 150 | This example shows the Redis [`SCAN` command](https://redis.io/commands/scan/). 151 | In particular it shows the behavior of optional primitive types and how they 152 | differ from optional enums. 153 | 154 | ``` 155 | use serde::Serialize; 156 | use seredies::components::Command; 157 | use serde_test::{assert_ser_tokens, Token}; 158 | 159 | #[derive(Serialize, Default)] 160 | #[serde(rename="SCAN")] 161 | struct Scan { 162 | cursor: u64, 163 | 164 | #[serde(rename="MATCH")] 165 | pattern: Option, 166 | 167 | #[serde(rename="COUNT")] 168 | count: Option, 169 | 170 | #[serde(rename="TYPE")] 171 | kind: Option, 172 | } 173 | 174 | let command = Command(Scan{ 175 | cursor: 0, 176 | ..Default::default() 177 | }); 178 | 179 | assert_ser_tokens(&command, &[ 180 | Token::Seq { len: Some(2) }, 181 | Token::Str("SCAN"), 182 | Token::Str("0"), 183 | Token::SeqEnd 184 | ]); 185 | 186 | let command = Command(Scan{ 187 | cursor: 10, 188 | count: Some(100), 189 | kind: Some("zkey".to_string()), 190 | pattern: None, 191 | }); 192 | 193 | assert_ser_tokens(&command, &[ 194 | Token::Seq { len: Some(6) }, 195 | Token::Str("SCAN"), 196 | Token::Str("10"), 197 | Token::Str("COUNT"), 198 | Token::Str("100"), 199 | Token::Str("TYPE"), 200 | Token::Str("zkey"), 201 | Token::SeqEnd 202 | ]); 203 | ``` 204 | */ 205 | #[derive(Debug, Copy, Clone, Default)] 206 | pub struct Command(pub T); 207 | 208 | impl From for Command 209 | where 210 | T: ser::Serialize, 211 | { 212 | fn from(cmd: T) -> Self { 213 | Self(cmd) 214 | } 215 | } 216 | 217 | impl ser::Serialize for Command 218 | where 219 | T: ser::Serialize, 220 | { 221 | fn serialize(&self, serializer: S) -> Result 222 | where 223 | S: serde::Serializer, 224 | { 225 | let length = self 226 | .0 227 | .serialize(CommandSerializer { 228 | serializer: length::Serializer, 229 | length: (), 230 | }) 231 | .map_err(|err| match err { 232 | length::Error::Custom(msg) => ser::Error::custom(msg), 233 | err => ser::Error::custom(err), 234 | })?; 235 | 236 | self.0.serialize(CommandSerializer { serializer, length }) 237 | } 238 | } 239 | 240 | fn invalid_command_type(kind: &str) -> Result { 241 | Err(ser::Error::custom(lazy_format!( 242 | "cannot serialize {kind} as a Redis command" 243 | ))) 244 | } 245 | 246 | trait MaybeLength: Copy { 247 | #[must_use] 248 | fn get(self) -> Option; 249 | } 250 | 251 | impl MaybeLength for () { 252 | #[inline(always)] 253 | #[must_use] 254 | fn get(self) -> Option { 255 | None 256 | } 257 | } 258 | 259 | impl MaybeLength for usize { 260 | #[inline(always)] 261 | #[must_use] 262 | fn get(self) -> Option { 263 | Some(self) 264 | } 265 | } 266 | 267 | struct CommandSerializer { 268 | serializer: S, 269 | length: L, 270 | } 271 | 272 | impl ser::Serializer for CommandSerializer 273 | where 274 | S: ser::Serializer, 275 | L: MaybeLength, 276 | { 277 | type Ok = S::Ok; 278 | type Error = S::Error; 279 | 280 | type SerializeSeq = ser::Impossible; 281 | type SerializeTuple = ser::Impossible; 282 | type SerializeMap = ser::Impossible; 283 | 284 | type SerializeStruct = CommandSequencer; 285 | type SerializeTupleStruct = TupleSeqAdapter>; 286 | type SerializeStructVariant = TupleSeqAdapter>; 287 | type SerializeTupleVariant = TupleSeqAdapter>; 288 | 289 | #[inline] 290 | fn serialize_bool(self, _v: bool) -> Result { 291 | invalid_command_type("a bool") 292 | } 293 | 294 | #[inline] 295 | fn serialize_i8(self, _v: i8) -> Result { 296 | invalid_command_type("an i8") 297 | } 298 | 299 | #[inline] 300 | fn serialize_i16(self, _v: i16) -> Result { 301 | invalid_command_type("an i16") 302 | } 303 | 304 | #[inline] 305 | fn serialize_i32(self, _v: i32) -> Result { 306 | invalid_command_type("an i32") 307 | } 308 | 309 | #[inline] 310 | fn serialize_i64(self, _v: i64) -> Result { 311 | invalid_command_type("an i64") 312 | } 313 | 314 | #[inline] 315 | fn serialize_i128(self, _v: i128) -> Result { 316 | invalid_command_type("an i128") 317 | } 318 | 319 | #[inline] 320 | fn serialize_u8(self, _v: u8) -> Result { 321 | invalid_command_type("a u8") 322 | } 323 | 324 | #[inline] 325 | fn serialize_u16(self, _v: u16) -> Result { 326 | invalid_command_type("a u16") 327 | } 328 | 329 | #[inline] 330 | fn serialize_u32(self, _v: u32) -> Result { 331 | invalid_command_type("a u32") 332 | } 333 | 334 | #[inline] 335 | fn serialize_u64(self, _v: u64) -> Result { 336 | invalid_command_type("a u64") 337 | } 338 | 339 | #[inline] 340 | fn serialize_u128(self, _v: u128) -> Result { 341 | invalid_command_type("a u128") 342 | } 343 | 344 | #[inline] 345 | fn serialize_f32(self, _v: f32) -> Result { 346 | invalid_command_type("an f32") 347 | } 348 | 349 | #[inline] 350 | fn serialize_f64(self, _v: f64) -> Result { 351 | invalid_command_type("an f64") 352 | } 353 | 354 | #[inline] 355 | fn serialize_char(self, _v: char) -> Result { 356 | invalid_command_type("a character") 357 | } 358 | 359 | #[inline] 360 | fn serialize_str(self, _v: &str) -> Result { 361 | invalid_command_type("a string") 362 | } 363 | 364 | #[inline] 365 | fn serialize_bytes(self, _v: &[u8]) -> Result { 366 | invalid_command_type("a bytes") 367 | } 368 | 369 | #[inline] 370 | fn serialize_none(self) -> Result { 371 | invalid_command_type("an option") 372 | } 373 | 374 | #[inline] 375 | fn serialize_some(self, _value: &T) -> Result 376 | where 377 | T: serde::Serialize, 378 | { 379 | invalid_command_type("an option") 380 | } 381 | 382 | #[inline] 383 | fn serialize_unit(self) -> Result { 384 | invalid_command_type("a unit") 385 | } 386 | 387 | #[inline] 388 | fn serialize_unit_struct(self, name: &'static str) -> Result { 389 | use ser::SerializeStruct as _; 390 | 391 | self.serialize_struct(name, 0)?.end() 392 | } 393 | 394 | #[inline] 395 | fn serialize_unit_variant( 396 | self, 397 | _name: &'static str, 398 | _variant_index: u32, 399 | variant: &'static str, 400 | ) -> Result { 401 | self.serialize_unit_struct(variant) 402 | } 403 | 404 | #[inline] 405 | fn serialize_newtype_struct( 406 | self, 407 | name: &'static str, 408 | value: &T, 409 | ) -> Result 410 | where 411 | T: serde::Serialize, 412 | { 413 | use ser::SerializeTupleStruct as _; 414 | 415 | let mut receiver = self.serialize_tuple_struct(name, 1)?; 416 | receiver.serialize_field(value)?; 417 | receiver.end() 418 | } 419 | 420 | #[inline] 421 | fn serialize_newtype_variant( 422 | self, 423 | _name: &'static str, 424 | _variant_index: u32, 425 | variant: &'static str, 426 | value: &T, 427 | ) -> Result 428 | where 429 | T: serde::Serialize, 430 | { 431 | self.serialize_newtype_struct(variant, value) 432 | } 433 | 434 | #[inline] 435 | fn serialize_seq(self, _len: Option) -> Result { 436 | invalid_command_type("a sequence") 437 | } 438 | 439 | #[inline] 440 | fn serialize_tuple(self, len: usize) -> Result { 441 | self.serialize_seq(Some(len)) 442 | } 443 | 444 | #[inline] 445 | fn serialize_tuple_struct( 446 | self, 447 | name: &'static str, 448 | _len: usize, 449 | ) -> Result { 450 | use ser::SerializeSeq as _; 451 | 452 | let mut sequence = self.serializer.serialize_seq(self.length.get())?; 453 | sequence.serialize_element(RedisString::new_ref(name))?; 454 | Ok(TupleSeqAdapter::new(CommandSequencer { sequence })) 455 | } 456 | 457 | #[inline] 458 | fn serialize_tuple_variant( 459 | self, 460 | _name: &'static str, 461 | _variant_index: u32, 462 | variant: &'static str, 463 | len: usize, 464 | ) -> Result { 465 | self.serialize_tuple_struct(variant, len) 466 | } 467 | 468 | #[inline] 469 | fn serialize_map(self, _len: Option) -> Result { 470 | invalid_command_type("a map") 471 | } 472 | 473 | #[inline] 474 | fn serialize_struct( 475 | self, 476 | name: &'static str, 477 | _len: usize, 478 | ) -> Result { 479 | use ser::SerializeSeq as _; 480 | 481 | let mut sequence = self.serializer.serialize_seq(self.length.get())?; 482 | sequence.serialize_element(RedisString::new_ref(name))?; 483 | Ok(CommandSequencer { sequence }) 484 | } 485 | 486 | #[inline] 487 | fn serialize_struct_variant( 488 | self, 489 | _name: &'static str, 490 | _variant_index: u32, 491 | variant: &'static str, 492 | len: usize, 493 | ) -> Result { 494 | self.serialize_struct(variant, len) 495 | .map(TupleSeqAdapter::new) 496 | } 497 | } 498 | 499 | /// This type implements SerializeSeq, SerializeStruct, etc. It's used to 500 | /// sequence the set of arguments passed to a command. This object is created 501 | /// *after* the command name itself is serialized. 502 | struct CommandSequencer { 503 | sequence: S, 504 | } 505 | 506 | impl ser::SerializeSeq for CommandSequencer 507 | where 508 | S: ser::SerializeSeq, 509 | { 510 | type Ok = S::Ok; 511 | type Error = S::Error; 512 | 513 | #[inline] 514 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> 515 | where 516 | T: serde::Serialize, 517 | { 518 | value.serialize(AnonymousParameterSerializer::new(&mut self.sequence)) 519 | } 520 | 521 | #[inline] 522 | fn end(self) -> Result { 523 | self.sequence.end() 524 | } 525 | } 526 | 527 | impl ser::SerializeStruct for CommandSequencer 528 | where 529 | S: ser::SerializeSeq, 530 | { 531 | type Ok = S::Ok; 532 | type Error = S::Error; 533 | 534 | #[inline] 535 | fn serialize_field( 536 | &mut self, 537 | key: &'static str, 538 | value: &T, 539 | ) -> Result<(), Self::Error> 540 | where 541 | T: serde::Serialize, 542 | { 543 | value.serialize(NamedParameterSerializer::new(key, &mut self.sequence)) 544 | } 545 | 546 | #[inline] 547 | fn end(self) -> Result { 548 | self.sequence.end() 549 | } 550 | } 551 | 552 | trait ParameterName: Copy { 553 | #[must_use] 554 | fn get(self) -> Option<&'static str>; 555 | } 556 | 557 | impl ParameterName for () { 558 | #[inline(always)] 559 | #[must_use] 560 | fn get(self) -> Option<&'static str> { 561 | None 562 | } 563 | } 564 | 565 | impl ParameterName for &'static str { 566 | #[inline(always)] 567 | #[must_use] 568 | fn get(self) -> Option<&'static str> { 569 | Some(self) 570 | } 571 | } 572 | 573 | /// This serializer handles a single parameter. It especially handles all the 574 | /// logic for variadic parameters (as in a list of keys for MGET), optional 575 | /// parameters, etc. 576 | struct CommandParameterSerializer<'a, S, N: ParameterName> { 577 | sequence: &'a mut S, 578 | name: N, 579 | } 580 | 581 | type AnonymousParameterSerializer<'a, S> = CommandParameterSerializer<'a, S, ()>; 582 | type NamedParameterSerializer<'a, S> = CommandParameterSerializer<'a, S, &'static str>; 583 | 584 | impl<'a, S: ser::SerializeSeq> AnonymousParameterSerializer<'a, S> { 585 | #[inline] 586 | #[must_use] 587 | pub fn new(sequence: &'a mut S) -> Self { 588 | Self { sequence, name: () } 589 | } 590 | } 591 | 592 | impl<'a, S: ser::SerializeSeq> NamedParameterSerializer<'a, S> { 593 | #[inline] 594 | #[must_use] 595 | pub fn new(name: &'static str, sequence: &'a mut S) -> Self { 596 | Self { sequence, name } 597 | } 598 | } 599 | 600 | impl<'a, S, N> CommandParameterSerializer<'a, S, N> 601 | where 602 | N: ParameterName, 603 | { 604 | #[inline] 605 | fn name(&self) -> Result<&'static str, E> { 606 | self.name.get().ok_or_else(|| { 607 | ser::Error::custom( 608 | "can't serialize a bool, optional parameter, \ 609 | or unit from a tuple struct", 610 | ) 611 | }) 612 | } 613 | } 614 | 615 | impl<'a, S, N> ser::Serializer for CommandParameterSerializer<'a, S, N> 616 | where 617 | S: ser::SerializeSeq, 618 | N: ParameterName, 619 | { 620 | type Ok = (); 621 | type Error = S::Error; 622 | 623 | type SerializeSeq = VariadicParameter<'a, S>; 624 | type SerializeTuple = TupleSeqAdapter>; 625 | type SerializeTupleStruct = TupleSeqAdapter>; 626 | 627 | type SerializeMap = VariadicParameter<'a, S>; 628 | type SerializeStruct = VariadicParameter<'a, S>; 629 | 630 | type SerializeTupleVariant = ser::Impossible<(), Self::Error>; 631 | type SerializeStructVariant = ser::Impossible<(), Self::Error>; 632 | 633 | #[inline] 634 | fn serialize_bool(self, v: bool) -> Result { 635 | // Even if `v` is false, we want to disallow serializing a bool parameter 636 | // without a name, so compute it eagerly 637 | let name = self.name()?; 638 | 639 | match v { 640 | true => self.sequence.serialize_element(RedisString::new_ref(name)), 641 | false => Ok(()), 642 | } 643 | } 644 | 645 | #[inline] 646 | fn serialize_i8(self, v: i8) -> Result { 647 | self.sequence.serialize_element(&RedisString(v)) 648 | } 649 | 650 | #[inline] 651 | fn serialize_i16(self, v: i16) -> Result { 652 | self.sequence.serialize_element(&RedisString(v)) 653 | } 654 | 655 | #[inline] 656 | fn serialize_i32(self, v: i32) -> Result { 657 | self.sequence.serialize_element(&RedisString(v)) 658 | } 659 | 660 | #[inline] 661 | fn serialize_i64(self, v: i64) -> Result { 662 | self.sequence.serialize_element(&RedisString(v)) 663 | } 664 | 665 | #[inline] 666 | fn serialize_i128(self, v: i128) -> Result { 667 | self.sequence.serialize_element(&RedisString(v)) 668 | } 669 | 670 | #[inline] 671 | fn serialize_u8(self, v: u8) -> Result { 672 | self.sequence.serialize_element(&RedisString(v)) 673 | } 674 | 675 | #[inline] 676 | fn serialize_u16(self, v: u16) -> Result { 677 | self.sequence.serialize_element(&RedisString(v)) 678 | } 679 | 680 | #[inline] 681 | fn serialize_u32(self, v: u32) -> Result { 682 | self.sequence.serialize_element(&RedisString(v)) 683 | } 684 | 685 | #[inline] 686 | fn serialize_u64(self, v: u64) -> Result { 687 | self.sequence.serialize_element(&RedisString(v)) 688 | } 689 | 690 | #[inline] 691 | fn serialize_u128(self, v: u128) -> Result { 692 | self.sequence.serialize_element(&RedisString(v)) 693 | } 694 | 695 | #[inline] 696 | fn serialize_f32(self, v: f32) -> Result { 697 | self.sequence.serialize_element(&RedisString(v)) 698 | } 699 | 700 | #[inline] 701 | fn serialize_f64(self, v: f64) -> Result { 702 | self.sequence.serialize_element(&RedisString(v)) 703 | } 704 | 705 | #[inline] 706 | fn serialize_char(self, v: char) -> Result { 707 | let mut buf = [0; 4]; 708 | self.serialize_str(v.encode_utf8(&mut buf)) 709 | } 710 | 711 | #[inline] 712 | fn serialize_str(self, v: &str) -> Result { 713 | self.sequence.serialize_element(RedisString::new_ref(v)) 714 | } 715 | 716 | #[inline] 717 | fn serialize_bytes(self, v: &[u8]) -> Result { 718 | self.sequence.serialize_element(Bytes::new(v)) 719 | } 720 | 721 | #[inline] 722 | fn serialize_none(self) -> Result { 723 | Ok(()) 724 | } 725 | 726 | #[inline] 727 | fn serialize_some(self, value: &T) -> Result 728 | where 729 | T: serde::Serialize, 730 | { 731 | value.serialize(OptionalParameterSerializer { 732 | name: self.name, 733 | sequence: self.sequence, 734 | }) 735 | } 736 | 737 | #[inline] 738 | fn serialize_unit(self) -> Result { 739 | let name = self.name()?; 740 | self.serialize_unit_struct(name) 741 | } 742 | 743 | #[inline] 744 | fn serialize_unit_struct(self, name: &'static str) -> Result { 745 | self.serialize_str(name) 746 | } 747 | 748 | #[inline] 749 | fn serialize_unit_variant( 750 | self, 751 | _name: &'static str, 752 | _variant_index: u32, 753 | variant: &'static str, 754 | ) -> Result { 755 | self.serialize_unit_struct(variant) 756 | } 757 | 758 | #[inline] 759 | fn serialize_newtype_struct( 760 | self, 761 | _name: &'static str, 762 | value: &T, 763 | ) -> Result 764 | where 765 | T: serde::Serialize, 766 | { 767 | value.serialize(self) 768 | } 769 | 770 | #[inline] 771 | fn serialize_newtype_variant( 772 | self, 773 | _name: &'static str, 774 | _variant_index: u32, 775 | variant: &'static str, 776 | value: &T, 777 | ) -> Result 778 | where 779 | T: serde::Serialize, 780 | { 781 | self.sequence 782 | .serialize_element(RedisString::new_ref(variant))?; 783 | self.sequence.serialize_element(RedisString::new_ref(value)) 784 | } 785 | 786 | #[inline] 787 | fn serialize_seq(self, _len: Option) -> Result { 788 | Ok(VariadicParameter { 789 | sequence: self.sequence, 790 | }) 791 | } 792 | 793 | #[inline] 794 | fn serialize_tuple(self, len: usize) -> Result { 795 | self.serialize_seq(Some(len)).map(TupleSeqAdapter::new) 796 | } 797 | 798 | #[inline] 799 | fn serialize_tuple_struct( 800 | self, 801 | _name: &'static str, 802 | len: usize, 803 | ) -> Result { 804 | self.serialize_tuple(len) 805 | } 806 | 807 | #[inline] 808 | fn serialize_tuple_variant( 809 | self, 810 | _name: &'static str, 811 | _variant_index: u32, 812 | _variant: &'static str, 813 | _len: usize, 814 | ) -> Result { 815 | Err(ser::Error::custom( 816 | "can't serialize complex enums as Redis command parameters", 817 | )) 818 | } 819 | 820 | #[inline] 821 | fn serialize_map(self, _len: Option) -> Result { 822 | Ok(VariadicParameter { 823 | sequence: self.sequence, 824 | }) 825 | } 826 | 827 | #[inline] 828 | fn serialize_struct( 829 | self, 830 | _name: &'static str, 831 | _len: usize, 832 | ) -> Result { 833 | Ok(VariadicParameter { 834 | sequence: self.sequence, 835 | }) 836 | } 837 | 838 | #[inline] 839 | fn serialize_struct_variant( 840 | self, 841 | _name: &'static str, 842 | _variant_index: u32, 843 | _variant: &'static str, 844 | _len: usize, 845 | ) -> Result { 846 | Err(ser::Error::custom( 847 | "can't serialize complex enums as Redis command parameters", 848 | )) 849 | } 850 | } 851 | 852 | struct VariadicParameter<'a, S> { 853 | sequence: &'a mut S, 854 | } 855 | 856 | impl<'a, S> ser::SerializeSeq for VariadicParameter<'a, S> 857 | where 858 | S: ser::SerializeSeq, 859 | { 860 | type Ok = (); 861 | type Error = S::Error; 862 | 863 | #[inline] 864 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> 865 | where 866 | T: serde::Serialize, 867 | { 868 | self.sequence.serialize_element(RedisString::new_ref(value)) 869 | } 870 | 871 | #[inline] 872 | fn end(self) -> Result { 873 | Ok(()) 874 | } 875 | } 876 | 877 | impl<'a, S: ser::SerializeSeq> ser::SerializeMap for VariadicParameter<'a, S> { 878 | type Ok = (); 879 | type Error = S::Error; 880 | 881 | #[inline] 882 | fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> 883 | where 884 | T: serde::Serialize, 885 | { 886 | self.sequence.serialize_element(RedisString::new_ref(key)) 887 | } 888 | 889 | #[inline] 890 | fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> 891 | where 892 | T: serde::Serialize, 893 | { 894 | self.sequence.serialize_element(RedisString::new_ref(value)) 895 | } 896 | 897 | #[inline] 898 | fn end(self) -> Result { 899 | Ok(()) 900 | } 901 | } 902 | 903 | impl<'a, S> ser::SerializeStruct for VariadicParameter<'a, S> 904 | where 905 | S: ser::SerializeSeq, 906 | { 907 | type Ok = (); 908 | type Error = S::Error; 909 | 910 | #[inline] 911 | fn serialize_field( 912 | &mut self, 913 | key: &'static str, 914 | value: &T, 915 | ) -> Result<(), Self::Error> 916 | where 917 | T: serde::Serialize, 918 | { 919 | self.sequence.serialize_element(RedisString::new_ref(key))?; 920 | self.sequence.serialize_element(RedisString::new_ref(value)) 921 | } 922 | 923 | #[inline] 924 | fn end(self) -> Result { 925 | Ok(()) 926 | } 927 | } 928 | 929 | /// Serializer for an optional parameter that is Some. Optional parameters 930 | /// always need to have a name associated with them, but in some cases the 931 | /// name is part of the type, rather than part of the containing struct. 932 | /// additionally, optionals can't contain variadic data; otherwise we'd probably 933 | /// just reuse CommandParameterSerializer. We do 934 | struct OptionalParameterSerializer<'a, S, N: ParameterName> { 935 | sequence: &'a mut S, 936 | name: N, 937 | } 938 | 939 | impl<'a, N: ParameterName, S> OptionalParameterSerializer<'a, S, N> { 940 | #[inline] 941 | fn name(&self) -> Result<&'static str, E> { 942 | self.name.get().ok_or_else(|| { 943 | ser::Error::custom( 944 | "can't serialize an optional primitive value \ 945 | in a tuple struct command; it needs a name", 946 | ) 947 | }) 948 | } 949 | } 950 | 951 | impl<'a, S: ser::SerializeSeq, N: ParameterName> OptionalParameterSerializer<'a, S, N> { 952 | #[inline] 953 | fn serialize_anonymous_value( 954 | self, 955 | value: &T, 956 | ) -> Result<(), S::Error> { 957 | let name = self.name()?; 958 | self.serialize_named_value(name, value) 959 | } 960 | 961 | #[inline] 962 | fn serialize_named_value( 963 | self, 964 | name: &str, 965 | value: &T, 966 | ) -> Result<(), S::Error> { 967 | self.sequence 968 | .serialize_element(RedisString::new_ref(name))?; 969 | self.sequence.serialize_element(RedisString::new_ref(value)) 970 | } 971 | 972 | #[inline] 973 | fn serialize_just_anonymous(self) -> Result<(), S::Error> { 974 | let name = self.name()?; 975 | self.serialize_just_name(name) 976 | } 977 | 978 | #[inline] 979 | fn serialize_just_name(self, name: &str) -> Result<(), S::Error> { 980 | self.sequence.serialize_element(RedisString::new_ref(name)) 981 | } 982 | } 983 | 984 | impl<'a, S: ser::SerializeSeq, N: ParameterName> ser::Serializer 985 | for OptionalParameterSerializer<'a, S, N> 986 | { 987 | type Ok = (); 988 | type Error = S::Error; 989 | 990 | type SerializeSeq = ser::Impossible<(), S::Error>; 991 | type SerializeTuple = ser::Impossible<(), S::Error>; 992 | type SerializeTupleStruct = ser::Impossible<(), S::Error>; 993 | type SerializeTupleVariant = ser::Impossible<(), S::Error>; 994 | type SerializeMap = ser::Impossible<(), S::Error>; 995 | type SerializeStruct = ser::Impossible<(), S::Error>; 996 | type SerializeStructVariant = ser::Impossible<(), S::Error>; 997 | 998 | #[inline] 999 | fn serialize_bool(self, _v: bool) -> Result { 1000 | Err(ser::Error::custom("can't serialize an Option")) 1001 | } 1002 | 1003 | #[inline] 1004 | fn serialize_i8(self, v: i8) -> Result { 1005 | self.serialize_anonymous_value(&v) 1006 | } 1007 | 1008 | #[inline] 1009 | fn serialize_i16(self, v: i16) -> Result { 1010 | self.serialize_anonymous_value(&v) 1011 | } 1012 | 1013 | #[inline] 1014 | fn serialize_i32(self, v: i32) -> Result { 1015 | self.serialize_anonymous_value(&v) 1016 | } 1017 | 1018 | #[inline] 1019 | fn serialize_i64(self, v: i64) -> Result { 1020 | self.serialize_anonymous_value(&v) 1021 | } 1022 | 1023 | #[inline] 1024 | fn serialize_i128(self, v: i128) -> Result { 1025 | self.serialize_anonymous_value(&v) 1026 | } 1027 | 1028 | #[inline] 1029 | fn serialize_u8(self, v: u8) -> Result { 1030 | self.serialize_anonymous_value(&v) 1031 | } 1032 | 1033 | #[inline] 1034 | fn serialize_u16(self, v: u16) -> Result { 1035 | self.serialize_anonymous_value(&v) 1036 | } 1037 | 1038 | #[inline] 1039 | fn serialize_u32(self, v: u32) -> Result { 1040 | self.serialize_anonymous_value(&v) 1041 | } 1042 | 1043 | #[inline] 1044 | fn serialize_u64(self, v: u64) -> Result { 1045 | self.serialize_anonymous_value(&v) 1046 | } 1047 | 1048 | #[inline] 1049 | fn serialize_u128(self, v: u128) -> Result { 1050 | self.serialize_anonymous_value(&v) 1051 | } 1052 | 1053 | #[inline] 1054 | fn serialize_f32(self, v: f32) -> Result { 1055 | self.serialize_anonymous_value(&v) 1056 | } 1057 | 1058 | #[inline] 1059 | fn serialize_f64(self, v: f64) -> Result { 1060 | self.serialize_anonymous_value(&v) 1061 | } 1062 | 1063 | #[inline] 1064 | fn serialize_char(self, v: char) -> Result { 1065 | self.serialize_anonymous_value(&v) 1066 | } 1067 | 1068 | #[inline] 1069 | fn serialize_str(self, v: &str) -> Result { 1070 | self.serialize_anonymous_value(v) 1071 | } 1072 | 1073 | #[inline] 1074 | fn serialize_bytes(self, v: &[u8]) -> Result { 1075 | self.serialize_anonymous_value(Bytes::new(v)) 1076 | } 1077 | 1078 | #[inline] 1079 | fn serialize_none(self) -> Result { 1080 | self.serialize_just_anonymous() 1081 | } 1082 | 1083 | #[inline] 1084 | fn serialize_some(self, value: &T) -> Result 1085 | where 1086 | T: serde::Serialize, 1087 | { 1088 | self.serialize_anonymous_value(value) 1089 | } 1090 | 1091 | #[inline] 1092 | fn serialize_unit(self) -> Result { 1093 | self.serialize_just_anonymous() 1094 | } 1095 | 1096 | #[inline] 1097 | fn serialize_unit_struct(self, name: &'static str) -> Result { 1098 | self.serialize_just_name(name) 1099 | } 1100 | 1101 | #[inline] 1102 | fn serialize_unit_variant( 1103 | self, 1104 | _name: &'static str, 1105 | _variant_index: u32, 1106 | variant: &'static str, 1107 | ) -> Result { 1108 | self.serialize_just_name(variant) 1109 | } 1110 | 1111 | #[inline] 1112 | fn serialize_newtype_struct( 1113 | self, 1114 | name: &'static str, 1115 | value: &T, 1116 | ) -> Result 1117 | where 1118 | T: serde::Serialize, 1119 | { 1120 | self.serialize_named_value(name, value) 1121 | } 1122 | 1123 | #[inline] 1124 | fn serialize_newtype_variant( 1125 | self, 1126 | _name: &'static str, 1127 | _variant_index: u32, 1128 | variant: &'static str, 1129 | value: &T, 1130 | ) -> Result 1131 | where 1132 | T: serde::Serialize, 1133 | { 1134 | self.serialize_named_value(variant, value) 1135 | } 1136 | 1137 | #[inline] 1138 | fn serialize_seq(self, _len: Option) -> Result { 1139 | Err(ser::Error::custom("can't serialize optional sequences")) 1140 | } 1141 | 1142 | #[inline] 1143 | fn serialize_tuple(self, _len: usize) -> Result { 1144 | Err(ser::Error::custom("can't serialize optional tuples")) 1145 | } 1146 | 1147 | #[inline] 1148 | fn serialize_tuple_struct( 1149 | self, 1150 | _name: &'static str, 1151 | _len: usize, 1152 | ) -> Result { 1153 | Err(ser::Error::custom( 1154 | "can't serialize optional complex structs", 1155 | )) 1156 | } 1157 | 1158 | #[inline] 1159 | fn serialize_tuple_variant( 1160 | self, 1161 | _name: &'static str, 1162 | _variant_index: u32, 1163 | _variant: &'static str, 1164 | _len: usize, 1165 | ) -> Result { 1166 | Err(ser::Error::custom("can't serialize optional complex enums")) 1167 | } 1168 | 1169 | #[inline] 1170 | fn serialize_map(self, _len: Option) -> Result { 1171 | Err(ser::Error::custom("can't serialize optional maps")) 1172 | } 1173 | 1174 | #[inline] 1175 | fn serialize_struct( 1176 | self, 1177 | _name: &'static str, 1178 | _len: usize, 1179 | ) -> Result { 1180 | Err(ser::Error::custom("can't serialize optional structs")) 1181 | } 1182 | 1183 | #[inline] 1184 | fn serialize_struct_variant( 1185 | self, 1186 | _name: &'static str, 1187 | _variant_index: u32, 1188 | _variant: &'static str, 1189 | _len: usize, 1190 | ) -> Result { 1191 | Err(ser::Error::custom("can't serialize optional complex enums")) 1192 | } 1193 | } 1194 | 1195 | #[cfg(test)] 1196 | mod tests { 1197 | use std::collections::BTreeMap; 1198 | 1199 | use super::*; 1200 | 1201 | use serde::Serialize; 1202 | use serde_test::{assert_ser_tokens, assert_ser_tokens_error, Token}; 1203 | 1204 | #[derive(Serialize)] 1205 | #[allow(dead_code)] 1206 | enum Skip { 1207 | NX, 1208 | XX, 1209 | } 1210 | 1211 | #[derive(Serialize)] 1212 | #[allow(dead_code)] 1213 | enum Expiry { 1214 | #[serde(rename = "EX")] 1215 | Seconds(u64), 1216 | 1217 | #[serde(rename = "PX")] 1218 | Millis(u64), 1219 | 1220 | #[serde(rename = "EXAT")] 1221 | Timestamp(u64), 1222 | 1223 | #[serde(rename = "PXAT")] 1224 | TimestampMillis(u64), 1225 | 1226 | #[serde(rename = "KEEPTTL")] 1227 | Keep, 1228 | } 1229 | 1230 | #[derive(Serialize)] 1231 | #[serde(rename = "SET")] 1232 | struct Set { 1233 | key: String, 1234 | value: RedisString, 1235 | /// If true, return the old value of the key after the SET 1236 | #[serde(rename = "GET")] 1237 | get: bool, 1238 | skip: Option, 1239 | expiry: Option, 1240 | } 1241 | 1242 | #[test] 1243 | fn test_basic_set() { 1244 | let command = Command(Set { 1245 | key: "my-key".to_owned(), 1246 | value: RedisString(36), 1247 | get: false, 1248 | skip: None, 1249 | expiry: None, 1250 | }); 1251 | 1252 | assert_ser_tokens( 1253 | &command, 1254 | &[ 1255 | Token::Seq { len: Some(3) }, 1256 | Token::Str("SET"), 1257 | Token::Str("my-key"), 1258 | Token::Str("36"), 1259 | Token::SeqEnd, 1260 | ], 1261 | ); 1262 | } 1263 | 1264 | #[test] 1265 | fn test_set_params() { 1266 | let command = Command(Set { 1267 | key: "my-key".to_owned(), 1268 | value: RedisString(-10), 1269 | get: true, 1270 | skip: Some(Skip::XX), 1271 | expiry: Some(Expiry::Seconds(60)), 1272 | }); 1273 | 1274 | assert_ser_tokens( 1275 | &command, 1276 | &[ 1277 | Token::Seq { len: Some(7) }, 1278 | Token::Str("SET"), 1279 | Token::Str("my-key"), 1280 | Token::Str("-10"), 1281 | Token::Str("GET"), 1282 | Token::Str("XX"), 1283 | Token::Str("EX"), 1284 | Token::Str("60"), 1285 | Token::SeqEnd, 1286 | ], 1287 | ) 1288 | } 1289 | 1290 | #[test] 1291 | fn test_raw_bytes() { 1292 | let command = Command(Set { 1293 | key: "bytes-key".to_owned(), 1294 | value: RedisString(Bytes::new(b"\0abc\xFF")), 1295 | get: false, 1296 | skip: None, 1297 | expiry: None, 1298 | }); 1299 | 1300 | assert_ser_tokens( 1301 | &command, 1302 | &[ 1303 | Token::Seq { len: Some(3) }, 1304 | Token::Str("SET"), 1305 | Token::Str("bytes-key"), 1306 | Token::Bytes(&[0, b'a', b'b', b'c', 255]), 1307 | Token::SeqEnd, 1308 | ], 1309 | ) 1310 | } 1311 | 1312 | #[derive(Serialize)] 1313 | #[serde(rename = "HMSET")] 1314 | struct HashMultiSet { 1315 | key: &'static str, 1316 | values: BTreeMap<&'static str, &'static str>, 1317 | } 1318 | 1319 | #[test] 1320 | fn test_variadic() { 1321 | let command = Command(HashMultiSet { 1322 | key: "hash-key", 1323 | values: BTreeMap::from([ 1324 | ("key1", "value1"), 1325 | ("key2", "value2"), 1326 | ("key3", "value3"), 1327 | ("key4", "value4"), 1328 | ]), 1329 | }); 1330 | 1331 | assert_ser_tokens( 1332 | &command, 1333 | &[ 1334 | Token::Seq { len: Some(10) }, 1335 | Token::Str("HMSET"), 1336 | Token::Str("hash-key"), 1337 | Token::Str("key1"), 1338 | Token::Str("value1"), 1339 | Token::Str("key2"), 1340 | Token::Str("value2"), 1341 | Token::Str("key3"), 1342 | Token::Str("value3"), 1343 | Token::Str("key4"), 1344 | Token::Str("value4"), 1345 | Token::SeqEnd, 1346 | ], 1347 | ) 1348 | } 1349 | 1350 | #[derive(Serialize)] 1351 | struct Fake { 1352 | data: Vec>, 1353 | } 1354 | 1355 | #[test] 1356 | fn disallow_nested_lists() { 1357 | let command = Command(Fake { 1358 | data: Vec::from([Vec::from([1, 2, 3]), Vec::from([4, 5, 6])]), 1359 | }); 1360 | 1361 | assert_ser_tokens_error(&command, &[], "can't serialize lists as redis strings"); 1362 | } 1363 | } 1364 | -------------------------------------------------------------------------------- /src/components/command/length.rs: -------------------------------------------------------------------------------- 1 | use serde::{ser, Serialize}; 2 | use thiserror::Error; 3 | 4 | use crate::ser::util::TupleSeqAdapter; 5 | 6 | #[derive(Debug, Clone, Error)] 7 | pub enum Error { 8 | #[error("overflowed a usize")] 9 | Overflow, 10 | 11 | #[error("tried to serialize {0} into a redis command; only sequences and bytes are allowed")] 12 | InvalidType(&'static str), 13 | 14 | #[error("error from serialized type: {0}")] 15 | Custom(String), 16 | } 17 | 18 | impl ser::Error for Error { 19 | fn custom(msg: T) -> Self 20 | where 21 | T: std::fmt::Display, 22 | { 23 | Self::Custom(msg.to_string()) 24 | } 25 | } 26 | 27 | /// Helper serializer that allows us to pre-compute the length of a command. 28 | /// 29 | /// Redis arrays must know the length ahead of time in order to serialize; 30 | /// this serializer can be used with a CommandSerializer to compute this 31 | /// length. 32 | pub struct Serializer; 33 | 34 | impl ser::Serializer for Serializer { 35 | type Ok = usize; 36 | type Error = Error; 37 | 38 | type SerializeSeq = Accumulator; 39 | type SerializeTuple = TupleSeqAdapter; 40 | 41 | type SerializeTupleStruct = ser::Impossible; 42 | type SerializeTupleVariant = ser::Impossible; 43 | type SerializeMap = ser::Impossible; 44 | type SerializeStruct = ser::Impossible; 45 | type SerializeStructVariant = ser::Impossible; 46 | 47 | #[inline] 48 | fn serialize_bool(self, _v: bool) -> Result { 49 | Err(Error::InvalidType("a bool")) 50 | } 51 | 52 | #[inline] 53 | fn serialize_i8(self, _v: i8) -> Result { 54 | Err(Error::InvalidType("an i8")) 55 | } 56 | 57 | #[inline] 58 | fn serialize_i16(self, _v: i16) -> Result { 59 | Err(Error::InvalidType("an i16")) 60 | } 61 | 62 | #[inline] 63 | fn serialize_i32(self, _v: i32) -> Result { 64 | Err(Error::InvalidType("an i32")) 65 | } 66 | 67 | #[inline] 68 | fn serialize_i64(self, _v: i64) -> Result { 69 | Err(Error::InvalidType("an i64")) 70 | } 71 | 72 | #[inline] 73 | fn serialize_i128(self, _v: i128) -> Result { 74 | Err(Error::InvalidType("an i128")) 75 | } 76 | 77 | #[inline] 78 | fn serialize_u8(self, _v: u8) -> Result { 79 | Err(Error::InvalidType("a u8")) 80 | } 81 | 82 | #[inline] 83 | fn serialize_u16(self, _v: u16) -> Result { 84 | Err(Error::InvalidType("a u16")) 85 | } 86 | 87 | #[inline] 88 | fn serialize_u32(self, _v: u32) -> Result { 89 | Err(Error::InvalidType("a u32")) 90 | } 91 | 92 | #[inline] 93 | fn serialize_u64(self, _v: u64) -> Result { 94 | Err(Error::InvalidType("a u64")) 95 | } 96 | 97 | #[inline] 98 | fn serialize_u128(self, _v: u128) -> Result { 99 | Err(Error::InvalidType("a u128")) 100 | } 101 | 102 | #[inline] 103 | fn serialize_f32(self, _v: f32) -> Result { 104 | Err(Error::InvalidType("an f32")) 105 | } 106 | 107 | #[inline] 108 | fn serialize_f64(self, _v: f64) -> Result { 109 | Err(Error::InvalidType("an f64")) 110 | } 111 | 112 | #[inline] 113 | fn serialize_char(self, _v: char) -> Result { 114 | Ok(1) 115 | } 116 | 117 | #[inline] 118 | fn serialize_str(self, _v: &str) -> Result { 119 | Ok(1) 120 | } 121 | 122 | #[inline] 123 | fn serialize_bytes(self, _v: &[u8]) -> Result { 124 | Ok(1) 125 | } 126 | 127 | #[inline] 128 | fn collect_str(self, _value: &T) -> Result 129 | where 130 | T: std::fmt::Display, 131 | { 132 | Ok(1) 133 | } 134 | 135 | #[inline] 136 | fn serialize_none(self) -> Result { 137 | Err(Error::InvalidType("an option")) 138 | } 139 | 140 | #[inline] 141 | fn serialize_some(self, _value: &T) -> Result 142 | where 143 | T: serde::Serialize, 144 | { 145 | Err(Error::InvalidType("an option")) 146 | } 147 | 148 | #[inline] 149 | fn serialize_unit(self) -> Result { 150 | Err(Error::InvalidType("a unit")) 151 | } 152 | 153 | #[inline] 154 | fn serialize_unit_struct(self, _name: &'static str) -> Result { 155 | Ok(1) 156 | } 157 | 158 | #[inline] 159 | fn serialize_unit_variant( 160 | self, 161 | _name: &'static str, 162 | _variant_index: u32, 163 | _variant: &'static str, 164 | ) -> Result { 165 | Ok(1) 166 | } 167 | 168 | #[inline] 169 | fn serialize_newtype_struct( 170 | self, 171 | _name: &'static str, 172 | _value: &T, 173 | ) -> Result 174 | where 175 | T: serde::Serialize, 176 | { 177 | Err(Error::InvalidType("a newtype struct")) 178 | } 179 | 180 | #[inline] 181 | fn serialize_newtype_variant( 182 | self, 183 | _name: &'static str, 184 | _variant_index: u32, 185 | _variant: &'static str, 186 | _value: &T, 187 | ) -> Result 188 | where 189 | T: serde::Serialize, 190 | { 191 | Err(Error::InvalidType("a data enum")) 192 | } 193 | 194 | #[inline] 195 | fn serialize_seq(self, _len: Option) -> Result { 196 | Ok(Accumulator::new()) 197 | } 198 | 199 | fn collect_seq(self, iter: I) -> Result 200 | where 201 | I: IntoIterator, 202 | ::Item: serde::Serialize, 203 | { 204 | iter.into_iter() 205 | .map(|item| item.serialize(Serializer)) 206 | .try_fold(0usize, |accum, len| { 207 | accum.checked_add(len?).ok_or(Error::Overflow) 208 | }) 209 | } 210 | 211 | #[inline] 212 | fn serialize_tuple(self, _len: usize) -> Result { 213 | Ok(TupleSeqAdapter::new(Accumulator::new())) 214 | } 215 | 216 | #[inline] 217 | fn serialize_tuple_struct( 218 | self, 219 | _name: &'static str, 220 | _len: usize, 221 | ) -> Result { 222 | Err(Error::InvalidType("a tuple struct")) 223 | } 224 | 225 | #[inline] 226 | fn serialize_tuple_variant( 227 | self, 228 | _name: &'static str, 229 | _variant_index: u32, 230 | _variant: &'static str, 231 | _len: usize, 232 | ) -> Result { 233 | Err(Error::InvalidType("a data enum")) 234 | } 235 | 236 | #[inline] 237 | fn serialize_map(self, _len: Option) -> Result { 238 | Err(Error::InvalidType("a map")) 239 | } 240 | 241 | #[inline] 242 | fn serialize_struct( 243 | self, 244 | _name: &'static str, 245 | _len: usize, 246 | ) -> Result { 247 | Err(Error::InvalidType("a struct")) 248 | } 249 | 250 | #[inline] 251 | fn serialize_struct_variant( 252 | self, 253 | _name: &'static str, 254 | _variant_index: u32, 255 | _variant: &'static str, 256 | _len: usize, 257 | ) -> Result { 258 | Err(Error::InvalidType("a data enum")) 259 | } 260 | } 261 | 262 | pub struct Accumulator { 263 | length: usize, 264 | } 265 | 266 | impl Accumulator { 267 | #[inline] 268 | fn new() -> Self { 269 | Self { length: 0 } 270 | } 271 | } 272 | 273 | impl ser::SerializeSeq for Accumulator { 274 | type Ok = usize; 275 | type Error = Error; 276 | 277 | #[inline] 278 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> 279 | where 280 | T: serde::Serialize, 281 | { 282 | self.length = self 283 | .length 284 | .checked_add(value.serialize(Serializer)?) 285 | .ok_or(Error::Overflow)?; 286 | 287 | Ok(()) 288 | } 289 | 290 | #[inline] 291 | fn end(self) -> Result { 292 | Ok(self.length) 293 | } 294 | } 295 | -------------------------------------------------------------------------------- /src/components/key_value.rs: -------------------------------------------------------------------------------- 1 | use serde::{de, forward_to_deserialize_any, ser}; 2 | 3 | /// Adapter for key-value pairs in Redis. 4 | /// 5 | /// Commonly, Redis will express a set of key-value pairs as a flattened array 6 | /// of the keys and values. For instance, `HGETALL` returns something 7 | /// resembling `["key1", "value1", "key2", "value2"]`. [`KeyValuePairs`] allows 8 | /// for rust maps and structs to be adapted in this way; a map or struct type 9 | /// wrapped in `KeyValuePairs` will serialize to, and deserialize from, a 10 | /// flattened array of key-value pairs. 11 | /// 12 | /// # Example 13 | /// 14 | /// ``` 15 | /// use serde::{Serialize, Deserialize}; 16 | /// use seredies::{de::Deserializer, ser::Serializer, components::KeyValuePairs}; 17 | /// 18 | /// let mut buffer: Vec = Vec::new(); 19 | /// 20 | /// let data = ["key1", "value1", "key2", "value2"]; 21 | /// data.serialize(Serializer::new(&mut buffer)).unwrap(); 22 | /// 23 | /// #[derive(Deserialize)] 24 | /// struct Data { 25 | /// key1: String, 26 | /// key2: String, 27 | /// } 28 | /// 29 | /// let mut buffer = buffer.as_slice(); 30 | /// let deserializer = Deserializer::new(&mut buffer); 31 | /// let KeyValuePairs(Data{key1, key2}) = Deserialize::deserialize(deserializer) 32 | /// .expect("failed to deserialize"); 33 | /// 34 | /// assert_eq!(key1, "value1"); 35 | /// assert_eq!(key2, "value2"); 36 | /// ``` 37 | #[derive(Debug, Copy, Clone, Default)] 38 | pub struct KeyValuePairs(pub T); 39 | 40 | impl From for KeyValuePairs { 41 | fn from(value: T) -> Self { 42 | Self(value) 43 | } 44 | } 45 | 46 | impl ser::Serialize for KeyValuePairs { 47 | fn serialize(&self, serializer: S) -> Result 48 | where 49 | S: serde::Serializer, 50 | { 51 | self.0.serialize(KeyValuePairsAdapter(serializer)) 52 | } 53 | } 54 | 55 | #[derive(Debug, Clone, Copy, Default)] 56 | struct KeyValuePairsAdapter(T); 57 | 58 | impl KeyValuePairsAdapter { 59 | fn non_collection_serialize_error(&self) -> Result { 60 | Err(E::custom( 61 | "KeyValuePairsAdapter must deserialize a struct or map", 62 | )) 63 | } 64 | } 65 | 66 | fn double_len(len: usize) -> Result { 67 | len.checked_mul(2) 68 | .ok_or_else(|| E::custom("overflowed a usize")) 69 | } 70 | 71 | impl ser::Serializer for KeyValuePairsAdapter { 72 | type Ok = S::Ok; 73 | type Error = S::Error; 74 | 75 | type SerializeSeq = ser::Impossible; 76 | type SerializeTuple = ser::Impossible; 77 | 78 | type SerializeMap = KeyValuePairsAdapter; 79 | type SerializeStruct = KeyValuePairsAdapter; 80 | 81 | type SerializeTupleStruct = ser::Impossible; 82 | type SerializeTupleVariant = ser::Impossible; 83 | type SerializeStructVariant = ser::Impossible; 84 | 85 | fn serialize_bool(self, _v: bool) -> Result { 86 | self.non_collection_serialize_error() 87 | } 88 | 89 | fn serialize_i8(self, _v: i8) -> Result { 90 | self.non_collection_serialize_error() 91 | } 92 | 93 | fn serialize_i16(self, _v: i16) -> Result { 94 | self.non_collection_serialize_error() 95 | } 96 | 97 | fn serialize_i32(self, _v: i32) -> Result { 98 | self.non_collection_serialize_error() 99 | } 100 | 101 | fn serialize_i64(self, _v: i64) -> Result { 102 | self.non_collection_serialize_error() 103 | } 104 | 105 | fn serialize_u8(self, _v: u8) -> Result { 106 | self.non_collection_serialize_error() 107 | } 108 | 109 | fn serialize_u16(self, _v: u16) -> Result { 110 | self.non_collection_serialize_error() 111 | } 112 | 113 | fn serialize_u32(self, _v: u32) -> Result { 114 | self.non_collection_serialize_error() 115 | } 116 | 117 | fn serialize_u64(self, _v: u64) -> Result { 118 | self.non_collection_serialize_error() 119 | } 120 | 121 | fn serialize_u128(self, _v: u128) -> Result { 122 | self.non_collection_serialize_error() 123 | } 124 | 125 | fn serialize_f32(self, _v: f32) -> Result { 126 | self.non_collection_serialize_error() 127 | } 128 | 129 | fn serialize_f64(self, _v: f64) -> Result { 130 | self.non_collection_serialize_error() 131 | } 132 | 133 | fn serialize_char(self, _v: char) -> Result { 134 | self.non_collection_serialize_error() 135 | } 136 | 137 | fn serialize_str(self, _v: &str) -> Result { 138 | self.non_collection_serialize_error() 139 | } 140 | 141 | fn serialize_bytes(self, _v: &[u8]) -> Result { 142 | self.non_collection_serialize_error() 143 | } 144 | 145 | fn serialize_none(self) -> Result { 146 | self.non_collection_serialize_error() 147 | } 148 | 149 | fn serialize_some(self, _value: &T) -> Result 150 | where 151 | T: serde::Serialize, 152 | { 153 | self.non_collection_serialize_error() 154 | } 155 | 156 | fn serialize_unit(self) -> Result { 157 | self.non_collection_serialize_error() 158 | } 159 | 160 | fn serialize_unit_struct(self, _name: &'static str) -> Result { 161 | self.non_collection_serialize_error() 162 | } 163 | 164 | fn serialize_unit_variant( 165 | self, 166 | _name: &'static str, 167 | _variant_index: u32, 168 | _variant: &'static str, 169 | ) -> Result { 170 | self.non_collection_serialize_error() 171 | } 172 | 173 | fn serialize_newtype_struct( 174 | self, 175 | name: &'static str, 176 | value: &T, 177 | ) -> Result 178 | where 179 | T: serde::Serialize, 180 | { 181 | self.0.serialize_newtype_struct(name, &KeyValuePairs(value)) 182 | } 183 | 184 | fn serialize_newtype_variant( 185 | self, 186 | _name: &'static str, 187 | _variant_index: u32, 188 | _variant: &'static str, 189 | _value: &T, 190 | ) -> Result 191 | where 192 | T: serde::Serialize, 193 | { 194 | self.non_collection_serialize_error() 195 | } 196 | 197 | fn serialize_seq(self, _len: Option) -> Result { 198 | self.non_collection_serialize_error() 199 | } 200 | 201 | fn serialize_tuple(self, _len: usize) -> Result { 202 | self.non_collection_serialize_error() 203 | } 204 | 205 | fn serialize_tuple_struct( 206 | self, 207 | _name: &'static str, 208 | _len: usize, 209 | ) -> Result { 210 | self.non_collection_serialize_error() 211 | } 212 | 213 | fn serialize_tuple_variant( 214 | self, 215 | _name: &'static str, 216 | _variant_index: u32, 217 | _variant: &'static str, 218 | _len: usize, 219 | ) -> Result { 220 | self.non_collection_serialize_error() 221 | } 222 | 223 | fn serialize_map(self, len: Option) -> Result { 224 | self.0 225 | .serialize_seq(len.map(double_len).transpose()?) 226 | .map(KeyValuePairsAdapter) 227 | } 228 | 229 | fn serialize_struct( 230 | self, 231 | _name: &'static str, 232 | len: usize, 233 | ) -> Result { 234 | self.0 235 | .serialize_tuple(double_len(len)?) 236 | .map(KeyValuePairsAdapter) 237 | } 238 | 239 | fn serialize_struct_variant( 240 | self, 241 | _name: &'static str, 242 | _variant_index: u32, 243 | _variant: &'static str, 244 | _len: usize, 245 | ) -> Result { 246 | self.non_collection_serialize_error() 247 | } 248 | } 249 | 250 | impl ser::SerializeMap for KeyValuePairsAdapter { 251 | type Ok = S::Ok; 252 | type Error = S::Error; 253 | 254 | fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> 255 | where 256 | T: serde::Serialize, 257 | { 258 | self.0.serialize_element(key) 259 | } 260 | 261 | fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> 262 | where 263 | T: serde::Serialize, 264 | { 265 | self.0.serialize_element(value) 266 | } 267 | 268 | fn end(self) -> Result { 269 | self.0.end() 270 | } 271 | } 272 | 273 | impl ser::SerializeStruct for KeyValuePairsAdapter { 274 | type Ok = S::Ok; 275 | type Error = S::Error; 276 | 277 | fn serialize_field( 278 | &mut self, 279 | key: &'static str, 280 | value: &T, 281 | ) -> Result<(), Self::Error> 282 | where 283 | T: serde::Serialize, 284 | { 285 | self.0.serialize_element(key)?; 286 | self.0.serialize_element(value) 287 | } 288 | 289 | fn end(self) -> Result { 290 | self.0.end() 291 | } 292 | } 293 | 294 | impl<'de, T> de::Deserialize<'de> for KeyValuePairs 295 | where 296 | T: de::Deserialize<'de>, 297 | { 298 | fn deserialize(deserializer: D) -> Result 299 | where 300 | D: serde::Deserializer<'de>, 301 | { 302 | T::deserialize(KeyValuePairsAdapter(deserializer)).map(Self) 303 | } 304 | } 305 | 306 | impl<'de, D> de::Deserializer<'de> for KeyValuePairsAdapter 307 | where 308 | D: de::Deserializer<'de>, 309 | { 310 | type Error = D::Error; 311 | 312 | forward_to_deserialize_any! { 313 | bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string 314 | bytes byte_buf unit_struct seq tuple unit option enum 315 | tuple_struct identifier ignored_any 316 | } 317 | 318 | fn deserialize_any(self, visitor: V) -> Result 319 | where 320 | V: de::Visitor<'de>, 321 | { 322 | self.0.deserialize_any(KeyValuePairsAdapter(visitor)) 323 | } 324 | 325 | fn deserialize_map(self, visitor: V) -> Result 326 | where 327 | V: de::Visitor<'de>, 328 | { 329 | self.0.deserialize_seq(KeyValuePairsAdapter(visitor)) 330 | } 331 | 332 | fn deserialize_newtype_struct( 333 | self, 334 | _name: &'static str, 335 | visitor: V, 336 | ) -> Result 337 | where 338 | V: de::Visitor<'de>, 339 | { 340 | visitor.visit_newtype_struct(self) 341 | } 342 | 343 | fn deserialize_struct( 344 | self, 345 | name: &'static str, 346 | fields: &'static [&'static str], 347 | visitor: V, 348 | ) -> Result 349 | where 350 | V: de::Visitor<'de>, 351 | { 352 | self.0.deserialize_tuple_struct( 353 | name, 354 | fields 355 | .len() 356 | .checked_mul(2) 357 | .ok_or_else(|| de::Error::custom("overflowed a usize"))?, 358 | KeyValuePairsAdapter(visitor), 359 | ) 360 | } 361 | } 362 | 363 | impl<'de, V> de::Visitor<'de> for KeyValuePairsAdapter 364 | where 365 | V: de::Visitor<'de>, 366 | { 367 | type Value = V::Value; 368 | 369 | fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 370 | write!(formatter, "an flattened array of key-value pairs")?; 371 | self.0.expecting(formatter) 372 | } 373 | 374 | fn visit_seq(self, seq: A) -> Result 375 | where 376 | A: de::SeqAccess<'de>, 377 | { 378 | self.0.visit_map(KeyValuePairsAdapter(seq)) 379 | } 380 | 381 | fn visit_map(self, map: A) -> Result 382 | where 383 | A: de::MapAccess<'de>, 384 | { 385 | self.0.visit_map(map) 386 | } 387 | } 388 | 389 | impl<'de, S> de::MapAccess<'de> for KeyValuePairsAdapter 390 | where 391 | S: de::SeqAccess<'de>, 392 | { 393 | type Error = S::Error; 394 | 395 | fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> 396 | where 397 | K: de::DeserializeSeed<'de>, 398 | { 399 | self.0.next_element_seed(seed) 400 | } 401 | 402 | fn next_value_seed(&mut self, seed: V) -> Result 403 | where 404 | V: de::DeserializeSeed<'de>, 405 | { 406 | self.0.next_element_seed(seed)?.ok_or_else(|| { 407 | de::Error::custom( 408 | "underlying array contained an odd number of \ 409 | elements while deserializing as key value pairs", 410 | ) 411 | }) 412 | } 413 | } 414 | -------------------------------------------------------------------------------- /src/components/string.rs: -------------------------------------------------------------------------------- 1 | use std::{ 2 | any::type_name, 3 | fmt::{self, Display}, 4 | marker::PhantomData, 5 | mem, 6 | str::{from_utf8, FromStr}, 7 | }; 8 | 9 | use arrayvec::ArrayString; 10 | use paste::paste; 11 | use serde::{de, forward_to_deserialize_any, ser}; 12 | 13 | /** 14 | Adapter type that serializes the contained value as a string. 15 | 16 | Frequently, especially when sending commands, Redis will require data to be 17 | passed as a string, even when the underlying data is something like an 18 | integer. This type serializes its inner value as a string, and works 19 | on most primitive types. This will serialize unit enum variants and unit 20 | structs as their name. 21 | 22 | Note that this type *cannot* distinguish a `[u8]` from other kinds of 23 | slices; be sure to use a container like [`serde_bytes::Bytes`] to ensure 24 | that these slices are serialized as bytes objects rather than sequences. 25 | 26 | # Example 27 | 28 | ``` 29 | use seredies::components::RedisString; 30 | use serde::{Serialize, Deserialize}; 31 | use serde_test::{assert_tokens, assert_ser_tokens, Token}; 32 | 33 | assert_tokens(&RedisString("Hello"), &[Token::BorrowedStr("Hello")]); 34 | assert_tokens(&RedisString(5i32), &[Token::Str("5")]); 35 | assert_tokens(&RedisString(4.5), &[Token::Str("4.5")]); 36 | 37 | let s: &RedisString = RedisString::new_ref("string"); 38 | assert_tokens(&s, &[Token::BorrowedStr("string")]); 39 | 40 | #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] 41 | struct UnitStruct; 42 | 43 | #[derive(Serialize, Deserialize, Debug, PartialEq, Eq)] 44 | enum Data { 45 | Foo, 46 | Bar 47 | } 48 | 49 | assert_tokens(&RedisString(UnitStruct), &[Token::Str("UnitStruct")]); 50 | assert_tokens(&RedisString(Data::Bar), &[Token::Str("Bar")]); 51 | ``` 52 | */ 53 | #[derive(Debug, Clone, Copy, Default, PartialEq, Eq)] 54 | #[repr(transparent)] 55 | pub struct RedisString(pub T); 56 | 57 | impl RedisString { 58 | /// Convert a reference to some underlying type into a reference to a 59 | /// `RedisString` containing that object. This works even on unsized values 60 | /// and allows for the creation of things like `&RedisString`. 61 | pub fn new_ref(value: &T) -> &Self { 62 | unsafe { mem::transmute(value) } 63 | } 64 | } 65 | 66 | impl ser::Serialize for RedisString 67 | where 68 | T: ser::Serialize + ?Sized, 69 | { 70 | fn serialize(&self, serializer: S) -> Result 71 | where 72 | S: serde::Serializer, 73 | { 74 | self.0.serialize(RedisStringAdapter(serializer)) 75 | } 76 | } 77 | 78 | impl<'de, T> de::Deserialize<'de> for RedisString 79 | where 80 | T: de::Deserialize<'de> + ?Sized, 81 | { 82 | fn deserialize(deserializer: D) -> Result 83 | where 84 | D: serde::Deserializer<'de>, 85 | { 86 | de::Deserialize::deserialize(RedisStringAdapter(deserializer)).map(RedisString) 87 | } 88 | } 89 | 90 | impl<'de, T: 'de> de::Deserialize<'de> for &'de RedisString 91 | where 92 | &'de T: de::Deserialize<'de>, 93 | T: ?Sized, 94 | { 95 | fn deserialize(deserializer: D) -> Result 96 | where 97 | D: serde::Deserializer<'de>, 98 | { 99 | <&T>::deserialize(RedisStringAdapter(deserializer)).map(RedisString::new_ref) 100 | } 101 | } 102 | 103 | /// Internal adapter type for serializers, deserializers, visitors, etc. 104 | struct RedisStringAdapter(T); 105 | 106 | impl RedisStringAdapter 107 | where 108 | S: ser::Serializer, 109 | { 110 | fn serialize_number(self, value: impl Display) -> Result { 111 | // 39 digits should be enough for even a 128 bit int, but we'll round 112 | // way up to be safe 113 | use fmt::Write as _; 114 | 115 | let mut buffer: ArrayString<64> = ArrayString::new(); 116 | 117 | write!(&mut buffer, "{value}") 118 | .map_err(|_| ser::Error::custom("integer was more than 64 digits"))?; 119 | 120 | self.0.serialize_str(&buffer) 121 | } 122 | } 123 | 124 | impl ser::Serializer for RedisStringAdapter 125 | where 126 | S: ser::Serializer, 127 | { 128 | type Ok = S::Ok; 129 | type Error = S::Error; 130 | 131 | type SerializeSeq = ser::Impossible; 132 | type SerializeTuple = ser::Impossible; 133 | type SerializeTupleStruct = ser::Impossible; 134 | type SerializeTupleVariant = ser::Impossible; 135 | type SerializeMap = ser::Impossible; 136 | type SerializeStruct = ser::Impossible; 137 | type SerializeStructVariant = ser::Impossible; 138 | 139 | #[inline] 140 | fn serialize_bool(self, _v: bool) -> Result { 141 | Err(ser::Error::custom( 142 | "can't serialize booleans as redis strings", 143 | )) 144 | } 145 | 146 | #[inline] 147 | fn serialize_i8(self, v: i8) -> Result { 148 | self.serialize_number(v) 149 | } 150 | 151 | #[inline] 152 | fn serialize_i16(self, v: i16) -> Result { 153 | self.serialize_number(v) 154 | } 155 | 156 | #[inline] 157 | fn serialize_i32(self, v: i32) -> Result { 158 | self.serialize_number(v) 159 | } 160 | 161 | #[inline] 162 | fn serialize_i64(self, v: i64) -> Result { 163 | self.serialize_number(v) 164 | } 165 | 166 | #[inline] 167 | fn serialize_i128(self, v: i128) -> Result { 168 | self.serialize_number(v) 169 | } 170 | 171 | #[inline] 172 | fn serialize_u8(self, v: u8) -> Result { 173 | self.serialize_number(v) 174 | } 175 | 176 | #[inline] 177 | fn serialize_u16(self, v: u16) -> Result { 178 | self.serialize_number(v) 179 | } 180 | 181 | #[inline] 182 | fn serialize_u32(self, v: u32) -> Result { 183 | self.serialize_number(v) 184 | } 185 | 186 | #[inline] 187 | fn serialize_u64(self, v: u64) -> Result { 188 | self.serialize_number(v) 189 | } 190 | 191 | #[inline] 192 | fn serialize_u128(self, v: u128) -> Result { 193 | self.serialize_number(v) 194 | } 195 | 196 | #[inline] 197 | fn serialize_f32(self, v: f32) -> Result { 198 | self.serialize_number(v) 199 | } 200 | 201 | #[inline] 202 | fn serialize_f64(self, v: f64) -> Result { 203 | self.serialize_number(v) 204 | } 205 | 206 | #[inline] 207 | fn serialize_char(self, v: char) -> Result { 208 | let mut buffer = [0; 4]; 209 | self.serialize_str(v.encode_utf8(&mut buffer)) 210 | } 211 | 212 | #[inline] 213 | fn serialize_str(self, v: &str) -> Result { 214 | self.0.serialize_str(v) 215 | } 216 | 217 | #[inline] 218 | fn serialize_bytes(self, v: &[u8]) -> Result { 219 | self.0.serialize_bytes(v) 220 | } 221 | 222 | #[inline] 223 | fn serialize_none(self) -> Result { 224 | Err(ser::Error::custom( 225 | "can't serialize options as redis strings", 226 | )) 227 | } 228 | 229 | #[inline] 230 | fn serialize_some(self, _value: &T) -> Result 231 | where 232 | T: serde::Serialize, 233 | { 234 | Err(ser::Error::custom( 235 | "can't serialize options as redis strings", 236 | )) 237 | } 238 | 239 | #[inline] 240 | fn serialize_unit(self) -> Result { 241 | Err(ser::Error::custom("can't serialize units as redis strings")) 242 | } 243 | 244 | #[inline] 245 | fn serialize_unit_struct(self, name: &'static str) -> Result { 246 | self.serialize_str(name) 247 | } 248 | 249 | #[inline] 250 | fn serialize_unit_variant( 251 | self, 252 | _name: &'static str, 253 | _variant_index: u32, 254 | variant: &'static str, 255 | ) -> Result { 256 | self.serialize_unit_struct(variant) 257 | } 258 | 259 | #[inline] 260 | fn serialize_newtype_struct( 261 | self, 262 | _name: &'static str, 263 | value: &T, 264 | ) -> Result 265 | where 266 | T: serde::Serialize, 267 | { 268 | value.serialize(self) 269 | } 270 | 271 | #[inline] 272 | fn serialize_newtype_variant( 273 | self, 274 | _name: &'static str, 275 | _variant_index: u32, 276 | _variant: &'static str, 277 | _value: &T, 278 | ) -> Result 279 | where 280 | T: serde::Serialize, 281 | { 282 | Err(ser::Error::custom( 283 | "can't serialize data enums as redis strings", 284 | )) 285 | } 286 | 287 | #[inline] 288 | fn serialize_seq(self, _len: Option) -> Result { 289 | Err(ser::Error::custom("can't serialize lists as redis strings")) 290 | } 291 | 292 | #[inline] 293 | fn serialize_tuple(self, _len: usize) -> Result { 294 | Err(ser::Error::custom( 295 | "can't serialize tuples as redis strings", 296 | )) 297 | } 298 | 299 | #[inline] 300 | fn serialize_tuple_struct( 301 | self, 302 | _name: &'static str, 303 | _len: usize, 304 | ) -> Result { 305 | Err(ser::Error::custom( 306 | "can't serialize structs as redis strings", 307 | )) 308 | } 309 | 310 | #[inline] 311 | fn serialize_tuple_variant( 312 | self, 313 | _name: &'static str, 314 | _variant_index: u32, 315 | _variant: &'static str, 316 | _len: usize, 317 | ) -> Result { 318 | Err(ser::Error::custom( 319 | "can't serialize data enums as redis strings", 320 | )) 321 | } 322 | 323 | fn serialize_map(self, _len: Option) -> Result { 324 | Err(ser::Error::custom("can't serialize maps as redis strings")) 325 | } 326 | 327 | fn serialize_struct( 328 | self, 329 | _name: &'static str, 330 | _len: usize, 331 | ) -> Result { 332 | Err(ser::Error::custom( 333 | "can't serialize structs as redis strings", 334 | )) 335 | } 336 | 337 | fn serialize_struct_variant( 338 | self, 339 | _name: &'static str, 340 | _variant_index: u32, 341 | _variant: &'static str, 342 | _len: usize, 343 | ) -> Result { 344 | Err(ser::Error::custom( 345 | "can't serialize data enums as redis strings", 346 | )) 347 | } 348 | } 349 | 350 | impl<'de, D: de::Deserializer<'de>> de::Deserializer<'de> for RedisStringAdapter { 351 | type Error = D::Error; 352 | 353 | #[inline] 354 | fn deserialize_any(self, visitor: V) -> Result 355 | where 356 | V: de::Visitor<'de>, 357 | { 358 | self.0.deserialize_bytes(visitor) 359 | } 360 | 361 | forward_to_deserialize_any! {bool option unit seq tuple tuple_struct map struct identifier ignored_any} 362 | 363 | #[inline] 364 | fn deserialize_i8(self, visitor: V) -> Result 365 | where 366 | V: de::Visitor<'de>, 367 | { 368 | self.0 369 | .deserialize_bytes(FromStrVisitor::<_, i8>::new(visitor)) 370 | } 371 | 372 | #[inline] 373 | fn deserialize_i16(self, visitor: V) -> Result 374 | where 375 | V: de::Visitor<'de>, 376 | { 377 | self.0 378 | .deserialize_bytes(FromStrVisitor::<_, i16>::new(visitor)) 379 | } 380 | 381 | #[inline] 382 | fn deserialize_i32(self, visitor: V) -> Result 383 | where 384 | V: de::Visitor<'de>, 385 | { 386 | self.0 387 | .deserialize_bytes(FromStrVisitor::<_, i32>::new(visitor)) 388 | } 389 | 390 | #[inline] 391 | fn deserialize_i64(self, visitor: V) -> Result 392 | where 393 | V: de::Visitor<'de>, 394 | { 395 | self.0 396 | .deserialize_bytes(FromStrVisitor::<_, i64>::new(visitor)) 397 | } 398 | 399 | #[inline] 400 | fn deserialize_i128(self, visitor: V) -> Result 401 | where 402 | V: de::Visitor<'de>, 403 | { 404 | self.0 405 | .deserialize_bytes(FromStrVisitor::<_, i128>::new(visitor)) 406 | } 407 | 408 | #[inline] 409 | fn deserialize_u8(self, visitor: V) -> Result 410 | where 411 | V: de::Visitor<'de>, 412 | { 413 | self.0 414 | .deserialize_bytes(FromStrVisitor::<_, u8>::new(visitor)) 415 | } 416 | 417 | #[inline] 418 | fn deserialize_u16(self, visitor: V) -> Result 419 | where 420 | V: de::Visitor<'de>, 421 | { 422 | self.0 423 | .deserialize_bytes(FromStrVisitor::<_, u16>::new(visitor)) 424 | } 425 | 426 | #[inline] 427 | fn deserialize_u32(self, visitor: V) -> Result 428 | where 429 | V: de::Visitor<'de>, 430 | { 431 | self.0 432 | .deserialize_bytes(FromStrVisitor::<_, u32>::new(visitor)) 433 | } 434 | 435 | #[inline] 436 | fn deserialize_u64(self, visitor: V) -> Result 437 | where 438 | V: de::Visitor<'de>, 439 | { 440 | self.0 441 | .deserialize_bytes(FromStrVisitor::<_, u64>::new(visitor)) 442 | } 443 | 444 | #[inline] 445 | fn deserialize_u128(self, visitor: V) -> Result 446 | where 447 | V: de::Visitor<'de>, 448 | { 449 | self.0 450 | .deserialize_bytes(FromStrVisitor::<_, u128>::new(visitor)) 451 | } 452 | 453 | #[inline] 454 | fn deserialize_f32(self, visitor: V) -> Result 455 | where 456 | V: de::Visitor<'de>, 457 | { 458 | self.0 459 | .deserialize_bytes(FromStrVisitor::<_, f32>::new(visitor)) 460 | } 461 | 462 | #[inline] 463 | fn deserialize_f64(self, visitor: V) -> Result 464 | where 465 | V: de::Visitor<'de>, 466 | { 467 | self.0 468 | .deserialize_bytes(FromStrVisitor::<_, f64>::new(visitor)) 469 | } 470 | 471 | #[inline] 472 | fn deserialize_char(self, visitor: V) -> Result 473 | where 474 | V: de::Visitor<'de>, 475 | { 476 | self.0.deserialize_bytes(StrBytesVisitor::new(visitor)) 477 | } 478 | 479 | #[inline] 480 | fn deserialize_str(self, visitor: V) -> Result 481 | where 482 | V: de::Visitor<'de>, 483 | { 484 | self.0.deserialize_bytes(StrBytesVisitor::new(visitor)) 485 | } 486 | 487 | #[inline] 488 | fn deserialize_string(self, visitor: V) -> Result 489 | where 490 | V: de::Visitor<'de>, 491 | { 492 | self.0.deserialize_byte_buf(StrBytesVisitor::new(visitor)) 493 | } 494 | 495 | #[inline] 496 | fn deserialize_bytes(self, visitor: V) -> Result 497 | where 498 | V: de::Visitor<'de>, 499 | { 500 | self.0.deserialize_bytes(visitor) 501 | } 502 | 503 | #[inline] 504 | fn deserialize_byte_buf(self, visitor: V) -> Result 505 | where 506 | V: de::Visitor<'de>, 507 | { 508 | self.0.deserialize_byte_buf(visitor) 509 | } 510 | 511 | #[inline] 512 | fn deserialize_unit_struct( 513 | self, 514 | name: &'static str, 515 | visitor: V, 516 | ) -> Result 517 | where 518 | V: de::Visitor<'de>, 519 | { 520 | struct Visitor { 521 | visitor: V, 522 | name: &'static str, 523 | } 524 | 525 | impl<'de, V: de::Visitor<'de>> de::Visitor<'de> for Visitor { 526 | type Value = V::Value; 527 | 528 | fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 529 | write!(formatter, "a byte slice containing {:?}", self.name) 530 | } 531 | 532 | fn visit_bytes(self, v: &[u8]) -> Result 533 | where 534 | E: de::Error, 535 | { 536 | if v == self.name.as_bytes() { 537 | self.visitor.visit_unit() 538 | } else { 539 | Err(de::Error::invalid_value(de::Unexpected::Bytes(v), &self)) 540 | } 541 | } 542 | 543 | #[inline] 544 | fn visit_str(self, v: &str) -> Result 545 | where 546 | E: de::Error, 547 | { 548 | if v == self.name { 549 | self.visitor.visit_unit() 550 | } else { 551 | Err(de::Error::invalid_value(de::Unexpected::Str(v), &self)) 552 | } 553 | } 554 | } 555 | 556 | self.0.deserialize_bytes(Visitor { visitor, name }) 557 | } 558 | 559 | #[inline] 560 | fn deserialize_newtype_struct( 561 | self, 562 | _name: &'static str, 563 | visitor: V, 564 | ) -> Result 565 | where 566 | V: de::Visitor<'de>, 567 | { 568 | visitor.visit_newtype_struct(self) 569 | } 570 | 571 | #[inline] 572 | fn deserialize_enum( 573 | self, 574 | _name: &'static str, 575 | _variants: &'static [&'static str], 576 | visitor: V, 577 | ) -> Result 578 | where 579 | V: de::Visitor<'de>, 580 | { 581 | struct Adapter { 582 | inner: T, 583 | error: PhantomData, 584 | } 585 | 586 | impl Adapter { 587 | #[inline] 588 | #[must_use] 589 | const fn new(inner: T) -> Self { 590 | Self { 591 | inner, 592 | error: PhantomData, 593 | } 594 | } 595 | } 596 | 597 | impl<'de, V: de::Visitor<'de>, E2> de::Visitor<'de> for Adapter { 598 | type Value = V::Value; 599 | 600 | fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 601 | write!(formatter, "a redis byte slice containing ")?; 602 | self.inner.expecting(formatter) 603 | } 604 | 605 | #[inline] 606 | fn visit_str(self, v: &str) -> Result 607 | where 608 | E: de::Error, 609 | { 610 | self.inner.visit_enum(Adapter::new(v)) 611 | } 612 | 613 | #[inline] 614 | fn visit_bytes(self, v: &[u8]) -> Result 615 | where 616 | E: de::Error, 617 | { 618 | self.inner.visit_enum(Adapter::new(v)) 619 | } 620 | } 621 | 622 | impl<'de, 'a, E: de::Error> de::EnumAccess<'de> for Adapter<&'a [u8], E> { 623 | type Error = E; 624 | type Variant = Adapter<(), E>; 625 | 626 | fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> 627 | where 628 | V: de::DeserializeSeed<'de>, 629 | { 630 | seed.deserialize(de::value::BytesDeserializer::new(self.inner)) 631 | .map(|value| (value, Adapter::new(()))) 632 | } 633 | } 634 | 635 | impl<'de, 'a, E: de::Error> de::EnumAccess<'de> for Adapter<&'a str, E> { 636 | type Error = E; 637 | type Variant = Adapter<(), E>; 638 | 639 | fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> 640 | where 641 | V: de::DeserializeSeed<'de>, 642 | { 643 | seed.deserialize(de::value::StrDeserializer::new(self.inner)) 644 | .map(|value| (value, Adapter::new(()))) 645 | } 646 | } 647 | 648 | impl<'de, E: de::Error> de::VariantAccess<'de> for Adapter<(), E> { 649 | type Error = E; 650 | 651 | #[inline] 652 | fn unit_variant(self) -> Result<(), Self::Error> { 653 | Ok(()) 654 | } 655 | 656 | #[inline] 657 | fn newtype_variant_seed(self, _seed: T) -> Result 658 | where 659 | T: de::DeserializeSeed<'de>, 660 | { 661 | Err(de::Error::invalid_type( 662 | de::Unexpected::UnitVariant, 663 | &"a newtype variant", 664 | )) 665 | } 666 | 667 | #[inline] 668 | fn tuple_variant(self, _len: usize, _visitor: V) -> Result 669 | where 670 | V: de::Visitor<'de>, 671 | { 672 | Err(de::Error::invalid_type( 673 | de::Unexpected::UnitVariant, 674 | &"a tuple variant", 675 | )) 676 | } 677 | 678 | #[inline] 679 | fn struct_variant( 680 | self, 681 | _fields: &'static [&'static str], 682 | _visitor: V, 683 | ) -> Result 684 | where 685 | V: de::Visitor<'de>, 686 | { 687 | Err(de::Error::invalid_type( 688 | de::Unexpected::UnitVariant, 689 | &"a struct variant", 690 | )) 691 | } 692 | } 693 | 694 | self.0.deserialize_bytes(Adapter { 695 | inner: visitor, 696 | error: PhantomData::<()>, 697 | }) 698 | } 699 | } 700 | 701 | trait VisitTo { 702 | fn apply_to_visitor<'de, V, E>(self, visitor: V) -> Result 703 | where 704 | V: de::Visitor<'de>, 705 | E: de::Error; 706 | } 707 | 708 | macro_rules! impl_visit_to { 709 | ($($type:ident)*) => { 710 | $( 711 | paste!{ 712 | impl VisitTo for $type { 713 | fn apply_to_visitor<'de, V, E>(self, visitor: V) -> Result 714 | where 715 | V: de::Visitor<'de>, 716 | E: de::Error 717 | { 718 | visitor.[](self) 719 | } 720 | } 721 | } 722 | )* 723 | } 724 | } 725 | 726 | impl_visit_to! { 727 | u8 u16 u32 u64 u128 728 | i8 i16 i32 i64 i128 729 | f32 f64 730 | } 731 | 732 | /// A visitor that tries to convert the bytes data it receives into a string 733 | /// before forwarding it to the underlying visitor. 734 | struct StrBytesVisitor { 735 | visitor: V, 736 | } 737 | 738 | impl<'de, V: de::Visitor<'de>> StrBytesVisitor { 739 | pub fn new(visitor: V) -> Self { 740 | Self { visitor } 741 | } 742 | } 743 | 744 | impl<'de, V> de::Visitor<'de> for StrBytesVisitor 745 | where 746 | V: de::Visitor<'de>, 747 | { 748 | type Value = V::Value; 749 | 750 | fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 751 | self.visitor.expecting(formatter) 752 | } 753 | 754 | fn visit_bytes(self, v: &[u8]) -> Result 755 | where 756 | E: de::Error, 757 | { 758 | let s = from_utf8(v) 759 | .map_err(|_err| de::Error::invalid_value(de::Unexpected::Bytes(v), &self.visitor))?; 760 | self.visitor.visit_str(s) 761 | } 762 | 763 | fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result 764 | where 765 | E: de::Error, 766 | { 767 | let s = from_utf8(v) 768 | .map_err(|_err| de::Error::invalid_value(de::Unexpected::Bytes(v), &self.visitor))?; 769 | self.visitor.visit_borrowed_str(s) 770 | } 771 | 772 | fn visit_byte_buf(self, v: Vec) -> Result 773 | where 774 | E: de::Error, 775 | { 776 | let s = String::from_utf8(v).map_err(|err| { 777 | de::Error::invalid_value(de::Unexpected::Bytes(err.as_bytes()), &self.visitor) 778 | })?; 779 | 780 | self.visitor.visit_string(s) 781 | } 782 | 783 | fn visit_str(self, v: &str) -> Result 784 | where 785 | E: de::Error, 786 | { 787 | self.visitor.visit_str(v) 788 | } 789 | 790 | fn visit_borrowed_str(self, v: &'de str) -> Result 791 | where 792 | E: de::Error, 793 | { 794 | self.visitor.visit_borrowed_str(v) 795 | } 796 | 797 | fn visit_string(self, v: String) -> Result 798 | where 799 | E: de::Error, 800 | { 801 | self.visitor.visit_string(v) 802 | } 803 | } 804 | 805 | /// A visitor that expects a string and converts it to `T` with `FromStr` and 806 | /// forwards it to the underlying visitor. 807 | struct FromStrVisitor { 808 | inner: V, 809 | kind: PhantomData, 810 | } 811 | 812 | impl<'de, V, T> FromStrVisitor 813 | where 814 | V: de::Visitor<'de>, 815 | T: FromStr + VisitTo, 816 | { 817 | fn new(visitor: V) -> Self { 818 | Self { 819 | inner: visitor, 820 | kind: PhantomData, 821 | } 822 | } 823 | } 824 | 825 | impl<'de, V, T> de::Visitor<'de> for FromStrVisitor 826 | where 827 | V: de::Visitor<'de>, 828 | T: FromStr + VisitTo, 829 | { 830 | type Value = V::Value; 831 | 832 | fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 833 | write!(formatter, "{}", type_name::()) 834 | } 835 | 836 | fn visit_str(self, v: &str) -> Result 837 | where 838 | E: de::Error, 839 | { 840 | let value: T = v 841 | .parse() 842 | .map_err(|_err| de::Error::invalid_value(de::Unexpected::Str(v), &self))?; 843 | 844 | value.apply_to_visitor(self.inner) 845 | } 846 | 847 | fn visit_bytes(self, v: &[u8]) -> Result 848 | where 849 | E: de::Error, 850 | { 851 | let s = from_utf8(v) 852 | .map_err(|_err| de::Error::invalid_value(de::Unexpected::Bytes(v), &self.inner))?; 853 | 854 | self.visit_str(s) 855 | } 856 | } 857 | -------------------------------------------------------------------------------- /src/de.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Serde deserializer for turning Redis RESP data into Rust data structures. 3 | 4 | This module contains a faithful implementation of the 5 | [Redis Serialization Protocol](https://redis.io/docs/reference/protocol-spec/). 6 | 7 | See the [crate docs][crate] for an overview of how seredies maps the RESP data 8 | model to the serde data model. 9 | 10 | # Basic example 11 | 12 | ``` 13 | use serde::Deserialize; 14 | use seredies::de::from_bytes; 15 | 16 | let data = b"\ 17 | *4\r\n\ 18 | +OK\r\n\ 19 | :24\r\n\ 20 | $8\r\nBorrowed\r\n\ 21 | *3\r\n\ 22 | $-1\r\n\ 23 | +Hello,\r\n\ 24 | +World!\r\n\ 25 | "; 26 | 27 | #[derive(Deserialize, PartialEq, Eq, Debug)] 28 | struct Data<'a>( 29 | String, 30 | i32, 31 | &'a str, 32 | Vec>, 33 | ); 34 | 35 | let data: Data = from_bytes(data).expect("failed to deserialize"); 36 | 37 | assert_eq!( 38 | data, 39 | Data( 40 | "OK".to_owned(), 41 | 24, 42 | "Borrowed", 43 | Vec::from([ 44 | None, 45 | Some("Hello,".to_owned()), 46 | Some("World!".to_owned()), 47 | ]), 48 | ), 49 | ); 50 | ``` 51 | 52 | # Error example 53 | 54 | ``` 55 | use seredies::de::{from_bytes, Error}; 56 | 57 | let error = b"-ERR unknown command \"helloworld\"\r\n"; 58 | 59 | // Normally, Redis errors appear as deserialize errors (in the same way that 60 | // a parse error would appear): 61 | let res: Result, Error> = from_bytes(error); 62 | assert!(res.is_err()); 63 | 64 | // However, you can instead Deserialize the Result directly: 65 | let data: Result, String> = from_bytes(error).expect("deserialize shouldn't fail"); 66 | assert_eq!(data, Err("ERR unknown command \"helloworld\"".to_owned())); 67 | ``` 68 | 69 | # `Result::Ok` example 70 | 71 | ``` 72 | use seredies::de::from_bytes; 73 | 74 | type BoringResult<'a> = Result<(), &'a str>; 75 | 76 | let result: BoringResult = from_bytes(b"+OK\r\n") 77 | .expect("deserialize shouldn't fail"); 78 | 79 | assert_eq!(result, Ok(())); 80 | 81 | let result: BoringResult = from_bytes(b"-ERR error message\r\n") 82 | .expect("deserialize shouldn't fail"); 83 | 84 | assert_eq!(result, Err("ERR error message")); 85 | ``` 86 | 87 | [error type]: https://redis.io/docs/reference/protocol-spec/#resp-errors 88 | */ 89 | 90 | pub mod parse; 91 | mod result; 92 | 93 | use std::fmt::Display; 94 | 95 | use paste::paste; 96 | use serde::{de, forward_to_deserialize_any}; 97 | use thiserror::Error; 98 | 99 | use self::parse::{ParseResult, TaggedHeader}; 100 | use self::result::ResultAccess; 101 | 102 | /// Deserialize a `T` object from a string containing RESP data. 103 | pub fn from_str<'a, T: de::Deserialize<'a>>(input: &'a str) -> Result { 104 | from_bytes(input.as_bytes()) 105 | } 106 | 107 | /// Deserialize a `T` object from a byte slice containing RESP data. 108 | pub fn from_bytes<'a, T>(mut input: &'a [u8]) -> Result 109 | where 110 | T: de::Deserialize<'a>, 111 | { 112 | let deserializer = Deserializer::new(&mut input); 113 | let value = T::deserialize(deserializer)?; 114 | input.is_empty().then_some(value).ok_or(Error::TrailingData) 115 | } 116 | 117 | /// Errors that can occur while deserializing RESP data. 118 | #[derive(Debug, Clone, Error)] 119 | #[non_exhaustive] 120 | pub enum Error { 121 | /// There was an error during parsing (such as a \r without a \n). 122 | #[error("parsing error")] 123 | Parse(#[from] parse::Error), 124 | 125 | /// The length of an array or bulk string was out of bounds. It might 126 | /// have been negative, or exceeded the 512MB limit for bulk strings. 127 | #[error("an array or bulk string length was out of bounds")] 128 | Length, 129 | 130 | /// There was leftover data in the input after the deserialize operation. 131 | /// This is only returned by [`from_str`] and similar functions; the 132 | /// [`Deserializer`] itself will normally just leave that data untouched, 133 | /// to facilitate response pipelining. 134 | #[error("the deserialize completed, but didn't consume the entire input")] 135 | TrailingData, 136 | 137 | /// The `Deserialize` type successfully deserialized from a Redis array, 138 | /// but didn't consume the whole thing. 139 | #[error("the `Deserialize` type didn't consume the entire array")] 140 | UnfinishedArray, 141 | 142 | /// There was an error from the `Deserialize` type 143 | #[error("error from Deserialize type: {0}")] 144 | Custom(String), 145 | 146 | /// We *successfully* deserialized a Redis Error value (with the `-` tag) 147 | /// See the module docs on `Result` deserialization for how to avoid this 148 | /// error. 149 | #[error("successfully deserialized a Redis Error containing this message")] 150 | Redis(Vec), 151 | } 152 | 153 | impl de::Error for Error { 154 | #[inline] 155 | #[must_use] 156 | fn custom(msg: T) -> Self 157 | where 158 | T: Display, 159 | { 160 | Self::Custom(msg.to_string()) 161 | } 162 | } 163 | 164 | #[inline] 165 | fn apply_parser<'de, T>( 166 | input: &mut &'de [u8], 167 | parser: impl FnOnce(&'de [u8]) -> ParseResult<'de, T>, 168 | ) -> Result { 169 | parser(input).map(|(value, tail)| { 170 | *input = tail; 171 | value 172 | }) 173 | } 174 | 175 | /// A RESP Deserializer. 176 | /// 177 | /// This is the core serde [`Deserializer`][de::Deserializer] for RESP data. 178 | /// it operates on `&mut &[u8]`, a mutable reference to a byte slice, and 179 | /// after a successful deserialize it updates the slice in place the reflect 180 | /// any remaining unparsed content. This is intended to facilitate response 181 | /// pipelining, where a single stream might include many responses. 182 | /// 183 | /// A single `Deserializer` can be used to deserialize at most one RESP value. 184 | /// They are trivially cheap to create, though, so a new `Deserializer` can 185 | /// be used for each additional value. 186 | /// 187 | /// See also `from_bytes` and `from_str` for more convenient deserialize 188 | /// behavior. 189 | #[derive(Debug)] 190 | pub struct Deserializer<'a, 'de> { 191 | inner: UnparsedDeserializer<'a, 'de>, 192 | } 193 | 194 | impl<'a, 'de> Deserializer<'a, 'de> { 195 | /// Create a new RESP deserializer. 196 | /// 197 | /// The input should contain at least one complete RESP object (which 198 | /// might contain additional sub-objects). The input will be mutated during 199 | /// deserialization, such that after an object is fully deserialized, the 200 | /// buffer will be at the unused tail of the input. 201 | #[inline] 202 | #[must_use] 203 | pub fn new(input: &'a mut &'de [u8]) -> Self { 204 | Self { 205 | inner: UnparsedDeserializer::new(input), 206 | } 207 | } 208 | } 209 | 210 | macro_rules! forward { 211 | ($($method:ident $(($($arg:ident : $type:ty),*))?)*) => {$( 212 | paste! { 213 | #[inline] 214 | fn []( 215 | self, 216 | $($($arg : $type,)*)? 217 | visitor: V, 218 | ) -> Result 219 | where 220 | V: de::Visitor<'de> 221 | { 222 | self.inner.[]($($($arg,)*)? visitor) 223 | } 224 | } 225 | )*} 226 | } 227 | 228 | impl<'a, 'de> de::Deserializer<'de> for Deserializer<'a, 'de> { 229 | type Error = Error; 230 | 231 | forward! { 232 | any ignored_any bool 233 | i8 i16 i32 i64 i128 234 | u8 u16 u32 u64 u128 235 | f32 f64 236 | char str string bytes byte_buf identifier 237 | option unit 238 | seq map 239 | 240 | unit_struct(name: &'static str) 241 | newtype_struct(name: &'static str) 242 | tuple(len: usize) 243 | tuple_struct(name: &'static str, len: usize) 244 | struct(name: &'static str, fields: &'static[&'static str]) 245 | enum(name: &'static str, variants: &'static[&'static str]) 246 | 247 | } 248 | } 249 | 250 | /// Trait that abstracts the header read operation. At various points during 251 | /// a deserialize, the Deserializer might either need to parse a header, or 252 | /// might already have one from a parse operation. For example, when 253 | /// deserializing an `Option`, if the value is NOT null, the parsed header 254 | /// is retained by the deserializer passed into `deserialize_some`. This trait 255 | /// abstracts over the presence or absence of a parsed header. 256 | trait ReadHeader<'de>: Sized { 257 | /// Read a header, possibly from the `input`. 258 | fn read_header(self, input: &mut &'de [u8]) -> Result, parse::Error>; 259 | } 260 | 261 | impl<'de> ReadHeader<'de> for TaggedHeader<'de> { 262 | /// A `TaggedHeader` can simply return itself without touching the input 263 | #[inline] 264 | fn read_header(self, _input: &mut &'de [u8]) -> Result, parse::Error> { 265 | Ok(self) 266 | } 267 | } 268 | 269 | #[derive(Debug)] 270 | struct ParseHeader; 271 | 272 | impl<'de> ReadHeader<'de> for ParseHeader { 273 | /// We don't have a header; we must try to read one from the input. 274 | #[inline] 275 | fn read_header(self, input: &mut &'de [u8]) -> Result, parse::Error> { 276 | apply_parser(input, parse::read_header) 277 | } 278 | } 279 | 280 | #[derive(Debug)] 281 | struct BaseDeserializer<'a, 'de, H> { 282 | header: H, 283 | input: &'a mut &'de [u8], 284 | } 285 | 286 | type UnparsedDeserializer<'a, 'de> = BaseDeserializer<'a, 'de, ParseHeader>; 287 | type PreParsedDeserializer<'a, 'de> = BaseDeserializer<'a, 'de, TaggedHeader<'de>>; 288 | 289 | impl<'a, 'de> UnparsedDeserializer<'a, 'de> { 290 | #[inline] 291 | pub fn new(input: &'a mut &'de [u8]) -> Self { 292 | Self { 293 | input, 294 | header: ParseHeader, 295 | } 296 | } 297 | } 298 | 299 | impl<'a, 'de> PreParsedDeserializer<'a, 'de> { 300 | #[inline] 301 | fn new(header: TaggedHeader<'de>, input: &'a mut &'de [u8]) -> Self { 302 | Self { input, header } 303 | } 304 | } 305 | 306 | // Bulk strings can be up to 512 MB 307 | const MAX_BULK_LENGTH: i64 = 512 * 1024 * 1024; 308 | 309 | impl<'a, 'de, H: ReadHeader<'de>> BaseDeserializer<'a, 'de, H> { 310 | /// Read the header from a RESP value. The header consists of a single 311 | /// tag byte, followed by some kind of payload (which may not contain \r 312 | /// or \n), followed by \r\n. 313 | #[inline] 314 | fn read_header(self) -> Result, parse::Error> { 315 | let input = self.input; 316 | 317 | self.header 318 | .read_header(input) 319 | .map(|header| PreParsedDeserializer::new(header, input)) 320 | } 321 | } 322 | 323 | impl<'de, P: ReadHeader<'de>> de::Deserializer<'de> for BaseDeserializer<'_, 'de, P> { 324 | type Error = Error; 325 | 326 | forward_to_deserialize_any! { 327 | i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string 328 | bytes byte_buf unit_struct seq tuple unit 329 | tuple_struct map struct identifier ignored_any 330 | } 331 | 332 | fn deserialize_any(self, visitor: V) -> Result 333 | where 334 | V: de::Visitor<'de>, 335 | { 336 | let parsed = self.read_header()?; 337 | 338 | match parsed.header { 339 | // Simple Strings are handled as byte arrays 340 | TaggedHeader::SimpleString(payload) => visitor.visit_borrowed_bytes(payload), 341 | 342 | // Errors are handled by default as actual deserialization errors. 343 | // (see deserialize_enum for how to circumvent this) 344 | TaggedHeader::Error(payload) => Err(Error::Redis(payload.to_owned())), 345 | 346 | // Integers are parsed then handled as i64. All Redis integers are 347 | // guaranteed to fit in a signed 64 bit int. 348 | TaggedHeader::Integer(value) => visitor.visit_i64(value), 349 | 350 | // Bulk strings are handled as byte arrays 351 | TaggedHeader::BulkString(len) if len > MAX_BULK_LENGTH => Err(Error::Length), 352 | TaggedHeader::BulkString(len) => visitor.visit_borrowed_bytes({ 353 | let len = len.try_into().map_err(|_| Error::Length)?; 354 | apply_parser(parsed.input, |input| parse::read_exact(len, input))? 355 | }), 356 | 357 | // Arrays are handled as serde sequences. 358 | TaggedHeader::Array(len) => { 359 | let mut seq = SeqAccess { 360 | input: parsed.input, 361 | length: len.try_into().map_err(|_| Error::Length)?, 362 | }; 363 | 364 | match visitor.visit_seq(&mut seq) { 365 | Ok(..) if seq.length > 0 => Err(Error::UnfinishedArray), 366 | Ok(value) => Ok(value), 367 | 368 | // If there was an unexpected EOF from inside the array, 369 | // increase the size. We know that the minimum size of a 370 | // RESP value is 3 bytes, plus the array itself has a 2 371 | // byte terminator. 372 | // TODO: include both a minimum and recommended byte count 373 | // (since in practice data in an array will usually be 374 | // bulk strings, which are minimum 5 bytes) 375 | Err(Error::Parse(parse::Error::UnexpectedEof(len))) => { 376 | Err(Error::Parse(parse::Error::UnexpectedEof( 377 | len.saturating_add(seq.length.saturating_mul(3)) 378 | .saturating_add(2), 379 | ))) 380 | } 381 | 382 | Err(err) => Err(err), 383 | } 384 | } 385 | 386 | // Null (technically a Bulk String with a length of -1) is a unit 387 | TaggedHeader::Null => visitor.visit_unit(), 388 | } 389 | } 390 | 391 | #[inline] 392 | fn deserialize_bool(self, visitor: V) -> Result 393 | where 394 | V: de::Visitor<'de>, 395 | { 396 | // Use deserialize_any, but provide a variant `Visitor` that treats 397 | // 0 and 1 as true and false 398 | struct BoolVisitAdapter { 399 | inner: V, 400 | } 401 | 402 | impl<'de, V> de::Visitor<'de> for BoolVisitAdapter 403 | where 404 | V: de::Visitor<'de>, 405 | { 406 | type Value = V::Value; 407 | 408 | #[inline] 409 | fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { 410 | self.inner.expecting(formatter) 411 | } 412 | 413 | #[inline] 414 | fn visit_bool(self, v: bool) -> Result 415 | where 416 | E: de::Error, 417 | { 418 | self.inner.visit_bool(v) 419 | } 420 | 421 | #[inline] 422 | fn visit_i64(self, v: i64) -> Result 423 | where 424 | E: de::Error, 425 | { 426 | match v { 427 | 0 => self.inner.visit_bool(false), 428 | 1 => self.inner.visit_bool(true), 429 | _ => self.inner.visit_i64(v), 430 | } 431 | } 432 | 433 | #[inline] 434 | fn visit_u64(self, v: u64) -> Result 435 | where 436 | E: de::Error, 437 | { 438 | match v { 439 | 0 => self.inner.visit_bool(false), 440 | 1 => self.inner.visit_bool(true), 441 | _ => self.inner.visit_u64(v), 442 | } 443 | } 444 | 445 | #[inline] 446 | fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result 447 | where 448 | E: de::Error, 449 | { 450 | self.inner.visit_borrowed_bytes(v) 451 | } 452 | 453 | #[inline] 454 | fn visit_unit(self) -> Result 455 | where 456 | E: de::Error, 457 | { 458 | self.inner.visit_unit() 459 | } 460 | 461 | #[inline] 462 | fn visit_seq(self, seq: A) -> Result 463 | where 464 | A: de::SeqAccess<'de>, 465 | { 466 | self.inner.visit_seq(seq) 467 | } 468 | } 469 | 470 | self.deserialize_any(BoolVisitAdapter { inner: visitor }) 471 | } 472 | 473 | fn deserialize_option(self, visitor: V) -> Result 474 | where 475 | V: de::Visitor<'de>, 476 | { 477 | let parsed = self.read_header()?; 478 | 479 | match parsed.header { 480 | TaggedHeader::Null => visitor.visit_none(), 481 | _ => visitor.visit_some(parsed), 482 | } 483 | } 484 | 485 | #[inline] 486 | fn deserialize_newtype_struct( 487 | self, 488 | _name: &'static str, 489 | visitor: V, 490 | ) -> Result 491 | where 492 | V: de::Visitor<'de>, 493 | { 494 | visitor.visit_newtype_struct(self) 495 | } 496 | 497 | #[inline] 498 | fn deserialize_enum( 499 | self, 500 | name: &'static str, 501 | variants: &'static [&'static str], 502 | visitor: V, 503 | ) -> Result 504 | where 505 | V: de::Visitor<'de>, 506 | { 507 | match (name, variants) { 508 | ("Result", ["Ok", "Err"] | ["Err", "Ok"]) => { 509 | let parsed = self.read_header()?; 510 | 511 | match parsed.header { 512 | // "+OK\r\n" can be deserialized to either Result::Ok("OK") or 513 | // Result::OK(()) 514 | TaggedHeader::SimpleString(b"OK") => { 515 | visitor.visit_enum(ResultAccess::new_plain_ok()) 516 | } 517 | 518 | // "-ERR message\r\n" can be deserialized into: 519 | // Err("ERR message") 520 | TaggedHeader::Error(message) => { 521 | visitor.visit_enum(ResultAccess::new_err(message)) 522 | } 523 | 524 | // For everything else, deserialize inline as a Result::Ok 525 | _ => visitor.visit_enum(ResultAccess::new_ok(parsed)), 526 | } 527 | } 528 | _ => self.deserialize_any(visitor), 529 | } 530 | } 531 | } 532 | 533 | struct SeqAccess<'a, 'de> { 534 | length: usize, 535 | input: &'a mut &'de [u8], 536 | } 537 | 538 | impl<'de> de::SeqAccess<'de> for SeqAccess<'_, 'de> { 539 | type Error = Error; 540 | 541 | #[inline] 542 | fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> 543 | where 544 | T: de::DeserializeSeed<'de>, 545 | { 546 | self.length = match self.length.checked_sub(1) { 547 | Some(length) => length, 548 | None => return Ok(None), 549 | }; 550 | 551 | seed.deserialize(Deserializer::new(self.input)).map(Some) 552 | } 553 | 554 | #[inline] 555 | #[must_use] 556 | fn size_hint(&self) -> Option { 557 | Some(self.length) 558 | } 559 | } 560 | 561 | #[cfg(test)] 562 | mod tests { 563 | use std::fmt::Debug; 564 | use std::iter; 565 | 566 | use cool_asserts::assert_matches; 567 | use serde::Deserialize as _; 568 | 569 | use super::*; 570 | 571 | #[derive(PartialEq, Eq, Debug)] 572 | enum Data<'a> { 573 | Null, 574 | String(&'a [u8]), 575 | Integer(i64), 576 | Array(Vec>), 577 | } 578 | 579 | use Data::Null; 580 | 581 | impl<'a> From<&'a [u8]> for Data<'a> { 582 | fn from(string: &'a [u8]) -> Self { 583 | Self::String(string) 584 | } 585 | } 586 | 587 | impl<'a> From<&'a str> for Data<'a> { 588 | fn from(string: &'a str) -> Self { 589 | string.as_bytes().into() 590 | } 591 | } 592 | 593 | impl From for Data<'_> { 594 | fn from(value: i64) -> Self { 595 | Self::Integer(value) 596 | } 597 | } 598 | 599 | impl<'a, T: Into>, const N: usize> From<[T; N]> for Data<'a> { 600 | fn from(array: [T; N]) -> Self { 601 | Self::Array(array.into_iter().map(Into::into).collect()) 602 | } 603 | } 604 | 605 | impl<'de> de::Deserialize<'de> for Data<'de> { 606 | fn deserialize(deserializer: D) -> Result 607 | where 608 | D: serde::Deserializer<'de>, 609 | { 610 | struct Visitor; 611 | 612 | impl<'de> de::Visitor<'de> for Visitor { 613 | type Value = Data<'de>; 614 | 615 | fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 616 | write!(f, "a byte string, integer, or array") 617 | } 618 | 619 | fn visit_borrowed_bytes(self, v: &'de [u8]) -> Result 620 | where 621 | E: de::Error, 622 | { 623 | Ok(Data::String(v)) 624 | } 625 | 626 | fn visit_i64(self, v: i64) -> Result 627 | where 628 | E: de::Error, 629 | { 630 | Ok(Data::Integer(v)) 631 | } 632 | 633 | fn visit_seq(self, mut seq: A) -> Result 634 | where 635 | A: de::SeqAccess<'de>, 636 | { 637 | let mut vec = Vec::with_capacity(seq.size_hint().unwrap_or(0)); 638 | 639 | itertools::process_results( 640 | iter::from_fn(|| seq.next_element().transpose()), 641 | |iter| { 642 | vec.extend(iter); 643 | vec 644 | }, 645 | ) 646 | .map(Data::Array) 647 | } 648 | 649 | fn visit_unit(self) -> Result 650 | where 651 | E: de::Error, 652 | { 653 | Ok(Data::Null) 654 | } 655 | } 656 | 657 | deserializer.deserialize_any(Visitor) 658 | } 659 | } 660 | 661 | fn test_basic_deserialize<'a>( 662 | input: &'a (impl AsRef<[u8]> + ?Sized), 663 | expected: impl Into>, 664 | ) { 665 | let mut input = input.as_ref(); 666 | let deserializer = Deserializer::new(&mut input); 667 | let result = Data::deserialize(deserializer).expect("Failed to deserialize"); 668 | assert_eq!(result, expected.into()); 669 | assert!(input.is_empty()); 670 | } 671 | 672 | macro_rules! data_tests { 673 | ($( 674 | $name:ident: $value:literal => $expected:expr; 675 | )*) => { 676 | $( 677 | #[test] 678 | fn $name() { 679 | test_basic_deserialize($value, $expected); 680 | } 681 | )* 682 | } 683 | } 684 | 685 | data_tests! { 686 | simple_string: "+Hello, World\r\n" => "Hello, World"; 687 | empty_simple_string: "+\r\n" => ""; 688 | integer: ":1000\r\n" => 1000; 689 | negative_int: ":-1000\r\n" => -1000; 690 | bulk_string: "$5\r\nhello\r\n" => "hello"; 691 | empty_bulk_string: "$0\r\n\r\n" => ""; 692 | null: "$-1\r\n" => Null; 693 | weird_null: "$-001\r\n" => Null; 694 | array: "*2\r\n$5\r\nhello\r\n$5\r\nworld\r\n" => ["hello", "world"]; 695 | heterogeneous: b"*3\r\n:10\r\n$5\r\nhello\r\n$-1\r\n" => [Data::Integer(10), Data::String(b"hello"), Null]; 696 | nested_array: "*3\r\n*2\r\n+hello\r\n+world\r\n*2\r\n+goodbye\r\n+night\r\n*2\r\n$3\r\nabc\r\n$3\r\ndef\r\n" => [["hello", "world"], ["goodbye", "night"], ["abc", "def"]]; 697 | } 698 | 699 | #[test] 700 | fn test_bool() { 701 | let input = b":1\r\n"; 702 | let mut input = &input[..]; 703 | let deserializer = Deserializer::new(&mut input); 704 | assert!(bool::deserialize(deserializer).expect("failed to deserialize")); 705 | assert!(input.is_empty()); 706 | } 707 | 708 | #[test] 709 | fn test_options() { 710 | let input = b"*3\r\n:3\r\n$-1\r\n$5\r\nhello\r\n"; 711 | let mut input = &input[..]; 712 | let deserializer = Deserializer::new(&mut input); 713 | let result: Vec>> = 714 | Vec::deserialize(deserializer).expect("Failed to deserialize"); 715 | 716 | assert_eq!( 717 | result, 718 | [Some(Data::Integer(3)), None, Some(Data::String(b"hello"))] 719 | ); 720 | 721 | assert!(input.is_empty()); 722 | } 723 | 724 | #[test] 725 | fn test_error() { 726 | let input = b"-ERROR bad data\r\n"; 727 | let mut input = &input[..]; 728 | let deserializer = Deserializer::new(&mut input); 729 | let result = 730 | i32::deserialize(deserializer).expect_err("deserialization unexpectedly succeeded"); 731 | 732 | assert_matches!(result, Error::Redis(message) => assert_eq!(message, b"ERROR bad data")); 733 | } 734 | 735 | fn test_result_deserializer<'a, T, E>(mut input: &'a [u8], expected: Result) 736 | where 737 | T: de::Deserialize<'a> + Eq + Debug, 738 | E: de::Deserialize<'a> + Eq + Debug, 739 | { 740 | let deserializer = Deserializer::new(&mut input); 741 | let result: Result = 742 | Result::deserialize(deserializer).expect("Failed to deserialize"); 743 | assert_eq!(result, expected); 744 | assert!(input.is_empty()); 745 | } 746 | 747 | #[test] 748 | fn test_result_ok() { 749 | test_result_deserializer::<&str, String>(b"$5\r\nhello\r\n", Ok("hello")); 750 | } 751 | 752 | #[test] 753 | fn test_result_some() { 754 | test_result_deserializer::, String>(b"$5\r\nhello\r\n", Ok(Some("hello"))); 755 | } 756 | 757 | #[test] 758 | fn test_result_none() { 759 | test_result_deserializer::, String>(b"$-1\r\n", Ok(None)); 760 | } 761 | 762 | #[test] 763 | fn test_result_unit() { 764 | test_result_deserializer::<(), String>(b"+OK\r\n", Ok(())); 765 | } 766 | 767 | #[test] 768 | fn test_result_unit_str() { 769 | test_result_deserializer::(b"+OK\r\n", Ok("OK".to_owned())); 770 | } 771 | 772 | #[test] 773 | fn test_result_error_msg() { 774 | test_result_deserializer::<&str, &str>(b"-ERROR bad data\r\n", Err("ERROR bad data")); 775 | } 776 | } 777 | -------------------------------------------------------------------------------- /src/de/parse.rs: -------------------------------------------------------------------------------- 1 | //! Low level parser implementations for RESP. 2 | //! 3 | //! The parsers and data types are available here for authors who want to write 4 | //! their own Redis abstractions, but they're designed to be very low-level. 5 | //! Usually you'll prefer to use the seredies 6 | //! [`Deserializer`][crate::de::Deserializer]. 7 | //! 8 | //! The parsers here are modeled after [nom](https://docs.rs/nom). 9 | 10 | use memchr::memchr2; 11 | use thiserror::Error; 12 | 13 | /// Parse errors that can occur while attempting to deserialize RESP data. 14 | /// 15 | /// Of especial note to protocol library authors is the 16 | /// [`UnexpectedEof`][Error::UnexpectedEof] variant; it includes a minimum 17 | /// amount of additional bytes that must be read, after which the parse can 18 | /// be retried. 19 | #[derive(Debug, Clone, Copy, Error)] 20 | #[non_exhaustive] 21 | pub enum Error { 22 | /// The data wasn't malformed, but it ended before the parse could complete. 23 | /// The value in the error is the minimum number of additional bytes 24 | /// required for a successful parse. 25 | #[error("unexpected end of input; read at least {0} more bytes and try again")] 26 | UnexpectedEof(usize), 27 | 28 | /// A newline was expected and was malformed somehow. It might have been 29 | /// entirely missing, or was only a `\n`. 30 | #[error("malformed newline during parsing (all redis newlines are \\r\\n")] 31 | MalformedNewline, 32 | 33 | /// A header tag byte wasn't one of the recognized RESP tag bytes. 34 | #[error("unrecognized tag byte {0:#x}")] 35 | BadTag(u8), 36 | 37 | /// A decimal number failed to parse. 38 | #[error("failed to parse a decimal integer")] 39 | Number, 40 | } 41 | 42 | /// A parsed RESP "header". 43 | /// 44 | /// In RESP, all data includes a header, which consists of some tag byte, 45 | /// a header payload, followed by `\r\n`. This type contains the result of 46 | /// parsing this header. For `BulkString` and `Array` objects, the header 47 | /// indicates how much additional data will be read; for the other types, 48 | /// the header is the entirety of the data. 49 | /// 50 | /// See the [protocol specification](https://redis.io/docs/reference/protocol-spec/) 51 | /// for details. 52 | #[derive(Debug, Clone, Copy)] 53 | pub enum TaggedHeader<'a> { 54 | /// A RESP [Simple String](https://redis.io/docs/reference/protocol-spec/#resp-simple-strings). 55 | /// These are often used to communicate trivial response information. 56 | SimpleString(&'a [u8]), 57 | 58 | /// A RESP [Error](https://redis.io/docs/reference/protocol-spec/#resp-errors). 59 | /// This is used in responses to indicate that something went wrong. The 60 | /// seredies `Deserializer` can automatically treat these either as 61 | /// deserialize errors or deserialize them into [`Result`] objects. 62 | Error(&'a [u8]), 63 | 64 | /// A RESP [Integer](https://redis.io/docs/reference/protocol-spec/#resp-integers). 65 | /// These are used as numeric response information. Note that redis commands 66 | /// are *always* a list of strings; integers only appear in responses. 67 | Integer(i64), 68 | 69 | /// A RESP [Bulk String](https://redis.io/docs/reference/protocol-spec/#resp-bulk-strings) 70 | /// header. Most data in RESP is sent as Bulk Strings, as they're binary-safe. 71 | /// The value in the header is the number of bytes in the bulk string. 72 | BulkString(i64), 73 | 74 | /// A RESP [Array](https://redis.io/docs/reference/protocol-spec/#resp-arrays). 75 | /// Redis commands are sent as RESP arrays, and many commands can return 76 | /// collections of data as arrays. The value in the header is the number 77 | /// of items in the array, and arrays can contain arbitrary RESP objects 78 | /// as items. 79 | Array(i64), 80 | 81 | /// Null is a special case of a Bulk String, and is used to indicate the 82 | /// absence of a value (such as a `GET` for a key that doesn't exist) 83 | Null, 84 | } 85 | 86 | /// The result of a parse, which can either be a parse error, or a successful 87 | /// parse that includes the parsed value and the unparsed tail of the input. 88 | pub type ParseResult<'a, O> = Result<(O, &'a [u8]), Error>; 89 | 90 | /// Read a single \r\n from the input. 91 | fn read_endline(input: &[u8]) -> ParseResult<'_, ()> { 92 | match input { 93 | [b'\r', b'\n', input @ ..] => Ok(((), input)), 94 | [b'\r'] => Err(Error::UnexpectedEof(1)), 95 | [] => Err(Error::UnexpectedEof(2)), 96 | _ => Err(Error::MalformedNewline), 97 | } 98 | } 99 | 100 | /** 101 | Read a tag and its payload, followed by an `\r\n`. 102 | 103 | # Example 104 | 105 | ``` 106 | use seredies::de::parse::{read_header, TaggedHeader}; 107 | use cool_asserts::assert_matches; 108 | 109 | assert_matches!( 110 | read_header(b"+OK\r\nabc"), 111 | Ok((TaggedHeader::SimpleString(b"OK"), b"abc")) 112 | ); 113 | ``` 114 | */ 115 | pub fn read_header(input: &[u8]) -> ParseResult<'_, TaggedHeader<'_>> { 116 | // Fast path for these common cases 117 | match try_split_at(input, 5) { 118 | Some((b"+OK\r\n", tail)) => return Ok((TaggedHeader::SimpleString(b"OK"), tail)), 119 | Some((b"$-1\r\n", tail)) => return Ok((TaggedHeader::Null, tail)), 120 | _ => {} 121 | }; 122 | 123 | let (&tag, input) = input.split_first().ok_or(Error::UnexpectedEof(3))?; 124 | let (payload, input) = { 125 | let idx = memchr2(b'\r', b'\n', input).ok_or(Error::UnexpectedEof(2))?; 126 | input.split_at(idx) 127 | }; 128 | let ((), input) = read_endline(input)?; 129 | 130 | match tag { 131 | b'+' => Ok(TaggedHeader::SimpleString(payload)), 132 | b'-' => Ok(TaggedHeader::Error(payload)), 133 | b':' => parse_number(payload).map(TaggedHeader::Integer), 134 | b'$' => parse_number(payload).map(|len| match len { 135 | -1 => TaggedHeader::Null, 136 | len => TaggedHeader::BulkString(len), 137 | }), 138 | b'*' => parse_number(payload).map(|len| match len { 139 | -1 => TaggedHeader::Null, 140 | len => TaggedHeader::Array(len), 141 | }), 142 | tag => Err(Error::BadTag(tag)), 143 | } 144 | .map(|header| (header, input)) 145 | } 146 | 147 | #[inline] 148 | #[must_use] 149 | fn try_split_at(input: &[u8], idx: usize) -> Option<(&[u8], &[u8])> { 150 | let head = input.get(..idx)?; 151 | let tail = input.get(idx..)?; 152 | 153 | Some((head, tail)) 154 | } 155 | 156 | /** 157 | Read precisely `length` bytes, followed by `\r\n`. 158 | 159 | # Example 160 | 161 | ``` 162 | use seredies::de::parse::{read_exact, TaggedHeader}; 163 | use cool_asserts::assert_matches; 164 | 165 | assert_matches!( 166 | read_exact(4, b"ABCD\r\n123"), 167 | Ok((b"ABCD", b"123")) 168 | ); 169 | ``` 170 | */ 171 | pub fn read_exact(length: usize, input: &[u8]) -> ParseResult<'_, &[u8]> { 172 | let (payload, input) = try_split_at(input, length) 173 | .ok_or_else(|| Error::UnexpectedEof((length - input.len()).saturating_add(2)))?; 174 | 175 | let ((), input) = read_endline(input)?; 176 | 177 | Ok((payload, input)) 178 | } 179 | 180 | #[inline] 181 | #[must_use] 182 | const fn ascii_to_digit(b: u8) -> Option { 183 | match b { 184 | b'0'..=b'9' => Some((b - b'0') as i64), 185 | _ => None, 186 | } 187 | } 188 | 189 | fn parse_number(payload: &[u8]) -> Result { 190 | let (payload, positive) = match payload.split_first().ok_or(Error::Number)? { 191 | (&b'-', tail) => (tail, false), 192 | (&b'+', tail) => (tail, true), 193 | _ => (payload, true), 194 | }; 195 | 196 | payload 197 | .iter() 198 | .copied() 199 | .try_fold(0i64, move |accum, b| { 200 | let digit = ascii_to_digit(b)?; 201 | let digit = if positive { digit } else { -digit }; 202 | let accum = accum.checked_mul(10)?; 203 | accum.checked_add(digit) 204 | }) 205 | .ok_or(Error::Number) 206 | } 207 | 208 | #[cfg(test)] 209 | mod tests { 210 | use super::*; 211 | use cool_asserts::assert_matches; 212 | 213 | macro_rules! test_cases { 214 | ($($name:ident: $input:expr, $expected:pat,)*) => {$( 215 | #[test] 216 | fn $name() { 217 | assert_matches!($input, $expected) 218 | } 219 | )*}; 220 | } 221 | 222 | mod read_endline { 223 | use super::*; 224 | 225 | macro_rules! endline_test_cases { 226 | ($($name:ident: $input:literal == $expected:pat,)*) => { 227 | test_cases!{$( 228 | $name: read_endline($input), $expected, 229 | )*} 230 | }; 231 | } 232 | 233 | endline_test_cases! { 234 | basic: b"\r\nabc" == Ok(((), b"abc")), 235 | missing: b"" == Err(Error::UnexpectedEof(2)), 236 | partial_missing: b"\r" == Err(Error::UnexpectedEof(1)), 237 | malformed1: b"\n\r" == Err(Error::MalformedNewline), 238 | malformed2: b"\r\r" == Err(Error::MalformedNewline), 239 | malformed3: b"abc" == Err(Error::MalformedNewline), 240 | } 241 | } 242 | 243 | mod read_header { 244 | use super::*; 245 | 246 | macro_rules! header_test_cases { 247 | ($($name:ident: $input:literal == $expected:pat,)*) => { 248 | test_cases!{$( 249 | $name: read_header($input), $expected, 250 | )*} 251 | }; 252 | } 253 | 254 | header_test_cases! { 255 | simple_string: b"+OK\r\nabc" == Ok((TaggedHeader::SimpleString(b"OK"), b"abc")), 256 | error: b"-CODE message\r\nabc" == Ok((TaggedHeader::Error(b"CODE message"), b"abc")), 257 | number: b":123\r\nabc" == Ok((TaggedHeader::Integer(123), b"abc")), 258 | negative: b":-123\r\nabc" == Ok((TaggedHeader::Integer(-123), b"abc")), 259 | bulk_string: b"$3\r\nabc\r\n" == Ok((TaggedHeader::BulkString(3), b"abc\r\n")), 260 | null: b"$-1\r\nabc\r\n" == Ok((TaggedHeader::Null, b"abc\r\n")), 261 | array: b"*1\r\n+OK\r\n" == Ok((TaggedHeader::Array(1), b"+OK\r\n")), 262 | null_array: b"*-1\r\nabc\r\n" == Ok((TaggedHeader::Null, b"abc\r\n")), 263 | bad_tag: b"xABC\r\n" == Err(Error::BadTag(b'x')), 264 | incomplete: b"+OK\r" == Err(Error::UnexpectedEof(1)), 265 | } 266 | } 267 | 268 | mod read_exact { 269 | use super::*; 270 | 271 | macro_rules! exact_test_cases { 272 | ($($name:ident: $amount:literal @ $input:literal == $expected:pat,)*) => { 273 | test_cases!{$( 274 | $name: read_exact($amount, $input), $expected, 275 | )*} 276 | }; 277 | } 278 | 279 | exact_test_cases! { 280 | basic: 4 @ b"abcd\r\n123" == Ok((b"abcd", b"123")), 281 | incomplete: 10 @ b"abc" == Err(Error::UnexpectedEof(9)), 282 | incomplete_newline: 4 @ b"abcd" == Err(Error::UnexpectedEof(2)), 283 | malformed: 4 @ b"abcdef\r\n" == Err(Error::MalformedNewline), 284 | } 285 | } 286 | } 287 | -------------------------------------------------------------------------------- /src/de/result.rs: -------------------------------------------------------------------------------- 1 | // Helpers for deserializing results from RESP values (and in particular 2 | // for handling `-ERR message\r\n` as an error) 3 | 4 | use serde::{de, forward_to_deserialize_any}; 5 | 6 | use super::{Error, PreParsedDeserializer}; 7 | 8 | pub(super) struct ResultAccess { 9 | access: T, 10 | } 11 | 12 | impl ResultAccess { 13 | #[inline] 14 | #[must_use] 15 | fn new(access: T) -> Self { 16 | Self { access } 17 | } 18 | } 19 | 20 | impl ResultAccess { 21 | #[inline] 22 | #[must_use] 23 | pub fn new_plain_ok() -> Self { 24 | Self::new(ResultPlainOkPattern) 25 | } 26 | } 27 | 28 | impl<'a, 'de> ResultAccess> { 29 | #[inline] 30 | #[must_use] 31 | pub fn new_ok(deserializer: PreParsedDeserializer<'a, 'de>) -> Self { 32 | Self::new(ResultOkPattern { deserializer }) 33 | } 34 | } 35 | 36 | impl<'de> ResultAccess> { 37 | #[inline] 38 | #[must_use] 39 | pub fn new_err(message: &'de [u8]) -> Self { 40 | Self::new(ResultErrPattern { message }) 41 | } 42 | } 43 | 44 | impl<'de, T: ResultAccessPattern<'de>> de::EnumAccess<'de> for ResultAccess { 45 | type Error = Error; 46 | type Variant = Self; 47 | 48 | #[inline] 49 | fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> 50 | where 51 | V: de::DeserializeSeed<'de>, 52 | { 53 | seed.deserialize(de::value::BorrowedStrDeserializer::new(T::VARIANT)) 54 | .map(|value| (value, self)) 55 | } 56 | } 57 | 58 | impl<'de, T: ResultAccessPattern<'de>> de::VariantAccess<'de> for ResultAccess { 59 | type Error = Error; 60 | 61 | #[inline] 62 | fn newtype_variant_seed(self, seed: S) -> Result 63 | where 64 | S: de::DeserializeSeed<'de>, 65 | { 66 | self.access.value(seed) 67 | } 68 | 69 | #[inline] 70 | fn unit_variant(self) -> Result<(), Self::Error> { 71 | Err(de::Error::invalid_type( 72 | de::Unexpected::NewtypeVariant, 73 | &"unit variant for Result::Ok", 74 | )) 75 | } 76 | 77 | #[inline] 78 | fn tuple_variant(self, _len: usize, visitor: V) -> Result 79 | where 80 | V: de::Visitor<'de>, 81 | { 82 | Err(de::Error::invalid_type( 83 | de::Unexpected::NewtypeVariant, 84 | &visitor, 85 | )) 86 | } 87 | 88 | #[inline] 89 | fn struct_variant( 90 | self, 91 | _fields: &'static [&'static str], 92 | visitor: V, 93 | ) -> Result 94 | where 95 | V: de::Visitor<'de>, 96 | { 97 | Err(de::Error::invalid_type( 98 | de::Unexpected::NewtypeVariant, 99 | &visitor, 100 | )) 101 | } 102 | } 103 | 104 | trait ResultAccessPattern<'de> { 105 | /// The name of the result variant being accessed, either `Ok` or `Err`. 106 | const VARIANT: &'static str; 107 | 108 | fn value(self, seed: T) -> Result 109 | where 110 | T: de::DeserializeSeed<'de>; 111 | } 112 | 113 | pub struct ResultPlainOkPattern; 114 | 115 | impl<'de> ResultAccessPattern<'de> for ResultPlainOkPattern { 116 | const VARIANT: &'static str = "Ok"; 117 | 118 | #[inline] 119 | fn value(self, seed: T) -> Result 120 | where 121 | T: de::DeserializeSeed<'de>, 122 | { 123 | seed.deserialize(self) 124 | } 125 | } 126 | 127 | impl<'de> de::Deserializer<'de> for ResultPlainOkPattern { 128 | type Error = Error; 129 | 130 | forward_to_deserialize_any! { 131 | bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string 132 | option unit_struct newtype_struct seq tuple 133 | tuple_struct map struct identifier ignored_any enum 134 | } 135 | 136 | #[inline] 137 | fn deserialize_any(self, visitor: V) -> Result 138 | where 139 | V: de::Visitor<'de>, 140 | { 141 | visitor.visit_borrowed_str("OK") 142 | } 143 | 144 | #[inline] 145 | fn deserialize_bytes(self, visitor: V) -> Result 146 | where 147 | V: de::Visitor<'de>, 148 | { 149 | visitor.visit_borrowed_bytes(b"OK") 150 | } 151 | 152 | #[inline] 153 | fn deserialize_byte_buf(self, visitor: V) -> Result 154 | where 155 | V: de::Visitor<'de>, 156 | { 157 | self.deserialize_bytes(visitor) 158 | } 159 | 160 | #[inline] 161 | fn deserialize_unit(self, visitor: V) -> Result 162 | where 163 | V: de::Visitor<'de>, 164 | { 165 | visitor.visit_unit() 166 | } 167 | } 168 | 169 | pub struct ResultOkPattern<'a, 'de> { 170 | deserializer: PreParsedDeserializer<'a, 'de>, 171 | } 172 | 173 | impl<'de> ResultAccessPattern<'de> for ResultOkPattern<'_, 'de> { 174 | const VARIANT: &'static str = "Ok"; 175 | 176 | #[inline] 177 | fn value(self, seed: T) -> Result 178 | where 179 | T: de::DeserializeSeed<'de>, 180 | { 181 | seed.deserialize(self.deserializer) 182 | } 183 | } 184 | 185 | pub struct ResultErrPattern<'de> { 186 | message: &'de [u8], 187 | } 188 | 189 | impl<'de> ResultAccessPattern<'de> for ResultErrPattern<'de> { 190 | const VARIANT: &'static str = "Err"; 191 | 192 | #[inline] 193 | fn value(self, seed: T) -> Result 194 | where 195 | T: de::DeserializeSeed<'de>, 196 | { 197 | seed.deserialize(de::value::BorrowedBytesDeserializer::new(self.message)) 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | `seredies` is a low-level implementation of 3 | [RESP](https://redis.io/docs/reference/protocol-spec/), the Redis 4 | Serialization Protocol. It is implemented using the [serde] data model, as 5 | a [`Serializer`][crate::ser::Serializer] and 6 | [`Deserializer`][crate::de::Deserializer]. 7 | 8 | See the [de] and [ser] modules for examples on how to serialize and deserialize 9 | RESP data. 10 | 11 | # Faithful 12 | 13 | `seredies` is a mostly faithful serde implementation of RESP. This means that 14 | it (mostly) doesn't try to go above and beyond what the RESP data model can 15 | express, which is mostly strings, integers, and arrays. In particular it's not 16 | capable of deserializing structs, maps, or complex enums. Instead, `seredies` 17 | provides a collection of [components][crate::components], which translate 18 | common patterns into Redis's minimal data model. This ensures that developers 19 | should never be surprised by the deserializer trying to do something 20 | unexpectedly "clever", but can opt-in to more streamlined behavior. 21 | 22 | ## Supported types 23 | 24 | These are the types supported by the [serializer][ser::Serializer] and 25 | [deserializer][de::Deserializer]. 26 | 27 | - `bool` (treated as an integer 0 or 1). 28 | - All integers (though note that RESP only supports integers in the signed 29 | 64 bit range). 30 | - Unit (treated as null). 31 | - Sequences, tuples, and tuple structs. 32 | - Bytes and string types. 33 | - See the [RedisString][crate::components::RedisString] component for a 34 | wrapper type that converts any primitive value to or from a Redis string. 35 | - RESP is totally binary safe, so it's easy to deserialize `&str` and other 36 | borrowed data from the payload. 37 | - [`Result`] (see below). 38 | - [`Option`]: similar to JSON, an [`Option`] is handled as either a null or as 39 | an untagged value 40 | - Unit variants: these are encoded as strings. 41 | 42 | ## Unsupported types 43 | 44 | - Floats. 45 | - Consider [RedisString][crate::components::RedisString] for the common 46 | case that Redis is treating your float data as a string. 47 | - Maps, structs, complex enums. 48 | - Consider [KeyValuePairs][crate::components::KeyValuePairs] for the common 49 | case that your key-value data is being treated by Redis as a flattened 50 | array of key-value pairs. 51 | 52 | If you're trying to serialize a Redis command, consider additionally using the 53 | [Command][crate::components::Command] component; it handles converting all 54 | of the command data into a list of strings, using conventions that follow the 55 | typical redis command conventions. 56 | 57 | # Errors and Results 58 | 59 | RESP includes an [error type], which is delivered in the response when 60 | something has gone wrong. By default, when deserializing, this error type 61 | is treated as a deserialize error, and appears as the 62 | [`Error::Redis`][crate::de::Error::Redis] variant when encountered. However, 63 | you can handle them by (de)serializing a [`Result`] directly; in this case, 64 | the [`Ok`] variant will contain the data, and a successfully (de)serialized 65 | [`Err`] variant will contain a redis error. 66 | 67 | Additionally, seredies ubiquitously uses the simple string "OK" to signal an 68 | uninteresting success. This pattern is so common that `seredies` supports 69 | (de)serializing it directly to an `Ok(())` [`Result`] value. 70 | 71 | [error type]: https://redis.io/docs/reference/protocol-spec/#resp-errors 72 | */ 73 | 74 | #![deny(missing_docs)] 75 | 76 | pub mod components; 77 | pub mod de; 78 | pub mod ser; 79 | -------------------------------------------------------------------------------- /src/ser.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Serde serializer for turning Rust data structures into RESP encoded data. 3 | 4 | This module contains a faithful implementation of the 5 | [Redis Serialization Protocol](https://redis.io/docs/reference/protocol-spec/). 6 | 7 | See the [crate docs][crate] for an overview of how seredies maps the RESP data 8 | model to the serde data model. 9 | 10 | # Basic example 11 | 12 | ``` 13 | use serde::Serialize; 14 | use seredies::ser::to_vec; 15 | 16 | #[derive(Serialize)] 17 | struct Data<'a>( 18 | String, 19 | i32, 20 | &'a str, 21 | Vec> 22 | ); 23 | 24 | let data = Data( 25 | "OK".to_owned(), 26 | 24, 27 | "Borrowed", 28 | Vec::from([ 29 | None, 30 | Some("Hello,".to_owned()), 31 | Some("World!".to_owned()), 32 | ]), 33 | ); 34 | 35 | let resp = to_vec(&data).expect("shouldn't fail to serialize"); 36 | 37 | assert_eq!( 38 | &resp, 39 | b"\ 40 | *4\r\n\ 41 | $2\r\nOK\r\n\ 42 | :24\r\n\ 43 | $8\r\nBorrowed\r\n\ 44 | *3\r\n\ 45 | $-1\r\n\ 46 | $6\r\nHello,\r\n\ 47 | $6\r\nWorld!\r\n\ 48 | " 49 | ) 50 | ``` 51 | 52 | # Error example 53 | 54 | It's unlikely that you'll ever need to *serialize* a `Result` object as a Redis 55 | error, but we provide for it for completeness and for pairity with the 56 | [deserializer][crate::de::Deserializer]. 57 | 58 | ``` 59 | use seredies::ser::to_vec; 60 | 61 | let data: Result, String> = Ok(Vec::from([1, 2, 3])); 62 | assert_eq!( 63 | to_vec(&data).expect("serialize shouldn't fail"), 64 | b"*3\r\n:1\r\n:2\r\n:3\r\n" 65 | ); 66 | 67 | let data: Result, String> = Err("ERROR".to_owned()); 68 | assert_eq!( 69 | to_vec(&data).expect("serialize shouldn't fail"), 70 | b"-ERROR\r\n", 71 | ); 72 | 73 | let data: Result<(), String> = Ok(()); 74 | assert_eq!( 75 | to_vec(&data).expect("serialize shouldn't fail"), 76 | b"+OK\r\n" 77 | ) 78 | ``` 79 | */ 80 | 81 | mod output; 82 | mod primitives; 83 | pub mod util; 84 | 85 | use std::io; 86 | 87 | use arrayvec::ArrayString; 88 | use paste::paste; 89 | use serde::ser; 90 | use thiserror::Error; 91 | 92 | pub use self::output::{IoWrite, Output}; 93 | use self::util::TupleSeqAdapter; 94 | 95 | /// Serialize an object as a RESP byte buffer. 96 | pub fn to_vec(data: &T) -> Result, Error> 97 | where 98 | T: ser::Serialize + ?Sized, 99 | { 100 | let mut buffer = Vec::new(); 101 | let serializer = Serializer::new(&mut buffer); 102 | data.serialize(serializer)?; 103 | Ok(buffer) 104 | } 105 | 106 | /// Serialize an object as a RESP byte buffer in a [`String`]. 107 | /// 108 | /// Note that RESP is a binary protocol, so if there is any non-UTF-8 109 | /// data in `data`, the serialization will fail with 110 | /// [`Error::Utf8Encode`]. Most data should be fine, though. 111 | pub fn to_string(data: &T) -> Result 112 | where 113 | T: ser::Serialize + ?Sized, 114 | { 115 | let mut buffer = String::new(); 116 | let serializer = Serializer::new(&mut buffer); 117 | data.serialize(serializer)?; 118 | Ok(buffer) 119 | } 120 | 121 | /// Serialize an object as RESP data to an [`io::Write`] destination, such as a 122 | /// [`File`][std::fs::File]. 123 | pub fn to_writer(data: &T, dest: impl io::Write) -> Result<(), Error> 124 | where 125 | T: ser::Serialize + ?Sized, 126 | { 127 | let mut dest = IoWrite(dest); 128 | let serializer = Serializer::new(&mut dest); 129 | data.serialize(serializer) 130 | } 131 | 132 | /// When serializing `Ok(())`, we prefer to serialize it as `"+OK\r\n"` 133 | /// instead of as a null. This trait switches the behavior for serializing a 134 | /// unit, allowing for this behavior 135 | trait UnitBehavior: Sized { 136 | #[must_use] 137 | fn unit_payload(self) -> &'static str; 138 | } 139 | 140 | /// Serialize a unit as `"$-1\r\n"` 141 | struct NullUnit; 142 | 143 | impl UnitBehavior for NullUnit { 144 | #[inline(always)] 145 | #[must_use] 146 | fn unit_payload(self) -> &'static str { 147 | "$-1\r\n" 148 | } 149 | } 150 | 151 | /// Serialize a unit as `"+OK\r\n"` 152 | struct ResultOkUnit; 153 | 154 | impl UnitBehavior for ResultOkUnit { 155 | #[inline(always)] 156 | #[must_use] 157 | fn unit_payload(self) -> &'static str { 158 | "+OK\r\n" 159 | } 160 | } 161 | 162 | macro_rules! forward_one { 163 | ($type:ident) => { 164 | forward_one!{ $type(v: $type) } 165 | }; 166 | 167 | ($method:ident $(<$Generic:ident>)? ($($arg:ident: $type:ty),*)) => { 168 | forward_one!{ $method $(<$Generic>)? ($($arg: $type),*) -> Ok } 169 | }; 170 | 171 | ($method:ident $(<$Generic:ident>)? ($($arg:ident: $type:ty),*) -> $Ret:ty) => { 172 | paste! { 173 | #[inline] 174 | fn [] $(<$Generic>)? ( 175 | self, 176 | $($arg: $type,)* 177 | ) -> Result 178 | $( 179 | where $Generic: ser::Serialize + ?Sized 180 | )? 181 | { 182 | self.inner.[]($($arg,)*) 183 | } 184 | } 185 | }; 186 | } 187 | 188 | macro_rules! forward { 189 | ($($method:ident $(<$Generic:ident>)? $( ( $($($arg:ident: $type:ty),+ $(,)?)? ) $(-> $Ret:ty)? )?)*) => { 190 | $( 191 | forward_one! { $method $(<$Generic>)? $(($($($arg : $type),+)?) $(-> $Ret)? )? } 192 | )* 193 | }; 194 | } 195 | 196 | /// A RESP Serializer. 197 | /// 198 | /// This is the core serde [`Serializer`][ser::Serializer] for RESP data. 199 | /// It writes encoded RESP data to any object implementing [`Output`]. This 200 | /// includes [`Vec`] and [`String`], as well as [`io::Write`] objects 201 | /// (via [`IoWrite`]) 202 | /// 203 | /// A single `Serializer` can be used to serialize at most one RESP value. They 204 | /// are trivially cheap to create, though, so a new `Serializer` can be used 205 | /// for each additional value. 206 | pub struct Serializer<'a, O> { 207 | inner: BaseSerializer<'a, O, NullUnit>, 208 | } 209 | 210 | impl<'a, O> Serializer<'a, O> 211 | where 212 | O: Output, 213 | { 214 | /// Create a new RESP serializer that will write the serialized data to 215 | /// the given writer. 216 | #[inline] 217 | #[must_use] 218 | pub fn new(writer: &'a mut O) -> Self { 219 | Self { 220 | inner: BaseSerializer::new(writer), 221 | } 222 | } 223 | } 224 | 225 | impl<'a, O> ser::Serializer for Serializer<'a, O> 226 | where 227 | O: Output, 228 | { 229 | type Ok = (); 230 | type Error = Error; 231 | 232 | type SerializeSeq = SerializeSeq<'a, O>; 233 | type SerializeTuple = TupleSeqAdapter>; 234 | type SerializeTupleStruct = TupleSeqAdapter>; 235 | 236 | type SerializeMap = ser::Impossible<(), Error>; 237 | type SerializeStruct = ser::Impossible<(), Error>; 238 | 239 | type SerializeStructVariant = ser::Impossible<(), Error>; 240 | type SerializeTupleVariant = ser::Impossible<(), Error>; 241 | 242 | forward! { 243 | bool 244 | i8 i16 i32 i64 i128 245 | u8 u16 u32 u64 u128 246 | f32 f64 247 | char 248 | str(v: &str) 249 | bytes(v: &[u8]) 250 | none() 251 | some(value: &T) 252 | unit() 253 | unit_struct(name: &'static str) 254 | unit_variant( 255 | name: &'static str, 256 | variant_index: u32, 257 | variant: &'static str 258 | ) 259 | newtype_struct(name: &'static str, value: &T) 260 | newtype_variant( 261 | name: &'static str, 262 | variant_index: u32, 263 | variant: &'static str, 264 | value: &T 265 | ) 266 | seq(len: Option) -> SerializeSeq 267 | tuple(len: usize) -> SerializeTuple 268 | tuple_struct(name: &'static str, len: usize) -> SerializeTupleStruct 269 | tuple_variant( 270 | name: &'static str, 271 | variant_index: u32, 272 | variant: &'static str, 273 | len: usize, 274 | ) -> SerializeTupleVariant 275 | map(len: Option) -> SerializeMap 276 | struct(name: &'static str, len: usize) -> SerializeStruct 277 | struct_variant( 278 | name: &'static str, 279 | variant_index: u32, 280 | variant: &'static str, 281 | len: usize 282 | ) -> SerializeStructVariant 283 | } 284 | 285 | #[inline] 286 | fn collect_map(self, iter: I) -> Result 287 | where 288 | K: serde::Serialize, 289 | V: serde::Serialize, 290 | I: IntoIterator, 291 | { 292 | self.inner.collect_map(iter) 293 | } 294 | 295 | #[inline] 296 | fn collect_seq(self, iter: I) -> Result 297 | where 298 | I: IntoIterator, 299 | ::Item: serde::Serialize, 300 | { 301 | self.inner.collect_seq(iter) 302 | } 303 | 304 | #[inline] 305 | fn collect_str(self, value: &T) -> Result 306 | where 307 | T: std::fmt::Display, 308 | { 309 | self.inner.collect_str(value) 310 | } 311 | } 312 | 313 | struct BaseSerializer<'a, O, U> { 314 | output: &'a mut O, 315 | unit: U, 316 | } 317 | 318 | impl<'a, O> BaseSerializer<'a, O, NullUnit> 319 | where 320 | O: Output, 321 | { 322 | #[inline] 323 | #[must_use] 324 | pub fn new(writer: &'a mut O) -> Self { 325 | Self { 326 | output: writer, 327 | unit: NullUnit, 328 | } 329 | } 330 | } 331 | 332 | impl<'a, O> BaseSerializer<'a, O, ResultOkUnit> 333 | where 334 | O: Output, 335 | { 336 | #[inline] 337 | #[must_use] 338 | pub fn new_ok(writer: &'a mut O) -> Self { 339 | Self { 340 | output: writer, 341 | unit: ResultOkUnit, 342 | } 343 | } 344 | } 345 | 346 | /// Errors that can occur during serialization. 347 | #[derive(Debug, Error)] 348 | #[non_exhaustive] 349 | pub enum Error { 350 | /// Certain types can't be serialized. The argument contains the kind of 351 | /// type that failed to serialize. 352 | #[error("can't serialize {0}")] 353 | UnsupportedType(&'static str), 354 | 355 | /// Attempted to serialize a number that was outside the range of a signed 356 | /// 64 bit integer. Redis integers always fit in this range. 357 | /// 358 | /// Don't forget that Redis commands are always a list of strings, even when 359 | /// they contain numeric data. Consider using 360 | /// [`RedisString`][crate::components::RedisString] or 361 | /// [`Command`][crate::components::Command] in this case. 362 | #[error("can't serialize numbers outside the range of a signed 64 bit integer")] 363 | NumberOutOfRange, 364 | 365 | /// Redis arrays are length-prefixed; they must know the length ahead of 366 | /// time. This error occurs when a sequence is serialized without a known 367 | /// length. Consider using [`Command`][crate::components::Command] if you're 368 | /// trying to serialize a Redis command, as it automatically handles 369 | /// efficiently computing the length of the array (without allocating). 370 | #[error("can't serialize sequences of unknown length")] 371 | UnknownSeqLength, 372 | 373 | /// Attempted to serialize too many or too few sequence elements. This error 374 | /// occurs when the number of serialized array elements differed from the 375 | /// prefix-reported length of the array. 376 | #[error("attempted to serialize too many or too few sequence elements")] 377 | BadSeqLength, 378 | 379 | /// Attempted to serialize a RESP [Simple String] or [Error] that contained 380 | /// a `\r` or `\n`. 381 | /// 382 | /// [Simple String]: 383 | /// https://redis.io/docs/reference/protocol-spec/#resp-simple-strings 384 | /// [Error]: https://redis.io/docs/reference/protocol-spec/#resp-errors 385 | #[error("attempted to serialize a Simple String that contained a \\r or \\n")] 386 | BadSimpleString, 387 | 388 | /// There was an i/o error during serialization. Generally this can only 389 | /// happen when serializing to a "real" i/o device, like a file. 390 | #[error("i/o error during serialization")] 391 | Io(#[from] io::Error), 392 | 393 | /// The data being serialized encountered some kind of error, separate from 394 | /// the RESP protocol. 395 | #[error("error from Serialize type: {0}")] 396 | Custom(String), 397 | 398 | /// Attempted to serialize something other than a string, bytes, or unit 399 | /// enum as a RESP [Error]. 400 | /// 401 | /// [Error]: https://redis.io/docs/reference/protocol-spec/#resp-errors 402 | #[error("invalid payload for a Result::Err. Must be a string or simple enum")] 403 | InvalidErrorPayload, 404 | 405 | /// Attempted to encode non-UTF-8 data. This error can only occur when the 406 | /// [`Output`] type must be UTF-8 data (such as a [`String`]); most output 407 | /// types can accept arbitrary bytes. 408 | #[error("attempted to encode non-UTF-8 data to a string-like destination")] 409 | Utf8Encode, 410 | } 411 | 412 | impl ser::Error for Error { 413 | #[inline] 414 | fn custom(msg: T) -> Self 415 | where 416 | T: std::fmt::Display, 417 | { 418 | Self::Custom(msg.to_string()) 419 | } 420 | } 421 | 422 | impl<'a, O, U> ser::Serializer for BaseSerializer<'a, O, U> 423 | where 424 | O: Output, 425 | U: UnitBehavior, 426 | { 427 | type Ok = (); 428 | type Error = Error; 429 | 430 | type SerializeSeq = SerializeSeq<'a, O>; 431 | type SerializeTuple = TupleSeqAdapter>; 432 | type SerializeTupleStruct = TupleSeqAdapter>; 433 | 434 | type SerializeMap = ser::Impossible<(), Error>; 435 | type SerializeStruct = ser::Impossible<(), Error>; 436 | 437 | type SerializeStructVariant = ser::Impossible<(), Error>; 438 | type SerializeTupleVariant = ser::Impossible<(), Error>; 439 | 440 | #[inline] 441 | fn serialize_bool(self, v: bool) -> Result { 442 | primitives::serialize_number(self.output, if v { 1 } else { 0 }) 443 | } 444 | 445 | #[inline] 446 | fn serialize_i8(self, v: i8) -> Result { 447 | primitives::serialize_number(self.output, v) 448 | } 449 | 450 | #[inline] 451 | fn serialize_i16(self, v: i16) -> Result { 452 | primitives::serialize_number(self.output, v) 453 | } 454 | 455 | #[inline] 456 | fn serialize_i32(self, v: i32) -> Result { 457 | primitives::serialize_number(self.output, v) 458 | } 459 | 460 | #[inline] 461 | fn serialize_i64(self, v: i64) -> Result { 462 | primitives::serialize_number(self.output, v) 463 | } 464 | 465 | #[inline] 466 | fn serialize_i128(self, v: i128) -> Result { 467 | primitives::serialize_number(self.output, v) 468 | } 469 | 470 | #[inline] 471 | fn serialize_u8(self, v: u8) -> Result { 472 | primitives::serialize_number(self.output, v) 473 | } 474 | 475 | #[inline] 476 | fn serialize_u16(self, v: u16) -> Result { 477 | primitives::serialize_number(self.output, v) 478 | } 479 | 480 | #[inline] 481 | fn serialize_u32(self, v: u32) -> Result { 482 | primitives::serialize_number(self.output, v) 483 | } 484 | 485 | #[inline] 486 | fn serialize_u64(self, v: u64) -> Result { 487 | primitives::serialize_number(self.output, v) 488 | } 489 | 490 | #[inline] 491 | fn serialize_u128(self, v: u128) -> Result { 492 | primitives::serialize_number(self.output, v) 493 | } 494 | 495 | #[inline] 496 | fn serialize_f32(self, _v: f32) -> Result { 497 | Err(Error::UnsupportedType("f32")) 498 | } 499 | 500 | #[inline] 501 | fn serialize_f64(self, _v: f64) -> Result { 502 | Err(Error::UnsupportedType("f64")) 503 | } 504 | 505 | #[inline] 506 | fn serialize_char(self, v: char) -> Result { 507 | let mut buf = [0; 4]; 508 | self.serialize_str(v.encode_utf8(&mut buf)) 509 | } 510 | 511 | #[inline] 512 | fn serialize_str(self, v: &str) -> Result { 513 | primitives::serialize_bulk_string(self.output, v) 514 | } 515 | 516 | fn collect_str(self, value: &T) -> Result 517 | where 518 | T: std::fmt::Display, 519 | { 520 | use std::fmt::Write as _; 521 | 522 | // We assume that things that need to be collected as strings are 523 | // usually pretty short, so we try first to serialize to a local buffer. 524 | // In the future we'll also have a #[no_std] switch here that fails 525 | // outright if Strings can't be created. 526 | let mut buffer: ArrayString<256> = ArrayString::new(); 527 | 528 | match write!(&mut buffer, "{value}") { 529 | Ok(_) => self.serialize_str(&buffer), 530 | Err(_) => self.serialize_str(&value.to_string()), 531 | } 532 | } 533 | 534 | #[inline] 535 | fn serialize_bytes(self, v: &[u8]) -> Result { 536 | primitives::serialize_bulk_string(self.output, v) 537 | } 538 | 539 | #[inline] 540 | fn serialize_none(self) -> Result { 541 | self.output.write_str("$-1\r\n") 542 | } 543 | 544 | #[inline] 545 | fn serialize_some(self, value: &T) -> Result 546 | where 547 | T: serde::Serialize, 548 | { 549 | value.serialize(self) 550 | } 551 | 552 | #[inline] 553 | fn serialize_unit(self) -> Result { 554 | self.output.write_str(self.unit.unit_payload()) 555 | } 556 | 557 | #[inline] 558 | fn serialize_unit_struct(self, _name: &'static str) -> Result { 559 | self.serialize_unit() 560 | } 561 | 562 | #[inline] 563 | fn serialize_unit_variant( 564 | self, 565 | _name: &'static str, 566 | _variant_index: u32, 567 | variant: &'static str, 568 | ) -> Result { 569 | self.serialize_str(variant) 570 | } 571 | 572 | #[inline] 573 | fn serialize_newtype_struct( 574 | self, 575 | _name: &'static str, 576 | value: &T, 577 | ) -> Result 578 | where 579 | T: serde::Serialize, 580 | { 581 | // TODO: use special newtype struct to handle simple strings 582 | value.serialize(self) 583 | } 584 | 585 | fn serialize_newtype_variant( 586 | self, 587 | name: &'static str, 588 | _variant_index: u32, 589 | variant: &'static str, 590 | value: &T, 591 | ) -> Result 592 | where 593 | T: serde::Serialize, 594 | { 595 | match (name, variant) { 596 | ("Result", "Ok") => value.serialize(BaseSerializer::new_ok(self.output)), 597 | ("Result", "Err") => value.serialize(SerializeResultError::new(self.output)), 598 | _ => Err(Error::UnsupportedType("data enum")), 599 | } 600 | } 601 | 602 | #[inline] 603 | fn serialize_seq(self, len: Option) -> Result { 604 | self.serialize_tuple(len.ok_or(Error::UnknownSeqLength)?) 605 | .map(|adapter| adapter.inner) 606 | } 607 | 608 | fn serialize_tuple(self, len: usize) -> Result { 609 | primitives::serialize_array_header(&mut *self.output, len)?; 610 | Ok(TupleSeqAdapter::new(SerializeSeq::new(self.output, len))) 611 | } 612 | 613 | #[inline] 614 | fn serialize_tuple_struct( 615 | self, 616 | _name: &'static str, 617 | len: usize, 618 | ) -> Result { 619 | self.serialize_tuple(len) 620 | } 621 | 622 | #[inline] 623 | fn serialize_tuple_variant( 624 | self, 625 | _name: &'static str, 626 | _variant_index: u32, 627 | _variant: &'static str, 628 | _len: usize, 629 | ) -> Result { 630 | Err(Error::UnsupportedType("data enum")) 631 | } 632 | 633 | #[inline] 634 | fn serialize_map(self, _len: Option) -> Result { 635 | Err(Error::UnsupportedType("map")) 636 | } 637 | 638 | #[inline] 639 | fn serialize_struct( 640 | self, 641 | _name: &'static str, 642 | _len: usize, 643 | ) -> Result { 644 | Err(Error::UnsupportedType("struct")) 645 | } 646 | 647 | #[inline] 648 | fn serialize_struct_variant( 649 | self, 650 | _name: &'static str, 651 | _variant_index: u32, 652 | _variant: &'static str, 653 | _len: usize, 654 | ) -> Result { 655 | Err(Error::UnsupportedType("enum")) 656 | } 657 | } 658 | 659 | /// The RESP sequence serializer. This is used by the [`Serializer`] to create 660 | /// RESP arrays. You should rarely need to interact with this type directly. 661 | #[derive(Debug)] 662 | pub struct SerializeSeq<'a, O> { 663 | remaining: usize, 664 | output: &'a mut O, 665 | } 666 | 667 | impl<'a, O> SerializeSeq<'a, O> 668 | where 669 | O: Output, 670 | { 671 | #[inline] 672 | #[must_use] 673 | fn new(output: &'a mut O, length: usize) -> Self { 674 | Self { 675 | output, 676 | remaining: length, 677 | } 678 | } 679 | } 680 | 681 | impl ser::SerializeSeq for SerializeSeq<'_, O> 682 | where 683 | O: Output, 684 | { 685 | type Ok = (); 686 | type Error = Error; 687 | 688 | #[inline] 689 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> 690 | where 691 | T: serde::Serialize, 692 | { 693 | let reserve = primitives::estimate_array_reservation(self.remaining); 694 | 695 | match self.remaining.checked_sub(1) { 696 | Some(remain) => self.remaining = remain, 697 | None => return Err(Error::BadSeqLength), 698 | } 699 | 700 | self.output.reserve(reserve); 701 | value.serialize(BaseSerializer::new(self.output)) 702 | } 703 | 704 | #[inline] 705 | fn end(self) -> Result { 706 | match self.remaining { 707 | 0 => Ok(()), 708 | _ => Err(Error::BadSeqLength), 709 | } 710 | } 711 | } 712 | 713 | /// An error serializer only accepts strings / bytes or similar payloads and 714 | /// serializes them as Redis error values. 715 | struct SerializeResultError { 716 | output: O, 717 | } 718 | 719 | impl SerializeResultError { 720 | pub fn new(output: O) -> Self { 721 | Self { output } 722 | } 723 | } 724 | 725 | impl ser::Serializer for SerializeResultError { 726 | type Ok = (); 727 | type Error = Error; 728 | 729 | type SerializeSeq = ser::Impossible<(), Error>; 730 | type SerializeTuple = ser::Impossible<(), Error>; 731 | type SerializeTupleStruct = ser::Impossible<(), Error>; 732 | type SerializeTupleVariant = ser::Impossible<(), Error>; 733 | type SerializeMap = ser::Impossible<(), Error>; 734 | type SerializeStruct = ser::Impossible<(), Error>; 735 | type SerializeStructVariant = ser::Impossible<(), Error>; 736 | 737 | #[inline] 738 | fn serialize_bool(self, _v: bool) -> Result { 739 | Err(Error::InvalidErrorPayload) 740 | } 741 | 742 | #[inline] 743 | fn serialize_i8(self, _v: i8) -> Result { 744 | Err(Error::InvalidErrorPayload) 745 | } 746 | 747 | #[inline] 748 | fn serialize_i16(self, _v: i16) -> Result { 749 | Err(Error::InvalidErrorPayload) 750 | } 751 | 752 | #[inline] 753 | fn serialize_i32(self, _v: i32) -> Result { 754 | Err(Error::InvalidErrorPayload) 755 | } 756 | 757 | #[inline] 758 | fn serialize_i64(self, _v: i64) -> Result { 759 | Err(Error::InvalidErrorPayload) 760 | } 761 | 762 | #[inline] 763 | fn serialize_i128(self, _v: i128) -> Result { 764 | Err(Error::InvalidErrorPayload) 765 | } 766 | 767 | #[inline] 768 | fn serialize_u8(self, _v: u8) -> Result { 769 | Err(Error::InvalidErrorPayload) 770 | } 771 | 772 | #[inline] 773 | fn serialize_u16(self, _v: u16) -> Result { 774 | Err(Error::InvalidErrorPayload) 775 | } 776 | 777 | #[inline] 778 | fn serialize_u32(self, _v: u32) -> Result { 779 | Err(Error::InvalidErrorPayload) 780 | } 781 | 782 | #[inline] 783 | fn serialize_u64(self, _v: u64) -> Result { 784 | Err(Error::InvalidErrorPayload) 785 | } 786 | 787 | #[inline] 788 | fn serialize_u128(self, _v: u128) -> Result { 789 | Err(Error::InvalidErrorPayload) 790 | } 791 | 792 | #[inline] 793 | fn serialize_f32(self, _v: f32) -> Result { 794 | Err(Error::InvalidErrorPayload) 795 | } 796 | 797 | #[inline] 798 | fn serialize_f64(self, _v: f64) -> Result { 799 | Err(Error::InvalidErrorPayload) 800 | } 801 | 802 | #[inline] 803 | fn serialize_char(self, v: char) -> Result { 804 | let mut buf = [0; 4]; 805 | self.serialize_str(v.encode_utf8(&mut buf)) 806 | } 807 | 808 | #[inline] 809 | fn serialize_str(self, v: &str) -> Result { 810 | primitives::serialize_error(self.output, v) 811 | } 812 | 813 | fn serialize_bytes(self, v: &[u8]) -> Result { 814 | primitives::serialize_error(self.output, v) 815 | } 816 | 817 | #[inline] 818 | fn serialize_none(self) -> Result { 819 | Err(Error::InvalidErrorPayload) 820 | } 821 | 822 | #[inline] 823 | fn serialize_some(self, _v: &T) -> Result 824 | where 825 | T: serde::Serialize, 826 | { 827 | Err(Error::InvalidErrorPayload) 828 | } 829 | 830 | #[inline] 831 | fn serialize_unit(self) -> Result { 832 | Err(Error::InvalidErrorPayload) 833 | } 834 | 835 | #[inline] 836 | fn serialize_unit_struct(self, name: &'static str) -> Result { 837 | self.serialize_str(name) 838 | } 839 | 840 | #[inline] 841 | fn serialize_unit_variant( 842 | self, 843 | _name: &'static str, 844 | _variant_index: u32, 845 | variant: &'static str, 846 | ) -> Result { 847 | self.serialize_str(variant) 848 | } 849 | 850 | #[inline] 851 | fn serialize_newtype_struct( 852 | self, 853 | _name: &'static str, 854 | value: &T, 855 | ) -> Result 856 | where 857 | T: serde::Serialize, 858 | { 859 | value.serialize(self) 860 | } 861 | 862 | #[inline] 863 | fn serialize_newtype_variant( 864 | self, 865 | _name: &'static str, 866 | _variant_index: u32, 867 | _variant: &'static str, 868 | _value: &T, 869 | ) -> Result 870 | where 871 | T: serde::Serialize, 872 | { 873 | Err(Error::InvalidErrorPayload) 874 | } 875 | 876 | #[inline] 877 | fn serialize_seq(self, _len: Option) -> Result { 878 | Err(Error::InvalidErrorPayload) 879 | } 880 | 881 | #[inline] 882 | fn serialize_tuple(self, _len: usize) -> Result { 883 | Err(Error::InvalidErrorPayload) 884 | } 885 | 886 | #[inline] 887 | fn serialize_tuple_struct( 888 | self, 889 | _name: &'static str, 890 | _len: usize, 891 | ) -> Result { 892 | Err(Error::InvalidErrorPayload) 893 | } 894 | 895 | #[inline] 896 | fn serialize_tuple_variant( 897 | self, 898 | _name: &'static str, 899 | _variant_index: u32, 900 | _variant: &'static str, 901 | _len: usize, 902 | ) -> Result { 903 | Err(Error::InvalidErrorPayload) 904 | } 905 | 906 | #[inline] 907 | fn serialize_map(self, _len: Option) -> Result { 908 | Err(Error::InvalidErrorPayload) 909 | } 910 | 911 | #[inline] 912 | fn serialize_struct( 913 | self, 914 | _name: &'static str, 915 | _len: usize, 916 | ) -> Result { 917 | Err(Error::InvalidErrorPayload) 918 | } 919 | 920 | #[inline] 921 | fn serialize_struct_variant( 922 | self, 923 | _name: &'static str, 924 | _variant_index: u32, 925 | _variant: &'static str, 926 | _len: usize, 927 | ) -> Result { 928 | Err(Error::InvalidErrorPayload) 929 | } 930 | } 931 | 932 | #[cfg(test)] 933 | mod tests { 934 | use std::io::Write; 935 | 936 | use super::*; 937 | 938 | use serde::Serialize; 939 | use serde_bytes::Bytes; 940 | use tempfile::tempfile; 941 | 942 | #[derive(Debug, Serialize)] 943 | #[serde(untagged)] 944 | enum Data<'a> { 945 | Null, 946 | String(&'a Bytes), 947 | Integer(i64), 948 | Array(Vec>), 949 | } 950 | 951 | use Data::Null; 952 | 953 | impl<'a> From<&'a [u8]> for Data<'a> { 954 | fn from(value: &'a [u8]) -> Self { 955 | Self::String(Bytes::new(value)) 956 | } 957 | } 958 | 959 | impl<'a> From<&'a str> for Data<'a> { 960 | fn from(value: &'a str) -> Self { 961 | value.as_bytes().into() 962 | } 963 | } 964 | 965 | impl From for Data<'_> { 966 | fn from(value: i64) -> Self { 967 | Self::Integer(value) 968 | } 969 | } 970 | 971 | impl<'a, T: Into>, const N: usize> From<[T; N]> for Data<'a> { 972 | fn from(value: [T; N]) -> Self { 973 | Self::Array(value.into_iter().map(Into::into).collect()) 974 | } 975 | } 976 | 977 | fn test_basic_serialize<'a>( 978 | input: impl Into>, 979 | expected: &'a (impl AsRef<[u8]> + ?Sized), 980 | ) { 981 | let input: Data = input.into(); 982 | let mut out = Vec::new(); 983 | let serializer = Serializer::new(&mut out); 984 | input.serialize(serializer).expect("failed to serialize"); 985 | assert_eq!(out, expected.as_ref()) 986 | } 987 | 988 | macro_rules! data_tests { 989 | ($($name:ident: $value:expr => $expected:literal;)*) => { 990 | $( 991 | #[test] 992 | fn $name() { 993 | test_basic_serialize($value, $expected) 994 | } 995 | )* 996 | }; 997 | } 998 | 999 | data_tests! { 1000 | integer: 1000 => ":1000\r\n"; 1001 | negative_int: -1000 => ":-1000\r\n"; 1002 | bulk_string: "Hello, World!" => "$13\r\nHello, World!\r\n"; 1003 | empty_bulk_string: "" => "$0\r\n\r\n"; 1004 | null: Null => "$-1\r\n"; 1005 | array: ["hello", "world"] => "\ 1006 | *2\r\n\ 1007 | $5\r\nhello\r\n\ 1008 | $5\r\nworld\r\n\ 1009 | "; 1010 | heterogeneous: [ 1011 | Data::Integer(10), 1012 | Data::String(Bytes::new(b"hello")), 1013 | Null 1014 | ] => "\ 1015 | *3\r\n\ 1016 | :10\r\n\ 1017 | $5\r\nhello\ 1018 | \r\n$-1\r\n\ 1019 | "; 1020 | nested_array: [ 1021 | ["hello", "world"], 1022 | ["goodbye", "night"], 1023 | ["abc", "def"] 1024 | ] => "\ 1025 | *3\r\n\ 1026 | *2\r\n\ 1027 | $5\r\nhello\r\n\ 1028 | $5\r\nworld\r\n\ 1029 | *2\r\n\ 1030 | $7\r\ngoodbye\r\n\ 1031 | $5\r\nnight\r\n\ 1032 | *2\r\n\ 1033 | $3\r\nabc\r\n\ 1034 | $3\r\ndef\r\n\ 1035 | "; 1036 | } 1037 | 1038 | #[test] 1039 | fn test_bool() { 1040 | let mut buffer = Vec::new(); 1041 | let serializer = Serializer::new(&mut buffer); 1042 | true.serialize(serializer).expect("failed to serialize"); 1043 | assert_eq!(buffer, b":1\r\n"); 1044 | } 1045 | 1046 | #[test] 1047 | fn test_options() { 1048 | let mut buffer = Vec::new(); 1049 | let serializer = Serializer::new(&mut buffer); 1050 | let data = Vec::from([ 1051 | Some(Data::Integer(3)), 1052 | None, 1053 | Some(Data::String(Bytes::new(b"hello"))), 1054 | ]); 1055 | data.serialize(serializer).expect("failed to serialize"); 1056 | assert_eq!( 1057 | buffer, 1058 | b"\ 1059 | *3\r\n\ 1060 | :3\r\n\ 1061 | $-1\r\n\ 1062 | $5\r\nhello\r\n\ 1063 | " 1064 | ); 1065 | } 1066 | 1067 | fn test_result_serializer(input: Result, expected: &[u8]) 1068 | where 1069 | T: ser::Serialize, 1070 | E: ser::Serialize, 1071 | { 1072 | let mut buffer = Vec::new(); 1073 | let serializer = Serializer::new(&mut buffer); 1074 | input.serialize(serializer).expect("failed to serialize"); 1075 | assert_eq!(buffer, expected); 1076 | } 1077 | 1078 | #[test] 1079 | fn test_result_ok() { 1080 | test_result_serializer::<&str, &str>(Ok("hello"), b"$5\r\nhello\r\n"); 1081 | } 1082 | 1083 | #[test] 1084 | fn test_result_some() { 1085 | test_result_serializer::, &str>(Ok(Some("hello")), b"$5\r\nhello\r\n"); 1086 | } 1087 | 1088 | #[test] 1089 | fn test_result_none() { 1090 | test_result_serializer::, &str>(Ok(None), b"$-1\r\n"); 1091 | } 1092 | 1093 | #[test] 1094 | fn test_result_unit() { 1095 | test_result_serializer::<(), &str>(Ok(()), b"+OK\r\n"); 1096 | } 1097 | 1098 | #[test] 1099 | fn test_result_error() { 1100 | test_result_serializer::<(), &str>(Err("ERROR bad data"), b"-ERROR bad data\r\n") 1101 | } 1102 | 1103 | #[test] 1104 | fn test_result_array() { 1105 | test_result_serializer::<((), i32), &str>(Ok(((), 10)), b"*2\r\n$-1\r\n:10\r\n") 1106 | } 1107 | 1108 | #[test] 1109 | fn test_to_writer() { 1110 | use std::io::Read as _; 1111 | use std::io::Seek as _; 1112 | 1113 | let mut file = tempfile().expect("failed to create tempfile"); 1114 | 1115 | let data = Vec::from([ 1116 | Data::Integer(-5), 1117 | Data::Null, 1118 | Data::String(Bytes::new(b"data")), 1119 | ]); 1120 | 1121 | to_writer(&data, &mut file).expect("failed to serialize to a file"); 1122 | file.flush().expect("failed to flush the file"); 1123 | file.rewind().expect("failed to seek the file"); 1124 | let mut buffer = Vec::new(); 1125 | file.read_to_end(&mut buffer) 1126 | .expect("failed to read the file"); 1127 | 1128 | assert_eq!( 1129 | buffer, 1130 | b"\ 1131 | *3\r\n\ 1132 | :-5\r\n\ 1133 | $-1\r\n\ 1134 | $4\r\ndata\r\n\ 1135 | " 1136 | ) 1137 | } 1138 | } 1139 | -------------------------------------------------------------------------------- /src/ser/output.rs: -------------------------------------------------------------------------------- 1 | use std::{fmt, io}; 2 | 3 | use super::Error; 4 | 5 | /// The [`Output`] trait is used as a destination for writing bytes by the 6 | /// [`Serializer`]. It serves a similar role as [`io::Write`] or [`fmt::Write`], 7 | /// but allows for the serializer to work in `#[no_std]` contexts. 8 | pub trait Output { 9 | /// Hint that there are upcoming writes totalling this number of 10 | /// bytes. 11 | fn reserve(&mut self, count: usize); 12 | 13 | /// Append string data to the output. 14 | fn write_str(&mut self, s: &str) -> Result<(), Error>; 15 | 16 | /// Append bytes data to the output. 17 | fn write_bytes(&mut self, b: &[u8]) -> Result<(), Error>; 18 | 19 | /// Append formatted data to the output. This method allows 20 | /// [`Output`] objects to be used as the destination of a [`write!`] call. 21 | fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<(), Error> { 22 | if let Some(s) = fmt.as_str() { 23 | return self.write_str(s); 24 | } 25 | 26 | struct Adapter { 27 | output: T, 28 | result: Result<(), Error>, 29 | } 30 | 31 | impl fmt::Write for Adapter { 32 | #[inline] 33 | fn write_str(&mut self, s: &str) -> fmt::Result { 34 | self.output.write_str(s).map_err(|err| { 35 | self.result = Err(err); 36 | fmt::Error 37 | }) 38 | } 39 | } 40 | 41 | let mut adapter = Adapter { 42 | output: self, 43 | result: Ok(()), 44 | }; 45 | 46 | let res = fmt::write(&mut adapter, fmt); 47 | 48 | debug_assert!(match adapter.result.as_ref() { 49 | Ok(()) => res.is_ok(), 50 | Err(_) => res.is_err(), 51 | }); 52 | 53 | adapter.result 54 | } 55 | 56 | // TODO: vectored write support 57 | } 58 | 59 | impl Output for &mut T { 60 | #[inline] 61 | fn write_str(&mut self, s: &str) -> Result<(), Error> { 62 | T::write_str(*self, s) 63 | } 64 | 65 | #[inline] 66 | fn write_bytes(&mut self, b: &[u8]) -> Result<(), Error> { 67 | T::write_bytes(*self, b) 68 | } 69 | 70 | #[inline] 71 | fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<(), Error> { 72 | T::write_fmt(*self, fmt) 73 | } 74 | 75 | #[inline] 76 | fn reserve(&mut self, count: usize) { 77 | T::reserve(*self, count) 78 | } 79 | } 80 | 81 | impl Output for Vec { 82 | #[inline] 83 | fn write_str(&mut self, s: &str) -> Result<(), Error> { 84 | self.write_bytes(s.as_bytes()) 85 | } 86 | 87 | #[inline] 88 | fn write_bytes(&mut self, s: &[u8]) -> Result<(), Error> { 89 | self.extend_from_slice(s); 90 | Ok(()) 91 | } 92 | 93 | #[inline] 94 | fn reserve(&mut self, count: usize) { 95 | self.reserve(count) 96 | } 97 | } 98 | 99 | impl Output for String { 100 | #[inline] 101 | fn write_str(&mut self, s: &str) -> Result<(), Error> { 102 | self.push_str(s); 103 | Ok(()) 104 | } 105 | 106 | #[inline] 107 | fn write_bytes(&mut self, b: &[u8]) -> Result<(), Error> { 108 | self.write_str(std::str::from_utf8(b).map_err(|_| Error::Utf8Encode)?) 109 | } 110 | 111 | #[inline] 112 | fn reserve(&mut self, count: usize) { 113 | self.reserve(count) 114 | } 115 | } 116 | 117 | /// [`Output`] adapter type for serializing to an [`io::Write`] object, such as a file 118 | /// or pipeline. 119 | #[derive(Debug, Clone, Copy, Default)] 120 | pub struct IoWrite(pub T); 121 | 122 | impl Output for IoWrite { 123 | #[inline] 124 | fn reserve(&mut self, _count: usize) {} 125 | 126 | #[inline] 127 | fn write_str(&mut self, s: &str) -> Result<(), Error> { 128 | self.write_bytes(s.as_bytes()) 129 | } 130 | 131 | #[inline] 132 | fn write_bytes(&mut self, b: &[u8]) -> Result<(), Error> { 133 | self.0.write_all(b).map_err(Error::Io) 134 | } 135 | 136 | #[inline] 137 | fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<(), Error> { 138 | self.0.write_fmt(fmt).map_err(Error::Io) 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /src/ser/primitives.rs: -------------------------------------------------------------------------------- 1 | /*! 2 | Basic implementations of serialize primitives for RESP 3 | */ 4 | 5 | use super::{Error, Output}; 6 | 7 | /// Helper trait for writing things to `Output`, using the best available 8 | /// method. Abstracts over `str` and `[u8]`. 9 | pub trait Writable { 10 | fn write_to_output(&self, output: impl Output) -> Result<(), Error>; 11 | 12 | #[must_use] 13 | fn len(&self) -> usize; 14 | } 15 | 16 | impl Writable for [u8] { 17 | #[inline] 18 | fn write_to_output(&self, mut output: impl Output) -> Result<(), Error> { 19 | output.write_bytes(self) 20 | } 21 | 22 | #[inline] 23 | #[must_use] 24 | fn len(&self) -> usize { 25 | self.len() 26 | } 27 | } 28 | 29 | impl Writable for str { 30 | #[inline] 31 | fn write_to_output(&self, mut output: impl Output) -> Result<(), Error> { 32 | output.write_str(self) 33 | } 34 | 35 | #[inline] 36 | #[must_use] 37 | fn len(&self) -> usize { 38 | self.len() 39 | } 40 | } 41 | 42 | /** 43 | Return an estimate of how wide a number's representation is (i.e., how 44 | many characters it will take to format the number) 45 | */ 46 | #[must_use] 47 | pub const fn estimate_number_reservation(value: i64) -> usize { 48 | match value.saturating_abs().checked_ilog10() { 49 | None => 1, 50 | Some(len) if value.is_negative() => len as usize + 2, 51 | Some(len) => len as usize + 1, 52 | } 53 | } 54 | 55 | /** 56 | Write a redis header containing a numeric `value` to the `output`, using the 57 | `prefix`. This method will reserve space in the `output` sufficient to contain 58 | the header, plus additional space equal to `suffix_reserve`. 59 | */ 60 | fn serialize_header( 61 | mut output: impl Output, 62 | prefix: u8, 63 | value: impl TryInto, 64 | suffix_reserve: usize, 65 | ) -> Result<(), Error> { 66 | let prefix = prefix as char; 67 | debug_assert!("*:$".contains(prefix)); 68 | 69 | let value: i64 = value.try_into().map_err(|_| Error::NumberOutOfRange)?; 70 | 71 | let width = (estimate_number_reservation(value) as usize) 72 | .saturating_add(3) // the width of the prefix byte and the CRLF 73 | .saturating_add(suffix_reserve); 74 | 75 | output.reserve(width); 76 | write!(output, "{prefix}{value}\r\n") 77 | } 78 | 79 | /** 80 | Serialize a plain Redis number 81 | */ 82 | #[inline] 83 | pub fn serialize_number(output: impl Output, value: impl TryInto) -> Result<(), Error> { 84 | serialize_header(output, b':', value, 0) 85 | } 86 | 87 | /** 88 | Given an array of length `len`, estimate how many bytes are reasonable 89 | to reserve in an output buffer that will contain that array. This should 90 | *mostly* be the lower bound but can make certain practical estimates about 91 | the data that is *likely* to be contained. 92 | */ 93 | #[inline] 94 | #[must_use] 95 | pub const fn estimate_array_reservation(len: usize) -> usize { 96 | // By far the most common thing we serialize is a bulk string (for a 97 | // command), and the smallest bulk string (an empty one) is 6 bytes, so 98 | // that's the factor we use. 99 | len.saturating_mul(6) 100 | } 101 | 102 | /** 103 | Serialize the header for an array of `len` elements. RESP will expect `len` 104 | elements to be serialized after this header. 105 | */ 106 | #[inline] 107 | pub fn serialize_array_header(output: impl Output, len: usize) -> Result<(), Error> { 108 | serialize_header(output, b'*', len, estimate_array_reservation(len)) 109 | } 110 | 111 | /** 112 | Serialize something writable as a Bulk String 113 | */ 114 | pub fn serialize_bulk_string( 115 | mut output: impl Output, 116 | value: &(impl Writable + ?Sized), 117 | ) -> Result<(), Error> { 118 | let len = value.len(); 119 | 120 | serialize_header(&mut output, b'$', len, len.saturating_add(2))?; 121 | value.write_to_output(&mut output)?; 122 | output.write_str("\r\n") 123 | } 124 | 125 | /** 126 | When writing a simple string or error string, the payload must not include 127 | `'\r'` or `'\n'` characters. This `Output` adapter rejects any writes that 128 | include these bytes. 129 | */ 130 | struct NewlineRejector(O); 131 | 132 | impl Output for NewlineRejector { 133 | #[inline] 134 | fn reserve(&mut self, count: usize) { 135 | self.0.reserve(count) 136 | } 137 | 138 | #[inline] 139 | fn write_str(&mut self, s: &str) -> Result<(), Error> { 140 | match has_newline(s.as_bytes()) { 141 | false => self.0.write_str(s), 142 | true => Err(Error::BadSimpleString), 143 | } 144 | } 145 | 146 | #[inline] 147 | fn write_bytes(&mut self, b: &[u8]) -> Result<(), Error> { 148 | match has_newline(b) { 149 | false => self.0.write_bytes(b), 150 | true => Err(Error::BadSimpleString), 151 | } 152 | } 153 | } 154 | 155 | #[inline] 156 | #[must_use] 157 | fn has_newline(data: &[u8]) -> bool { 158 | memchr::memchr2(b'\n', b'\r', data).is_some() 159 | } 160 | 161 | /** 162 | Serialize a RESP error 163 | */ 164 | pub fn serialize_error( 165 | mut dest: impl Output, 166 | value: &(impl Writable + ?Sized), 167 | ) -> Result<(), Error> { 168 | dest.reserve(value.len().saturating_add(3)); 169 | dest.write_str("-")?; 170 | value.write_to_output(NewlineRejector(&mut dest))?; 171 | dest.write_str("\r\n") 172 | } 173 | -------------------------------------------------------------------------------- /src/ser/util.rs: -------------------------------------------------------------------------------- 1 | //! Utility types to support the serializer implementations. 2 | 3 | use serde::ser; 4 | 5 | /// Utility type intended to reduce serde serializer boilerplate. 6 | /// 7 | /// Many of the trait serialization traits are functionally identical. This 8 | /// type wraps some inner type and forwards the trait implementations 9 | /// accordingly. It forwards the following traits: 10 | /// 11 | /// - From [`ser::SerializeSeq`]: 12 | /// - [`ser::SerializeTuple`] 13 | /// - [`ser::SerializeTupleStruct`] 14 | /// - [`ser::SerializeTupleVariant`] 15 | /// - From [`ser::SerializeStruct`]: 16 | /// - [`ser::SerializeStructVariant`] 17 | #[derive(Debug, Clone, Copy, Default)] 18 | pub struct TupleSeqAdapter { 19 | /// The wrapped serializer type. This should implement 20 | /// [`ser::SerializeSeq`] or [`ser::SerializeStruct`] (or both) 21 | pub inner: T, 22 | } 23 | 24 | impl TupleSeqAdapter { 25 | /// Create a new `TupleSeqAdapter` 26 | #[inline] 27 | #[must_use] 28 | pub fn new(inner: T) -> Self { 29 | Self { inner } 30 | } 31 | } 32 | 33 | impl ser::SerializeTuple for TupleSeqAdapter { 34 | type Ok = S::Ok; 35 | type Error = S::Error; 36 | 37 | #[inline] 38 | fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> 39 | where 40 | T: serde::Serialize, 41 | { 42 | self.inner.serialize_element(value) 43 | } 44 | 45 | #[inline] 46 | fn end(self) -> Result { 47 | self.inner.end() 48 | } 49 | } 50 | 51 | impl ser::SerializeTupleStruct for TupleSeqAdapter { 52 | type Ok = S::Ok; 53 | type Error = S::Error; 54 | 55 | fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> 56 | where 57 | T: serde::Serialize, 58 | { 59 | self.inner.serialize_element(value) 60 | } 61 | 62 | fn end(self) -> Result { 63 | self.inner.end() 64 | } 65 | } 66 | 67 | impl ser::SerializeTupleVariant for TupleSeqAdapter { 68 | type Ok = S::Ok; 69 | type Error = S::Error; 70 | 71 | fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> 72 | where 73 | T: serde::Serialize, 74 | { 75 | self.inner.serialize_element(value) 76 | } 77 | 78 | fn end(self) -> Result { 79 | self.inner.end() 80 | } 81 | } 82 | 83 | impl ser::SerializeStructVariant for TupleSeqAdapter { 84 | type Ok = S::Ok; 85 | type Error = S::Error; 86 | 87 | fn serialize_field( 88 | &mut self, 89 | key: &'static str, 90 | value: &T, 91 | ) -> Result<(), Self::Error> 92 | where 93 | T: serde::Serialize, 94 | { 95 | self.inner.serialize_field(key, value) 96 | } 97 | 98 | fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { 99 | self.inner.skip_field(key) 100 | } 101 | 102 | fn end(self) -> Result { 103 | self.inner.end() 104 | } 105 | } 106 | --------------------------------------------------------------------------------