taffy/style/
available_space.rs1use crate::{
3 prelude::{FromLength, TaffyMaxContent, TaffyMinContent, TaffyZero},
4 sys::abs,
5 Size,
6};
7
8#[derive(Copy, Clone, Debug, PartialEq)]
11#[cfg_attr(feature = "serde", derive(Serialize))]
12pub enum AvailableSpace {
13 Definite(f32),
15 MinContent,
17 MaxContent,
19}
20impl TaffyZero for AvailableSpace {
21 const ZERO: Self = Self::Definite(0.0);
22}
23impl TaffyMaxContent for AvailableSpace {
24 const MAX_CONTENT: Self = Self::MaxContent;
25}
26impl TaffyMinContent for AvailableSpace {
27 const MIN_CONTENT: Self = Self::MinContent;
28}
29impl FromLength for AvailableSpace {
30 fn from_length<Input: Into<f32> + Copy>(value: Input) -> Self {
31 Self::Definite(value.into())
32 }
33}
34
35impl AvailableSpace {
36 pub fn is_definite(self) -> bool {
38 matches!(self, AvailableSpace::Definite(_))
39 }
40
41 pub fn into_option(self) -> Option<f32> {
44 match self {
45 AvailableSpace::Definite(value) => Some(value),
46 _ => None,
47 }
48 }
49
50 pub fn unwrap_or(self, default: f32) -> f32 {
52 self.into_option().unwrap_or(default)
53 }
54
55 #[track_caller]
57 pub fn unwrap(self) -> f32 {
58 self.into_option().unwrap()
59 }
60
61 pub fn or(self, default: AvailableSpace) -> AvailableSpace {
63 match self {
64 AvailableSpace::Definite(_) => self,
65 _ => default,
66 }
67 }
68
69 pub fn or_else(self, default_cb: impl FnOnce() -> AvailableSpace) -> AvailableSpace {
71 match self {
72 AvailableSpace::Definite(_) => self,
73 _ => default_cb(),
74 }
75 }
76
77 pub fn unwrap_or_else(self, default_cb: impl FnOnce() -> f32) -> f32 {
79 self.into_option().unwrap_or_else(default_cb)
80 }
81
82 pub fn maybe_set(self, value: Option<f32>) -> AvailableSpace {
84 match value {
85 Some(value) => AvailableSpace::Definite(value),
86 None => self,
87 }
88 }
89
90 pub fn map_definite_value(self, map_function: impl FnOnce(f32) -> f32) -> AvailableSpace {
92 match self {
93 AvailableSpace::Definite(value) => AvailableSpace::Definite(map_function(value)),
94 _ => self,
95 }
96 }
97
98 pub fn compute_free_space(&self, used_space: f32) -> f32 {
100 match self {
101 AvailableSpace::MaxContent => f32::INFINITY,
102 AvailableSpace::MinContent => 0.0,
103 AvailableSpace::Definite(available_space) => available_space - used_space,
104 }
105 }
106
107 pub fn is_roughly_equal(self, other: AvailableSpace) -> bool {
110 use AvailableSpace::*;
111 match (self, other) {
112 (Definite(a), Definite(b)) => abs(a - b) < f32::EPSILON,
113 (MinContent, MinContent) => true,
114 (MaxContent, MaxContent) => true,
115 _ => false,
116 }
117 }
118}
119
120impl From<f32> for AvailableSpace {
121 fn from(value: f32) -> Self {
122 Self::Definite(value)
123 }
124}
125
126impl From<Option<f32>> for AvailableSpace {
127 fn from(option: Option<f32>) -> Self {
128 match option {
129 Some(value) => Self::Definite(value),
130 None => Self::MaxContent,
131 }
132 }
133}
134
135impl Size<AvailableSpace> {
136 pub fn into_options(self) -> Size<Option<f32>> {
138 Size { width: self.width.into_option(), height: self.height.into_option() }
139 }
140
141 pub fn maybe_set(self, value: Size<Option<f32>>) -> Size<AvailableSpace> {
143 Size { width: self.width.maybe_set(value.width), height: self.height.maybe_set(value.height) }
144 }
145}