Skip to main content

cotis_modules_debug/declaration_debugger/
debug_element_configuring.rs

1//! Recording wrappers around [`cotis::element_configuring`] for stage-1 capture.
2//!
3//! Each wrapper delegates to the real configuring API and mirrors every operation into a
4//! [`LeafedInterfaceDeclaration`].
5//! [`DebugOpenElement`] and [`DebugConfiguredParentElement`] record [`Close`](crate::serialize_targets::SerializableInterfaceInstructions::Close)
6//! on drop if not closed explicitly.
7
8use cotis::element_configuring::{
9    ConfigureElements, ConfigureLeafElements, ConfiguredParentElement, OpenElement,
10};
11use serde::Serialize;
12
13use crate::serialize_targets::LeafedInterfaceDeclaration;
14
15/// Root debug wrapper used at the start of [`UiFn::draw_in`](cotis::cotis_app::UiFn::draw_in).
16///
17/// Wrap the layout root `ConfiguredParentElement` and pass a mutable reference to the
18/// declaration recorder. All child elements created via [`new_element`](Self::new_element)
19/// record [`Open`](crate::serialize_targets::SerializableInterfaceInstructions::Open)
20/// before delegating to the inner layout.
21pub struct DebugInitialConfiguredParentElement<
22    'b,
23    'element,
24    Configurer: ConfigureElements<ConfigType>,
25    ConfigType: Clone + Serialize,
26    List: Copy,
27> {
28    internal: &'b mut ConfiguredParentElement<'element, Configurer, ConfigType>,
29    interface_recorder: &'b mut LeafedInterfaceDeclaration<ConfigType, List>,
30}
31
32impl<
33    'b,
34    'element,
35    Configurer: ConfigureElements<ConfigType>,
36    ConfigType: Clone + Serialize,
37    List: Copy,
38> DebugInitialConfiguredParentElement<'b, 'element, Configurer, ConfigType, List>
39{
40    /// Creates a root wrapper that records into `interface_recorder`.
41    pub fn new(
42        internal: &'b mut ConfiguredParentElement<'element, Configurer, ConfigType>,
43        interface_recorder: &'b mut LeafedInterfaceDeclaration<ConfigType, List>,
44    ) -> Self {
45        Self {
46            internal,
47            interface_recorder,
48        }
49    }
50
51    /// Opens a new child element, recording `Open` in the declaration stream.
52    ///
53    /// Returns a [`DebugOpenElement`] that can be used to configure the new element.
54    pub fn new_element(&'_ mut self) -> DebugOpenElement<'_, Configurer, ConfigType, List>
55    where
56        Self: Sized,
57    {
58        self.interface_recorder.open();
59
60        let new_element = self.internal.new_element();
61        DebugOpenElement {
62            internal: Some(new_element),
63            interface_recorder: Some(&mut self.interface_recorder),
64        }
65    }
66
67    /// Closes the root element and records `Close` in the declaration stream.
68    ///
69    /// It is not strictly necessary to call this method; closing also occurs when the
70    /// wrapper is dropped after all child [`DebugOpenElement`] handles are released.
71    pub fn close_element(self) {
72        self.interface_recorder.close();
73    }
74}
75
76/// Debug wrapper for a parent element created via [`DebugOpenElement::make_parent`].
77///
78/// Records `Open` for each child via [`new_element`](Self::new_element). Records
79/// `Close` on drop.
80pub struct DebugConfiguredParentElement<
81    'element,
82    Configurer: ConfigureElements<ConfigType>,
83    ConfigType: Clone + Serialize,
84    List: Copy,
85> {
86    internal: ConfiguredParentElement<'element, Configurer, ConfigType>,
87    interface_recorder: &'element mut LeafedInterfaceDeclaration<ConfigType, List>,
88}
89
90impl<'element, Configurer: ConfigureElements<ConfigType>, ConfigType: Clone + Serialize, List: Copy>
91    DebugConfiguredParentElement<'element, Configurer, ConfigType, List>
92{
93    /// Creates a parent wrapper (typically via [`DebugOpenElement::make_parent`]).
94    pub fn new(
95        internal: ConfiguredParentElement<'element, Configurer, ConfigType>,
96        interface_recorder: &'element mut LeafedInterfaceDeclaration<ConfigType, List>,
97    ) -> Self {
98        Self {
99            internal,
100            interface_recorder,
101        }
102    }
103
104    /// Opens a new child element, recording `Open` in the declaration stream.
105    pub fn new_element(&'_ mut self) -> DebugOpenElement<'_, Configurer, ConfigType, List>
106    where
107        Self: Sized,
108    {
109        self.interface_recorder.open();
110
111        let new_element = self.internal.new_element();
112        DebugOpenElement {
113            internal: Some(new_element),
114            interface_recorder: Some(&mut self.interface_recorder),
115        }
116    }
117
118    /// Closes this parent element.
119    ///
120    /// `Close` is also recorded when this wrapper is dropped.
121    pub fn close_element(self) {
122        drop(self)
123    }
124}
125
126/// Debug wrapper for an open element being configured.
127///
128/// Use [`set_config`](Self::set_config) for parent configs and
129/// [`set_leaf_config`](Self::set_leaf_config) for leaf configs. Converting to a parent via
130/// [`make_parent`](Self::make_parent) does not record an extra instruction.
131pub struct DebugOpenElement<
132    'element,
133    Configurer: ConfigureElements<ConfigType>,
134    ConfigType: Clone + Serialize,
135    List: Copy,
136> {
137    internal: Option<OpenElement<'element, Configurer, ConfigType>>,
138    interface_recorder: Option<&'element mut LeafedInterfaceDeclaration<ConfigType, List>>,
139}
140
141impl<'element, ConfigType: Clone + Serialize, Configurer: ConfigureElements<ConfigType>, List: Copy>
142    DebugOpenElement<'element, Configurer, ConfigType, List>
143{
144    /// Sets the element config, recording `Configure` and applying it to the live element.
145    pub fn set_config(&mut self, config: ConfigType) {
146        self.interface_recorder
147            .as_mut()
148            .unwrap()
149            .add_config(config.clone());
150        self.internal.as_mut().unwrap().set_config(config);
151    }
152
153    /// Converts this open element into a parent that can accept children.
154    ///
155    /// Returns a [`DebugConfiguredParentElement`] wrapping the inner parent element.
156    pub fn make_parent(
157        mut self,
158    ) -> DebugConfiguredParentElement<'element, Configurer, ConfigType, List> {
159        DebugConfiguredParentElement {
160            internal: self.internal.take().unwrap().make_parent(),
161            interface_recorder: self.interface_recorder.take().unwrap(),
162        }
163    }
164
165    /// Closes this open element.
166    ///
167    /// `Close` is also recorded when this wrapper is dropped.
168    pub fn close_element(self) {
169        drop(self)
170    }
171
172    /// Sets a leaf-specific config, recording `LeafConfig` and applying it to the live element.
173    ///
174    /// Consumes `self` because the inner [`OpenElement::set_leaf_config`] also consumes
175    /// the open handle.
176    pub fn set_leaf_config<LeafConfig>(mut self, config: LeafConfig)
177    where
178        Configurer: ConfigureLeafElements<LeafConfig>,
179        LeafConfig: Serialize,
180    {
181        self.interface_recorder
182            .as_mut()
183            .unwrap()
184            .add_leaf_config(&config);
185        self.internal.take().unwrap().set_leaf_config(config);
186    }
187}
188
189/// Records `Close` when a [`DebugOpenElement`] is dropped without an explicit close.
190impl<'element, Configurer: ConfigureElements<ConfigType>, ConfigType: Clone + Serialize, List: Copy>
191    Drop for DebugOpenElement<'element, Configurer, ConfigType, List>
192{
193    fn drop(&mut self) {
194        match &mut self.interface_recorder {
195            None => {}
196            Some(recorder) => {
197                recorder.close();
198            }
199        }
200    }
201}
202
203/// Records `Close` when a [`DebugConfiguredParentElement`] is dropped.
204impl<'element, ConfigType: Clone + Serialize, Configurer: ConfigureElements<ConfigType>, List: Copy>
205    Drop for DebugConfiguredParentElement<'element, Configurer, ConfigType, List>
206{
207    fn drop(&mut self) {
208        self.interface_recorder.close();
209    }
210}