1#![allow(incomplete_features)]
2#![recursion_limit = "256"]
3#![cfg_attr(feature = "nightly", feature(specialization))]
4#![deny(missing_docs)]
5#![deny(warnings)]
6#![allow(clippy::bool_comparison)]
7#![allow(clippy::box_default)]
8#![allow(clippy::needless_question_mark)]
9#![allow(clippy::needless_return)]
10#![allow(clippy::manual_try_fold)] #![allow(clippy::needless_range_loop)]
12#![allow(clippy::len_zero)]
13#![allow(clippy::new_without_default)]
14#![allow(clippy::transmute_num_to_bytes)] #![allow(clippy::manual_memcpy)] #![allow(clippy::needless_late_init)]
17
18pub mod prelude;
854
855#[cfg(feature = "serde_derive")]
856extern crate serde;
857#[cfg(feature = "serde_derive")]
858extern crate serde_derive;
859
860use core::str::Utf8Error;
861#[cfg(feature = "serde_derive")]
862use serde_derive::{Deserialize, Serialize};
863use std::any::TypeId;
864
865#[cfg(feature = "quickcheck")]
866extern crate quickcheck;
867
868extern crate alloc;
869#[cfg(feature = "arrayvec")]
870extern crate arrayvec;
871extern crate byteorder;
872#[cfg(feature = "parking_lot")]
873extern crate parking_lot;
874#[cfg(feature = "smallvec")]
875extern crate smallvec;
876
877#[cfg(feature = "parking_lot")]
878use parking_lot::{Mutex, MutexGuard, RwLock, RwLockReadGuard};
879
880use std::borrow::Cow;
881use std::fs::File;
882use std::io::{BufReader, BufWriter, Read};
883use std::io::{ErrorKind, Write};
884use std::sync::atomic::{
885 AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16, AtomicU32, AtomicU64, AtomicU8,
886 AtomicUsize, Ordering,
887};
888
889pub use ::byteorder::LittleEndian;
890use std::collections::BinaryHeap;
891use std::collections::VecDeque;
892use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
893use std::hash::Hash;
894#[allow(unused_imports)]
895use std::mem::MaybeUninit;
896
897#[cfg(feature = "indexmap")]
898extern crate indexmap;
899#[cfg(feature = "indexmap")]
900use indexmap::{IndexMap, IndexSet};
901
902#[cfg(feature = "quickcheck")]
903use quickcheck::{Arbitrary, Gen};
904
905#[cfg(feature = "bit-vec")]
906extern crate bit_vec;
907#[cfg(feature = "bzip2")]
908extern crate bzip2;
909
910#[cfg(feature = "bit-set")]
911extern crate bit_set;
912
913#[cfg(feature = "rustc-hash")]
914extern crate rustc_hash;
915
916extern crate memoffset;
917
918#[cfg(feature = "derive")]
919extern crate savefile_derive;
920
921pub const CURRENT_SAVEFILE_LIB_VERSION: u16 = 2;
928
929#[derive(Debug)]
932#[must_use]
933#[non_exhaustive]
934pub enum SavefileError {
935 IncompatibleSchema {
939 message: String,
941 },
942 IOError {
944 io_error: std::io::Error,
946 },
947 InvalidUtf8 {
952 msg: String,
954 },
955 MemoryAllocationLayoutError,
957 ArrayvecCapacityError {
959 msg: String,
961 },
962 ShortRead,
964 CryptographyError,
966 SizeOverflow,
970 WrongVersion {
972 msg: String,
974 },
975 GeneralError {
977 msg: String,
979 },
980 PoisonedMutex,
982 CompressionSupportNotCompiledIn,
984 InvalidChar,
986 IncompatibleSavefileLibraryVersion,
989 MissingMethod {
991 method_name: String,
993 },
994 TooManyArguments,
996 CalleePanic {
998 msg: String,
1000 },
1001 LoadLibraryFailed {
1003 libname: String,
1005 msg: String,
1007 },
1008 LoadSymbolFailed {
1010 libname: String,
1012 symbol: String,
1014 msg: String,
1016 },
1017}
1018impl From<Utf8Error> for SavefileError {
1019 fn from(value: Utf8Error) -> Self {
1020 SavefileError::InvalidUtf8 {
1021 msg: format!("{:?}", value),
1022 }
1023 }
1024}
1025impl Display for SavefileError {
1026 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1027 match self {
1028 SavefileError::IncompatibleSchema { message } => {
1029 write!(f, "Incompatible schema: {}", message)
1030 }
1031 SavefileError::IOError { io_error } => {
1032 write!(f, "IO error: {}", io_error)
1033 }
1034 SavefileError::InvalidUtf8 { msg } => {
1035 write!(f, "Invalid UTF-8: {}", msg)
1036 }
1037 SavefileError::MemoryAllocationLayoutError => {
1038 write!(f, "Memory allocation layout error")
1039 }
1040 SavefileError::ArrayvecCapacityError { msg } => {
1041 write!(f, "Arrayvec capacity error: {}", msg)
1042 }
1043 SavefileError::ShortRead => {
1044 write!(f, "Short read")
1045 }
1046 SavefileError::CryptographyError => {
1047 write!(f, "Cryptography error")
1048 }
1049 SavefileError::SizeOverflow => {
1050 write!(f, "Size overflow")
1051 }
1052 SavefileError::WrongVersion { msg } => {
1053 write!(f, "Wrong version: {}", msg)
1054 }
1055 SavefileError::GeneralError { msg } => {
1056 write!(f, "General error: {}", msg)
1057 }
1058 SavefileError::PoisonedMutex => {
1059 write!(f, "Poisoned mutex")
1060 }
1061 SavefileError::CompressionSupportNotCompiledIn => {
1062 write!(f, "Compression support missing - recompile with bzip2 feature enabled.")
1063 }
1064 SavefileError::InvalidChar => {
1065 write!(f, "Invalid char value encountered.")
1066 }
1067 SavefileError::IncompatibleSavefileLibraryVersion => {
1068 write!(f, "Incompatible savefile library version. Perhaps a plugin was loaded that is a future unsupported version?")
1069 }
1070 SavefileError::MissingMethod { method_name } => {
1071 write!(f, "Plugin is missing method {}", method_name)
1072 }
1073 SavefileError::TooManyArguments => {
1074 write!(f, "Function has too many arguments")
1075 }
1076 SavefileError::CalleePanic { msg } => {
1077 write!(f, "Invocation target panicked: {}", msg)
1078 }
1079 SavefileError::LoadLibraryFailed { libname, msg } => {
1080 write!(f, "Failed while loading library {}: {}", libname, msg)
1081 }
1082 SavefileError::LoadSymbolFailed { libname, symbol, msg } => {
1083 write!(
1084 f,
1085 "Failed while loading symbol {} from library {}: {}",
1086 symbol, libname, msg
1087 )
1088 }
1089 }
1090 }
1091}
1092
1093impl std::error::Error for SavefileError {}
1094
1095impl SavefileError {
1096 pub fn general(something: impl Display) -> SavefileError {
1098 SavefileError::GeneralError {
1099 msg: format!("{}", something),
1100 }
1101 }
1102}
1103
1104pub struct Serializer<'a, W: Write> {
1111 pub writer: &'a mut W,
1113 pub file_version: u32,
1117}
1118
1119pub struct Deserializer<'a, R: Read> {
1125 pub reader: &'a mut R,
1127 pub file_version: u32,
1129 pub ephemeral_state: HashMap<TypeId, Box<dyn Any>>,
1132}
1133
1134impl<TR: Read> Deserializer<'_, TR> {
1135 pub fn get_state<T: 'static, R: Default + 'static>(&mut self) -> &mut R {
1144 let type_id = TypeId::of::<T>();
1145 let the_any = self
1146 .ephemeral_state
1147 .entry(type_id)
1148 .or_insert_with(|| Box::new(R::default()));
1149
1150 the_any.downcast_mut().unwrap()
1151 }
1152}
1153
1154#[derive(Default, Debug)]
1157pub struct IsPacked(bool);
1158
1159#[doc(hidden)]
1160#[deprecated(since = "0.17.0", note = "The 'IsReprC' type has been renamed to 'IsPacked'.")]
1161pub type IsReprC = IsPacked;
1162
1163impl std::ops::BitAnd<IsPacked> for IsPacked {
1164 type Output = IsPacked;
1165
1166 fn bitand(self, rhs: Self) -> Self::Output {
1167 IsPacked(self.0 && rhs.0)
1168 }
1169}
1170
1171impl IsPacked {
1172 pub unsafe fn yes() -> IsPacked {
1180 IsPacked(true)
1181 }
1182 pub fn no() -> IsPacked {
1186 IsPacked(false)
1187 }
1188
1189 #[inline(always)]
1191 pub fn is_false(self) -> bool {
1192 !self.0
1193 }
1194
1195 #[inline(always)]
1197 pub fn is_yes(self) -> bool {
1198 self.0
1199 }
1200}
1201
1202#[cfg_attr(
1207 feature = "rust1_78",
1208 diagnostic::on_unimplemented(
1209 message = "`{Self}` cannot be serialized or deserialized by Savefile, since it doesn't implement trait `savefile::Packed`",
1210 label = "This cannot be serialized or deserialized",
1211 note = "You can implement it by adding `#[derive(Savefile)]` before the declaration of `{Self}`",
1212 note = "Or you can manually implement the `savefile::Packed` trait."
1213 )
1214)]
1215pub trait Packed {
1216 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
1248 IsPacked::no()
1249 }
1250}
1251
1252#[doc(hidden)]
1256#[deprecated(since = "0.17.0", note = "The 'ReprC' trait has been renamed to 'Packed'.")]
1257pub struct DeliberatelyUnimplementable {
1258 #[allow(dead_code)]
1259 private: (),
1260}
1261
1262#[deprecated(since = "0.17.0", note = "The 'ReprC' trait has been renamed to 'Packed'.")]
1263#[doc(hidden)]
1264#[cfg_attr(
1265 feature = "rust1_78",
1266 diagnostic::on_unimplemented(
1267 message = "ReprC has been deprecated and must not be used. Use trait `savefile::Packed` instead!",
1268 label = "ReprC was erroneously required here",
1269 note = "Please change any `ReprC` bounds into `Packed` bounds.",
1270 )
1271)]
1272pub trait ReprC {
1273 #[deprecated(since = "0.17.0", note = "The 'ReprC' trait has been renamed to 'Packed'.")]
1274 #[doc(hidden)]
1275 #[allow(non_snake_case)]
1276 #[allow(deprecated)]
1277 fn this_is_a_placeholder__if_you_see_this_it_is_likely_that_you_have_code_that_refers_to_ReprC_trait__this_trait_has_been_renamed_to__Packed(
1278 ) -> DeliberatelyUnimplementable;
1279 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
1280 IsPacked::no()
1281 }
1282}
1283
1284impl From<std::io::Error> for SavefileError {
1285 fn from(s: std::io::Error) -> SavefileError {
1286 SavefileError::IOError { io_error: s }
1287 }
1288}
1289
1290impl<T> From<std::sync::PoisonError<T>> for SavefileError {
1291 fn from(_: std::sync::PoisonError<T>) -> SavefileError {
1292 SavefileError::PoisonedMutex
1293 }
1294}
1295
1296impl From<std::string::FromUtf8Error> for SavefileError {
1297 fn from(s: std::string::FromUtf8Error) -> SavefileError {
1298 SavefileError::InvalidUtf8 { msg: s.to_string() }
1299 }
1300}
1301#[cfg(feature = "arrayvec")]
1302impl<T> From<arrayvec::CapacityError<T>> for SavefileError {
1303 fn from(s: arrayvec::CapacityError<T>) -> SavefileError {
1304 SavefileError::ArrayvecCapacityError { msg: s.to_string() }
1305 }
1306}
1307
1308impl WithSchema for PathBuf {
1309 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
1310 Schema::Primitive(SchemaPrimitive::schema_string(VecOrStringLayout::Unknown))
1311 }
1312}
1313impl Serialize for PathBuf {
1314 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
1315 let as_string: String = self.to_string_lossy().to_string();
1316 as_string.serialize(serializer)
1317 }
1318}
1319impl Packed for PathBuf {}
1320impl Deserialize for PathBuf {
1321 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
1322 Ok(PathBuf::from(String::deserialize(deserializer)?))
1323 }
1324}
1325impl Introspect for PathBuf {
1326 fn introspect_value(&self) -> String {
1327 self.to_string_lossy().to_string()
1328 }
1329
1330 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem>> {
1331 None
1332 }
1333}
1334
1335impl<'a, T: 'a + WithSchema + ToOwned + ?Sized> WithSchema for Cow<'a, T> {
1336 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
1337 T::schema(version, context)
1338 }
1339}
1340impl<'a, T: 'a + ToOwned + ?Sized> Packed for Cow<'a, T> {}
1341
1342impl<'a, T: 'a + Serialize + ToOwned + ?Sized> Serialize for Cow<'a, T> {
1343 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
1344 (**self).serialize(serializer)
1345 }
1346}
1347impl<'a, T: 'a + WithSchema + ToOwned + ?Sized> Deserialize for Cow<'a, T>
1348where
1349 T::Owned: Deserialize,
1350{
1351 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Cow<'a, T>, SavefileError> {
1352 Ok(Cow::Owned(<T as ToOwned>::Owned::deserialize(deserializer)?))
1353 }
1354}
1355impl<'a, T: 'a + Introspect + ToOwned + ?Sized> Introspect for Cow<'a, T> {
1356 fn introspect_value(&self) -> String {
1357 (**self).introspect_value()
1358 }
1359
1360 fn introspect_child<'b>(&'b self, index: usize) -> Option<Box<dyn IntrospectItem<'b> + 'b>> {
1361 (**self).introspect_child(index)
1362 }
1363
1364 fn introspect_len(&self) -> usize {
1365 (**self).introspect_len()
1366 }
1367}
1368
1369impl WithSchema for std::io::Error {
1370 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
1371 Schema::StdIoError
1372 }
1373}
1374impl Packed for std::io::Error {}
1375
1376impl Serialize for std::io::Error {
1377 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
1378 let kind = match self.kind() {
1379 ErrorKind::NotFound => 1,
1380 ErrorKind::PermissionDenied => 2,
1381 ErrorKind::ConnectionRefused => 3,
1382 ErrorKind::ConnectionReset => 4,
1383 ErrorKind::ConnectionAborted => 7,
1384 ErrorKind::NotConnected => 8,
1385 ErrorKind::AddrInUse => 9,
1386 ErrorKind::AddrNotAvailable => 10,
1387 ErrorKind::BrokenPipe => 12,
1388 ErrorKind::AlreadyExists => 13,
1389 ErrorKind::WouldBlock => 14,
1390 ErrorKind::InvalidInput => 21,
1391 ErrorKind::InvalidData => 22,
1392 ErrorKind::TimedOut => 23,
1393 ErrorKind::WriteZero => 24,
1394 ErrorKind::Interrupted => 36,
1395 ErrorKind::Unsupported => 37,
1396 ErrorKind::UnexpectedEof => 38,
1397 ErrorKind::OutOfMemory => 39,
1398 ErrorKind::Other => 40,
1399 _ => 42,
1400 };
1401 serializer.write_u16(kind as u16)?;
1402 serializer.write_string(&self.to_string())?;
1403 Ok(())
1404 }
1405}
1406impl Deserialize for std::io::Error {
1407 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
1408 let kind = deserializer.read_u16()?;
1409 let kind = match kind {
1410 1 => ErrorKind::NotFound,
1411 2 => ErrorKind::PermissionDenied,
1412 3 => ErrorKind::ConnectionRefused,
1413 4 => ErrorKind::ConnectionReset,
1414 7 => ErrorKind::ConnectionAborted,
1415 8 => ErrorKind::NotConnected,
1416 9 => ErrorKind::AddrInUse,
1417 10 => ErrorKind::AddrNotAvailable,
1418 12 => ErrorKind::BrokenPipe,
1419 13 => ErrorKind::AlreadyExists,
1420 14 => ErrorKind::WouldBlock,
1421 21 => ErrorKind::InvalidInput,
1422 22 => ErrorKind::InvalidData,
1423 23 => ErrorKind::TimedOut,
1424 24 => ErrorKind::WriteZero,
1425 36 => ErrorKind::Interrupted,
1426 37 => ErrorKind::Unsupported,
1427 38 => ErrorKind::UnexpectedEof,
1428 39 => ErrorKind::OutOfMemory,
1429 40 => ErrorKind::Other,
1430 _ => ErrorKind::Other,
1431 };
1432
1433 let string = String::deserialize(deserializer)?;
1434 Ok(std::io::Error::new(kind, string))
1435 }
1436}
1437
1438#[cfg(feature = "ring")]
1439mod crypto {
1440 use ring::aead;
1441 use ring::aead::{BoundKey, Nonce, NonceSequence, OpeningKey, SealingKey, UnboundKey, AES_256_GCM};
1442 use ring::error::Unspecified;
1443 use std::fs::File;
1444 use std::io::{Error, ErrorKind, Read, Write};
1445 use std::path::Path;
1446
1447 extern crate rand;
1448
1449 use crate::{Deserialize, Deserializer, SavefileError, Serialize, Serializer, WithSchema};
1450 use byteorder::WriteBytesExt;
1451 use byteorder::{LittleEndian, ReadBytesExt};
1452 use rand::rngs::OsRng;
1453 use rand::RngCore;
1454
1455 extern crate ring;
1456
1457 #[derive(Debug)]
1458 struct RandomNonceSequence {
1459 data1: u64,
1460 data2: u32,
1461 }
1462
1463 impl RandomNonceSequence {
1464 pub fn new() -> RandomNonceSequence {
1465 RandomNonceSequence {
1466 data1: OsRng.next_u64(),
1467 data2: OsRng.next_u32(),
1468 }
1469 }
1470 pub fn serialize(&self, writer: &mut dyn Write) -> Result<(), SavefileError> {
1471 writer.write_u64::<LittleEndian>(self.data1)?;
1472 writer.write_u32::<LittleEndian>(self.data2)?;
1473 Ok(())
1474 }
1475 pub fn deserialize(reader: &mut dyn Read) -> Result<RandomNonceSequence, SavefileError> {
1476 Ok(RandomNonceSequence {
1477 data1: reader.read_u64::<LittleEndian>()?,
1478 data2: reader.read_u32::<LittleEndian>()?,
1479 })
1480 }
1481 }
1482
1483 impl NonceSequence for RandomNonceSequence {
1484 fn advance(&mut self) -> Result<Nonce, Unspecified> {
1485 self.data2 = self.data2.wrapping_add(1);
1486 if self.data2 == 0 {
1487 self.data1 = self.data1.wrapping_add(1);
1488 }
1489 let mut bytes = [0u8; 12];
1490 let bytes1: [u8; 8] = self.data1.to_le_bytes();
1491 let bytes2: [u8; 4] = self.data2.to_le_bytes();
1492 for i in 0..8 {
1493 bytes[i] = bytes1[i];
1494 }
1495 for i in 0..4 {
1496 bytes[i + 8] = bytes2[i];
1497 }
1498
1499 Ok(Nonce::assume_unique_for_key(bytes))
1500 }
1501 }
1502
1503 pub struct CryptoWriter<'a> {
1507 writer: &'a mut dyn Write,
1508 buf: Vec<u8>,
1509 sealkey: SealingKey<RandomNonceSequence>,
1510 failed: bool,
1511 }
1512
1513 pub struct CryptoReader<'a> {
1517 reader: &'a mut dyn Read,
1518 buf: Vec<u8>,
1519 offset: usize,
1520 openingkey: OpeningKey<RandomNonceSequence>,
1521 }
1522
1523 impl<'a> CryptoReader<'a> {
1524 pub fn new(reader: &'a mut dyn Read, key_bytes: [u8; 32]) -> Result<CryptoReader<'a>, SavefileError> {
1528 let unboundkey = UnboundKey::new(&AES_256_GCM, &key_bytes).unwrap();
1529
1530 let nonce_sequence = RandomNonceSequence::deserialize(reader)?;
1531 let openingkey = OpeningKey::new(unboundkey, nonce_sequence);
1532
1533 Ok(CryptoReader {
1534 reader,
1535 offset: 0,
1536 buf: Vec::new(),
1537 openingkey,
1538 })
1539 }
1540 }
1541
1542 const CRYPTO_BUFSIZE: usize = 100_000;
1543
1544 impl Drop for CryptoWriter<'_> {
1545 fn drop(&mut self) {
1546 self.flush().expect("The implicit flush in the Drop of CryptoWriter failed. This causes this panic. If you want to be able to handle this, make sure to call flush() manually. If a manual flush has failed, Drop won't panic.");
1547 }
1548 }
1549
1550 impl<'a> CryptoWriter<'a> {
1551 pub fn new(writer: &'a mut dyn Write, key_bytes: [u8; 32]) -> Result<CryptoWriter<'a>, SavefileError> {
1555 let unboundkey = UnboundKey::new(&AES_256_GCM, &key_bytes).unwrap();
1556 let nonce_sequence = RandomNonceSequence::new();
1557 nonce_sequence.serialize(writer)?;
1558 let sealkey = SealingKey::new(unboundkey, nonce_sequence);
1559 Ok(CryptoWriter {
1560 writer,
1561 buf: Vec::new(),
1562 sealkey,
1563 failed: false,
1564 })
1565 }
1566 pub fn flush_final(mut self) -> Result<(), SavefileError> {
1570 if self.failed {
1571 panic!("Call to failed CryptoWriter");
1572 }
1573 self.flush()?;
1574 Ok(())
1575 }
1576 }
1577
1578 impl Read for CryptoReader<'_> {
1579 fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
1580 loop {
1581 if buf.len() <= self.buf.len() - self.offset {
1582 buf.clone_from_slice(&self.buf[self.offset..self.offset + buf.len()]);
1583 self.offset += buf.len();
1584 return Ok(buf.len());
1585 }
1586
1587 {
1588 let oldlen = self.buf.len();
1589 let newlen = self.buf.len() - self.offset;
1590 self.buf.copy_within(self.offset..oldlen, 0);
1591 self.buf.resize(newlen, 0);
1592 self.offset = 0;
1593 }
1594 let mut sizebuf = [0; 8];
1595 let mut sizebuf_bytes_read = 0;
1596 loop {
1597 match self.reader.read(&mut sizebuf[sizebuf_bytes_read..]) {
1598 Ok(gotsize) => {
1599 if gotsize == 0 {
1600 if sizebuf_bytes_read == 0 {
1601 let cur_content_size = self.buf.len() - self.offset;
1602 buf[0..cur_content_size]
1603 .clone_from_slice(&self.buf[self.offset..self.offset + cur_content_size]);
1604 self.offset += cur_content_size;
1605 return Ok(cur_content_size);
1606 } else {
1607 return Err(Error::new(ErrorKind::UnexpectedEof, "Unexpected EOF"));
1608 }
1609 } else {
1610 sizebuf_bytes_read += gotsize;
1611 assert!(sizebuf_bytes_read <= 8);
1612 }
1613 }
1614 Err(err) => return Err(err),
1615 }
1616 if sizebuf_bytes_read == 8 {
1617 break;
1618 }
1619 }
1620 use byteorder::ByteOrder;
1621 let curlen = byteorder::LittleEndian::read_u64(&sizebuf) as usize;
1622
1623 if curlen > CRYPTO_BUFSIZE + 16 {
1624 return Err(Error::new(ErrorKind::Other, "Cryptography error"));
1625 }
1626 let orglen = self.buf.len();
1627 self.buf.resize(orglen + curlen, 0);
1628
1629 self.reader.read_exact(&mut self.buf[orglen..orglen + curlen])?;
1630
1631 match self
1632 .openingkey
1633 .open_in_place(aead::Aad::empty(), &mut self.buf[orglen..])
1634 {
1635 Ok(_) => {}
1636 Err(_) => {
1637 return Err(Error::new(ErrorKind::Other, "Cryptography error"));
1638 }
1639 }
1640 self.buf.resize(self.buf.len() - 16, 0);
1641 }
1642 }
1643 }
1644
1645 impl Write for CryptoWriter<'_> {
1646 fn write(&mut self, buf: &[u8]) -> Result<usize, Error> {
1647 if self.failed {
1648 panic!("Call to failed CryptoWriter");
1649 }
1650 self.buf.extend(buf);
1651 if self.buf.len() > CRYPTO_BUFSIZE {
1652 self.flush()?;
1653 }
1654 Ok(buf.len())
1655 }
1656
1657 fn flush(&mut self) -> Result<(), Error> {
1661 self.failed = true;
1662 let mut offset = 0;
1663
1664 let mut tempbuf = Vec::new();
1665 if self.buf.len() > CRYPTO_BUFSIZE {
1666 tempbuf = Vec::<u8>::with_capacity(CRYPTO_BUFSIZE + 16);
1667 }
1668
1669 while self.buf.len() > offset {
1670 let curbuf;
1671 if offset == 0 && self.buf.len() <= CRYPTO_BUFSIZE {
1672 curbuf = &mut self.buf;
1673 } else {
1674 let chunksize = (self.buf.len() - offset).min(CRYPTO_BUFSIZE);
1675 tempbuf.resize(chunksize, 0u8);
1676 tempbuf.clone_from_slice(&self.buf[offset..offset + chunksize]);
1677 curbuf = &mut tempbuf;
1678 }
1679 let expected_final_len = curbuf.len() as u64 + 16;
1680 debug_assert!(expected_final_len <= CRYPTO_BUFSIZE as u64 + 16);
1681
1682 self.writer.write_u64::<LittleEndian>(expected_final_len)?; match self.sealkey.seal_in_place_append_tag(aead::Aad::empty(), curbuf) {
1684 Ok(_) => {}
1685 Err(_) => {
1686 return Err(Error::new(ErrorKind::Other, "Cryptography error"));
1687 }
1688 }
1689 debug_assert!(curbuf.len() == expected_final_len as usize, "The size of the TAG generated by the AES 256 GCM in ring seems to have changed! This is very unexpected. File a bug on the savefile-crate");
1690
1691 self.writer.write_all(&curbuf[..])?;
1692 self.writer.flush()?;
1693 offset += curbuf.len() - 16;
1694 curbuf.resize(curbuf.len() - 16, 0);
1695 }
1696 self.buf.clear();
1697 self.failed = false;
1698 Ok(())
1699 }
1700 }
1701 pub fn save_encrypted_file<T: WithSchema + Serialize, P: AsRef<Path>>(
1704 filepath: P,
1705 version: u32,
1706 data: &T,
1707 password: &str,
1708 ) -> Result<(), SavefileError> {
1709 use ring::digest;
1710 let actual = digest::digest(&digest::SHA256, password.as_bytes());
1711 let mut key = [0u8; 32];
1712 let password_hash = actual.as_ref();
1713 assert_eq!(password_hash.len(), key.len(), "A SHA256 sum must be 32 bytes");
1714 key.clone_from_slice(password_hash);
1715
1716 let mut f = File::create(filepath)?;
1717 let mut writer = CryptoWriter::new(&mut f, key)?;
1718
1719 Serializer::<CryptoWriter>::save::<T>(&mut writer, version, data, true)?;
1720 writer.flush()?;
1721 Ok(())
1722 }
1723
1724 pub fn load_encrypted_file<T: WithSchema + Deserialize, P: AsRef<Path>>(
1727 filepath: P,
1728 version: u32,
1729 password: &str,
1730 ) -> Result<T, SavefileError> {
1731 use ring::digest;
1732 let actual = digest::digest(&digest::SHA256, password.as_bytes());
1733 let mut key = [0u8; 32];
1734 let password_hash = actual.as_ref();
1735 assert_eq!(password_hash.len(), key.len(), "A SHA256 sum must be 32 bytes");
1736 key.clone_from_slice(password_hash);
1737
1738 let mut f = File::open(filepath)?;
1739 let mut reader = CryptoReader::new(&mut f, key).unwrap();
1740 Deserializer::<CryptoReader>::load::<T>(&mut reader, version)
1741 }
1742}
1743#[cfg(feature = "ring")]
1744pub use crypto::{load_encrypted_file, save_encrypted_file, CryptoReader, CryptoWriter};
1745
1746impl<'a, W: Write + 'a> Serializer<'a, W> {
1747 #[inline(always)]
1749 pub fn write_bool(&mut self, v: bool) -> Result<(), SavefileError> {
1750 Ok(self.writer.write_u8(if v { 1 } else { 0 })?)
1751 }
1752 #[inline(always)]
1754 pub fn write_u8(&mut self, v: u8) -> Result<(), SavefileError> {
1755 Ok(self.writer.write_all(&[v])?)
1756 }
1757 #[inline(always)]
1759 pub fn write_i8(&mut self, v: i8) -> Result<(), SavefileError> {
1760 Ok(self.writer.write_i8(v)?)
1761 }
1762
1763 #[inline(always)]
1765 pub fn write_u16(&mut self, v: u16) -> Result<(), SavefileError> {
1766 Ok(self.writer.write_u16::<LittleEndian>(v)?)
1767 }
1768 #[inline(always)]
1770 pub fn write_i16(&mut self, v: i16) -> Result<(), SavefileError> {
1771 Ok(self.writer.write_i16::<LittleEndian>(v)?)
1772 }
1773
1774 #[inline(always)]
1776 pub fn write_u32(&mut self, v: u32) -> Result<(), SavefileError> {
1777 Ok(self.writer.write_u32::<LittleEndian>(v)?)
1778 }
1779 #[inline(always)]
1781 pub fn write_i32(&mut self, v: i32) -> Result<(), SavefileError> {
1782 Ok(self.writer.write_i32::<LittleEndian>(v)?)
1783 }
1784
1785 #[inline(always)]
1787 pub fn write_f32(&mut self, v: f32) -> Result<(), SavefileError> {
1788 Ok(self.writer.write_f32::<LittleEndian>(v)?)
1789 }
1790 #[inline(always)]
1792 pub fn write_f64(&mut self, v: f64) -> Result<(), SavefileError> {
1793 Ok(self.writer.write_f64::<LittleEndian>(v)?)
1794 }
1795
1796 #[inline(always)]
1798 pub fn write_u64(&mut self, v: u64) -> Result<(), SavefileError> {
1799 Ok(self.writer.write_u64::<LittleEndian>(v)?)
1800 }
1801
1802 #[inline(always)]
1809 pub unsafe fn write_raw_ptr<T: ?Sized>(&mut self, data: *const T) -> Result<(), SavefileError> {
1810 let temp = &data as *const *const T;
1811 let temp_data = temp as *const u8;
1812 let buf = slice::from_raw_parts(temp_data, std::mem::size_of::<*const T>());
1813 self.write_bytes(buf)
1814 }
1815
1816 pub unsafe fn write_raw_ptr_size<T>(&mut self, data: *const T, len: usize) -> Result<(), SavefileError> {
1818 self.write_raw_ptr(data)?;
1819 self.write_usize(len)?;
1820 Ok(())
1821 }
1822
1823 #[inline(always)]
1825 pub fn write_ptr(&mut self, v: *const ()) -> Result<(), SavefileError> {
1826 let slice_to_write = unsafe {
1827 std::slice::from_raw_parts(&v as *const *const () as *const u8, std::mem::size_of::<*const ()>())
1828 };
1829 Ok(self.writer.write_all(slice_to_write)?)
1830 }
1831 #[inline(always)]
1833 pub fn write_i64(&mut self, v: i64) -> Result<(), SavefileError> {
1834 Ok(self.writer.write_i64::<LittleEndian>(v)?)
1835 }
1836 #[inline(always)]
1838 pub fn write_u128(&mut self, v: u128) -> Result<(), SavefileError> {
1839 Ok(self.writer.write_u128::<LittleEndian>(v)?)
1840 }
1841 #[inline(always)]
1843 pub fn write_i128(&mut self, v: i128) -> Result<(), SavefileError> {
1844 Ok(self.writer.write_i128::<LittleEndian>(v)?)
1845 }
1846 #[inline(always)]
1848 pub fn write_usize(&mut self, v: usize) -> Result<(), SavefileError> {
1849 Ok(self.writer.write_u64::<LittleEndian>(v as u64)?)
1850 }
1851 #[inline(always)]
1853 pub fn write_isize(&mut self, v: isize) -> Result<(), SavefileError> {
1854 Ok(self.writer.write_i64::<LittleEndian>(v as i64)?)
1855 }
1856 #[inline(always)]
1858 pub fn write_buf(&mut self, v: &[u8]) -> Result<(), SavefileError> {
1859 Ok(self.writer.write_all(v)?)
1860 }
1861 #[inline(always)]
1863 pub fn write_string(&mut self, v: &str) -> Result<(), SavefileError> {
1864 let asb = v.as_bytes();
1865 self.write_usize(asb.len())?;
1866 Ok(self.writer.write_all(asb)?)
1867 }
1868 #[inline(always)]
1870 pub fn write_bytes(&mut self, v: &[u8]) -> Result<(), SavefileError> {
1871 Ok(self.writer.write_all(v)?)
1872 }
1873
1874 #[inline(always)]
1882 #[doc(hidden)]
1883 pub unsafe fn raw_write_region<T, T1: Packed, T2: Packed>(
1884 &mut self,
1885 full: &T,
1886 t1: &T1,
1887 t2: &T2,
1888 version: u32,
1889 ) -> Result<(), SavefileError> {
1890 assert!(T1::repr_c_optimization_safe(version).is_yes());
1891 assert!(T2::repr_c_optimization_safe(version).is_yes());
1892
1893 let base = full as *const T as *const u8;
1894 let totlen = std::mem::size_of::<T>();
1895 let p1 = (t1 as *const T1 as *const u8) as usize;
1896 let p2 = (t2 as *const T2 as *const u8) as usize;
1897 let start = p1 - (base as usize);
1898 let end = (p2 - (base as usize)) + std::mem::size_of::<T2>();
1899 let full_slice = std::slice::from_raw_parts(base, totlen);
1900 Ok(self.writer.write_all(&full_slice[start..end])?)
1901 }
1902 pub fn save<T: WithSchema + Serialize>(
1905 writer: &mut W,
1906 version: u32,
1907 data: &T,
1908 with_compression: bool,
1909 ) -> Result<(), SavefileError> {
1910 Ok(Self::save_impl(
1911 writer,
1912 version,
1913 data,
1914 Some(T::schema(version, &mut WithSchemaContext::new())),
1915 with_compression,
1916 None,
1917 )?)
1918 }
1919 pub fn save_noschema<T: Serialize>(writer: &mut W, version: u32, data: &T) -> Result<(), SavefileError> {
1922 Ok(Self::save_impl(writer, version, data, None, false, None)?)
1923 }
1924
1925 #[doc(hidden)]
1926 pub fn save_noschema_internal<T: Serialize>(
1927 writer: &mut W,
1928 version: u32,
1929 data: &T,
1930 lib_version_override: u16,
1931 ) -> Result<(), SavefileError> {
1932 Ok(Self::save_impl(
1933 writer,
1934 version,
1935 data,
1936 None,
1937 false,
1938 Some(lib_version_override),
1939 )?)
1940 }
1941 pub fn bare_serialize<T: Serialize>(writer: &mut W, file_version: u32, data: &T) -> Result<(), SavefileError> {
1944 let mut serializer = Serializer { writer, file_version };
1945 data.serialize(&mut serializer)?;
1946 writer.flush()?;
1947 Ok(())
1948 }
1949
1950 #[inline(always)]
1951 fn save_impl<T: Serialize>(
1952 writer: &mut W,
1953 version: u32,
1954 data: &T,
1955 with_schema: Option<Schema>,
1956 with_compression: bool,
1957 lib_version_override: Option<u16>,
1958 ) -> Result<(), SavefileError> {
1959 let header = "savefile\0".to_string().into_bytes();
1960
1961 writer.write_all(&header)?; writer.write_u16::<LittleEndian>(
1964 lib_version_override.unwrap_or(CURRENT_SAVEFILE_LIB_VERSION), )?;
1966 writer.write_u32::<LittleEndian>(version)?;
1967 {
1969 if with_compression {
1970 writer.write_u8(1)?; #[cfg(feature = "bzip2")]
1973 {
1974 let mut compressed_writer = bzip2::write::BzEncoder::new(writer, Compression::best());
1975 if let Some(schema) = with_schema {
1976 let mut schema_serializer = Serializer::<bzip2::write::BzEncoder<W>>::new_raw(
1977 &mut compressed_writer,
1978 lib_version_override.unwrap_or(CURRENT_SAVEFILE_LIB_VERSION) as u32,
1979 );
1980 schema.serialize(&mut schema_serializer)?;
1981 }
1982
1983 let mut serializer = Serializer {
1984 writer: &mut compressed_writer,
1985 file_version: version,
1986 }; data.serialize(&mut serializer)?;
1988 compressed_writer.flush()?;
1989 return Ok(());
1990 }
1991 #[cfg(not(feature = "bzip2"))]
1992 {
1993 return Err(SavefileError::CompressionSupportNotCompiledIn);
1994 }
1995 } else {
1996 writer.write_u8(0)?;
1997 if let Some(schema) = with_schema {
1998 let mut schema_serializer = Serializer::<W>::new_raw(
1999 writer,
2000 lib_version_override.unwrap_or(CURRENT_SAVEFILE_LIB_VERSION) as u32,
2001 );
2002 schema.serialize(&mut schema_serializer)?;
2003 }
2004
2005 let mut serializer = Serializer {
2006 writer,
2007 file_version: version,
2008 };
2009 data.serialize(&mut serializer)?;
2010 writer.flush()?;
2011 Ok(())
2012 }
2013 }
2014 }
2015
2016 pub fn new_raw(writer: &mut impl Write, file_version: u32) -> Serializer<impl Write> {
2020 Serializer { writer, file_version }
2021 }
2022}
2023
2024impl<TR: Read> Deserializer<'_, TR> {
2025 pub fn read_bool(&mut self) -> Result<bool, SavefileError> {
2027 Ok(self.reader.read_u8()? == 1)
2028 }
2029 pub fn read_u8(&mut self) -> Result<u8, SavefileError> {
2031 let mut buf = [0u8];
2032 self.reader.read_exact(&mut buf)?;
2033 Ok(buf[0])
2034 }
2035 pub fn read_u16(&mut self) -> Result<u16, SavefileError> {
2037 Ok(self.reader.read_u16::<LittleEndian>()?)
2038 }
2039 pub fn read_u32(&mut self) -> Result<u32, SavefileError> {
2041 Ok(self.reader.read_u32::<LittleEndian>()?)
2042 }
2043 pub fn read_u64(&mut self) -> Result<u64, SavefileError> {
2045 Ok(self.reader.read_u64::<LittleEndian>()?)
2046 }
2047
2048 pub unsafe fn read_raw_ptr<T: ?Sized>(&mut self) -> Result<*const T, SavefileError> {
2052 let mut temp = MaybeUninit::<*const T>::zeroed();
2053
2054 let temp_data = &mut temp as *mut MaybeUninit<*const T> as *mut u8;
2055 let temp_size = std::mem::size_of::<*const T>();
2056 let buf = unsafe { slice::from_raw_parts_mut(temp_data, temp_size) };
2057
2058 self.read_bytes_to_buf(buf)?;
2059
2060 Ok(unsafe { temp.assume_init() })
2061 }
2062 pub unsafe fn read_raw_ptr_mut<T: ?Sized>(&mut self) -> Result<*mut T, SavefileError> {
2066 let mut temp = MaybeUninit::<*mut T>::zeroed();
2067
2068 let temp_data = &mut temp as *mut MaybeUninit<*mut T> as *mut u8;
2069 let temp_size = std::mem::size_of::<*mut T>();
2070 let buf = unsafe { slice::from_raw_parts_mut(temp_data, temp_size) };
2071
2072 self.read_bytes_to_buf(buf)?;
2073
2074 Ok(unsafe { temp.assume_init() })
2075 }
2076 pub fn read_ptr(&mut self) -> Result<*const (), SavefileError> {
2078 let mut ptr: MaybeUninit<*const ()> = MaybeUninit::zeroed();
2079 let data = ptr.as_mut_ptr();
2080 let target = unsafe { slice::from_raw_parts_mut(data as *mut u8, std::mem::size_of::<*const ()>()) };
2081 self.reader.read_exact(target)?;
2082 Ok(unsafe { ptr.assume_init() })
2083 }
2084 pub fn read_u128(&mut self) -> Result<u128, SavefileError> {
2086 Ok(self.reader.read_u128::<LittleEndian>()?)
2087 }
2088 pub fn read_i8(&mut self) -> Result<i8, SavefileError> {
2090 Ok(self.reader.read_i8()?)
2091 }
2092 pub fn read_i16(&mut self) -> Result<i16, SavefileError> {
2094 Ok(self.reader.read_i16::<LittleEndian>()?)
2095 }
2096 pub fn read_i32(&mut self) -> Result<i32, SavefileError> {
2098 Ok(self.reader.read_i32::<LittleEndian>()?)
2099 }
2100 pub fn read_i64(&mut self) -> Result<i64, SavefileError> {
2102 Ok(self.reader.read_i64::<LittleEndian>()?)
2103 }
2104 pub fn read_i128(&mut self) -> Result<i128, SavefileError> {
2106 Ok(self.reader.read_i128::<LittleEndian>()?)
2107 }
2108 pub fn read_f32(&mut self) -> Result<f32, SavefileError> {
2110 Ok(self.reader.read_f32::<LittleEndian>()?)
2111 }
2112 pub fn read_f64(&mut self) -> Result<f64, SavefileError> {
2114 Ok(self.reader.read_f64::<LittleEndian>()?)
2115 }
2116 pub fn read_isize(&mut self) -> Result<isize, SavefileError> {
2118 if let Ok(val) = TryFrom::try_from(self.reader.read_i64::<LittleEndian>()?) {
2119 Ok(val)
2120 } else {
2121 Err(SavefileError::SizeOverflow)
2122 }
2123 }
2124 pub fn read_usize(&mut self) -> Result<usize, SavefileError> {
2126 if let Ok(val) = TryFrom::try_from(self.reader.read_u64::<LittleEndian>()?) {
2127 Ok(val)
2128 } else {
2129 Err(SavefileError::SizeOverflow)
2130 }
2131 }
2132 pub fn read_string(&mut self) -> Result<String, SavefileError> {
2134 let l = self.read_usize()?;
2135 #[cfg(feature = "size_sanity_checks")]
2136 {
2137 if l > 1_000_000 {
2138 return Err(SavefileError::GeneralError {
2139 msg: format!("String too large: {}", l),
2140 });
2141 }
2142 }
2143 let mut v = vec![0; l];
2144 self.reader.read_exact(&mut v)?;
2145 Ok(String::from_utf8(v)?)
2146 }
2147
2148 pub fn read_bytes(&mut self, len: usize) -> Result<Vec<u8>, SavefileError> {
2150 let mut v = vec![0; len];
2151 self.reader.read_exact(&mut v)?;
2152 Ok(v)
2153 }
2154 pub fn read_bytes_to_buf(&mut self, buf: &mut [u8]) -> Result<(), SavefileError> {
2157 self.reader.read_exact(buf)?;
2158 Ok(())
2159 }
2160
2161 pub fn load<T: WithSchema + Deserialize>(reader: &mut TR, version: u32) -> Result<T, SavefileError> {
2165 Deserializer::<_>::load_impl::<T>(
2166 reader,
2167 version,
2168 Some(|version| T::schema(version, &mut WithSchemaContext::new())),
2169 )
2170 }
2171
2172 pub fn load_noschema<T: Deserialize>(reader: &mut TR, version: u32) -> Result<T, SavefileError> {
2176 let dummy: Option<fn(u32) -> Schema> = None;
2177 Deserializer::<TR>::load_impl::<T>(reader, version, dummy)
2178 }
2179
2180 pub fn bare_deserialize<T: Deserialize>(reader: &mut TR, file_version: u32) -> Result<T, SavefileError> {
2182 let mut deserializer = Deserializer {
2183 reader,
2184 file_version,
2185 ephemeral_state: HashMap::new(),
2186 };
2187 Ok(T::deserialize(&mut deserializer)?)
2188 }
2189
2190 #[inline(always)]
2191 fn load_impl<T: Deserialize>(
2192 reader: &mut TR,
2193 version: u32,
2194 expected_schema: Option<impl FnOnce(u32) -> Schema>,
2195 ) -> Result<T, SavefileError> {
2196 let mut head: [u8; 9] = [0u8; 9];
2197 reader.read_exact(&mut head)?;
2198
2199 if head[..] != ("savefile\0".to_string().into_bytes())[..] {
2200 return Err(SavefileError::GeneralError {
2201 msg: "File is not in new savefile-format.".into(),
2202 });
2203 }
2204
2205 let savefile_lib_version = reader.read_u16::<LittleEndian>()?;
2206 if savefile_lib_version > CURRENT_SAVEFILE_LIB_VERSION {
2207 return Err(SavefileError::GeneralError {
2208 msg: "This file has been created by a future, incompatible version of the savefile crate.".into(),
2209 });
2210 }
2211 let file_ver = reader.read_u32::<LittleEndian>()?;
2212
2213 if file_ver > version {
2214 return Err(SavefileError::WrongVersion {
2215 msg: format!(
2216 "File has later version ({}) than structs in memory ({}).",
2217 file_ver, version
2218 ),
2219 });
2220 }
2221 let with_compression = reader.read_u8()? != 0;
2222
2223 if with_compression {
2224 #[cfg(feature = "bzip2")]
2225 {
2226 let mut compressed_reader = bzip2::read::BzDecoder::new(reader);
2227 if let Some(memory_schema) = expected_schema {
2228 let mut schema_deserializer = new_schema_deserializer(&mut compressed_reader, savefile_lib_version);
2229 let memory_schema = memory_schema(file_ver);
2230 let file_schema = Schema::deserialize(&mut schema_deserializer)?;
2231
2232 if let Some(err) = diff_schema(&memory_schema, &file_schema, ".".to_string(), false) {
2233 return Err(SavefileError::IncompatibleSchema {
2234 message: format!(
2235 "Saved schema differs from in-memory schema for version {}. Error: {}",
2236 file_ver, err
2237 ),
2238 });
2239 }
2240 }
2241 let mut deserializer = Deserializer {
2242 reader: &mut compressed_reader,
2243 file_version: file_ver,
2244 ephemeral_state: HashMap::new(),
2245 };
2246 Ok(T::deserialize(&mut deserializer)?)
2247 }
2248 #[cfg(not(feature = "bzip2"))]
2249 {
2250 return Err(SavefileError::CompressionSupportNotCompiledIn);
2251 }
2252 } else {
2253 if let Some(memory_schema) = expected_schema {
2254 let mut schema_deserializer = new_schema_deserializer(reader, savefile_lib_version);
2255 let memory_schema = memory_schema(file_ver);
2256 let file_schema = Schema::deserialize(&mut schema_deserializer)?;
2257
2258 if let Some(err) = diff_schema(&memory_schema, &file_schema, ".".to_string(), false) {
2259 return Err(SavefileError::IncompatibleSchema {
2260 message: format!(
2261 "Saved schema differs from in-memory schema for version {}. Error: {}",
2262 file_ver, err
2263 ),
2264 });
2265 }
2266 }
2267 let mut deserializer = Deserializer {
2268 reader,
2269 file_version: file_ver,
2270 ephemeral_state: HashMap::new(),
2271 };
2272 Ok(T::deserialize(&mut deserializer)?)
2273 }
2274 }
2275}
2276
2277pub fn new_schema_deserializer(reader: &mut impl Read, file_schema_version: u16) -> Deserializer<impl Read> {
2281 Deserializer {
2282 reader,
2283 file_version: file_schema_version as u32,
2284 ephemeral_state: HashMap::new(),
2285 }
2286}
2287
2288pub fn load<T: WithSchema + Deserialize>(reader: &mut impl Read, version: u32) -> Result<T, SavefileError> {
2294 Deserializer::<_>::load::<T>(reader, version)
2295}
2296
2297pub fn load_from_mem<T: WithSchema + Deserialize>(input: &[u8], version: u32) -> Result<T, SavefileError> {
2303 let mut input = input;
2304 Deserializer::load::<T>(&mut input, version)
2305}
2306
2307pub fn save<T: WithSchema + Serialize>(writer: &mut impl Write, version: u32, data: &T) -> Result<(), SavefileError> {
2311 Serializer::save::<T>(writer, version, data, false)
2312}
2313
2314pub fn save_compressed<T: WithSchema + Serialize>(
2321 writer: &mut impl Write,
2322 version: u32,
2323 data: &T,
2324) -> Result<(), SavefileError> {
2325 Serializer::save::<T>(writer, version, data, true)
2326}
2327
2328pub fn save_file_compressed<T: WithSchema + Serialize, P: AsRef<Path>>(
2335 path: P,
2336 version: u32,
2337 data: &T,
2338) -> Result<(), SavefileError> {
2339 let mut f = BufWriter::new(File::create(path)?);
2340 Serializer::save::<T>(&mut f, version, data, true)
2341}
2342
2343pub fn save_to_mem<T: WithSchema + Serialize>(version: u32, data: &T) -> Result<Vec<u8>, SavefileError> {
2346 let mut retval = Vec::new();
2347 Serializer::save::<T>(&mut retval, version, data, false)?;
2348 Ok(retval)
2349}
2350
2351pub fn load_noschema<T: Deserialize>(reader: &mut impl Read, version: u32) -> Result<T, SavefileError> {
2354 Deserializer::<_>::load_noschema::<T>(reader, version)
2355}
2356
2357pub fn save_noschema<T: Serialize>(writer: &mut impl Write, version: u32, data: &T) -> Result<(), SavefileError> {
2368 Serializer::save_noschema::<T>(writer, version, data)
2369}
2370
2371pub fn load_file<T: WithSchema + Deserialize, P: AsRef<Path>>(filepath: P, version: u32) -> Result<T, SavefileError> {
2374 let mut f = BufReader::new(File::open(filepath)?);
2375 Deserializer::load::<T>(&mut f, version)
2376}
2377
2378pub fn save_file<T: WithSchema + Serialize, P: AsRef<Path>>(
2381 filepath: P,
2382 version: u32,
2383 data: &T,
2384) -> Result<(), SavefileError> {
2385 let mut f = BufWriter::new(File::create(filepath)?);
2386 Serializer::save::<T>(&mut f, version, data, false)
2387}
2388
2389pub fn load_file_noschema<T: Deserialize, P: AsRef<Path>>(filepath: P, version: u32) -> Result<T, SavefileError> {
2392 let mut f = BufReader::new(File::open(filepath)?);
2393 Deserializer::load_noschema::<T>(&mut f, version)
2394}
2395
2396pub fn save_file_noschema<T: Serialize, P: AsRef<Path>>(
2401 filepath: P,
2402 version: u32,
2403 data: &T,
2404) -> Result<(), SavefileError> {
2405 let mut f = BufWriter::new(File::create(filepath)?);
2406 Serializer::save_noschema::<T>(&mut f, version, data)
2407}
2408
2409pub struct WithSchemaContext {
2418 seen_types: HashMap<TypeId, usize >,
2419}
2420
2421impl WithSchemaContext {
2422 pub fn new() -> WithSchemaContext {
2425 let seen_types = HashMap::new();
2426 WithSchemaContext { seen_types }
2427 }
2428}
2429
2430impl WithSchemaContext {
2431 pub fn possible_recursion<T: 'static>(&mut self, cb: impl FnOnce(&mut WithSchemaContext) -> Schema) -> Schema {
2451 let typeid = TypeId::of::<T>();
2452 let prevlen = self.seen_types.len();
2453 match self.seen_types.entry(typeid) {
2454 Entry::Occupied(occ) => {
2455 let present_value_depth = *occ.get();
2456 return Schema::Recursion(prevlen - present_value_depth);
2457 }
2458 Entry::Vacant(vac) => {
2459 vac.insert(prevlen);
2460 }
2461 }
2462 let ret = (cb)(self);
2463 self.seen_types.remove(&typeid);
2464 ret
2465 }
2466}
2467
2468#[cfg_attr(
2477 feature = "rust1_78",
2478 diagnostic::on_unimplemented(
2479 message = "`{Self}` does not have a defined schema for savefile, since it doesn't implement the trait `savefile::WithSchema`",
2480 label = "This cannot be serialized or deserialized with a schema",
2481 note = "You can implement it by adding `#[derive(Savefile)]` before the declaration of `{Self}`",
2482 note = "Or you can manually implement the `savefile::WithSchema` trait.",
2483 note = "You can also use one of the `*_noschema` functions to save/load without a schema."
2484 )
2485)]
2486pub trait WithSchema {
2487 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema;
2491}
2492
2493pub fn get_schema<T: WithSchema + 'static>(version: u32) -> Schema {
2496 T::schema(version, &mut WithSchemaContext::new())
2497}
2498
2499pub fn get_result_schema(ok: Schema, err: Schema) -> Schema {
2502 Schema::Enum(SchemaEnum {
2503 dbg_name: "Result".to_string(),
2504 size: None,
2505 alignment: None,
2506 variants: vec![
2507 Variant {
2508 name: "Ok".to_string(),
2509 discriminant: 0,
2510 fields: vec![Field {
2511 name: "ok".to_string(),
2512 value: Box::new(ok),
2513 offset: None,
2514 }],
2515 },
2516 Variant {
2517 name: "Err".to_string(),
2518 discriminant: 0,
2519 fields: vec![Field {
2520 name: "err".to_string(),
2521 value: Box::new(err),
2522 offset: None,
2523 }],
2524 },
2525 ],
2526 discriminant_size: 1,
2527 has_explicit_repr: false,
2528 })
2529}
2530
2531#[cfg_attr(
2543 feature = "rust1_78",
2544 diagnostic::on_unimplemented(
2545 message = "`{Self}` cannot be serialized by Savefile, since it doesn't implement the trait `savefile::Serialize`",
2546 label = "This cannot be serialized",
2547 note = "You can implement it by adding `#[derive(Savefile)]` before the declaration of `{Self}`",
2548 note = "Or you can manually implement the `savefile::Serialize` trait."
2549 )
2550)]
2551pub trait Serialize: WithSchema {
2552 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError>; }
2558
2559#[cfg_attr(
2566 feature = "rust1_78",
2567 diagnostic::on_unimplemented(
2568 message = "`{Self}` cannot be an introspected value used by Savefile, since it doesn't implement the trait `savefile::IntrospectItem`",
2569 label = "This cannot be the type of an introspected field value",
2570 note = "You can possibly implement IntrospectItem manually for the type `{Self}`, or try to use `String` instead of `{Self}`."
2571 )
2572)]
2573pub trait IntrospectItem<'a> {
2574 fn key(&self) -> &str;
2577 fn val(&self) -> &dyn Introspect;
2579}
2580
2581struct NullIntrospectable {}
2584static THE_NULL_INTROSPECTABLE: NullIntrospectable = NullIntrospectable {};
2585
2586impl Introspect for NullIntrospectable {
2587 fn introspect_value(&self) -> String {
2588 String::new()
2589 }
2590
2591 fn introspect_child<'a>(&'a self, _index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
2592 None
2593 }
2594 fn introspect_len(&self) -> usize {
2595 0
2596 }
2597}
2598
2599impl IntrospectItem<'_> for str {
2600 fn key(&self) -> &str {
2601 self
2602 }
2603
2604 fn val(&self) -> &dyn Introspect {
2605 &THE_NULL_INTROSPECTABLE
2606 }
2607}
2608
2609impl IntrospectItem<'_> for String {
2610 fn key(&self) -> &str {
2611 self
2612 }
2613
2614 fn val(&self) -> &dyn Introspect {
2615 &THE_NULL_INTROSPECTABLE
2616 }
2617}
2618
2619pub const MAX_CHILDREN: usize = 10000;
2625
2626#[cfg_attr(
2628 feature = "rust1_78",
2629 diagnostic::on_unimplemented(
2630 message = "`{Self}` cannot be introspected by Savefile, since it doesn't implement trait `savefile::Introspect`",
2631 label = "This cannot be introspected",
2632 note = "If you get this message after having used the #[savefile_ignore] attribute on a field, consider adding #[savefile_introspect_ignore].",
2633 note = "You can implement it by adding `#[derive(Savefile)]` or `#[derive(SavefileIntrospectOnly)]` before the declaration of `{Self}`",
2634 note = "Or you can manually implement the `savefile::Introspect` trait."
2635 )
2636)]
2637pub trait Introspect {
2638 fn introspect_value(&self) -> String;
2646
2647 fn introspect_child<'a>(&'a self, index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>>;
2654
2655 fn introspect_len(&self) -> usize {
2661 for child_index in 0..MAX_CHILDREN {
2662 if self.introspect_child(child_index).is_none() {
2663 return child_index;
2664 }
2665 }
2666 return MAX_CHILDREN;
2667 }
2668}
2669
2670#[cfg_attr(
2678 feature = "rust1_78",
2679 diagnostic::on_unimplemented(
2680 message = "`{Self}` cannot be deserialized by Savefile, since it doesn't implement the trait `savefile::Deserialize`",
2681 label = "This cannot be deserialized",
2682 note = "You can implement it by adding `#[derive(Savefile)]` before the declaration of `{Self}`",
2683 note = "Or you can manually implement the `savefile::Deserialize` trait."
2684 )
2685)]
2686pub trait Deserialize: WithSchema + Sized {
2687 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError>; }
2690
2691#[derive(Debug, PartialEq, Clone)]
2694#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
2695pub struct Field {
2696 pub name: String,
2698 pub value: Box<Schema>,
2700 offset: Option<usize>,
2710}
2711
2712impl Field {
2713 pub fn new(name: String, value: Box<Schema>) -> Field {
2715 Field {
2716 name,
2717 value,
2718 offset: None,
2719 }
2720 }
2721 pub unsafe fn unsafe_new(name: String, value: Box<Schema>, offset: Option<usize>) -> Field {
2727 Field { name, value, offset }
2728 }
2729 pub fn layout_compatible(&self, other: &Field) -> bool {
2731 let (Some(offset_a), Some(offset_b)) = (self.offset, other.offset) else {
2732 return false;
2733 };
2734 if offset_a != offset_b {
2735 return false;
2736 }
2737 self.value.layout_compatible(&other.value)
2738 }
2739}
2740
2741#[derive(Debug, PartialEq, Clone)]
2745#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
2746pub struct SchemaArray {
2747 pub item_type: Box<Schema>,
2749 pub count: usize,
2751}
2752
2753impl SchemaArray {
2754 fn layout_compatible(&self, other: &SchemaArray) -> bool {
2755 if self.count != other.count {
2756 return false;
2757 }
2758 self.item_type.layout_compatible(&other.item_type)
2759 }
2760 fn serialized_size(&self) -> Option<usize> {
2761 self.item_type.serialized_size().map(|x| x * self.count)
2762 }
2763}
2764
2765#[derive(Debug, PartialEq, Clone)]
2774#[repr(C)]
2775#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
2776pub struct SchemaStruct {
2777 pub dbg_name: String,
2779 size: Option<usize>,
2782 alignment: Option<usize>,
2785 pub fields: Vec<Field>,
2787}
2788fn maybe_add(a: Option<usize>, b: Option<usize>) -> Option<usize> {
2789 if let Some(a) = a {
2790 if let Some(b) = b {
2791 return Some(a + b);
2792 }
2793 }
2794 None
2795}
2796impl SchemaStruct {
2797 pub fn new(dbg_name: String, fields: Vec<Field>) -> SchemaStruct {
2800 SchemaStruct {
2801 dbg_name,
2802 fields,
2803 size: None,
2804 alignment: None,
2805 }
2806 }
2807 pub fn new_unsafe(
2814 dbg_name: String,
2815 fields: Vec<Field>,
2816 size: Option<usize>,
2817 alignment: Option<usize>,
2818 ) -> SchemaStruct {
2819 SchemaStruct {
2820 dbg_name,
2821 fields,
2822 size,
2823 alignment,
2824 }
2825 }
2826
2827 fn layout_compatible(&self, other: &SchemaStruct) -> bool {
2828 if self.fields.len() != other.fields.len() {
2829 return false;
2830 }
2831 if self.alignment.is_none() || self.size.is_none() {
2832 return false;
2833 }
2834 if self.alignment != other.alignment || self.size != other.size {
2835 return false;
2836 }
2837 for (a, b) in self.fields.iter().zip(other.fields.iter()) {
2838 if !a.layout_compatible(b) {
2839 return false;
2840 }
2841 }
2842 true
2843 }
2844 fn serialized_size(&self) -> Option<usize> {
2845 self.fields
2846 .iter()
2847 .fold(Some(0usize), |prev, x| maybe_add(prev, x.value.serialized_size()))
2848 }
2849}
2850
2851#[derive(Debug, PartialEq, Clone)]
2854#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
2855pub struct Variant {
2856 pub name: String,
2858 pub discriminant: u8,
2860 pub fields: Vec<Field>,
2862}
2863impl Variant {
2864 fn layout_compatible(&self, other: &Variant) -> bool {
2865 if self.discriminant != other.discriminant {
2866 return false;
2867 }
2868 if self.fields.len() != other.fields.len() {
2869 return false;
2870 }
2871 for (a, b) in self.fields.iter().zip(other.fields.iter()) {
2872 if !a.layout_compatible(b) {
2873 return false;
2874 }
2875 }
2876 true
2877 }
2878 fn serialized_size(&self) -> Option<usize> {
2879 self.fields
2880 .iter()
2881 .fold(Some(0usize), |prev, x| maybe_add(prev, x.value.serialized_size()))
2882 }
2883}
2884
2885#[derive(Debug, PartialEq, Clone)]
2897#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
2898pub struct SchemaEnum {
2899 pub dbg_name: String,
2901 pub variants: Vec<Variant>,
2903 pub discriminant_size: u8,
2908 has_explicit_repr: bool,
2911 size: Option<usize>,
2913 alignment: Option<usize>,
2915}
2916
2917fn maybe_max(a: Option<usize>, b: Option<usize>) -> Option<usize> {
2918 if let Some(a) = a {
2919 if let Some(b) = b {
2920 return Some(a.max(b));
2921 }
2922 }
2923 None
2924}
2925impl SchemaEnum {
2926 pub fn new(dbg_name: String, discriminant_size: u8, variants: Vec<Variant>) -> SchemaEnum {
2938 SchemaEnum {
2939 dbg_name,
2940 variants,
2941 discriminant_size,
2942 has_explicit_repr: false,
2943 size: None,
2944 alignment: None,
2945 }
2946 }
2947 pub fn new_unsafe(
2966 dbg_name: String,
2967 variants: Vec<Variant>,
2968 discriminant_size: u8,
2969 has_explicit_repr: bool,
2970 size: Option<usize>,
2971 alignment: Option<usize>,
2972 ) -> SchemaEnum {
2973 SchemaEnum {
2974 dbg_name,
2975 variants,
2976 discriminant_size,
2977 has_explicit_repr,
2978 size,
2979 alignment,
2980 }
2981 }
2982 fn layout_compatible(&self, other: &SchemaEnum) -> bool {
2983 if self.has_explicit_repr == false || other.has_explicit_repr == false {
2984 return false;
2985 }
2986 if self.alignment.is_none() || self.size.is_none() {
2987 return false;
2988 }
2989 if self.alignment != other.alignment || self.size != other.size {
2990 return false;
2991 }
2992 if self.discriminant_size != other.discriminant_size {
2993 return false;
2994 }
2995 if self.variants.len() != other.variants.len() {
2996 return false;
2997 }
2998 for (a, b) in self.variants.iter().zip(other.variants.iter()) {
2999 if !a.layout_compatible(b) {
3000 return false;
3001 }
3002 }
3003 true
3004 }
3005 fn serialized_size(&self) -> Option<usize> {
3006 let discr_size = 1usize; self.variants
3008 .iter()
3009 .fold(Some(discr_size), |prev, x| maybe_max(prev, x.serialized_size()))
3010 }
3011}
3012
3013#[allow(non_camel_case_types)]
3022#[derive(Copy, Clone, Debug, PartialEq)]
3023#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
3024pub enum SchemaPrimitive {
3025 schema_i8,
3027 schema_u8,
3029 schema_i16,
3031 schema_u16,
3033 schema_i32,
3035 schema_u32,
3037 schema_i64,
3039 schema_u64,
3041 schema_string(VecOrStringLayout),
3043 schema_f32,
3045 schema_f64,
3047 schema_bool,
3049 schema_canary1,
3051 schema_u128,
3053 schema_i128,
3055 schema_char,
3057}
3058impl SchemaPrimitive {
3059 fn layout_compatible(&self, other: &SchemaPrimitive) -> bool {
3060 if let (SchemaPrimitive::schema_string(layout1), SchemaPrimitive::schema_string(layout2)) = (self, other) {
3061 if *layout1 == VecOrStringLayout::Unknown || *layout2 == VecOrStringLayout::Unknown {
3062 return false;
3063 }
3064 }
3065 self == other
3066 }
3067 fn name(&self) -> &'static str {
3068 match *self {
3069 SchemaPrimitive::schema_i8 => "i8",
3070 SchemaPrimitive::schema_u8 => "u8",
3071 SchemaPrimitive::schema_i16 => "i16",
3072 SchemaPrimitive::schema_u16 => "u16",
3073 SchemaPrimitive::schema_i32 => "i32",
3074 SchemaPrimitive::schema_u32 => "u32",
3075 SchemaPrimitive::schema_i64 => "i64",
3076 SchemaPrimitive::schema_u64 => "u64",
3077 SchemaPrimitive::schema_string(_) => "String",
3078 SchemaPrimitive::schema_f32 => "f32",
3079 SchemaPrimitive::schema_f64 => "f64",
3080 SchemaPrimitive::schema_bool => "bool",
3081 SchemaPrimitive::schema_canary1 => "u32",
3082 SchemaPrimitive::schema_u128 => "u128",
3083 SchemaPrimitive::schema_i128 => "i128",
3084 SchemaPrimitive::schema_char => "char",
3085 }
3086 }
3087
3088 fn serialized_size(&self) -> Option<usize> {
3089 match *self {
3090 SchemaPrimitive::schema_i8 | SchemaPrimitive::schema_u8 => Some(1),
3091 SchemaPrimitive::schema_i16 | SchemaPrimitive::schema_u16 => Some(2),
3092 SchemaPrimitive::schema_i32 | SchemaPrimitive::schema_u32 => Some(4),
3093 SchemaPrimitive::schema_i64 | SchemaPrimitive::schema_u64 => Some(8),
3094 SchemaPrimitive::schema_string(_) => None,
3095 SchemaPrimitive::schema_f32 => Some(4),
3096 SchemaPrimitive::schema_f64 => Some(8),
3097 SchemaPrimitive::schema_bool => Some(1),
3098 SchemaPrimitive::schema_canary1 => Some(4),
3099 SchemaPrimitive::schema_i128 | SchemaPrimitive::schema_u128 => Some(16),
3100 SchemaPrimitive::schema_char => Some(4),
3101 }
3102 }
3103}
3104
3105fn diff_primitive(a: SchemaPrimitive, b: SchemaPrimitive, path: &str) -> Option<String> {
3106 if a != b {
3107 if let (SchemaPrimitive::schema_string(_), SchemaPrimitive::schema_string(_)) = (&a, &b) {
3108 return None; }
3110 return Some(format!(
3111 "At location [{}]: Application protocol has datatype {}, but disk format has {}",
3112 path,
3113 a.name(),
3114 b.name()
3115 ));
3116 }
3117 None
3118}
3119
3120#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
3124#[repr(u8)]
3125#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
3126pub enum VecOrStringLayout {
3127 #[default]
3128 Unknown,
3130 DataCapacityLength,
3132 DataLengthCapacity,
3134 CapacityDataLength,
3136 LengthDataCapacity,
3138 CapacityLengthData,
3140 LengthCapacityData,
3142 LengthData,
3144 DataLength,
3146}
3147
3148impl Packed for AbiMethodArgument {}
3149
3150#[derive(Debug, PartialEq, Clone)]
3152#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
3153pub struct AbiMethodArgument {
3154 pub schema: Schema,
3159}
3160
3161impl Deserialize for AbiMethodArgument {
3162 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
3163 Ok(AbiMethodArgument {
3164 schema: <_ as Deserialize>::deserialize(deserializer)?,
3165 })
3166 }
3167}
3168
3169impl WithSchema for AbiMethodArgument {
3170 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
3171 Schema::Undefined
3172 }
3173}
3174
3175impl Serialize for AbiMethodArgument {
3176 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
3177 self.schema.serialize(serializer)?;
3178 Ok(())
3179 }
3180}
3181
3182#[non_exhaustive]
3184#[derive(PartialEq, Debug, Clone, Copy)]
3185#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
3186#[repr(u8)]
3187pub enum ReceiverType {
3188 Shared, Mut, PinMut, }
3195
3196#[derive(Debug, PartialEq, Clone)]
3198#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
3199pub struct AbiMethodInfo {
3200 pub return_value: Schema,
3202 pub receiver: ReceiverType,
3204 pub arguments: Vec<AbiMethodArgument>,
3206 pub async_trait_heuristic: bool,
3209}
3210
3211impl Packed for AbiMethodInfo {}
3212impl WithSchema for AbiMethodInfo {
3213 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
3214 Schema::Undefined
3215 }
3216}
3217
3218impl Serialize for AbiMethodInfo {
3219 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
3220 self.return_value.serialize(serializer)?;
3221 if serializer.file_version >= 2 {
3222 serializer.write_u8(match self.receiver {
3223 ReceiverType::Shared => 100,
3224 ReceiverType::Mut => 101,
3225 ReceiverType::PinMut => 102,
3226 })?;
3227 serializer.write_bool(self.async_trait_heuristic)?;
3228 }
3229 self.arguments.serialize(serializer)?;
3230 Ok(())
3231 }
3232}
3233impl Deserialize for AbiMethodInfo {
3234 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
3235 let return_value = <_ as Deserialize>::deserialize(deserializer)?;
3236 let async_trait_heuristic;
3237 let receiver;
3238 if deserializer.file_version >= 2 {
3239 receiver = match deserializer.read_u8()? {
3240 100 => ReceiverType::Shared,
3241 101 => ReceiverType::Mut,
3242 102 => ReceiverType::PinMut,
3243 x => return Err(SavefileError::WrongVersion {
3244 msg: format!("Version 0.17.x (or earlier) of the savefile-library detected. It is not compatible with the current version. Please upgrade to version >0.18. Unexpected value: {}", x),
3245 }),
3246 };
3247 async_trait_heuristic = deserializer.read_bool()?;
3248 } else {
3249 receiver = ReceiverType::Shared;
3250 async_trait_heuristic = false;
3251 };
3252 Ok(AbiMethodInfo {
3253 return_value,
3254 receiver,
3255 arguments: <_ as Deserialize>::deserialize(deserializer)?,
3256 async_trait_heuristic,
3257 })
3258 }
3259}
3260
3261#[derive(Debug, PartialEq, Clone)]
3264#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
3265pub struct AbiMethod {
3266 pub name: String,
3268 pub info: AbiMethodInfo,
3270}
3271impl Packed for AbiMethod {}
3272impl WithSchema for AbiMethod {
3273 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
3274 Schema::Undefined
3275 }
3276}
3277impl Serialize for AbiMethod {
3278 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
3279 self.name.serialize(serializer)?;
3280 self.info.serialize(serializer)?;
3281 Ok(())
3282 }
3283}
3284impl Deserialize for AbiMethod {
3285 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
3286 Ok(AbiMethod {
3287 name: <_ as Deserialize>::deserialize(deserializer)?,
3288 info: <_ as Deserialize>::deserialize(deserializer)?,
3289 })
3290 }
3291}
3292
3293#[derive(Default, Debug, PartialEq, Clone)]
3295#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
3296pub struct AbiTraitDefinition {
3297 pub name: String,
3299 pub methods: Vec<AbiMethod>,
3301 pub sync: bool,
3303 pub send: bool,
3305}
3306impl Packed for AbiTraitDefinition {}
3307impl WithSchema for AbiTraitDefinition {
3308 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
3309 Schema::Undefined
3310 }
3311}
3312impl Serialize for AbiTraitDefinition {
3313 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
3314 let mut effective_name = self.name.clone();
3315 if self.sync {
3316 effective_name += "+Sync";
3317 }
3318 if self.send {
3319 effective_name += "+Send";
3320 }
3321 effective_name.serialize(serializer)?;
3322 self.methods.serialize(serializer)?;
3323 Ok(())
3324 }
3325}
3326impl Deserialize for AbiTraitDefinition {
3327 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
3328 let name: String = <_ as Deserialize>::deserialize(deserializer)?;
3329
3330 let actual_name = name.split('+').next().unwrap();
3331 let mut sync = false;
3332 let mut send = false;
3333 for segment in name.split('+').skip(1) {
3334 match segment {
3335 "Sync" => sync = true,
3336 "Send" => send = true,
3337 _ => panic!("Unexpected trait name encountered: {}", name),
3338 }
3339 }
3340
3341 let t = AbiTraitDefinition {
3342 name: actual_name.to_string(),
3343 methods: <_ as Deserialize>::deserialize(deserializer)?,
3344 sync,
3345 send,
3346 };
3347 Ok(t)
3348 }
3349}
3350
3351impl AbiTraitDefinition {
3352 fn verify_compatible_with_old_impl(
3365 &self,
3366 old_version: u32,
3367 old: &AbiTraitDefinition,
3368 is_return_position: bool,
3369 ) -> Result<(), String> {
3370 if is_return_position {
3371 if !old.sync && self.sync {
3372 return Err(format!("Trait {} was not Sync in version {}, but the Sync-bound has since been added. This is not a backward-compatible change.",
3373 self.name, old_version,
3374 ));
3375 }
3376 if !old.send && self.send {
3377 return Err(format!("Trait {} was not Send in version {}, but the Send-bound has since been added. This is not a backward-compatible change.",
3378 self.name, old_version,
3379 ));
3380 }
3381 } else {
3382 if old.sync && !self.sync {
3383 return Err(format!("Trait {} was Sync in version {}, but the Sync-bound has since been removed. This is not a backward-compatible change.",
3384 self.name, old_version,
3385 ));
3386 }
3387 if old.send && !self.send {
3388 return Err(format!("Trait {} was Send in version {}, but the Send-bound has since been removed. This is not a backward-compatible change.",
3389 self.name, old_version,
3390 ));
3391 }
3392 }
3393
3394 for old_method in old.methods.iter() {
3395 let Some(new_method) = self.methods.iter().find(|x| x.name == old_method.name) else {
3396 return Err(format!("In trait {}, the method {} existed in version {}, but has been removed. This is not a backward-compatible change.",
3397 self.name, old_method.name, old_version,
3398 ));
3399 };
3400 if new_method.info.async_trait_heuristic != old_method.info.async_trait_heuristic {
3401 if old_method.info.async_trait_heuristic {
3402 return Err(format!("In trait {}, the method {} was previously async, using #[async_trait], but it does no longer. This is not a backward-compatible change.",
3403 self.name, old_method.name
3404 ));
3405 } else {
3406 return Err(format!("In trait {}, the method {} is now async, using #[async_trait], but it previously did not. This is not a backward-compatible change.",
3407 self.name, old_method.name
3408 ));
3409 }
3410 }
3411 if new_method.info.arguments.len() != old_method.info.arguments.len() {
3412 return Err(format!("In trait {}, method {}, the number of arguments has changed from {} in version {} to {}. This is not a backward-compatible change.",
3413 self.name, old_method.name, old_method.info.arguments.len(), old_version, new_method.info.arguments.len()
3414 ));
3415 }
3416 if let Some(diff) = diff_schema(
3417 &new_method.info.return_value,
3418 &old_method.info.return_value,
3419 "".into(),
3420 is_return_position,
3421 ) {
3422 return Err(format!("In trait {}, method {}, the return value type has changed from version {}: {}. This is not a backward-compatible change.",
3423 self.name, old_method.name, old_version, diff
3424 ));
3425 }
3426 for (arg_index, (new_arg, old_arg)) in new_method
3427 .info
3428 .arguments
3429 .iter()
3430 .zip(old_method.info.arguments.iter())
3431 .enumerate()
3432 {
3433 if let Some(diff) = diff_schema(&new_arg.schema, &old_arg.schema, "".into(), is_return_position) {
3434 return Err(format!("In trait {}, method {}, argument {}, the type has changed from version {}: {}. This is not a backward-compatible change.",
3435 self.name, old_method.name, arg_index , old_version, diff
3436 ));
3437 }
3438 }
3439 }
3440
3441 Ok(())
3442 }
3443
3444 pub fn verify_backward_compatible(
3450 &self,
3451 old_version: u32,
3452 old: &AbiTraitDefinition,
3453 is_return_position: bool,
3454 ) -> Result<(), SavefileError> {
3455 self.verify_compatible_with_old_impl(old_version, old, is_return_position)
3456 .map_err(|x| SavefileError::IncompatibleSchema { message: x })
3457 }
3458}
3459
3460#[derive(Debug, PartialEq, Clone)]
3479#[repr(C, u32)]
3480#[cfg_attr(feature = "serde_derive", derive(Serialize, Deserialize))]
3481#[non_exhaustive]
3482pub enum Schema {
3483 Struct(SchemaStruct),
3485 Enum(SchemaEnum),
3487 Primitive(SchemaPrimitive),
3489 Vector(Box<Schema>, VecOrStringLayout ),
3492 Array(SchemaArray),
3495 SchemaOption(Box<Schema>),
3498 Undefined,
3501 ZeroSize,
3504 Custom(String),
3509 Boxed(Box<Schema>),
3513 Slice(Box<Schema>),
3517 Str,
3521 Reference(Box<Schema>),
3526 Trait(bool , AbiTraitDefinition),
3530 FnClosure(bool , AbiTraitDefinition),
3538 Recursion(usize ),
3545 StdIoError,
3547 Future(
3549 AbiTraitDefinition,
3550 bool,
3551 bool,
3552 bool,
3553 ),
3554 UninitSlice,
3556}
3557impl Introspect for Schema {
3559 fn introspect_value(&self) -> String {
3560 "Schema".to_string()
3561 }
3562
3563 fn introspect_child<'a>(&'a self, _index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
3564 None
3565 }
3566}
3567
3568impl Schema {
3569 pub fn top_level_description(&self) -> String {
3572 match self {
3573 Schema::Struct(_) => "struct".into(),
3574 Schema::Enum(_) => "enum".into(),
3575 Schema::Primitive(_) => "primitive".into(),
3576 Schema::Vector(_, _) => "vector".into(),
3577 Schema::Array(_) => "array".into(),
3578 Schema::SchemaOption(_) => "option".into(),
3579 Schema::Undefined => "undefined".into(),
3580 Schema::ZeroSize => "zerosize".into(),
3581 Schema::Custom(_) => "custom".into(),
3582 Schema::Boxed(_) => "box".into(),
3583 Schema::FnClosure(_, _) => "fntrait".into(),
3584 Schema::Slice(_) => "slice".into(),
3585 Schema::Str => "str".into(),
3586 Schema::Reference(_) => "reference".into(),
3587 Schema::Trait(_, _) => "trait".into(),
3588 Schema::Recursion(depth) => {
3589 format!("<recursion {}>", depth)
3590 }
3591 Schema::StdIoError => "stdioerror".into(),
3592 Schema::Future(_, _, _, _) => "future".into(),
3593 Schema::UninitSlice => {"UninitSlice".into()}
3594 }
3595 }
3596 pub fn layout_compatible(&self, b_native: &Schema) -> bool {
3598 match (self, b_native) {
3599 (Schema::Struct(a), Schema::Struct(b)) => a.layout_compatible(b),
3600 (Schema::Enum(a), Schema::Enum(b)) => a.layout_compatible(b),
3601 (Schema::Primitive(a), Schema::Primitive(b)) => a.layout_compatible(b),
3602 (Schema::Vector(a, a_standard_layout), Schema::Vector(b, b_standard_layout)) => {
3603 a.layout_compatible(b)
3604 && *a_standard_layout != VecOrStringLayout::Unknown
3605 && *b_standard_layout != VecOrStringLayout::Unknown
3606 && *a_standard_layout == *b_standard_layout
3607 }
3608 (Schema::Array(a), Schema::Array(b)) => a.layout_compatible(b),
3609 (Schema::SchemaOption(_), Schema::SchemaOption(_)) => {
3610 false }
3612 (Schema::ZeroSize, Schema::ZeroSize) => true,
3613 (Schema::Custom(_), Schema::Custom(_)) => {
3614 false }
3616 (Schema::FnClosure(_a1, _a2), Schema::FnClosure(_b1, _b2)) => {
3617 false
3620 }
3621 (Schema::Boxed(a), Schema::Boxed(b)) => {
3622 a.layout_compatible(b)
3627 }
3628 (Schema::Reference(a), Schema::Reference(b)) => a.layout_compatible(b),
3629 (Schema::Slice(a), Schema::Slice(b)) => a.layout_compatible(b),
3630 _ => false,
3631 }
3632 }
3633 pub fn new_tuple1<T1: WithSchema>(version: u32, context: &mut WithSchemaContext) -> Schema {
3635 let schema = Box::new(T1::schema(version, context));
3636 Schema::Struct(SchemaStruct {
3637 dbg_name: "1-Tuple".to_string(),
3638 size: Some(std::mem::size_of::<(T1,)>()),
3639 alignment: Some(std::mem::align_of::<(T1,)>()),
3640 fields: vec![Field {
3641 name: "0".to_string(),
3642 value: schema,
3643 offset: Some(offset_of_tuple!((T1,), 0)),
3644 }],
3645 })
3646 }
3647
3648 pub fn new_tuple2<T1: WithSchema, T2: WithSchema>(version: u32, context: &mut WithSchemaContext) -> Schema {
3650 Schema::Struct(SchemaStruct {
3651 dbg_name: "2-Tuple".to_string(),
3652 size: Some(std::mem::size_of::<(T1, T2)>()),
3653 alignment: Some(std::mem::align_of::<(T1, T2)>()),
3654 fields: vec![
3655 Field {
3656 name: "0".to_string(),
3657 value: Box::new(T1::schema(version, context)),
3658 offset: Some(offset_of_tuple!((T1, T2), 0)),
3659 },
3660 Field {
3661 name: "1".to_string(),
3662 value: Box::new(T2::schema(version, context)),
3663 offset: Some(offset_of_tuple!((T1, T2), 1)),
3664 },
3665 ],
3666 })
3667 }
3668 pub fn new_tuple3<T1: WithSchema, T2: WithSchema, T3: WithSchema>(
3670 version: u32,
3671 context: &mut WithSchemaContext,
3672 ) -> Schema {
3673 Schema::Struct(SchemaStruct {
3674 dbg_name: "3-Tuple".to_string(),
3675 size: Some(std::mem::size_of::<(T1, T2, T3)>()),
3676 alignment: Some(std::mem::align_of::<(T1, T2, T3)>()),
3677 fields: vec![
3678 Field {
3679 name: "0".to_string(),
3680 value: Box::new(T1::schema(version, context)),
3681 offset: Some(offset_of_tuple!((T1, T2, T3), 0)),
3682 },
3683 Field {
3684 name: "1".to_string(),
3685 value: Box::new(T2::schema(version, context)),
3686 offset: Some(offset_of_tuple!((T1, T2, T3), 1)),
3687 },
3688 Field {
3689 name: "2".to_string(),
3690 value: Box::new(T3::schema(version, context)),
3691 offset: Some(offset_of_tuple!((T1, T2, T3), 2)),
3692 },
3693 ],
3694 })
3695 }
3696 pub fn new_tuple4<T1: WithSchema, T2: WithSchema, T3: WithSchema, T4: WithSchema>(
3698 version: u32,
3699 context: &mut WithSchemaContext,
3700 ) -> Schema {
3701 Schema::Struct(SchemaStruct {
3702 dbg_name: "4-Tuple".to_string(),
3703 size: Some(std::mem::size_of::<(T1, T2, T3, T4)>()),
3704 alignment: Some(std::mem::align_of::<(T1, T2, T3, T4)>()),
3705 fields: vec![
3706 Field {
3707 name: "0".to_string(),
3708 value: Box::new(T1::schema(version, context)),
3709 offset: Some(offset_of_tuple!((T1, T2, T3, T4), 0)),
3710 },
3711 Field {
3712 name: "1".to_string(),
3713 value: Box::new(T2::schema(version, context)),
3714 offset: Some(offset_of_tuple!((T1, T2, T3, T4), 1)),
3715 },
3716 Field {
3717 name: "2".to_string(),
3718 value: Box::new(T3::schema(version, context)),
3719 offset: Some(offset_of_tuple!((T1, T2, T3, T4), 2)),
3720 },
3721 Field {
3722 name: "3".to_string(),
3723 value: Box::new(T4::schema(version, context)),
3724 offset: Some(offset_of_tuple!((T1, T2, T3, T4), 3)),
3725 },
3726 ],
3727 })
3728 }
3729 pub fn serialized_size(&self) -> Option<usize> {
3731 match self {
3732 Schema::Struct(ref schema_struct) => schema_struct.serialized_size(),
3733 Schema::Enum(ref schema_enum) => schema_enum.serialized_size(),
3734 Schema::Primitive(ref schema_primitive) => schema_primitive.serialized_size(),
3735 Schema::Vector(ref _vector, _) => None,
3736 Schema::Array(ref array) => array.serialized_size(),
3737 Schema::SchemaOption(ref _content) => None,
3738 Schema::Undefined => None,
3739 Schema::ZeroSize => Some(0),
3740 Schema::Custom(_) => None,
3741 Schema::Boxed(inner) => inner.serialized_size(),
3742 Schema::FnClosure(_, _) => None,
3743 Schema::Slice(_) => None,
3744 Schema::Str => None,
3745 Schema::Reference(_) => None,
3746 Schema::Trait(_, _) => None,
3747 Schema::Recursion(_) => None,
3748 Schema::StdIoError => None,
3749 Schema::Future(_, _, _, _) => None,
3750 Schema::UninitSlice => None,
3751 }
3752 }
3753}
3754
3755fn diff_vector(a: &Schema, b: &Schema, path: String) -> Option<String> {
3756 diff_schema(a, b, path + "/*", false)
3757}
3758
3759fn diff_array(a: &SchemaArray, b: &SchemaArray, path: String) -> Option<String> {
3760 if a.count != b.count {
3761 return Some(format!(
3762 "At location [{}]: In memory array has length {}, but disk format length {}.",
3763 path, a.count, b.count
3764 ));
3765 }
3766
3767 diff_schema(&a.item_type, &b.item_type, format!("{}/[{}]", path, a.count), false)
3768}
3769
3770fn diff_option(a: &Schema, b: &Schema, path: String) -> Option<String> {
3771 diff_schema(a, b, path + "/?", false)
3772}
3773
3774fn diff_enum(a: &SchemaEnum, b: &SchemaEnum, path: String) -> Option<String> {
3775 let path = (path + &b.dbg_name).to_string();
3776 if a.variants.len() != b.variants.len() {
3777 return Some(format!(
3778 "At location [{}]: In memory enum has {} variants, but disk format has {} variants.",
3779 path,
3780 a.variants.len(),
3781 b.variants.len()
3782 ));
3783 }
3784 if a.discriminant_size != b.discriminant_size {
3785 return Some(format!(
3786 "At location [{}]: In memory enum has a representation with {} bytes for the discriminant, but disk format has {}.",
3787 path,
3788 a.discriminant_size,
3789 b.discriminant_size
3790 ));
3791 }
3792 for i in 0..a.variants.len() {
3793 if a.variants[i].name != b.variants[i].name {
3794 return Some(format!(
3795 "At location [{}]: Enum variant #{} in memory is called {}, but in disk format it is called {}",
3796 &path, i, a.variants[i].name, b.variants[i].name
3797 ));
3798 }
3799 if a.variants[i].discriminant != b.variants[i].discriminant {
3800 return Some(format!(
3801 "At location [{}]: Enum variant #{} in memory has discriminant {}, but in disk format it has {}",
3802 &path, i, a.variants[i].discriminant, b.variants[i].discriminant
3803 ));
3804 }
3805 let r = diff_fields(
3806 &a.variants[i].fields,
3807 &b.variants[i].fields,
3808 &(path.to_string() + "/" + &b.variants[i].name).to_string(),
3809 "enum",
3810 "",
3811 "",
3812 );
3813 if let Some(err) = r {
3814 return Some(err);
3815 }
3816 }
3817 None
3818}
3819fn diff_struct(a: &SchemaStruct, b: &SchemaStruct, path: String) -> Option<String> {
3820 diff_fields(
3821 &a.fields,
3822 &b.fields,
3823 &(path + "/" + &b.dbg_name).to_string(),
3824 "struct",
3825 &(" (struct ".to_string() + &a.dbg_name + ")"),
3826 &(" (struct ".to_string() + &b.dbg_name + ")"),
3827 )
3828}
3829fn diff_fields(
3830 a: &[Field],
3831 b: &[Field],
3832 path: &str,
3833 structuretype: &str,
3834 extra_a: &str,
3835 extra_b: &str,
3836) -> Option<String> {
3837 if a.len() != b.len() {
3838 return Some(format!(
3839 "At location [{}]: In memory {}{} has {} fields, disk format{} has {} fields.",
3840 path,
3841 structuretype,
3842 extra_a,
3843 a.len(),
3844 extra_b,
3845 b.len()
3846 ));
3847 }
3848 for i in 0..a.len() {
3849 let r = diff_schema(
3850 &a[i].value,
3851 &b[i].value,
3852 (path.to_string() + "/" + &b[i].name).to_string(),
3853 false,
3854 );
3855 if let Some(err) = r {
3856 return Some(err);
3857 }
3858 }
3859 None
3860}
3861pub fn diff_schema(a: &Schema, b: &Schema, path: String, is_return_pos: bool) -> Option<String> {
3876 let (atype, btype) = match (a, b) {
3877 (Schema::Struct(a), Schema::Struct(b)) => return diff_struct(a, b, path),
3878 (Schema::Enum(a), Schema::Enum(b)) => return diff_enum(a, b, path),
3879 (Schema::Primitive(a1), Schema::Primitive(b1)) => return diff_primitive(*a1, *b1, &path),
3880 (Schema::Vector(a1, _a2), Schema::Vector(b1, _b2)) => return diff_vector(a1, b1, path),
3881 (Schema::SchemaOption(a), Schema::SchemaOption(b)) => {
3882 return diff_option(a, b, path);
3883 }
3884 (Schema::Undefined, Schema::Undefined) => {
3885 return Some(format!("At location [{}]: Undefined schema encountered.", path))
3886 }
3887 (Schema::ZeroSize, Schema::ZeroSize) => {
3888 return None;
3889 }
3890 (Schema::Array(a), Schema::Array(b)) => return diff_array(a, b, path),
3891 (Schema::Custom(a), Schema::Custom(b)) => {
3892 if a != b {
3893 return Some(format!(
3894 "At location [{}]: Application protocol has datatype Custom({}), but foreign format has Custom({})",
3895 path, a, b
3896 ));
3897 }
3898 return None;
3899 }
3900 (Schema::Str, Schema::Str) => {
3901 return None;
3902 }
3903 (Schema::StdIoError, Schema::StdIoError) => {
3904 return None;
3905 }
3906 (Schema::Boxed(a), Schema::Boxed(b)) => {
3907 return diff_schema(a, b, path, is_return_pos);
3908 }
3909 (Schema::Reference(a), Schema::Reference(b)) => {
3910 return diff_schema(a, b, path, is_return_pos);
3911 }
3912 (Schema::Slice(a), Schema::Slice(b)) => {
3913 return diff_schema(a, b, path, is_return_pos);
3914 }
3915 (Schema::Trait(amut, a), Schema::Trait(bmut, b)) | (Schema::FnClosure(amut, a), Schema::FnClosure(bmut, b)) => {
3916 if amut != bmut {
3917 if *amut {
3918 return Some(format!(
3919 "At location [{}]: Application protocol uses FnMut, but foreign format has Fn.",
3920 path
3921 ));
3922 }
3923 if *bmut {
3924 return Some(format!(
3925 "At location [{}]: Application protocol uses Fn, but foreign format uses FnMut.",
3926 path
3927 ));
3928 }
3929 }
3930 return diff_abi_def(a, b, path, is_return_pos);
3931 }
3932 (Schema::Recursion(adepth), Schema::Recursion(bdepth)) => {
3933 if adepth == bdepth {
3934 return None; } else {
3936 return Some(format!(
3937 "At location [{}]: Application protocol uses recursion up {} levels, but foreign format uses {}.",
3938 path, adepth, bdepth
3939 ));
3940 }
3941 }
3942 (Schema::Future(a, a_send, a_sync, a_unpin), Schema::Future(b, b_send, b_sync, b_unpin)) => {
3943 if !is_return_pos {
3944 panic!("Futures are only supported in return position");
3945 }
3946 for (a, b, bound) in [
3947 (*a_send, *b_send, "Send"),
3948 (*a_sync, *b_sync, "Sync"),
3949 (*a_unpin, *b_unpin, "Unpin"),
3950 ] {
3951 if a && !b {
3952 return Some(format!(
3953 "At location [{}]: Caller expects a future with an {}-bound, but implementation provides one without. This is an incompatible difference.",
3954 path, bound
3955 ));
3956 }
3957 }
3958 return diff_abi_def(a, b, path, is_return_pos);
3959 }
3960 (Schema::UninitSlice, Schema::UninitSlice) => {
3961 return None; }
3963 (a, b) => (a.top_level_description(), b.top_level_description()),
3964 };
3965
3966 Some(format!(
3967 "At location [{}]: In memory schema: {}, file schema: {}",
3968 path, atype, btype
3969 ))
3970}
3971
3972fn diff_abi_def(a: &AbiTraitDefinition, b: &AbiTraitDefinition, path: String, is_return_pos: bool) -> Option<String> {
3973 for amet in a.methods.iter() {
3974 if let Some(bmet) = b.methods.iter().find(|x| x.name == amet.name) {
3975 if amet.info.arguments.len() != bmet.info.arguments.len() {
3976 return Some(format!(
3977 "At location [{}]: Application protocol method {} has {} args, but foreign version has {}.",
3978 path,
3979 amet.name,
3980 amet.info.arguments.len(),
3981 bmet.info.arguments.len()
3982 ));
3983 }
3984 for (arg_index, (a_arg, b_arg)) in amet.info.arguments.iter().zip(bmet.info.arguments.iter()).enumerate() {
3985 if let Some(diff) = diff_schema(
3986 &a_arg.schema,
3987 &b_arg.schema,
3988 format!("{}(arg #{})", amet.name, arg_index),
3989 is_return_pos,
3990 ) {
3991 return Some(diff);
3992 }
3993 }
3994 }
3995 }
3996 return None;
3997}
3998
3999impl WithSchema for Field {
4000 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4001 Schema::Undefined
4002 }
4003}
4004
4005impl Serialize for Field {
4006 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4007 serializer.write_string(&self.name)?;
4008 self.value.serialize(serializer)?;
4009 self.offset.serialize(serializer)?;
4010 Ok(())
4011 }
4012}
4013impl Packed for Field {}
4014impl Deserialize for Field {
4015 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
4016 Ok(Field {
4017 name: deserializer.read_string()?,
4018 value: Box::new(Schema::deserialize(deserializer)?),
4019 offset: if deserializer.file_version > 0 {
4020 Option::deserialize(deserializer)?
4021 } else {
4022 None
4023 },
4024 })
4025 }
4026}
4027impl WithSchema for Variant {
4028 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4029 Schema::Undefined
4030 }
4031}
4032impl Serialize for Variant {
4033 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4034 serializer.write_string(&self.name)?;
4035 serializer.write_u8(self.discriminant)?;
4036 serializer.write_usize(self.fields.len())?;
4037 for field in &self.fields {
4038 field.serialize(serializer)?;
4039 }
4040 Ok(())
4041 }
4042}
4043
4044impl Packed for Variant {}
4045impl Deserialize for Variant {
4046 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
4047 Ok(Variant {
4048 name: deserializer.read_string()?,
4049 discriminant: deserializer.read_u8()?,
4050 fields: {
4051 let l = deserializer.read_usize()?;
4052 let mut ret = Vec::new();
4053 for _ in 0..l {
4054 ret.push(Field {
4055 name: deserializer.read_string()?,
4056 value: Box::new(Schema::deserialize(deserializer)?),
4057 offset: if deserializer.file_version > 0 {
4058 Option::deserialize(deserializer)?
4059 } else {
4060 None
4061 },
4062 });
4063 }
4064 ret
4065 },
4066 })
4067 }
4068}
4069impl Serialize for SchemaArray {
4070 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4071 serializer.write_usize(self.count)?;
4072 self.item_type.serialize(serializer)?;
4073 Ok(())
4074 }
4075}
4076impl Packed for SchemaArray {}
4077impl Deserialize for SchemaArray {
4078 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
4079 let count = deserializer.read_usize()?;
4080 let item_type = Box::new(Schema::deserialize(deserializer)?);
4081 Ok(SchemaArray { count, item_type })
4082 }
4083}
4084impl WithSchema for SchemaArray {
4085 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4086 Schema::Undefined
4087 }
4088}
4089
4090impl WithSchema for SchemaStruct {
4091 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4092 Schema::Undefined
4093 }
4094}
4095impl Serialize for SchemaStruct {
4096 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4097 serializer.write_string(&self.dbg_name)?;
4098 serializer.write_usize(self.fields.len())?;
4099 self.size.serialize(serializer)?;
4100 self.alignment.serialize(serializer)?;
4101 for field in &self.fields {
4102 field.serialize(serializer)?;
4103 }
4104 Ok(())
4105 }
4106}
4107impl Packed for SchemaStruct {}
4108impl Deserialize for SchemaStruct {
4109 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
4110 let dbg_name = deserializer.read_string()?;
4111 let l = deserializer.read_usize()?;
4112 Ok(SchemaStruct {
4113 dbg_name,
4114 size: if deserializer.file_version > 0 {
4115 <_ as Deserialize>::deserialize(deserializer)?
4116 } else {
4117 None
4118 },
4119 alignment: if deserializer.file_version > 0 {
4120 <_ as Deserialize>::deserialize(deserializer)?
4121 } else {
4122 None
4123 },
4124 fields: {
4125 let mut ret = Vec::new();
4126 for _ in 0..l {
4127 ret.push(Field::deserialize(deserializer)?)
4128 }
4129 ret
4130 },
4131 })
4132 }
4133}
4134
4135impl WithSchema for SchemaPrimitive {
4136 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4137 Schema::Undefined
4138 }
4139}
4140impl Serialize for SchemaPrimitive {
4141 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4142 let discr = match *self {
4143 SchemaPrimitive::schema_i8 => 1,
4144 SchemaPrimitive::schema_u8 => 2,
4145 SchemaPrimitive::schema_i16 => 3,
4146 SchemaPrimitive::schema_u16 => 4,
4147 SchemaPrimitive::schema_i32 => 5,
4148 SchemaPrimitive::schema_u32 => 6,
4149 SchemaPrimitive::schema_i64 => 7,
4150 SchemaPrimitive::schema_u64 => 8,
4151 SchemaPrimitive::schema_f32 => 10,
4152 SchemaPrimitive::schema_f64 => 11,
4153 SchemaPrimitive::schema_bool => 12,
4154 SchemaPrimitive::schema_canary1 => 13,
4155 SchemaPrimitive::schema_i128 => 14,
4156 SchemaPrimitive::schema_u128 => 15,
4157 SchemaPrimitive::schema_char => 16,
4158 SchemaPrimitive::schema_string(layout) => {
4159 serializer.write_u8(9)?;
4160 if serializer.file_version > 0 {
4161 serializer.write_u8(layout as u8)?;
4162 }
4163 return Ok(());
4164 }
4165 };
4166 serializer.write_u8(discr)
4167 }
4168}
4169impl WithSchema for VecOrStringLayout {
4170 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4171 Schema::Undefined
4172 }
4173}
4174impl Deserialize for VecOrStringLayout {
4175 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
4176 Ok(match deserializer.read_u8()? {
4177 1 => VecOrStringLayout::DataCapacityLength,
4178 2 => VecOrStringLayout::DataLengthCapacity,
4179 3 => VecOrStringLayout::CapacityDataLength,
4180 4 => VecOrStringLayout::LengthDataCapacity,
4181 5 => VecOrStringLayout::CapacityLengthData,
4182 6 => VecOrStringLayout::LengthCapacityData,
4183 7 => VecOrStringLayout::LengthData,
4184 8 => VecOrStringLayout::DataLength,
4185 _ => VecOrStringLayout::Unknown,
4186 })
4187 }
4188}
4189impl Packed for SchemaPrimitive {}
4190impl Deserialize for SchemaPrimitive {
4191 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
4192 let var = match deserializer.read_u8()? {
4193 1 => SchemaPrimitive::schema_i8,
4194 2 => SchemaPrimitive::schema_u8,
4195 3 => SchemaPrimitive::schema_i16,
4196 4 => SchemaPrimitive::schema_u16,
4197 5 => SchemaPrimitive::schema_i32,
4198 6 => SchemaPrimitive::schema_u32,
4199 7 => SchemaPrimitive::schema_i64,
4200 8 => SchemaPrimitive::schema_u64,
4201 9 => SchemaPrimitive::schema_string({
4202 if deserializer.file_version > 0 {
4203 VecOrStringLayout::deserialize(deserializer)?
4204 } else {
4205 VecOrStringLayout::Unknown
4206 }
4207 }),
4208 10 => SchemaPrimitive::schema_f32,
4209 11 => SchemaPrimitive::schema_f64,
4210 12 => SchemaPrimitive::schema_bool,
4211 13 => SchemaPrimitive::schema_canary1,
4212 14 => SchemaPrimitive::schema_i128,
4213 15 => SchemaPrimitive::schema_u128,
4214 16 => SchemaPrimitive::schema_char,
4215 c => {
4216 return Err(SavefileError::GeneralError {
4217 msg: format!(
4218 "Corrupt schema, type {} encountered. Perhaps data is from future version?",
4219 c
4220 ),
4221 })
4222 }
4223 };
4224 Ok(var)
4225 }
4226}
4227
4228impl WithSchema for SchemaEnum {
4229 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4230 Schema::Undefined
4231 }
4232}
4233
4234impl Serialize for SchemaEnum {
4235 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4236 serializer.write_string(&self.dbg_name)?;
4237 serializer.write_usize(self.variants.len())?;
4238 for var in &self.variants {
4239 var.serialize(serializer)?;
4240 }
4241 self.discriminant_size.serialize(serializer)?;
4242 self.has_explicit_repr.serialize(serializer)?;
4243 self.size.serialize(serializer)?;
4244 self.alignment.serialize(serializer)?;
4245 Ok(())
4246 }
4247}
4248impl Packed for SchemaEnum {}
4249impl Deserialize for SchemaEnum {
4250 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
4251 let dbg_name = deserializer.read_string()?;
4252 let l = deserializer.read_usize()?;
4253 let mut ret = Vec::new();
4254 for _ in 0..l {
4255 ret.push(Variant::deserialize(deserializer)?);
4256 }
4257 let (discriminant_size, has_explicit_repr, size, alignment) = if deserializer.file_version > 0 {
4258 (
4259 u8::deserialize(deserializer)?,
4260 bool::deserialize(deserializer)?,
4261 Option::<usize>::deserialize(deserializer)?,
4262 Option::<usize>::deserialize(deserializer)?,
4263 )
4264 } else {
4265 (1, false, None, None)
4266 };
4267 Ok(SchemaEnum {
4268 dbg_name,
4269 variants: ret,
4270 discriminant_size,
4271 has_explicit_repr,
4272 size,
4273 alignment,
4274 })
4275 }
4276}
4277
4278#[cfg(feature = "quickcheck")]
4279impl Arbitrary for VecOrStringLayout {
4280 fn arbitrary(g: &mut Gen) -> Self {
4281 let x = u8::arbitrary(g);
4282 match x % 9 {
4283 0 => VecOrStringLayout::Unknown,
4284 1 => VecOrStringLayout::DataCapacityLength,
4285 2 => VecOrStringLayout::DataLengthCapacity,
4286 3 => VecOrStringLayout::CapacityDataLength,
4287 4 => VecOrStringLayout::LengthDataCapacity,
4288 5 => VecOrStringLayout::CapacityLengthData,
4289 6 => VecOrStringLayout::LengthCapacityData,
4290 7 => VecOrStringLayout::LengthData,
4291 8 => VecOrStringLayout::DataLength,
4292 _ => unreachable!(),
4293 }
4294 }
4295}
4296
4297#[cfg(feature = "quickcheck")]
4298impl Arbitrary for SchemaPrimitive {
4299 fn arbitrary(g: &mut Gen) -> Self {
4300 let x = u8::arbitrary(g);
4301 match x % 16 {
4302 0 => SchemaPrimitive::schema_i8,
4303 1 => SchemaPrimitive::schema_u8,
4304 2 => SchemaPrimitive::schema_i16,
4305 3 => SchemaPrimitive::schema_u16,
4306 4 => SchemaPrimitive::schema_i32,
4307 5 => SchemaPrimitive::schema_u32,
4308 6 => SchemaPrimitive::schema_i64,
4309 7 => SchemaPrimitive::schema_u64,
4310 8 => SchemaPrimitive::schema_string(VecOrStringLayout::arbitrary(g)),
4311 9 => SchemaPrimitive::schema_f32,
4312 10 => SchemaPrimitive::schema_f64,
4313 11 => SchemaPrimitive::schema_bool,
4314 12 => SchemaPrimitive::schema_canary1,
4315 13 => SchemaPrimitive::schema_u128,
4316 14 => SchemaPrimitive::schema_i128,
4317 15 => SchemaPrimitive::schema_char,
4318 _ => unreachable!(),
4319 }
4320 }
4321}
4322
4323#[cfg(feature = "quickcheck")]
4324impl Arbitrary for Field {
4325 fn arbitrary(g: &mut Gen) -> Self {
4326 Field {
4327 name: g.choose(&["", "test"]).unwrap().to_string(),
4328 value: <_ as Arbitrary>::arbitrary(g),
4329 offset: <_ as Arbitrary>::arbitrary(g),
4330 }
4331 }
4332}
4333
4334#[cfg(feature = "quickcheck")]
4335impl Arbitrary for Variant {
4336 fn arbitrary(g: &mut Gen) -> Self {
4337 Variant {
4338 name: g.choose(&["", "test"]).unwrap().to_string(),
4339 discriminant: <_ as Arbitrary>::arbitrary(g),
4340 fields: <_ as Arbitrary>::arbitrary(g),
4341 }
4342 }
4343}
4344
4345#[cfg(feature = "quickcheck")]
4346impl Arbitrary for SchemaEnum {
4347 fn arbitrary(g: &mut Gen) -> Self {
4348 SchemaEnum {
4349 dbg_name: g.choose(&["", "test"]).unwrap().to_string(),
4350 variants: (0..*g.choose(&[0usize, 1, 2, 3]).unwrap())
4351 .map(|_| <_ as Arbitrary>::arbitrary(g))
4352 .collect(),
4353 discriminant_size: *g.choose(&[1, 2, 4]).unwrap(),
4354 has_explicit_repr: *g.choose(&[false, true]).unwrap(),
4355 size: <_ as Arbitrary>::arbitrary(g),
4356 alignment: <_ as Arbitrary>::arbitrary(g),
4357 }
4358 }
4359}
4360
4361#[cfg(feature = "quickcheck")]
4362impl Arbitrary for SchemaStruct {
4363 fn arbitrary(g: &mut Gen) -> Self {
4364 SchemaStruct {
4365 fields: (0..*g.choose(&[0usize, 1, 2, 3]).unwrap())
4366 .map(|_| <_ as Arbitrary>::arbitrary(g))
4367 .collect(),
4368 dbg_name: <_ as Arbitrary>::arbitrary(g),
4369 size: <_ as Arbitrary>::arbitrary(g),
4370 alignment: <_ as Arbitrary>::arbitrary(g),
4371 }
4372 }
4373}
4374#[cfg(feature = "quickcheck")]
4375impl Arbitrary for SchemaArray {
4376 fn arbitrary(g: &mut Gen) -> Self {
4377 SchemaArray {
4378 item_type: <_ as Arbitrary>::arbitrary(g),
4379 count: <_ as Arbitrary>::arbitrary(g),
4380 }
4381 }
4382}
4383#[cfg(feature = "quickcheck")]
4384static QUICKCHECKBOUND: AtomicU8 = AtomicU8::new(0);
4385#[cfg(feature = "quickcheck")]
4386impl Arbitrary for Schema {
4387 fn arbitrary(g: &mut Gen) -> Self {
4388 let val = QUICKCHECKBOUND.fetch_add(1, Ordering::Relaxed);
4389 if val > 1 {
4390 QUICKCHECKBOUND.fetch_sub(1, Ordering::Relaxed);
4391 return Schema::ZeroSize;
4392 }
4393 let arg = g.choose(&[0, 1, 2, 3, 4, 5, 6, 7]).unwrap_or(&8);
4394 let temp = match arg {
4395 0 => Schema::Struct(<_ as Arbitrary>::arbitrary(g)),
4396 1 => Schema::Enum(<_ as Arbitrary>::arbitrary(g)),
4397 2 => Schema::Primitive(<_ as Arbitrary>::arbitrary(g)),
4398 3 => Schema::Vector(<_ as Arbitrary>::arbitrary(g), VecOrStringLayout::arbitrary(g)),
4399 4 => Schema::Array(SchemaArray::arbitrary(g)),
4400 5 => Schema::SchemaOption(<_ as Arbitrary>::arbitrary(g)),
4401 6 => Schema::ZeroSize,
4403 7 => Schema::Custom(g.choose(&["", "test"]).unwrap().to_string()),
4404 _ => Schema::ZeroSize,
4405 };
4406 _ = QUICKCHECKBOUND.fetch_sub(1, Ordering::Relaxed);
4407 temp
4408 }
4409}
4410
4411impl WithSchema for Schema {
4412 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4413 Schema::Undefined
4414 }
4415}
4416impl Serialize for Schema {
4417 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4418 match self {
4419 Schema::Struct(schema_struct) => {
4420 serializer.write_u8(1)?;
4421 schema_struct.serialize(serializer)
4422 }
4423 Schema::Enum(schema_enum) => {
4424 serializer.write_u8(2)?;
4425 schema_enum.serialize(serializer)
4426 }
4427 Schema::Primitive(schema_prim) => {
4428 serializer.write_u8(3)?;
4429 schema_prim.serialize(serializer)?;
4430 Ok(())
4431 }
4432 Schema::Vector(schema_vector, is_standard_layout) => {
4433 serializer.write_u8(4)?;
4434 schema_vector.serialize(serializer)?;
4435 if serializer.file_version > 0 {
4436 serializer.write_u8(*is_standard_layout as u8)?;
4437 }
4438 Ok(())
4439 }
4440 Schema::Undefined => serializer.write_u8(5),
4441 Schema::ZeroSize => serializer.write_u8(6),
4442 Schema::SchemaOption(content) => {
4443 serializer.write_u8(7)?;
4444 content.serialize(serializer)
4445 }
4446 Schema::Array(array) => {
4447 serializer.write_u8(8)?;
4448 array.serialize(serializer)
4449 }
4450 Schema::Custom(custom) => {
4451 serializer.write_u8(9)?;
4452 custom.serialize(serializer)
4453 }
4454 Schema::Boxed(name) => {
4455 serializer.write_u8(10)?;
4456 name.serialize(serializer)
4457 }
4458 Schema::FnClosure(a, b) => {
4459 serializer.write_u8(11)?;
4460 a.serialize(serializer)?;
4461 b.serialize(serializer)?;
4462 Ok(())
4463 }
4464 Schema::Slice(inner) => {
4465 serializer.write_u8(12)?;
4466 inner.serialize(serializer)?;
4467 Ok(())
4468 }
4469 Schema::Str => {
4470 serializer.write_u8(13)?;
4471 Ok(())
4472 }
4473 Schema::Reference(inner) => {
4474 serializer.write_u8(14)?;
4475 inner.serialize(serializer)?;
4476 Ok(())
4477 }
4478 Schema::Trait(a, b) => {
4479 serializer.write_u8(15)?;
4480 serializer.write_bool(*a)?;
4481 b.serialize(serializer)?;
4482 Ok(())
4483 }
4484 Schema::Recursion(depth) => {
4485 serializer.write_u8(16)?;
4486 serializer.write_usize(*depth)?;
4487 Ok(())
4488 }
4489 Schema::StdIoError => {
4490 serializer.write_u8(17)?;
4491 Ok(())
4492 }
4493 Schema::Future(o, send, sync, unpin) => {
4494 serializer.write_u8(18)?;
4495 serializer
4496 .write_u8(if *send { 1 } else { 0 } | if *sync { 2 } else { 0 } | if *unpin { 4 } else { 0 })?;
4497 o.serialize(serializer)?;
4498 Ok(())
4499 }
4500 Schema::UninitSlice => {
4501 serializer.write_u8(19)?;
4502 Ok(())
4503 }
4504 }
4505 }
4506}
4507
4508impl Packed for Schema {}
4509impl Deserialize for Schema {
4510 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
4511 let x = deserializer.read_u8()?;
4512 let schema = match x {
4513 1 => Schema::Struct(SchemaStruct::deserialize(deserializer)?),
4514 2 => Schema::Enum(SchemaEnum::deserialize(deserializer)?),
4515 3 => Schema::Primitive(SchemaPrimitive::deserialize(deserializer)?),
4516 4 => Schema::Vector(
4517 Box::new(Schema::deserialize(deserializer)?),
4518 if deserializer.file_version > 0 {
4519 VecOrStringLayout::deserialize(deserializer)?
4520 } else {
4521 VecOrStringLayout::Unknown
4522 },
4523 ),
4524 5 => Schema::Undefined,
4525 6 => Schema::ZeroSize,
4526 7 => Schema::SchemaOption(Box::new(Schema::deserialize(deserializer)?)),
4527 8 => Schema::Array(SchemaArray::deserialize(deserializer)?),
4528 9 => Schema::Custom(String::deserialize(deserializer)?),
4529 10 => Schema::Boxed(<_ as Deserialize>::deserialize(deserializer)?),
4530 11 => Schema::FnClosure(
4531 <_ as Deserialize>::deserialize(deserializer)?,
4532 <_ as Deserialize>::deserialize(deserializer)?,
4533 ),
4534 12 => Schema::Slice(Box::new(<_ as Deserialize>::deserialize(deserializer)?)),
4535 13 => Schema::Str,
4536 14 => Schema::Reference(Box::new(<_ as Deserialize>::deserialize(deserializer)?)),
4537 15 => Schema::Trait(
4538 <_ as Deserialize>::deserialize(deserializer)?,
4539 <_ as Deserialize>::deserialize(deserializer)?,
4540 ),
4541 16 => Schema::Recursion(<_ as Deserialize>::deserialize(deserializer)?),
4542 17 => Schema::StdIoError,
4543 18 => {
4544 let mask = deserializer.read_u8()?;
4545 let send = (mask & 1) != 0;
4546 let sync = (mask & 2) != 0;
4547 let unpin = (mask & 4) != 0;
4548 Schema::Future(<_ as Deserialize>::deserialize(deserializer)?, send, sync, unpin)
4549 }
4550 19 => {
4551 Schema::UninitSlice
4552 }
4553 c => {
4554 return Err(SavefileError::GeneralError {
4555 msg: format!("Corrupt, or future schema, schema variant {} encountered", c),
4556 })
4557 }
4558 };
4559
4560 Ok(schema)
4561 }
4562}
4563impl WithSchema for str {
4564 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4565 Schema::Primitive(SchemaPrimitive::schema_string(VecOrStringLayout::Unknown))
4566 }
4567}
4568
4569impl WithSchema for String {
4570 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
4571 Schema::Primitive(SchemaPrimitive::schema_string(calculate_string_memory_layout()))
4572 }
4573}
4574impl Introspect for str {
4575 fn introspect_value(&self) -> String {
4576 self.to_string()
4577 }
4578
4579 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem>> {
4580 None
4581 }
4582}
4583impl Introspect for String {
4584 fn introspect_value(&self) -> String {
4585 self.to_string()
4586 }
4587
4588 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem>> {
4589 None
4590 }
4591}
4592impl Serialize for String {
4593 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4594 serializer.write_string(self)
4595 }
4596}
4597impl Serialize for str {
4598 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4599 serializer.write_string(self)
4600 }
4601}
4602
4603impl Packed for String {}
4604
4605impl Packed for str {}
4606
4607impl Deserialize for String {
4608 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<String, SavefileError> {
4609 deserializer.read_string()
4610 }
4611}
4612
4613#[cfg(feature = "parking_lot")]
4615pub struct IntrospectItemMutex<'a, T> {
4616 g: MutexGuard<'a, T>,
4617}
4618
4619#[cfg(feature = "parking_lot")]
4620impl<'a, T: Introspect> IntrospectItem<'a> for IntrospectItemMutex<'a, T> {
4621 fn key(&self) -> &str {
4622 "0"
4623 }
4624
4625 fn val(&self) -> &dyn Introspect {
4626 self.g.deref()
4627 }
4628}
4629
4630#[cfg(feature = "parking_lot")]
4631impl<T: Introspect> Introspect for Mutex<T> {
4632 fn introspect_value(&self) -> String {
4633 format!("Mutex<{}>", std::any::type_name::<T>())
4634 }
4635
4636 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4637 if index == 0 {
4638 Some(Box::new(IntrospectItemMutex { g: self.lock() }))
4639 } else {
4640 None
4641 }
4642 }
4643}
4644
4645pub struct IntrospectItemStdMutex<'a, T> {
4647 g: std::sync::MutexGuard<'a, T>,
4648}
4649
4650impl<'a, T: Introspect> IntrospectItem<'a> for IntrospectItemStdMutex<'a, T> {
4651 fn key(&self) -> &str {
4652 "0"
4653 }
4654
4655 fn val(&self) -> &dyn Introspect {
4656 self.g.deref()
4657 }
4658}
4659
4660impl<T: Introspect> Introspect for std::sync::Mutex<T> {
4661 fn introspect_value(&self) -> String {
4662 format!("Mutex<{}>", std::any::type_name::<T>())
4663 }
4664
4665 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4666 match self.lock() {
4667 Ok(item) => {
4668 if index == 0 {
4669 Some(Box::new(IntrospectItemStdMutex { g: item }))
4670 } else {
4671 None
4672 }
4673 }
4674 Err(_) => None,
4675 }
4676 }
4677}
4678
4679impl<T: WithSchema> WithSchema for std::sync::Mutex<T> {
4680 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
4681 T::schema(version, context)
4682 }
4683}
4684impl<T> Packed for std::sync::Mutex<T> {}
4685impl<T: Serialize> Serialize for std::sync::Mutex<T> {
4686 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4687 let data = self.lock()?;
4688 data.serialize(serializer)
4689 }
4690}
4691
4692impl<T: Deserialize> Deserialize for std::sync::Mutex<T> {
4693 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<std::sync::Mutex<T>, SavefileError> {
4694 Ok(std::sync::Mutex::new(T::deserialize(deserializer)?))
4695 }
4696}
4697
4698#[cfg(feature = "parking_lot")]
4699impl<T: WithSchema> WithSchema for Mutex<T> {
4700 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
4701 T::schema(version, context)
4702 }
4703}
4704
4705#[cfg(feature = "parking_lot")]
4706impl<T> Packed for Mutex<T> {}
4707
4708#[cfg(feature = "parking_lot")]
4709impl<T: Serialize> Serialize for Mutex<T> {
4710 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4711 let data = self.lock();
4712 data.serialize(serializer)
4713 }
4714}
4715
4716#[cfg(feature = "parking_lot")]
4717impl<T: Deserialize> Deserialize for Mutex<T> {
4718 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Mutex<T>, SavefileError> {
4719 Ok(Mutex::new(T::deserialize(deserializer)?))
4720 }
4721}
4722
4723#[cfg(feature = "parking_lot")]
4725pub struct IntrospectItemRwLock<'a, T> {
4726 g: RwLockReadGuard<'a, T>,
4727}
4728
4729#[cfg(feature = "parking_lot")]
4730impl<'a, T: Introspect> IntrospectItem<'a> for IntrospectItemRwLock<'a, T> {
4731 fn key(&self) -> &str {
4732 "0"
4733 }
4734
4735 fn val(&self) -> &dyn Introspect {
4736 self.g.deref()
4737 }
4738}
4739
4740impl<T: Introspect> Introspect for std::cell::Ref<'_, T> {
4741 fn introspect_value(&self) -> String {
4742 let sub_value = (**self).introspect_value();
4743 format!("Ref({})", sub_value)
4744 }
4745 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4746 (**self).introspect_child(index)
4747 }
4748 fn introspect_len(&self) -> usize {
4749 (**self).introspect_len()
4750 }
4751}
4752
4753impl<'a, T: Introspect> IntrospectItem<'a> for std::cell::Ref<'a, T> {
4754 fn key(&self) -> &str {
4755 "ref"
4756 }
4757 fn val(&self) -> &dyn Introspect {
4759 self
4760 }
4761}
4762
4763impl<T: Introspect> Introspect for RefCell<T> {
4764 fn introspect_value(&self) -> String {
4765 let sub_value = self.borrow().introspect_value();
4766 format!("RefCell({})", sub_value)
4767 }
4768
4769 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4770 if index != 0 {
4772 return None;
4773 }
4774 let rf = self.borrow();
4775 Some(Box::new(rf))
4776 }
4777
4778 fn introspect_len(&self) -> usize {
4779 1
4781 }
4782}
4783
4784impl<T: Introspect> Introspect for Rc<T> {
4785 fn introspect_value(&self) -> String {
4786 format!("Rc({})", self.deref().introspect_value())
4787 }
4788
4789 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4790 self.deref().introspect_child(index)
4791 }
4792
4793 fn introspect_len(&self) -> usize {
4794 self.deref().introspect_len()
4795 }
4796}
4797
4798impl<T: Introspect> Introspect for Arc<T> {
4799 fn introspect_value(&self) -> String {
4800 format!("Arc({})", self.deref().introspect_value())
4801 }
4802
4803 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4804 self.deref().introspect_child(index)
4805 }
4806
4807 fn introspect_len(&self) -> usize {
4808 self.deref().introspect_len()
4809 }
4810}
4811#[cfg(feature = "parking_lot")]
4812impl<T: Introspect> Introspect for RwLock<T> {
4813 fn introspect_value(&self) -> String {
4814 format!("RwLock<{}>", std::any::type_name::<T>())
4815 }
4816 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4817 if index == 0 {
4818 Some(Box::new(IntrospectItemRwLock { g: self.read() }))
4819 } else {
4820 None
4821 }
4822 }
4823
4824 fn introspect_len(&self) -> usize {
4825 1
4826 }
4827}
4828
4829#[cfg(feature = "parking_lot")]
4830impl<T: WithSchema> WithSchema for RwLock<T> {
4831 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
4832 T::schema(version, context)
4833 }
4834}
4835
4836#[cfg(feature = "parking_lot")]
4837impl<T> Packed for RwLock<T> {}
4838
4839#[cfg(feature = "parking_lot")]
4840impl<T: Serialize> Serialize for RwLock<T> {
4841 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
4842 let data = self.read();
4843 data.serialize(serializer)
4844 }
4845}
4846
4847#[cfg(feature = "parking_lot")]
4848impl<T: Deserialize> Deserialize for RwLock<T> {
4849 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<RwLock<T>, SavefileError> {
4850 Ok(RwLock::new(T::deserialize(deserializer)?))
4851 }
4852}
4853
4854pub struct IntrospectItemSimple<'a> {
4856 key: String,
4857 val: &'a dyn Introspect,
4858}
4859
4860impl<'a> IntrospectItem<'a> for IntrospectItemSimple<'a> {
4861 fn key(&self) -> &str {
4862 &self.key
4863 }
4864
4865 fn val(&self) -> &dyn Introspect {
4866 self.val
4867 }
4868}
4869
4870pub fn introspect_item<'a>(key: String, val: &'a dyn Introspect) -> Box<dyn IntrospectItem<'a> + 'a> {
4872 Box::new(IntrospectItemSimple { key, val })
4873}
4874
4875#[cfg(not(feature = "nightly"))]
4876impl<K: Introspect + Eq + Hash, V: Introspect, S: ::std::hash::BuildHasher> Introspect for HashMap<K, V, S> {
4877 fn introspect_value(&self) -> String {
4878 format!("HashMap<{},{}>", std::any::type_name::<K>(), std::any::type_name::<V>())
4879 }
4880
4881 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4882 let bucket = index / 2;
4883 let off = index % 2;
4884 if let Some((key, val)) = self.iter().nth(bucket) {
4885 if off == 0 {
4886 Some(introspect_item(format!("Key #{}", index), key))
4887 } else {
4888 Some(introspect_item(format!("Value #{}", index), val))
4889 }
4890 } else {
4891 None
4892 }
4893 }
4894 fn introspect_len(&self) -> usize {
4895 self.len()
4896 }
4897}
4898
4899#[cfg(feature = "nightly")]
4900impl<K: Introspect + Eq + Hash, V: Introspect, S: ::std::hash::BuildHasher> Introspect for HashMap<K, V, S> {
4901 default fn introspect_value(&self) -> String {
4902 format!("HashMap<{},{}>", std::any::type_name::<K>(), std::any::type_name::<V>())
4903 }
4904
4905 default fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4906 let bucket = index / 2;
4907 let off = index % 2;
4908 if let Some((key, val)) = self.iter().nth(bucket) {
4909 if off == 0 {
4910 Some(introspect_item(format!("Key #{}", index), key))
4911 } else {
4912 Some(introspect_item(format!("Value #{}", index), val))
4913 }
4914 } else {
4915 None
4916 }
4917 }
4918 default fn introspect_len(&self) -> usize {
4919 self.len()
4920 }
4921}
4922
4923#[cfg(feature = "nightly")]
4924impl<K: Introspect + Eq + Hash, V: Introspect, S: ::std::hash::BuildHasher> Introspect for HashMap<K, V, S>
4925where
4926 K: ToString,
4927{
4928 fn introspect_value(&self) -> String {
4929 format!("HashMap<{},{}>", std::any::type_name::<K>(), std::any::type_name::<V>())
4930 }
4931
4932 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4933 if let Some((key, val)) = self.iter().nth(index) {
4934 Some(introspect_item(key.to_string(), val))
4935 } else {
4936 None
4937 }
4938 }
4939 fn introspect_len(&self) -> usize {
4940 self.len()
4941 }
4942}
4943
4944impl<K: Introspect + Eq + Hash, S: ::std::hash::BuildHasher> Introspect for HashSet<K, S> {
4945 fn introspect_value(&self) -> String {
4946 format!("HashSet<{}>", std::any::type_name::<K>())
4947 }
4948
4949 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4950 if let Some(key) = self.iter().nth(index) {
4951 Some(introspect_item(format!("#{}", index), key))
4952 } else {
4953 None
4954 }
4955 }
4956 fn introspect_len(&self) -> usize {
4957 self.len()
4958 }
4959}
4960
4961impl<K: Introspect> Introspect for BTreeSet<K> {
4962 fn introspect_value(&self) -> String {
4963 format!("BTreeSet<{}>", std::any::type_name::<K>())
4964 }
4965
4966 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4967 if let Some(key) = self.iter().nth(index) {
4968 Some(introspect_item(format!("#{}", index), key))
4969 } else {
4970 None
4971 }
4972 }
4973 fn introspect_len(&self) -> usize {
4974 self.len()
4975 }
4976}
4977
4978impl<K: Introspect, V: Introspect> Introspect for BTreeMap<K, V> {
4979 fn introspect_value(&self) -> String {
4980 format!(
4981 "BTreeMap<{},{}>",
4982 std::any::type_name::<K>(),
4983 std::any::type_name::<V>()
4984 )
4985 }
4986
4987 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
4990 let bucket = index / 2;
4991 let off = index % 2;
4992 if let Some((key, val)) = self.iter().nth(bucket) {
4993 if off == 0 {
4994 Some(introspect_item(format!("Key #{}", index), key))
4995 } else {
4996 Some(introspect_item(format!("Value #{}", index), val))
4997 }
4998 } else {
4999 None
5000 }
5001 }
5002 fn introspect_len(&self) -> usize {
5003 self.len()
5004 }
5005}
5006impl<K: WithSchema + 'static, V: WithSchema + 'static> WithSchema for BTreeMap<K, V> {
5007 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5008 Schema::Vector(
5009 Box::new(Schema::Struct(SchemaStruct {
5010 dbg_name: "KeyValuePair".to_string(),
5011 size: None,
5012 alignment: None,
5013 fields: vec![
5014 Field {
5015 name: "key".to_string(),
5016 value: Box::new(context.possible_recursion::<K>(|context| K::schema(version, context))),
5017 offset: None,
5018 },
5019 Field {
5020 name: "value".to_string(),
5021 value: Box::new(context.possible_recursion::<V>(|context| V::schema(version, context))),
5022 offset: None,
5023 },
5024 ],
5025 })),
5026 VecOrStringLayout::Unknown,
5027 )
5028 }
5029}
5030impl<K, V> Packed for BTreeMap<K, V> {}
5031impl<K: Serialize + 'static, V: Serialize + 'static> Serialize for BTreeMap<K, V> {
5032 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5033 self.len().serialize(serializer)?;
5034 for (k, v) in self {
5035 k.serialize(serializer)?;
5036 v.serialize(serializer)?;
5037 }
5038 Ok(())
5039 }
5040}
5041impl<K: Deserialize + Ord + 'static, V: Deserialize + 'static> Deserialize for BTreeMap<K, V> {
5042 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5043 let mut ret = BTreeMap::new();
5044 let count = <usize as Deserialize>::deserialize(deserializer)?;
5045 for _ in 0..count {
5046 ret.insert(
5047 <_ as Deserialize>::deserialize(deserializer)?,
5048 <_ as Deserialize>::deserialize(deserializer)?,
5049 );
5050 }
5051 Ok(ret)
5052 }
5053}
5054
5055impl<K> Packed for BTreeSet<K> {}
5056impl<K: WithSchema + 'static> WithSchema for BTreeSet<K> {
5057 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5058 Schema::Vector(
5059 Box::new(context.possible_recursion::<K>(|context| K::schema(version, context))),
5060 VecOrStringLayout::Unknown,
5061 )
5062 }
5063}
5064impl<K: Serialize + 'static> Serialize for BTreeSet<K> {
5065 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5066 serializer.write_usize(self.len())?;
5067 for item in self {
5068 item.serialize(serializer)?;
5069 }
5070 Ok(())
5071 }
5072}
5073impl<K: Deserialize + 'static + Ord> Deserialize for BTreeSet<K> {
5074 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5075 let cnt = deserializer.read_usize()?;
5076 let mut ret = BTreeSet::new();
5077 for _ in 0..cnt {
5078 ret.insert(<_ as Deserialize>::deserialize(deserializer)?);
5079 }
5080 Ok(ret)
5081 }
5082}
5083
5084impl<K, S: ::std::hash::BuildHasher> Packed for HashSet<K, S> {}
5085impl<K: WithSchema + 'static, S: ::std::hash::BuildHasher> WithSchema for HashSet<K, S> {
5086 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5087 Schema::Vector(
5088 Box::new(context.possible_recursion::<K>(|context| K::schema(version, context))),
5089 VecOrStringLayout::Unknown,
5090 )
5091 }
5092}
5093impl<K: Serialize + 'static, S: ::std::hash::BuildHasher> Serialize for HashSet<K, S> {
5094 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5095 serializer.write_usize(self.len())?;
5096 for item in self {
5097 item.serialize(serializer)?;
5098 }
5099 Ok(())
5100 }
5101}
5102impl<K: Deserialize + Eq + Hash + 'static, S: ::std::hash::BuildHasher + Default> Deserialize for HashSet<K, S> {
5103 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5104 let cnt = deserializer.read_usize()?;
5105 let mut ret = HashSet::with_capacity_and_hasher(cnt, S::default());
5106 for _ in 0..cnt {
5107 ret.insert(<_ as Deserialize>::deserialize(deserializer)?);
5108 }
5109 Ok(ret)
5110 }
5111}
5112
5113impl<K: WithSchema + Eq + Hash + 'static, V: WithSchema + 'static, S: ::std::hash::BuildHasher> WithSchema
5114 for HashMap<K, V, S>
5115{
5116 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5117 Schema::Vector(
5118 Box::new(Schema::Struct(SchemaStruct {
5119 dbg_name: "KeyValuePair".to_string(),
5120 size: None,
5121 alignment: None,
5122 fields: vec![
5123 Field {
5124 name: "key".to_string(),
5125 value: Box::new(context.possible_recursion::<K>(|context| K::schema(version, context))),
5126 offset: None,
5127 },
5128 Field {
5129 name: "value".to_string(),
5130 value: Box::new(context.possible_recursion::<K>(|context| V::schema(version, context))),
5131 offset: None,
5132 },
5133 ],
5134 })),
5135 VecOrStringLayout::Unknown,
5136 )
5137 }
5138}
5139impl<K: Eq + Hash, V, S: ::std::hash::BuildHasher> Packed for HashMap<K, V, S> {}
5140impl<K: Serialize + Eq + Hash + 'static, V: Serialize + 'static, S: ::std::hash::BuildHasher> Serialize
5141 for HashMap<K, V, S>
5142{
5143 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5144 serializer.write_usize(self.len())?;
5145 for (k, v) in self.iter() {
5146 k.serialize(serializer)?;
5147 v.serialize(serializer)?;
5148 }
5149 Ok(())
5150 }
5151}
5152
5153impl<K: Deserialize + Eq + Hash + 'static, V: Deserialize + 'static, S: ::std::hash::BuildHasher + Default> Deserialize
5154 for HashMap<K, V, S>
5155{
5156 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5157 let l = deserializer.read_usize()?;
5158 let mut ret: Self = HashMap::with_capacity_and_hasher(l, Default::default());
5159 for _ in 0..l {
5160 ret.insert(K::deserialize(deserializer)?, V::deserialize(deserializer)?);
5161 }
5162 Ok(ret)
5163 }
5164}
5165
5166#[cfg(feature = "indexmap")]
5167impl<K: WithSchema + Eq + Hash + 'static, V: WithSchema + 'static, S: ::std::hash::BuildHasher> WithSchema
5168 for IndexMap<K, V, S>
5169{
5170 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5171 Schema::Vector(
5172 Box::new(Schema::Struct(SchemaStruct {
5173 dbg_name: "KeyValuePair".to_string(),
5174 size: None,
5175 alignment: None,
5176 fields: vec![
5177 Field {
5178 name: "key".to_string(),
5179 value: Box::new(context.possible_recursion::<K>(|context| K::schema(version, context))),
5180 offset: None,
5181 },
5182 Field {
5183 name: "value".to_string(),
5184 value: Box::new(context.possible_recursion::<K>(|context| V::schema(version, context))),
5185 offset: None,
5186 },
5187 ],
5188 })),
5189 VecOrStringLayout::Unknown,
5190 )
5191 }
5192}
5193
5194#[cfg(all(not(feature = "nightly"), feature = "indexmap"))]
5195impl<K: Introspect + Eq + Hash, V: Introspect, S: ::std::hash::BuildHasher> Introspect for IndexMap<K, V, S> {
5196 fn introspect_value(&self) -> String {
5197 format!(
5198 "IndexMap<{},{}>",
5199 std::any::type_name::<K>(),
5200 std::any::type_name::<V>()
5201 )
5202 }
5203
5204 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5205 let bucket = index / 2;
5206 let off = index % 2;
5207 if let Some((k, v)) = self.get_index(bucket) {
5208 if off == 0 {
5209 Some(introspect_item(format!("Key #{}", bucket), k))
5210 } else {
5211 Some(introspect_item(format!("Value #{}", bucket), v))
5212 }
5213 } else {
5214 None
5215 }
5216 }
5217
5218 fn introspect_len(&self) -> usize {
5219 self.len()
5220 }
5221}
5222
5223#[cfg(all(feature = "nightly", feature = "indexmap"))]
5224impl<K: Introspect + Eq + Hash, V: Introspect, S: ::std::hash::BuildHasher> Introspect for IndexMap<K, V, S> {
5225 default fn introspect_value(&self) -> String {
5226 format!(
5227 "IndexMap<{},{}>",
5228 std::any::type_name::<K>(),
5229 std::any::type_name::<V>()
5230 )
5231 }
5232
5233 default fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5234 let bucket = index / 2;
5235 let off = index % 2;
5236 if let Some((k, v)) = self.get_index(bucket) {
5237 if off == 0 {
5238 Some(introspect_item(format!("Key #{}", bucket), k))
5239 } else {
5240 Some(introspect_item(format!("Value #{}", bucket), v))
5241 }
5242 } else {
5243 None
5244 }
5245 }
5246
5247 default fn introspect_len(&self) -> usize {
5248 self.len()
5249 }
5250}
5251
5252#[cfg(all(feature = "nightly", feature = "indexmap"))]
5253impl<K: Introspect + Eq + Hash, V: Introspect, S: ::std::hash::BuildHasher> Introspect for IndexMap<K, V, S>
5254where
5255 K: ToString,
5256{
5257 fn introspect_value(&self) -> String {
5258 format!(
5259 "IndexMap<{},{}>",
5260 std::any::type_name::<K>(),
5261 std::any::type_name::<V>()
5262 )
5263 }
5264
5265 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5266 if let Some((k, v)) = self.get_index(index) {
5267 Some(introspect_item(k.to_string(), v))
5268 } else {
5269 None
5270 }
5271 }
5272
5273 fn introspect_len(&self) -> usize {
5274 self.len()
5275 }
5276}
5277#[cfg(feature = "indexmap")]
5278impl<K: Eq + Hash, V, S: ::std::hash::BuildHasher> Packed for IndexMap<K, V, S> {}
5279
5280#[cfg(feature = "indexmap")]
5281impl<K: Serialize + Eq + Hash + 'static, V: Serialize + 'static, S: ::std::hash::BuildHasher> Serialize
5282 for IndexMap<K, V, S>
5283{
5284 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5285 serializer.write_usize(self.len())?;
5286 for (k, v) in self.iter() {
5287 k.serialize(serializer)?;
5288 v.serialize(serializer)?;
5289 }
5290 Ok(())
5291 }
5292}
5293
5294#[cfg(feature = "indexmap")]
5295impl<K: Deserialize + Eq + Hash + 'static, V: Deserialize + 'static> Deserialize for IndexMap<K, V> {
5296 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5297 let l = deserializer.read_usize()?;
5298 let mut ret = IndexMap::with_capacity(l);
5299 for _ in 0..l {
5300 ret.insert(K::deserialize(deserializer)?, V::deserialize(deserializer)?);
5301 }
5302 Ok(ret)
5303 }
5304}
5305
5306#[cfg(feature = "indexmap")]
5307impl<K: Introspect + Eq + Hash, S: ::std::hash::BuildHasher> Introspect for IndexSet<K, S> {
5308 fn introspect_value(&self) -> String {
5309 format!("IndexSet<{}>", std::any::type_name::<K>())
5310 }
5311
5312 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5313 if let Some(val) = self.get_index(index) {
5314 Some(introspect_item(format!("#{}", index), val))
5315 } else {
5316 None
5317 }
5318 }
5319
5320 fn introspect_len(&self) -> usize {
5321 self.len()
5322 }
5323}
5324
5325#[cfg(feature = "indexmap")]
5326impl<K: Eq + Hash, S: ::std::hash::BuildHasher> Packed for IndexSet<K, S> {}
5327
5328#[cfg(feature = "indexmap")]
5329impl<K: WithSchema + Eq + Hash + 'static, S: ::std::hash::BuildHasher> WithSchema for IndexSet<K, S> {
5330 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5331 Schema::Vector(
5332 Box::new(Schema::Struct(SchemaStruct {
5333 dbg_name: "Key".to_string(),
5334 size: None,
5335 alignment: None,
5336 fields: vec![Field {
5337 name: "key".to_string(),
5338 value: Box::new(context.possible_recursion::<K>(|context| K::schema(version, context))),
5339 offset: None,
5340 }],
5341 })),
5342 VecOrStringLayout::Unknown,
5343 )
5344 }
5345}
5346
5347#[cfg(feature = "indexmap")]
5348impl<K: Serialize + Eq + Hash + 'static, S: ::std::hash::BuildHasher> Serialize for IndexSet<K, S> {
5349 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5350 serializer.write_usize(self.len())?;
5351 for k in self.iter() {
5352 k.serialize(serializer)?;
5353 }
5354 Ok(())
5355 }
5356}
5357
5358#[cfg(feature = "indexmap")]
5359impl<K: Deserialize + Eq + Hash + 'static> Deserialize for IndexSet<K> {
5360 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5361 let l = deserializer.read_usize()?;
5362 let mut ret = IndexSet::with_capacity(l);
5363 for _ in 0..l {
5364 ret.insert(K::deserialize(deserializer)?);
5365 }
5366 Ok(ret)
5367 }
5368}
5369
5370#[cfg_attr(
5390 feature = "rust1_78",
5391 diagnostic::on_unimplemented(
5392 message = "`{Self}` cannot serve as a factory generating default values of type {T}, since it doesn't implement the trait `savefile::ValueConstructor<{T}>`-",
5393 label = "`{Self}` cannot produce values of type `{T}`",
5394 note = "Check that any type used as 2nd type parameter to AbiRemoved implements `savefile::ValueConstructor<{T}>`.",
5395 note = "Alternatively, skip the 2nd parameter entirely, and ensure that `{T}` implements `Default`.",
5396 )
5397)]
5398pub trait ValueConstructor<T> {
5399 fn make_value() -> T;
5403}
5404
5405#[derive(Debug, PartialEq, Eq)]
5408pub struct DefaultValueConstructor<T> {
5409 phantom: PhantomData<*const T>,
5410}
5411
5412impl<T: Default> ValueConstructor<T> for DefaultValueConstructor<T> {
5413 fn make_value() -> T {
5414 <T as Default>::default()
5415 }
5416}
5417
5418#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
5428pub struct Removed<T> {
5429 phantom: std::marker::PhantomData<*const T>,
5430}
5431
5432unsafe impl<T> Send for Removed<T> {}
5436unsafe impl<T> Sync for Removed<T> {}
5440
5441impl<T> Removed<T> {
5442 pub fn new() -> Removed<T> {
5444 Removed {
5445 phantom: std::marker::PhantomData,
5446 }
5447 }
5448}
5449impl<T: WithSchema> WithSchema for Removed<T> {
5450 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5451 <T>::schema(version, context)
5452 }
5453}
5454
5455impl<T: Introspect> Introspect for Removed<T> {
5456 fn introspect_value(&self) -> String {
5457 format!("Removed<{}>", std::any::type_name::<T>())
5458 }
5459
5460 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5461 None
5462 }
5463}
5464impl<T> Packed for Removed<T> {
5465 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
5466 IsPacked::yes()
5467 }
5468}
5469impl<T: WithSchema> Serialize for Removed<T> {
5470 fn serialize(&self, _serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5471 panic!("Something is wrong with version-specification of fields - there was an attempt to actually serialize a removed field!");
5472 }
5473}
5474impl<T: WithSchema + Deserialize> Deserialize for Removed<T> {
5475 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5476 T::deserialize(deserializer)?;
5477 Ok(Removed {
5478 phantom: std::marker::PhantomData,
5479 })
5480 }
5481}
5482
5483#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
5491pub struct AbiRemoved<T, D = DefaultValueConstructor<T>>
5492where
5493 D: ValueConstructor<T>,
5494{
5495 phantom: std::marker::PhantomData<(*const T, *const D)>,
5496}
5497
5498unsafe impl<T, D: ValueConstructor<T>> Send for AbiRemoved<T, D> {}
5502unsafe impl<T, D: ValueConstructor<T>> Sync for AbiRemoved<T, D> {}
5506
5507impl<T, D: ValueConstructor<T>> AbiRemoved<T, D> {
5508 pub fn new() -> AbiRemoved<T, D> {
5510 AbiRemoved {
5511 phantom: std::marker::PhantomData,
5512 }
5513 }
5514}
5515
5516impl<T: WithSchema, D: ValueConstructor<T>> WithSchema for AbiRemoved<T, D> {
5517 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5518 <T>::schema(version, context)
5519 }
5520}
5521
5522impl<T: Introspect, D: ValueConstructor<T>> Introspect for AbiRemoved<T, D> {
5523 fn introspect_value(&self) -> String {
5524 format!("AbiRemoved<{}>", std::any::type_name::<T>())
5525 }
5526
5527 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5528 None
5529 }
5530}
5531impl<T, D: ValueConstructor<T>> Packed for AbiRemoved<T, D> {
5532 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
5533 IsPacked::yes()
5534 }
5535}
5536impl<T: WithSchema + Serialize + Default, D: ValueConstructor<T>> Serialize for AbiRemoved<T, D> {
5537 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5538 let dummy = D::make_value();
5539 dummy.serialize(serializer)?;
5540 Ok(())
5541 }
5542}
5543impl<T: WithSchema + Deserialize, D: ValueConstructor<T>> Deserialize for AbiRemoved<T, D> {
5544 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5545 T::deserialize(deserializer)?;
5546 Ok(AbiRemoved {
5547 phantom: std::marker::PhantomData,
5548 })
5549 }
5550}
5551
5552impl<T> Introspect for PhantomData<T> {
5553 fn introspect_value(&self) -> String {
5554 "PhantomData".to_string()
5555 }
5556
5557 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5558 None
5559 }
5560}
5561impl<T> WithSchema for std::marker::PhantomData<T> {
5562 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
5563 Schema::ZeroSize
5564 }
5565}
5566impl<T> Packed for std::marker::PhantomData<T> {
5567 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
5568 IsPacked::yes()
5569 }
5570}
5571impl<T> Serialize for std::marker::PhantomData<T> {
5572 fn serialize(&self, _serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5573 Ok(())
5574 }
5575}
5576impl<T> Deserialize for std::marker::PhantomData<T> {
5577 fn deserialize(_deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5578 Ok(std::marker::PhantomData)
5579 }
5580}
5581
5582impl<T: Introspect> Introspect for Box<T> {
5583 fn introspect_value(&self) -> String {
5584 self.deref().introspect_value()
5585 }
5586 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5587 self.deref().introspect_child(index)
5588 }
5589 fn introspect_len(&self) -> usize {
5590 self.deref().introspect_len()
5591 }
5592}
5593impl<T: Introspect> Introspect for Option<T> {
5594 fn introspect_value(&self) -> String {
5595 if let Some(cont) = self {
5596 format!("Some({})", cont.introspect_value())
5597 } else {
5598 "None".to_string()
5599 }
5600 }
5601
5602 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5603 if let Some(cont) = self {
5604 cont.introspect_child(index)
5605 } else {
5606 None
5607 }
5608 }
5609 fn introspect_len(&self) -> usize {
5610 if let Some(cont) = self {
5611 cont.introspect_len()
5612 } else {
5613 0
5614 }
5615 }
5616}
5617
5618impl<T: WithSchema> WithSchema for Option<T> {
5619 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5620 Schema::SchemaOption(Box::new(T::schema(version, context)))
5621 }
5622}
5623impl<T> Packed for Option<T> {} impl<T: Serialize> Serialize for Option<T> {
5625 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5626 match self {
5627 Some(ref x) => {
5628 serializer.write_bool(true)?;
5629 x.serialize(serializer)
5630 }
5631 None => serializer.write_bool(false),
5632 }
5633 }
5634}
5635impl<T: Deserialize> Deserialize for Option<T> {
5636 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5637 let issome = deserializer.read_bool()?;
5638 if issome {
5639 Ok(Some(T::deserialize(deserializer)?))
5640 } else {
5641 Ok(None)
5642 }
5643 }
5644}
5645
5646impl<T: Introspect, R: Introspect> Introspect for Result<T, R> {
5647 fn introspect_value(&self) -> String {
5648 match self {
5649 Ok(cont) => format!("Ok({})", cont.introspect_value()),
5650 Err(cont) => format!("Err({})", cont.introspect_value()),
5651 }
5652 }
5653
5654 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5655 match self {
5656 Ok(cont) => cont.introspect_child(index),
5657 Err(cont) => cont.introspect_child(index),
5658 }
5659 }
5660 fn introspect_len(&self) -> usize {
5661 match self {
5662 Ok(cont) => cont.introspect_len(),
5663 Err(cont) => cont.introspect_len(),
5664 }
5665 }
5666}
5667
5668impl<T: WithSchema, R: WithSchema> WithSchema for Result<T, R> {
5669 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5670 Schema::Enum(SchemaEnum {
5671 dbg_name: "Result".to_string(),
5672 size: None,
5673 alignment: None,
5674 variants: vec![
5675 Variant {
5676 name: "Ok".to_string(),
5677 discriminant: 0,
5678 fields: vec![Field {
5679 name: "ok".to_string(),
5680 value: Box::new(T::schema(version, context)),
5681 offset: None,
5682 }],
5683 },
5684 Variant {
5685 name: "Err".to_string(),
5686 discriminant: 0,
5687 fields: vec![Field {
5688 name: "err".to_string(),
5689 value: Box::new(R::schema(version, context)),
5690 offset: None,
5691 }],
5692 },
5693 ],
5694 discriminant_size: 1,
5695 has_explicit_repr: false,
5696 })
5697 }
5698}
5699impl<T, R> Packed for Result<T, R> {} impl<T: Serialize, R: Serialize> Serialize for Result<T, R> {
5701 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5702 match self {
5703 Ok(x) => {
5704 serializer.write_bool(true)?;
5705 x.serialize(serializer)
5706 }
5707 Err(x) => {
5708 serializer.write_bool(false)?;
5709 x.serialize(serializer)
5710 }
5711 }
5712 }
5713}
5714impl<T: Deserialize, R: Deserialize> Deserialize for Result<T, R> {
5715 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5716 let issome = deserializer.read_bool()?;
5717 if issome {
5718 Ok(Ok(T::deserialize(deserializer)?))
5719 } else {
5720 Ok(Err(R::deserialize(deserializer)?))
5721 }
5722 }
5723}
5724
5725#[cfg(any(feature = "bit-vec", feature = "bit-vec08"))]
5726#[cfg(target_endian = "big")]
5727compile_error!("savefile bit-vec feature does not support big-endian machines");
5728
5729#[cfg(feature = "bit-vec")]
5730impl WithSchema for bit_vec::BitVec {
5731 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5732 Schema::Struct(SchemaStruct {
5733 dbg_name: "BitVec".to_string(),
5734 size: None,
5735 alignment: None,
5736 fields: vec![
5737 Field {
5738 name: "num_bits".to_string(),
5739 value: Box::new(usize::schema(version, context)),
5740 offset: None,
5741 },
5742 Field {
5743 name: "num_bytes".to_string(),
5744 value: Box::new(usize::schema(version, context)),
5745 offset: None,
5746 },
5747 Field {
5748 name: "buffer".to_string(),
5749 value: Box::new(Schema::Vector(
5750 Box::new(u8::schema(version, context)),
5751 VecOrStringLayout::Unknown,
5752 )),
5753 offset: None,
5754 },
5755 ],
5756 })
5757 }
5758}
5759
5760#[cfg(feature = "bit-vec")]
5761impl Introspect for bit_vec::BitVec {
5762 fn introspect_value(&self) -> String {
5763 let mut ret = String::new();
5764 for i in 0..self.len() {
5765 if self[i] {
5766 ret.push('1');
5767 } else {
5768 ret.push('0');
5769 }
5770 }
5771 ret
5772 }
5773
5774 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5775 None
5776 }
5777}
5778
5779#[cfg(feature = "bit-vec")]
5780impl Serialize for bit_vec::BitVec<u32> {
5781 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5782 let l = self.len();
5783 serializer.write_usize(l)?;
5784 let storage = self.storage();
5785 let rawbytes_ptr = storage.as_ptr() as *const u8;
5786 let rawbytes: &[u8] = unsafe { std::slice::from_raw_parts(rawbytes_ptr, 4 * storage.len()) };
5787 serializer.write_usize(rawbytes.len() | (1 << 63))?;
5788 serializer.write_bytes(rawbytes)?;
5789 Ok(())
5790 }
5791}
5792
5793#[cfg(feature = "bit-vec")]
5794impl Packed for bit_vec::BitVec<u32> {}
5795
5796#[cfg(feature = "bit-vec")]
5797impl Deserialize for bit_vec::BitVec<u32> {
5798 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5799 let numbits = deserializer.read_usize()?;
5800 let mut numbytes = deserializer.read_usize()?;
5801 if numbytes & (1 << 63) != 0 {
5802 numbytes &= !(1 << 63);
5804 let mut ret = bit_vec::BitVec::with_capacity(numbytes * 8);
5805 unsafe {
5806 let num_words = numbytes / 4;
5807 let storage = ret.storage_mut();
5808 storage.resize(num_words, 0);
5809 let storage_ptr = storage.as_ptr() as *mut u8;
5810 let storage_bytes: &mut [u8] = std::slice::from_raw_parts_mut(storage_ptr, 4 * num_words);
5811 deserializer.read_bytes_to_buf(storage_bytes)?;
5812 ret.set_len(numbits);
5813 }
5814 Ok(ret)
5815 } else {
5816 let bytes = deserializer.read_bytes(numbytes)?;
5817 let mut ret = bit_vec::BitVec::from_bytes(&bytes);
5818 ret.truncate(numbits);
5819 Ok(ret)
5820 }
5821 }
5822}
5823
5824#[cfg(feature = "bit-set")]
5825impl WithSchema for bit_set::BitSet {
5826 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5827 Schema::Struct(SchemaStruct {
5828 dbg_name: "BitSet".to_string(),
5829 size: None,
5830 alignment: None,
5831 fields: vec![
5832 Field {
5833 name: "num_bits".to_string(),
5834 value: Box::new(usize::schema(version, context)),
5835 offset: None,
5836 },
5837 Field {
5838 name: "num_bytes".to_string(),
5839 value: Box::new(usize::schema(version, context)),
5840 offset: None,
5841 },
5842 Field {
5843 name: "buffer".to_string(),
5844 value: Box::new(Schema::Vector(
5845 Box::new(u8::schema(version, context)),
5846 VecOrStringLayout::Unknown,
5847 )),
5848 offset: None,
5849 },
5850 ],
5851 })
5852 }
5853}
5854
5855#[cfg(feature = "bit-set")]
5856impl Introspect for bit_set::BitSet {
5857 fn introspect_value(&self) -> String {
5858 let mut ret = String::new();
5859 for i in 0..self.len() {
5860 if self.contains(i) {
5861 use std::fmt::Write;
5862 if !ret.is_empty() {
5863 ret += " ";
5864 }
5865 write!(&mut ret, "{}", i).unwrap();
5866 }
5867 }
5868 ret
5869 }
5870
5871 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5872 None
5873 }
5874}
5875
5876#[cfg(feature = "bit-set")]
5877impl Packed for bit_set::BitSet<u32> {}
5878
5879#[cfg(feature = "bit-set")]
5880impl Serialize for bit_set::BitSet<u32> {
5881 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5882 let bitset = self.get_ref();
5883 bitset.serialize(serializer)
5884 }
5885}
5886
5887#[cfg(feature = "bit-set")]
5888impl Deserialize for bit_set::BitSet<u32> {
5889 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5890 let bit_vec: bit_vec::BitVec = bit_vec::BitVec::deserialize(deserializer)?;
5891 Ok(bit_set::BitSet::from_bit_vec(bit_vec))
5892 }
5893}
5894
5895#[cfg(feature = "bit-vec08")]
5896impl WithSchema for bit_vec08::BitVec {
5897 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5898 Schema::Struct(SchemaStruct {
5899 dbg_name: "BitVec".to_string(),
5900 size: None,
5901 alignment: None,
5902 fields: vec![
5903 Field {
5904 name: "num_bits".to_string(),
5905 value: Box::new(usize::schema(version, context)),
5906 offset: None,
5907 },
5908 Field {
5909 name: "num_bytes".to_string(),
5910 value: Box::new(usize::schema(version, context)),
5911 offset: None,
5912 },
5913 Field {
5914 name: "buffer".to_string(),
5915 value: Box::new(Schema::Vector(
5916 Box::new(u8::schema(version, context)),
5917 VecOrStringLayout::Unknown,
5918 )),
5919 offset: None,
5920 },
5921 ],
5922 })
5923 }
5924}
5925
5926#[cfg(feature = "bit-vec08")]
5927impl Introspect for bit_vec08::BitVec {
5928 fn introspect_value(&self) -> String {
5929 let mut ret = String::new();
5930 for i in 0..self.len() {
5931 if self[i] {
5932 ret.push('1');
5933 } else {
5934 ret.push('0');
5935 }
5936 }
5937 ret
5938 }
5939
5940 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
5941 None
5942 }
5943}
5944
5945#[cfg(feature = "bit-vec08")]
5946impl Serialize for bit_vec08::BitVec<u32> {
5947 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
5948 let l = self.len();
5949 serializer.write_usize(l)?;
5950 let storage = self.storage();
5951 let rawbytes_ptr = storage.as_ptr() as *const u8;
5952 let rawbytes: &[u8] = unsafe { std::slice::from_raw_parts(rawbytes_ptr, 4 * storage.len()) };
5953 serializer.write_usize(rawbytes.len() | (1 << 63))?;
5954 serializer.write_bytes(rawbytes)?;
5955 Ok(())
5956 }
5957}
5958
5959#[cfg(feature = "bit-vec08")]
5960impl Packed for bit_vec08::BitVec<u32> {}
5961
5962#[cfg(feature = "bit-vec08")]
5963impl Deserialize for bit_vec08::BitVec<u32> {
5964 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
5965 let numbits = deserializer.read_usize()?;
5966 let mut numbytes = deserializer.read_usize()?;
5967 if numbytes & (1 << 63) != 0 {
5968 numbytes &= !(1 << 63);
5970 let mut ret = bit_vec08::BitVec::with_capacity(numbytes * 8);
5971 unsafe {
5972 let num_words = numbytes / 4;
5973 let storage = ret.storage_mut();
5974 storage.resize(num_words, 0);
5975 let storage_ptr = storage.as_ptr() as *mut u8;
5976 let storage_bytes: &mut [u8] = std::slice::from_raw_parts_mut(storage_ptr, 4 * num_words);
5977 deserializer.read_bytes_to_buf(storage_bytes)?;
5978 ret.set_len(numbits);
5979 }
5980 Ok(ret)
5981 } else {
5982 let bytes = deserializer.read_bytes(numbytes)?;
5983 let mut ret = bit_vec08::BitVec::from_bytes(&bytes);
5984 ret.truncate(numbits);
5985 Ok(ret)
5986 }
5987 }
5988}
5989
5990#[cfg(feature = "bit-set")]
5991impl WithSchema for bit_set08::BitSet {
5992 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
5993 Schema::Struct(SchemaStruct {
5994 dbg_name: "BitSet".to_string(),
5995 size: None,
5996 alignment: None,
5997 fields: vec![
5998 Field {
5999 name: "num_bits".to_string(),
6000 value: Box::new(usize::schema(version, context)),
6001 offset: None,
6002 },
6003 Field {
6004 name: "num_bytes".to_string(),
6005 value: Box::new(usize::schema(version, context)),
6006 offset: None,
6007 },
6008 Field {
6009 name: "buffer".to_string(),
6010 value: Box::new(Schema::Vector(
6011 Box::new(u8::schema(version, context)),
6012 VecOrStringLayout::Unknown,
6013 )),
6014 offset: None,
6015 },
6016 ],
6017 })
6018 }
6019}
6020
6021#[cfg(feature = "bit-set08")]
6022impl Introspect for bit_set08::BitSet {
6023 fn introspect_value(&self) -> String {
6024 let mut ret = String::new();
6025 for i in 0..self.len() {
6026 if self.contains(i) {
6027 use std::fmt::Write;
6028 if !ret.is_empty() {
6029 ret += " ";
6030 }
6031 write!(&mut ret, "{}", i).unwrap();
6032 }
6033 }
6034 ret
6035 }
6036
6037 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
6038 None
6039 }
6040}
6041
6042#[cfg(feature = "bit-set08")]
6043impl Packed for bit_set08::BitSet<u32> {}
6044
6045#[cfg(feature = "bit-set08")]
6046impl Serialize for bit_set08::BitSet<u32> {
6047 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6048 let bitset = self.get_ref();
6049 bitset.serialize(serializer)
6050 }
6051}
6052
6053#[cfg(feature = "bit-set")]
6054impl Deserialize for bit_set08::BitSet<u32> {
6055 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6056 let bit_vec: bit_vec08::BitVec = bit_vec08::BitVec::deserialize(deserializer)?;
6057 Ok(bit_set08::BitSet::from_bit_vec(bit_vec))
6058 }
6059}
6060
6061impl<T: Introspect> Introspect for BinaryHeap<T> {
6062 fn introspect_value(&self) -> String {
6063 "BinaryHeap".to_string()
6064 }
6065
6066 fn introspect_child<'a>(&'a self, index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
6067 if index >= self.len() {
6068 return None;
6069 }
6070 return Some(introspect_item(index.to_string(), self.iter().nth(index).unwrap()));
6071 }
6072
6073 fn introspect_len(&self) -> usize {
6074 self.len()
6075 }
6076}
6077
6078impl<T> Packed for BinaryHeap<T> {}
6079impl<T: WithSchema + 'static> WithSchema for BinaryHeap<T> {
6080 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6081 Schema::Vector(
6082 Box::new(context.possible_recursion::<T>(|context| T::schema(version, context))),
6083 VecOrStringLayout::Unknown,
6084 )
6085 }
6086}
6087impl<T: Serialize + Ord + 'static> Serialize for BinaryHeap<T> {
6088 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6089 let l = self.len();
6090 serializer.write_usize(l)?;
6091 for item in self.iter() {
6092 item.serialize(serializer)?
6093 }
6094 Ok(())
6095 }
6096}
6097impl<T: Deserialize + Ord + 'static> Deserialize for BinaryHeap<T> {
6098 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6099 let l = deserializer.read_usize()?;
6100 let mut ret = BinaryHeap::with_capacity(l);
6101 for _ in 0..l {
6102 ret.push(T::deserialize(deserializer)?);
6103 }
6104 Ok(ret)
6105 }
6106}
6107
6108#[cfg(feature = "smallvec")]
6109impl<T: smallvec::Array> Introspect for smallvec::SmallVec<T>
6110where
6111 T::Item: Introspect,
6112{
6113 fn introspect_value(&self) -> String {
6114 format!("SmallVec<{}>", std::any::type_name::<T>())
6115 }
6116
6117 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
6118 if let Some(val) = self.get(index) {
6119 Some(introspect_item(index.to_string(), val))
6120 } else {
6121 None
6122 }
6123 }
6124
6125 fn introspect_len(&self) -> usize {
6126 self.len()
6127 }
6128}
6129
6130#[cfg(feature = "smallvec")]
6131impl<T: smallvec::Array + 'static> WithSchema for smallvec::SmallVec<T>
6132where
6133 T::Item: WithSchema,
6134{
6135 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6136 Schema::Vector(
6137 Box::new(context.possible_recursion::<T>(|context| T::Item::schema(version, context))),
6138 VecOrStringLayout::Unknown,
6139 )
6140 }
6141}
6142#[cfg(feature = "smallvec")]
6143impl<T: smallvec::Array> Packed for smallvec::SmallVec<T> {}
6144
6145#[cfg(feature = "smallvec")]
6146impl<T: smallvec::Array + 'static> Serialize for smallvec::SmallVec<T>
6147where
6148 T::Item: Serialize,
6149{
6150 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6151 let l = self.len();
6152 serializer.write_usize(l)?;
6153 for item in self.iter() {
6154 item.serialize(serializer)?
6155 }
6156 Ok(())
6157 }
6158}
6159#[cfg(feature = "smallvec")]
6160impl<T: smallvec::Array + 'static> Deserialize for smallvec::SmallVec<T>
6161where
6162 T::Item: Deserialize,
6163{
6164 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6165 let l = deserializer.read_usize()?;
6166 let mut ret = Self::with_capacity(l);
6167 for _ in 0..l {
6168 ret.push(T::Item::deserialize(deserializer)?);
6169 }
6170 Ok(ret)
6171 }
6172}
6173
6174fn regular_serialize_vec<T: Serialize>(
6175 items: &[T],
6176 serializer: &mut Serializer<impl Write>,
6177) -> Result<(), SavefileError> {
6178 let l = items.len();
6179 serializer.write_usize(l)?;
6180 if std::mem::size_of::<T>() == 0 {
6181 return Ok(());
6182 }
6183
6184 if std::mem::size_of::<T>() < 32 {
6185 let chunks = items.chunks_exact((64 / std::mem::size_of::<T>()).max(1));
6187 let remainder = chunks.remainder();
6188 for chunk in chunks {
6189 for item in chunk {
6190 item.serialize(serializer)?;
6191 }
6192 }
6193 for item in remainder {
6194 item.serialize(serializer)?;
6195 }
6196 Ok(())
6197 } else {
6198 for item in items {
6199 item.serialize(serializer)?;
6200 }
6201 Ok(())
6202 }
6203}
6204
6205impl<T: WithSchema + 'static> WithSchema for Box<[T]> {
6206 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6207 Schema::Vector(
6208 Box::new(context.possible_recursion::<T>(|context| T::schema(version, context))),
6209 VecOrStringLayout::Unknown,
6210 )
6211 }
6212}
6213impl<T: WithSchema + 'static> WithSchema for Arc<[T]> {
6214 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6215 Schema::Vector(
6216 Box::new(context.possible_recursion::<T>(|context| T::schema(version, context))),
6217 VecOrStringLayout::Unknown,
6218 )
6219 }
6220}
6221impl<T: Introspect> Introspect for Box<[T]> {
6222 fn introspect_value(&self) -> String {
6223 return "Box[]".to_string();
6224 }
6225
6226 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
6227 if index >= self.len() {
6228 return None;
6229 }
6230 return Some(introspect_item(index.to_string(), &self[index]));
6231 }
6232 fn introspect_len(&self) -> usize {
6233 self.len()
6234 }
6235}
6236
6237impl<T: Introspect> Introspect for Arc<[T]> {
6238 fn introspect_value(&self) -> String {
6239 return "Arc[]".to_string();
6240 }
6241
6242 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
6243 if index >= self.len() {
6244 return None;
6245 }
6246 return Some(introspect_item(index.to_string(), &self[index]));
6247 }
6248 fn introspect_len(&self) -> usize {
6249 self.len()
6250 }
6251}
6252
6253impl WithSchema for Arc<str> {
6254 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
6255 Schema::Primitive(SchemaPrimitive::schema_string(VecOrStringLayout::Unknown))
6256 }
6257}
6258impl Introspect for Arc<str> {
6259 fn introspect_value(&self) -> String {
6260 self.deref().to_string()
6261 }
6262
6263 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem>> {
6264 None
6265 }
6266 fn introspect_len(&self) -> usize {
6267 0
6268 }
6269}
6270impl Serialize for Arc<str> {
6271 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6272 serializer.write_string(self)
6273 }
6274}
6275
6276impl Packed for Arc<str> {}
6277
6278impl Deserialize for Arc<str> {
6279 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6280 let s = deserializer.read_string()?;
6281
6282 let state = deserializer.get_state::<Arc<str>, HashMap<String, Arc<str>>>();
6283
6284 if let Some(needle) = state.get(&s) {
6285 return Ok(Arc::clone(needle));
6286 }
6287
6288 let arc_ref = state.entry(s.clone()).or_insert(s.into());
6289 Ok(Arc::clone(arc_ref))
6290 }
6291}
6292
6293impl<T: Serialize + Packed + 'static> Serialize for Box<[T]> {
6294 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6295 unsafe {
6296 if T::repr_c_optimization_safe(serializer.file_version).is_false() {
6297 regular_serialize_vec(self, serializer)
6298 } else {
6299 let l = self.len();
6300 serializer.write_usize(l)?;
6301 serializer.write_buf(std::slice::from_raw_parts(
6302 (*self).as_ptr() as *const u8,
6303 std::mem::size_of::<T>() * l,
6304 ))
6305 }
6306 }
6307 }
6308}
6309impl<T: Packed> Packed for Box<[T]> {}
6310
6311impl<T: Serialize + Packed + 'static> Serialize for Arc<[T]> {
6312 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6313 unsafe {
6314 if T::repr_c_optimization_safe(serializer.file_version).is_false() {
6315 regular_serialize_vec(self, serializer)
6316 } else {
6317 let l = self.len();
6318 serializer.write_usize(l)?;
6319 serializer.write_buf(std::slice::from_raw_parts(
6320 (*self).as_ptr() as *const u8,
6321 std::mem::size_of::<T>() * l,
6322 ))
6323 }
6324 }
6325 }
6326}
6327impl<T: Packed> Packed for Arc<[T]> {}
6328
6329impl<T: Deserialize + Packed + 'static> Deserialize for Arc<[T]> {
6330 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6331 Ok(Vec::<T>::deserialize(deserializer)?.into())
6332 }
6333}
6334impl<T: Deserialize + Packed + 'static> Deserialize for Box<[T]> {
6335 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6336 Ok(Vec::<T>::deserialize(deserializer)?.into_boxed_slice())
6337 }
6338}
6339impl WithSchema for &'_ str {
6340 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
6341 Schema::Primitive(SchemaPrimitive::schema_string(calculate_string_memory_layout()))
6342 }
6344}
6345impl Serialize for &'_ str {
6346 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6347 let l = self.len();
6348 serializer.write_usize(l)?;
6349 serializer.write_buf(self.as_bytes())
6350 }
6351}
6352
6353impl<T: WithSchema + 'static> WithSchema for &'_ [T] {
6354 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6355 Schema::Vector(
6356 Box::new(context.possible_recursion::<T>(|context| T::schema(version, context))),
6357 calculate_slice_memory_layout::<T>(),
6358 )
6359 }
6361}
6362impl<T: Serialize + Packed + 'static> Serialize for &'_ [T] {
6363 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6364 unsafe {
6365 if T::repr_c_optimization_safe(serializer.file_version).is_false() {
6366 regular_serialize_vec(self, serializer)
6367 } else {
6368 let l = self.len();
6369 serializer.write_usize(l)?;
6370 #[allow(clippy::manual_slice_size_calculation)] serializer.write_buf(std::slice::from_raw_parts(
6372 self.as_ptr() as *const u8,
6373 std::mem::size_of::<T>() * l,
6374 ))
6375 }
6376 }
6377 }
6378}
6379
6380pub fn deserialize_slice_as_vec<R: Read, T: Deserialize + Packed + 'static>(
6383 deserializer: &mut Deserializer<R>,
6384) -> Result<Vec<T>, SavefileError> {
6385 Vec::deserialize(deserializer)
6386}
6387
6388impl<T> Packed for Vec<T> {}
6389
6390static STRING_IS_STANDARD_LAYOUT: AtomicU8 = AtomicU8::new(255);
6392#[derive(Debug)]
6393#[repr(C)]
6394struct RawVecInspector {
6395 p1: usize,
6396 p2: usize,
6397 p3: usize,
6398}
6399#[derive(Debug)]
6400#[repr(C)]
6401struct RawSliceInspector {
6402 p1: usize,
6403 p2: usize,
6404}
6405impl RawSliceInspector {
6406 const fn get_layout(&self) -> VecOrStringLayout {
6407 if self.p1 == 0 {
6408 VecOrStringLayout::LengthData
6409 } else {
6410 VecOrStringLayout::DataLength
6411 }
6412 }
6413}
6414impl RawVecInspector {
6415 fn get_layout(&self, ptr: *const u8) -> VecOrStringLayout {
6416 let ptr = ptr as usize;
6417 const LENGTH: usize = 0;
6419 const CAPACITY: usize = 7;
6420 match (self.p1, self.p2, self.p3) {
6421 (LENGTH, CAPACITY, x) if x == ptr => VecOrStringLayout::LengthCapacityData,
6422 (CAPACITY, LENGTH, x) if x == ptr => VecOrStringLayout::CapacityLengthData,
6423 (LENGTH, x, CAPACITY) if x == ptr => VecOrStringLayout::LengthDataCapacity,
6424 (CAPACITY, x, LENGTH) if x == ptr => VecOrStringLayout::CapacityDataLength,
6425 (x, LENGTH, CAPACITY) if x == ptr => VecOrStringLayout::DataLengthCapacity,
6426 (x, CAPACITY, LENGTH) if x == ptr => VecOrStringLayout::DataCapacityLength,
6427 _ => VecOrStringLayout::Unknown,
6428 }
6429 }
6430}
6431
6432pub const fn calculate_slice_memory_layout<T>() -> VecOrStringLayout {
6438 if std::mem::size_of::<&[T]>() != 16 || std::mem::size_of::<RawSliceInspector>() != 16 {
6439 VecOrStringLayout::Unknown
6440 } else {
6441 let test_slice: &[T] = &[];
6442 let insp: RawSliceInspector = unsafe { std::mem::transmute_copy::<&[T], RawSliceInspector>(&test_slice) };
6443 insp.get_layout()
6444 }
6445}
6446pub fn calculate_vec_memory_layout<T>() -> VecOrStringLayout {
6448 if std::mem::size_of::<Vec<u8>>() != 24 || std::mem::size_of::<RawVecInspector>() != 24 {
6449 VecOrStringLayout::Unknown
6450 } else {
6451 let test_vec = Vec::with_capacity(7);
6452 let insp: RawVecInspector = unsafe { std::mem::transmute_copy(&test_vec) };
6453 let ptr = test_vec.as_ptr();
6454 insp.get_layout(ptr)
6455 }
6456}
6457fn calculate_string_memory_layout() -> VecOrStringLayout {
6458 let mut is_std = STRING_IS_STANDARD_LAYOUT.load(Ordering::Relaxed);
6459 if is_std != 255 {
6460 return unsafe { std::mem::transmute::<u8, VecOrStringLayout>(is_std) };
6464 }
6465 if std::mem::size_of::<String>() != 24 || std::mem::size_of::<RawVecInspector>() != 24 {
6466 is_std = VecOrStringLayout::Unknown as u8;
6467 } else {
6468 let test_string = String::with_capacity(7);
6469 let insp: RawVecInspector = unsafe { std::mem::transmute_copy(&test_string) };
6470 let ptr = test_string.as_ptr();
6471
6472 is_std = insp.get_layout(ptr) as u8;
6473
6474 drop(test_string);
6475 }
6476
6477 STRING_IS_STANDARD_LAYOUT.store(is_std, Ordering::Relaxed);
6478 return unsafe { std::mem::transmute::<u8, VecOrStringLayout>(is_std) };
6479}
6480impl<T: WithSchema + 'static> WithSchema for Vec<T> {
6481 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6482 Schema::Vector(
6483 Box::new(context.possible_recursion::<T>(|context| T::schema(version, context))),
6484 calculate_vec_memory_layout::<T>(),
6485 )
6486 }
6487}
6488
6489impl<T: Introspect> Introspect for Vec<T> {
6490 fn introspect_value(&self) -> String {
6491 return "vec[]".to_string();
6492 }
6493
6494 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
6495 if index >= self.len() {
6496 return None;
6497 }
6498 return Some(introspect_item(index.to_string(), &self[index]));
6499 }
6500 fn introspect_len(&self) -> usize {
6501 self.len()
6502 }
6503}
6504
6505impl<T: Serialize + Packed + 'static> Serialize for Vec<T> {
6506 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6507 unsafe {
6508 if T::repr_c_optimization_safe(serializer.file_version).is_false() {
6509 regular_serialize_vec(self, serializer)
6510 } else {
6511 let l = self.len();
6512 serializer.write_usize(l)?;
6513 serializer.write_buf(std::slice::from_raw_parts(
6514 self.as_ptr() as *const u8,
6515 std::mem::size_of::<T>() * l,
6516 ))
6517 }
6518 }
6519 }
6520}
6521
6522fn regular_deserialize_vec<T: Deserialize>(
6523 deserializer: &mut Deserializer<impl Read>,
6524) -> Result<Vec<T>, SavefileError> {
6525 let l = deserializer.read_usize()?;
6526
6527 #[cfg(feature = "size_sanity_checks")]
6528 {
6529 if l > 1_000_000 {
6530 return Err(SavefileError::GeneralError {
6531 msg: format!("Too many items in Vec: {}", l),
6532 });
6533 }
6534 }
6535 let mut ret = Vec::with_capacity(l);
6536 for _ in 0..l {
6537 ret.push(T::deserialize(deserializer)?);
6538 }
6539 Ok(ret)
6540}
6541
6542impl<T: Deserialize + Packed + 'static> Deserialize for Vec<T> {
6543 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6544 if unsafe { T::repr_c_optimization_safe(deserializer.file_version) }.is_false() {
6545 Ok(regular_deserialize_vec(deserializer)?)
6546 } else {
6547 use std::mem;
6548
6549 let align = mem::align_of::<T>();
6550 let elem_size = mem::size_of::<T>();
6551 let num_elems = deserializer.read_usize()?;
6552
6553 if num_elems == 0 {
6554 return Ok(Vec::new());
6555 }
6556 let num_bytes = elem_size * num_elems;
6557
6558 let layout = if let Ok(layout) = std::alloc::Layout::from_size_align(num_bytes, align) {
6559 Ok(layout)
6560 } else {
6561 Err(SavefileError::MemoryAllocationLayoutError)
6562 }?;
6563 let ptr = if elem_size == 0 {
6564 NonNull::dangling().as_ptr()
6565 } else {
6566 let ptr = unsafe { std::alloc::alloc(layout) };
6567 if ptr.is_null() {
6568 panic!("Failed to allocate {} bytes of memory", num_bytes);
6569 }
6570
6571 ptr
6572 };
6573
6574 {
6575 let slice = unsafe { std::slice::from_raw_parts_mut(ptr, num_bytes) };
6576 match deserializer.reader.read_exact(slice) {
6577 Ok(()) => Ok(()),
6578 Err(err) => {
6579 unsafe {
6580 std::alloc::dealloc(ptr, layout);
6581 }
6582 Err(err)
6583 }
6584 }?;
6585 }
6586 let ret = unsafe { Vec::from_raw_parts(ptr as *mut T, num_elems, num_elems) };
6587 Ok(ret)
6588 }
6589 }
6590}
6591
6592impl<T: Introspect> Introspect for VecDeque<T> {
6593 fn introspect_value(&self) -> String {
6594 format!("VecDeque<{}>", std::any::type_name::<T>())
6595 }
6596
6597 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
6598 if let Some(val) = self.get(index) {
6599 Some(introspect_item(index.to_string(), val))
6600 } else {
6601 None
6602 }
6603 }
6604
6605 fn introspect_len(&self) -> usize {
6606 self.len()
6607 }
6608}
6609
6610impl<T: WithSchema + 'static> WithSchema for VecDeque<T> {
6611 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6612 Schema::Vector(
6613 Box::new(context.possible_recursion::<T>(|context| T::schema(version, context))),
6614 VecOrStringLayout::Unknown,
6615 )
6616 }
6617}
6618
6619impl<T> Packed for VecDeque<T> {}
6620impl<T: Serialize + 'static> Serialize for VecDeque<T> {
6621 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6622 regular_serialize_vecdeque(self, serializer)
6623 }
6624}
6625
6626impl<T: Deserialize + 'static> Deserialize for VecDeque<T> {
6627 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6628 Ok(regular_deserialize_vecdeque(deserializer)?)
6629 }
6630}
6631
6632fn regular_serialize_vecdeque<T: Serialize>(
6633 item: &VecDeque<T>,
6634 serializer: &mut Serializer<impl Write>,
6635) -> Result<(), SavefileError> {
6636 let l = item.len();
6637 serializer.write_usize(l)?;
6638 for item in item.iter() {
6639 item.serialize(serializer)?
6640 }
6641 Ok(())
6642}
6643
6644fn regular_deserialize_vecdeque<T: Deserialize>(
6645 deserializer: &mut Deserializer<impl Read>,
6646) -> Result<VecDeque<T>, SavefileError> {
6647 let l = deserializer.read_usize()?;
6648 let mut ret = VecDeque::with_capacity(l);
6649 for _ in 0..l {
6650 ret.push_back(T::deserialize(deserializer)?);
6651 }
6652 Ok(ret)
6653}
6654
6655impl Packed for bool {
6656 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6657 IsPacked::yes()
6658 }
6659} impl Packed for u8 {
6661 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6662 IsPacked::yes()
6663 }
6664}
6665impl Packed for i8 {
6666 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6667 IsPacked::yes()
6668 }
6669}
6670impl Packed for u16 {
6671 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6672 IsPacked::yes()
6673 }
6674}
6675impl Packed for i16 {
6676 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6677 IsPacked::yes()
6678 }
6679}
6680impl Packed for u32 {
6681 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6682 IsPacked::yes()
6683 }
6684}
6685impl Packed for i32 {
6686 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6687 IsPacked::yes()
6688 }
6689}
6690impl Packed for u64 {
6691 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6692 IsPacked::yes()
6693 }
6694}
6695impl Packed for u128 {
6696 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6697 IsPacked::yes()
6698 }
6699}
6700impl Packed for i128 {
6701 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6702 IsPacked::yes()
6703 }
6704}
6705impl Packed for i64 {
6706 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6707 IsPacked::yes()
6708 }
6709}
6710impl Packed for char {
6711 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6712 IsPacked::yes()
6713 }
6714}
6715impl Packed for f32 {
6716 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6717 IsPacked::yes()
6718 }
6719}
6720impl Packed for f64 {
6721 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6722 IsPacked::yes()
6723 }
6724}
6725impl Packed for usize {
6726 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6727 IsPacked::no()
6728 } }
6730impl Packed for isize {
6731 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6732 IsPacked::no()
6733 } }
6735impl Packed for () {
6736 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
6737 IsPacked::yes()
6738 }
6739}
6740
6741impl<T: WithSchema + 'static, const N: usize> WithSchema for [T; N] {
6742 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6743 Schema::Array(SchemaArray {
6744 item_type: Box::new(context.possible_recursion::<T>(|context| T::schema(version, context))),
6745 count: N,
6746 })
6747 }
6748}
6749
6750impl<T: Introspect, const N: usize> Introspect for [T; N] {
6751 fn introspect_value(&self) -> String {
6752 format!("[{}; {}]", std::any::type_name::<T>(), N)
6753 }
6754
6755 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
6756 if index >= self.len() {
6757 None
6758 } else {
6759 Some(introspect_item(index.to_string(), &self[index]))
6760 }
6761 }
6762}
6763
6764impl<T: Packed, const N: usize> Packed for [T; N] {
6765 unsafe fn repr_c_optimization_safe(version: u32) -> IsPacked {
6766 T::repr_c_optimization_safe(version)
6767 }
6768}
6769impl<T: Serialize + Packed + 'static, const N: usize> Serialize for [T; N] {
6770 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6771 if N == 0 {
6772 return Ok(());
6773 }
6774 unsafe {
6775 if T::repr_c_optimization_safe(serializer.file_version).is_false() {
6776 for item in self.iter() {
6777 item.serialize(serializer)?
6778 }
6779 Ok(())
6780 } else {
6781 serializer.write_buf(std::slice::from_raw_parts(
6782 self.as_ptr() as *const u8,
6783 std::mem::size_of::<T>() * N,
6784 ))
6785 }
6786 }
6787 }
6788}
6789
6790impl<T: Deserialize + Packed + 'static, const N: usize> Deserialize for [T; N] {
6791 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6792 if N == 0 {
6793 return Ok([(); N].map(|_| unreachable!()));
6794 }
6795
6796 if unsafe { T::repr_c_optimization_safe(deserializer.file_version) }.is_false() {
6797 let mut data: [MaybeUninit<T>; N] = unsafe {
6798 MaybeUninit::uninit().assume_init() };
6800 for idx in 0..N {
6801 data[idx] = MaybeUninit::new(T::deserialize(deserializer)?); }
6803 let ptr = &mut data as *mut _ as *mut [T; N];
6804 let res = unsafe { ptr.read() };
6805 Ok(res)
6806 } else {
6807 let mut data: [MaybeUninit<T>; N] = unsafe {
6808 MaybeUninit::uninit().assume_init() };
6810
6811 {
6812 let ptr = data.as_mut_ptr();
6813 let num_bytes: usize = std::mem::size_of::<T>() * N;
6814 let slice: &mut [MaybeUninit<u8>] =
6815 unsafe { std::slice::from_raw_parts_mut(ptr as *mut MaybeUninit<u8>, num_bytes) };
6816 deserializer
6817 .reader
6818 .read_exact(unsafe { std::mem::transmute::<&mut [MaybeUninit<u8>], &mut [u8]>(slice) })?;
6819 }
6820 let ptr = &mut data as *mut _ as *mut [T; N];
6821 let res = unsafe { ptr.read() };
6822 Ok(res)
6823 }
6824 }
6825}
6826
6827impl<T1> Packed for Range<T1> {}
6828impl<T1: WithSchema> WithSchema for Range<T1> {
6829 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6830 Schema::new_tuple2::<T1, T1>(version, context)
6831 }
6832}
6833impl<T1: Serialize> Serialize for Range<T1> {
6834 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6835 self.start.serialize(serializer)?;
6836 self.end.serialize(serializer)?;
6837 Ok(())
6838 }
6839}
6840impl<T1: Deserialize> Deserialize for Range<T1> {
6841 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6842 Ok(T1::deserialize(deserializer)?..T1::deserialize(deserializer)?)
6843 }
6844}
6845impl<T1: Introspect> Introspect for Range<T1> {
6846 fn introspect_value(&self) -> String {
6847 return "Range".to_string();
6848 }
6849
6850 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
6851 if index == 0 {
6852 return Some(introspect_item("start".to_string(), &self.start));
6853 }
6854 if index == 1 {
6855 return Some(introspect_item("end".to_string(), &self.end));
6856 }
6857 return None;
6858 }
6859}
6860
6861impl<T1: Packed> Packed for (T1,) {
6862 unsafe fn repr_c_optimization_safe(version: u32) -> IsPacked {
6863 if offset_of_tuple!((T1,), 0) == 0 && std::mem::size_of::<T1>() == std::mem::size_of::<(T1,)>() {
6864 T1::repr_c_optimization_safe(version)
6865 } else {
6866 IsPacked::no()
6867 }
6868 }
6869}
6870impl<T1: Packed, T2: Packed> Packed for (T1, T2) {
6871 unsafe fn repr_c_optimization_safe(version: u32) -> IsPacked {
6872 if offset_of_tuple!((T1, T2), 0) == 0
6873 && std::mem::size_of::<T1>() + std::mem::size_of::<T2>() == std::mem::size_of::<(T1, T2)>()
6874 {
6875 T1::repr_c_optimization_safe(version) & T2::repr_c_optimization_safe(version)
6876 } else {
6877 IsPacked::no()
6878 }
6879 }
6880}
6881impl<T1: Packed, T2: Packed, T3: Packed> Packed for (T1, T2, T3) {
6882 unsafe fn repr_c_optimization_safe(version: u32) -> IsPacked {
6883 if offset_of_tuple!((T1, T2, T3), 0) == 0
6884 && offset_of_tuple!((T1, T2, T3), 1) == std::mem::size_of::<T1>()
6885 && std::mem::size_of::<T1>() + std::mem::size_of::<T2>() + std::mem::size_of::<T3>()
6886 == std::mem::size_of::<(T1, T2, T3)>()
6887 {
6888 T1::repr_c_optimization_safe(version)
6889 & T2::repr_c_optimization_safe(version)
6890 & T3::repr_c_optimization_safe(version)
6891 } else {
6892 IsPacked::no()
6893 }
6894 }
6895}
6896impl<T1: Packed, T2: Packed, T3: Packed, T4: Packed> Packed for (T1, T2, T3, T4) {
6897 unsafe fn repr_c_optimization_safe(version: u32) -> IsPacked {
6898 if offset_of_tuple!((T1, T2, T3, T4), 0) == 0
6899 && offset_of_tuple!((T1, T2, T3, T4), 1) == std::mem::size_of::<T1>()
6900 && offset_of_tuple!((T1, T2, T3, T4), 2) == std::mem::size_of::<T1>() + std::mem::size_of::<T2>()
6901 && std::mem::size_of::<T1>()
6902 + std::mem::size_of::<T2>()
6903 + std::mem::size_of::<T3>()
6904 + std::mem::size_of::<T4>()
6905 == std::mem::size_of::<(T1, T2, T3, T4)>()
6906 {
6907 T1::repr_c_optimization_safe(version)
6908 & T2::repr_c_optimization_safe(version)
6909 & T3::repr_c_optimization_safe(version)
6910 & T4::repr_c_optimization_safe(version)
6911 } else {
6912 IsPacked::no()
6913 }
6914 }
6915}
6916
6917impl<T1: WithSchema, T2: WithSchema, T3: WithSchema> WithSchema for (T1, T2, T3) {
6918 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6919 Schema::new_tuple3::<T1, T2, T3>(version, context)
6920 }
6921}
6922impl<T1: Serialize, T2: Serialize, T3: Serialize> Serialize for (T1, T2, T3) {
6923 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6924 self.0.serialize(serializer)?;
6925 self.1.serialize(serializer)?;
6926 self.2.serialize(serializer)
6927 }
6928}
6929impl<T1: Deserialize, T2: Deserialize, T3: Deserialize> Deserialize for (T1, T2, T3) {
6930 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6931 Ok((
6932 T1::deserialize(deserializer)?,
6933 T2::deserialize(deserializer)?,
6934 T3::deserialize(deserializer)?,
6935 ))
6936 }
6937}
6938
6939impl<T1: WithSchema, T2: WithSchema> WithSchema for (T1, T2) {
6940 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6941 Schema::new_tuple2::<T1, T2>(version, context)
6942 }
6943}
6944impl<T1: Serialize, T2: Serialize> Serialize for (T1, T2) {
6945 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6946 self.0.serialize(serializer)?;
6947 self.1.serialize(serializer)
6948 }
6949}
6950impl<T1: Deserialize, T2: Deserialize> Deserialize for (T1, T2) {
6951 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6952 Ok((T1::deserialize(deserializer)?, T2::deserialize(deserializer)?))
6953 }
6954}
6955
6956impl<T1: WithSchema> WithSchema for (T1,) {
6957 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
6958 Schema::new_tuple1::<T1>(version, context)
6959 }
6960}
6961impl<T1: Serialize> Serialize for (T1,) {
6962 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
6963 self.0.serialize(serializer)
6964 }
6965}
6966impl<T1: Deserialize> Deserialize for (T1,) {
6967 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
6968 Ok((T1::deserialize(deserializer)?,))
6969 }
6970}
6971
6972#[cfg(feature = "nalgebra")]
6973impl<T: nalgebra::Scalar> Introspect for nalgebra::Point3<T> {
6974 fn introspect_value(&self) -> String {
6975 format!("{:?}", self)
6976 }
6977
6978 fn introspect_child<'a>(&'a self, _index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
6979 None
6980 }
6981}
6982#[cfg(feature = "nalgebra")]
6983impl<T: nalgebra::Scalar> Introspect for nalgebra::Vector3<T> {
6984 fn introspect_value(&self) -> String {
6985 format!("{:?}", self)
6986 }
6987
6988 fn introspect_child<'a>(&'a self, _index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
6989 None
6990 }
6991}
6992#[cfg(feature = "nalgebra")]
6993impl<T: nalgebra::Scalar> Introspect for nalgebra::Isometry3<T> {
6994 fn introspect_value(&self) -> String {
6995 format!("{:?}", self)
6996 }
6997
6998 fn introspect_child<'a>(&'a self, _index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
6999 None
7000 }
7001}
7002#[cfg(feature = "nalgebra")]
7003impl<T: Packed + nalgebra::Scalar + Default> Packed for nalgebra::Point3<T> {
7004 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
7005 let d = nalgebra::Point3::<T>::new(T::default(), T::default(), T::default());
7006 let p1 = &d.x as *const T;
7007 let p2 = &d.y as *const T;
7008 let p3 = &d.z as *const T;
7009
7010 if std::mem::size_of::<nalgebra::Point3<T>>() == 3 * std::mem::size_of::<T>()
7011 && p1.offset(1) == p2
7012 && p1.offset(2) == p3
7013 {
7014 IsPacked::yes()
7015 } else {
7016 IsPacked::no()
7017 }
7018 }
7019}
7020#[cfg(feature = "nalgebra")]
7021impl<T: WithSchema + nalgebra::Scalar> WithSchema for nalgebra::Point3<T> {
7022 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
7023 Schema::Array(SchemaArray {
7024 item_type: Box::new(T::schema(version, context)),
7025 count: 3,
7026 })
7027 }
7028}
7029#[cfg(feature = "nalgebra")]
7030impl<T: Serialize + Packed + WithSchema + nalgebra::Scalar> Serialize for nalgebra::Point3<T> {
7031 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7032 self.coords.x.serialize(serializer)?;
7033 self.coords.y.serialize(serializer)?;
7034 self.coords.z.serialize(serializer)?;
7035
7036 Ok(())
7037 }
7038}
7039#[cfg(feature = "nalgebra")]
7040impl<T: Deserialize + Packed + WithSchema + nalgebra::Scalar + nalgebra::SimdValue + nalgebra::RealField> Deserialize
7041 for nalgebra::Point3<T>
7042{
7043 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7044 Ok(nalgebra::Point3::new(
7045 <T as Deserialize>::deserialize(deserializer)?,
7046 <T as Deserialize>::deserialize(deserializer)?,
7047 <T as Deserialize>::deserialize(deserializer)?,
7048 ))
7049 }
7050}
7051
7052#[cfg(feature = "nalgebra")]
7053impl<T: Packed + nalgebra::Scalar + Default> Packed for nalgebra::Vector3<T> {
7054 unsafe fn repr_c_optimization_safe(_version: u32) -> IsPacked {
7055 let d = nalgebra::Vector3::<T>::new(T::default(), T::default(), T::default());
7056 let p1 = &d.x as *const T;
7057 let p2 = &d.y as *const T;
7058 let p3 = &d.z as *const T;
7059
7060 if std::mem::size_of::<nalgebra::Point3<T>>() == 3 * std::mem::size_of::<T>()
7061 && p1.offset(1) == p2
7062 && p1.offset(2) == p3
7063 {
7064 IsPacked::yes()
7065 } else {
7066 IsPacked::no()
7067 }
7068 }
7069}
7070#[cfg(feature = "nalgebra")]
7071impl<T: WithSchema + nalgebra::Scalar> WithSchema for nalgebra::Vector3<T> {
7072 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
7073 Schema::Array(SchemaArray {
7074 item_type: Box::new(T::schema(version, context)),
7075 count: 3,
7076 })
7077 }
7078}
7079#[cfg(feature = "nalgebra")]
7080impl<T: Serialize + Packed + WithSchema + nalgebra::Scalar> Serialize for nalgebra::Vector3<T> {
7081 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7082 self.x.serialize(serializer)?;
7083 self.y.serialize(serializer)?;
7084 self.z.serialize(serializer)?;
7085
7086 Ok(())
7087 }
7088}
7089#[cfg(feature = "nalgebra")]
7090impl<T: Deserialize + Packed + WithSchema + nalgebra::Scalar + nalgebra::SimdValue + nalgebra::RealField> Deserialize
7091 for nalgebra::Vector3<T>
7092{
7093 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7094 Ok(nalgebra::Vector3::new(
7095 <T as Deserialize>::deserialize(deserializer)?,
7096 <T as Deserialize>::deserialize(deserializer)?,
7097 <T as Deserialize>::deserialize(deserializer)?,
7098 ))
7099 }
7100}
7101
7102#[cfg(feature = "nalgebra")]
7103impl<T: Packed> Packed for nalgebra::Isometry3<T> {}
7104#[cfg(feature = "nalgebra")]
7105impl<T: WithSchema> WithSchema for nalgebra::Isometry3<T> {
7106 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
7107 Schema::Array(SchemaArray {
7108 item_type: Box::new(T::schema(version, context)),
7109 count: 7,
7110 })
7111 }
7112}
7113#[cfg(feature = "nalgebra")]
7114impl<T: Serialize + Packed + WithSchema + nalgebra::Scalar> Serialize for nalgebra::Isometry3<T> {
7115 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7116 self.translation.vector.x.serialize(serializer)?;
7117 self.translation.vector.y.serialize(serializer)?;
7118 self.translation.vector.z.serialize(serializer)?;
7119
7120 self.rotation.coords.w.serialize(serializer)?;
7121 self.rotation.coords.x.serialize(serializer)?;
7122 self.rotation.coords.y.serialize(serializer)?;
7123 self.rotation.coords.z.serialize(serializer)?;
7124
7125 Ok(())
7126 }
7127}
7128#[cfg(feature = "nalgebra")]
7129impl<T: Deserialize + Packed + WithSchema + nalgebra::Scalar + nalgebra::SimdValue + nalgebra::RealField> Deserialize
7130 for nalgebra::Isometry3<T>
7131{
7132 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7133 Ok(nalgebra::Isometry3::from_parts(
7134 nalgebra::Point3::new(
7135 <T as Deserialize>::deserialize(deserializer)?,
7136 <T as Deserialize>::deserialize(deserializer)?,
7137 <T as Deserialize>::deserialize(deserializer)?,
7138 )
7139 .into(),
7140 nalgebra::UnitQuaternion::new_unchecked(nalgebra::Quaternion::new(
7141 <T as Deserialize>::deserialize(deserializer)?,
7142 <T as Deserialize>::deserialize(deserializer)?,
7143 <T as Deserialize>::deserialize(deserializer)?,
7144 <T as Deserialize>::deserialize(deserializer)?,
7145 )),
7146 ))
7147 }
7148}
7149
7150#[cfg(feature = "arrayvec")]
7151impl<const C: usize> Packed for arrayvec::ArrayString<C> {}
7152
7153#[cfg(feature = "arrayvec")]
7154impl<const C: usize> WithSchema for arrayvec::ArrayString<C> {
7155 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7156 Schema::Primitive(SchemaPrimitive::schema_string(VecOrStringLayout::Unknown))
7157 }
7158}
7159#[cfg(feature = "arrayvec")]
7160impl<const C: usize> Serialize for arrayvec::ArrayString<C> {
7161 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7162 serializer.write_string(self.as_str())
7163 }
7164}
7165#[cfg(feature = "arrayvec")]
7166impl<const C: usize> Deserialize for arrayvec::ArrayString<C> {
7167 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7168 let l = deserializer.read_usize()?;
7169 if l > C {
7170 return Err(SavefileError::ArrayvecCapacityError {
7171 msg: format!("Deserialized data had length {}, but ArrayString capacity is {}", l, C),
7172 });
7173 }
7174 let mut tempbuf = [0u8; C];
7175 deserializer.read_bytes_to_buf(&mut tempbuf[0..l])?;
7176
7177 match std::str::from_utf8(&tempbuf[0..l]) {
7178 Ok(s) => Ok(arrayvec::ArrayString::try_from(s)?),
7179 Err(_err) => Err(SavefileError::InvalidUtf8 {
7180 msg: format!("ArrayString<{}> contained invalid UTF8", C),
7181 }),
7182 }
7183 }
7184}
7185#[cfg(feature = "arrayvec")]
7186impl<const C: usize> Introspect for arrayvec::ArrayString<C> {
7187 fn introspect_value(&self) -> String {
7188 self.to_string()
7189 }
7190
7191 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem>> {
7192 None
7193 }
7194}
7195
7196#[cfg(feature = "arrayvec")]
7197impl<V: WithSchema, const C: usize> WithSchema for arrayvec::ArrayVec<V, C> {
7198 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
7199 Schema::Vector(Box::new(V::schema(version, context)), VecOrStringLayout::Unknown)
7200 }
7201}
7202
7203#[cfg(feature = "arrayvec")]
7204impl<V: Introspect + 'static, const C: usize> Introspect for arrayvec::ArrayVec<V, C> {
7205 fn introspect_value(&self) -> String {
7206 return "arrayvec[]".to_string();
7207 }
7208
7209 fn introspect_child<'s>(&'s self, index: usize) -> Option<Box<dyn IntrospectItem<'s> + 's>> {
7210 if index >= self.len() {
7211 return None;
7212 }
7213 return Some(Box::new(IntrospectItemSimple {
7214 key: index.to_string(),
7215 val: &self[index],
7216 }));
7217 }
7218 fn introspect_len(&self) -> usize {
7219 self.len()
7220 }
7221}
7222
7223#[cfg(feature = "arrayvec")]
7224impl<V: Packed, const C: usize> Packed for arrayvec::ArrayVec<V, C> {
7225 unsafe fn repr_c_optimization_safe(version: u32) -> IsPacked {
7226 V::repr_c_optimization_safe(version)
7227 }
7228}
7229
7230#[cfg(feature = "arrayvec")]
7231impl<V: Serialize + Packed, const C: usize> Serialize for arrayvec::ArrayVec<V, C> {
7232 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7233 unsafe {
7234 if V::repr_c_optimization_safe(serializer.file_version).is_false() {
7235 regular_serialize_vec(self, serializer)
7236 } else {
7237 let l = self.len();
7238 serializer.write_usize(l)?;
7239 serializer.write_buf(std::slice::from_raw_parts(
7240 self.as_ptr() as *const u8,
7241 std::mem::size_of::<V>() * l,
7242 ))
7243 }
7244 }
7245 }
7246}
7247
7248#[cfg(feature = "arrayvec")]
7249impl<V: Deserialize + Packed, const C: usize> Deserialize for arrayvec::ArrayVec<V, C> {
7250 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<arrayvec::ArrayVec<V, C>, SavefileError> {
7251 let mut ret = arrayvec::ArrayVec::new();
7252 let l = deserializer.read_usize()?;
7253 if l > ret.capacity() {
7254 return Err(SavefileError::ArrayvecCapacityError {
7255 msg: format!("ArrayVec with capacity {} can't hold {} items", ret.capacity(), l),
7256 });
7257 }
7258 if unsafe { V::repr_c_optimization_safe(deserializer.file_version) }.is_false() {
7259 for _ in 0..l {
7260 ret.push(V::deserialize(deserializer)?);
7261 }
7262 } else {
7263 unsafe {
7264 let bytebuf = std::slice::from_raw_parts_mut(ret.as_mut_ptr() as *mut u8, std::mem::size_of::<V>() * l);
7265 deserializer.reader.read_exact(bytebuf)?; ret.set_len(l);
7267 }
7268 }
7269 Ok(ret)
7270 }
7271}
7272
7273use std::ops::{Deref, Range};
7274impl<T: WithSchema + 'static> WithSchema for Box<T> {
7275 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
7276 context.possible_recursion::<T>(|context| T::schema(version, context))
7277 }
7278}
7279impl<T> Packed for Box<T> {}
7280impl<T: Serialize + 'static> Serialize for Box<T> {
7281 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7282 self.deref().serialize(serializer)
7283 }
7284}
7285impl<T: Deserialize + 'static> Deserialize for Box<T> {
7286 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7287 Ok(Box::new(T::deserialize(deserializer)?))
7288 }
7289}
7290
7291use std::rc::Rc;
7292
7293impl<T> Packed for Rc<T> {}
7294impl<T: WithSchema + 'static> WithSchema for Rc<T> {
7295 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
7296 context.possible_recursion::<T>(|context| T::schema(version, context))
7297 }
7298}
7299impl<T: Serialize + 'static> Serialize for Rc<T> {
7300 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7301 self.deref().serialize(serializer)
7302 }
7303}
7304impl<T: Deserialize + 'static> Deserialize for Rc<T> {
7305 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7306 Ok(Rc::new(T::deserialize(deserializer)?))
7307 }
7308}
7309
7310impl<T> Packed for Arc<T> {}
7311impl<T: WithSchema + 'static> WithSchema for Arc<T> {
7312 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
7313 context.possible_recursion::<T>(|context| T::schema(version, context))
7314 }
7315}
7316impl<T: Serialize + 'static> Serialize for Arc<T> {
7317 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7318 self.deref().serialize(serializer)
7319 }
7320}
7321impl<T: Deserialize + 'static> Deserialize for Arc<T> {
7322 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7323 Ok(Arc::new(T::deserialize(deserializer)?))
7324 }
7325}
7326use byteorder::{ReadBytesExt, WriteBytesExt};
7327#[cfg(feature = "bzip2")]
7328use bzip2::Compression;
7329use memoffset::offset_of_tuple;
7330use std::any::Any;
7331use std::cell::Cell;
7332use std::cell::RefCell;
7333use std::collections::hash_map::Entry;
7334#[allow(unused_imports)]
7335use std::convert::{TryFrom, TryInto};
7336use std::fmt::{Debug, Display, Formatter};
7337use std::marker::PhantomData;
7338use std::path::{Path, PathBuf};
7339use std::ptr::NonNull;
7340use std::slice;
7341use std::sync::Arc;
7342use std::time::{Duration, SystemTime};
7343
7344impl<T> Packed for RefCell<T> {}
7345impl<T: WithSchema> WithSchema for RefCell<T> {
7346 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
7347 T::schema(version, context)
7348 }
7349}
7350impl<T: Serialize> Serialize for RefCell<T> {
7351 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7352 self.borrow().serialize(serializer)
7353 }
7354}
7355impl<T: Deserialize> Deserialize for RefCell<T> {
7356 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7357 Ok(RefCell::new(T::deserialize(deserializer)?))
7358 }
7359}
7360
7361impl<T: Packed> Packed for Cell<T> {
7362 unsafe fn repr_c_optimization_safe(version: u32) -> IsPacked {
7363 T::repr_c_optimization_safe(version)
7364 }
7365}
7366impl<T: WithSchema> WithSchema for Cell<T> {
7367 fn schema(version: u32, context: &mut WithSchemaContext) -> Schema {
7368 T::schema(version, context)
7369 }
7370}
7371impl<T: Serialize + Copy> Serialize for Cell<T> {
7372 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7373 let t: T = self.get();
7374 t.serialize(serializer)
7375 }
7376}
7377impl<T: Deserialize> Deserialize for Cell<T> {
7378 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7379 Ok(Cell::new(T::deserialize(deserializer)?))
7380 }
7381}
7382
7383impl WithSchema for () {
7384 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7385 Schema::ZeroSize
7386 }
7387}
7388impl Serialize for () {
7389 fn serialize(&self, _serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7390 Ok(())
7391 }
7392}
7393
7394impl Introspect for () {
7395 fn introspect_value(&self) -> String {
7396 "()".to_string()
7397 }
7398 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7399 None
7400 }
7401}
7402impl Deserialize for () {
7403 fn deserialize(_deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7404 Ok(())
7405 }
7406}
7407
7408impl<T: Introspect> Introspect for (T,) {
7409 fn introspect_value(&self) -> String {
7410 return "1-tuple".to_string();
7411 }
7412
7413 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7414 if index == 0 {
7415 return Some(introspect_item("0".to_string(), &self.0));
7416 }
7417 return None;
7418 }
7419}
7420
7421impl<T1: Introspect, T2: Introspect> Introspect for (T1, T2) {
7422 fn introspect_value(&self) -> String {
7423 return "2-tuple".to_string();
7424 }
7425
7426 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7427 if index == 0 {
7428 return Some(introspect_item("0".to_string(), &self.0));
7429 }
7430 if index == 1 {
7431 return Some(introspect_item("1".to_string(), &self.1));
7432 }
7433 return None;
7434 }
7435}
7436impl<T1: Introspect, T2: Introspect, T3: Introspect> Introspect for (T1, T2, T3) {
7437 fn introspect_value(&self) -> String {
7438 return "3-tuple".to_string();
7439 }
7440
7441 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7442 if index == 0 {
7443 return Some(introspect_item("0".to_string(), &self.0));
7444 }
7445 if index == 1 {
7446 return Some(introspect_item("1".to_string(), &self.1));
7447 }
7448 if index == 2 {
7449 return Some(introspect_item("2".to_string(), &self.2));
7450 }
7451 return None;
7452 }
7453}
7454impl<T1: Introspect, T2: Introspect, T3: Introspect, T4: Introspect> Introspect for (T1, T2, T3, T4) {
7455 fn introspect_value(&self) -> String {
7456 return "4-tuple".to_string();
7457 }
7458
7459 fn introspect_child(&self, index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7460 if index == 0 {
7461 return Some(introspect_item("0".to_string(), &self.0));
7462 }
7463 if index == 1 {
7464 return Some(introspect_item("1".to_string(), &self.1));
7465 }
7466 if index == 2 {
7467 return Some(introspect_item("2".to_string(), &self.2));
7468 }
7469 if index == 3 {
7470 return Some(introspect_item("3".to_string(), &self.3));
7471 }
7472 return None;
7473 }
7474}
7475
7476impl Introspect for AtomicBool {
7477 fn introspect_value(&self) -> String {
7478 self.load(Ordering::SeqCst).to_string()
7479 }
7480 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7481 None
7482 }
7483}
7484impl Introspect for AtomicU8 {
7485 fn introspect_value(&self) -> String {
7486 self.load(Ordering::SeqCst).to_string()
7487 }
7488 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7489 None
7490 }
7491}
7492impl Introspect for AtomicI8 {
7493 fn introspect_value(&self) -> String {
7494 self.load(Ordering::SeqCst).to_string()
7495 }
7496 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7497 None
7498 }
7499}
7500impl Introspect for AtomicU16 {
7501 fn introspect_value(&self) -> String {
7502 self.load(Ordering::SeqCst).to_string()
7503 }
7504 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7505 None
7506 }
7507}
7508impl Introspect for AtomicI16 {
7509 fn introspect_value(&self) -> String {
7510 self.load(Ordering::SeqCst).to_string()
7511 }
7512 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7513 None
7514 }
7515}
7516impl Introspect for AtomicU32 {
7517 fn introspect_value(&self) -> String {
7518 self.load(Ordering::SeqCst).to_string()
7519 }
7520 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7521 None
7522 }
7523}
7524impl Introspect for AtomicI32 {
7525 fn introspect_value(&self) -> String {
7526 self.load(Ordering::SeqCst).to_string()
7527 }
7528 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7529 None
7530 }
7531}
7532impl Introspect for AtomicU64 {
7533 fn introspect_value(&self) -> String {
7534 self.load(Ordering::SeqCst).to_string()
7535 }
7536 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7537 None
7538 }
7539}
7540impl Introspect for AtomicI64 {
7541 fn introspect_value(&self) -> String {
7542 self.load(Ordering::SeqCst).to_string()
7543 }
7544 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7545 None
7546 }
7547}
7548impl Introspect for AtomicUsize {
7549 fn introspect_value(&self) -> String {
7550 self.load(Ordering::SeqCst).to_string()
7551 }
7552 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7553 None
7554 }
7555}
7556impl Introspect for AtomicIsize {
7557 fn introspect_value(&self) -> String {
7558 self.load(Ordering::SeqCst).to_string()
7559 }
7560 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7561 None
7562 }
7563}
7564
7565impl WithSchema for AtomicBool {
7566 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7567 Schema::Primitive(SchemaPrimitive::schema_bool)
7568 }
7569}
7570impl WithSchema for AtomicU8 {
7571 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7572 Schema::Primitive(SchemaPrimitive::schema_u8)
7573 }
7574}
7575impl WithSchema for AtomicI8 {
7576 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7577 Schema::Primitive(SchemaPrimitive::schema_i8)
7578 }
7579}
7580impl WithSchema for AtomicU16 {
7581 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7582 Schema::Primitive(SchemaPrimitive::schema_u16)
7583 }
7584}
7585impl WithSchema for AtomicI16 {
7586 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7587 Schema::Primitive(SchemaPrimitive::schema_i16)
7588 }
7589}
7590impl WithSchema for AtomicU32 {
7591 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7592 Schema::Primitive(SchemaPrimitive::schema_u32)
7593 }
7594}
7595impl WithSchema for AtomicI32 {
7596 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7597 Schema::Primitive(SchemaPrimitive::schema_i32)
7598 }
7599}
7600impl WithSchema for AtomicU64 {
7601 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7602 Schema::Primitive(SchemaPrimitive::schema_u64)
7603 }
7604}
7605impl WithSchema for AtomicI64 {
7606 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7607 Schema::Primitive(SchemaPrimitive::schema_i64)
7608 }
7609}
7610impl WithSchema for AtomicUsize {
7611 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7612 match std::mem::size_of::<usize>() {
7613 4 => Schema::Primitive(SchemaPrimitive::schema_u32),
7614 8 => Schema::Primitive(SchemaPrimitive::schema_u64),
7615 _ => panic!("Size of usize was neither 32 bit nor 64 bit. This is not supported by the savefile crate."),
7616 }
7617 }
7618}
7619impl WithSchema for AtomicIsize {
7620 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7621 match std::mem::size_of::<isize>() {
7622 4 => Schema::Primitive(SchemaPrimitive::schema_i32),
7623 8 => Schema::Primitive(SchemaPrimitive::schema_i64),
7624 _ => panic!("Size of isize was neither 32 bit nor 64 bit. This is not supported by the savefile crate."),
7625 }
7626 }
7627}
7628
7629impl WithSchema for bool {
7630 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7631 Schema::Primitive(SchemaPrimitive::schema_bool)
7632 }
7633}
7634impl WithSchema for u8 {
7635 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7636 Schema::Primitive(SchemaPrimitive::schema_u8)
7637 }
7638}
7639impl WithSchema for i8 {
7640 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7641 Schema::Primitive(SchemaPrimitive::schema_i8)
7642 }
7643}
7644impl WithSchema for u16 {
7645 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7646 Schema::Primitive(SchemaPrimitive::schema_u16)
7647 }
7648}
7649impl WithSchema for i16 {
7650 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7651 Schema::Primitive(SchemaPrimitive::schema_i16)
7652 }
7653}
7654impl WithSchema for u32 {
7655 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7656 Schema::Primitive(SchemaPrimitive::schema_u32)
7657 }
7658}
7659impl WithSchema for i32 {
7660 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7661 Schema::Primitive(SchemaPrimitive::schema_i32)
7662 }
7663}
7664impl WithSchema for u64 {
7665 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7666 Schema::Primitive(SchemaPrimitive::schema_u64)
7667 }
7668}
7669impl WithSchema for u128 {
7670 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7671 Schema::Primitive(SchemaPrimitive::schema_u128)
7672 }
7673}
7674impl WithSchema for i128 {
7675 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7676 Schema::Primitive(SchemaPrimitive::schema_i128)
7677 }
7678}
7679impl WithSchema for i64 {
7680 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7681 Schema::Primitive(SchemaPrimitive::schema_i64)
7682 }
7683}
7684impl WithSchema for char {
7685 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7686 Schema::Primitive(SchemaPrimitive::schema_char)
7687 }
7688}
7689impl WithSchema for usize {
7690 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7691 match std::mem::size_of::<usize>() {
7692 4 => Schema::Primitive(SchemaPrimitive::schema_u32),
7693 8 => Schema::Primitive(SchemaPrimitive::schema_u64),
7694 _ => panic!("Size of usize was neither 32 bit nor 64 bit. This is not supported by the savefile crate."),
7695 }
7696 }
7697}
7698impl WithSchema for isize {
7699 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7700 match std::mem::size_of::<isize>() {
7701 4 => Schema::Primitive(SchemaPrimitive::schema_i32),
7702 8 => Schema::Primitive(SchemaPrimitive::schema_i64),
7703 _ => panic!("Size of isize was neither 32 bit nor 64 bit. This is not supported by the savefile crate."),
7704 }
7705 }
7706}
7707impl WithSchema for f32 {
7708 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7709 Schema::Primitive(SchemaPrimitive::schema_f32)
7710 }
7711}
7712impl WithSchema for f64 {
7713 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
7714 Schema::Primitive(SchemaPrimitive::schema_f64)
7715 }
7716}
7717
7718impl Introspect for bool {
7719 fn introspect_value(&self) -> String {
7720 self.to_string()
7721 }
7722 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7723 None
7724 }
7725}
7726impl Introspect for u8 {
7727 fn introspect_value(&self) -> String {
7728 self.to_string()
7729 }
7730 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7731 None
7732 }
7733}
7734impl Introspect for u16 {
7735 fn introspect_value(&self) -> String {
7736 self.to_string()
7737 }
7738 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7739 None
7740 }
7741}
7742impl Introspect for u32 {
7743 fn introspect_value(&self) -> String {
7744 self.to_string()
7745 }
7746 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7747 None
7748 }
7749}
7750impl Introspect for u64 {
7751 fn introspect_value(&self) -> String {
7752 self.to_string()
7753 }
7754 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7755 None
7756 }
7757}
7758impl Introspect for u128 {
7759 fn introspect_value(&self) -> String {
7760 self.to_string()
7761 }
7762 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7763 None
7764 }
7765}
7766impl Introspect for i8 {
7767 fn introspect_value(&self) -> String {
7768 self.to_string()
7769 }
7770 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7771 None
7772 }
7773}
7774impl Introspect for i16 {
7775 fn introspect_value(&self) -> String {
7776 self.to_string()
7777 }
7778 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7779 None
7780 }
7781}
7782impl Introspect for i32 {
7783 fn introspect_value(&self) -> String {
7784 self.to_string()
7785 }
7786 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7787 None
7788 }
7789}
7790impl Introspect for i64 {
7791 fn introspect_value(&self) -> String {
7792 self.to_string()
7793 }
7794 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7795 None
7796 }
7797}
7798impl Introspect for char {
7799 fn introspect_value(&self) -> String {
7800 self.to_string()
7801 }
7802 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7803 None
7804 }
7805}
7806impl Introspect for i128 {
7807 fn introspect_value(&self) -> String {
7808 self.to_string()
7809 }
7810 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7811 None
7812 }
7813}
7814impl Introspect for f32 {
7815 fn introspect_value(&self) -> String {
7816 self.to_string()
7817 }
7818 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7819 None
7820 }
7821}
7822impl Introspect for f64 {
7823 fn introspect_value(&self) -> String {
7824 self.to_string()
7825 }
7826 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7827 None
7828 }
7829}
7830impl Introspect for usize {
7831 fn introspect_value(&self) -> String {
7832 self.to_string()
7833 }
7834 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7835 None
7836 }
7837}
7838impl Introspect for isize {
7839 fn introspect_value(&self) -> String {
7840 self.to_string()
7841 }
7842 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
7843 None
7844 }
7845}
7846
7847impl Serialize for u8 {
7848 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7849 serializer.write_u8(*self)
7850 }
7851}
7852impl Deserialize for u8 {
7853 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7854 deserializer.read_u8()
7855 }
7856}
7857impl Serialize for bool {
7858 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7859 serializer.write_bool(*self)
7860 }
7861}
7862impl Deserialize for bool {
7863 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7864 deserializer.read_bool()
7865 }
7866}
7867
7868impl Serialize for f32 {
7869 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7870 serializer.write_f32(*self)
7871 }
7872}
7873impl Deserialize for f32 {
7874 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7875 deserializer.read_f32()
7876 }
7877}
7878
7879impl Serialize for f64 {
7880 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7881 serializer.write_f64(*self)
7882 }
7883}
7884impl Deserialize for f64 {
7885 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7886 deserializer.read_f64()
7887 }
7888}
7889
7890impl Serialize for i8 {
7891 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7892 serializer.write_i8(*self)
7893 }
7894}
7895impl Deserialize for i8 {
7896 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7897 deserializer.read_i8()
7898 }
7899}
7900impl Serialize for u16 {
7901 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7902 serializer.write_u16(*self)
7903 }
7904}
7905impl Deserialize for u16 {
7906 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7907 deserializer.read_u16()
7908 }
7909}
7910impl Serialize for i16 {
7911 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7912 serializer.write_i16(*self)
7913 }
7914}
7915impl Deserialize for i16 {
7916 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7917 deserializer.read_i16()
7918 }
7919}
7920
7921impl Serialize for u32 {
7922 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7923 serializer.write_u32(*self)
7924 }
7925}
7926impl Deserialize for u32 {
7927 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7928 deserializer.read_u32()
7929 }
7930}
7931impl Serialize for i32 {
7932 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7933 serializer.write_i32(*self)
7934 }
7935}
7936impl Deserialize for i32 {
7937 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7938 deserializer.read_i32()
7939 }
7940}
7941
7942impl Serialize for u64 {
7943 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7944 serializer.write_u64(*self)
7945 }
7946}
7947impl Deserialize for u64 {
7948 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7949 deserializer.read_u64()
7950 }
7951}
7952impl Serialize for i64 {
7953 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7954 serializer.write_i64(*self)
7955 }
7956}
7957impl Serialize for char {
7958 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7959 serializer.write_u32((*self).into())
7960 }
7961}
7962impl Deserialize for i64 {
7963 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7964 deserializer.read_i64()
7965 }
7966}
7967impl Deserialize for char {
7968 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7969 let uc = deserializer.read_u32()?;
7970 match uc.try_into() {
7971 Ok(x) => Ok(x),
7972 Err(_) => Err(SavefileError::InvalidChar),
7973 }
7974 }
7975}
7976impl Serialize for u128 {
7977 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7978 serializer.write_u128(*self)
7979 }
7980}
7981impl Deserialize for u128 {
7982 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7983 deserializer.read_u128()
7984 }
7985}
7986impl Serialize for i128 {
7987 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7988 serializer.write_i128(*self)
7989 }
7990}
7991impl Deserialize for i128 {
7992 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
7993 deserializer.read_i128()
7994 }
7995}
7996
7997impl Serialize for usize {
7998 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
7999 serializer.write_usize(*self)
8000 }
8001}
8002impl Deserialize for usize {
8003 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8004 deserializer.read_usize()
8005 }
8006}
8007impl Serialize for isize {
8008 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8009 serializer.write_isize(*self)
8010 }
8011}
8012impl Deserialize for isize {
8013 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8014 deserializer.read_isize()
8015 }
8016}
8017
8018impl Serialize for AtomicBool {
8019 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8020 serializer.write_bool(self.load(Ordering::SeqCst))
8021 }
8022}
8023impl Deserialize for AtomicBool {
8024 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8025 Ok(AtomicBool::new(deserializer.read_bool()?))
8026 }
8027}
8028
8029impl Serialize for AtomicU8 {
8030 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8031 serializer.write_u8(self.load(Ordering::SeqCst))
8032 }
8033}
8034impl Deserialize for AtomicU8 {
8035 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8036 Ok(AtomicU8::new(deserializer.read_u8()?))
8037 }
8038}
8039impl Serialize for AtomicI8 {
8040 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8041 serializer.write_i8(self.load(Ordering::SeqCst))
8042 }
8043}
8044impl Deserialize for AtomicI8 {
8045 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8046 Ok(AtomicI8::new(deserializer.read_i8()?))
8047 }
8048}
8049impl Serialize for AtomicU16 {
8050 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8051 serializer.write_u16(self.load(Ordering::SeqCst))
8052 }
8053}
8054impl Deserialize for AtomicU16 {
8055 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8056 Ok(AtomicU16::new(deserializer.read_u16()?))
8057 }
8058}
8059impl Serialize for AtomicI16 {
8060 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8061 serializer.write_i16(self.load(Ordering::SeqCst))
8062 }
8063}
8064impl Deserialize for AtomicI16 {
8065 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8066 Ok(AtomicI16::new(deserializer.read_i16()?))
8067 }
8068}
8069
8070impl Serialize for AtomicU32 {
8071 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8072 serializer.write_u32(self.load(Ordering::SeqCst))
8073 }
8074}
8075impl Deserialize for AtomicU32 {
8076 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8077 Ok(AtomicU32::new(deserializer.read_u32()?))
8078 }
8079}
8080impl Serialize for AtomicI32 {
8081 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8082 serializer.write_i32(self.load(Ordering::SeqCst))
8083 }
8084}
8085impl Deserialize for AtomicI32 {
8086 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8087 Ok(AtomicI32::new(deserializer.read_i32()?))
8088 }
8089}
8090
8091impl Serialize for AtomicU64 {
8092 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8093 serializer.write_u64(self.load(Ordering::SeqCst))
8094 }
8095}
8096impl Deserialize for AtomicU64 {
8097 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8098 Ok(AtomicU64::new(deserializer.read_u64()?))
8099 }
8100}
8101impl Serialize for AtomicI64 {
8102 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8103 serializer.write_i64(self.load(Ordering::SeqCst))
8104 }
8105}
8106impl Deserialize for AtomicI64 {
8107 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8108 Ok(AtomicI64::new(deserializer.read_i64()?))
8109 }
8110}
8111
8112impl Serialize for AtomicUsize {
8113 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8114 serializer.write_usize(self.load(Ordering::SeqCst))
8115 }
8116}
8117impl Deserialize for AtomicUsize {
8118 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8119 Ok(AtomicUsize::new(deserializer.read_usize()?))
8120 }
8121}
8122impl Serialize for AtomicIsize {
8123 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8124 serializer.write_isize(self.load(Ordering::SeqCst))
8125 }
8126}
8127impl Deserialize for AtomicIsize {
8128 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8129 Ok(AtomicIsize::new(deserializer.read_isize()?))
8130 }
8131}
8132
8133impl Packed for AtomicBool {}
8134impl Packed for AtomicI8 {}
8135impl Packed for AtomicU8 {}
8136impl Packed for AtomicI16 {}
8137impl Packed for AtomicU16 {}
8138impl Packed for AtomicI32 {}
8139impl Packed for AtomicU32 {}
8140impl Packed for AtomicI64 {}
8141impl Packed for AtomicU64 {}
8142impl Packed for AtomicIsize {}
8143impl Packed for AtomicUsize {}
8144
8145#[derive(Clone, Copy, Eq, PartialEq, Default, Debug)]
8151pub struct Canary1 {}
8152impl Canary1 {
8153 pub fn new() -> Canary1 {
8155 Canary1 {}
8156 }
8157}
8158impl Introspect for Canary1 {
8159 fn introspect_value(&self) -> String {
8160 "Canary1".to_string()
8161 }
8162
8163 fn introspect_child(&self, _index: usize) -> Option<Box<dyn IntrospectItem + '_>> {
8164 None
8165 }
8166}
8167
8168impl Deserialize for Canary1 {
8169 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8170 let magic = deserializer.read_u32()?;
8171 if magic != 0x47566843 {
8172 return Err(SavefileError::GeneralError {
8173 msg: format!(
8174 "Encountered bad magic value when deserializing Canary1. Expected {} but got {}",
8175 0x47566843, magic
8176 ),
8177 });
8178 }
8179 Ok(Canary1 {})
8180 }
8181}
8182
8183impl Serialize for Canary1 {
8184 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8185 serializer.write_u32(0x47566843)
8186 }
8187}
8188impl Packed for Canary1 {}
8189impl WithSchema for Canary1 {
8190 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
8191 Schema::Primitive(SchemaPrimitive::schema_canary1)
8192 }
8193}
8194
8195impl WithSchema for Duration {
8196 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
8197 Schema::Struct(SchemaStruct {
8198 dbg_name: "Duration".to_string(),
8199 size: None,
8200 alignment: None,
8201 fields: vec![Field {
8202 name: "Duration".to_string(),
8203 value: Box::new(Schema::Primitive(SchemaPrimitive::schema_u128)),
8204 offset: None,
8205 }],
8206 })
8207 }
8208}
8209impl Packed for Duration {}
8210impl Serialize for Duration {
8211 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8212 serializer.write_u128(self.as_nanos())
8213 }
8214}
8215impl Deserialize for Duration {
8216 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8217 let temp = deserializer.read_u128()?;
8218 Ok(Duration::from_secs((temp / 1_000_000_000) as u64) + Duration::from_nanos((temp % 1_000_000_000) as u64))
8219 }
8220}
8221
8222impl Introspect for Duration {
8223 fn introspect_value(&self) -> String {
8224 format!("{:?}", self)
8225 }
8226
8227 fn introspect_child<'a>(&'a self, _index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
8228 None
8229 }
8230
8231 fn introspect_len(&self) -> usize {
8232 0
8233 }
8234}
8235impl Introspect for SystemTime {
8236 fn introspect_value(&self) -> String {
8237 format!("{:?}", self)
8238 }
8239
8240 fn introspect_child<'a>(&'a self, _index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
8241 None
8242 }
8243
8244 fn introspect_len(&self) -> usize {
8245 0
8246 }
8247}
8248impl WithSchema for SystemTime {
8249 fn schema(_version: u32, _context: &mut WithSchemaContext) -> Schema {
8250 Schema::Struct(SchemaStruct {
8251 dbg_name: "SystemTime".to_string(),
8252 size: None,
8253 alignment: None,
8254 fields: vec![Field {
8255 name: "SystemTimeDuration".to_string(),
8256 value: Box::new(Schema::Primitive(SchemaPrimitive::schema_u128)),
8257 offset: None,
8258 }],
8259 })
8260 }
8261}
8262impl Packed for SystemTime {}
8263impl Serialize for SystemTime {
8264 fn serialize(&self, serializer: &mut Serializer<impl Write>) -> Result<(), SavefileError> {
8265 match self.duration_since(SystemTime::UNIX_EPOCH) {
8266 Ok(nanos) => {
8267 let temp = nanos.as_nanos();
8268 if temp >= 1u128 << 120 {
8269 return Err(SavefileError::GeneralError {
8270 msg: "Savefile cannot handle dates where the year is larger than ca 10^19 years.".to_string(),
8271 });
8272 }
8273 serializer.write_u128(temp)?;
8274 }
8275 Err(err) => {
8276 let mut temp = err.duration().as_nanos();
8278 if temp >= 1u128 << 120 {
8279 return Err(SavefileError::GeneralError {
8280 msg: "Savefile cannot handle dates much earlier than the creation of the universe.".to_string(),
8281 });
8282 }
8283 temp |= 1u128 << 127;
8284 serializer.write_u128(temp)?;
8285 }
8286 }
8287 Ok(())
8288 }
8289}
8290
8291impl Introspect for std::time::Instant {
8292 fn introspect_value(&self) -> String {
8293 format!("{:?}", self)
8294 }
8295 fn introspect_child<'a>(&'a self, _index: usize) -> Option<Box<dyn IntrospectItem<'a> + 'a>> {
8296 None
8297 }
8298}
8299
8300fn u128_duration_nanos(nanos: u128) -> Duration {
8301 if nanos > u64::MAX as u128 {
8302 Duration::from_nanos((nanos % 1_000_000_000) as u64) + Duration::from_secs((nanos / 1_000_000_000) as u64)
8303 } else {
8304 Duration::from_nanos(nanos as u64)
8305 }
8306}
8307impl Deserialize for SystemTime {
8308 fn deserialize(deserializer: &mut Deserializer<impl Read>) -> Result<Self, SavefileError> {
8309 let mut temp = deserializer.read_u128()?;
8310 if temp >= (1u128 << 127) {
8311 temp &= (1u128 << 127) - 1; return Ok(SystemTime::UNIX_EPOCH - u128_duration_nanos(temp));
8313 } else {
8314 return Ok(SystemTime::UNIX_EPOCH + u128_duration_nanos(temp));
8315 }
8316 }
8317}
8318
8319#[derive(Clone, Debug)]
8320struct PathElement {
8321 key: String,
8322 key_disambiguator: usize,
8323 max_children: usize,
8324}
8325
8326#[derive(Clone, Debug)]
8329pub struct Introspector {
8330 path: Vec<PathElement>,
8331 child_load_count: usize,
8332}
8333
8334#[derive(Debug, PartialEq, Eq, Clone)]
8336pub enum IntrospectorNavCommand {
8337 ExpandElement(IntrospectedElementKey),
8340 SelectNth {
8343 select_depth: usize,
8345 select_index: usize,
8347 },
8348 Nothing,
8350 Up,
8352}
8353
8354#[derive(PartialEq, Eq, Clone)]
8357pub struct IntrospectedElementKey {
8358 pub depth: usize,
8360 pub key: String,
8362 pub key_disambiguator: usize,
8365}
8366impl Default for IntrospectedElementKey {
8367 fn default() -> Self {
8368 IntrospectedElementKey {
8369 depth: 0,
8370 key: "".to_string(),
8371 key_disambiguator: 0,
8372 }
8373 }
8374}
8375
8376#[derive(PartialEq, Eq, Clone)]
8378pub struct IntrospectedElement {
8379 pub key: IntrospectedElementKey,
8381 pub value: String,
8383 pub has_children: bool,
8385 pub selected: bool,
8387}
8388
8389impl Debug for IntrospectedElementKey {
8390 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
8391 write!(
8392 f,
8393 "Key({} (at depth {}, key disambig {}))",
8394 self.key, self.depth, self.key_disambiguator
8395 )
8396 }
8397}
8398
8399impl Debug for IntrospectedElement {
8400 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
8401 write!(
8402 f,
8403 "KeyVal({} = {} (at depth {}, key disambig {}))",
8404 self.key.key, self.value, self.key.depth, self.key.key_disambiguator
8405 )
8406 }
8407}
8408
8409impl Display for IntrospectedElement {
8410 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
8411 write!(f, "{} = {}", self.key.key, self.value)
8412 }
8413}
8414
8415#[derive(Debug, PartialEq, Eq, Clone, Copy)]
8417pub enum IntrospectionError {
8418 BadDepth,
8422 UnknownKey,
8424 NoChildren,
8426 IndexOutOfRange,
8428 AlreadyAtTop,
8430}
8431
8432#[derive(Debug, Clone)]
8434pub struct IntrospectionFrame {
8435 pub selected: Option<usize>,
8437 pub keyvals: Vec<IntrospectedElement>,
8439 pub limit_reached: bool,
8442}
8443#[derive(Debug, Clone)]
8446pub struct IntrospectionResult {
8447 pub frames: Vec<IntrospectionFrame>,
8449 cached_total_len: usize,
8450}
8451
8452impl Display for IntrospectionResult {
8453 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
8454 self.format_result_row(f)
8455 }
8456}
8457
8458impl IntrospectionResult {
8459 pub fn total_index(&self, index: usize) -> Option<IntrospectedElement> {
8463 let mut cur = 0;
8464 self.total_index_impl(index, 0, &mut cur)
8465 }
8466 fn total_index_impl(&self, index: usize, depth: usize, cur: &mut usize) -> Option<IntrospectedElement> {
8467 if depth >= self.frames.len() {
8468 return None;
8469 }
8470 let frame = &self.frames[depth];
8471 {
8472 let mut offset = 0;
8473 if let Some(selection) = frame.selected {
8474 if index <= *cur + selection {
8475 return Some(frame.keyvals[index - *cur].clone());
8476 }
8477 *cur += selection + 1;
8478 if let Some(result) = self.total_index_impl(index, depth + 1, cur) {
8479 return Some(result);
8480 }
8481 offset = selection + 1;
8482 }
8483 if (index - *cur) + offset < frame.keyvals.len() {
8484 return Some(frame.keyvals[(index - *cur) + offset].clone());
8485 }
8486 *cur += frame.keyvals.len() - offset;
8487 }
8488 return None;
8489 }
8490
8491 pub fn total_len(&self) -> usize {
8495 self.cached_total_len
8496 }
8497
8498 fn format_result_row(self: &IntrospectionResult, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
8499 if self.frames.len() == 0 {
8500 writeln!(f, "Introspectionresult:\n*empty*")?;
8501 return Ok(());
8502 }
8503 let mut idx = 0;
8504 let mut depth = Vec::new();
8505
8506 writeln!(f, "Introspectionresult:")?;
8507
8508 'outer: loop {
8509 let cur_row = &self.frames[depth.len()];
8510 if idx >= cur_row.keyvals.len() {
8511 if let Some(new_idx) = depth.pop() {
8512 idx = new_idx;
8513 continue;
8514 } else {
8515 break;
8516 }
8517 }
8518 while idx < cur_row.keyvals.len() {
8519 let item = &cur_row.keyvals[idx];
8520 let is_selected = Some(idx) == cur_row.selected;
8521 let pad = if is_selected {
8522 "*"
8523 } else if item.has_children {
8524 ">"
8525 } else {
8526 " "
8527 };
8528 writeln!(f, "{:>indent$}{}", pad, item, indent = 1 + 2 * depth.len())?;
8529 idx += 1;
8530 if is_selected && depth.len() + 1 < self.frames.len() {
8531 depth.push(idx);
8532 idx = 0;
8533 continue 'outer;
8534 }
8535 }
8536 }
8537 Ok(())
8538 }
8539}
8540impl Display for IntrospectedElementKey {
8541 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), std::fmt::Error> {
8542 write!(f, "{}", self.key)
8543 }
8544}
8545impl Introspector {
8546 pub fn new() -> Introspector {
8548 Introspector {
8549 path: vec![],
8550 child_load_count: usize::MAX,
8551 }
8552 }
8553 pub fn new_with(child_load_count: usize) -> Introspector {
8557 Introspector {
8558 path: vec![],
8559 child_load_count,
8560 }
8561 }
8562
8563 pub fn num_frames(&self) -> usize {
8565 self.path.len()
8566 }
8567
8568 fn dive(
8569 &mut self,
8570 depth: usize,
8571 object: &dyn Introspect,
8572 navigation_command: IntrospectorNavCommand,
8573 ) -> Result<Vec<IntrospectionFrame>, IntrospectionError> {
8574 let mut result_vec = Vec::new();
8575 let mut navigation_command = Some(navigation_command);
8576 let mut cur_path = self.path.get(depth).cloned();
8577 let mut index = 0;
8578 let mut row = IntrospectionFrame {
8579 selected: None,
8580 keyvals: vec![],
8581 limit_reached: false,
8582 };
8583 let mut key_disambig_map = HashMap::new();
8584
8585 let mut do_select_nth = None;
8586
8587 let mut err_if_key_not_found = false;
8588 if let Some(navigation_command) = navigation_command.as_ref() {
8589 match navigation_command {
8590 IntrospectorNavCommand::ExpandElement(elem) => {
8591 if elem.depth > self.path.len() {
8592 return Err(IntrospectionError::BadDepth);
8593 }
8594 if depth == elem.depth {
8595 self.path.drain(depth..);
8596 self.path.push(PathElement {
8597 key: elem.key.clone(),
8598 key_disambiguator: elem.key_disambiguator,
8599 max_children: self.child_load_count,
8600 });
8601 cur_path = self.path.get(depth).cloned();
8602 err_if_key_not_found = true;
8603 }
8604 }
8605 IntrospectorNavCommand::SelectNth {
8606 select_depth,
8607 select_index,
8608 } => {
8609 if depth == *select_depth {
8610 do_select_nth = Some(*select_index);
8611 }
8612 }
8613 IntrospectorNavCommand::Nothing => {}
8614 IntrospectorNavCommand::Up => {}
8615 }
8616 }
8617
8618 loop {
8619 if let Some(child_item) = object.introspect_child(index) {
8620 let key: String = child_item.key().into();
8621
8622 let disambig_counter: &mut usize = key_disambig_map.entry(key.clone()).or_insert(0usize);
8623 let has_children = child_item.val().introspect_child(0).is_some();
8624 row.keyvals.push(IntrospectedElement {
8625 key: IntrospectedElementKey {
8626 depth,
8627 key: key.clone(),
8628 key_disambiguator: *disambig_counter,
8629 },
8630 value: child_item.val().introspect_value(),
8631 has_children,
8632 selected: false,
8633 });
8634
8635 if Some(index) == do_select_nth {
8636 self.path.push(PathElement {
8637 key: key.clone(),
8638 key_disambiguator: *disambig_counter,
8639 max_children: self.child_load_count,
8640 });
8641 do_select_nth = None;
8642 cur_path = self.path.last().cloned();
8643 }
8644
8645 if let Some(cur_path_obj) = &cur_path {
8646 if row.selected.is_none()
8647 && cur_path_obj.key == key
8648 && cur_path_obj.key_disambiguator == *disambig_counter
8649 {
8650 row.selected = Some(index);
8651 row.keyvals.last_mut().unwrap().selected = true;
8652 if has_children {
8653 let mut subresult =
8654 self.dive(depth + 1, child_item.val(), navigation_command.take().unwrap())?;
8655 debug_assert_eq!(result_vec.len(), 0);
8656 std::mem::swap(&mut result_vec, &mut subresult);
8657 }
8658 }
8659 }
8660
8661 *disambig_counter += 1;
8662 } else {
8663 break;
8664 }
8665
8666 index += 1;
8667 if index
8668 >= cur_path
8669 .as_ref()
8670 .map(|x| x.max_children)
8671 .unwrap_or(self.child_load_count)
8672 {
8673 row.limit_reached = true;
8674 break;
8675 }
8676 }
8677 if do_select_nth.is_some() {
8678 if index == 0 {
8679 return Err(IntrospectionError::NoChildren);
8680 }
8681 return Err(IntrospectionError::IndexOutOfRange);
8682 }
8683 if err_if_key_not_found && row.selected.is_none() {
8684 self.path.pop().unwrap();
8685 return Err(IntrospectionError::UnknownKey);
8686 }
8687 result_vec.insert(0, row);
8688 Ok(result_vec)
8689 }
8690
8691 pub fn do_introspect(
8694 &mut self,
8695 object: &dyn Introspect,
8696 navigation_command: IntrospectorNavCommand,
8697 ) -> Result<IntrospectionResult, IntrospectionError> {
8698 match &navigation_command {
8699 IntrospectorNavCommand::ExpandElement(_) => {}
8700 IntrospectorNavCommand::SelectNth { .. } => {}
8701 IntrospectorNavCommand::Nothing => {}
8702 IntrospectorNavCommand::Up => {
8703 if self.path.len() == 0 {
8704 return Err(IntrospectionError::AlreadyAtTop);
8705 }
8706 self.path.pop();
8707 }
8708 }
8709 let frames = self.dive(0, object, navigation_command)?;
8710
8711 let mut total = 0;
8712 for frame in &frames {
8713 total += frame.keyvals.len();
8714 }
8715 let accum = IntrospectionResult {
8716 frames,
8717 cached_total_len: total,
8718 };
8719 Ok(accum)
8720 }
8721}