├── .gitignore ├── Cargo.toml ├── Cargo.lock ├── README.md ├── examples └── serde_valuable.rs └── src ├── imp.rs └── lib.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "serde-save" 3 | version = "0.1.1" 4 | edition = "2021" 5 | description = "the most complete serialization tree for serde" 6 | license = "MIT OR Apache-2.0" 7 | homepage = "https://crates.io/serde-save" 8 | documentation = "https://docs.rs/serde-save" 9 | repository = "https://github.com/aatifsyed/serde-save" 10 | 11 | [dependencies] 12 | serde = "1.0.198" 13 | 14 | [dev-dependencies] 15 | serde = { version = "1.0.198", features = ["derive"] } 16 | valuable = "0.1.0" 17 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "proc-macro2" 7 | version = "1.0.81" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" 10 | dependencies = [ 11 | "unicode-ident", 12 | ] 13 | 14 | [[package]] 15 | name = "quote" 16 | version = "1.0.36" 17 | source = "registry+https://github.com/rust-lang/crates.io-index" 18 | checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" 19 | dependencies = [ 20 | "proc-macro2", 21 | ] 22 | 23 | [[package]] 24 | name = "serde" 25 | version = "1.0.198" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc" 28 | dependencies = [ 29 | "serde_derive", 30 | ] 31 | 32 | [[package]] 33 | name = "serde-save" 34 | version = "0.1.1" 35 | dependencies = [ 36 | "serde", 37 | "valuable", 38 | ] 39 | 40 | [[package]] 41 | name = "serde_derive" 42 | version = "1.0.198" 43 | source = "registry+https://github.com/rust-lang/crates.io-index" 44 | checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9" 45 | dependencies = [ 46 | "proc-macro2", 47 | "quote", 48 | "syn", 49 | ] 50 | 51 | [[package]] 52 | name = "syn" 53 | version = "2.0.60" 54 | source = "registry+https://github.com/rust-lang/crates.io-index" 55 | checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" 56 | dependencies = [ 57 | "proc-macro2", 58 | "quote", 59 | "unicode-ident", 60 | ] 61 | 62 | [[package]] 63 | name = "unicode-ident" 64 | version = "1.0.12" 65 | source = "registry+https://github.com/rust-lang/crates.io-index" 66 | checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" 67 | 68 | [[package]] 69 | name = "valuable" 70 | version = "0.1.0" 71 | source = "registry+https://github.com/rust-lang/crates.io-index" 72 | checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" 73 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | The most complete serialization tree for [`serde`]. 4 | 5 | [`Save`] represents the entire [serde data model](https://serde.rs/data-model.html), 6 | including [struct names](Save::Struct::name), [field names](Save::Struct::fields), 7 | and [enum variant information](Variant). 8 | This means that it can intercept structures when they are serialized, before 9 | losslessly forwarding them. 10 | 11 | [`Save`] can optionally [persist errors](save_errors) _in the serialization tree_, 12 | instead of short-circuiting. 13 | This is a zero-cost option - see documentation on [`Save::Error`] for more. 14 | ```rust 15 | #[derive(Serialize)] 16 | struct MyStruct { 17 | system_time: SystemTime, 18 | path_buf: PathBuf, 19 | normal_string: String, 20 | } 21 | 22 | // These will fail to serialize 23 | let before_unix_epoch = SystemTime::UNIX_EPOCH - Duration::from_secs(1); 24 | let non_utf8_path = PathBuf::from(OsString::from_vec(vec![u8::MAX])); 25 | 26 | let my_struct = MyStruct { 27 | system_time: before_unix_epoch, 28 | path_buf: non_utf8_path, 29 | normal_string: String::from("this is a string"), // this is fine 30 | }; 31 | 32 | // By default errors are short-circuiting 33 | assert_eq!( 34 | save(&my_struct).unwrap_err().to_string(), 35 | "SystemTime must be later than UNIX_EPOCH" 36 | ); 37 | 38 | // But you can persist and inspect them in-tree if you prefer. 39 | assert_eq!( 40 | save_errors(&my_struct), // use this method instead 41 | Save::strukt( 42 | "MyStruct", 43 | [ 44 | ("system_time", Save::error("SystemTime must be later than UNIX_EPOCH")), 45 | ("path_buf", Save::error("path contains invalid UTF-8 characters")), 46 | ("normal_string", Save::string("this is a string")), 47 | ] 48 | ) 49 | ) 50 | ``` 51 | 52 | [`Serializer`] can also check for incorrect implementations of the serde protocol. 53 | 54 | See the documentation on [`Save`]s variants to see which invariants are checked. 55 | You can [configure this behaviour](Serializer::check_for_protocol_errors). 56 | 57 | 58 | -------------------------------------------------------------------------------- /examples/serde_valuable.rs: -------------------------------------------------------------------------------- 1 | use serde_save::{Save, Variant}; 2 | use std::{error::Error, path::PathBuf}; 3 | use valuable::{ 4 | EnumDef, Enumerable, Fields, Listable, Mappable, NamedField, NamedValues, StructDef, 5 | Structable, Tuplable, TupleDef, Valuable, Value, VariantDef, Visit, 6 | }; 7 | 8 | pub enum OwnedValue { 9 | Bool(bool), 10 | Char(char), 11 | F32(f32), 12 | F64(f64), 13 | I8(i8), 14 | I16(i16), 15 | I32(i32), 16 | I64(i64), 17 | I128(i128), 18 | Isize(isize), 19 | String(String), 20 | U8(u8), 21 | U16(u16), 22 | U32(u32), 23 | U64(u64), 24 | U128(u128), 25 | Usize(usize), 26 | Path(PathBuf), 27 | Error(Box), 28 | Listable(Box), 29 | Mappable(Box), 30 | Structable(Box), 31 | Enumerable(Box), 32 | Tuplable(Box), 33 | Unit, 34 | } 35 | 36 | impl Valuable for OwnedValue { 37 | fn as_value(&self) -> Value<'_> { 38 | match self { 39 | OwnedValue::Bool(it) => Value::Bool(*it), 40 | OwnedValue::Char(it) => Value::Char(*it), 41 | OwnedValue::F32(it) => Value::F32(*it), 42 | OwnedValue::F64(it) => Value::F64(*it), 43 | OwnedValue::I8(it) => Value::I8(*it), 44 | OwnedValue::I16(it) => Value::I16(*it), 45 | OwnedValue::I32(it) => Value::I32(*it), 46 | OwnedValue::I64(it) => Value::I64(*it), 47 | OwnedValue::I128(it) => Value::I128(*it), 48 | OwnedValue::Isize(it) => Value::Isize(*it), 49 | OwnedValue::String(it) => Value::String(it), 50 | OwnedValue::U8(it) => Value::U8(*it), 51 | OwnedValue::U16(it) => Value::U16(*it), 52 | OwnedValue::U32(it) => Value::U32(*it), 53 | OwnedValue::U64(it) => Value::U64(*it), 54 | OwnedValue::U128(it) => Value::U128(*it), 55 | OwnedValue::Usize(it) => Value::Usize(*it), 56 | OwnedValue::Path(it) => Value::Path(it), 57 | OwnedValue::Error(it) => Value::Error(&**it), 58 | OwnedValue::Listable(it) => Value::Listable(it), 59 | OwnedValue::Mappable(it) => Value::Mappable(it), 60 | OwnedValue::Structable(it) => Value::Structable(it), 61 | OwnedValue::Enumerable(it) => Value::Enumerable(it), 62 | OwnedValue::Tuplable(it) => Value::Tuplable(it), 63 | OwnedValue::Unit => Value::Unit, 64 | } 65 | } 66 | 67 | fn visit(&self, visit: &mut dyn Visit) { 68 | visit.visit_value(self.as_value()) 69 | } 70 | } 71 | 72 | impl From> for OwnedValue 73 | where 74 | E: Error + Send + Sync + 'static, 75 | { 76 | fn from(value: Save<'static, E>) -> Self { 77 | match value { 78 | Save::Bool(it) => Self::Bool(it), 79 | Save::I8(it) => Self::I8(it), 80 | Save::I16(it) => Self::I16(it), 81 | Save::I32(it) => Self::I32(it), 82 | Save::I64(it) => Self::I64(it), 83 | Save::I128(it) => Self::I128(it), 84 | Save::U8(it) => Self::U8(it), 85 | Save::U16(it) => Self::U16(it), 86 | Save::U32(it) => Self::U32(it), 87 | Save::U64(it) => Self::U64(it), 88 | Save::U128(it) => Self::U128(it), 89 | Save::F32(it) => Self::F32(it), 90 | Save::F64(it) => Self::F64(it), 91 | Save::Char(it) => Self::Char(it), 92 | Save::String(it) => Self::String(it), 93 | Save::ByteArray(_) => todo!(), 94 | Save::Option(it) => { 95 | use valuable::Variant; 96 | const NONE: VariantDef = VariantDef::new("None", Fields::Unnamed(0)); 97 | const SOME: VariantDef = VariantDef::new("Some", Fields::Unnamed(1)); 98 | struct Helper(Option); 99 | impl Enumerable for Helper { 100 | fn definition(&self) -> EnumDef<'_> { 101 | const VARIANTS: &[VariantDef] = &[NONE, SOME]; 102 | EnumDef::new_static("Option", VARIANTS) 103 | } 104 | fn variant(&self) -> Variant<'_> { 105 | match &self.0 { 106 | Some(_) => Variant::Static(&SOME), 107 | None => Variant::Static(&SOME), 108 | } 109 | } 110 | } 111 | impl Valuable for Helper { 112 | fn as_value(&self) -> Value<'_> { 113 | match &self.0 { 114 | Some(it) => it.as_value(), 115 | None => Value::Unit, 116 | } 117 | } 118 | fn visit(&self, visit: &mut dyn Visit) { 119 | visit.visit_value(self.as_value()) 120 | } 121 | } 122 | Self::Enumerable(Box::new(Helper(it.map(|it| (*it).into())))) 123 | } 124 | Save::Unit => Self::Unit, 125 | Save::UnitStruct(name) => { 126 | struct Helper(&'static str); 127 | impl Structable for Helper { 128 | fn definition(&self) -> StructDef<'_> { 129 | StructDef::new_static(self.0, Fields::Unnamed(0)) 130 | } 131 | } 132 | impl Valuable for Helper { 133 | fn as_value(&self) -> Value<'_> { 134 | Value::Unit 135 | } 136 | fn visit(&self, visit: &mut dyn Visit) { 137 | visit.visit_value(self.as_value()) 138 | } 139 | } 140 | Self::Structable(Box::new(Helper(name))) 141 | } 142 | Save::UnitVariant(Variant { 143 | name, 144 | variant_index: _, 145 | variant, 146 | }) => { 147 | struct Helper { 148 | name: &'static str, 149 | variants: [VariantDef<'static>; 1], 150 | } 151 | impl Enumerable for Helper { 152 | fn definition(&self) -> EnumDef<'_> { 153 | EnumDef::new_dynamic(self.name, &self.variants) 154 | } 155 | fn variant(&self) -> valuable::Variant<'_> { 156 | // TODO(aatifsyed): valuable::Variant::Static { &'a VariantDef<'static> } 157 | // TODO(aatifsyed): this doesn't actually follow the documentation for 158 | // VariantDef::Dynamic - we return the same variant from 159 | // `fn definition` and `fn variant` 160 | valuable::Variant::Dynamic(VariantDef::new( 161 | self.variants[0].name(), 162 | Fields::Unnamed(0), 163 | )) 164 | } 165 | } 166 | impl Valuable for Helper { 167 | fn as_value(&self) -> Value<'_> { 168 | Value::Unit 169 | } 170 | fn visit(&self, visit: &mut dyn Visit) { 171 | visit.visit_value(self.as_value()) 172 | } 173 | } 174 | Self::Enumerable(Box::new(Helper { 175 | name, 176 | variants: [VariantDef::new(variant, Fields::Unnamed(0))], 177 | })) 178 | } 179 | Save::NewTypeStruct { name, value } => { 180 | struct Helper { 181 | name: &'static str, 182 | value: OwnedValue, 183 | } 184 | impl Valuable for Helper { 185 | fn as_value(&self) -> Value<'_> { 186 | self.value.as_value() 187 | } 188 | 189 | fn visit(&self, visit: &mut dyn Visit) { 190 | visit.visit_value(self.as_value()) 191 | } 192 | } 193 | impl Structable for Helper { 194 | fn definition(&self) -> StructDef<'_> { 195 | StructDef::new_dynamic(self.name, Fields::Unnamed(1)) 196 | } 197 | } 198 | 199 | Self::Structable(Box::new(Helper { 200 | name, 201 | value: (*value).into(), 202 | })) 203 | } 204 | Save::NewTypeVariant { 205 | variant: 206 | Variant { 207 | name, 208 | variant_index: _, 209 | variant, 210 | }, 211 | value, 212 | } => { 213 | struct Helper { 214 | name: &'static str, 215 | variants: [VariantDef<'static>; 1], 216 | value: OwnedValue, 217 | } 218 | impl Valuable for Helper { 219 | fn as_value(&self) -> Value<'_> { 220 | self.value.as_value() 221 | } 222 | fn visit(&self, visit: &mut dyn Visit) { 223 | visit.visit_value(self.as_value()) 224 | } 225 | } 226 | impl Enumerable for Helper { 227 | fn definition(&self) -> EnumDef<'_> { 228 | EnumDef::new_dynamic(self.name, &self.variants) 229 | } 230 | fn variant(&self) -> valuable::Variant<'_> { 231 | // TODO(aatifsyed): same as for UnitVariant 232 | valuable::Variant::Dynamic(VariantDef::new( 233 | self.variants[0].name(), 234 | Fields::Unnamed(0), 235 | )) 236 | } 237 | } 238 | Self::Enumerable(Box::new(Helper { 239 | name, 240 | variants: [VariantDef::new(variant, Fields::Unnamed(1))], 241 | value: (*value).into(), 242 | })) 243 | } 244 | Save::Seq(it) => Self::Listable(Box::new( 245 | // TODO(aatifsyed): shouldn't need double-indirection here 246 | it.into_iter().map(OwnedValue::from).collect::>(), 247 | )), 248 | Save::Map(it) => { 249 | struct Helper(Box<[(OwnedValue, OwnedValue)]>); 250 | impl Mappable for Helper { 251 | fn size_hint(&self) -> (usize, Option) { 252 | self.0.size_hint() 253 | } 254 | } 255 | impl Valuable for Helper { 256 | fn as_value(&self) -> Value<'_> { 257 | Value::Mappable(self) 258 | } 259 | 260 | fn visit(&self, visit: &mut dyn Visit) { 261 | for (k, v) in &*self.0 { 262 | visit.visit_entry(k.as_value(), v.as_value()) 263 | } 264 | } 265 | } 266 | Self::Mappable(Box::new(Helper( 267 | it.into_iter().map(|(k, v)| (k.into(), v.into())).collect(), 268 | ))) 269 | } 270 | Save::Tuple(it) => { 271 | struct Helper(Box<[OwnedValue]>); 272 | impl Valuable for Helper { 273 | fn as_value(&self) -> Value<'_> { 274 | Value::Tuplable(self) 275 | } 276 | 277 | fn visit(&self, visit: &mut dyn Visit) { 278 | for it in &*self.0 { 279 | visit.visit_value(it.as_value()) 280 | } 281 | } 282 | } 283 | impl Tuplable for Helper { 284 | fn definition(&self) -> TupleDef { 285 | TupleDef::new_static(self.0.len()) 286 | } 287 | } 288 | Self::Tuplable(Box::new(Helper(it.into_iter().map(Into::into).collect()))) 289 | } 290 | Save::TupleStruct { name, values } => { 291 | struct Helper { 292 | name: &'static str, 293 | values: Box<[OwnedValue]>, 294 | } 295 | impl Structable for Helper { 296 | fn definition(&self) -> StructDef<'_> { 297 | StructDef::new_static(self.name, Fields::Unnamed(self.values.len())) 298 | } 299 | } 300 | impl Valuable for Helper { 301 | fn as_value(&self) -> Value<'_> { 302 | Value::Structable(self) 303 | } 304 | 305 | fn visit(&self, visit: &mut dyn Visit) { 306 | for it in &*self.values { 307 | visit.visit_value(it.as_value()) 308 | } 309 | } 310 | } 311 | Self::Structable(Box::new(Helper { 312 | name, 313 | values: values.into_iter().map(Into::into).collect(), 314 | })) 315 | } 316 | Save::TupleVariant { 317 | variant: 318 | Variant { 319 | name, 320 | variant_index: _, 321 | variant, 322 | }, 323 | values, 324 | } => { 325 | struct Helper { 326 | name: &'static str, 327 | variants: [VariantDef<'static>; 1], 328 | values: Box<[OwnedValue]>, 329 | } 330 | impl Enumerable for Helper { 331 | fn definition(&self) -> EnumDef<'_> { 332 | EnumDef::new_dynamic(self.name, &self.variants) 333 | } 334 | 335 | fn variant(&self) -> valuable::Variant<'_> { 336 | // TODO(aatifsyed): same as for UnitVariant 337 | valuable::Variant::Dynamic(VariantDef::new( 338 | self.variants[0].name(), 339 | Fields::Unnamed(0), 340 | )) 341 | } 342 | } 343 | impl Valuable for Helper { 344 | fn as_value(&self) -> Value<'_> { 345 | Value::Enumerable(self) 346 | } 347 | 348 | fn visit(&self, visit: &mut dyn Visit) { 349 | for it in &*self.values { 350 | visit.visit_value(it.as_value()) 351 | } 352 | } 353 | } 354 | Self::Enumerable(Box::new(Helper { 355 | name, 356 | variants: [VariantDef::new(variant, Fields::Unnamed(values.len()))], 357 | values: values.into_iter().map(Into::into).collect(), 358 | })) 359 | } 360 | Save::Struct { name, fields } => { 361 | struct Helper { 362 | name: &'static str, 363 | all: Box<[NamedField<'static>]>, 364 | present: Box<[NamedField<'static>]>, 365 | values: Box<[OwnedValue]>, 366 | } 367 | impl Structable for Helper { 368 | fn definition(&self) -> StructDef<'_> { 369 | StructDef::new_dynamic(self.name, Fields::Named(&self.all)) 370 | } 371 | } 372 | impl Valuable for Helper { 373 | fn as_value(&self) -> Value<'_> { 374 | Value::Structable(self) 375 | } 376 | fn visit(&self, visit: &mut dyn Visit) { 377 | visit.visit_named_fields(&NamedValues::new( 378 | &self.present, 379 | &self 380 | .values 381 | .iter() 382 | .map(valuable::Valuable::as_value) 383 | .collect::>(), 384 | )) 385 | } 386 | } 387 | Self::Structable(Box::new(Helper { 388 | name, 389 | all: collect_fields(&fields), 390 | present: fields.iter().map(|(it, _)| NamedField::new(it)).collect(), 391 | values: fields 392 | .into_iter() 393 | .flat_map(|(_, it)| it.map(Into::into)) 394 | .collect(), 395 | })) 396 | } 397 | Save::StructVariant { 398 | variant: 399 | Variant { 400 | name, 401 | variant_index: _, 402 | variant, 403 | }, 404 | fields, 405 | } => { 406 | struct Helper { 407 | name: &'static str, 408 | variants: [VariantDef<'static>; 1], 409 | all: Box<[NamedField<'static>]>, 410 | present: Box<[NamedField<'static>]>, 411 | values: Box<[OwnedValue]>, 412 | } 413 | impl Enumerable for Helper { 414 | fn definition(&self) -> EnumDef<'_> { 415 | EnumDef::new_dynamic(self.name, &self.variants) 416 | } 417 | 418 | fn variant(&self) -> valuable::Variant<'_> { 419 | valuable::Variant::Dynamic(VariantDef::new( 420 | self.variants[0].name(), 421 | Fields::Named(&self.all), 422 | )) 423 | } 424 | } 425 | impl Valuable for Helper { 426 | fn as_value(&self) -> Value<'_> { 427 | Value::Enumerable(self) 428 | } 429 | 430 | fn visit(&self, visit: &mut dyn Visit) { 431 | visit.visit_named_fields(&NamedValues::new( 432 | &self.present, 433 | &self 434 | .values 435 | .iter() 436 | .map(valuable::Valuable::as_value) 437 | .collect::>(), 438 | )) 439 | } 440 | } 441 | // TODO(aatifsyed): is there any way to plumb the field names through? 442 | const MARKER: &[NamedField] = &[NamedField::new("!missing")]; 443 | Self::Enumerable(Box::new(Helper { 444 | name, 445 | variants: [VariantDef::new(variant, Fields::Named(MARKER))], 446 | all: collect_fields(&fields), 447 | present: fields.iter().map(|(it, _)| NamedField::new(it)).collect(), 448 | values: fields 449 | .into_iter() 450 | .flat_map(|(_, it)| it.map(Into::into)) 451 | .collect(), 452 | })) 453 | } 454 | Save::Error(e) => Self::Error(Box::new(e)), 455 | } 456 | } 457 | } 458 | 459 | fn collect_fields( 460 | fields: &[(&'static str, Option>)], 461 | ) -> Box<[valuable::NamedField<'static>]> { 462 | let fields = fields 463 | .iter() 464 | .map(|(it, _)| valuable::NamedField::new(it)) 465 | .collect::>(); 466 | fields 467 | } 468 | 469 | fn main() {} 470 | -------------------------------------------------------------------------------- /src/imp.rs: -------------------------------------------------------------------------------- 1 | use crate::{Error, Save, Variant}; 2 | use core::{cmp, convert::Infallible, fmt, marker::PhantomData}; 3 | use std::collections::BTreeSet; 4 | 5 | mod sealed { 6 | pub trait Sealed {} 7 | impl Sealed for super::ShortCircuit {} 8 | impl Sealed for super::Persist {} 9 | } 10 | 11 | pub trait ErrorDiscipline: sealed::Sealed { 12 | type SaveError; 13 | fn handle(res: Result, Error>) -> Result, Error>; 14 | } 15 | 16 | pub enum ShortCircuit {} 17 | pub enum Persist {} 18 | 19 | impl ErrorDiscipline for ShortCircuit { 20 | type SaveError = Infallible; 21 | fn handle(res: Result, Error>) -> Result, Error> { 22 | res 23 | } 24 | } 25 | 26 | impl ErrorDiscipline for Persist { 27 | type SaveError = Error; 28 | fn handle(res: Result, Error>) -> Result, Error> { 29 | Ok(res.unwrap_or_else(Save::Error)) 30 | } 31 | } 32 | 33 | /// Serializer which produces [`Save`]s. 34 | /// 35 | /// See [crate documentation](mod@super) for more. 36 | pub struct Serializer { 37 | config: Config, 38 | } 39 | 40 | impl Serializer { 41 | /// Create a serializer which is: 42 | /// - [human readable](`serde::Serializer::is_human_readable`) (this is the default for serde formats). 43 | /// - NOT sensitive to [protocol errors](Self::check_for_protocol_errors). 44 | pub fn new() -> Self { 45 | Self { 46 | config: Config { 47 | is_human_readable: true, 48 | protocol_errors: false, 49 | _error_discipline: PhantomData, 50 | }, 51 | } 52 | } 53 | } 54 | 55 | impl Serializer { 56 | /// See [`serde::Serializer::is_human_readable`]. 57 | pub fn human_readable(mut self, is_human_readable: bool) -> Self { 58 | self.config.is_human_readable = is_human_readable; 59 | self 60 | } 61 | /// Whether to check for incorrect implementations of e.g [`serde::ser::SerializeSeq`]. 62 | /// See documentation on variants of [`Save`] for the invariants which are checked. 63 | pub fn check_for_protocol_errors(mut self, check: bool) -> Self { 64 | self.config.protocol_errors = check; 65 | self 66 | } 67 | /// Persist the errors in-tree. 68 | /// 69 | /// If any node's implementation of [`serde::Serialize::serialize`] fails, it 70 | /// will be recorded as a [`Save::Error`]. 71 | /// 72 | /// If there are any [protocol errors](Self::check_for_protocol_errors), they 73 | /// will be recorded as the final element(s) of the corresponding collection. 74 | pub fn save_errors(self) -> Serializer { 75 | let Self { 76 | config: 77 | Config { 78 | is_human_readable, 79 | protocol_errors, 80 | _error_discipline, 81 | }, 82 | } = self; 83 | Serializer { 84 | config: Config { 85 | is_human_readable, 86 | protocol_errors, 87 | _error_discipline: PhantomData, 88 | }, 89 | } 90 | } 91 | } 92 | 93 | impl Default for Serializer { 94 | /// See [`Self::new`]. 95 | fn default() -> Self { 96 | Self::new() 97 | } 98 | } 99 | 100 | struct Config { 101 | is_human_readable: bool, 102 | protocol_errors: bool, 103 | _error_discipline: PhantomData E>, 104 | } 105 | 106 | impl Clone for Config { 107 | fn clone(&self) -> Self { 108 | *self 109 | } 110 | } 111 | impl Copy for Config {} 112 | 113 | macro_rules! simple { 114 | ($($method:ident($ty:ty) -> $variant:ident);* $(;)?) => { 115 | $( 116 | fn $method(self, v: $ty) -> Result { 117 | Ok(Save::$variant(v)) 118 | } 119 | )* 120 | }; 121 | } 122 | 123 | impl serde::Serializer for Serializer 124 | where 125 | E: ErrorDiscipline, 126 | { 127 | type Ok = Save<'static, E::SaveError>; 128 | type Error = Error; 129 | type SerializeSeq = SerializeSeq; 130 | type SerializeTuple = SerializeTuple; 131 | type SerializeTupleStruct = SerializeTupleStruct; 132 | type SerializeTupleVariant = SerializeTupleVariant; 133 | type SerializeMap = SerializeMap; 134 | type SerializeStruct = SerializeStruct; 135 | type SerializeStructVariant = SerializeStructVariant; 136 | 137 | fn is_human_readable(&self) -> bool { 138 | self.config.is_human_readable 139 | } 140 | 141 | simple! { 142 | serialize_bool(bool) -> Bool; 143 | serialize_i8(i8) -> I8; 144 | serialize_i16(i16) -> I16; 145 | serialize_i32(i32) -> I32; 146 | serialize_i64(i64) -> I64; 147 | serialize_u8(u8) -> U8; 148 | serialize_u16(u16) -> U16; 149 | serialize_u32(u32) -> U32; 150 | serialize_u64(u64) -> U64; 151 | serialize_f32(f32) -> F32; 152 | serialize_f64(f64) -> F64; 153 | serialize_char(char) -> Char; 154 | } 155 | 156 | fn serialize_str(self, v: &str) -> Result { 157 | Ok(Save::String(v.into())) 158 | } 159 | fn collect_str(self, value: &T) -> Result { 160 | Ok(Save::String(value.to_string())) 161 | } 162 | fn serialize_bytes(self, v: &[u8]) -> Result { 163 | Ok(Save::ByteArray(v.into())) 164 | } 165 | fn serialize_none(self) -> Result { 166 | Ok(Save::Option(None)) 167 | } 168 | fn serialize_some( 169 | self, 170 | value: &T, 171 | ) -> Result { 172 | Ok(Save::Option(Some(Box::new(E::handle( 173 | value.serialize(self), 174 | )?)))) 175 | } 176 | fn serialize_unit(self) -> Result { 177 | Ok(Save::Unit) 178 | } 179 | fn serialize_unit_struct(self, name: &'static str) -> Result { 180 | Ok(Save::UnitStruct(name)) 181 | } 182 | fn serialize_unit_variant( 183 | self, 184 | name: &'static str, 185 | variant_index: u32, 186 | variant: &'static str, 187 | ) -> Result { 188 | Ok(Save::UnitVariant(Variant { 189 | name, 190 | variant_index, 191 | variant, 192 | })) 193 | } 194 | fn serialize_newtype_struct( 195 | self, 196 | name: &'static str, 197 | value: &T, 198 | ) -> Result { 199 | Ok(Save::NewTypeStruct { 200 | name, 201 | value: Box::new(E::handle(value.serialize(self))?), 202 | }) 203 | } 204 | fn serialize_newtype_variant( 205 | self, 206 | name: &'static str, 207 | variant_index: u32, 208 | variant: &'static str, 209 | value: &T, 210 | ) -> Result { 211 | Ok(Save::NewTypeVariant { 212 | variant: Variant { 213 | name, 214 | variant_index, 215 | variant, 216 | }, 217 | value: Box::new(E::handle(value.serialize(self))?), 218 | }) 219 | } 220 | fn serialize_seq(self, len: Option) -> Result { 221 | Ok(SerializeSeq { 222 | config: self.config, 223 | inner: Vec::with_capacity(len.unwrap_or_default()), 224 | expected_len: len, 225 | }) 226 | } 227 | fn serialize_tuple(self, len: usize) -> Result { 228 | Ok(SerializeTuple { 229 | config: self.config, 230 | inner: Vec::with_capacity(len), 231 | expected_len: len, 232 | }) 233 | } 234 | fn serialize_tuple_struct( 235 | self, 236 | name: &'static str, 237 | len: usize, 238 | ) -> Result { 239 | Ok(SerializeTupleStruct { 240 | expected_len: len, 241 | config: self.config, 242 | name, 243 | values: Vec::with_capacity(len), 244 | }) 245 | } 246 | fn serialize_tuple_variant( 247 | self, 248 | name: &'static str, 249 | variant_index: u32, 250 | variant: &'static str, 251 | len: usize, 252 | ) -> Result { 253 | Ok(SerializeTupleVariant { 254 | expected_len: len, 255 | config: self.config, 256 | variant: Variant { 257 | name, 258 | variant_index, 259 | variant, 260 | }, 261 | values: Vec::with_capacity(len), 262 | }) 263 | } 264 | fn serialize_map(self, len: Option) -> Result { 265 | let capacity = len.unwrap_or_default(); 266 | Ok(SerializeMap { 267 | config: self.config, 268 | expected_len: len, 269 | keys: Vec::with_capacity(capacity), 270 | values: Vec::with_capacity(capacity), 271 | }) 272 | } 273 | fn serialize_struct( 274 | self, 275 | name: &'static str, 276 | len: usize, 277 | ) -> Result { 278 | Ok(SerializeStruct { 279 | expected_len: len, 280 | config: self.config, 281 | name, 282 | fields: Vec::with_capacity(len), 283 | }) 284 | } 285 | fn serialize_struct_variant( 286 | self, 287 | name: &'static str, 288 | variant_index: u32, 289 | variant: &'static str, 290 | len: usize, 291 | ) -> Result { 292 | Ok(SerializeStructVariant { 293 | config: self.config, 294 | variant: Variant { 295 | name, 296 | variant_index, 297 | variant, 298 | }, 299 | fields: Vec::with_capacity(len), 300 | expected_len: len, 301 | }) 302 | } 303 | } 304 | 305 | fn check_length( 306 | what: &str, 307 | config: &Config, 308 | expected: usize, 309 | pushing: &mut Vec>, 310 | ) -> Result<(), Error> 311 | where 312 | E: ErrorDiscipline, 313 | { 314 | if config.protocol_errors { 315 | let actual = pushing.len(); 316 | if expected != actual { 317 | let e = Error { 318 | msg: format!( 319 | "protocol error: expected a {} of length {}, got {}", 320 | what, expected, actual 321 | ), 322 | protocol: true, 323 | }; 324 | pushing.push(E::handle(Err(e))?) 325 | } 326 | } 327 | Ok(()) 328 | } 329 | 330 | pub struct SerializeSeq { 331 | config: Config, 332 | expected_len: Option, 333 | inner: Vec>, 334 | } 335 | impl serde::ser::SerializeSeq for SerializeSeq 336 | where 337 | E: ErrorDiscipline, 338 | { 339 | type Ok = Save<'static, E::SaveError>; 340 | type Error = Error; 341 | fn serialize_element( 342 | &mut self, 343 | value: &T, 344 | ) -> Result<(), Self::Error> { 345 | self.inner.push(E::handle(value.serialize(Serializer { 346 | config: self.config, 347 | }))?); 348 | Ok(()) 349 | } 350 | fn end(mut self) -> Result { 351 | if let Some(expected_len) = self.expected_len { 352 | check_length("sequence", &self.config, expected_len, &mut self.inner)?; 353 | } 354 | Ok(Save::Seq(self.inner)) 355 | } 356 | } 357 | pub struct SerializeTuple { 358 | expected_len: usize, 359 | config: Config, 360 | inner: Vec>, 361 | } 362 | impl serde::ser::SerializeTuple for SerializeTuple 363 | where 364 | E: ErrorDiscipline, 365 | { 366 | type Ok = Save<'static, E::SaveError>; 367 | type Error = Error; 368 | fn serialize_element( 369 | &mut self, 370 | value: &T, 371 | ) -> Result<(), Self::Error> { 372 | self.inner.push(E::handle(value.serialize(Serializer { 373 | config: self.config, 374 | }))?); 375 | Ok(()) 376 | } 377 | fn end(mut self) -> Result { 378 | check_length("tuple", &self.config, self.expected_len, &mut self.inner)?; 379 | Ok(Save::Tuple(self.inner)) 380 | } 381 | } 382 | pub struct SerializeTupleStruct { 383 | expected_len: usize, 384 | config: Config, 385 | name: &'static str, 386 | values: Vec>, 387 | } 388 | impl serde::ser::SerializeTupleStruct for SerializeTupleStruct 389 | where 390 | E: ErrorDiscipline, 391 | { 392 | type Ok = Save<'static, E::SaveError>; 393 | type Error = Error; 394 | fn serialize_field( 395 | &mut self, 396 | value: &T, 397 | ) -> Result<(), Self::Error> { 398 | self.values.push(E::handle(value.serialize(Serializer { 399 | config: self.config, 400 | }))?); 401 | Ok(()) 402 | } 403 | 404 | fn end(mut self) -> Result { 405 | check_length( 406 | "tuple struct", 407 | &self.config, 408 | self.expected_len, 409 | &mut self.values, 410 | )?; 411 | Ok(Save::TupleStruct { 412 | name: self.name, 413 | values: self.values, 414 | }) 415 | } 416 | } 417 | pub struct SerializeTupleVariant { 418 | expected_len: usize, 419 | config: Config, 420 | variant: Variant<'static>, 421 | values: Vec>, 422 | } 423 | impl serde::ser::SerializeTupleVariant for SerializeTupleVariant 424 | where 425 | E: ErrorDiscipline, 426 | { 427 | type Ok = Save<'static, E::SaveError>; 428 | type Error = Error; 429 | fn serialize_field( 430 | &mut self, 431 | value: &T, 432 | ) -> Result<(), Self::Error> { 433 | self.values.push(E::handle(value.serialize(Serializer { 434 | config: self.config, 435 | }))?); 436 | Ok(()) 437 | } 438 | fn end(mut self) -> Result { 439 | check_length( 440 | "tuple variant", 441 | &self.config, 442 | self.expected_len, 443 | &mut self.values, 444 | )?; 445 | 446 | Ok(Save::TupleVariant { 447 | variant: self.variant, 448 | values: self.values, 449 | }) 450 | } 451 | } 452 | pub struct SerializeMap { 453 | expected_len: Option, 454 | config: Config, 455 | keys: Vec>, 456 | values: Vec>, 457 | } 458 | impl serde::ser::SerializeMap for SerializeMap 459 | where 460 | E: ErrorDiscipline, 461 | { 462 | type Ok = Save<'static, E::SaveError>; 463 | type Error = Error; 464 | fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> { 465 | self.keys.push(E::handle(key.serialize(Serializer { 466 | config: self.config, 467 | }))?); 468 | Ok(()) 469 | } 470 | fn serialize_value( 471 | &mut self, 472 | value: &T, 473 | ) -> Result<(), Self::Error> { 474 | self.values.push(E::handle(value.serialize(Serializer { 475 | config: self.config, 476 | }))?); 477 | Ok(()) 478 | } 479 | fn end(self) -> Result { 480 | let n_keys = self.keys.len(); 481 | let n_values = self.values.len(); 482 | let mut map = Vec::with_capacity(cmp::max(n_keys, n_values)); 483 | let mut keys = self.keys.into_iter(); 484 | let mut values = self.values.into_iter(); 485 | loop { 486 | let e = || Error { 487 | msg: format!( 488 | "protocol error: map has {} keys and {} values", 489 | n_keys, n_values 490 | ), 491 | protocol: true, 492 | }; 493 | match (keys.next(), values.next()) { 494 | (None, None) => { 495 | if let Some(expected) = self.expected_len { 496 | if self.config.protocol_errors && expected != map.len() { 497 | let e = || Error { 498 | msg: format!( 499 | "protocol error: expected a map of length {}, got {}", 500 | expected, 501 | map.len() 502 | ), 503 | protocol: true, 504 | }; 505 | map.push((E::handle(Err(e()))?, E::handle(Err(e()))?)) 506 | } 507 | } 508 | return Ok(Save::Map(map)); 509 | } 510 | (Some(key), Some(value)) => map.push((key, value)), 511 | (None, Some(value)) => map.push((E::handle(Err(e()))?, value)), 512 | (Some(key), None) => map.push((key, E::handle(Err(e()))?)), 513 | } 514 | } 515 | } 516 | } 517 | 518 | fn check( 519 | what: &str, 520 | config: &Config, 521 | expected_len: usize, 522 | fields: &mut Vec<(&'static str, Option>)>, 523 | ) -> Result<(), Error> 524 | where 525 | E: ErrorDiscipline, 526 | { 527 | if config.protocol_errors { 528 | let mut seen = BTreeSet::new(); 529 | let mut dups = Vec::new(); 530 | for name in fields.iter().map(|(it, _)| it) { 531 | let new = seen.insert(*name); 532 | if !new { 533 | dups.push(*name) 534 | } 535 | } 536 | if !dups.is_empty() { 537 | let e = Error { 538 | msg: format!( 539 | "protocol error: {} has duplicate field names: {}", 540 | what, 541 | dups.join(", ") 542 | ), 543 | protocol: true, 544 | }; 545 | fields.push(("!error", Some(E::handle(Err(e))?))) 546 | } 547 | 548 | let actual = fields.len(); 549 | if expected_len != actual { 550 | let e = Error { 551 | msg: format!( 552 | "protocol error: expected a {} of length {}, got {}", 553 | what, expected_len, actual 554 | ), 555 | protocol: true, 556 | }; 557 | fields.push(("!error", Some(E::handle(Err(e))?))) 558 | } 559 | } 560 | Ok(()) 561 | } 562 | 563 | pub struct SerializeStruct { 564 | expected_len: usize, 565 | config: Config, 566 | name: &'static str, 567 | fields: Vec<(&'static str, Option>)>, 568 | } 569 | impl serde::ser::SerializeStruct for SerializeStruct 570 | where 571 | E: ErrorDiscipline, 572 | { 573 | type Ok = Save<'static, E::SaveError>; 574 | type Error = Error; 575 | fn serialize_field( 576 | &mut self, 577 | key: &'static str, 578 | value: &T, 579 | ) -> Result<(), Self::Error> { 580 | self.fields.push(( 581 | key, 582 | Some(E::handle(value.serialize(Serializer { 583 | config: self.config, 584 | }))?), 585 | )); 586 | Ok(()) 587 | } 588 | fn end(mut self) -> Result { 589 | check("struct", &self.config, self.expected_len, &mut self.fields)?; 590 | Ok(Save::Struct { 591 | name: self.name, 592 | fields: self.fields, 593 | }) 594 | } 595 | fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { 596 | self.fields.push((key, None)); 597 | Ok(()) 598 | } 599 | } 600 | pub struct SerializeStructVariant { 601 | expected_len: usize, 602 | config: Config, 603 | variant: Variant<'static>, 604 | fields: Vec<(&'static str, Option>)>, 605 | } 606 | impl serde::ser::SerializeStructVariant for SerializeStructVariant 607 | where 608 | E: ErrorDiscipline, 609 | { 610 | type Ok = Save<'static, E::SaveError>; 611 | type Error = Error; 612 | fn serialize_field( 613 | &mut self, 614 | key: &'static str, 615 | value: &T, 616 | ) -> Result<(), Self::Error> { 617 | self.fields.push(( 618 | key, 619 | Some(E::handle(value.serialize(Serializer { 620 | config: self.config, 621 | }))?), 622 | )); 623 | Ok(()) 624 | } 625 | fn end(mut self) -> Result { 626 | check("struct", &self.config, self.expected_len, &mut self.fields)?; 627 | 628 | Ok(Save::StructVariant { 629 | variant: self.variant, 630 | fields: self.fields, 631 | }) 632 | } 633 | fn skip_field(&mut self, key: &'static str) -> Result<(), Self::Error> { 634 | self.fields.push((key, None)); 635 | Ok(()) 636 | } 637 | } 638 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | //! The most complete serialization tree for [`serde`]. 2 | //! 3 | //! [`Save`] represents the entire [serde data model](https://serde.rs/data-model.html), 4 | //! including [struct names](Save::Struct::name), [field names](Save::Struct::fields), 5 | //! and [enum variant information](Variant). 6 | //! This means that it can intercept structures when they are serialized, before 7 | //! losslessly forwarding them. 8 | //! 9 | //! [`Save`] can optionally [persist errors](save_errors) _in the serialization tree_, 10 | //! instead of short-circuiting. 11 | //! This is a zero-cost option - see documentation on [`Save::Error`] for more. 12 | //! ``` 13 | //! # use std::time::{Duration, SystemTime}; 14 | //! # use std::{ffi::OsString, os::unix::ffi::OsStringExt as _, path::PathBuf}; 15 | //! # use serde::Serialize; 16 | //! # use serde_save::{Save, save, save_errors}; 17 | //! #[derive(Serialize)] 18 | //! struct MyStruct { 19 | //! system_time: SystemTime, 20 | //! path_buf: PathBuf, 21 | //! normal_string: String, 22 | //! } 23 | //! 24 | //! // These will fail to serialize 25 | //! let before_unix_epoch = SystemTime::UNIX_EPOCH - Duration::from_secs(1); 26 | //! let non_utf8_path = PathBuf::from(OsString::from_vec(vec![u8::MAX])); 27 | //! 28 | //! let my_struct = MyStruct { 29 | //! system_time: before_unix_epoch, 30 | //! path_buf: non_utf8_path, 31 | //! normal_string: String::from("this is a string"), // this is fine 32 | //! }; 33 | //! 34 | //! // By default errors are short-circuiting 35 | //! assert_eq!( 36 | //! save(&my_struct).unwrap_err().to_string(), 37 | //! "SystemTime must be later than UNIX_EPOCH" 38 | //! ); 39 | //! 40 | //! // But you can persist and inspect them in-tree if you prefer. 41 | //! assert_eq!( 42 | //! save_errors(&my_struct), // use this method instead 43 | //! Save::strukt( 44 | //! "MyStruct", 45 | //! [ 46 | //! ("system_time", Save::error("SystemTime must be later than UNIX_EPOCH")), 47 | //! ("path_buf", Save::error("path contains invalid UTF-8 characters")), 48 | //! ("normal_string", Save::string("this is a string")), 49 | //! ] 50 | //! ) 51 | //! ) 52 | //! ``` 53 | //! 54 | //! [`Serializer`] can also check for incorrect implementations of the serde protocol. 55 | //! 56 | //! See the documentation on [`Save`]s variants to see which invariants are checked. 57 | //! You can [configure this behaviour](Serializer::check_for_protocol_errors). 58 | 59 | mod imp; 60 | 61 | pub use imp::Serializer; 62 | 63 | use core::{convert::Infallible, fmt}; 64 | use core::{iter, marker::PhantomData}; 65 | 66 | use serde::{ 67 | ser::{ 68 | Error as _, SerializeMap as _, SerializeStruct as _, SerializeStructVariant as _, 69 | SerializeTuple as _, SerializeTupleStruct as _, SerializeTupleVariant as _, 70 | }, 71 | Deserialize, Serialize, 72 | }; 73 | 74 | /// A complete [`serde`] serialization tree. 75 | /// 76 | /// Accepts a lifetime to allow users to write dynamic tests. 77 | /// 78 | /// See [`crate documentation`](mod@self) for more. 79 | #[derive(Debug, Clone, PartialEq, PartialOrd)] 80 | pub enum Save<'a, E = Infallible> { 81 | /// Primitive type, from a call to [`serde::Serializer::serialize_bool`]. 82 | Bool(bool), 83 | /// Primitive type, from a call to [`serde::Serializer::serialize_i8`]. 84 | I8(i8), 85 | /// Primitive type, from a call to [`serde::Serializer::serialize_i16`]. 86 | I16(i16), 87 | /// Primitive type, from a call to [`serde::Serializer::serialize_i32`]. 88 | I32(i32), 89 | /// Primitive type, from a call to [`serde::Serializer::serialize_i64`]. 90 | I64(i64), 91 | /// Primitive type, from a call to [`serde::Serializer::serialize_i128`]. 92 | I128(i128), 93 | /// Primitive type, from a call to [`serde::Serializer::serialize_u8`]. 94 | U8(u8), 95 | /// Primitive type, from a call to [`serde::Serializer::serialize_u16`]. 96 | U16(u16), 97 | /// Primitive type, from a call to [`serde::Serializer::serialize_u32`]. 98 | U32(u32), 99 | /// Primitive type, from a call to [`serde::Serializer::serialize_u64`]. 100 | U64(u64), 101 | /// Primitive type, from a call to [`serde::Serializer::serialize_u128`]. 102 | U128(u128), 103 | /// Primitive type, from a call to [`serde::Serializer::serialize_f32`]. 104 | F32(f32), 105 | /// Primitive type, from a call to [`serde::Serializer::serialize_f64`]. 106 | F64(f64), 107 | /// Primitive type, from a call to [`serde::Serializer::serialize_char`]. 108 | Char(char), 109 | 110 | /// A call to [`serde::Serializer::serialize_str`]. 111 | String(String), 112 | /// A call to [`serde::Serializer::serialize_bytes`]. 113 | ByteArray(Vec), 114 | /// A call to [`serde::Serializer::serialize_some`] or [`serde::Serializer::serialize_none`]. 115 | Option(Option>), 116 | 117 | /// The empty tuple, from a call to [`serde::Serializer::serialize_unit`]. 118 | Unit, 119 | /// A unit struct, from a call to [`serde::Serializer::serialize_unit_struct`]. 120 | /// ``` 121 | /// struct MyUnitStruct; 122 | /// ``` 123 | UnitStruct(&'a str), 124 | /// A unit variant of an enum, from a call to [`serde::Serializer::serialize_unit_variant`]. 125 | /// ``` 126 | /// enum MyEnum { 127 | /// MyUnitVariant, 128 | /// // ... 129 | /// } 130 | /// ``` 131 | UnitVariant(Variant<'a>), 132 | 133 | /// A tuple struct with a single unnamed field, from a call to [`serde::Serializer::serialize_newtype_struct`]. 134 | /// ``` 135 | /// # struct A; 136 | /// struct MyStruct(A); 137 | /// ``` 138 | NewTypeStruct { name: &'a str, value: Box }, 139 | /// A tuple variant of an enum with a single unnamed field, from a call to [`serde::Serializer::serialize_newtype_variant`]. 140 | /// ``` 141 | /// # struct A; 142 | /// enum MyEnum { 143 | /// MyNewTypeVariant(A), 144 | /// // ... 145 | /// } 146 | /// ``` 147 | NewTypeVariant { 148 | variant: Variant<'a>, 149 | value: Box, 150 | }, 151 | 152 | /// A dynamic sequence of values, from a call to [`serde::Serializer::serialize_seq`]. 153 | /// 154 | /// If [protocol errors] are enabled, checks that the number of items matches 155 | /// the length (if any) passed to the call to `serialize_seq`. 156 | /// 157 | /// [protocol errors]: Serializer::check_for_protocol_errors 158 | Seq(Vec), 159 | /// A dynamic mapping between values, from a call to [`serde::Serializer::serialize_map`]. 160 | /// 161 | /// If [protocol errors] are enabled, checks that the number of items matches 162 | /// the length (if any) passed to the call to `serialize_map`. 163 | /// 164 | /// Note: 165 | /// - Orphaned keys or values are always an error. 166 | /// - Duplicate map keys are always allowed. 167 | /// 168 | /// [protocol errors]: Serializer::check_for_protocol_errors 169 | Map(Vec<(Self, Self)>), 170 | 171 | /// A fixed sequence of values, from a call to [`serde::Serializer::serialize_tuple`]. 172 | /// 173 | /// ``` 174 | /// # struct A; struct B; struct C; 175 | /// (A, B, C); 176 | /// ``` 177 | /// 178 | /// If [protocol errors] are enabled, checks that the number of items matches 179 | /// the length passed to the call to `serialize_tuple`. 180 | /// 181 | /// [protocol errors]: Serializer::check_for_protocol_errors 182 | Tuple(Vec), 183 | /// A fixed sequence of unnamed fields in a struct, from a call to [`serde::Serializer::serialize_tuple_struct`]. 184 | /// 185 | /// ``` 186 | /// # struct A; struct B; struct C; 187 | /// struct MyTupleStruct(A, B, C); 188 | /// ``` 189 | /// 190 | /// If [protocol errors] are enabled, checks that the number of items matches 191 | /// the length passed to the call to `serialize_tuple_struct`. 192 | /// 193 | /// [protocol errors]: Serializer::check_for_protocol_errors 194 | TupleStruct { name: &'a str, values: Vec }, 195 | /// A fixed sequence of unnamed fields in an enum variant, from a call to [`serde::Serializer::serialize_tuple_variant`]. 196 | /// ``` 197 | /// # struct A; struct B; struct C; 198 | /// enum MyEnum { 199 | /// MyTupleVariant(A, B, C), 200 | /// // ... 201 | /// } 202 | /// ``` 203 | /// If [protocol errors] are enabled, checks that the number of items matches 204 | /// the length passed to the call to `serialize_tuple_variant`. 205 | /// 206 | /// [protocol errors]: Serializer::check_for_protocol_errors 207 | TupleVariant { 208 | variant: Variant<'a>, 209 | values: Vec, 210 | }, 211 | 212 | /// A fixed mapping from field names to values in a struct, from a call to [`serde::Serializer::serialize_struct`]. 213 | /// ``` 214 | /// struct MyStruct { 215 | /// num_yaks: usize, 216 | /// shepherd_name: String, 217 | /// } 218 | /// ``` 219 | /// If [protocol errors] are enabled, checks that: 220 | /// - the number of items matches the length passed to the call to `serialize_struct`. 221 | /// - all fields are unique 222 | /// 223 | /// [protocol errors]: Serializer::check_for_protocol_errors 224 | Struct { 225 | name: &'a str, 226 | /// RHS is [`None`] for [skip](`serde::ser::SerializeStruct::skip_field`)ed fields. 227 | /// 228 | /// For in-tree errors, the field name is `"!error"`. 229 | fields: Vec<(&'a str, Option)>, 230 | }, 231 | /// A fixed mapping from named fields to values in an enum variant, from a call to [`serde::Serializer::serialize_struct_variant`]. 232 | /// ``` 233 | /// enum MyEnum { 234 | /// MyStructVariant { 235 | /// num_yaks: usize, 236 | /// shepherd_name: String, 237 | /// }, 238 | /// // ... 239 | /// } 240 | /// ``` 241 | /// If [protocol errors] are enabled, checks that: 242 | /// - the number of items matches the length passed to the call to `serialize_struct_variant`. 243 | /// - all fields are unique 244 | /// 245 | /// [protocol errors]: Serializer::check_for_protocol_errors 246 | StructVariant { 247 | variant: Variant<'a>, 248 | /// RHS is [`None`] for [skip](`serde::ser::SerializeStructVariant::skip_field`)ed fields. 249 | /// 250 | /// For in-tree errors, the field name is `"!error"`. 251 | fields: Vec<(&'a str, Option)>, 252 | }, 253 | 254 | /// An in-tree persisted error. 255 | /// 256 | /// Note that this is _uninhabited_ by default, and you can prove it to be 257 | /// unreachable in your code: 258 | /// 259 | /// ```no_run 260 | /// # use serde_save::Save; 261 | /// 262 | /// fn stringify(save: Save) -> String { 263 | /// match save { 264 | /// // the compiler knows this branch won't be hit, so coerced the 265 | /// // empty match to String 266 | /// Save::Error(e) => match e {}, 267 | /// // ... 268 | /// # _ => todo!(), 269 | /// } 270 | /// } 271 | /// ``` 272 | /// 273 | /// However, if [errors are persisted](save_errors), you can inspect them 274 | /// ```no_run 275 | /// # use serde_save::{Save, Error}; 276 | /// let save: Save; 277 | /// # let save: Save = todo!(); 278 | /// match save { 279 | /// Save::Error(e) => { 280 | /// println!("{}", e); 281 | /// if e.is_protocol() { /* .. */ } 282 | /// } 283 | /// // ... 284 | /// # _ => todo!(), 285 | /// } 286 | /// ``` 287 | Error(E), 288 | } 289 | 290 | impl<'a> Save<'a, Error> { 291 | /// Convenience method for creating a custom error. 292 | pub fn error(msg: impl fmt::Display) -> Self { 293 | Self::Error(Error::custom(msg)) 294 | } 295 | } 296 | 297 | impl<'a, E> Save<'a, E> { 298 | /// Convenience method for creating a [`Save::Struct`] with no skipped fields. 299 | pub fn strukt(name: &'a str, fields: impl IntoIterator) -> Self 300 | where 301 | V: Into>, 302 | { 303 | Self::Struct { 304 | name, 305 | fields: fields 306 | .into_iter() 307 | .map(|(k, v)| (k, Some(v.into()))) 308 | .collect(), 309 | } 310 | } 311 | /// Convenience method for creating a [`Save::String`] 312 | pub fn string(it: impl Into) -> Self { 313 | Self::String(it.into()) 314 | } 315 | /// Convenience method for creating a [`Save::ByteArray`] 316 | pub fn bytes(it: impl Into>) -> Self { 317 | Self::ByteArray(it.into()) 318 | } 319 | } 320 | 321 | /// Save the serialization tree, returning an [`Err`] if: 322 | /// - Any node's call to [`serde::Serialize::serialize`] fails. 323 | /// - Any [`Save::Map`] has an unmatched number of keys and values 324 | /// 325 | /// [protocol errors] are ignored. 326 | /// 327 | /// [protocol errors]: Serializer::check_for_protocol_errors 328 | pub fn save(t: T) -> Result, Error> { 329 | t.serialize(Serializer::new()) 330 | } 331 | 332 | /// Save the serialization tree, annotating it with [`Save::Error`] if: 333 | /// - Any node's call to [`serde::Serialize::serialize`] fails. 334 | /// - Any node has any [protocol errors]. 335 | /// 336 | /// [protocol errors]: Serializer::check_for_protocol_errors 337 | #[must_use] 338 | pub fn save_errors(t: T) -> Save<'static, Error> { 339 | t.serialize( 340 | Serializer::new() 341 | .check_for_protocol_errors(true) 342 | .save_errors(), 343 | ) 344 | .unwrap_or_else(Save::Error) 345 | } 346 | 347 | /// An error returned by an implementation of [`serde::Serialize::serialize`], or 348 | /// [protocol error] checking. 349 | /// 350 | /// [protocol error]: Serializer::check_for_protocol_errors 351 | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone)] 352 | pub struct Error { 353 | msg: String, 354 | protocol: bool, 355 | } 356 | 357 | impl Error { 358 | /// Returns `true` if these error was caused by an incorrect implementation 359 | /// of the [`serde`] methods. 360 | /// 361 | /// See documentation on [`Save`]'s variants for the invariants that are checked. 362 | pub fn is_protocol(&self) -> bool { 363 | self.protocol 364 | } 365 | } 366 | 367 | impl fmt::Display for Error { 368 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 369 | f.write_str(&self.msg) 370 | } 371 | } 372 | 373 | impl serde::ser::Error for Error { 374 | fn custom(msg: T) -> Self { 375 | Self { 376 | msg: msg.to_string(), 377 | protocol: false, 378 | } 379 | } 380 | } 381 | 382 | impl std::error::Error for Error {} 383 | 384 | /// Information about a serialized `enum` variant. 385 | #[derive(Debug, Clone, Copy, Hash, PartialEq, Eq, PartialOrd, Ord)] 386 | pub struct Variant<'a> { 387 | /// The name of the outer `enum`. 388 | pub name: &'a str, 389 | /// The index of this variant within the outer `enum`. 390 | pub variant_index: u32, 391 | /// The name of the inhabited variant within the outer `enum` 392 | pub variant: &'a str, 393 | } 394 | 395 | macro_rules! from { 396 | ($($variant:ident($ty:ty)),* $(,)?) => { 397 | $( 398 | impl<'a, E> From<$ty> for Save<'a, E> { 399 | fn from(it: $ty) -> Self { 400 | Self::$variant(it) 401 | } 402 | } 403 | )* 404 | }; 405 | } 406 | 407 | from! { 408 | Bool(bool), 409 | I8(i8), 410 | I16(i16), 411 | I32(i32), 412 | I64(i64), 413 | I128(i128), 414 | U8(u8), 415 | U16(u16), 416 | U32(u32), 417 | U64(u64), 418 | U128(u128), 419 | F32(f32), 420 | F64(f64), 421 | Char(char), 422 | String(String), 423 | ByteArray(Vec), 424 | UnitVariant(Variant<'a>), 425 | } 426 | 427 | impl<'a, E> From<()> for Save<'a, E> { 428 | fn from(_: ()) -> Self { 429 | Self::Unit 430 | } 431 | } 432 | impl<'a, E, T> From> for Save<'a, E> 433 | where 434 | T: Into>, 435 | { 436 | fn from(it: Option) -> Self { 437 | Self::Option(it.map(Into::into).map(Box::new)) 438 | } 439 | } 440 | 441 | impl<'a, E, T> FromIterator for Save<'a, E> 442 | where 443 | T: Into>, 444 | { 445 | fn from_iter>(iter: II) -> Self { 446 | Self::Seq(iter.into_iter().map(Into::into).collect()) 447 | } 448 | } 449 | 450 | impl<'a, E, K, V> FromIterator<(K, V)> for Save<'a, E> 451 | where 452 | K: Into>, 453 | V: Into>, 454 | { 455 | fn from_iter>(iter: II) -> Self { 456 | Self::Map( 457 | iter.into_iter() 458 | .map(|(k, v)| (k.into(), v.into())) 459 | .collect(), 460 | ) 461 | } 462 | } 463 | 464 | macro_rules! from_tuple { 465 | ($($ident:ident),* $(,)?) => { 466 | #[doc(hidden)] 467 | #[allow(non_snake_case)] 468 | impl<'a, E, $($ident),*> From<($($ident,)*)> for Save<'a, E> 469 | where 470 | $($ident: Into>,)* 471 | { 472 | fn from(($($ident,)*): ($($ident,)*)) -> Self { 473 | Self::Tuple([ 474 | $($ident.into()),* 475 | ].into()) 476 | } 477 | } 478 | }; 479 | } 480 | 481 | /// You can construct a [`Save::Tuple`] using [`From`] for tuples of arities 482 | /// between 1 and 24, _except_ 2. 483 | /// 484 | /// The other implementations are hidden from rustdoc for brevity. 485 | impl<'a, E, T0, T1, T2> From<(T0, T1, T2)> for Save<'a, E> 486 | where 487 | T0: Into>, 488 | T1: Into>, 489 | T2: Into>, 490 | { 491 | fn from((t0, t1, t2): (T0, T1, T2)) -> Self { 492 | Self::Tuple([t0.into(), t1.into(), t2.into()].into()) 493 | } 494 | } 495 | 496 | from_tuple!(T0); 497 | // from_tuple!(T0, T1); // conflicting 498 | // from_tuple!(T0, T1, T2); // document it 499 | from_tuple!(T0, T1, T2, T3); 500 | from_tuple!(T0, T1, T2, T3, T4); 501 | from_tuple!(T0, T1, T2, T3, T4, T5); 502 | from_tuple!(T0, T1, T2, T3, T4, T5, T6); 503 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7); 504 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8); 505 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9); 506 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10); 507 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11); 508 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12); 509 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13); 510 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14); 511 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15); 512 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16); 513 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17); 514 | from_tuple!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18); 515 | from_tuple!( 516 | T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19 517 | ); 518 | from_tuple!( 519 | T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20 520 | ); 521 | from_tuple!( 522 | T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, 523 | T21 524 | ); 525 | from_tuple!( 526 | T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, 527 | T21, T22 528 | ); 529 | from_tuple!( 530 | T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, T17, T18, T19, T20, 531 | T21, T22, T23 532 | ); 533 | 534 | /// If [`protocol errors`](Serializer::check_for_protocol_errors) are disabled, 535 | /// this will perfectly preserve the underlying structure of the originally 536 | /// saved item. 537 | impl Serialize for Save<'static, E> 538 | where 539 | E: fmt::Display, 540 | { 541 | fn serialize(&self, serializer: S) -> Result 542 | where 543 | S: serde::Serializer, 544 | { 545 | match self { 546 | Save::Bool(it) => serializer.serialize_bool(*it), 547 | Save::I8(it) => serializer.serialize_i8(*it), 548 | Save::I16(it) => serializer.serialize_i16(*it), 549 | Save::I32(it) => serializer.serialize_i32(*it), 550 | Save::I64(it) => serializer.serialize_i64(*it), 551 | Save::I128(it) => serializer.serialize_i128(*it), 552 | Save::U8(it) => serializer.serialize_u8(*it), 553 | Save::U16(it) => serializer.serialize_u16(*it), 554 | Save::U32(it) => serializer.serialize_u32(*it), 555 | Save::U64(it) => serializer.serialize_u64(*it), 556 | Save::U128(it) => serializer.serialize_u128(*it), 557 | Save::F32(it) => serializer.serialize_f32(*it), 558 | Save::F64(it) => serializer.serialize_f64(*it), 559 | Save::Char(it) => serializer.serialize_char(*it), 560 | Save::String(it) => serializer.serialize_str(it), 561 | Save::ByteArray(it) => serializer.serialize_bytes(it), 562 | Save::Option(None) => serializer.serialize_none(), 563 | Save::Option(Some(it)) => serializer.serialize_some(it), 564 | Save::UnitStruct(it) => serializer.serialize_unit_struct(it), 565 | Save::UnitVariant(Variant { 566 | name, 567 | variant_index, 568 | variant, 569 | }) => serializer.serialize_unit_variant(name, *variant_index, variant), 570 | Save::Unit => serializer.serialize_unit(), 571 | Save::NewTypeStruct { name, value } => serializer.serialize_newtype_struct(name, value), 572 | Save::NewTypeVariant { 573 | variant: 574 | Variant { 575 | name, 576 | variant_index, 577 | variant, 578 | }, 579 | value, 580 | } => serializer.serialize_newtype_variant(name, *variant_index, variant, value), 581 | Save::Seq(it) => it.serialize(serializer), 582 | Save::Map(it) => { 583 | let mut map = serializer.serialize_map(Some(it.len()))?; 584 | for (k, v) in it { 585 | map.serialize_entry(k, v)? 586 | } 587 | map.end() 588 | } 589 | Save::Tuple(it) => { 590 | let mut tup = serializer.serialize_tuple(it.len())?; 591 | for it in it { 592 | tup.serialize_element(it)? 593 | } 594 | tup.end() 595 | } 596 | Save::TupleStruct { name, values } => { 597 | let mut tup = serializer.serialize_tuple_struct(name, values.len())?; 598 | for it in values { 599 | tup.serialize_field(it)? 600 | } 601 | tup.end() 602 | } 603 | Save::TupleVariant { 604 | variant: 605 | Variant { 606 | name, 607 | variant_index, 608 | variant, 609 | }, 610 | values, 611 | } => { 612 | let mut var = serializer.serialize_tuple_variant( 613 | name, 614 | *variant_index, 615 | variant, 616 | values.len(), 617 | )?; 618 | for it in values { 619 | var.serialize_field(it)? 620 | } 621 | var.end() 622 | } 623 | Save::Struct { name, fields } => { 624 | let mut strukt = serializer.serialize_struct(name, fields.len())?; 625 | for (k, v) in fields { 626 | match v { 627 | Some(v) => strukt.serialize_field(k, v)?, 628 | None => strukt.skip_field(k)?, 629 | } 630 | } 631 | strukt.end() 632 | } 633 | Save::StructVariant { 634 | variant: 635 | Variant { 636 | name, 637 | variant_index, 638 | variant, 639 | }, 640 | fields, 641 | } => { 642 | let mut var = serializer.serialize_struct_variant( 643 | name, 644 | *variant_index, 645 | variant, 646 | fields.len(), 647 | )?; 648 | for (k, v) in fields { 649 | match v { 650 | Some(v) => var.serialize_field(k, v)?, 651 | None => var.skip_field(k)?, 652 | } 653 | } 654 | var.end() 655 | } 656 | Save::Error(e) => Err(S::Error::custom(e)), 657 | } 658 | } 659 | } 660 | 661 | /// This is a best-effort deserialization, provided for completeness. 662 | impl<'a, 'de> Deserialize<'de> for Save<'a> { 663 | fn deserialize(deserializer: D) -> Result 664 | where 665 | D: serde::Deserializer<'de>, 666 | { 667 | struct Visitor<'a>(PhantomData<&'a ()>); 668 | 669 | macro_rules! simple { 670 | ($($fn:ident($ty:ty) -> $variant:ident);* $(;)?) => { 671 | $( 672 | fn $fn(self, v: $ty) -> Result { 673 | Ok(Save::$variant(v)) 674 | } 675 | )* 676 | }; 677 | } 678 | impl<'a, 'de> serde::de::Visitor<'de> for Visitor<'a> { 679 | type Value = Save<'a>; 680 | 681 | fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 682 | f.write_str("a `Save`-able type") 683 | } 684 | 685 | simple! { 686 | visit_bool(bool) -> Bool; 687 | visit_i8(i8) -> I8; 688 | visit_i16(i16) -> I16; 689 | visit_i32(i32) -> I32; 690 | visit_i64(i64) -> I64; 691 | visit_i128(i128) -> I128; 692 | visit_u8(u8) -> U8; 693 | visit_u16(u16) -> U16; 694 | visit_u32(u32) -> U32; 695 | visit_u64(u64) -> U64; 696 | visit_u128(u128) -> U128; 697 | visit_f32(f32) -> F32; 698 | visit_f64(f64) -> F64; 699 | visit_char(char) -> Char; 700 | visit_string(String) -> String; 701 | visit_byte_buf(Vec) -> ByteArray; 702 | } 703 | 704 | fn visit_str(self, v: &str) -> Result { 705 | Ok(Save::String(v.into())) 706 | } 707 | 708 | fn visit_borrowed_str( 709 | self, 710 | v: &'de str, 711 | ) -> Result { 712 | Ok(Save::String(v.into())) 713 | } 714 | 715 | fn visit_bytes(self, v: &[u8]) -> Result { 716 | Ok(Save::ByteArray(v.into())) 717 | } 718 | 719 | fn visit_borrowed_bytes( 720 | self, 721 | v: &'de [u8], 722 | ) -> Result { 723 | Ok(Save::ByteArray(v.into())) 724 | } 725 | 726 | fn visit_none(self) -> Result { 727 | Ok(Save::Option(None)) 728 | } 729 | 730 | fn visit_some(self, deserializer: D) -> Result 731 | where 732 | D: serde::Deserializer<'de>, 733 | { 734 | Ok(Save::Option(Some(Box::new( 735 | deserializer.deserialize_any(self)?, 736 | )))) 737 | } 738 | 739 | fn visit_unit(self) -> Result { 740 | Ok(Save::Unit) 741 | } 742 | 743 | fn visit_newtype_struct(self, deserializer: D) -> Result 744 | where 745 | D: serde::Deserializer<'de>, 746 | { 747 | let _ = deserializer; 748 | Err(serde::de::Error::invalid_type( 749 | serde::de::Unexpected::NewtypeStruct, 750 | &self, 751 | )) 752 | } 753 | 754 | fn visit_seq(self, mut seq: A) -> Result 755 | where 756 | A: serde::de::SeqAccess<'de>, 757 | { 758 | Ok(Save::Seq( 759 | iter::from_fn(|| seq.next_element().transpose()) 760 | .fuse() 761 | .collect::>()?, 762 | )) 763 | } 764 | 765 | fn visit_map(self, mut map: A) -> Result 766 | where 767 | A: serde::de::MapAccess<'de>, 768 | { 769 | Ok(Save::Map( 770 | iter::from_fn(|| map.next_entry().transpose()) 771 | .fuse() 772 | .collect::>()?, 773 | )) 774 | } 775 | 776 | fn visit_enum(self, data: A) -> Result 777 | where 778 | A: serde::de::EnumAccess<'de>, 779 | { 780 | let _ = data; 781 | Err(serde::de::Error::invalid_type( 782 | serde::de::Unexpected::Enum, 783 | &self, 784 | )) 785 | } 786 | } 787 | deserializer.deserialize_any(Visitor(PhantomData)) 788 | } 789 | } 790 | --------------------------------------------------------------------------------