From 69209391039570a784268ef3b36c6fa8f7c94084 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 01:43:17 +0000 Subject: [PATCH 01/57] C binding experiments --- src/ffi.rs | 223 +++++++++++++++++++++++++++++++++++++++++++++++++++++ src/lib.rs | 3 +- 2 files changed, 225 insertions(+), 1 deletion(-) create mode 100644 src/ffi.rs diff --git a/src/ffi.rs b/src/ffi.rs new file mode 100644 index 000000000..9c80f2527 --- /dev/null +++ b/src/ffi.rs @@ -0,0 +1,223 @@ +//! Types for C FFI + +use crate::prelude as core; +use std::ffi::c_void; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum ErrorCode { + /// Operation suceeded + Ok, + /// A None unit was specified but is not valid in this context + InvalidNone, + /// A Length unit was specified but is not valid in this context + InvalidLength, + /// A Percent unit was specified but is not valid in this context + InvalidPercent, + /// A MinContent unit was specified but is not valid in this context + InvalidMinContent, + /// A MaxContent unit was specified but is not valid in this context + InvalidMaxContent, + /// A FitContentPx unit was specified but is not valid in this context + InvalidFitContentPx, + /// A FitContentPercent unit was specified but is not valid in this context + InvalidFitContentPercent, + /// An Auto unit was specified but is not valid in this context + InvalidAuto, + /// An Fr unit was specified but is not valid in this context + InvalidFr, + /// A NaN value was specified but is not valid in this context + UnexpectedNaN, + /// A infinite value was specified but is not valid in this context + UnexpectedInfinity, + /// A negative value was specified but is not valid in this context + UnexpectedNegative, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum StyleValueUnit { + /// A none value (used to unset optional fields) + None, + /// Fixed Length (pixel) value + Length, + /// Percentage value + Percent, + /// Min-content size + MinContent, + /// Max-content size + MaxContent, + /// fit-content() function with a pixel limit + FitContentPx, + /// fit-content() function with a percentage limit + FitContentPercent, + /// Automatic values + Auto, + /// fr unit + Fr, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +#[repr(C)] +pub struct StyleValue { + pub unit: StyleValueUnit, + /// The value. If the unit is variant that doesn't require a value (e.g. Auto) then the value + /// is ignored. + pub value: f32, +} + +impl StyleValue { + #[inline(always)] + fn from_raw(unit: StyleValueUnit, value: f32) -> Self { + Self { unit, value } + } +} + +impl TryFrom for core::LengthPercentage { + type Error = ErrorCode; + + fn try_from(value: StyleValue) -> Result { + match value.unit { + StyleValueUnit::Length => Ok(core::LengthPercentage::Length(value.value)), + StyleValueUnit::Percent => Ok(core::LengthPercentage::Percent(value.value)), + StyleValueUnit::None => Err(ErrorCode::InvalidNone), + StyleValueUnit::Auto => Err(ErrorCode::InvalidAuto), + StyleValueUnit::MinContent => Err(ErrorCode::InvalidMinContent), + StyleValueUnit::MaxContent => Err(ErrorCode::InvalidMaxContent), + StyleValueUnit::FitContentPx => Err(ErrorCode::InvalidFitContentPx), + StyleValueUnit::FitContentPercent => Err(ErrorCode::InvalidFitContentPercent), + StyleValueUnit::Fr => Err(ErrorCode::InvalidFr), + } + } +} + +impl TryFrom for core::LengthPercentageAuto { + type Error = ErrorCode; + + fn try_from(value: StyleValue) -> Result { + match value.unit { + StyleValueUnit::Auto => Ok(core::LengthPercentageAuto::Auto), + StyleValueUnit::Length => Ok(core::LengthPercentageAuto::Length(value.value)), + StyleValueUnit::Percent => Ok(core::LengthPercentageAuto::Percent(value.value)), + StyleValueUnit::None => Err(ErrorCode::InvalidNone), + StyleValueUnit::MinContent => Err(ErrorCode::InvalidMinContent), + StyleValueUnit::MaxContent => Err(ErrorCode::InvalidMaxContent), + StyleValueUnit::FitContentPx => Err(ErrorCode::InvalidFitContentPx), + StyleValueUnit::FitContentPercent => Err(ErrorCode::InvalidFitContentPercent), + StyleValueUnit::Fr => Err(ErrorCode::InvalidFr), + } + } +} + +#[repr(transparent)] +pub struct Style { + inner: core::Style, +} + +pub fn assert_pointer_address(pointer: *const c_void, pointer_type: &str) { + assert_ne!( + pointer, + std::ptr::null(), + "Invalid {:} pointer address", + pointer_type + ); +} + +macro_rules! with_style_mut { + ($raw_style_ptr:expr, $rust_style_ptr:ident, $block:expr) => { + assert_pointer_address($raw_style_ptr, "style"); + let mut $rust_style_ptr = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + + $block; + + Box::leak($rust_style_ptr); + }; +} + +macro_rules! try_from_value { + ($value:expr) => { + match $value.try_into() { + Ok(val) => val, + Err(err) => return err, + } + }; +} + +macro_rules! try_from_raw { + ($unit:expr, $value:expr) => { + try_from_value!(StyleValue::from_raw($unit, $value)) + }; +} + +/// Function to set all the value of padding +#[no_mangle] +pub extern "C" fn Taffy_set_padding_trbl( + raw_style: *mut c_void, + top_value: f32, + top_value_unit: StyleValueUnit, + right_value: f32, + right_value_unit: StyleValueUnit, + left_value: f32, + left_value_unit: StyleValueUnit, + bottom_value: f32, + bottom_value_unit: StyleValueUnit, +) -> ErrorCode { + let top = try_from_raw!(top_value_unit, top_value); + let right = try_from_raw!(right_value_unit, right_value); + let bottom = try_from_raw!(bottom_value_unit, bottom_value); + let left = try_from_raw!(left_value_unit, left_value); + + with_style_mut!(raw_style, style, { + style.inner.padding.top = top; + style.inner.padding.right = right; + style.inner.padding.bottom = bottom; + style.inner.padding.left = left; + }); + + ErrorCode::Ok +} + +/// Function to set all the value of margin +#[no_mangle] +pub extern "C" fn Taffy_set_padding_top( + raw_style: *mut c_void, + value: f32, + unit: StyleValueUnit, +) -> ErrorCode { + with_style_mut!(raw_style, style, style.inner.padding.top = try_from_raw!(unit, value)); + ErrorCode::Ok +} + +/// Function to set all the value of margin +#[no_mangle] +pub extern "C" fn Taffy_set_margin_trbl( + raw_style: *mut c_void, + top: StyleValue, + right: StyleValue, + bottom: StyleValue, + left: StyleValue, +) -> ErrorCode { + let top = try_from_value!(top); + let right = try_from_value!(right); + let bottom = try_from_value!(bottom); + let left = try_from_value!(left); + + with_style_mut!(raw_style, style, { + style.inner.margin.top = top; + style.inner.margin.right = right; + style.inner.margin.bottom = bottom; + style.inner.margin.left = left; + }); + + ErrorCode::Ok +} + +/// Function to set all the value of margin +#[no_mangle] +pub extern "C" fn Taffy_set_margin_top( + raw_style: *mut c_void, + value: StyleValue, +) -> ErrorCode { + with_style_mut!(raw_style, style, style.inner.margin.top = try_from_value!(value)); + ErrorCode::Ok +} diff --git a/src/lib.rs b/src/lib.rs index 577abf778..662f56641 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,7 +59,7 @@ #![cfg_attr(not(feature = "std"), no_std)] #![deny(unsafe_code)] -#![forbid(unsafe_code)] +// #![forbid(unsafe_code)] #![warn(missing_docs)] #![warn(clippy::missing_docs_in_private_items)] @@ -77,6 +77,7 @@ extern crate alloc; extern crate serde; pub mod compute; +pub mod ffi; pub mod geometry; pub mod prelude; pub mod style; From b93c73bce13ff59f21eb643bf13d10a309cc82a4 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 01:55:19 +0000 Subject: [PATCH 02/57] Simplify conversion functions --- src/ffi.rs | 55 ++++++++++++++++++++++-------------------------------- 1 file changed, 22 insertions(+), 33 deletions(-) diff --git a/src/ffi.rs b/src/ffi.rs index 9c80f2527..aad492696 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -1,6 +1,7 @@ //! Types for C FFI use crate::prelude as core; +use crate::geometry::{Rect}; use std::ffi::c_void; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -60,10 +61,9 @@ pub enum StyleValueUnit { #[derive(Debug, Clone, Copy, PartialEq)] #[repr(C)] pub struct StyleValue { - pub unit: StyleValueUnit, - /// The value. If the unit is variant that doesn't require a value (e.g. Auto) then the value - /// is ignored. + /// The value. If the unit is variant that doesn't require a value (e.g. Auto) then the value is ignored. pub value: f32, + pub unit: StyleValueUnit, } impl StyleValue { @@ -124,14 +124,15 @@ pub fn assert_pointer_address(pointer: *const c_void, pointer_type: &str) { } macro_rules! with_style_mut { - ($raw_style_ptr:expr, $rust_style_ptr:ident, $block:expr) => { + ($raw_style_ptr:expr, $rust_style_ptr:ident, $block:expr) => {{ assert_pointer_address($raw_style_ptr, "style"); let mut $rust_style_ptr = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; $block; Box::leak($rust_style_ptr); - }; + ErrorCode::Ok + }}; } macro_rules! try_from_value { @@ -162,19 +163,14 @@ pub extern "C" fn Taffy_set_padding_trbl( bottom_value: f32, bottom_value_unit: StyleValueUnit, ) -> ErrorCode { - let top = try_from_raw!(top_value_unit, top_value); - let right = try_from_raw!(right_value_unit, right_value); - let bottom = try_from_raw!(bottom_value_unit, bottom_value); - let left = try_from_raw!(left_value_unit, left_value); - with_style_mut!(raw_style, style, { - style.inner.padding.top = top; - style.inner.padding.right = right; - style.inner.padding.bottom = bottom; - style.inner.padding.left = left; - }); - - ErrorCode::Ok + style.inner.padding = Rect { + top: try_from_raw!(top_value_unit, top_value), + right: try_from_raw!(right_value_unit, right_value), + bottom: try_from_raw!(bottom_value_unit, bottom_value), + left: try_from_raw!(left_value_unit, left_value), + }; + }) } /// Function to set all the value of margin @@ -184,8 +180,7 @@ pub extern "C" fn Taffy_set_padding_top( value: f32, unit: StyleValueUnit, ) -> ErrorCode { - with_style_mut!(raw_style, style, style.inner.padding.top = try_from_raw!(unit, value)); - ErrorCode::Ok + with_style_mut!(raw_style, style, style.inner.padding.top = try_from_raw!(unit, value)) } /// Function to set all the value of margin @@ -197,19 +192,14 @@ pub extern "C" fn Taffy_set_margin_trbl( bottom: StyleValue, left: StyleValue, ) -> ErrorCode { - let top = try_from_value!(top); - let right = try_from_value!(right); - let bottom = try_from_value!(bottom); - let left = try_from_value!(left); - with_style_mut!(raw_style, style, { - style.inner.margin.top = top; - style.inner.margin.right = right; - style.inner.margin.bottom = bottom; - style.inner.margin.left = left; - }); - - ErrorCode::Ok + style.inner.margin = Rect { + top: try_from_value!(top), + right: try_from_value!(right), + bottom: try_from_value!(bottom), + left: try_from_value!(left), + }; + }) } /// Function to set all the value of margin @@ -218,6 +208,5 @@ pub extern "C" fn Taffy_set_margin_top( raw_style: *mut c_void, value: StyleValue, ) -> ErrorCode { - with_style_mut!(raw_style, style, style.inner.margin.top = try_from_value!(value)); - ErrorCode::Ok + with_style_mut!(raw_style, style, style.inner.margin.top = try_from_value!(value)) } From c04de15ea69faccdbd543c08a13054d4d844f009 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 01:57:08 +0000 Subject: [PATCH 03/57] Reorder padding/margin examples --- src/ffi.rs | 57 +++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/ffi.rs b/src/ffi.rs index aad492696..ebe333cda 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -150,6 +150,35 @@ macro_rules! try_from_raw { }; } + +/// Function to set all the value of margin +#[no_mangle] +pub extern "C" fn Taffy_set_margin_trbl( + raw_style: *mut c_void, + top: StyleValue, + right: StyleValue, + bottom: StyleValue, + left: StyleValue, +) -> ErrorCode { + with_style_mut!(raw_style, style, { + style.inner.margin = Rect { + top: try_from_value!(top), + right: try_from_value!(right), + bottom: try_from_value!(bottom), + left: try_from_value!(left), + }; + }) +} + +/// Function to set all the value of margin +#[no_mangle] +pub extern "C" fn Taffy_set_margin_top( + raw_style: *mut c_void, + value: StyleValue, +) -> ErrorCode { + with_style_mut!(raw_style, style, style.inner.margin.top = try_from_value!(value)) +} + /// Function to set all the value of padding #[no_mangle] pub extern "C" fn Taffy_set_padding_trbl( @@ -182,31 +211,3 @@ pub extern "C" fn Taffy_set_padding_top( ) -> ErrorCode { with_style_mut!(raw_style, style, style.inner.padding.top = try_from_raw!(unit, value)) } - -/// Function to set all the value of margin -#[no_mangle] -pub extern "C" fn Taffy_set_margin_trbl( - raw_style: *mut c_void, - top: StyleValue, - right: StyleValue, - bottom: StyleValue, - left: StyleValue, -) -> ErrorCode { - with_style_mut!(raw_style, style, { - style.inner.margin = Rect { - top: try_from_value!(top), - right: try_from_value!(right), - bottom: try_from_value!(bottom), - left: try_from_value!(left), - }; - }) -} - -/// Function to set all the value of margin -#[no_mangle] -pub extern "C" fn Taffy_set_margin_top( - raw_style: *mut c_void, - value: StyleValue, -) -> ErrorCode { - with_style_mut!(raw_style, style, style.inner.margin.top = try_from_value!(value)) -} From 9d0112a78ebc15c8a8e32d1c6ab01a39de247527 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 02:17:10 +0000 Subject: [PATCH 04/57] Add getter example --- src/ffi.rs | 132 +++++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 99 insertions(+), 33 deletions(-) diff --git a/src/ffi.rs b/src/ffi.rs index ebe333cda..3a1cc155a 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -6,7 +6,7 @@ use std::ffi::c_void; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] -pub enum ErrorCode { +pub enum ReturnCode { /// Operation suceeded Ok, /// A None unit was specified but is not valid in this context @@ -73,42 +73,67 @@ impl StyleValue { } } +impl From for StyleValue { + fn from(value: core::LengthPercentage) -> Self { + match value { + core::LengthPercentage::Points(value) => Self { unit: StyleValueUnit::Points, value }, + core::LengthPercentage::Percent(value) => Self { unit: StyleValueUnit::Percent, value }, + } + } +} + impl TryFrom for core::LengthPercentage { - type Error = ErrorCode; + type Error = ReturnCode; fn try_from(value: StyleValue) -> Result { match value.unit { StyleValueUnit::Length => Ok(core::LengthPercentage::Length(value.value)), StyleValueUnit::Percent => Ok(core::LengthPercentage::Percent(value.value)), - StyleValueUnit::None => Err(ErrorCode::InvalidNone), - StyleValueUnit::Auto => Err(ErrorCode::InvalidAuto), - StyleValueUnit::MinContent => Err(ErrorCode::InvalidMinContent), - StyleValueUnit::MaxContent => Err(ErrorCode::InvalidMaxContent), - StyleValueUnit::FitContentPx => Err(ErrorCode::InvalidFitContentPx), - StyleValueUnit::FitContentPercent => Err(ErrorCode::InvalidFitContentPercent), - StyleValueUnit::Fr => Err(ErrorCode::InvalidFr), + StyleValueUnit::None => Err(ReturnCode::InvalidNone), + StyleValueUnit::Auto => Err(ReturnCode::InvalidAuto), + StyleValueUnit::MinContent => Err(ReturnCode::InvalidMinContent), + StyleValueUnit::MaxContent => Err(ReturnCode::InvalidMaxContent), + StyleValueUnit::FitContentPx => Err(ReturnCode::InvalidFitContentPx), + StyleValueUnit::FitContentPercent => Err(ReturnCode::InvalidFitContentPercent), + StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), + } + } +} + +impl From for StyleValue { + fn from(value: core::LengthPercentageAuto) -> Self { + match value { + core::LengthPercentageAuto::Points(value) => Self { unit: StyleValueUnit::Points, value }, + core::LengthPercentageAuto::Percent(value) => Self { unit: StyleValueUnit::Percent, value }, + core::LengthPercentageAuto::Auto => Self { unit: StyleValueUnit::Auto, value: 0.0 }, } } } impl TryFrom for core::LengthPercentageAuto { - type Error = ErrorCode; + type Error = ReturnCode; fn try_from(value: StyleValue) -> Result { match value.unit { StyleValueUnit::Auto => Ok(core::LengthPercentageAuto::Auto), StyleValueUnit::Length => Ok(core::LengthPercentageAuto::Length(value.value)), StyleValueUnit::Percent => Ok(core::LengthPercentageAuto::Percent(value.value)), - StyleValueUnit::None => Err(ErrorCode::InvalidNone), - StyleValueUnit::MinContent => Err(ErrorCode::InvalidMinContent), - StyleValueUnit::MaxContent => Err(ErrorCode::InvalidMaxContent), - StyleValueUnit::FitContentPx => Err(ErrorCode::InvalidFitContentPx), - StyleValueUnit::FitContentPercent => Err(ErrorCode::InvalidFitContentPercent), - StyleValueUnit::Fr => Err(ErrorCode::InvalidFr), + StyleValueUnit::None => Err(ReturnCode::InvalidNone), + StyleValueUnit::MinContent => Err(ReturnCode::InvalidMinContent), + StyleValueUnit::MaxContent => Err(ReturnCode::InvalidMaxContent), + StyleValueUnit::FitContentPx => Err(ReturnCode::InvalidFitContentPx), + StyleValueUnit::FitContentPercent => Err(ReturnCode::InvalidFitContentPercent), + StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), } } } +#[repr(C)] +pub struct StyleValueResult { + pub return_code: ReturnCode, + pub value: StyleValue, +} + #[repr(transparent)] pub struct Style { inner: core::Style, @@ -123,6 +148,21 @@ pub fn assert_pointer_address(pointer: *const c_void, pointer_type: &str) { ); } +macro_rules! get_style { + ($raw_style_ptr:expr, $rust_style_ptr:ident, $block:expr) => {{ + assert_pointer_address($raw_style_ptr, "style"); + let $rust_style_ptr = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + + let return_value = $block; + + Box::leak($rust_style_ptr); + StyleValueResult { + return_code: ReturnCode::Ok, + value: return_value.into() + } + }}; +} + macro_rules! with_style_mut { ($raw_style_ptr:expr, $rust_style_ptr:ident, $block:expr) => {{ assert_pointer_address($raw_style_ptr, "style"); @@ -131,10 +171,12 @@ macro_rules! with_style_mut { $block; Box::leak($rust_style_ptr); - ErrorCode::Ok + ReturnCode::Ok }}; } +/// Attempt to convert a [`StyleValue`] into a type that implements `TryFrom` +/// In the case of a conversion error, return a [`ReturnCode`]. macro_rules! try_from_value { ($value:expr) => { match $value.try_into() { @@ -144,12 +186,33 @@ macro_rules! try_from_value { }; } +/// Attempt to convert a [`StyleValueUnit`] and a `f32` into a type that implements `TryFrom` +/// In the case of a conversion error, return a [`ReturnCode`]. macro_rules! try_from_raw { ($unit:expr, $value:expr) => { try_from_value!(StyleValue::from_raw($unit, $value)) }; } +/* API variant with single parameter that combines "value" and "unit" into a `StyleValue` struct */ + +/// Function to get the margin_top value +#[no_mangle] +pub extern "C" fn Taffy_get_margin_top( + raw_style: *const c_void, +) -> StyleValueResult { + get_style!(raw_style, style, style.inner.margin.top) +} + +/// Function to set the margin_top value +#[no_mangle] +pub extern "C" fn Taffy_set_margin_top( + raw_style: *mut c_void, + value: StyleValue, +) -> ReturnCode { + with_style_mut!(raw_style, style, style.inner.margin.top = try_from_value!(value)) +} + /// Function to set all the value of margin #[no_mangle] @@ -159,7 +222,7 @@ pub extern "C" fn Taffy_set_margin_trbl( right: StyleValue, bottom: StyleValue, left: StyleValue, -) -> ErrorCode { +) -> ReturnCode { with_style_mut!(raw_style, style, { style.inner.margin = Rect { top: try_from_value!(top), @@ -170,13 +233,24 @@ pub extern "C" fn Taffy_set_margin_trbl( }) } -/// Function to set all the value of margin +/* API variant with seperate "value" and "unit" parameters */ + +/// Function to get the margin_top value #[no_mangle] -pub extern "C" fn Taffy_set_margin_top( +pub extern "C" fn Taffy_get_padding_top( + raw_style: *const c_void, +) -> StyleValueResult { + get_style!(raw_style, style, style.inner.padding.top) +} + +/// Function to set the padding_top value +#[no_mangle] +pub extern "C" fn Taffy_set_padding_top( raw_style: *mut c_void, - value: StyleValue, -) -> ErrorCode { - with_style_mut!(raw_style, style, style.inner.margin.top = try_from_value!(value)) + value: f32, + unit: StyleValueUnit, +) -> ReturnCode { + with_style_mut!(raw_style, style, style.inner.padding.top = try_from_raw!(unit, value)) } /// Function to set all the value of padding @@ -191,7 +265,7 @@ pub extern "C" fn Taffy_set_padding_trbl( left_value_unit: StyleValueUnit, bottom_value: f32, bottom_value_unit: StyleValueUnit, -) -> ErrorCode { +) -> ReturnCode { with_style_mut!(raw_style, style, { style.inner.padding = Rect { top: try_from_raw!(top_value_unit, top_value), @@ -202,12 +276,4 @@ pub extern "C" fn Taffy_set_padding_trbl( }) } -/// Function to set all the value of margin -#[no_mangle] -pub extern "C" fn Taffy_set_padding_top( - raw_style: *mut c_void, - value: f32, - unit: StyleValueUnit, -) -> ErrorCode { - with_style_mut!(raw_style, style, style.inner.padding.top = try_from_raw!(unit, value)) -} + From 0ad8c377f8ea2bae11f3c31c43d1166de440a363 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 02:24:40 +0000 Subject: [PATCH 05/57] Return error code rather than panicking on null style pointer --- src/ffi.rs | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/ffi.rs b/src/ffi.rs index 3a1cc155a..e1311668d 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -9,6 +9,8 @@ use std::ffi::c_void; pub enum ReturnCode { /// Operation suceeded Ok, + /// The style pointer passed was null + NullStylePointer, /// A None unit was specified but is not valid in this context InvalidNone, /// A Length unit was specified but is not valid in this context @@ -134,23 +136,36 @@ pub struct StyleValueResult { pub value: StyleValue, } +impl From for StyleValueResult { + fn from(return_code: ReturnCode) -> Self { + Self { return_code, value: StyleValue { unit: StyleValueUnit::None, value: 0.0 }} + } +} + #[repr(transparent)] pub struct Style { inner: core::Style, } -pub fn assert_pointer_address(pointer: *const c_void, pointer_type: &str) { +pub fn assert_pointer_address(pointer: *const c_void) { assert_ne!( pointer, std::ptr::null(), - "Invalid {:} pointer address", - pointer_type + "Invalid style pointer address" ); } +macro_rules! assert_style_pointer_is_non_null { + ($raw_style_ptr:expr) => {{ + if ($raw_style_ptr as *const c_void) == std::ptr::null() { + return ReturnCode::NullStylePointer.into(); + } + }}; +} + macro_rules! get_style { ($raw_style_ptr:expr, $rust_style_ptr:ident, $block:expr) => {{ - assert_pointer_address($raw_style_ptr, "style"); + assert_style_pointer_is_non_null!($raw_style_ptr); let $rust_style_ptr = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; let return_value = $block; @@ -165,7 +180,7 @@ macro_rules! get_style { macro_rules! with_style_mut { ($raw_style_ptr:expr, $rust_style_ptr:ident, $block:expr) => {{ - assert_pointer_address($raw_style_ptr, "style"); + assert_style_pointer_is_non_null!($raw_style_ptr); let mut $rust_style_ptr = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; $block; From ab9289bc03a1c4eb1292e87cad720d4e2f89daf2 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 02:24:50 +0000 Subject: [PATCH 06/57] cargo fmt --- src/ffi.rs | 41 ++++++++++------------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) diff --git a/src/ffi.rs b/src/ffi.rs index e1311668d..324829902 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -1,7 +1,7 @@ //! Types for C FFI +use crate::geometry::Rect; use crate::prelude as core; -use crate::geometry::{Rect}; use std::ffi::c_void; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -97,7 +97,7 @@ impl TryFrom for core::LengthPercentage { StyleValueUnit::MaxContent => Err(ReturnCode::InvalidMaxContent), StyleValueUnit::FitContentPx => Err(ReturnCode::InvalidFitContentPx), StyleValueUnit::FitContentPercent => Err(ReturnCode::InvalidFitContentPercent), - StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), + StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), } } } @@ -125,7 +125,7 @@ impl TryFrom for core::LengthPercentageAuto { StyleValueUnit::MaxContent => Err(ReturnCode::InvalidMaxContent), StyleValueUnit::FitContentPx => Err(ReturnCode::InvalidFitContentPx), StyleValueUnit::FitContentPercent => Err(ReturnCode::InvalidFitContentPercent), - StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), + StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), } } } @@ -138,7 +138,7 @@ pub struct StyleValueResult { impl From for StyleValueResult { fn from(return_code: ReturnCode) -> Self { - Self { return_code, value: StyleValue { unit: StyleValueUnit::None, value: 0.0 }} + Self { return_code, value: StyleValue { unit: StyleValueUnit::None, value: 0.0 } } } } @@ -148,11 +148,7 @@ pub struct Style { } pub fn assert_pointer_address(pointer: *const c_void) { - assert_ne!( - pointer, - std::ptr::null(), - "Invalid style pointer address" - ); + assert_ne!(pointer, std::ptr::null(), "Invalid style pointer address"); } macro_rules! assert_style_pointer_is_non_null { @@ -171,10 +167,7 @@ macro_rules! get_style { let return_value = $block; Box::leak($rust_style_ptr); - StyleValueResult { - return_code: ReturnCode::Ok, - value: return_value.into() - } + StyleValueResult { return_code: ReturnCode::Ok, value: return_value.into() } }}; } @@ -213,22 +206,16 @@ macro_rules! try_from_raw { /// Function to get the margin_top value #[no_mangle] -pub extern "C" fn Taffy_get_margin_top( - raw_style: *const c_void, -) -> StyleValueResult { +pub extern "C" fn Taffy_get_margin_top(raw_style: *const c_void) -> StyleValueResult { get_style!(raw_style, style, style.inner.margin.top) } /// Function to set the margin_top value #[no_mangle] -pub extern "C" fn Taffy_set_margin_top( - raw_style: *mut c_void, - value: StyleValue, -) -> ReturnCode { +pub extern "C" fn Taffy_set_margin_top(raw_style: *mut c_void, value: StyleValue) -> ReturnCode { with_style_mut!(raw_style, style, style.inner.margin.top = try_from_value!(value)) } - /// Function to set all the value of margin #[no_mangle] pub extern "C" fn Taffy_set_margin_trbl( @@ -252,19 +239,13 @@ pub extern "C" fn Taffy_set_margin_trbl( /// Function to get the margin_top value #[no_mangle] -pub extern "C" fn Taffy_get_padding_top( - raw_style: *const c_void, -) -> StyleValueResult { +pub extern "C" fn Taffy_get_padding_top(raw_style: *const c_void) -> StyleValueResult { get_style!(raw_style, style, style.inner.padding.top) } /// Function to set the padding_top value #[no_mangle] -pub extern "C" fn Taffy_set_padding_top( - raw_style: *mut c_void, - value: f32, - unit: StyleValueUnit, -) -> ReturnCode { +pub extern "C" fn Taffy_set_padding_top(raw_style: *mut c_void, value: f32, unit: StyleValueUnit) -> ReturnCode { with_style_mut!(raw_style, style, style.inner.padding.top = try_from_raw!(unit, value)) } @@ -290,5 +271,3 @@ pub extern "C" fn Taffy_set_padding_trbl( }; }) } - - From ae72e491cc0573cb7fc08daf730ba5e68a09a335 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 02:34:36 +0000 Subject: [PATCH 07/57] Documentation get_style and with_style_mut macros --- src/ffi.rs | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/ffi.rs b/src/ffi.rs index 324829902..d660fee36 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -151,6 +151,8 @@ pub fn assert_pointer_address(pointer: *const c_void) { assert_ne!(pointer, std::ptr::null(), "Invalid style pointer address"); } + +/// Return [`ReturnCode::NullStylePointer`] if the passed pointer is null macro_rules! assert_style_pointer_is_non_null { ($raw_style_ptr:expr) => {{ if ($raw_style_ptr as *const c_void) == std::ptr::null() { @@ -159,26 +161,34 @@ macro_rules! assert_style_pointer_is_non_null { }}; } +/// Assert that the passed raw style pointer is non-null +/// Then give the passed expression access to the value of the inner [`core::Style`] struct pointed to by the raw style pointer +/// Return whatever the expression evaluates to wrapped in a [`StyleValueResult`] if the expression does not interally return. macro_rules! get_style { - ($raw_style_ptr:expr, $rust_style_ptr:ident, $block:expr) => {{ + ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ assert_style_pointer_is_non_null!($raw_style_ptr); - let $rust_style_ptr = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + let style_box = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + let $style_ident = &style_box.inner; let return_value = $block; - Box::leak($rust_style_ptr); + Box::leak(style_box); StyleValueResult { return_code: ReturnCode::Ok, value: return_value.into() } }}; } +/// Assert that the passed raw style pointer is non-null +/// Then give the passed expression mutable access to the value of the inner [`core::Style`] struct pointed to by the raw style pointer +/// Return [`ReturnCode::Ok`] if the expression does not internally return. macro_rules! with_style_mut { - ($raw_style_ptr:expr, $rust_style_ptr:ident, $block:expr) => {{ + ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ assert_style_pointer_is_non_null!($raw_style_ptr); - let mut $rust_style_ptr = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + let mut style_box = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + let $style_ident = &mut style_box.inner; $block; - Box::leak($rust_style_ptr); + Box::leak(style_box); ReturnCode::Ok }}; } @@ -207,13 +217,13 @@ macro_rules! try_from_raw { /// Function to get the margin_top value #[no_mangle] pub extern "C" fn Taffy_get_margin_top(raw_style: *const c_void) -> StyleValueResult { - get_style!(raw_style, style, style.inner.margin.top) + get_style!(raw_style, style, style.margin.top) } /// Function to set the margin_top value #[no_mangle] pub extern "C" fn Taffy_set_margin_top(raw_style: *mut c_void, value: StyleValue) -> ReturnCode { - with_style_mut!(raw_style, style, style.inner.margin.top = try_from_value!(value)) + with_style_mut!(raw_style, style, style.margin.top = try_from_value!(value)) } /// Function to set all the value of margin @@ -226,7 +236,7 @@ pub extern "C" fn Taffy_set_margin_trbl( left: StyleValue, ) -> ReturnCode { with_style_mut!(raw_style, style, { - style.inner.margin = Rect { + style.margin = Rect { top: try_from_value!(top), right: try_from_value!(right), bottom: try_from_value!(bottom), @@ -240,13 +250,13 @@ pub extern "C" fn Taffy_set_margin_trbl( /// Function to get the margin_top value #[no_mangle] pub extern "C" fn Taffy_get_padding_top(raw_style: *const c_void) -> StyleValueResult { - get_style!(raw_style, style, style.inner.padding.top) + get_style!(raw_style, style, style.padding.top) } /// Function to set the padding_top value #[no_mangle] pub extern "C" fn Taffy_set_padding_top(raw_style: *mut c_void, value: f32, unit: StyleValueUnit) -> ReturnCode { - with_style_mut!(raw_style, style, style.inner.padding.top = try_from_raw!(unit, value)) + with_style_mut!(raw_style, style, style.padding.top = try_from_raw!(unit, value)) } /// Function to set all the value of padding @@ -263,7 +273,7 @@ pub extern "C" fn Taffy_set_padding_trbl( bottom_value_unit: StyleValueUnit, ) -> ReturnCode { with_style_mut!(raw_style, style, { - style.inner.padding = Rect { + style.padding = Rect { top: try_from_raw!(top_value_unit, top_value), right: try_from_raw!(right_value_unit, right_value), bottom: try_from_raw!(bottom_value_unit, bottom_value), From 31bfebbc82a37dab266c20e3987da0b75f3ed4d0 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 02:42:52 +0000 Subject: [PATCH 08/57] Split FFI into multiple files --- src/ffi.rs | 283 ----------------------------------------------- src/ffi/api.rs | 136 +++++++++++++++++++++++ src/ffi/error.rs | 48 ++++++++ src/ffi/mod.rs | 7 ++ src/ffi/value.rs | 104 +++++++++++++++++ 5 files changed, 295 insertions(+), 283 deletions(-) delete mode 100644 src/ffi.rs create mode 100644 src/ffi/api.rs create mode 100644 src/ffi/error.rs create mode 100644 src/ffi/mod.rs create mode 100644 src/ffi/value.rs diff --git a/src/ffi.rs b/src/ffi.rs deleted file mode 100644 index d660fee36..000000000 --- a/src/ffi.rs +++ /dev/null @@ -1,283 +0,0 @@ -//! Types for C FFI - -use crate::geometry::Rect; -use crate::prelude as core; -use std::ffi::c_void; - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] -pub enum ReturnCode { - /// Operation suceeded - Ok, - /// The style pointer passed was null - NullStylePointer, - /// A None unit was specified but is not valid in this context - InvalidNone, - /// A Length unit was specified but is not valid in this context - InvalidLength, - /// A Percent unit was specified but is not valid in this context - InvalidPercent, - /// A MinContent unit was specified but is not valid in this context - InvalidMinContent, - /// A MaxContent unit was specified but is not valid in this context - InvalidMaxContent, - /// A FitContentPx unit was specified but is not valid in this context - InvalidFitContentPx, - /// A FitContentPercent unit was specified but is not valid in this context - InvalidFitContentPercent, - /// An Auto unit was specified but is not valid in this context - InvalidAuto, - /// An Fr unit was specified but is not valid in this context - InvalidFr, - /// A NaN value was specified but is not valid in this context - UnexpectedNaN, - /// A infinite value was specified but is not valid in this context - UnexpectedInfinity, - /// A negative value was specified but is not valid in this context - UnexpectedNegative, -} - -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] -pub enum StyleValueUnit { - /// A none value (used to unset optional fields) - None, - /// Fixed Length (pixel) value - Length, - /// Percentage value - Percent, - /// Min-content size - MinContent, - /// Max-content size - MaxContent, - /// fit-content() function with a pixel limit - FitContentPx, - /// fit-content() function with a percentage limit - FitContentPercent, - /// Automatic values - Auto, - /// fr unit - Fr, -} - -#[derive(Debug, Clone, Copy, PartialEq)] -#[repr(C)] -pub struct StyleValue { - /// The value. If the unit is variant that doesn't require a value (e.g. Auto) then the value is ignored. - pub value: f32, - pub unit: StyleValueUnit, -} - -impl StyleValue { - #[inline(always)] - fn from_raw(unit: StyleValueUnit, value: f32) -> Self { - Self { unit, value } - } -} - -impl From for StyleValue { - fn from(value: core::LengthPercentage) -> Self { - match value { - core::LengthPercentage::Points(value) => Self { unit: StyleValueUnit::Points, value }, - core::LengthPercentage::Percent(value) => Self { unit: StyleValueUnit::Percent, value }, - } - } -} - -impl TryFrom for core::LengthPercentage { - type Error = ReturnCode; - - fn try_from(value: StyleValue) -> Result { - match value.unit { - StyleValueUnit::Length => Ok(core::LengthPercentage::Length(value.value)), - StyleValueUnit::Percent => Ok(core::LengthPercentage::Percent(value.value)), - StyleValueUnit::None => Err(ReturnCode::InvalidNone), - StyleValueUnit::Auto => Err(ReturnCode::InvalidAuto), - StyleValueUnit::MinContent => Err(ReturnCode::InvalidMinContent), - StyleValueUnit::MaxContent => Err(ReturnCode::InvalidMaxContent), - StyleValueUnit::FitContentPx => Err(ReturnCode::InvalidFitContentPx), - StyleValueUnit::FitContentPercent => Err(ReturnCode::InvalidFitContentPercent), - StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), - } - } -} - -impl From for StyleValue { - fn from(value: core::LengthPercentageAuto) -> Self { - match value { - core::LengthPercentageAuto::Points(value) => Self { unit: StyleValueUnit::Points, value }, - core::LengthPercentageAuto::Percent(value) => Self { unit: StyleValueUnit::Percent, value }, - core::LengthPercentageAuto::Auto => Self { unit: StyleValueUnit::Auto, value: 0.0 }, - } - } -} - -impl TryFrom for core::LengthPercentageAuto { - type Error = ReturnCode; - - fn try_from(value: StyleValue) -> Result { - match value.unit { - StyleValueUnit::Auto => Ok(core::LengthPercentageAuto::Auto), - StyleValueUnit::Length => Ok(core::LengthPercentageAuto::Length(value.value)), - StyleValueUnit::Percent => Ok(core::LengthPercentageAuto::Percent(value.value)), - StyleValueUnit::None => Err(ReturnCode::InvalidNone), - StyleValueUnit::MinContent => Err(ReturnCode::InvalidMinContent), - StyleValueUnit::MaxContent => Err(ReturnCode::InvalidMaxContent), - StyleValueUnit::FitContentPx => Err(ReturnCode::InvalidFitContentPx), - StyleValueUnit::FitContentPercent => Err(ReturnCode::InvalidFitContentPercent), - StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), - } - } -} - -#[repr(C)] -pub struct StyleValueResult { - pub return_code: ReturnCode, - pub value: StyleValue, -} - -impl From for StyleValueResult { - fn from(return_code: ReturnCode) -> Self { - Self { return_code, value: StyleValue { unit: StyleValueUnit::None, value: 0.0 } } - } -} - -#[repr(transparent)] -pub struct Style { - inner: core::Style, -} - -pub fn assert_pointer_address(pointer: *const c_void) { - assert_ne!(pointer, std::ptr::null(), "Invalid style pointer address"); -} - - -/// Return [`ReturnCode::NullStylePointer`] if the passed pointer is null -macro_rules! assert_style_pointer_is_non_null { - ($raw_style_ptr:expr) => {{ - if ($raw_style_ptr as *const c_void) == std::ptr::null() { - return ReturnCode::NullStylePointer.into(); - } - }}; -} - -/// Assert that the passed raw style pointer is non-null -/// Then give the passed expression access to the value of the inner [`core::Style`] struct pointed to by the raw style pointer -/// Return whatever the expression evaluates to wrapped in a [`StyleValueResult`] if the expression does not interally return. -macro_rules! get_style { - ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ - assert_style_pointer_is_non_null!($raw_style_ptr); - let style_box = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; - let $style_ident = &style_box.inner; - - let return_value = $block; - - Box::leak(style_box); - StyleValueResult { return_code: ReturnCode::Ok, value: return_value.into() } - }}; -} - -/// Assert that the passed raw style pointer is non-null -/// Then give the passed expression mutable access to the value of the inner [`core::Style`] struct pointed to by the raw style pointer -/// Return [`ReturnCode::Ok`] if the expression does not internally return. -macro_rules! with_style_mut { - ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ - assert_style_pointer_is_non_null!($raw_style_ptr); - let mut style_box = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; - let $style_ident = &mut style_box.inner; - - $block; - - Box::leak(style_box); - ReturnCode::Ok - }}; -} - -/// Attempt to convert a [`StyleValue`] into a type that implements `TryFrom` -/// In the case of a conversion error, return a [`ReturnCode`]. -macro_rules! try_from_value { - ($value:expr) => { - match $value.try_into() { - Ok(val) => val, - Err(err) => return err, - } - }; -} - -/// Attempt to convert a [`StyleValueUnit`] and a `f32` into a type that implements `TryFrom` -/// In the case of a conversion error, return a [`ReturnCode`]. -macro_rules! try_from_raw { - ($unit:expr, $value:expr) => { - try_from_value!(StyleValue::from_raw($unit, $value)) - }; -} - -/* API variant with single parameter that combines "value" and "unit" into a `StyleValue` struct */ - -/// Function to get the margin_top value -#[no_mangle] -pub extern "C" fn Taffy_get_margin_top(raw_style: *const c_void) -> StyleValueResult { - get_style!(raw_style, style, style.margin.top) -} - -/// Function to set the margin_top value -#[no_mangle] -pub extern "C" fn Taffy_set_margin_top(raw_style: *mut c_void, value: StyleValue) -> ReturnCode { - with_style_mut!(raw_style, style, style.margin.top = try_from_value!(value)) -} - -/// Function to set all the value of margin -#[no_mangle] -pub extern "C" fn Taffy_set_margin_trbl( - raw_style: *mut c_void, - top: StyleValue, - right: StyleValue, - bottom: StyleValue, - left: StyleValue, -) -> ReturnCode { - with_style_mut!(raw_style, style, { - style.margin = Rect { - top: try_from_value!(top), - right: try_from_value!(right), - bottom: try_from_value!(bottom), - left: try_from_value!(left), - }; - }) -} - -/* API variant with seperate "value" and "unit" parameters */ - -/// Function to get the margin_top value -#[no_mangle] -pub extern "C" fn Taffy_get_padding_top(raw_style: *const c_void) -> StyleValueResult { - get_style!(raw_style, style, style.padding.top) -} - -/// Function to set the padding_top value -#[no_mangle] -pub extern "C" fn Taffy_set_padding_top(raw_style: *mut c_void, value: f32, unit: StyleValueUnit) -> ReturnCode { - with_style_mut!(raw_style, style, style.padding.top = try_from_raw!(unit, value)) -} - -/// Function to set all the value of padding -#[no_mangle] -pub extern "C" fn Taffy_set_padding_trbl( - raw_style: *mut c_void, - top_value: f32, - top_value_unit: StyleValueUnit, - right_value: f32, - right_value_unit: StyleValueUnit, - left_value: f32, - left_value_unit: StyleValueUnit, - bottom_value: f32, - bottom_value_unit: StyleValueUnit, -) -> ReturnCode { - with_style_mut!(raw_style, style, { - style.padding = Rect { - top: try_from_raw!(top_value_unit, top_value), - right: try_from_raw!(right_value_unit, right_value), - bottom: try_from_raw!(bottom_value_unit, bottom_value), - left: try_from_raw!(left_value_unit, left_value), - }; - }) -} diff --git a/src/ffi/api.rs b/src/ffi/api.rs new file mode 100644 index 000000000..7ccaf9099 --- /dev/null +++ b/src/ffi/api.rs @@ -0,0 +1,136 @@ +//! Public API for C FFI + +use crate::geometry::Rect; +use std::ffi::c_void; + +use super::{StyleValueUnit, StyleValue, StyleValueResult, ReturnCode, Style}; + +/// Return [`ReturnCode::NullStylePointer`] if the passed pointer is null +macro_rules! assert_style_pointer_is_non_null { + ($raw_style_ptr:expr) => {{ + if ($raw_style_ptr as *const c_void) == std::ptr::null() { + return ReturnCode::NullStylePointer.into(); + } + }}; +} + +/// Assert that the passed raw style pointer is non-null +/// Then give the passed expression access to the value of the inner [`core::Style`] struct pointed to by the raw style pointer +/// Return whatever the expression evaluates to wrapped in a [`StyleValueResult`] if the expression does not interally return. +macro_rules! get_style { + ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ + assert_style_pointer_is_non_null!($raw_style_ptr); + let style_box = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + let $style_ident = &style_box.inner; + + let return_value = $block; + + Box::leak(style_box); + StyleValueResult { return_code: ReturnCode::Ok, value: return_value.into() } + }}; +} + +/// Assert that the passed raw style pointer is non-null +/// Then give the passed expression mutable access to the value of the inner [`core::Style`] struct pointed to by the raw style pointer +/// Return [`ReturnCode::Ok`] if the expression does not internally return. +macro_rules! with_style_mut { + ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ + assert_style_pointer_is_non_null!($raw_style_ptr); + let mut style_box = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + let $style_ident = &mut style_box.inner; + + $block; + + Box::leak(style_box); + ReturnCode::Ok + }}; +} + +/// Attempt to convert a [`StyleValue`] into a type that implements `TryFrom` +/// In the case of a conversion error, return a [`ReturnCode`]. +macro_rules! try_from_value { + ($value:expr) => { + match $value.try_into() { + Ok(val) => val, + Err(err) => return err, + } + }; +} + +/// Attempt to convert a [`StyleValueUnit`] and a `f32` into a type that implements `TryFrom` +/// In the case of a conversion error, return a [`ReturnCode`]. +macro_rules! try_from_raw { + ($unit:expr, $value:expr) => { + try_from_value!(StyleValue::from_raw($unit, $value)) + }; +} + +/* API variant with single parameter that combines "value" and "unit" into a `StyleValue` struct */ + +/// Function to get the margin_top value +#[no_mangle] +pub extern "C" fn Taffy_get_margin_top(raw_style: *const c_void) -> StyleValueResult { + get_style!(raw_style, style, style.margin.top) +} + +/// Function to set the margin_top value +#[no_mangle] +pub extern "C" fn Taffy_set_margin_top(raw_style: *mut c_void, value: StyleValue) -> ReturnCode { + with_style_mut!(raw_style, style, style.margin.top = try_from_value!(value)) +} + +/// Function to set all the value of margin +#[no_mangle] +pub extern "C" fn Taffy_set_margin_trbl( + raw_style: *mut c_void, + top: StyleValue, + right: StyleValue, + bottom: StyleValue, + left: StyleValue, +) -> ReturnCode { + with_style_mut!(raw_style, style, { + style.margin = Rect { + top: try_from_value!(top), + right: try_from_value!(right), + bottom: try_from_value!(bottom), + left: try_from_value!(left), + }; + }) +} + +/* API variant with seperate "value" and "unit" parameters */ + +/// Function to get the margin_top value +#[no_mangle] +pub extern "C" fn Taffy_get_padding_top(raw_style: *const c_void) -> StyleValueResult { + get_style!(raw_style, style, style.padding.top) +} + +/// Function to set the padding_top value +#[no_mangle] +pub extern "C" fn Taffy_set_padding_top(raw_style: *mut c_void, value: f32, unit: StyleValueUnit) -> ReturnCode { + with_style_mut!(raw_style, style, style.padding.top = try_from_raw!(unit, value)) +} + +/// Function to set all the value of padding +#[no_mangle] +pub extern "C" fn Taffy_set_padding_trbl( + raw_style: *mut c_void, + top_value: f32, + top_value_unit: StyleValueUnit, + right_value: f32, + right_value_unit: StyleValueUnit, + left_value: f32, + left_value_unit: StyleValueUnit, + bottom_value: f32, + bottom_value_unit: StyleValueUnit, +) -> ReturnCode { + with_style_mut!(raw_style, style, { + style.padding = Rect { + top: try_from_raw!(top_value_unit, top_value), + right: try_from_raw!(right_value_unit, right_value), + bottom: try_from_raw!(bottom_value_unit, bottom_value), + left: try_from_raw!(left_value_unit, left_value), + }; + }) +} diff --git a/src/ffi/error.rs b/src/ffi/error.rs new file mode 100644 index 000000000..32aa410af --- /dev/null +++ b/src/ffi/error.rs @@ -0,0 +1,48 @@ +//! Return types for C FFI + +use super::{StyleValueUnit, StyleValue}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum ReturnCode { + /// Operation suceeded + Ok, + /// The style pointer passed was null + NullStylePointer, + /// A None unit was specified but is not valid in this context + InvalidNone, + /// A Points unit was specified but is not valid in this context + InvalidPoints, + /// A Percent unit was specified but is not valid in this context + InvalidPercent, + /// A MinContent unit was specified but is not valid in this context + InvalidMinContent, + /// A MaxContent unit was specified but is not valid in this context + InvalidMaxContent, + /// A FitContentPx unit was specified but is not valid in this context + InvalidFitContentPx, + /// A FitContentPercent unit was specified but is not valid in this context + InvalidFitContentPercent, + /// An Auto unit was specified but is not valid in this context + InvalidAuto, + /// An Fr unit was specified but is not valid in this context + InvalidFr, + /// A NaN value was specified but is not valid in this context + UnexpectedNaN, + /// A infinite value was specified but is not valid in this context + UnexpectedInfinity, + /// A negative value was specified but is not valid in this context + UnexpectedNegative, +} + +#[repr(C)] +pub struct StyleValueResult { + pub return_code: ReturnCode, + pub value: StyleValue, +} + +impl From for StyleValueResult { + fn from(return_code: ReturnCode) -> Self { + Self { return_code, value: StyleValue { unit: StyleValueUnit::None, value: 0.0 } } + } +} \ No newline at end of file diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs new file mode 100644 index 000000000..ecd1e7a55 --- /dev/null +++ b/src/ffi/mod.rs @@ -0,0 +1,7 @@ +mod error; +mod value; +mod api; + +pub use error::*; +pub use value::*; +pub use api::*; \ No newline at end of file diff --git a/src/ffi/value.rs b/src/ffi/value.rs new file mode 100644 index 000000000..6040b946a --- /dev/null +++ b/src/ffi/value.rs @@ -0,0 +1,104 @@ +//! Values types for C FFI + +use crate::prelude as core; + +use super::{ReturnCode}; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(u8)] +pub enum StyleValueUnit { + /// A none value (used to unset optional fields) + None, + /// Fixed Length (pixel) value + Length, + /// Percentage value + Percent, + /// Min-content size + MinContent, + /// Max-content size + MaxContent, + /// fit-content() function with a pixel limit + FitContentPx, + /// fit-content() function with a percentage limit + FitContentPercent, + /// Automatic values + Auto, + /// fr unit + Fr, +} + +#[derive(Debug, Clone, Copy, PartialEq)] +#[repr(C)] +pub struct StyleValue { + /// The value. If the unit is variant that doesn't require a value (e.g. Auto) then the value is ignored. + pub value: f32, + pub unit: StyleValueUnit, +} + +impl StyleValue { + #[inline(always)] + pub fn from_raw(unit: StyleValueUnit, value: f32) -> Self { + Self { unit, value } + } +} + +impl From for StyleValue { + fn from(value: core::LengthPercentage) -> Self { + match value { + core::LengthPercentage::Length(value) => Self { unit: StyleValueUnit::Length, value }, + core::LengthPercentage::Percent(value) => Self { unit: StyleValueUnit::Percent, value }, + } + } +} + +impl TryFrom for core::LengthPercentage { + type Error = ReturnCode; + + fn try_from(value: StyleValue) -> Result { + match value.unit { + StyleValueUnit::Length => Ok(core::LengthPercentage::Length(value.value)), + StyleValueUnit::Percent => Ok(core::LengthPercentage::Percent(value.value)), + StyleValueUnit::None => Err(ReturnCode::InvalidNone), + StyleValueUnit::Auto => Err(ReturnCode::InvalidAuto), + StyleValueUnit::MinContent => Err(ReturnCode::InvalidMinContent), + StyleValueUnit::MaxContent => Err(ReturnCode::InvalidMaxContent), + StyleValueUnit::FitContentPx => Err(ReturnCode::InvalidFitContentPx), + StyleValueUnit::FitContentPercent => Err(ReturnCode::InvalidFitContentPercent), + StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), + } + } +} + +impl From for StyleValue { + fn from(value: core::LengthPercentageAuto) -> Self { + match value { + core::LengthPercentageAuto::Length(value) => Self { unit: StyleValueUnit::Length, value }, + core::LengthPercentageAuto::Percent(value) => Self { unit: StyleValueUnit::Percent, value }, + core::LengthPercentageAuto::Auto => Self { unit: StyleValueUnit::Auto, value: 0.0 }, + } + } +} + +impl TryFrom for core::LengthPercentageAuto { + type Error = ReturnCode; + + fn try_from(value: StyleValue) -> Result { + match value.unit { + StyleValueUnit::Auto => Ok(core::LengthPercentageAuto::Auto), + StyleValueUnit::Length => Ok(core::LengthPercentageAuto::Length(value.value)), + StyleValueUnit::Percent => Ok(core::LengthPercentageAuto::Percent(value.value)), + StyleValueUnit::None => Err(ReturnCode::InvalidNone), + StyleValueUnit::MinContent => Err(ReturnCode::InvalidMinContent), + StyleValueUnit::MaxContent => Err(ReturnCode::InvalidMaxContent), + StyleValueUnit::FitContentPx => Err(ReturnCode::InvalidFitContentPx), + StyleValueUnit::FitContentPercent => Err(ReturnCode::InvalidFitContentPercent), + StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), + } + } +} + + +#[repr(transparent)] +pub struct Style { + pub(crate) inner: core::Style, +} \ No newline at end of file From ff7fe6caf6cbf8dd42e5b6e22f134eeff22161ae Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 02:48:33 +0000 Subject: [PATCH 09/57] Rename api module to style --- src/ffi/error.rs | 4 ++-- src/ffi/mod.rs | 4 ++-- src/ffi/{api.rs => style.rs} | 10 +++++++++- src/ffi/value.rs | 8 +------- 4 files changed, 14 insertions(+), 12 deletions(-) rename src/ffi/{api.rs => style.rs} (93%) diff --git a/src/ffi/error.rs b/src/ffi/error.rs index 32aa410af..5b26eece7 100644 --- a/src/ffi/error.rs +++ b/src/ffi/error.rs @@ -1,6 +1,6 @@ //! Return types for C FFI -use super::{StyleValueUnit, StyleValue}; +use super::{StyleValue, StyleValueUnit}; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] @@ -45,4 +45,4 @@ impl From for StyleValueResult { fn from(return_code: ReturnCode) -> Self { Self { return_code, value: StyleValue { unit: StyleValueUnit::None, value: 0.0 } } } -} \ No newline at end of file +} diff --git a/src/ffi/mod.rs b/src/ffi/mod.rs index ecd1e7a55..ed2144adc 100644 --- a/src/ffi/mod.rs +++ b/src/ffi/mod.rs @@ -1,7 +1,7 @@ mod error; +mod style; mod value; -mod api; pub use error::*; +pub use style::*; pub use value::*; -pub use api::*; \ No newline at end of file diff --git a/src/ffi/api.rs b/src/ffi/style.rs similarity index 93% rename from src/ffi/api.rs rename to src/ffi/style.rs index 7ccaf9099..92674e246 100644 --- a/src/ffi/api.rs +++ b/src/ffi/style.rs @@ -1,9 +1,17 @@ //! Public API for C FFI use crate::geometry::Rect; +use crate::prelude as core; use std::ffi::c_void; -use super::{StyleValueUnit, StyleValue, StyleValueResult, ReturnCode, Style}; +use super::{ReturnCode, StyleValue, StyleValueResult, StyleValueUnit}; + +/// A wrapper around [`core::Style`] which allows the individual style properties to be accessed +/// via FFI-friendly getter and setter functions +#[repr(transparent)] +pub struct Style { + pub(crate) inner: core::Style, +} /// Return [`ReturnCode::NullStylePointer`] if the passed pointer is null macro_rules! assert_style_pointer_is_non_null { diff --git a/src/ffi/value.rs b/src/ffi/value.rs index 6040b946a..147414f0f 100644 --- a/src/ffi/value.rs +++ b/src/ffi/value.rs @@ -2,7 +2,7 @@ use crate::prelude as core; -use super::{ReturnCode}; +use super::ReturnCode; #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] @@ -96,9 +96,3 @@ impl TryFrom for core::LengthPercentageAuto { } } } - - -#[repr(transparent)] -pub struct Style { - pub(crate) inner: core::Style, -} \ No newline at end of file From ca2c22300f4eda56efb473e29877d5b3cdf96e63 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 02:49:30 +0000 Subject: [PATCH 10/57] Make style getters/setters unsafe --- src/ffi/style.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/ffi/style.rs b/src/ffi/style.rs index 92674e246..2cba70194 100644 --- a/src/ffi/style.rs +++ b/src/ffi/style.rs @@ -77,19 +77,19 @@ macro_rules! try_from_raw { /// Function to get the margin_top value #[no_mangle] -pub extern "C" fn Taffy_get_margin_top(raw_style: *const c_void) -> StyleValueResult { +pub unsafe extern "C" fn Taffy_get_margin_top(raw_style: *const c_void) -> StyleValueResult { get_style!(raw_style, style, style.margin.top) } /// Function to set the margin_top value #[no_mangle] -pub extern "C" fn Taffy_set_margin_top(raw_style: *mut c_void, value: StyleValue) -> ReturnCode { +pub unsafe extern "C" fn Taffy_set_margin_top(raw_style: *mut c_void, value: StyleValue) -> ReturnCode { with_style_mut!(raw_style, style, style.margin.top = try_from_value!(value)) } /// Function to set all the value of margin #[no_mangle] -pub extern "C" fn Taffy_set_margin_trbl( +pub unsafe extern "C" fn Taffy_set_margin_trbl( raw_style: *mut c_void, top: StyleValue, right: StyleValue, @@ -110,19 +110,19 @@ pub extern "C" fn Taffy_set_margin_trbl( /// Function to get the margin_top value #[no_mangle] -pub extern "C" fn Taffy_get_padding_top(raw_style: *const c_void) -> StyleValueResult { +pub unsafe extern "C" fn Taffy_get_padding_top(raw_style: *const c_void) -> StyleValueResult { get_style!(raw_style, style, style.padding.top) } /// Function to set the padding_top value #[no_mangle] -pub extern "C" fn Taffy_set_padding_top(raw_style: *mut c_void, value: f32, unit: StyleValueUnit) -> ReturnCode { +pub unsafe extern "C" fn Taffy_set_padding_top(raw_style: *mut c_void, value: f32, unit: StyleValueUnit) -> ReturnCode { with_style_mut!(raw_style, style, style.padding.top = try_from_raw!(unit, value)) } /// Function to set all the value of padding #[no_mangle] -pub extern "C" fn Taffy_set_padding_trbl( +pub unsafe extern "C" fn Taffy_set_padding_trbl( raw_style: *mut c_void, top_value: f32, top_value_unit: StyleValueUnit, From 54fc2dd19edb3a0fdd0edf1bfff8ae1fabb93280 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 03:39:59 +0000 Subject: [PATCH 11/57] Add grid placement APIs --- src/ffi/error.rs | 43 ++++++++++++++++++++++++++++++++++++++++--- src/ffi/style.rs | 19 ++++++++++++++++--- src/ffi/value.rs | 22 ++++++++++++++++++++++ src/style/grid.rs | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 111 insertions(+), 6 deletions(-) diff --git a/src/ffi/error.rs b/src/ffi/error.rs index 5b26eece7..c5da261c9 100644 --- a/src/ffi/error.rs +++ b/src/ffi/error.rs @@ -1,6 +1,12 @@ //! Return types for C FFI -use super::{StyleValue, StyleValueUnit}; +use super::{StyleValue, StyleValueUnit, GridPlacement}; + +pub (crate) trait TaffyFFIResult { + type Value; + fn from_value(value: Self::Value) -> Self; + fn from_return_code(return_code: ReturnCode) -> Self; +} #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(u8)] @@ -35,14 +41,45 @@ pub enum ReturnCode { UnexpectedNegative, } +impl TaffyFFIResult for ReturnCode { + type Value = ReturnCode; + fn from_value(value: Self::Value) -> Self { + value + } + fn from_return_code(return_code: ReturnCode) -> Self { + return_code + } +} + #[repr(C)] pub struct StyleValueResult { pub return_code: ReturnCode, pub value: StyleValue, } -impl From for StyleValueResult { - fn from(return_code: ReturnCode) -> Self { +impl TaffyFFIResult for StyleValueResult { + type Value = StyleValue; + fn from_value(value: Self::Value) -> Self { + Self { return_code: ReturnCode::Ok, value } + } + fn from_return_code(return_code: ReturnCode) -> Self { Self { return_code, value: StyleValue { unit: StyleValueUnit::None, value: 0.0 } } } } + + +#[repr(C)] +pub struct GridPlacementResult { + pub return_code: ReturnCode, + pub value: GridPlacement, +} + +impl TaffyFFIResult for GridPlacementResult { + type Value = GridPlacement; + fn from_value(value: Self::Value) -> Self { + Self { return_code: ReturnCode::Ok, value } + } + fn from_return_code(return_code: ReturnCode) -> Self { + Self { return_code, value: GridPlacement { start: 0, end: 0, span: 0 } } + } +} diff --git a/src/ffi/style.rs b/src/ffi/style.rs index 2cba70194..2936a24a5 100644 --- a/src/ffi/style.rs +++ b/src/ffi/style.rs @@ -4,7 +4,7 @@ use crate::geometry::Rect; use crate::prelude as core; use std::ffi::c_void; -use super::{ReturnCode, StyleValue, StyleValueResult, StyleValueUnit}; +use super::{GridPlacement, ReturnCode, StyleValue, StyleValueResult, StyleValueUnit, GridPlacementResult, TaffyFFIResult}; /// A wrapper around [`core::Style`] which allows the individual style properties to be accessed /// via FFI-friendly getter and setter functions @@ -17,7 +17,7 @@ pub struct Style { macro_rules! assert_style_pointer_is_non_null { ($raw_style_ptr:expr) => {{ if ($raw_style_ptr as *const c_void) == std::ptr::null() { - return ReturnCode::NullStylePointer.into(); + return TaffyFFIResult::from_return_code(ReturnCode::NullStylePointer); } }}; } @@ -34,7 +34,8 @@ macro_rules! get_style { let return_value = $block; Box::leak(style_box); - StyleValueResult { return_code: ReturnCode::Ok, value: return_value.into() } + + TaffyFFIResult::from_value(return_value.into()) }}; } @@ -142,3 +143,15 @@ pub unsafe extern "C" fn Taffy_set_padding_trbl( }; }) } + +/* Grid APIs */ + +/// Get grid item's column placement +pub fn style_get_grid_column(raw_style: *mut c_void) -> GridPlacementResult { + get_style!(raw_style, style, style.grid_column) +} + +/// Set grid item's column placement +pub fn style_set_grid_column(raw_style: *mut c_void, placement: GridPlacement) -> ReturnCode { + with_style_mut!(raw_style, style, style.grid_column = placement.into()) +} diff --git a/src/ffi/value.rs b/src/ffi/value.rs index 147414f0f..bc571a60f 100644 --- a/src/ffi/value.rs +++ b/src/ffi/value.rs @@ -96,3 +96,25 @@ impl TryFrom for core::LengthPercentageAuto { } } } + +/// For all fields, zero represents not set +#[derive(Debug, Clone, Copy, PartialEq)] +#[repr(C)] +pub struct GridPlacement { + pub start: i16, + pub end: i16, + pub span: u16, +} + +impl From for core::Line { + fn from(placement: GridPlacement) -> Self { + Self::from_raw_parts(placement.start, placement.span, placement.end) + } +} + +impl From> for GridPlacement { + fn from(placement: core::Line) -> Self { + let (start, span, end) = placement.into_raw_parts(); + Self { start, span, end } + } +} diff --git a/src/style/grid.rs b/src/style/grid.rs index 5d77e3593..e5728983f 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -161,6 +161,39 @@ impl Line { end: self.end.into_origin_zero_placement(explicit_track_count), } } + + /// Convert raw values of start, span, and end into a [`GridPlacement`]. + /// Zero is not a valid value for any of the values and is thus used to indicate unset + /// Only 2 of the 3 values should be set. If all 3 are set then `span_value` is ignored. + pub (crate) fn from_raw_parts(start: i16, span_value: u16, end: i16) -> Self { + match (start, span_value, end) { + (0, 0, 0) => auto(), + (start, 0, 0) => Line { start: line(start), end: auto() }, + (0, 0, end) => Line { start: auto(), end: line(end) }, + (0, span_value, 0) => span(span_value), + (start, span_value, 0) => Line { start: line(start), end: span(span_value) }, + (0, span_value, end) => Line { start: auto(), end: line(end) }, + (start, _, end) => Line { start: line(start), end: line(end) }, + } + } + + /// Convert raw values of start, span, and end into a [`GridPlacement`]. + /// Zero is not a valid value for any of the values and is thus used to indicate unset + /// Only 2 of the 3 values should be set. If all 3 are set then `span_value` is ignored. + pub (crate) fn into_raw_parts(self) -> (i16, u16, i16) { + use GenericGridPlacement::*; + match (self.start, self.end) { + (Line(start), Line(end)) => (start.as_i16(), 0, end.as_i16()), + (Line(start), Span(span)) => (start.as_i16(), span, 0), + (Line(start), Auto) => (start.as_i16(), 1, 0), + (Span(span), Line(end)) => (0, span, end.as_i16()), + (Span(span), Span(_)) => (0, span, 0), + (Span(span), Auto) => (0, span, 0), + (Auto, Line(end)) => (0, 1, end.as_i16()), + (Auto, Span(span)) => (0, span, 0), + (Auto, Auto) => (0, 1, 0), + } + } } impl Line { From cc73f281feb021e2bd56f82668641dd5ae2d224f Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Tue, 21 Mar 2023 03:44:40 +0000 Subject: [PATCH 12/57] Prefix style methods with TaffyStyle --- src/ffi/style.rs | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/ffi/style.rs b/src/ffi/style.rs index 2936a24a5..d13614b1b 100644 --- a/src/ffi/style.rs +++ b/src/ffi/style.rs @@ -9,7 +9,7 @@ use super::{GridPlacement, ReturnCode, StyleValue, StyleValueResult, StyleValueU /// A wrapper around [`core::Style`] which allows the individual style properties to be accessed /// via FFI-friendly getter and setter functions #[repr(transparent)] -pub struct Style { +pub struct TaffyStyle { pub(crate) inner: core::Style, } @@ -28,7 +28,7 @@ macro_rules! assert_style_pointer_is_non_null { macro_rules! get_style { ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ assert_style_pointer_is_non_null!($raw_style_ptr); - let style_box = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + let style_box = unsafe { Box::from_raw($raw_style_ptr as *mut TaffyStyle) }; let $style_ident = &style_box.inner; let return_value = $block; @@ -45,7 +45,7 @@ macro_rules! get_style { macro_rules! with_style_mut { ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ assert_style_pointer_is_non_null!($raw_style_ptr); - let mut style_box = unsafe { Box::from_raw($raw_style_ptr as *mut Style) }; + let mut style_box = unsafe { Box::from_raw($raw_style_ptr as *mut TaffyStyle) }; let $style_ident = &mut style_box.inner; $block; @@ -78,19 +78,19 @@ macro_rules! try_from_raw { /// Function to get the margin_top value #[no_mangle] -pub unsafe extern "C" fn Taffy_get_margin_top(raw_style: *const c_void) -> StyleValueResult { +pub unsafe extern "C" fn TaffyStyle_get_margin_top(raw_style: *const c_void) -> StyleValueResult { get_style!(raw_style, style, style.margin.top) } /// Function to set the margin_top value #[no_mangle] -pub unsafe extern "C" fn Taffy_set_margin_top(raw_style: *mut c_void, value: StyleValue) -> ReturnCode { +pub unsafe extern "C" fn TaffyStyle_set_margin_top(raw_style: *mut c_void, value: StyleValue) -> ReturnCode { with_style_mut!(raw_style, style, style.margin.top = try_from_value!(value)) } /// Function to set all the value of margin #[no_mangle] -pub unsafe extern "C" fn Taffy_set_margin_trbl( +pub unsafe extern "C" fn TaffyStyle_set_margin_trbl( raw_style: *mut c_void, top: StyleValue, right: StyleValue, @@ -111,19 +111,19 @@ pub unsafe extern "C" fn Taffy_set_margin_trbl( /// Function to get the margin_top value #[no_mangle] -pub unsafe extern "C" fn Taffy_get_padding_top(raw_style: *const c_void) -> StyleValueResult { +pub unsafe extern "C" fn TaffyStyle_get_padding_top(raw_style: *const c_void) -> StyleValueResult { get_style!(raw_style, style, style.padding.top) } /// Function to set the padding_top value #[no_mangle] -pub unsafe extern "C" fn Taffy_set_padding_top(raw_style: *mut c_void, value: f32, unit: StyleValueUnit) -> ReturnCode { +pub unsafe extern "C" fn TaffyStyle_set_padding_top(raw_style: *mut c_void, value: f32, unit: StyleValueUnit) -> ReturnCode { with_style_mut!(raw_style, style, style.padding.top = try_from_raw!(unit, value)) } /// Function to set all the value of padding #[no_mangle] -pub unsafe extern "C" fn Taffy_set_padding_trbl( +pub unsafe extern "C" fn TaffyStyle_set_padding_trbl( raw_style: *mut c_void, top_value: f32, top_value_unit: StyleValueUnit, @@ -147,11 +147,13 @@ pub unsafe extern "C" fn Taffy_set_padding_trbl( /* Grid APIs */ /// Get grid item's column placement -pub fn style_get_grid_column(raw_style: *mut c_void) -> GridPlacementResult { +#[no_mangle] +pub unsafe extern "C" fn TaffyStyle_get_grid_column(raw_style: *mut c_void) -> GridPlacementResult { get_style!(raw_style, style, style.grid_column) } /// Set grid item's column placement -pub fn style_set_grid_column(raw_style: *mut c_void, placement: GridPlacement) -> ReturnCode { +#[no_mangle] +pub unsafe extern "C" fn TaffyStyle_set_grid_column(raw_style: *mut c_void, placement: GridPlacement) -> ReturnCode { with_style_mut!(raw_style, style, style.grid_column = placement.into()) } From 27f4f8b9ea5050279cecd38358fe57d37964362c Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 22 Sep 2023 20:36:27 +0100 Subject: [PATCH 13/57] Move c bindings to an external crate --- Cargo.toml | 2 +- ctaffy/Cargo.toml | 14 ++++++++++++++ {src/ffi => ctaffy/src}/error.rs | 0 src/ffi/mod.rs => ctaffy/src/lib.rs | 0 {src/ffi => ctaffy/src}/style.rs | 4 ++-- {src/ffi => ctaffy/src}/value.rs | 2 +- src/lib.rs | 1 - src/style/grid.rs | 6 +++--- 8 files changed, 21 insertions(+), 8 deletions(-) create mode 100644 ctaffy/Cargo.toml rename {src/ffi => ctaffy/src}/error.rs (100%) rename src/ffi/mod.rs => ctaffy/src/lib.rs (100%) rename {src/ffi => ctaffy/src}/style.rs (99%) rename {src/ffi => ctaffy/src}/value.rs (99%) diff --git a/Cargo.toml b/Cargo.toml index 01ea1ee50..e81e298c5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,4 +72,4 @@ path = "benches/dummy_benchmark.rs" harness = false [workspace] -members = ["scripts/gentest", "scripts/format-fixtures", "scripts/import-yoga-tests", "benches"] +members = ["scripts/gentest", "scripts/format-fixtures", "scripts/import-yoga-tests", "benches", "ctaffy"] diff --git a/ctaffy/Cargo.toml b/ctaffy/Cargo.toml new file mode 100644 index 000000000..aced08828 --- /dev/null +++ b/ctaffy/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "ctaffy" +version = "0.0.1" +authors = [ + "Nico Burns ", +] +edition = "2021" +include = ["src/**/*", "Cargo.toml"] +description = "C bindings to Taffy (A flexible UI layout library)" +repository = "https://github.com/DioxusLabs/taffy" +license = "MIT" + +[dependencies] +taffy = { path = ".." } \ No newline at end of file diff --git a/src/ffi/error.rs b/ctaffy/src/error.rs similarity index 100% rename from src/ffi/error.rs rename to ctaffy/src/error.rs diff --git a/src/ffi/mod.rs b/ctaffy/src/lib.rs similarity index 100% rename from src/ffi/mod.rs rename to ctaffy/src/lib.rs diff --git a/src/ffi/style.rs b/ctaffy/src/style.rs similarity index 99% rename from src/ffi/style.rs rename to ctaffy/src/style.rs index d13614b1b..a60d165f1 100644 --- a/src/ffi/style.rs +++ b/ctaffy/src/style.rs @@ -1,7 +1,7 @@ //! Public API for C FFI -use crate::geometry::Rect; -use crate::prelude as core; +use taffy::geometry::Rect; +use taffy::prelude as core; use std::ffi::c_void; use super::{GridPlacement, ReturnCode, StyleValue, StyleValueResult, StyleValueUnit, GridPlacementResult, TaffyFFIResult}; diff --git a/src/ffi/value.rs b/ctaffy/src/value.rs similarity index 99% rename from src/ffi/value.rs rename to ctaffy/src/value.rs index bc571a60f..07cc76d2c 100644 --- a/src/ffi/value.rs +++ b/ctaffy/src/value.rs @@ -1,6 +1,6 @@ //! Values types for C FFI -use crate::prelude as core; +use taffy::prelude as core; use super::ReturnCode; diff --git a/src/lib.rs b/src/lib.rs index 662f56641..ed8543b42 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -77,7 +77,6 @@ extern crate alloc; extern crate serde; pub mod compute; -pub mod ffi; pub mod geometry; pub mod prelude; pub mod style; diff --git a/src/style/grid.rs b/src/style/grid.rs index e5728983f..62d5be93a 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -165,14 +165,14 @@ impl Line { /// Convert raw values of start, span, and end into a [`GridPlacement`]. /// Zero is not a valid value for any of the values and is thus used to indicate unset /// Only 2 of the 3 values should be set. If all 3 are set then `span_value` is ignored. - pub (crate) fn from_raw_parts(start: i16, span_value: u16, end: i16) -> Self { + pub fn from_raw_parts(start: i16, span_value: u16, end: i16) -> Self { match (start, span_value, end) { (0, 0, 0) => auto(), (start, 0, 0) => Line { start: line(start), end: auto() }, (0, 0, end) => Line { start: auto(), end: line(end) }, (0, span_value, 0) => span(span_value), (start, span_value, 0) => Line { start: line(start), end: span(span_value) }, - (0, span_value, end) => Line { start: auto(), end: line(end) }, + (0, span_value, end) => Line { start: span(span_value), end: line(end) }, (start, _, end) => Line { start: line(start), end: line(end) }, } } @@ -180,7 +180,7 @@ impl Line { /// Convert raw values of start, span, and end into a [`GridPlacement`]. /// Zero is not a valid value for any of the values and is thus used to indicate unset /// Only 2 of the 3 values should be set. If all 3 are set then `span_value` is ignored. - pub (crate) fn into_raw_parts(self) -> (i16, u16, i16) { + pub fn into_raw_parts(self) -> (i16, u16, i16) { use GenericGridPlacement::*; match (self.start, self.end) { (Line(start), Line(end)) => (start.as_i16(), 0, end.as_i16()), From 52429af26614a7406b225d734f8f7e41fe0cdd7b Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 22 Sep 2023 20:45:40 +0100 Subject: [PATCH 14/57] Eliminate boxes and raw pointers from C api --- ctaffy/src/style.rs | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/ctaffy/src/style.rs b/ctaffy/src/style.rs index a60d165f1..85bec659c 100644 --- a/ctaffy/src/style.rs +++ b/ctaffy/src/style.rs @@ -1,17 +1,10 @@ //! Public API for C FFI +pub use taffy::style::Style as TaffyStyle; use taffy::geometry::Rect; -use taffy::prelude as core; use std::ffi::c_void; - use super::{GridPlacement, ReturnCode, StyleValue, StyleValueResult, StyleValueUnit, GridPlacementResult, TaffyFFIResult}; -/// A wrapper around [`core::Style`] which allows the individual style properties to be accessed -/// via FFI-friendly getter and setter functions -#[repr(transparent)] -pub struct TaffyStyle { - pub(crate) inner: core::Style, -} /// Return [`ReturnCode::NullStylePointer`] if the passed pointer is null macro_rules! assert_style_pointer_is_non_null { @@ -28,13 +21,10 @@ macro_rules! assert_style_pointer_is_non_null { macro_rules! get_style { ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ assert_style_pointer_is_non_null!($raw_style_ptr); - let style_box = unsafe { Box::from_raw($raw_style_ptr as *mut TaffyStyle) }; - let $style_ident = &style_box.inner; + let $style_ident = unsafe { &*($raw_style_ptr as *const TaffyStyle) }; let return_value = $block; - Box::leak(style_box); - TaffyFFIResult::from_value(return_value.into()) }}; } @@ -45,12 +35,10 @@ macro_rules! get_style { macro_rules! with_style_mut { ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ assert_style_pointer_is_non_null!($raw_style_ptr); - let mut style_box = unsafe { Box::from_raw($raw_style_ptr as *mut TaffyStyle) }; - let $style_ident = &mut style_box.inner; + let $style_ident = unsafe { &mut*($raw_style_ptr as *mut TaffyStyle) }; $block; - Box::leak(style_box); ReturnCode::Ok }}; } @@ -78,20 +66,20 @@ macro_rules! try_from_raw { /// Function to get the margin_top value #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_get_margin_top(raw_style: *const c_void) -> StyleValueResult { +pub unsafe extern "C" fn TaffyStyle_get_margin_top(raw_style: *const TaffyStyle) -> StyleValueResult { get_style!(raw_style, style, style.margin.top) } /// Function to set the margin_top value #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_margin_top(raw_style: *mut c_void, value: StyleValue) -> ReturnCode { +pub unsafe extern "C" fn TaffyStyle_set_margin_top(raw_style: *mut TaffyStyle, value: StyleValue) -> ReturnCode { with_style_mut!(raw_style, style, style.margin.top = try_from_value!(value)) } /// Function to set all the value of margin #[no_mangle] pub unsafe extern "C" fn TaffyStyle_set_margin_trbl( - raw_style: *mut c_void, + raw_style: *mut TaffyStyle, top: StyleValue, right: StyleValue, bottom: StyleValue, @@ -111,20 +99,20 @@ pub unsafe extern "C" fn TaffyStyle_set_margin_trbl( /// Function to get the margin_top value #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_get_padding_top(raw_style: *const c_void) -> StyleValueResult { +pub unsafe extern "C" fn TaffyStyle_get_padding_top(raw_style: *const TaffyStyle) -> StyleValueResult { get_style!(raw_style, style, style.padding.top) } /// Function to set the padding_top value #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_padding_top(raw_style: *mut c_void, value: f32, unit: StyleValueUnit) -> ReturnCode { +pub unsafe extern "C" fn TaffyStyle_set_padding_top(raw_style: *mut TaffyStyle, value: f32, unit: StyleValueUnit) -> ReturnCode { with_style_mut!(raw_style, style, style.padding.top = try_from_raw!(unit, value)) } /// Function to set all the value of padding #[no_mangle] pub unsafe extern "C" fn TaffyStyle_set_padding_trbl( - raw_style: *mut c_void, + raw_style: *mut TaffyStyle, top_value: f32, top_value_unit: StyleValueUnit, right_value: f32, @@ -148,12 +136,12 @@ pub unsafe extern "C" fn TaffyStyle_set_padding_trbl( /// Get grid item's column placement #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_get_grid_column(raw_style: *mut c_void) -> GridPlacementResult { +pub unsafe extern "C" fn TaffyStyle_get_grid_column(raw_style: *mut TaffyStyle) -> GridPlacementResult { get_style!(raw_style, style, style.grid_column) } /// Set grid item's column placement #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_grid_column(raw_style: *mut c_void, placement: GridPlacement) -> ReturnCode { +pub unsafe extern "C" fn TaffyStyle_set_grid_column(raw_style: *mut TaffyStyle, placement: GridPlacement) -> ReturnCode { with_style_mut!(raw_style, style, style.grid_column = placement.into()) } From 9c4c58c6ec070115b3d812143d542b8030f6a378 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 22 Sep 2023 20:45:56 +0100 Subject: [PATCH 15/57] cargo fmt --- ctaffy/src/error.rs | 7 +++---- ctaffy/src/style.rs | 20 ++++++++++++++------ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/ctaffy/src/error.rs b/ctaffy/src/error.rs index c5da261c9..16bd4ea50 100644 --- a/ctaffy/src/error.rs +++ b/ctaffy/src/error.rs @@ -1,8 +1,8 @@ //! Return types for C FFI -use super::{StyleValue, StyleValueUnit, GridPlacement}; +use super::{GridPlacement, StyleValue, StyleValueUnit}; -pub (crate) trait TaffyFFIResult { +pub(crate) trait TaffyFFIResult { type Value; fn from_value(value: Self::Value) -> Self; fn from_return_code(return_code: ReturnCode) -> Self; @@ -44,7 +44,7 @@ pub enum ReturnCode { impl TaffyFFIResult for ReturnCode { type Value = ReturnCode; fn from_value(value: Self::Value) -> Self { - value + value } fn from_return_code(return_code: ReturnCode) -> Self { return_code @@ -67,7 +67,6 @@ impl TaffyFFIResult for StyleValueResult { } } - #[repr(C)] pub struct GridPlacementResult { pub return_code: ReturnCode, diff --git a/ctaffy/src/style.rs b/ctaffy/src/style.rs index 85bec659c..0a33604c0 100644 --- a/ctaffy/src/style.rs +++ b/ctaffy/src/style.rs @@ -1,10 +1,11 @@ //! Public API for C FFI pub use taffy::style::Style as TaffyStyle; -use taffy::geometry::Rect; +use super::{ + GridPlacement, GridPlacementResult, ReturnCode, StyleValue, StyleValueResult, StyleValueUnit, TaffyFFIResult, +}; use std::ffi::c_void; -use super::{GridPlacement, ReturnCode, StyleValue, StyleValueResult, StyleValueUnit, GridPlacementResult, TaffyFFIResult}; - +use taffy::geometry::Rect; /// Return [`ReturnCode::NullStylePointer`] if the passed pointer is null macro_rules! assert_style_pointer_is_non_null { @@ -35,7 +36,7 @@ macro_rules! get_style { macro_rules! with_style_mut { ($raw_style_ptr:expr, $style_ident:ident, $block:expr) => {{ assert_style_pointer_is_non_null!($raw_style_ptr); - let $style_ident = unsafe { &mut*($raw_style_ptr as *mut TaffyStyle) }; + let $style_ident = unsafe { &mut *($raw_style_ptr as *mut TaffyStyle) }; $block; @@ -105,7 +106,11 @@ pub unsafe extern "C" fn TaffyStyle_get_padding_top(raw_style: *const TaffyStyle /// Function to set the padding_top value #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_padding_top(raw_style: *mut TaffyStyle, value: f32, unit: StyleValueUnit) -> ReturnCode { +pub unsafe extern "C" fn TaffyStyle_set_padding_top( + raw_style: *mut TaffyStyle, + value: f32, + unit: StyleValueUnit, +) -> ReturnCode { with_style_mut!(raw_style, style, style.padding.top = try_from_raw!(unit, value)) } @@ -142,6 +147,9 @@ pub unsafe extern "C" fn TaffyStyle_get_grid_column(raw_style: *mut TaffyStyle) /// Set grid item's column placement #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_grid_column(raw_style: *mut TaffyStyle, placement: GridPlacement) -> ReturnCode { +pub unsafe extern "C" fn TaffyStyle_set_grid_column( + raw_style: *mut TaffyStyle, + placement: GridPlacement, +) -> ReturnCode { with_style_mut!(raw_style, style, style.grid_column = placement.into()) } From c0bd4f6c93d73096b9928d744077156af772e909 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 22 Sep 2023 20:49:00 +0100 Subject: [PATCH 16/57] Make function UpperCamelCase with underscore between struct name and function name --- ctaffy/src/style.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/ctaffy/src/style.rs b/ctaffy/src/style.rs index 0a33604c0..3e8279af2 100644 --- a/ctaffy/src/style.rs +++ b/ctaffy/src/style.rs @@ -67,19 +67,19 @@ macro_rules! try_from_raw { /// Function to get the margin_top value #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_get_margin_top(raw_style: *const TaffyStyle) -> StyleValueResult { +pub unsafe extern "C" fn TaffyStyle_GetMarginTop(raw_style: *const TaffyStyle) -> StyleValueResult { get_style!(raw_style, style, style.margin.top) } /// Function to set the margin_top value #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_margin_top(raw_style: *mut TaffyStyle, value: StyleValue) -> ReturnCode { +pub unsafe extern "C" fn TaffyStyle_SetMarginTop(raw_style: *mut TaffyStyle, value: StyleValue) -> ReturnCode { with_style_mut!(raw_style, style, style.margin.top = try_from_value!(value)) } /// Function to set all the value of margin #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_margin_trbl( +pub unsafe extern "C" fn TaffyStyle_SetMarginTrbl( raw_style: *mut TaffyStyle, top: StyleValue, right: StyleValue, @@ -100,13 +100,13 @@ pub unsafe extern "C" fn TaffyStyle_set_margin_trbl( /// Function to get the margin_top value #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_get_padding_top(raw_style: *const TaffyStyle) -> StyleValueResult { +pub unsafe extern "C" fn TaffyStyle_GetPaddingTop(raw_style: *const TaffyStyle) -> StyleValueResult { get_style!(raw_style, style, style.padding.top) } /// Function to set the padding_top value #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_padding_top( +pub unsafe extern "C" fn TaffyStyle_SetPaddingTop( raw_style: *mut TaffyStyle, value: f32, unit: StyleValueUnit, @@ -116,7 +116,7 @@ pub unsafe extern "C" fn TaffyStyle_set_padding_top( /// Function to set all the value of padding #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_padding_trbl( +pub unsafe extern "C" fn TaffyStyle_SetPaddingTrbl( raw_style: *mut TaffyStyle, top_value: f32, top_value_unit: StyleValueUnit, @@ -141,13 +141,13 @@ pub unsafe extern "C" fn TaffyStyle_set_padding_trbl( /// Get grid item's column placement #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_get_grid_column(raw_style: *mut TaffyStyle) -> GridPlacementResult { +pub unsafe extern "C" fn TaffyStyleGetGridColumn(raw_style: *mut TaffyStyle) -> GridPlacementResult { get_style!(raw_style, style, style.grid_column) } /// Set grid item's column placement #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_set_grid_column( +pub unsafe extern "C" fn TaffyStyleSetGridColumn( raw_style: *mut TaffyStyle, placement: GridPlacement, ) -> ReturnCode { From 76bd4186617839a501ae2375da40cb29ad772466 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 22 Sep 2023 20:54:10 +0100 Subject: [PATCH 17/57] Use repr(C) instead of repr(u8) --- ctaffy/src/error.rs | 2 +- ctaffy/src/value.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ctaffy/src/error.rs b/ctaffy/src/error.rs index 16bd4ea50..421e39f13 100644 --- a/ctaffy/src/error.rs +++ b/ctaffy/src/error.rs @@ -9,7 +9,7 @@ pub(crate) trait TaffyFFIResult { } #[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] +#[repr(C)] pub enum ReturnCode { /// Operation suceeded Ok, diff --git a/ctaffy/src/value.rs b/ctaffy/src/value.rs index 07cc76d2c..40eaac850 100644 --- a/ctaffy/src/value.rs +++ b/ctaffy/src/value.rs @@ -5,7 +5,7 @@ use taffy::prelude as core; use super::ReturnCode; #[derive(Debug, Clone, Copy, PartialEq, Eq)] -#[repr(u8)] +#[repr(C)] pub enum StyleValueUnit { /// A none value (used to unset optional fields) None, From d80f333141e5b39977874273737fc18ded1935f8 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 22 Sep 2023 21:00:18 +0100 Subject: [PATCH 18/57] Replace trbl function with function with dynamic edge parameter --- ctaffy/src/style.rs | 35 ++++++++++++++++++++++++----------- ctaffy/src/value.rs | 19 +++++++++++++++++++ 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/ctaffy/src/style.rs b/ctaffy/src/style.rs index 3e8279af2..1b2911356 100644 --- a/ctaffy/src/style.rs +++ b/ctaffy/src/style.rs @@ -2,7 +2,7 @@ pub use taffy::style::Style as TaffyStyle; use super::{ - GridPlacement, GridPlacementResult, ReturnCode, StyleValue, StyleValueResult, StyleValueUnit, TaffyFFIResult, + GridPlacement, GridPlacementResult, ReturnCode, StyleValue, StyleValueResult, StyleValueUnit, TaffyFFIResult, TaffyEdge, }; use std::ffi::c_void; use taffy::geometry::Rect; @@ -79,19 +79,32 @@ pub unsafe extern "C" fn TaffyStyle_SetMarginTop(raw_style: *mut TaffyStyle, val /// Function to set all the value of margin #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_SetMarginTrbl( +pub unsafe extern "C" fn TaffyStyle_SetMargin( raw_style: *mut TaffyStyle, - top: StyleValue, - right: StyleValue, - bottom: StyleValue, - left: StyleValue, + edge: TaffyEdge, + value: StyleValue, ) -> ReturnCode { + let value = try_from_value!(value); with_style_mut!(raw_style, style, { - style.margin = Rect { - top: try_from_value!(top), - right: try_from_value!(right), - bottom: try_from_value!(bottom), - left: try_from_value!(left), + match edge { + TaffyEdge::Top => style.margin.top = value, + TaffyEdge::Bottom => style.margin.bottom = value, + TaffyEdge::Left => style.margin.left = value, + TaffyEdge::Right => style.margin.right = value, + TaffyEdge::Vertical => { + style.margin.top = value; + style.margin.bottom = value; + }, + TaffyEdge::Horizontal => { + style.margin.left = value; + style.margin.right = value; + }, + TaffyEdge::All => { + style.margin.top = value; + style.margin.bottom = value; + style.margin.left = value; + style.margin.right = value; + }, }; }) } diff --git a/ctaffy/src/value.rs b/ctaffy/src/value.rs index 40eaac850..16a7f8833 100644 --- a/ctaffy/src/value.rs +++ b/ctaffy/src/value.rs @@ -4,6 +4,25 @@ use taffy::prelude as core; use super::ReturnCode; +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[repr(C)] +pub enum TaffyEdge { + /// The top edge of the box + Top, + /// The bottom edge of the box + Bottom, + /// The left edge of the box + Left, + /// The right edge of the box + Right, + /// Both the top and bottom edges of the box + Vertical, + /// Both the left and right edges of the box + Horizontal, + /// All four edges of the box + All, +} + #[derive(Debug, Clone, Copy, PartialEq, Eq)] #[repr(C)] pub enum StyleValueUnit { From 76561065a714fea4917bf1e71099a2f71ece693b Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 22 Sep 2023 22:17:02 +0100 Subject: [PATCH 19/57] Implement getters/setters for all non-grid numeric style properties --- ctaffy/src/error.rs | 16 +++++ ctaffy/src/style.rs | 172 ++++++++++++++++++++++++++++++++++++-------- ctaffy/src/value.rs | 28 ++++++++ 3 files changed, 186 insertions(+), 30 deletions(-) diff --git a/ctaffy/src/error.rs b/ctaffy/src/error.rs index 421e39f13..ada25f782 100644 --- a/ctaffy/src/error.rs +++ b/ctaffy/src/error.rs @@ -67,6 +67,22 @@ impl TaffyFFIResult for StyleValueResult { } } +#[repr(C)] +pub struct FloatResult { + pub return_code: ReturnCode, + pub value: f32, +} + +impl TaffyFFIResult for FloatResult { + type Value = f32; + fn from_value(value: Self::Value) -> Self { + Self { return_code: ReturnCode::Ok, value } + } + fn from_return_code(return_code: ReturnCode) -> Self { + Self { return_code, value: 0.0 } + } +} + #[repr(C)] pub struct GridPlacementResult { pub return_code: ReturnCode, diff --git a/ctaffy/src/style.rs b/ctaffy/src/style.rs index 1b2911356..865cf3e91 100644 --- a/ctaffy/src/style.rs +++ b/ctaffy/src/style.rs @@ -2,7 +2,8 @@ pub use taffy::style::Style as TaffyStyle; use super::{ - GridPlacement, GridPlacementResult, ReturnCode, StyleValue, StyleValueResult, StyleValueUnit, TaffyFFIResult, TaffyEdge, + FloatResult, GridPlacement, GridPlacementResult, ReturnCode, StyleValue, StyleValueResult, StyleValueUnit, + TaffyEdge, TaffyFFIResult, }; use std::ffi::c_void; use taffy::geometry::Rect; @@ -65,17 +66,147 @@ macro_rules! try_from_raw { /* API variant with single parameter that combines "value" and "unit" into a `StyleValue` struct */ -/// Function to get the margin_top value +// Generate a function to get a style value such as margin.top or size.width +macro_rules! numeric_prop_getter { + ($func_name:ident, $property:ident, $edge:ident) => { + #[no_mangle] + pub unsafe extern "C" fn $func_name(raw_style: *const TaffyStyle) -> StyleValueResult { + get_style!(raw_style, style, style.$property.$edge) + } + }; +} + +// Generate a function to set a style value such as margin.top or size.width +macro_rules! numeric_prop_setter { + ($func_name:ident, $property:ident, $edge:ident) => { + #[no_mangle] + pub unsafe extern "C" fn $func_name(raw_style: *mut TaffyStyle, value: StyleValue) -> ReturnCode { + with_style_mut!(raw_style, style, style.$property.$edge = try_from_value!(value)) + } + }; +} + +// Size +numeric_prop_getter!(TaffyStyle_GetWidth, size, width); +numeric_prop_setter!(TaffyStyle_SetWidth, size, width); +numeric_prop_getter!(TaffyStyle_GetHeight, size, height); +numeric_prop_setter!(TaffyStyle_SetHeight, size, height); + +// MinSize +numeric_prop_getter!(TaffyStyle_GetMinWidth, min_size, width); +numeric_prop_setter!(TaffyStyle_SetMinWidth, min_size, width); +numeric_prop_getter!(TaffyStyle_GetMinHeight, min_size, height); +numeric_prop_setter!(TaffyStyle_SetMinHeight, min_size, height); + +// MaxSize +numeric_prop_getter!(TaffyStyle_GetMaxWidth, max_size, width); +numeric_prop_setter!(TaffyStyle_SetMaxWidth, max_size, width); +numeric_prop_getter!(TaffyStyle_GetMaxHeight, max_size, height); +numeric_prop_setter!(TaffyStyle_SetMaxHeight, max_size, height); + +// Inset +numeric_prop_getter!(TaffyStyle_GetInsetTop, inset, top); +numeric_prop_setter!(TaffyStyle_SetInsetTop, inset, top); +numeric_prop_getter!(TaffyStyle_GetInsetBottom, inset, bottom); +numeric_prop_setter!(TaffyStyle_SetInsetBottom, inset, bottom); +numeric_prop_getter!(TaffyStyle_GetInsetLeft, inset, left); +numeric_prop_getter!(TaffyStyle_GetInsetRight, inset, right); +numeric_prop_setter!(TaffyStyle_SetInsetLeft, inset, left); +numeric_prop_setter!(TaffyStyle_SetInsetRight, inset, right); + +// Margin +numeric_prop_getter!(TaffyStyle_GetMarginTop, margin, top); +numeric_prop_setter!(TaffyStyle_SetMarginTop, margin, top); +numeric_prop_getter!(TaffyStyle_GetMarginBottom, margin, bottom); +numeric_prop_setter!(TaffyStyle_SetMarginBottom, margin, bottom); +numeric_prop_getter!(TaffyStyle_GetMarginLeft, margin, left); +numeric_prop_getter!(TaffyStyle_GetMarginRight, margin, right); +numeric_prop_setter!(TaffyStyle_SetMarginLeft, margin, left); +numeric_prop_setter!(TaffyStyle_SetMarginRight, margin, right); + +// Padding +numeric_prop_getter!(TaffyStyle_GetPaddingTop, padding, top); +numeric_prop_setter!(TaffyStyle_SetPaddingTop, padding, top); +numeric_prop_getter!(TaffyStyle_GetPaddingBottom, padding, bottom); +numeric_prop_setter!(TaffyStyle_SetPaddingBottom, padding, bottom); +numeric_prop_getter!(TaffyStyle_GetPaddingLeft, padding, left); +numeric_prop_getter!(TaffyStyle_GetPaddingRight, padding, right); +numeric_prop_setter!(TaffyStyle_SetPaddingLeft, padding, left); +numeric_prop_setter!(TaffyStyle_SetPaddingRight, padding, right); + +// Border +numeric_prop_getter!(TaffyStyle_GetBorderTop, border, top); +numeric_prop_setter!(TaffyStyle_SetBorderTop, border, top); +numeric_prop_getter!(TaffyStyle_GetBorderBottom, border, bottom); +numeric_prop_setter!(TaffyStyle_SetBorderBottom, border, bottom); +numeric_prop_getter!(TaffyStyle_GetBorderLeft, border, left); +numeric_prop_getter!(TaffyStyle_GetBorderRight, border, right); +numeric_prop_setter!(TaffyStyle_SetBorderLeft, border, left); +numeric_prop_setter!(TaffyStyle_SetBorderRight, border, right); + +// Gap +numeric_prop_getter!(TaffyStyle_GetColumnGap, gap, width); +numeric_prop_setter!(TaffyStyle_SetColumnGap, gap, width); +numeric_prop_getter!(TaffyStyle_GetRowGap, gap, height); +numeric_prop_setter!(TaffyStyle_SetRowGap, gap, height); + +// Aspect ratio #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_GetMarginTop(raw_style: *const TaffyStyle) -> StyleValueResult { - get_style!(raw_style, style, style.margin.top) +pub unsafe extern "C" fn TaffyStyle_GetAspectRatio(raw_style: *const TaffyStyle) -> FloatResult { + get_style!(raw_style, style, style.aspect_ratio.unwrap_or(f32::NAN)) +} +#[no_mangle] +pub unsafe extern "C" fn TaffyStyle_SetAspectRatio(raw_style: *mut TaffyStyle, value: f32) -> ReturnCode { + with_style_mut!(raw_style, style, { + if value.is_finite() && value > 0.0 { + style.aspect_ratio = Some(value) + } else { + style.aspect_ratio = None; + } + }) } -/// Function to set the margin_top value +// Flex #[no_mangle] -pub unsafe extern "C" fn TaffyStyle_SetMarginTop(raw_style: *mut TaffyStyle, value: StyleValue) -> ReturnCode { - with_style_mut!(raw_style, style, style.margin.top = try_from_value!(value)) +pub unsafe extern "C" fn TaffyStyle_GetFlexBasis(raw_style: *const TaffyStyle) -> StyleValueResult { + get_style!(raw_style, style, style.flex_basis) } +#[no_mangle] +pub unsafe extern "C" fn TaffyStyle_SetFlexBasis( + raw_style: *mut TaffyStyle, + value: f32, + unit: StyleValueUnit, +) -> ReturnCode { + with_style_mut!(raw_style, style, style.flex_basis = try_from_raw!(unit, value)) +} +#[no_mangle] +pub unsafe extern "C" fn TaffyStyle_GetFlexGrow(raw_style: *const TaffyStyle) -> FloatResult { + get_style!(raw_style, style, style.flex_grow) +} +#[no_mangle] +pub unsafe extern "C" fn TaffyStyle_SetFlexGrow(raw_style: *mut TaffyStyle, value: f32) -> ReturnCode { + with_style_mut!(raw_style, style, style.flex_grow = value) +} +#[no_mangle] +pub unsafe extern "C" fn TaffyStyle_GetFlexShrink(raw_style: *const TaffyStyle) -> FloatResult { + get_style!(raw_style, style, style.flex_shrink) +} +#[no_mangle] +pub unsafe extern "C" fn TaffyStyle_SetFlexShrink(raw_style: *mut TaffyStyle, value: f32) -> ReturnCode { + with_style_mut!(raw_style, style, style.flex_shrink = value) +} + +// /// Function to get the margin_top value +// #[no_mangle] +// pub unsafe extern "C" fn TaffyStyle_GetMarginTop(raw_style: *const TaffyStyle) -> StyleValueResult { +// get_style!(raw_style, style, style.margin.top) +// } + +// /// Function to set the margin_top value +// #[no_mangle] +// pub unsafe extern "C" fn TaffyStyle_SetMarginTop(raw_style: *mut TaffyStyle, value: StyleValue) -> ReturnCode { +// with_style_mut!(raw_style, style, style.margin.top = try_from_value!(value)) +// } /// Function to set all the value of margin #[no_mangle] @@ -94,39 +225,23 @@ pub unsafe extern "C" fn TaffyStyle_SetMargin( TaffyEdge::Vertical => { style.margin.top = value; style.margin.bottom = value; - }, + } TaffyEdge::Horizontal => { style.margin.left = value; style.margin.right = value; - }, + } TaffyEdge::All => { style.margin.top = value; style.margin.bottom = value; style.margin.left = value; style.margin.right = value; - }, + } }; }) } /* API variant with seperate "value" and "unit" parameters */ -/// Function to get the margin_top value -#[no_mangle] -pub unsafe extern "C" fn TaffyStyle_GetPaddingTop(raw_style: *const TaffyStyle) -> StyleValueResult { - get_style!(raw_style, style, style.padding.top) -} - -/// Function to set the padding_top value -#[no_mangle] -pub unsafe extern "C" fn TaffyStyle_SetPaddingTop( - raw_style: *mut TaffyStyle, - value: f32, - unit: StyleValueUnit, -) -> ReturnCode { - with_style_mut!(raw_style, style, style.padding.top = try_from_raw!(unit, value)) -} - /// Function to set all the value of padding #[no_mangle] pub unsafe extern "C" fn TaffyStyle_SetPaddingTrbl( @@ -160,9 +275,6 @@ pub unsafe extern "C" fn TaffyStyleGetGridColumn(raw_style: *mut TaffyStyle) -> /// Set grid item's column placement #[no_mangle] -pub unsafe extern "C" fn TaffyStyleSetGridColumn( - raw_style: *mut TaffyStyle, - placement: GridPlacement, -) -> ReturnCode { +pub unsafe extern "C" fn TaffyStyleSetGridColumn(raw_style: *mut TaffyStyle, placement: GridPlacement) -> ReturnCode { with_style_mut!(raw_style, style, style.grid_column = placement.into()) } diff --git a/ctaffy/src/value.rs b/ctaffy/src/value.rs index 16a7f8833..48a6cb009 100644 --- a/ctaffy/src/value.rs +++ b/ctaffy/src/value.rs @@ -116,6 +116,34 @@ impl TryFrom for core::LengthPercentageAuto { } } +impl From for StyleValue { + fn from(value: core::Dimension) -> Self { + match value { + core::Dimension::Length(value) => Self { unit: StyleValueUnit::Length, value }, + core::Dimension::Percent(value) => Self { unit: StyleValueUnit::Percent, value }, + core::Dimension::Auto => Self { unit: StyleValueUnit::Auto, value: 0.0 }, + } + } +} + +impl TryFrom for core::Dimension { + type Error = ReturnCode; + + fn try_from(value: StyleValue) -> Result { + match value.unit { + StyleValueUnit::Auto => Ok(core::Dimension::Auto), + StyleValueUnit::Length => Ok(core::Dimension::Length(value.value)), + StyleValueUnit::Percent => Ok(core::Dimension::Percent(value.value)), + StyleValueUnit::None => Err(ReturnCode::InvalidNone), + StyleValueUnit::MinContent => Err(ReturnCode::InvalidMinContent), + StyleValueUnit::MaxContent => Err(ReturnCode::InvalidMaxContent), + StyleValueUnit::FitContentPx => Err(ReturnCode::InvalidFitContentPx), + StyleValueUnit::FitContentPercent => Err(ReturnCode::InvalidFitContentPercent), + StyleValueUnit::Fr => Err(ReturnCode::InvalidFr), + } + } +} + /// For all fields, zero represents not set #[derive(Debug, Clone, Copy, PartialEq)] #[repr(C)] From 33677e73d95b8b34d682edbd6db39b1ece4c2d27 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 22 Sep 2023 22:28:21 +0100 Subject: [PATCH 20/57] Format grid style --- src/style/grid.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/style/grid.rs b/src/style/grid.rs index 62d5be93a..08d569f9e 100644 --- a/src/style/grid.rs +++ b/src/style/grid.rs @@ -166,7 +166,7 @@ impl Line { /// Zero is not a valid value for any of the values and is thus used to indicate unset /// Only 2 of the 3 values should be set. If all 3 are set then `span_value` is ignored. pub fn from_raw_parts(start: i16, span_value: u16, end: i16) -> Self { - match (start, span_value, end) { + match (start, span_value, end) { (0, 0, 0) => auto(), (start, 0, 0) => Line { start: line(start), end: auto() }, (0, 0, end) => Line { start: auto(), end: line(end) }, @@ -182,7 +182,7 @@ impl Line { /// Only 2 of the 3 values should be set. If all 3 are set then `span_value` is ignored. pub fn into_raw_parts(self) -> (i16, u16, i16) { use GenericGridPlacement::*; - match (self.start, self.end) { + match (self.start, self.end) { (Line(start), Line(end)) => (start.as_i16(), 0, end.as_i16()), (Line(start), Span(span)) => (start.as_i16(), span, 0), (Line(start), Auto) => (start.as_i16(), 1, 0), @@ -192,7 +192,7 @@ impl Line { (Auto, Line(end)) => (0, 1, end.as_i16()), (Auto, Span(span)) => (0, span, 0), (Auto, Auto) => (0, 1, 0), - } + } } } From 3a0668d2deebc003fada56a8b66a8e0253b8f8d3 Mon Sep 17 00:00:00 2001 From: Nico Burns Date: Fri, 22 Sep 2023 22:28:31 +0100 Subject: [PATCH 21/57] Update style size tests to include alignment --- src/style/mod.rs | 71 ++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 30 deletions(-) diff --git a/src/style/mod.rs b/src/style/mod.rs index f77973156..c48e8ce0d 100644 --- a/src/style/mod.rs +++ b/src/style/mod.rs @@ -439,64 +439,75 @@ mod tests { fn style_sizes() { use super::*; - fn assert_type_size(expected_size: usize) { + fn assert_type_size_and_align(expected_size: usize, expected_align: usize) { let name = ::core::any::type_name::(); let name = name.replace("taffy::geometry::", ""); let name = name.replace("taffy::style::dimension::", ""); let name = name.replace("taffy::style::alignment::", ""); let name = name.replace("taffy::style::flex::", ""); let name = name.replace("taffy::style::grid::", ""); + let name = name.replace("alloc::vec::", ""); + let name = name.replace("taffy::compute::grid::types::coordinates::", ""); assert_eq!( ::core::mem::size_of::(), expected_size, - "Expected {} for be {} byte(s) but it was {} byte(s)", + "Expected size_of {} to be {} byte(s) but it was {} byte(s)", name, expected_size, ::core::mem::size_of::(), ); + + assert_eq!( + ::core::mem::align_of::(), + expected_align, + "Expected align_of {} to be {} byte(s) but it was {} byte(s)", + name, + expected_align, + ::core::mem::align_of::(), + ); } // Display and Position - assert_type_size::(1); - assert_type_size::(1); - assert_type_size::(1); + assert_type_size_and_align::(1, 1); + assert_type_size_and_align::(1, 1); + assert_type_size_and_align::(1, 1); // Dimensions and aggregations of Dimensions - assert_type_size::(4); - assert_type_size::(8); - assert_type_size::(8); - assert_type_size::(8); - assert_type_size::>(16); - assert_type_size::>(16); - assert_type_size::>(16); - assert_type_size::>(32); - assert_type_size::>(32); - assert_type_size::>(32); + assert_type_size_and_align::(4, 4); + assert_type_size_and_align::(8, 4); + assert_type_size_and_align::(8, 4); + assert_type_size_and_align::(8, 4); + assert_type_size_and_align::>(16, 4); + assert_type_size_and_align::>(16, 4); + assert_type_size_and_align::>(16, 4); + assert_type_size_and_align::>(32, 4); + assert_type_size_and_align::>(32, 4); + assert_type_size_and_align::>(32, 4); // Alignment - assert_type_size::(1); - assert_type_size::(1); - assert_type_size::>(1); + assert_type_size_and_align::(1, 1); + assert_type_size_and_align::(1, 1); + assert_type_size_and_align::>(1, 1); // Flexbox Container - assert_type_size::(1); - assert_type_size::(1); + assert_type_size_and_align::(1, 1); + assert_type_size_and_align::(1, 1); // CSS Grid Container - assert_type_size::(1); - assert_type_size::(8); - assert_type_size::(12); - assert_type_size::(20); - assert_type_size::(32); - assert_type_size::>(24); - assert_type_size::>(24); + assert_type_size_and_align::(1, 1); + assert_type_size_and_align::(8, 4); + assert_type_size_and_align::(12, 4); + assert_type_size_and_align::(20, 4); + assert_type_size_and_align::(32, 8); + assert_type_size_and_align::>(24, 8); + assert_type_size_and_align::>(24, 8); // CSS Grid Item - assert_type_size::(4); - assert_type_size::>(8); + assert_type_size_and_align::(4, 2); + assert_type_size_and_align::>(8, 2); // Overall - assert_type_size::