diff --git a/src/style/compact_length.rs b/src/style/compact_length.rs index 7e6be88f8..89280f621 100644 --- a/src/style/compact_length.rs +++ b/src/style/compact_length.rs @@ -506,10 +506,21 @@ impl<'de> serde::Deserialize<'de> for CompactLength { { let bits: u64 = u64::deserialize(deserializer)?; let value = Self(CompactLengthInner::from_serialized(bits)); - if value.is_calc() { - Err(serde::de::Error::custom("Cannot deserialize Calc value")) - } else { + // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported + if matches!( + value.tag(), + CompactLength::LENGTH_TAG + | CompactLength::PERCENT_TAG + | CompactLength::AUTO_TAG + | CompactLength::MIN_CONTENT_TAG + | CompactLength::MAX_CONTENT_TAG + | CompactLength::FIT_CONTENT_PX_TAG + | CompactLength::FIT_CONTENT_PERCENT_TAG + | CompactLength::FR_TAG + ) { Ok(value) + } else { + Err(serde::de::Error::custom("Cannot deserialize Calc value")) } } } diff --git a/src/style/dimension.rs b/src/style/dimension.rs index 83cddd79b..2391d5ba3 100644 --- a/src/style/dimension.rs +++ b/src/style/dimension.rs @@ -7,7 +7,7 @@ use crate::style_helpers::{FromLength, FromPercent, TaffyAuto, TaffyZero}; /// /// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size`](crate::geometry::Size). #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct LengthPercentage(pub(crate) CompactLength); impl TaffyZero for LengthPercentage { const ZERO: Self = Self(CompactLength::ZERO); @@ -61,11 +61,27 @@ impl LengthPercentage { } } +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for LengthPercentage { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let inner = CompactLength::deserialize(deserializer)?; + // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported + if matches!(inner.tag(), CompactLength::LENGTH_TAG | CompactLength::PERCENT_TAG) { + Ok(Self(inner)) + } else { + Err(serde::de::Error::custom("Invalid tag")) + } + } +} + /// A unit of linear measurement /// /// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size`](crate::geometry::Size). #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct LengthPercentageAuto(pub(crate) CompactLength); impl TaffyZero for LengthPercentageAuto { const ZERO: Self = Self(CompactLength::ZERO); @@ -156,11 +172,27 @@ impl LengthPercentageAuto { } } +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for LengthPercentageAuto { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let inner = CompactLength::deserialize(deserializer)?; + // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported + if matches!(inner.tag(), CompactLength::LENGTH_TAG | CompactLength::PERCENT_TAG | CompactLength::AUTO_TAG) { + Ok(Self(inner)) + } else { + Err(serde::de::Error::custom("Invalid tag")) + } + } +} + /// A unit of linear measurement /// /// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size`](crate::geometry::Size). #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct Dimension(pub(crate) CompactLength); impl TaffyZero for Dimension { const ZERO: Self = Self(CompactLength::ZERO); @@ -259,6 +291,22 @@ impl Dimension { } } +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for Dimension { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let inner = CompactLength::deserialize(deserializer)?; + // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported + if matches!(inner.tag(), CompactLength::LENGTH_TAG | CompactLength::PERCENT_TAG | CompactLength::AUTO_TAG) { + Ok(Self(inner)) + } else { + Err(serde::de::Error::custom("Invalid tag")) + } + } +} + impl Rect { /// Create a new Rect with length values #[must_use] diff --git a/src/style/grid.rs b/src/style/grid.rs index 28c71dd6c..9f800a25b 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -366,7 +366,7 @@ impl Default for Line { /// on the size of it's contents, the amount of available space, and the sizing constraint the grid is being size under. /// See #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct MaxTrackSizingFunction(pub(crate) CompactLength); impl TaffyZero for MaxTrackSizingFunction { const ZERO: Self = Self(CompactLength::ZERO); @@ -420,6 +420,31 @@ impl From for MaxTrackSizingFunction { Self(input.0) } } +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for MaxTrackSizingFunction { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let inner = CompactLength::deserialize(deserializer)?; + // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported + if matches!( + inner.tag(), + CompactLength::LENGTH_TAG + | CompactLength::PERCENT_TAG + | CompactLength::AUTO_TAG + | CompactLength::MIN_CONTENT_TAG + | CompactLength::MAX_CONTENT_TAG + | CompactLength::FIT_CONTENT_PX_TAG + | CompactLength::FIT_CONTENT_PERCENT_TAG + | CompactLength::FR_TAG + ) { + Ok(Self(inner)) + } else { + Err(serde::de::Error::custom("Invalid tag")) + } + } +} impl MaxTrackSizingFunction { /// An absolute length in some abstract units. Users of Taffy may define what they correspond @@ -637,7 +662,7 @@ impl MaxTrackSizingFunction { /// on the size of it's contents, the amount of available space, and the sizing constraint the grid is being size under. /// See #[derive(Copy, Clone, PartialEq, Debug)] -#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] +#[cfg_attr(feature = "serde", derive(Serialize))] pub struct MinTrackSizingFunction(pub(crate) CompactLength); impl TaffyZero for MinTrackSizingFunction { const ZERO: Self = Self(CompactLength::ZERO); @@ -676,6 +701,30 @@ impl From for MinTrackSizingFunction { Self(input.0) } } +#[cfg(feature = "serde")] +impl<'de> serde::Deserialize<'de> for MinTrackSizingFunction { + fn deserialize(deserializer: D) -> Result + where + D: serde::Deserializer<'de>, + { + let inner = CompactLength::deserialize(deserializer)?; + // Note: validation intentionally excludes the CALC_TAG as deserializing calc() values is not supported + if matches!( + inner.tag(), + CompactLength::LENGTH_TAG + | CompactLength::PERCENT_TAG + | CompactLength::AUTO_TAG + | CompactLength::MIN_CONTENT_TAG + | CompactLength::MAX_CONTENT_TAG + | CompactLength::FIT_CONTENT_PX_TAG + | CompactLength::FIT_CONTENT_PERCENT_TAG + ) { + Ok(Self(inner)) + } else { + Err(serde::de::Error::custom("Invalid tag")) + } + } +} impl MinTrackSizingFunction { /// An absolute length in some abstract units. Users of Taffy may define what they correspond