Skip to content

Commit

Permalink
Merge branch 'main' into number-yeet
Browse files Browse the repository at this point in the history
  • Loading branch information
alice-i-cecile authored Jun 11, 2022
2 parents 91a665c + 712df30 commit 504eee2
Show file tree
Hide file tree
Showing 12 changed files with 130 additions and 71 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
/tests/generated/** linguist-generated=true
/benches/generated/** linguist-generated=true
5 changes: 4 additions & 1 deletion RELEASES.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,18 @@

### 0.2.0 Added

- Nothing yet
- Added `taffy::error::InvalidChild` Error type

### 0.2.0 Changed

- removed the public `Number` type; a more idiomatic `Option<f32>` is used instead
- the associated public `MinMax` and `OrElse` traits have also been removed; these should never have been public
- `Sprawl::remove` now returns a `Result<usize, Error>`, to indicate if the operation was sucessful, and if it was, which ID was invalidated.
- renamed `taffy::forest::Forest.new-node(..)` `taffy::forest::Forest.new_with_children(..)`
- renamed `taffy::node::Taffy.new-node(..)` -> `taffy::node::Taffy.new_with_children(..)`
- renamed `taffy::style::Style` -> `taffy::style::FlexboxLayout` to more precicely indicate its purpose
- renamed `taffy::Error` -> `taffy::error::InvalidNode`
- `taffy::Taffy::remove_child_at_index`, `taffy::Taffy::replace_child_at_index`, and `taffy::Taffy::child_at_index` now return `taffy::InvalidChild::ChildIndexOutOfBounds` instead of panicing

### 0.2.0 Fixed

Expand Down
2 changes: 1 addition & 1 deletion examples/basic.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use taffy::prelude::*;

fn main() -> Result<(), Error> {
fn main() -> Result<(), taffy::error::InvalidNode> {
let mut taffy = Taffy::new();

let child = taffy.new_with_children(
Expand Down
2 changes: 1 addition & 1 deletion examples/nested.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use taffy::prelude::*;

fn main() -> Result<(), Error> {
fn main() -> Result<(), taffy::error::InvalidNode> {
let mut taffy = Taffy::new();

// left
Expand Down
5 changes: 4 additions & 1 deletion scripts/gentest/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,10 @@ async fn main() {

info!("starting webdriver instance");
let webdriver_url = "http://localhost:4444";
let mut webdriver_handle = Command::new("chromedriver").arg("--port=4444").spawn().unwrap();
let mut webdriver_handle = Command::new("chromedriver")
.arg("--port=4444")
.spawn()
.expect("ChromeDriver not found: Make sure you have it installed and added to your PATH.");

// this is silly, but it works
std::thread::sleep(std::time::Duration::from_secs(1));
Expand Down
57 changes: 57 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
//! The Error types produced by Taffy.
#[cfg(feature = "std")]
use core::fmt::{Display, Formatter, Result};

use crate::node::Node;

/// The [`Node`] was not found in the [`Taffy`](crate::Taffy) instance
#[derive(Debug)]
pub struct InvalidNode(pub Node);

#[cfg(feature = "std")]
impl Display for InvalidNode {
fn fmt(&self, f: &mut Formatter) -> Result {
write!(f, "Node {:?} is not in the Taffy instance", self.0)
}
}

#[cfg(feature = "std")]
impl std::error::Error for InvalidNode {}

/// An error that occurs while trying to access or modify a [`Node`]'s children by index.
#[derive(Debug)]
pub enum InvalidChild {
/// The parent [`Node`] does not have a child at `child_index`. It only has `child_count` children
ChildIndexOutOfBounds {
/// The parent node whose child was being looked up
parent: Node,
/// The index that was looked up
child_index: usize,
/// The total number of children the parent has
child_count: usize,
},
/// The parent [`Node`] was not found in the [`Taffy`](crate::Taffy) instance.
InvalidParentNode(Node),
/// The child [`Node`] was not found in the [`Taffy`](crate::Taffy) instance.
InvalidChildNode(Node),
}

#[cfg(feature = "std")]
impl Display for InvalidChild {
fn fmt(&self, f: &mut Formatter) -> Result {
match self {
InvalidChild::ChildIndexOutOfBounds { parent, child_index, child_count } => write!(
f,
"Index (is {}) should be < child_count ({}) for parent node {:?}",
child_index, child_count, parent
),
InvalidChild::InvalidParentNode(parent) => {
write!(f, "Parent Node {:?} is not in the Taffy instance", parent)
}
InvalidChild::InvalidChildNode(child) => write!(f, "Child Node {:?} is not in the Taffy instance", child),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for InvalidChild {}
7 changes: 4 additions & 3 deletions src/flexbox.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,20 +54,21 @@ struct FlexItem {
/// The position of the bottom edge of this item
baseline: f32,

/// A temporary values for holding offset in the main / cross direction.

/// A temporary value for the main offset
///
/// Offset is the relative position from the item's natural flow position based on
/// relative position values, alignment, and justification. Does not include margin/padding/border.
offset_main: f32,
/// A temporary value for the cross offset
///
/// Offset is the relative position from the item's natural flow position based on
/// relative position values, alignment, and justification. Does not include margin/padding/border.
offset_cross: f32,
}

/// A line of [`FlexItem`] used for intermediate computation
struct FlexLine<'a> {
/// The slice of items to
/// The slice of items to iterate over during computation of this line
items: &'a mut [FlexItem],
/// The dimensions of the cross-axis
cross_size: f32,
Expand Down
29 changes: 1 addition & 28 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ extern crate alloc;
#[cfg(feature = "serde")]
extern crate serde;

pub mod error;
pub mod geometry;
pub mod layout;
pub mod math;
Expand All @@ -25,31 +26,3 @@ mod indexmap;
mod sys;

pub use crate::node::Taffy;

#[cfg(feature = "std")]
use core::fmt::{Display, Formatter, Result};

/// An error that can occur when performing layout
#[derive(Debug)]
pub enum Error {
/// The [`Node`](node::Node) was invalid
InvalidNode(node::Node),
}

#[cfg(feature = "std")]
impl Display for Error {
fn fmt(&self, f: &mut Formatter) -> Result {
match *self {
Error::InvalidNode(ref node) => write!(f, "Invalid node {:?}", node),
}
}
}

#[cfg(feature = "std")]
impl std::error::Error for Error {
fn description(&self) -> &str {
match *self {
Error::InvalidNode(_) => "The node is not part of the Taffy instance",
}
}
}
83 changes: 53 additions & 30 deletions src/node.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
//! UI [`Node`] types and related data structures.
//!
//! Layouts are composed of multiple nodes, which live in a forest-like data structure.
use crate::error;
use crate::forest::Forest;
use crate::geometry::Size;
use crate::layout::Layout;
use crate::style::FlexboxLayout;
#[cfg(any(feature = "std", feature = "alloc"))]
use crate::sys::Box;
use crate::sys::{new_map_with_capacity, ChildrenVec, Map, Vec};
use crate::Error;
use core::sync::atomic::{AtomicUsize, Ordering};

/// A function that can be applied to a `Size<Option<f32>>` to obtain a `Size<f32>`
Expand Down Expand Up @@ -86,26 +86,28 @@ impl Taffy {
}

/// Returns the `NodeId` of the provided node within the forest
fn find_node(&self, node: Node) -> Result<NodeId, Error> {
fn find_node(&self, node: Node) -> Result<NodeId, error::InvalidNode> {
match self.nodes_to_ids.get(&node) {
Some(id) => Ok(*id),
None => Err(Error::InvalidNode(node)),
None => Err(error::InvalidNode(node)),
}
}

/// Adds a new leaf node, which does not have any children
pub fn new_leaf(&mut self, style: FlexboxLayout, measure: MeasureFunc) -> Result<Node, Error> {
pub fn new_leaf(&mut self, style: FlexboxLayout, measure: MeasureFunc) -> Result<Node, error::InvalidNode> {
let node = self.allocate_node();
let id = self.forest.new_leaf(style, measure);
self.add_node(node, id);
Ok(node)
}

/// Adds a new node, which may have any number of `children`
pub fn new_with_children(&mut self, style: FlexboxLayout, children: &[Node]) -> Result<Node, Error> {
pub fn new_with_children(&mut self, style: FlexboxLayout, children: &[Node]) -> Result<Node, error::InvalidNode> {
let node = self.allocate_node();
let children =
children.iter().map(|child| self.find_node(*child)).collect::<Result<ChildrenVec<_>, Error>>()?;
let children = children
.iter()
.map(|child| self.find_node(*child))
.collect::<Result<ChildrenVec<_>, error::InvalidNode>>()?;
let id = self.forest.new_with_children(style, children);
self.add_node(node, id);
Ok(node)
Expand All @@ -122,9 +124,9 @@ impl Taffy {

/// Remove a specific [`Node`] from the tree
///
/// Its [`Id`] is marked as invalid.
pub fn remove(&mut self, node: Node) {
let id = if let Ok(id) = self.find_node(node) { id } else { return };
/// Its [`Id`] is marked as invalid. Returns the id of the node removed.
pub fn remove(&mut self, node: Node) -> Result<usize, error::InvalidNode> {
let id = self.find_node(node)?;

self.nodes_to_ids.remove(&node);
self.ids_to_nodes.remove(&id);
Expand All @@ -134,18 +136,20 @@ impl Taffy {
let _ = self.nodes_to_ids.insert(new, id);
let _ = self.ids_to_nodes.insert(id, new);
}

Ok(id)
}

/// Sets the [`MeasureFunc`] of the associated node
pub fn set_measure(&mut self, node: Node, measure: Option<MeasureFunc>) -> Result<(), Error> {
pub fn set_measure(&mut self, node: Node, measure: Option<MeasureFunc>) -> Result<(), error::InvalidNode> {
let id = self.find_node(node)?;
self.forest.nodes[id].measure = measure;
self.forest.mark_dirty(id);
Ok(())
}

/// Adds a `child` [`Node`] under the supplied `parent`
pub fn add_child(&mut self, parent: Node, child: Node) -> Result<(), Error> {
pub fn add_child(&mut self, parent: Node, child: Node) -> Result<(), error::InvalidNode> {
let node_id = self.find_node(parent)?;
let child_id = self.find_node(child)?;

Expand All @@ -154,7 +158,7 @@ impl Taffy {
}

/// Directly sets the `children` of the supplied `parent`
pub fn set_children(&mut self, parent: Node, children: &[Node]) -> Result<(), Error> {
pub fn set_children(&mut self, parent: Node, children: &[Node]) -> Result<(), error::InvalidNode> {
let node_id = self.find_node(parent)?;
let children_id = children.iter().map(|child| self.find_node(*child)).collect::<Result<ChildrenVec<_>, _>>()?;

Expand All @@ -176,7 +180,7 @@ impl Taffy {
/// Removes the `child` of the parent `node`
///
/// The child is not removed from the forest entirely, it is simply no longer attached to its previous parent.
pub fn remove_child(&mut self, parent: Node, child: Node) -> Result<Node, Error> {
pub fn remove_child(&mut self, parent: Node, child: Node) -> Result<Node, error::InvalidNode> {
let node_id = self.find_node(parent)?;
let child_id = self.find_node(child)?;

Expand All @@ -187,9 +191,13 @@ impl Taffy {
/// Removes the child at the given `index` from the `parent`
///
/// The child is not removed from the forest entirely, it is simply no longer attached to its previous parent.
pub fn remove_child_at_index(&mut self, parent: Node, child_index: usize) -> Result<Node, Error> {
let node_id = self.find_node(parent)?;
// TODO: index check
pub fn remove_child_at_index(&mut self, parent: Node, child_index: usize) -> Result<Node, error::InvalidChild> {
let node_id = self.find_node(parent).map_err(|e| error::InvalidChild::InvalidParentNode(e.0))?;

let child_count = self.forest.children[node_id].len();
if child_index >= child_count {
return Err(error::InvalidChild::ChildIndexOutOfBounds { parent, child_index, child_count });
}

let prev_id = self.forest.remove_child_at_index(node_id, child_index);
Ok(self.ids_to_nodes[&prev_id])
Expand All @@ -198,10 +206,19 @@ impl Taffy {
/// Replaces the child at the given `child_index` from the `parent` node with the new `child` node
///
/// The child is not removed from the forest entirely, it is simply no longer attached to its previous parent.
pub fn replace_child_at_index(&mut self, parent: Node, child_index: usize, new_child: Node) -> Result<Node, Error> {
let node_id = self.find_node(parent)?;
let child_id = self.find_node(new_child)?;
pub fn replace_child_at_index(
&mut self,
parent: Node,
child_index: usize,
new_child: Node,
) -> Result<Node, error::InvalidChild> {
let node_id = self.find_node(parent).map_err(|e| error::InvalidChild::InvalidParentNode(e.0))?;
let child_id = self.find_node(new_child).map_err(|e| error::InvalidChild::InvalidChildNode(e.0))?;
// TODO: index check
let child_count = self.forest.children[node_id].len();
if child_index >= child_count {
return Err(error::InvalidChild::ChildIndexOutOfBounds { parent, child_index, child_count });
}

self.forest.parents[child_id].push(node_id);
let old_child = core::mem::replace(&mut self.forest.children[node_id][child_index], child_id);
Expand All @@ -213,58 +230,64 @@ impl Taffy {
}

/// Returns the child [`Node`] of the parent `node` at the provided `child_index`
pub fn child_at_index(&self, parent: Node, child_index: usize) -> Result<Node, Error> {
let id = self.find_node(parent)?;
pub fn child_at_index(&self, parent: Node, child_index: usize) -> Result<Node, error::InvalidChild> {
let id = self.find_node(parent).map_err(|e| error::InvalidChild::InvalidParentNode(e.0))?;

let child_count = self.forest.children[id].len();
if child_index >= child_count {
return Err(error::InvalidChild::ChildIndexOutOfBounds { parent, child_index, child_count });
}

Ok(self.ids_to_nodes[&self.forest.children[id][child_index]])
}

/// Returns the number of children of the `parent` [`Node`]
pub fn child_count(&self, parent: Node) -> Result<usize, Error> {
pub fn child_count(&self, parent: Node) -> Result<usize, error::InvalidNode> {
let id = self.find_node(parent)?;
Ok(self.forest.children[id].len())
}

/// Returns a list of children that belong to the [`Parent`]
pub fn children(&self, parent: Node) -> Result<Vec<Node>, Error> {
pub fn children(&self, parent: Node) -> Result<Vec<Node>, error::InvalidNode> {
let id = self.find_node(parent)?;
Ok(self.forest.children[id].iter().map(|child| self.ids_to_nodes[child]).collect())
}

/// Sets the [`Style`] of the provided `node`
pub fn set_style(&mut self, node: Node, style: FlexboxLayout) -> Result<(), Error> {
pub fn set_style(&mut self, node: Node, style: FlexboxLayout) -> Result<(), error::InvalidNode> {
let id = self.find_node(node)?;
self.forest.nodes[id].style = style;
self.forest.mark_dirty(id);
Ok(())
}

/// Gets the [`Style`] of the provided `node`
pub fn style(&self, node: Node) -> Result<&FlexboxLayout, Error> {
pub fn style(&self, node: Node) -> Result<&FlexboxLayout, error::InvalidNode> {
let id = self.find_node(node)?;
Ok(&self.forest.nodes[id].style)
}

/// Return this node layout relative to its parent
pub fn layout(&self, node: Node) -> Result<&Layout, Error> {
pub fn layout(&self, node: Node) -> Result<&Layout, error::InvalidNode> {
let id = self.find_node(node)?;
Ok(&self.forest.nodes[id].layout)
}

/// Marks the layout computation of this node and its children as outdated
pub fn mark_dirty(&mut self, node: Node) -> Result<(), Error> {
pub fn mark_dirty(&mut self, node: Node) -> Result<(), error::InvalidNode> {
let id = self.find_node(node)?;
self.forest.mark_dirty(id);
Ok(())
}

/// Indicates whether the layout of this node (and its children) need to be recomputed
pub fn dirty(&self, node: Node) -> Result<bool, Error> {
pub fn dirty(&self, node: Node) -> Result<bool, error::InvalidNode> {
let id = self.find_node(node)?;
Ok(self.forest.nodes[id].is_dirty)
}

/// Updates the stored layout of the provided `node` and its children
pub fn compute_layout(&mut self, node: Node, size: Size<Option<f32>>) -> Result<(), Error> {
pub fn compute_layout(&mut self, node: Node, size: Size<Option<f32>>) -> Result<(), error::InvalidNode> {
let id = self.find_node(node)?;
self.forest.compute_layout(id, size);
Ok(())
Expand Down
1 change: 0 additions & 1 deletion src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,4 @@ pub use crate::{
AlignContent, AlignItems, AlignSelf, Dimension, Display, FlexDirection, FlexWrap, FlexboxLayout,
JustifyContent, PositionType,
},
Error,
};
Loading

0 comments on commit 504eee2

Please sign in to comment.