Skip to content

Commit

Permalink
Make serialization support optional.
Browse files Browse the repository at this point in the history
This will improve compilation time for anyone using `all-is-cubes` as a
library (which is a use case I want to support, perhaps foolishly) in an
application where serialization is irrelevant.

It is also a small step towards hopefully being able to support `no_std`
compilation of `all-is-cubes`; if this works at all then we will also
want serialization, but that will require replacing `flate2` so it can
be a followup project.
  • Loading branch information
kpreid committed Sep 4, 2023
1 parent 46680ce commit 5b538b8
Show file tree
Hide file tree
Showing 22 changed files with 94 additions and 30 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ macro_rules_attribute = "0.2.0"
mutants = "0.0.3"
num-traits = "0.2.15"
once_cell = "1.17.1"
ordered-float = { version = "3.0.0", default-features = false, features = ["serde"] }
ordered-float = { version = "3.0.0", default-features = false }
pretty_assertions = "1.2.0"
rand = { version = "0.8.2", default-features = false }
rand_xoshiro = "0.6.0"
Expand Down
2 changes: 1 addition & 1 deletion all-is-cubes-desktop/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ doc = false # Do not overwrite library crate's documentation
bench = false

[dependencies]
all-is-cubes = { path = "../all-is-cubes", version = "0.6.0", features = ["threads"] }
all-is-cubes = { path = "../all-is-cubes", version = "0.6.0", features = ["save", "threads"] }
all-is-cubes-content = { path = "../all-is-cubes-content", version = "0.6.0" }
all-is-cubes-gpu = { path = "../all-is-cubes-gpu", version = "0.6.0", features = ["wgpu"] }
all-is-cubes-mesh = { path = "../all-is-cubes-mesh", version = "0.6.0" }
Expand Down
3 changes: 2 additions & 1 deletion all-is-cubes-port/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ categories = ["games", "rendering::data-formats"]
bench = false

[features]
# TODO: Add features to make each format optional so that single-purpose importers or exporters are possible.

[dependencies]
all-is-cubes = { path = "../all-is-cubes", version = "0.6.0" }
all-is-cubes = { path = "../all-is-cubes", version = "0.6.0", features = ["save"] }
all-is-cubes-mesh = { path = "../all-is-cubes-mesh", version = "0.6.0" }
dot_vox = { version = "5.1.1" }
futures-core = { workspace = true }
Expand Down
10 changes: 6 additions & 4 deletions all-is-cubes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ harness = false
default = []
# Adds `impl arbitrary::Arbitrary for ...`
arbitrary = ["dep:arbitrary", "ordered-float/arbitrary"]
# Adds serde implementations.
save = ["dep:serde", "dep:serde_repr", "dep:flate2", "ordered-float/serde"]
# Adds automatic parallelism to some algorithms such as raytracing.
threads = ["dep:rayon"]

Expand All @@ -62,7 +64,7 @@ cgmath = "0.18.0"
downcast-rs = { version = "1.2.0", default-features = false }
embedded-graphics = "0.8.0"
exhaust = { workspace = true, default-features = false }
flate2 = { version = "1.0.26" }
flate2 = { version = "1.0.26", optional = true }
futures-core = { workspace = true }
indoc = { workspace = true }
instant = { workspace = true }
Expand All @@ -76,9 +78,9 @@ png-decoder = { version = "0.1.1" }
rand = { workspace = true }
rand_xoshiro = { workspace = true }
rayon = { workspace = true, optional = true }
# std and rc features needed because we are [de]serializing `Arc`s
serde = { workspace = true, features = ["derive", "std", "rc"] }
serde_repr = { version = "0.1.12", default-features = false }
# rc feature needed because we are [de]serializing `Arc`s
serde = { workspace = true, optional = true, features = ["derive", "rc"] }
serde_repr = { version = "0.1.12", optional = true, default-features = false }
thiserror = { workspace = true }
yield-progress = { version = "0.1.0" }

Expand Down
7 changes: 6 additions & 1 deletion all-is-cubes/src/behavior.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,10 +182,12 @@ impl<H: BehaviorHost> BehaviorSet<H> {
transaction.unwrap_or_default()
}

#[allow(unused)] // currently only used on feature=save
pub(crate) fn iter(&self) -> impl Iterator<Item = &BehaviorSetEntry<H>> + '_ {
self.items.iter()
}

#[allow(unused)] // currently only used on feature=save
pub(crate) fn is_empty(&self) -> bool {
self.items.is_empty()
}
Expand Down Expand Up @@ -543,7 +545,10 @@ mod testing {
/// offer some means to access this functionality or replace the [`Behavior`] system
/// entirely.
#[derive(Debug)]
pub struct BehaviorPersistence(pub(crate) crate::save::schema::BehaviorV1Ser);
pub struct BehaviorPersistence(
#[cfg(feature = "save")] pub(crate) crate::save::schema::BehaviorV1Ser,
#[cfg(not(feature = "save"))] (),
);

#[cfg(test)]
mod tests {
Expand Down
3 changes: 2 additions & 1 deletion all-is-cubes/src/block/modifier/composite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -238,8 +238,9 @@ impl universe::VisitRefs for Composite {
/// TODO: Document behavior of `collision` and `selectable` properties.
///
#[doc = include_str!("../../save/serde-warning.md")]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum CompositeOperator {
/// Porter-Duff “over”. If both source and destination are opaque, the source is taken;
Expand Down
1 change: 1 addition & 0 deletions all-is-cubes/src/block/modifier/zoom.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ impl Zoom {
}

/// Decompose into parts, for serialization.
#[cfg(feature = "save")]
pub(crate) fn to_serial_schema(&self) -> crate::save::schema::ModifierSer {
let Zoom { scale, offset } = *self;
crate::save::schema::ModifierSer::ZoomV1 {
Expand Down
2 changes: 2 additions & 0 deletions all-is-cubes/src/block/resolution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,12 +184,14 @@ impl ops::Div<Resolution> for Resolution {
}
}

#[cfg(feature = "save")]
impl serde::Serialize for Resolution {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
u16::from(*self).serialize(serializer)
}
}

#[cfg(feature = "save")]
impl<'de> serde::Deserialize<'de> for Resolution {
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
u16::deserialize(deserializer)?
Expand Down
23 changes: 15 additions & 8 deletions all-is-cubes/src/camera/graphics_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ use crate::math::{FreeCoordinate, Rgb, Rgba};
/// report such failings via [`Flaws`](crate::camera::Flaws).
///
#[doc = include_str!("../save/serde-warning.md")]
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[serde(default)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[cfg_attr(feature = "save", serde(default))]
#[non_exhaustive]
pub struct GraphicsOptions {
/// Whether and how to draw fog obscuring the view distance limit.
Expand Down Expand Up @@ -165,7 +166,8 @@ impl Default for GraphicsOptions {
/// Choices for [`GraphicsOptions::fog`].
///
#[doc = include_str!("../save/serde-warning.md")]
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum FogOption {
/// No fog: objects will maintain their color and disappear raggedly.
Expand All @@ -181,7 +183,8 @@ pub enum FogOption {
/// Choices for [`GraphicsOptions::tone_mapping`].
///
#[doc = include_str!("../save/serde-warning.md")]
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum ToneMappingOperator {
/// Limit values above the maximum (or below zero) to lie within that range.
Expand Down Expand Up @@ -218,7 +221,8 @@ impl ToneMappingOperator {
/// [`ToneMappingOperator`].
///
#[doc = include_str!("../save/serde-warning.md")]
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum ExposureOption {
/// Constant exposure; light values in the scene are multiplied by this value
Expand Down Expand Up @@ -251,7 +255,8 @@ impl Default for ExposureOption {
#[doc = include_str!("../save/serde-warning.md")]
///
/// [`Space`]: crate::space::Space
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum LightingOption {
/// No lighting: objects will be displayed with their original surface color.
Expand All @@ -270,8 +275,9 @@ pub enum LightingOption {
/// of the volumetric interpretation.
///
#[doc = include_str!("../save/serde-warning.md")]
#[derive(Clone, Debug, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum TransparencyOption {
/// Conventional transparent surfaces.
Expand Down Expand Up @@ -311,8 +317,9 @@ impl TransparencyOption {
/// Choices for [`GraphicsOptions::antialiasing`].
///
#[doc = include_str!("../save/serde-warning.md")]
#[derive(Clone, Debug, Default, Eq, PartialEq, serde::Deserialize, serde::Serialize)]
#[derive(Clone, Debug, Default, Eq, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[non_exhaustive]
pub enum AntialiasingOption {
/// Do not apply antialiasing. Every pixel of the rendered image will be the exact
Expand Down
8 changes: 5 additions & 3 deletions all-is-cubes/src/character.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
//! Player-character stuff.

use std::borrow::Cow::Borrowed;
use std::collections::HashSet;
use std::fmt;
use std::sync::Arc;
Expand All @@ -19,6 +18,7 @@ use crate::listen::{Listen, Listener, Notifier};
use crate::math::{Aab, Face6, Face7, FreeCoordinate, Rgb};
use crate::physics::{Body, BodyStepInfo, BodyTransaction, Contact};
use crate::raycast::Ray;
#[cfg(feature = "save")]
use crate::save::schema;
use crate::space::Space;
use crate::time::Tick;
Expand Down Expand Up @@ -552,6 +552,7 @@ impl crate::behavior::BehaviorHost for Character {
type Attachment = ();
}

#[cfg(feature = "save")]
impl serde::Serialize for Character {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand Down Expand Up @@ -597,14 +598,15 @@ impl serde::Serialize for Character {
yaw,
pitch,

inventory: Borrowed(inventory),
inventory: std::borrow::Cow::Borrowed(inventory),
selected_slots,
behaviors: Borrowed(behaviors),
behaviors: std::borrow::Cow::Borrowed(behaviors),
}
.serialize(serializer)
}
}

#[cfg(feature = "save")]
impl<'de> serde::Deserialize<'de> for Character {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down
3 changes: 3 additions & 0 deletions all-is-cubes/src/character/spawn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use cgmath::{Point3, Vector3};
use crate::camera::eye_for_look_at;
use crate::inv::Slot;
use crate::math::{Face6, FreeCoordinate, GridAab, NotNan};
#[cfg(feature = "save")]
use crate::save::schema;
use crate::universe::{RefVisitor, VisitRefs};

Expand Down Expand Up @@ -118,6 +119,7 @@ impl VisitRefs for Spawn {
}
}

#[cfg(feature = "save")]
impl serde::Serialize for Spawn {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
Expand All @@ -140,6 +142,7 @@ impl serde::Serialize for Spawn {
}
}

#[cfg(feature = "save")]
impl<'de> serde::Deserialize<'de> for Spawn {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
Expand Down
2 changes: 2 additions & 0 deletions all-is-cubes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@
//!
//! This crate, `all_is_cubes`, defines the following feature flags:
//!
//! * `save`:
//! Enable [`serde`] serialization of [`Universe`]s and some other types.
//! * `threads`:
//! Enable use of threads for parallel and background processing, including via
//! [`rayon`]’s global thread pool.
Expand Down
10 changes: 4 additions & 6 deletions all-is-cubes/src/math/face.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,9 @@ use crate::math::*;
#[doc = include_str!("../save/serde-warning.md")]
#[allow(clippy::upper_case_acronyms)]
#[allow(clippy::exhaustive_enums)]
#[derive(
Clone, Copy, Debug, Hash, Eq, PartialEq, exhaust::Exhaust, serde::Deserialize, serde::Serialize,
)]
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, exhaust::Exhaust)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
pub enum Face6 {
/// Negative X; the face whose normal vector is `(-1, 0, 0)`.
Expand All @@ -45,10 +44,9 @@ pub enum Face6 {
#[doc = include_str!("../save/serde-warning.md")]
#[allow(clippy::upper_case_acronyms)]
#[allow(clippy::exhaustive_enums)]
#[derive(
Clone, Copy, Debug, Hash, Eq, PartialEq, exhaust::Exhaust, serde::Deserialize, serde::Serialize,
)]
#[derive(Clone, Copy, Debug, Hash, Eq, PartialEq, exhaust::Exhaust)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
pub enum Face7 {
/// The interior volume of a cube, or an undefined direction. Corresponds to the vector `(0, 0, 0)`.
Expand Down
3 changes: 2 additions & 1 deletion all-is-cubes/src/math/rotation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,9 @@ use crate::math::*;
#[allow(clippy::upper_case_acronyms)]
#[allow(clippy::exhaustive_enums)]
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "arbitrary", derive(arbitrary::Arbitrary))]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
#[repr(u8)]
pub enum GridRotation {
// TODO: shuffle or explicitly number these to choose a meaningful numbering
Expand Down
4 changes: 4 additions & 0 deletions all-is-cubes/src/save.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,15 @@ use futures_core::future::BoxFuture;
use crate::universe::Universe;
use crate::util::YieldProgress;

#[cfg(feature = "save")]
mod compress;
#[cfg(feature = "save")]
pub(crate) mod conversion;
#[cfg(feature = "save")]
pub(crate) mod schema;

#[cfg(test)]
#[cfg(feature = "save")]
mod tests;

/// Specifies a file or other data storage a [`Universe`] can be read from or written to.
Expand Down
4 changes: 3 additions & 1 deletion all-is-cubes/src/space.rs
Original file line number Diff line number Diff line change
Expand Up @@ -770,7 +770,8 @@ impl crate::behavior::BehaviorHost for Space {
/// exists.
// ---
// TODO: This shouldn't directly implement Serialize
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, serde::Serialize, serde::Deserialize)]
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
#[cfg_attr(feature = "save", derive(serde::Serialize, serde::Deserialize))]
pub struct SpaceBehaviorAttachment {
bounds: GridAab,
rotation: GridRotation,
Expand Down Expand Up @@ -1089,6 +1090,7 @@ pub struct Extract<'s> {

impl<'s> Extract<'s> {
/// Returns the cube being processed.
#[allow(unused)] // currently only used on feature=save
pub(crate) fn cube(&self) -> Cube {
self.cube
}
Expand Down
1 change: 1 addition & 0 deletions all-is-cubes/src/space/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ impl<B> SpaceBuilder<B> {
}

/// TODO: not sure if this is good public API
#[allow(unused)] // currently only used on feature=save
pub(crate) fn behaviors(mut self, behaviors: BehaviorSet<Space>) -> Self {
self.behaviors = behaviors;
self
Expand Down
3 changes: 3 additions & 0 deletions all-is-cubes/src/space/light/data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ pub(crate) type PackedLightScalar = u8;
#[repr(u8)]
pub(crate) enum LightStatus {
/// The cube's light value has never been computed.
#[allow(unused)] // currently only used on feature=save
Uninitialized = 0,
/// The cube has no surfaces to catch light and therefore the light value is not tracked.
NoRays = 1,
Expand Down Expand Up @@ -194,6 +195,7 @@ impl From<Rgb> for PackedLight {
}
}

#[cfg(feature = "save")]
impl From<PackedLight> for crate::save::schema::LightSerV1 {
fn from(p: PackedLight) -> Self {
use crate::save::schema::LightStatusSerV1 as S;
Expand All @@ -209,6 +211,7 @@ impl From<PackedLight> for crate::save::schema::LightSerV1 {
}
}

#[cfg(feature = "save")]
impl From<crate::save::schema::LightSerV1> for PackedLight {
fn from(ls: crate::save::schema::LightSerV1) -> Self {
use crate::save::schema::LightStatusSerV1 as S;
Expand Down
1 change: 1 addition & 0 deletions all-is-cubes/src/space/light/updater.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ impl Space {
}
}

#[allow(unused)] // currently only used on feature=save
pub(crate) fn in_light_update_queue(&self, cube: Cube) -> bool {
self.light_update_queue.contains(cube)
}
Expand Down
Loading

0 comments on commit 5b538b8

Please sign in to comment.