gioser

tawasuyu/taffy

A high performance rust-powered UI layout library

HTML 5544Rust 88Markdown 11TOML 91926 Definiciones

Fix deserialize partial values with serde (#366)

* Enable serde to deserialize partial style values

* Implement style helpers for Line<T>

* Cargo fmt

52ae96646aca7b811a12109ca699fb14bf5b50b4 · por Nico Burns · (hace 3 años) · padre 08e47a4ae · ver el árbol en este commit

Delta semántico · 18

src/style/mod.rs

  • cambió de firma struct Style pub

src/style_helpers.rs

tests/serde.rs

4 archivos · +143 −1

diff --git a/Cargo.toml b/Cargo.toml
index 492dff138..d87be4af0 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -39,6 +39,7 @@ rand = "0.8.5"
 rand_chacha = "0.3.1"
 yoga = "0.4.0"
 ordered-float = "3.4.0"
+serde_json = "1.0.93"
 
 # Enable example and test-specific features
 taffy = { path = ".", features = ["random"] }
diff --git a/src/style/mod.rs b/src/style/mod.rs
index b0cf1c238..ee4fa9d21 100644
--- a/src/style/mod.rs
+++ b/src/style/mod.rs
@@ -20,6 +20,8 @@ use crate::geometry::{Rect, Size};
 
 #[cfg(feature = "grid")]
 use crate::geometry::Line;
+#[cfg(feature = "serde")]
+use crate::style_helpers;
 #[cfg(feature = "grid")]
 use crate::sys::GridTrackVec;
 
@@ -98,14 +100,18 @@ pub struct Style {
     /// What should the `position` value of this struct use as a base offset?
     pub position: Position,
     /// How should the position of this element be tweaked relative to the layout defined?
+    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
     pub inset: Rect<LengthPercentageAuto>,
 
     // Size properies
     /// Sets the initial size of the item
+    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
     pub size: Size<Dimension>,
     /// Controls the minimum size of the item
+    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
     pub min_size: Size<Dimension>,
     /// Controls the maximum size of the item
+    #[cfg_attr(feature = "serde", serde(default = "style_helpers::auto"))]
     pub max_size: Size<Dimension>,
     /// Sets the preferred aspect ratio for the item
     ///
@@ -114,10 +120,13 @@ pub struct Style {
 
     // Spacing Properties
     /// How large should the margin be on each side?
+    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
     pub margin: Rect<LengthPercentageAuto>,
     /// How large should the padding be on each side?
+    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
     pub padding: Rect<LengthPercentage>,
     /// How large should the border be on each side?
+    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
     pub border: Rect<LengthPercentage>,
 
     // Alignment properties
@@ -137,6 +146,7 @@ pub struct Style {
     /// How should contained within this item be aligned in the main/inline axis
     pub justify_content: Option<JustifyContent>,
     /// How large should the gaps between items in a grid or flex container be?
+    #[cfg_attr(feature = "serde", serde(default = "style_helpers::zero"))]
     pub gap: Size<LengthPercentage>,
 
     // Flexbox properies
diff --git a/src/style_helpers.rs b/src/style_helpers.rs
index 94f262b9f..7e1f55082 100644
--- a/src/style_helpers.rs
+++ b/src/style_helpers.rs
@@ -1,6 +1,6 @@
 //! Helper functions which it make it easier to create instances of types in the `style` and `geometry` modules.
 use crate::{
-    geometry::{MinMax, Point, Rect, Size},
+    geometry::{Line, MinMax, Point, Rect, Size},
     style::LengthPercentage,
 };
 use core::fmt::Debug;
@@ -119,6 +119,16 @@ impl<T: TaffyZero> Point<T> {
         zero::<Self>()
     }
 }
+impl<T: TaffyZero> TaffyZero for Line<T> {
+    const ZERO: Line<T> = Line { start: T::ZERO, end: T::ZERO };
+}
+impl<T: TaffyZero> Line<T> {
+    /// Returns a Line where both the start and end values are the zero value of the contained type
+    /// (e.g. 0.0, Some(0.0), or Dimension::Points(0.0))
+    pub const fn zero() -> Self {
+        zero::<Self>()
+    }
+}
 impl<T: TaffyZero> TaffyZero for Size<T> {
     const ZERO: Size<T> = Size { width: T::ZERO, height: T::ZERO };
 }
@@ -163,6 +173,16 @@ impl<T: TaffyAuto> Point<T> {
         auto::<Self>()
     }
 }
+impl<T: TaffyAuto> TaffyAuto for Line<T> {
+    const AUTO: Line<T> = Line { start: T::AUTO, end: T::AUTO };
+}
+impl<T: TaffyAuto> Line<T> {
+    /// Returns a Line where both the start and end values are the auto value of the contained type
+    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
+    pub const fn auto() -> Self {
+        auto::<Self>()
+    }
+}
 impl<T: TaffyAuto> TaffyAuto for Size<T> {
     const AUTO: Size<T> = Size { width: T::AUTO, height: T::AUTO };
 }
@@ -207,6 +227,16 @@ impl<T: TaffyMinContent> Point<T> {
         min_content::<Self>()
     }
 }
+impl<T: TaffyMinContent> TaffyMinContent for Line<T> {
+    const MIN_CONTENT: Line<T> = Line { start: T::MIN_CONTENT, end: T::MIN_CONTENT };
+}
+impl<T: TaffyMinContent> Line<T> {
+    /// Returns a Line where both the start and end values are the min_content value of the contained type
+    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
+    pub const fn min_content() -> Self {
+        min_content::<Self>()
+    }
+}
 impl<T: TaffyMinContent> TaffyMinContent for Size<T> {
     const MIN_CONTENT: Size<T> = Size { width: T::MIN_CONTENT, height: T::MIN_CONTENT };
 }
@@ -252,6 +282,16 @@ impl<T: TaffyMaxContent> Point<T> {
         max_content::<Self>()
     }
 }
+impl<T: TaffyMaxContent> TaffyMaxContent for Line<T> {
+    const MAX_CONTENT: Line<T> = Line { start: T::MAX_CONTENT, end: T::MAX_CONTENT };
+}
+impl<T: TaffyMaxContent> Line<T> {
+    /// Returns a Line where both the start and end values are the max_content value of the contained type
+    /// (e.g. Dimension::Auto or LengthPercentageAuto::Auto)
+    pub const fn max_content() -> Self {
+        max_content::<Self>()
+    }
+}
 impl<T: TaffyMaxContent> TaffyMaxContent for Size<T> {
     const MAX_CONTENT: Size<T> = Size { width: T::MAX_CONTENT, height: T::MAX_CONTENT };
 }
@@ -296,6 +336,18 @@ impl<T: TaffyFitContent> Point<T> {
         fit_content(argument)
     }
 }
+impl<T: TaffyFitContent> TaffyFitContent for Line<T> {
+    fn fit_content(argument: LengthPercentage) -> Self {
+        Line { start: T::fit_content(argument), end: T::fit_content(argument) }
+    }
+}
+impl<T: TaffyFitContent> Line<T> {
+    /// Returns a Line where both the start and end values are the constant points value of the contained type
+    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
+    pub fn fit_content(argument: LengthPercentage) -> Self {
+        fit_content(argument)
+    }
+}
 impl<T: TaffyFitContent> TaffyFitContent for Size<T> {
     fn fit_content(argument: LengthPercentage) -> Self {
         Size { width: T::fit_content(argument), height: T::fit_content(argument) }
@@ -358,6 +410,18 @@ impl<T: FromPoints> Point<T> {
         points::<Input, Self>(points_value)
     }
 }
+impl<T: FromPoints> FromPoints for Line<T> {
+    fn from_points<Input: Into<f32> + Copy>(points: Input) -> Self {
+        Line { start: T::from_points(points.into()), end: T::from_points(points.into()) }
+    }
+}
+impl<T: FromPoints> Line<T> {
+    /// Returns a Line where both the start and end values are the constant points value of the contained type
+    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
+    pub fn points<Input: Into<f32> + Copy>(points_value: Input) -> Self {
+        points::<Input, Self>(points_value)
+    }
+}
 impl<T: FromPoints> FromPoints for Size<T> {
     fn from_points<Input: Into<f32> + Copy>(points: Input) -> Self {
         Size { width: T::from_points(points.into()), height: T::from_points(points.into()) }
@@ -420,6 +484,18 @@ impl<T: FromPercent> Point<T> {
         percent::<Input, Self>(percent_value)
     }
 }
+impl<T: FromPercent> FromPercent for Line<T> {
+    fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
+        Line { start: T::from_percent(percent.into()), end: T::from_percent(percent.into()) }
+    }
+}
+impl<T: FromPercent> Line<T> {
+    /// Returns a Line where both the start and end values are the constant percent value of the contained type
+    /// (e.g. 2.1, Some(2.1), or Dimension::Points(2.1))
+    pub fn percent<Input: Into<f32> + Copy>(percent_value: Input) -> Self {
+        percent::<Input, Self>(percent_value)
+    }
+}
 impl<T: FromPercent> FromPercent for Size<T> {
     fn from_percent<Input: Into<f32> + Copy>(percent: Input) -> Self {
         Size { width: T::from_percent(percent.into()), height: T::from_percent(percent.into()) }
diff --git a/tests/serde.rs b/tests/serde.rs
new file mode 100644
index 000000000..8d4d913af
--- /dev/null
+++ b/tests/serde.rs
@@ -0,0 +1,55 @@
+#[cfg(test)]
+#[cfg(feature = "serde")]
+mod serde {
+
+    use serde_json::{self, Value};
+    use taffy::style::Style;
+
+    #[test]
+    fn serde_can_serialize() {
+        let style = Style::DEFAULT;
+        let _ = serde_json::to_string(&style).unwrap();
+    }
+
+    #[test]
+    fn serde_can_deserialize_partial_values() {
+        use serde_json;
+        let json = r###"{
+            "inset": {
+                "left": { "Points": 22 },
+                "right": "Auto"
+            },
+            "size":
+            {
+                "width": { "Percent": 50 }
+            },
+            "min_size":
+            {
+                "height": { "Points": 10 }
+            },
+            "max_size":
+            {
+                "width": "Auto"
+            },
+            "margin":
+            {
+                "right": { "Points": 99.0 },
+                "bottom": { "Points": 99.0 }
+            },
+            "padding":
+            {
+                "left": { "Points": 99.0 }
+            },
+            "border":
+            {
+                "bottom": { "Points": 99.0 }
+            },
+            "gap": {
+                "width": { "Points": 99.0 }
+            },
+            "grid_row": { "start": "Auto" },
+            "grid_column": { "end": "Auto" }
+        }"###;
+        let _: Value = serde_json::from_str(&json).unwrap();
+    }
+}