From 968cabccf00c455799b012bffa899fc8905cbe58 Mon Sep 17 00:00:00 2001 From: Anders Musikka Date: Fri, 11 Oct 2024 17:38:47 +0200 Subject: [PATCH] std io error (#71) --- Cargo.lock | 6 +-- README.md | 6 +++ savefile-abi/Cargo.toml | 6 +-- savefile-derive/Cargo.toml | 2 +- savefile-test/Cargo.toml | 2 +- savefile-test/src/lib.rs | 38 +++++++++++++++- savefile/Cargo.toml | 6 +-- savefile/src/lib.rs | 89 +++++++++++++++++++++++++++++++++++++- 8 files changed, 141 insertions(+), 14 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 78b887d..2cf973a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -588,7 +588,7 @@ dependencies = [ [[package]] name = "savefile" -version = "0.17.9" +version = "0.17.10" dependencies = [ "arrayvec", "bit-set 0.5.3", @@ -614,7 +614,7 @@ dependencies = [ [[package]] name = "savefile-abi" -version = "0.17.9" +version = "0.17.10" dependencies = [ "byteorder", "libloading", @@ -655,7 +655,7 @@ dependencies = [ [[package]] name = "savefile-derive" -version = "0.17.9" +version = "0.17.10" dependencies = [ "proc-macro-error2", "proc-macro2", diff --git a/README.md b/README.md index 0d4681a..31709c6 100644 --- a/README.md +++ b/README.md @@ -78,6 +78,12 @@ fn main() { See the docs for more information, including schema-versioning: https://docs.rs/savefile/latest/savefile/ . # Changelog + +## 0.17.10 + +Support for serializing the std::io::Error type. +Note, non-stabilized Error-kinds are not supported. + ## 0.17.9 Replace the un-maintained proc-macro-error with proc-macro-error2. diff --git a/savefile-abi/Cargo.toml b/savefile-abi/Cargo.toml index 63702ef..7587ebc 100644 --- a/savefile-abi/Cargo.toml +++ b/savefile-abi/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "savefile-abi" -version = "0.17.9" +version = "0.17.10" edition = "2021" authors = ["Anders Musikka "] documentation = "https://docs.rs/savefile-abi/" @@ -17,8 +17,8 @@ keywords = ["dylib", "dlopen", "ffi"] license = "MIT/Apache-2.0" [dependencies] -savefile = { path="../savefile", version = "=0.17.9" } -savefile-derive = { path="../savefile-derive", version = "=0.17.9" } +savefile = { path="../savefile", version = "=0.17.10" } +savefile-derive = { path="../savefile-derive", version = "=0.17.10" } byteorder = "1.4" libloading = "0.8" diff --git a/savefile-derive/Cargo.toml b/savefile-derive/Cargo.toml index 4ae1de5..4a99fd1 100644 --- a/savefile-derive/Cargo.toml +++ b/savefile-derive/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "savefile-derive" -version = "0.17.9" +version = "0.17.10" authors = ["Anders Musikka "] repository = "https://github.com/avl/savefile" rust-version = "1.74" diff --git a/savefile-test/Cargo.toml b/savefile-test/Cargo.toml index 408d1b5..64b41ac 100644 --- a/savefile-test/Cargo.toml +++ b/savefile-test/Cargo.toml @@ -12,7 +12,7 @@ nightly=["savefile/nightly"] [dependencies] savefile = { path = "../savefile", features = ["size_sanity_checks", "encryption", "compression","bit-set","bit-vec","rustc-hash","serde_derive", "quickcheck", "nalgebra"]} -savefile-derive = { path = "../savefile-derive", version = "=0.17.9" } +savefile-derive = { path = "../savefile-derive", version = "=0.17.10" } savefile-abi = { path = "../savefile-abi" } bit-vec = "0.8" arrayvec="0.7" diff --git a/savefile-test/src/lib.rs b/savefile-test/src/lib.rs index a8a8085..d388ac5 100644 --- a/savefile-test/src/lib.rs +++ b/savefile-test/src/lib.rs @@ -32,7 +32,7 @@ use indexmap::IndexMap; use indexmap::IndexSet; use savefile::prelude::*; use std::fmt::Debug; -use std::io::Write; +use std::io::{ErrorKind, Write}; extern crate arrayvec; extern crate bincode; extern crate parking_lot; @@ -84,6 +84,26 @@ pub fn assert_roundtrip_version( assert_eq!(f.position() as usize, f_internal_size); } +pub fn assert_roundtrip_by(sample: E, comp: impl Fn(E, E) -> bool) { + let mut f = Cursor::new(Vec::new()); + { + let mut bufw = BufWriter::new(&mut f); + { + Serializer::save(&mut bufw, 1, &sample, false).unwrap(); + } + bufw.flush().unwrap(); + } + f.set_position(0); + { + let roundtrip_result = Deserializer::load::(&mut f, 1).unwrap(); + assert!(comp(sample, roundtrip_result)); + } + + let f_internal_size = f.get_ref().len(); + assert_eq!(f.position() as usize, f_internal_size); +} + + pub fn assert_roundtrip_debug(sample: E) { let sample_debug_string = format!("{:?}", sample); let round_tripped = roundtrip(sample); @@ -1502,6 +1522,22 @@ pub fn test_unit_struct() { let h = MyUnitStruct; assert_roundtrip(h); } +#[test] +fn roundtrip_io_error() { + fn assert_error_roundtrip(err: std::io::Error) { + assert_roundtrip_by( + err, + |a,b|{ + a.kind() == b.kind() && + a.to_string() == b.to_string() + } + ); + } + assert_error_roundtrip(std::io::Error::new(ErrorKind::AddrNotAvailable,"Hello")); + assert_error_roundtrip(std::io::Error::new(ErrorKind::AddrInUse,"Hello2")); + assert_error_roundtrip(std::io::Error::new(ErrorKind::Other,"Hello3")); + assert_error_roundtrip(std::io::Error::new(ErrorKind::TimedOut,"Hello4")); +} #[test] pub fn test_zero_size_vec_items() { diff --git a/savefile/Cargo.toml b/savefile/Cargo.toml index 5a2804f..95b299c 100644 --- a/savefile/Cargo.toml +++ b/savefile/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "savefile" -version = "0.17.9" +version = "0.17.10" authors = ["Anders Musikka "] documentation = "https://docs.rs/savefile/" homepage = "https://github.com/avl/savefile/" @@ -63,13 +63,13 @@ bit-set08 = {package="bit-set", version = "0.8", optional = true} rustc-hash = {version = "1.1", optional = true} memoffset = "0.9" byteorder = "1.4" -savefile-derive = {path="../savefile-derive", version = "=0.17.9", optional = true } +savefile-derive = {path="../savefile-derive", version = "=0.17.10", optional = true } serde_derive = {version= "1.0", optional = true} serde = {version= "1.0", optional = true} quickcheck = {version= "1.0", optional = true} [dev-dependencies] -savefile-derive = { path="../savefile-derive", version = "=0.17.9" } +savefile-derive = { path="../savefile-derive", version = "=0.17.10" } [build-dependencies] rustc_version="0.2" diff --git a/savefile/src/lib.rs b/savefile/src/lib.rs index af9c1b2..712baee 100644 --- a/savefile/src/lib.rs +++ b/savefile/src/lib.rs @@ -884,7 +884,7 @@ use parking_lot::{Mutex, MutexGuard, RwLock, RwLockReadGuard}; use std::borrow::Cow; use std::fs::File; -use std::io::Write; +use std::io::{ErrorKind, Write}; use std::io::{BufReader, BufWriter, Read}; use std::sync::atomic::{ AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU64, AtomicU8, @@ -1360,6 +1360,79 @@ impl<'a, T: 'a + Introspect + ToOwned + ?Sized> Introspect for Cow<'a, T> { } } +impl WithSchema for std::io::Error { + fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema { + Schema::StdIoError + } +} +impl Packed for std::io::Error {} + +impl Serialize for std::io::Error { + fn serialize(&self, serializer: &mut Serializer) -> Result<(), SavefileError> { + let kind = match self.kind() { + ErrorKind::NotFound => {1} + ErrorKind::PermissionDenied => {2} + ErrorKind::ConnectionRefused => {3} + ErrorKind::ConnectionReset => {4} + ErrorKind::ConnectionAborted => {7} + ErrorKind::NotConnected => {8} + ErrorKind::AddrInUse => {9} + ErrorKind::AddrNotAvailable => {10} + ErrorKind::BrokenPipe => {12} + ErrorKind::AlreadyExists => {13} + ErrorKind::WouldBlock => {14} + ErrorKind::InvalidInput => {21} + ErrorKind::InvalidData => {22} + ErrorKind::TimedOut => {23} + ErrorKind::WriteZero => {24} + ErrorKind::Interrupted => {36} + ErrorKind::Unsupported => {37} + ErrorKind::UnexpectedEof => {38} + ErrorKind::OutOfMemory => {39} + ErrorKind::Other => {40} + _ => { + 42 + } + }; + serializer.write_u16(kind as u16)?; + serializer.write_string(&self.to_string())?; + Ok(()) + } +} +impl Deserialize for std::io::Error { + fn deserialize(deserializer: &mut Deserializer) -> Result { + let kind = deserializer.read_u16()?; + let kind = match kind { + 1 => ErrorKind::NotFound, + 2 => ErrorKind::PermissionDenied, + 3 => ErrorKind::ConnectionRefused, + 4 => ErrorKind::ConnectionReset, + 7 => ErrorKind::ConnectionAborted, + 8 => ErrorKind::NotConnected, + 9 => ErrorKind::AddrInUse, + 10 => ErrorKind::AddrNotAvailable, + 12 => ErrorKind::BrokenPipe, + 13 => ErrorKind::AlreadyExists, + 14 => ErrorKind::WouldBlock, + 21 => ErrorKind::InvalidInput, + 22 => ErrorKind::InvalidData, + 23 => ErrorKind::TimedOut, + 24 => ErrorKind::WriteZero, + 36 => ErrorKind::Interrupted, + 37 => ErrorKind::Unsupported, + 38 => ErrorKind::UnexpectedEof, + 39 => ErrorKind::OutOfMemory, + 40 => ErrorKind::Other, + _ => { + ErrorKind::Other + } + }; + + let string = String::deserialize(deserializer)?; + Ok(std::io::Error::new(kind, string)) + } +} + #[cfg(feature = "ring")] mod crypto { use ring::aead; @@ -3243,6 +3316,8 @@ pub enum Schema { /// if it is identical in memory and file, and because of this, counting /// only the recursion points is non-ambiguous. Recursion(usize /*depth*/), + /// std::io::Error + StdIoError, } /// Introspect is not implemented for Schema, though it could be impl Introspect for Schema { @@ -3278,6 +3353,7 @@ impl Schema { Schema::Recursion(depth) => { format!("", depth) } + Schema::StdIoError => "stdioerror".into(), } } /// Determine if the two fields are laid out identically in memory, in their parent objects. @@ -3432,6 +3508,7 @@ impl Schema { Schema::Reference(_) => None, Schema::Trait(_, _) => None, Schema::Recursion(_) => None, + Schema::StdIoError => None, } } } @@ -3574,6 +3651,9 @@ pub fn diff_schema(a: &Schema, b: &Schema, path: String) -> Option { (Schema::Str, Schema::Str) => { return None; } + (Schema::StdIoError, Schema::StdIoError) => { + return None; + } (Schema::Boxed(a), Schema::Boxed(b)) => { return diff_schema(&**a, &**b, path); } @@ -4135,6 +4215,10 @@ impl Serialize for Schema { serializer.write_usize(*depth)?; Ok(()) } + Schema::StdIoError => { + serializer.write_u8(17)?; + Ok(()) + } } } } @@ -4173,9 +4257,10 @@ impl Deserialize for Schema { <_ as Deserialize>::deserialize(deserializer)?, ), 16 => Schema::Recursion(<_ as Deserialize>::deserialize(deserializer)?), + 17 => Schema::StdIoError, c => { return Err(SavefileError::GeneralError { - msg: format!("Corrupt schema, schema variant {} encountered", c), + msg: format!("Corrupt, or future schema, schema variant {} encountered", c), }) } };