Skip to content

Commit

Permalink
Validate tag when deserializing values
Browse files Browse the repository at this point in the history
Signed-off-by: Nico Burns <[email protected]>
  • Loading branch information
nicoburns committed Feb 20, 2025
1 parent 8d2a036 commit 2ddb381
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 8 deletions.
17 changes: 14 additions & 3 deletions src/style/compact_length.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
}
}
}
54 changes: 51 additions & 3 deletions src/style/dimension.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::style_helpers::{FromLength, FromPercent, TaffyAuto, TaffyZero};
///
/// This is commonly combined with [`Rect`], [`Point`](crate::geometry::Point) and [`Size<T>`](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);
Expand Down Expand Up @@ -61,11 +61,27 @@ impl LengthPercentage {
}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for LengthPercentage {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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<T>`](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);
Expand Down Expand Up @@ -156,11 +172,27 @@ impl LengthPercentageAuto {
}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for LengthPercentageAuto {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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<T>`](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);
Expand Down Expand Up @@ -259,6 +291,22 @@ impl Dimension {
}
}

#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for Dimension {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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<Dimension> {
/// Create a new Rect with length values
#[must_use]
Expand Down
53 changes: 51 additions & 2 deletions src/style/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@ impl Default for Line<GridPlacement> {
/// on the size of it's contents, the amount of available space, and the sizing constraint the grid is being size under.
/// See <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns>
#[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);
Expand Down Expand Up @@ -420,6 +420,31 @@ impl From<MinTrackSizingFunction> for MaxTrackSizingFunction {
Self(input.0)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for MaxTrackSizingFunction {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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
Expand Down Expand Up @@ -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 <https://developer.mozilla.org/en-US/docs/Web/CSS/grid-template-columns>
#[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);
Expand Down Expand Up @@ -676,6 +701,30 @@ impl From<Dimension> for MinTrackSizingFunction {
Self(input.0)
}
}
#[cfg(feature = "serde")]
impl<'de> serde::Deserialize<'de> for MinTrackSizingFunction {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
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
Expand Down

0 comments on commit 2ddb381

Please sign in to comment.