kas_core/layout/
storage.rs

1// Licensed under the Apache License, Version 2.0 (the "License");
2// you may not use this file except in compliance with the License.
3// You may obtain a copy of the License in the LICENSE-APACHE file or at:
4//     https://www.apache.org/licenses/LICENSE-2.0
5
6//! Layout solver — storage
7
8use super::SizeRules;
9use kas_macros::impl_scope;
10use std::fmt::Debug;
11
12/// Requirements of row solver storage type
13///
14/// Usually this is set by a [`crate::layout::RowSolver`] from
15/// [`crate::Layout::size_rules`], then used by [`crate::Layout::set_rect`] to
16/// divide the assigned rect between children.
17///
18/// It may be useful to access this directly if not solving size rules normally;
19/// specifically this allows a different size solver to replace `size_rules` and
20/// influence `set_rect`.
21///
22/// Note: some implementations allocate when [`Self::set_dim`] is first called.
23/// It is expected that this method is called before other methods.
24pub trait RowStorage: Clone + Debug + sealed::Sealed {
25    /// Set dimension: number of columns or rows
26    fn set_dim(&mut self, cols: usize);
27
28    /// Access [`SizeRules`] for each column/row
29    fn rules(&mut self) -> &mut [SizeRules] {
30        self.widths_and_rules().1
31    }
32
33    /// Access widths for each column/row
34    ///
35    /// Widths are calculated from rules when `set_rect` is called. Assigning
36    /// to widths before `set_rect` is called only has any effect when the available
37    /// size exceeds the minimum required (see [`SizeRules::solve_seq`]).
38    fn widths(&mut self) -> &mut [i32] {
39        self.widths_and_rules().0
40    }
41
42    /// Access widths and rules simultaneously
43    fn widths_and_rules(&mut self) -> (&mut [i32], &mut [SizeRules]);
44}
45
46/// Fixed-length row storage
47///
48/// Uses const-generics argument `C` (the number of columns).
49#[derive(Clone, Debug)]
50pub struct FixedRowStorage<const C: usize> {
51    rules: [SizeRules; C],
52    widths: [i32; C],
53}
54
55impl<const C: usize> Default for FixedRowStorage<C> {
56    fn default() -> Self {
57        FixedRowStorage {
58            rules: [SizeRules::default(); C],
59            widths: [0; C],
60        }
61    }
62}
63
64impl<const C: usize> RowStorage for FixedRowStorage<C> {
65    fn set_dim(&mut self, cols: usize) {
66        assert_eq!(self.rules.as_ref().len(), cols);
67        assert_eq!(self.widths.as_ref().len(), cols);
68    }
69
70    fn widths_and_rules(&mut self) -> (&mut [i32], &mut [SizeRules]) {
71        (self.widths.as_mut(), self.rules.as_mut())
72    }
73}
74
75/// Variable-length row storage
76#[derive(Clone, Debug, Default)]
77pub struct DynRowStorage {
78    rules: Vec<SizeRules>,
79    widths: Vec<i32>,
80}
81
82impl RowStorage for DynRowStorage {
83    fn set_dim(&mut self, cols: usize) {
84        self.rules.resize(cols, SizeRules::EMPTY);
85        self.widths.resize(cols, 0);
86    }
87
88    fn widths_and_rules(&mut self) -> (&mut [i32], &mut [SizeRules]) {
89        (&mut self.widths, &mut self.rules)
90    }
91}
92
93/// Temporary storage type.
94///
95/// For dynamic-length rows and fixed-length rows with more than 16 items use
96/// `Vec<i32>`. For fixed-length rows up to 16 items, use `[i32; rows]`.
97pub trait RowTemp: AsMut<[i32]> + Default + Debug + sealed::Sealed {
98    fn set_len(&mut self, len: usize);
99}
100
101impl RowTemp for Vec<i32> {
102    fn set_len(&mut self, len: usize) {
103        self.resize(len, 0);
104    }
105}
106
107impl<const L: usize> RowTemp for [i32; L]
108where
109    [i32; L]: Default,
110{
111    fn set_len(&mut self, len: usize) {
112        assert_eq!(self.len(), len);
113    }
114}
115
116/// Requirements of grid solver storage type
117///
118/// Usually this is set by a [`crate::layout::GridSolver`] from
119/// [`crate::Layout::size_rules`], then used by [`crate::Layout::set_rect`] to
120/// divide the assigned rect between children.
121///
122/// It may be useful to access this directly if not solving size rules normally;
123/// specifically this allows a different size solver to replace `size_rules` and
124/// influence `set_rect`.
125///
126/// Note: some implementations allocate when [`Self::set_dims`] is first called.
127/// It is expected that this method is called before other methods.
128pub trait GridStorage: sealed::Sealed + Clone + std::fmt::Debug {
129    /// Set dimension: number of columns and rows
130    fn set_dims(&mut self, cols: usize, rows: usize);
131
132    /// Access [`SizeRules`] for each column
133    fn width_rules(&mut self) -> &mut [SizeRules] {
134        self.widths_and_rules().1
135    }
136
137    /// Access [`SizeRules`] for each row
138    fn height_rules(&mut self) -> &mut [SizeRules] {
139        self.heights_and_rules().1
140    }
141
142    /// Access widths for each column
143    ///
144    /// Widths are calculated from rules when `set_rect` is called. Assigning
145    /// to widths before `set_rect` is called only has any effect when the available
146    /// size exceeds the minimum required (see [`SizeRules::solve_seq`]).
147    fn widths(&mut self) -> &mut [i32] {
148        self.widths_and_rules().0
149    }
150
151    /// Access heights for each row
152    ///
153    /// Heights are calculated from rules when `set_rect` is called. Assigning
154    /// to heights before `set_rect` is called only has any effect when the available
155    /// size exceeds the minimum required (see [`SizeRules::solve_seq`]).
156    fn heights(&mut self) -> &mut [i32] {
157        self.heights_and_rules().0
158    }
159
160    /// Access column widths and rules simultaneously
161    fn widths_and_rules(&mut self) -> (&mut [i32], &mut [SizeRules]);
162
163    /// Access row heights and rules simultaneously
164    fn heights_and_rules(&mut self) -> (&mut [i32], &mut [SizeRules]);
165}
166
167impl_scope! {
168    /// Fixed-length grid storage
169    ///
170    /// Uses const-generics arguments `R, C` (the number of rows and columns).
171    #[impl_default]
172    #[derive(Clone, Debug)]
173    pub struct FixedGridStorage<const C: usize, const R: usize> {
174        width_rules: [SizeRules; C] = [SizeRules::default(); C],
175        height_rules: [SizeRules; R] = [SizeRules::default(); R],
176        widths: [i32; C] = [0; C],
177        heights: [i32; R] = [0; R],
178    }
179
180    impl GridStorage for Self {
181        fn set_dims(&mut self, cols: usize, rows: usize) {
182            assert_eq!(self.width_rules.as_ref().len(), cols);
183            assert_eq!(self.height_rules.as_ref().len(), rows);
184            assert_eq!(self.widths.len(), cols);
185            assert_eq!(self.heights.len(), rows);
186        }
187
188        fn widths_and_rules(&mut self) -> (&mut [i32], &mut [SizeRules]) {
189            (
190                self.widths.as_mut(),
191                self.width_rules.as_mut(),
192            )
193        }
194        fn heights_and_rules(&mut self) -> (&mut [i32], &mut [SizeRules]) {
195            (
196                self.heights.as_mut(),
197                self.height_rules.as_mut(),
198            )
199        }
200    }
201}
202
203/// Variable-length grid storage
204#[derive(Clone, Debug, Default)]
205pub struct DynGridStorage {
206    width_rules: Vec<SizeRules>,
207    height_rules: Vec<SizeRules>,
208    widths: Vec<i32>,
209    heights: Vec<i32>,
210}
211
212impl GridStorage for DynGridStorage {
213    fn set_dims(&mut self, cols: usize, rows: usize) {
214        self.width_rules.resize(cols, SizeRules::EMPTY);
215        self.height_rules.resize(rows, SizeRules::EMPTY);
216        self.widths.resize(cols, 0);
217        self.heights.resize(rows, 0);
218    }
219
220    fn widths_and_rules(&mut self) -> (&mut [i32], &mut [SizeRules]) {
221        (self.widths.as_mut(), self.width_rules.as_mut())
222    }
223    fn heights_and_rules(&mut self) -> (&mut [i32], &mut [SizeRules]) {
224        (self.heights.as_mut(), self.height_rules.as_mut())
225    }
226}
227
228mod sealed {
229    pub trait Sealed {}
230    impl<const C: usize> Sealed for super::FixedRowStorage<C> {}
231    impl Sealed for super::DynRowStorage {}
232    impl Sealed for Vec<i32> {}
233    impl<const L: usize> Sealed for [i32; L] {}
234    impl<const C: usize, const R: usize> Sealed for super::FixedGridStorage<C, R> {}
235    impl Sealed for super::DynGridStorage {}
236}