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