MutableVec

Struct MutableVec 

Source
pub struct MutableVec<T> { /* private fields */ }
Expand description

Wrapper around a Vec that emits mutations as VecDiffs, enabling diff-less constant-time reactive updates for downstream SignalVecs.

Implementations§

Source§

impl<T> MutableVec<T>

Source

pub fn read<'s>( &self, mutable_vec_data_reader: impl ReadMutableVecData<'s, T>, ) -> MutableVecReadGuard<'s, T>
where T: SSs,

Provides read-only access to the underlying Vec via either a &World or a &Query<MutableVecData<T>>.

Source

pub fn write<'w>( &self, mutable_vec_data_writer: impl WriteMutableVecData<'w, T>, ) -> MutableVecWriteGuard<'w, T>
where T: SSs,

Provides write access to the underlying Vec via either a &mut World or a &mut Query<&mut MutableVecData<T>>.

Examples found in repository?
examples/test.rs (line 144)
139fn hotkeys(
140    keys: Res<ButtonInput<KeyCode>>,
141    numbers: ResMut<Numbers>,
142    mut mutable_vec_datas: Query<&mut MutableVecData<i32>>,
143) {
144    let mut guard = numbers.0.write(&mut mutable_vec_datas);
145    if keys.just_pressed(KeyCode::Equal) {
146        guard.push((guard.len() + 1) as i32);
147    } else if keys.just_pressed(KeyCode::Minus) {
148        guard.pop();
149    }
150}
More examples
Hide additional examples
examples/filters.rs (line 119)
86fn ui(items: MutableVec<Data>, rows: MutableVec<()>) -> JonmoBuilder {
87    JonmoBuilder::from(Node {
88        height: Val::Percent(100.),
89        width: Val::Percent(100.),
90        ..default()
91    })
92    .child(
93        JonmoBuilder::from(Node {
94            flex_direction: FlexDirection::Column,
95            align_self: AlignSelf::Start,
96            justify_self: JustifySelf::Start,
97            row_gap: Val::Px(GAP * 2.),
98            padding: UiRect::all(Val::Px(GAP * 4.)),
99            ..default()
100        })
101        .child(
102            JonmoBuilder::from((Node {
103                flex_direction: FlexDirection::Row,
104                align_items: AlignItems::Center,
105                column_gap: Val::Px(GAP * 2.),
106                ..default()
107            },))
108            .child(JonmoBuilder::from((
109                Node::default(),
110                Text::new("source"),
111                TextColor(Color::WHITE),
112                TextFont::from_font_size(30.),
113                TextLayout::new_with_justify(JustifyText::Center),
114            )))
115            .child(button("+", -2.).apply(on_click(
116                |_: Trigger<Pointer<Click>>,
117                 datas: Res<Datas>,
118                 mut mutable_vec_datas: Query<&mut MutableVecData<_>>| {
119                    datas.0.write(&mut mutable_vec_datas).insert(0, random_data());
120                },
121            )))
122            .child(
123                JonmoBuilder::from(Node {
124                    flex_direction: FlexDirection::Row,
125                    align_items: AlignItems::Center,
126                    column_gap: Val::Px(GAP),
127                    ..default()
128                })
129                .children_signal_vec(
130                    items
131                        .signal_vec()
132                        .enumerate()
133                        .map_in(|(index, data)| item(index.dedupe(), data)),
134                ),
135            ),
136        )
137        .children_signal_vec(
138            rows.signal_vec()
139                .enumerate()
140                .map_in(clone!((items) move |(index, _)| row(index.dedupe(), items.clone()))),
141        )
142        .child(
143            JonmoBuilder::from((
144                Node {
145                    height: Val::Px(55.),
146                    justify_content: JustifyContent::Center,
147                    flex_direction: FlexDirection::Column,
148                    ..default()
149                },
150                // BackgroundColor(Color::WHITE),
151            ))
152            .child(button("+", -2.).apply(on_click(
153                |_: Trigger<Pointer<Click>>, rows: Res<Rows>, mut mutable_vec_datas: Query<&mut MutableVecData<_>>| {
154                    rows.0.write(&mut mutable_vec_datas).push(());
155                },
156            ))),
157        ),
158    )
159}
160
161fn random_subset<T: Clone>(items: &[T]) -> Vec<T> {
162    let mut rng = rand::rng();
163    loop {
164        let subset: Vec<T> = items
165            .iter()
166            .filter(|_| rng.random_bool(0.5)) // "Flip a coin" for each item
167            .cloned() // Convert from `&&T` to `T`
168            .collect();
169
170        if !subset.is_empty() {
171            // If we have at least one item, return the subset
172            return subset;
173        }
174        // Otherwise, the loop continues and we try again
175    }
176}
177
178fn random_number_filters() -> NumberFilters {
179    NumberFilters(HashSet::from_iter(random_subset(&[Parity::Odd, Parity::Even])))
180}
181
182fn random_color_filters() -> ColorFilters {
183    ColorFilters(HashSet::from_iter(random_subset(&[
184        ColorEnum::Blue,
185        ColorEnum::Pink,
186        ColorEnum::White,
187    ])))
188}
189
190fn random_shape_filters() -> ShapeFilters {
191    ShapeFilters(HashSet::from_iter(random_subset(&[Shape::Square, Shape::Circle])))
192}
193
194fn maybe_insert_random_sorted(builder: JonmoBuilder) -> JonmoBuilder {
195    let mut rng = rand::rng();
196    if rng.random_bool(0.5) {
197        builder.insert(Sorted)
198    } else {
199        builder
200    }
201}
202
203fn text_node(text: &'static str) -> JonmoBuilder {
204    JonmoBuilder::from((
205        Node::default(),
206        Text::new(text),
207        TextColor(Color::WHITE),
208        TextLayout::new_with_justify(JustifyText::Center),
209        BorderRadius::all(Val::Px(GAP)),
210    ))
211}
212
213fn toggle<T: Eq + core::hash::Hash>(set: &mut HashSet<T>, value: T) {
214    if !set.remove(&value) {
215        set.insert(value);
216    }
217}
218
219fn on_click<M>(
220    on_click: impl IntoObserverSystem<Pointer<Click>, (), M> + SSs,
221) -> impl FnOnce(JonmoBuilder) -> JonmoBuilder {
222    move |builder: JonmoBuilder| {
223        builder.on_spawn(move |world, entity| {
224            world.entity_mut(entity).observe(on_click);
225        })
226    }
227}
228
229fn outline() -> Outline {
230    Outline {
231        width: Val::Px(1.),
232        ..default()
233    }
234}
235
236fn number_toggle(row_parent: LazyEntity, parity: Parity) -> impl Fn(JonmoBuilder) -> JonmoBuilder {
237    move |builder| {
238        builder
239            .apply(on_click(
240                clone!((row_parent) move |_: Trigger<Pointer<Click>>, mut number_filters: Query<&mut NumberFilters>| {
241                    toggle(&mut number_filters.get_mut(row_parent.get()).unwrap().0, parity);
242                }),
243            ))
244            .component_signal(
245                SignalBuilder::from_component_lazy(row_parent.clone())
246                    .dedupe()
247                    .map_in(move |NumberFilters(filters)| filters.contains(&parity))
248                    .dedupe()
249                    .map_true(|_: In<()>| outline()),
250            )
251    }
252}
253
254fn number_toggles(row_parent: LazyEntity) -> JonmoBuilder {
255    JonmoBuilder::from(Node {
256        flex_direction: FlexDirection::Column,
257        row_gap: Val::Px(2.),
258        ..default()
259    })
260    .child(
261        text_node("even")
262            .insert(TextFont::from_font_size(13.))
263            .insert(BackgroundColor(bevy::color::palettes::basic::GRAY.into()))
264            .apply(number_toggle(row_parent.clone(), Parity::Even)),
265    )
266    .child(
267        text_node("odd")
268            .insert(TextFont::from_font_size(13.))
269            .insert(BackgroundColor(bevy::color::palettes::basic::GRAY.into()))
270            .apply(number_toggle(row_parent.clone(), Parity::Odd)),
271    )
272    .child(
273        text_node("sort")
274            .insert(TextFont::from_font_size(13.))
275            .insert(BackgroundColor(bevy::color::palettes::basic::GRAY.into()))
276            .apply(on_click(
277                clone!((row_parent) move |_: Trigger<Pointer<Click>>, world: &mut World| {
278                    let mut entity = world.entity_mut(row_parent.get());
279                    if entity.take::<Sorted>().is_none() { entity.insert(Sorted); }
280                }),
281            ))
282            .component_signal(
283                SignalBuilder::from_lazy_entity(row_parent.clone())
284                    .has_component::<Sorted>()
285                    .dedupe()
286                    .map_true(|_: In<()>| outline()),
287            ),
288    )
289}
290
291fn shape_toggle(row_parent: LazyEntity, shape: Shape) -> JonmoBuilder {
292    JonmoBuilder::from((
293        Node {
294            width: Val::Px(20.),
295            height: Val::Px(20.),
296            ..default()
297        },
298        BackgroundColor(bevy::color::palettes::basic::GRAY.into()),
299    ))
300    .apply(on_click(
301        clone!((row_parent) move |_: Trigger<Pointer<Click>>, mut shape_filters: Query<&mut ShapeFilters>| {
302            toggle(&mut shape_filters.get_mut(row_parent.get()).unwrap().0, shape);
303        }),
304    ))
305    .component_signal(
306        SignalBuilder::from_component_lazy(row_parent.clone())
307            .dedupe()
308            .map_in(move |ShapeFilters(filters)| filters.contains(&shape))
309            .dedupe()
310            .map_true(|_: In<()>| outline()),
311    )
312}
313
314fn shape_toggles(row_parent: LazyEntity) -> JonmoBuilder {
315    JonmoBuilder::from(Node {
316        flex_direction: FlexDirection::Column,
317        justify_content: JustifyContent::Center,
318        row_gap: Val::Px(GAP),
319        ..default()
320    })
321    .child(shape_toggle(row_parent.clone(), Shape::Square))
322    .child(shape_toggle(row_parent.clone(), Shape::Circle).insert(BorderRadius::MAX))
323}
324
325fn color_toggles(row_parent: LazyEntity) -> JonmoBuilder {
326    JonmoBuilder::from(Node {
327        flex_direction: FlexDirection::Column,
328        justify_content: JustifyContent::Center,
329        row_gap: Val::Px(GAP),
330        ..default()
331    })
332    .children(
333        [ColorEnum::Blue, ColorEnum::Pink, ColorEnum::White]
334            .into_iter()
335            .map(move |color| {
336                JonmoBuilder::from((
337                    Node {
338                        width: Val::Px(15.),
339                        height: Val::Px(15.),
340                        border: UiRect::all(Val::Px(1.)),
341                        ..default()
342                    },
343                    BorderRadius::all(Val::Px(GAP)),
344                    BackgroundColor(color.into()),
345                    BorderColor(Color::BLACK),
346                ))
347                .apply(on_click(
348                    clone!((row_parent) move |_: Trigger<Pointer<Click>>, mut color_filters: Query<&mut ColorFilters>| {
349                        toggle(&mut color_filters.get_mut(row_parent.get()).unwrap().0, color);
350                    }),
351                ))
352                .component_signal(
353                    SignalBuilder::from_component_lazy(row_parent.clone())
354                        .dedupe()
355                        .map_in(move |ColorFilters(filters)| filters.contains(&color))
356                        .dedupe()
357                        .map_true(|_: In<()>| outline()),
358                )
359            }),
360    )
361}
362
363fn button(text: &'static str, offset: f32) -> JonmoBuilder {
364    JonmoBuilder::from((
365        Node {
366            width: Val::Px((ITEM_SIZE / 2) as f32),
367            height: Val::Px((ITEM_SIZE / 2) as f32),
368            justify_content: JustifyContent::Center,
369            border: UiRect::all(Val::Px(1.)),
370            ..default()
371        },
372        BackgroundColor(bevy::color::palettes::basic::GRAY.into()),
373        BorderColor(Color::WHITE),
374        BorderRadius::all(Val::Px(GAP)),
375    ))
376    .child(
377        text_node(text)
378            .with_component::<Node>(move |mut node| node.top = Val::Px(offset))
379            .insert(TextFont::from_font_size(24.)),
380    )
381}
382
383#[derive(Component, Clone)]
384struct Index(usize);
385
386fn row(index: impl Signal<Item = Option<usize>>, items: MutableVec<Data>) -> JonmoBuilder {
387    let row_parent = LazyEntity::new();
388    JonmoBuilder::from((
389        Node {
390            flex_direction: FlexDirection::Row,
391            align_items: AlignItems::Center,
392            column_gap: Val::Px(GAP * 2.),
393            ..default()
394        },
395        random_number_filters(),
396        random_color_filters(),
397        random_shape_filters(),
398    ))
399    .apply(maybe_insert_random_sorted)
400    .entity_sync(row_parent.clone())
401    .child(
402        button("-", -3.)
403            .component_signal(index.map_in(|index| index.map(Index)))
404            .apply(on_click(
405                |click: Trigger<Pointer<Click>>,
406                 rows: Res<Rows>,
407                 indices: Query<&Index>,
408                 mut mutable_vec_datas: Query<&mut MutableVecData<_>>| {
409                    if let Ok(&Index(index)) = indices.get(click.target()) {
410                        rows.0.write(&mut mutable_vec_datas).remove(index);
411                    }
412                },
413            )),
414    )
415    .child(
416        JonmoBuilder::from((Node {
417            flex_direction: FlexDirection::Row,
418            width: Val::Px(108.),
419            height: Val::Percent(100.),
420            column_gap: Val::Px(GAP * 2.),
421            justify_content: JustifyContent::Center,
422            ..default()
423        },))
424        .child(number_toggles(row_parent.clone()))
425        .child(shape_toggles(row_parent.clone()))
426        .child(color_toggles(row_parent.clone())),
427    )
428    .child(
429        JonmoBuilder::from((Node {
430            flex_direction: FlexDirection::Row,
431            align_items: AlignItems::Center,
432            column_gap: Val::Px(GAP),
433            ..default()
434        },))
435        .children_signal_vec(
436            SignalBuilder::from_lazy_entity(row_parent.clone())
437                .has_component::<Sorted>()
438                .dedupe()
439                .switch_signal_vec(move |In(sorted)| {
440                    let base = items.signal_vec().enumerate();
441                    if sorted {
442                        base.sort_by_key(|In((_, Data { number, .. }))| number).left_either()
443                    } else {
444                        base.right_either()
445                    }
446                })
447                .filter_signal(clone!((row_parent) move | In((_, Data { number, .. })) | {
448                    SignalBuilder::from_component_lazy(row_parent.clone())
449                        .dedupe()
450                        .map_in(move |number_filters: NumberFilters| {
451                            number_filters.0.contains(&if number.is_multiple_of(2) {
452                                Parity::Even
453                            } else {
454                                Parity::Odd
455                            })
456                        })
457                        .dedupe()
458                }))
459                .filter_signal(clone!((row_parent) move | In((_, Data { shape, .. })) | {
460                    SignalBuilder::from_component_lazy(row_parent.clone())
461                        .dedupe()
462                        .map_in(move |shape_filters: ShapeFilters| shape_filters.0.contains(&shape))
463                        .dedupe()
464                }))
465                .filter_signal(clone!((row_parent) move | In((_, Data { color, .. })) | {
466                    SignalBuilder::from_component_lazy(row_parent.clone())
467                        .dedupe()
468                        .map_in(move |color_filters: ColorFilters| color_filters.0.contains(&color))
469                        .dedupe()
470                }))
471                .map_in(|(index, data)| item(index.dedupe(), data)),
472        ),
473    )
474}
475
476const ITEM_SIZE: u32 = 50;
477
478#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
479enum Shape {
480    Square,
481    Circle,
482}
483
484#[derive(Clone, Copy, PartialEq, Hash, Eq, Debug)]
485enum Parity {
486    Even,
487    Odd,
488}
489
490fn item(index: impl Signal<Item = Option<usize>>, Data { number, color, shape }: Data) -> JonmoBuilder {
491    JonmoBuilder::from((
492        Node {
493            height: Val::Px(ITEM_SIZE as f32),
494            width: Val::Px(ITEM_SIZE as f32),
495            align_items: AlignItems::Center,
496            justify_content: JustifyContent::Center,
497            ..default()
498        },
499        BackgroundColor(color.into()),
500        match shape {
501            Shape::Square => BorderRadius::default(),
502            Shape::Circle => BorderRadius::MAX,
503        },
504    ))
505    .component_signal(index.map_in(|index| index.map(Index)))
506    .apply(on_click(
507        |click: Trigger<Pointer<Click>>,
508         datas: Res<Datas>,
509         indices: Query<&Index>,
510         mut mutable_vec_datas: Query<&mut MutableVecData<_>>| {
511            if let Ok(&Index(index)) = indices.get(click.target()) {
512                datas.0.write(&mut mutable_vec_datas).remove(index);
513            }
514        },
515    ))
516    .child((
517        Node::default(),
518        Text::new(number.to_string()),
519        TextColor(Color::BLACK),
520        TextLayout::new_with_justify(JustifyText::Center),
521    ))
522}
examples/lifetimes.rs (line 130)
81fn ui_root(colors: impl SignalVec<Item = Color>) -> JonmoBuilder {
82    // A standard vertical flexbox to hold our list items.
83    JonmoBuilder::from(Node {
84        height: Val::Percent(100.0),
85        width: Val::Percent(100.0),
86        flex_direction: FlexDirection::Column,
87        align_items: AlignItems::Center,
88        justify_content: JustifyContent::Center,
89        row_gap: Val::Px(10.0),
90        ..default()
91    })
92    // This is the core of the dynamic list.
93    // `children_signal_vec` subscribes to a `SignalVec`. For each item in the
94    // vector, it spawns a child entity using the `JonmoBuilder` returned by the closure.
95    // It handles all diffs automatically: `Push` creates a new child, `RemoveAt`
96    // despawns one, `Move` reorders them, etc.
97    .children_signal_vec(
98        // `.enumerate()` is a powerful combinator that transforms a `SignalVec<T>`
99        // into a `SignalVec<(Signal<Option<usize>>, T)>`.
100        // The first element of the tuple is a *new signal* that will always contain
101        // the current index of that specific item, or `None` if it has been removed.
102        // This is crucial for displaying the index or for actions like removing a specific item.
103        colors.enumerate().map_in(|(index, color)| item(index.dedupe(), color)),
104    )
105    .child(
106        JonmoBuilder::from((
107            Node {
108                height: Val::Px(40.),
109                width: Val::Px(100.),
110                align_items: AlignItems::Center,
111                justify_content: JustifyContent::Center,
112                ..default()
113            },
114            BackgroundColor(bevy::color::palettes::basic::GREEN.into()),
115        ))
116        // `on_spawn` runs a closure with access to the `World` and the spawned `Entity`
117        // just after the entity is created. This is a good place to set up observers or
118        // other one-time logic.
119        .on_spawn(|world, entity| {
120            // `observe` is a Bevy event-handling pattern. Here, we're setting up this
121            // button entity to listen for a `Click` event.
122            world.entity_mut(entity).observe(
123                // This closure is the event handler that runs when the button is clicked.
124                move |_: Trigger<Pointer<Click>>,
125                      colors: Res<Colors>,
126                      mut mutable_vec_datas: Query<&mut MutableVecData<_>>| {
127                    // Try to get the `Index` component from the clicked entity.
128                    // We found the index! Now we can mutate the central data source.
129                    // `colors.0.write()` gets a write lock on the `MutableVec`.
130                    let mut guard = colors.0.write(&mut mutable_vec_datas);
131                    guard.insert(guard.len(), random_color());
132                },
133            );
134        })
135        .child(JonmoBuilder::from((
136            Node::default(),
137            Text::new("+"),
138            TextColor(Color::WHITE),
139            TextLayout::new_with_justify(JustifyText::Center),
140        ))),
141    )
142}
143
144/// A component to hold the index of a list item. This is inserted onto the
145/// "remove" button so that when it's clicked, we know which item in the
146/// `MutableVec` to remove.
147#[derive(Component, Clone)]
148struct Index(usize);
149
150/// Constructs a `JonmoBuilder` for a single item in our list.
151///
152/// # Arguments
153/// * `index` - A `Signal<Item = Option<usize>>` that provides the current index of this item. This
154///   signal is provided by the `.enumerate()` call in `ui_root`.
155/// * `color` - The `Color` for this specific item.
156fn item(index: impl Signal<Item = Option<usize>> + Clone, color: Color) -> JonmoBuilder {
157    // --- The LazyEntity Pattern ---
158    // `LazyEntity` is a thread-safe, clone-able handle to an `Entity` that can be
159    // created *before* the entity is spawned.
160    // We need this because we want to create a signal for the text display that *reads*
161    // the `Lifetime` component from its own parent entity. When we define the text signal,
162    // the parent entity doesn't exist yet. `LazyEntity` acts as a promise that will be
163    // fulfilled later.
164    let lifetime_holder = LazyEntity::new();
165
166    JonmoBuilder::from((
167        Node {
168            height: Val::Px(40.0),
169            width: Val::Px(350.0),
170            align_items: AlignItems::Center,
171            flex_direction: FlexDirection::Row,
172            column_gap: Val::Px(10.0),
173            ..default()
174        },
175        // Each item gets its own `Lifetime` component, which will be updated by the `live` system.
176        Lifetime::default(),
177    ))
178    // Here we fulfill the promise. `entity_sync` will set the `Entity` id into the
179    // `lifetime_holder` once this `JonmoBuilder` is spawned into an actual entity.
180    // Any signals that were created using `lifetime_holder` will now point to the correct entity.
181    .entity_sync(lifetime_holder.clone())
182    .child({
183        // The main info panel for the item.
184        JonmoBuilder::from((
185            Node {
186                height: Val::Percent(100.),
187                width: Val::Percent(90.),
188                align_items: AlignItems::Center,
189                justify_content: JustifyContent::Center,
190                ..default()
191            },
192            BackgroundColor(color),
193        ))
194        .child(
195            // This `JonmoBuilder` will hold the text. Bevy UI text is composed of `TextSection`s,
196            // which are children of a `Text` entity. We use `JonmoBuilder`'s child methods to
197            // construct these sections reactively.
198            JonmoBuilder::from((
199                Node::default(),
200                // Start with a `Text` component with no sections. We'll add them as children.
201                Text::new(""),
202                TextColor(Color::BLACK), // Default color, can be overridden by children.
203                TextLayout::new_with_justify(JustifyText::Center),
204            ))
205            // Child 1: A static text span.
206            .child((TextColor(Color::BLACK), TextSpan::new("item ")))
207            // Child 2: A reactive text span for the index.
208            .child(
209                JonmoBuilder::from(TextColor(Color::BLACK)).component_signal(
210                    // `component_signal` takes a signal and uses its output to insert/update a component.
211                    index
212                        .clone()
213                        .map_in(|index| index.as_ref().map(ToString::to_string).map(TextSpan)),
214                ),
215            )
216            // Child 3: Another static text span.
217            .child((TextColor(Color::BLACK), TextSpan::new(" | lifetime: ")))
218            // Child 4: A reactive text span for the lifetime.
219            .child(
220                JonmoBuilder::from(TextColor(Color::BLACK)).component_signal(
221                    // This is where the `LazyEntity` becomes powerful.
222                    // We create a signal that reads a component from the entity that `lifetime_holder` will eventually
223                    // point to.
224                    SignalBuilder::from_component_lazy(lifetime_holder)
225                        // Map the `Lifetime` component to its inner `f32` value and round it.
226                        .map_in(|Lifetime(lifetime)| lifetime.round())
227                        // `dedupe` is a crucial optimization. It ensures the rest of the signal chain only runs
228                        // when the rounded lifetime value actually changes (once per second in this case),
229                        // not on every single frame.
230                        .dedupe()
231                        // Convert the rounded `f32` to a `String`.
232                        .map_in_ref(ToString::to_string)
233                        // Wrap it in a `TextSpan` component for display.
234                        .map_in(TextSpan)
235                        .map_in(Some),
236                ),
237            ),
238        )
239    })
240    // Add the "remove" button as a child of the item row.
241    .child(
242        JonmoBuilder::from((
243            Node {
244                height: Val::Percent(100.),
245                width: Val::Percent(10.),
246                align_items: AlignItems::Center,
247                justify_content: JustifyContent::Center,
248                ..default()
249            },
250            // Using a color from Bevy's built-in palette for the button.
251            BackgroundColor(bevy::color::palettes::basic::RED.into()),
252        ))
253        // `on_spawn` runs a closure with access to the `World` and the spawned `Entity`
254        // just after the entity is created. This is a good place to set up observers or
255        // other one-time logic.
256        .on_spawn(|world, entity| {
257            // `observe` is a Bevy event-handling pattern. Here, we're setting up this
258            // button entity to listen for a `Click` event.
259            world.entity_mut(entity).observe(
260                // This closure is the event handler that runs when the button is clicked.
261                move |_: Trigger<Pointer<Click>>,
262                      indices: Query<&Index>,
263                      colors: Res<Colors>,
264                      mut mutable_vec_datas: Query<&mut MutableVecData<_>>| {
265                    // Try to get the `Index` component from the clicked entity.
266                    if let Ok(&Index(index)) = indices.get(entity) {
267                        // We found the index! Now we can mutate the central data source.
268                        // `colors.0.write()` gets a write lock on the `MutableVec`.
269                        colors.0.write(&mut mutable_vec_datas).remove(index);
270                    }
271                },
272            );
273        })
274        // To make the observer work, the button entity needs to *have* an `Index` component.
275        // We use `component_signal` again to reactively insert the `Index` component,
276        // driven by the same `index` signal we used for the display text.
277        .component_signal(index.map_in(|index| index.map(Index)))
278        .child(JonmoBuilder::from((
279            Node::default(),
280            Text::new("x"),
281            TextColor(Color::WHITE),
282            TextLayout::new_with_justify(JustifyText::Center),
283        ))),
284    )
285}
Source

pub fn signal_vec(&self) -> Source<T>
where T: Clone + SSs,

Returns a Source signal from this MutableVec.

Examples found in repository?
examples/lifetimes.rs (line 48)
22fn main() {
23    let mut app = App::new();
24    let world = app.world_mut();
25    // 1. --- DATA SOURCE SETUP ---
26    // `MutableVec` is the core reactive data source for lists in `jonmo`.
27    // We initialize it with two random colors.
28    // It's wrapped in an `Arc<RwLock<...>>` internally, so cloning it is cheap
29    // and allows multiple systems to access and modify the same data.
30    let colors = MutableVecBuilder::from([random_color(), random_color()]).spawn(world);
31
32    app.add_plugins(examples_plugin)
33        // 2. --- RESOURCE MANAGEMENT ---
34        // We insert a clone of our `MutableVec` into a Bevy resource. This makes it
35        // accessible to any system that needs to read or modify the list of colors,
36        // such as our `hotkeys` system or the remove button's `observe` system.
37        .insert_resource(Colors(colors.clone()))
38        .add_systems(
39            // We use `PostStartup` to ensure that Bevy's UI systems are initialized
40            // before we try to spawn our UI.
41            Startup,
42            (
43                // 3. --- UI SPAWNING ---
44                // We move the `colors` `MutableVec` into a closure that will spawn the UI.
45                // `colors.signal_vec()` creates a `SignalVec`, which is a stream of
46                // changes (`VecDiff`s) that other parts of the UI can subscribe to.
47                move |world: &mut World| {
48                    ui_root(colors.signal_vec()).spawn(world);
49                },
50                camera,
51            ),
52        )
53        // 4. --- UPDATE SYSTEMS ---
54        // These systems run every frame.
55        .add_systems(
56            Update,
57            (
58                // The `live` system increments the lifetime of each list item.
59                // It only runs if there is at least one entity with a `Lifetime` component.
60                live.run_if(any_with_component::<Lifetime>),
61            ),
62        )
63        .run();
64}
More examples
Hide additional examples
examples/filters.rs (line 131)
86fn ui(items: MutableVec<Data>, rows: MutableVec<()>) -> JonmoBuilder {
87    JonmoBuilder::from(Node {
88        height: Val::Percent(100.),
89        width: Val::Percent(100.),
90        ..default()
91    })
92    .child(
93        JonmoBuilder::from(Node {
94            flex_direction: FlexDirection::Column,
95            align_self: AlignSelf::Start,
96            justify_self: JustifySelf::Start,
97            row_gap: Val::Px(GAP * 2.),
98            padding: UiRect::all(Val::Px(GAP * 4.)),
99            ..default()
100        })
101        .child(
102            JonmoBuilder::from((Node {
103                flex_direction: FlexDirection::Row,
104                align_items: AlignItems::Center,
105                column_gap: Val::Px(GAP * 2.),
106                ..default()
107            },))
108            .child(JonmoBuilder::from((
109                Node::default(),
110                Text::new("source"),
111                TextColor(Color::WHITE),
112                TextFont::from_font_size(30.),
113                TextLayout::new_with_justify(JustifyText::Center),
114            )))
115            .child(button("+", -2.).apply(on_click(
116                |_: Trigger<Pointer<Click>>,
117                 datas: Res<Datas>,
118                 mut mutable_vec_datas: Query<&mut MutableVecData<_>>| {
119                    datas.0.write(&mut mutable_vec_datas).insert(0, random_data());
120                },
121            )))
122            .child(
123                JonmoBuilder::from(Node {
124                    flex_direction: FlexDirection::Row,
125                    align_items: AlignItems::Center,
126                    column_gap: Val::Px(GAP),
127                    ..default()
128                })
129                .children_signal_vec(
130                    items
131                        .signal_vec()
132                        .enumerate()
133                        .map_in(|(index, data)| item(index.dedupe(), data)),
134                ),
135            ),
136        )
137        .children_signal_vec(
138            rows.signal_vec()
139                .enumerate()
140                .map_in(clone!((items) move |(index, _)| row(index.dedupe(), items.clone()))),
141        )
142        .child(
143            JonmoBuilder::from((
144                Node {
145                    height: Val::Px(55.),
146                    justify_content: JustifyContent::Center,
147                    flex_direction: FlexDirection::Column,
148                    ..default()
149                },
150                // BackgroundColor(Color::WHITE),
151            ))
152            .child(button("+", -2.).apply(on_click(
153                |_: Trigger<Pointer<Click>>, rows: Res<Rows>, mut mutable_vec_datas: Query<&mut MutableVecData<_>>| {
154                    rows.0.write(&mut mutable_vec_datas).push(());
155                },
156            ))),
157        ),
158    )
159}
160
161fn random_subset<T: Clone>(items: &[T]) -> Vec<T> {
162    let mut rng = rand::rng();
163    loop {
164        let subset: Vec<T> = items
165            .iter()
166            .filter(|_| rng.random_bool(0.5)) // "Flip a coin" for each item
167            .cloned() // Convert from `&&T` to `T`
168            .collect();
169
170        if !subset.is_empty() {
171            // If we have at least one item, return the subset
172            return subset;
173        }
174        // Otherwise, the loop continues and we try again
175    }
176}
177
178fn random_number_filters() -> NumberFilters {
179    NumberFilters(HashSet::from_iter(random_subset(&[Parity::Odd, Parity::Even])))
180}
181
182fn random_color_filters() -> ColorFilters {
183    ColorFilters(HashSet::from_iter(random_subset(&[
184        ColorEnum::Blue,
185        ColorEnum::Pink,
186        ColorEnum::White,
187    ])))
188}
189
190fn random_shape_filters() -> ShapeFilters {
191    ShapeFilters(HashSet::from_iter(random_subset(&[Shape::Square, Shape::Circle])))
192}
193
194fn maybe_insert_random_sorted(builder: JonmoBuilder) -> JonmoBuilder {
195    let mut rng = rand::rng();
196    if rng.random_bool(0.5) {
197        builder.insert(Sorted)
198    } else {
199        builder
200    }
201}
202
203fn text_node(text: &'static str) -> JonmoBuilder {
204    JonmoBuilder::from((
205        Node::default(),
206        Text::new(text),
207        TextColor(Color::WHITE),
208        TextLayout::new_with_justify(JustifyText::Center),
209        BorderRadius::all(Val::Px(GAP)),
210    ))
211}
212
213fn toggle<T: Eq + core::hash::Hash>(set: &mut HashSet<T>, value: T) {
214    if !set.remove(&value) {
215        set.insert(value);
216    }
217}
218
219fn on_click<M>(
220    on_click: impl IntoObserverSystem<Pointer<Click>, (), M> + SSs,
221) -> impl FnOnce(JonmoBuilder) -> JonmoBuilder {
222    move |builder: JonmoBuilder| {
223        builder.on_spawn(move |world, entity| {
224            world.entity_mut(entity).observe(on_click);
225        })
226    }
227}
228
229fn outline() -> Outline {
230    Outline {
231        width: Val::Px(1.),
232        ..default()
233    }
234}
235
236fn number_toggle(row_parent: LazyEntity, parity: Parity) -> impl Fn(JonmoBuilder) -> JonmoBuilder {
237    move |builder| {
238        builder
239            .apply(on_click(
240                clone!((row_parent) move |_: Trigger<Pointer<Click>>, mut number_filters: Query<&mut NumberFilters>| {
241                    toggle(&mut number_filters.get_mut(row_parent.get()).unwrap().0, parity);
242                }),
243            ))
244            .component_signal(
245                SignalBuilder::from_component_lazy(row_parent.clone())
246                    .dedupe()
247                    .map_in(move |NumberFilters(filters)| filters.contains(&parity))
248                    .dedupe()
249                    .map_true(|_: In<()>| outline()),
250            )
251    }
252}
253
254fn number_toggles(row_parent: LazyEntity) -> JonmoBuilder {
255    JonmoBuilder::from(Node {
256        flex_direction: FlexDirection::Column,
257        row_gap: Val::Px(2.),
258        ..default()
259    })
260    .child(
261        text_node("even")
262            .insert(TextFont::from_font_size(13.))
263            .insert(BackgroundColor(bevy::color::palettes::basic::GRAY.into()))
264            .apply(number_toggle(row_parent.clone(), Parity::Even)),
265    )
266    .child(
267        text_node("odd")
268            .insert(TextFont::from_font_size(13.))
269            .insert(BackgroundColor(bevy::color::palettes::basic::GRAY.into()))
270            .apply(number_toggle(row_parent.clone(), Parity::Odd)),
271    )
272    .child(
273        text_node("sort")
274            .insert(TextFont::from_font_size(13.))
275            .insert(BackgroundColor(bevy::color::palettes::basic::GRAY.into()))
276            .apply(on_click(
277                clone!((row_parent) move |_: Trigger<Pointer<Click>>, world: &mut World| {
278                    let mut entity = world.entity_mut(row_parent.get());
279                    if entity.take::<Sorted>().is_none() { entity.insert(Sorted); }
280                }),
281            ))
282            .component_signal(
283                SignalBuilder::from_lazy_entity(row_parent.clone())
284                    .has_component::<Sorted>()
285                    .dedupe()
286                    .map_true(|_: In<()>| outline()),
287            ),
288    )
289}
290
291fn shape_toggle(row_parent: LazyEntity, shape: Shape) -> JonmoBuilder {
292    JonmoBuilder::from((
293        Node {
294            width: Val::Px(20.),
295            height: Val::Px(20.),
296            ..default()
297        },
298        BackgroundColor(bevy::color::palettes::basic::GRAY.into()),
299    ))
300    .apply(on_click(
301        clone!((row_parent) move |_: Trigger<Pointer<Click>>, mut shape_filters: Query<&mut ShapeFilters>| {
302            toggle(&mut shape_filters.get_mut(row_parent.get()).unwrap().0, shape);
303        }),
304    ))
305    .component_signal(
306        SignalBuilder::from_component_lazy(row_parent.clone())
307            .dedupe()
308            .map_in(move |ShapeFilters(filters)| filters.contains(&shape))
309            .dedupe()
310            .map_true(|_: In<()>| outline()),
311    )
312}
313
314fn shape_toggles(row_parent: LazyEntity) -> JonmoBuilder {
315    JonmoBuilder::from(Node {
316        flex_direction: FlexDirection::Column,
317        justify_content: JustifyContent::Center,
318        row_gap: Val::Px(GAP),
319        ..default()
320    })
321    .child(shape_toggle(row_parent.clone(), Shape::Square))
322    .child(shape_toggle(row_parent.clone(), Shape::Circle).insert(BorderRadius::MAX))
323}
324
325fn color_toggles(row_parent: LazyEntity) -> JonmoBuilder {
326    JonmoBuilder::from(Node {
327        flex_direction: FlexDirection::Column,
328        justify_content: JustifyContent::Center,
329        row_gap: Val::Px(GAP),
330        ..default()
331    })
332    .children(
333        [ColorEnum::Blue, ColorEnum::Pink, ColorEnum::White]
334            .into_iter()
335            .map(move |color| {
336                JonmoBuilder::from((
337                    Node {
338                        width: Val::Px(15.),
339                        height: Val::Px(15.),
340                        border: UiRect::all(Val::Px(1.)),
341                        ..default()
342                    },
343                    BorderRadius::all(Val::Px(GAP)),
344                    BackgroundColor(color.into()),
345                    BorderColor(Color::BLACK),
346                ))
347                .apply(on_click(
348                    clone!((row_parent) move |_: Trigger<Pointer<Click>>, mut color_filters: Query<&mut ColorFilters>| {
349                        toggle(&mut color_filters.get_mut(row_parent.get()).unwrap().0, color);
350                    }),
351                ))
352                .component_signal(
353                    SignalBuilder::from_component_lazy(row_parent.clone())
354                        .dedupe()
355                        .map_in(move |ColorFilters(filters)| filters.contains(&color))
356                        .dedupe()
357                        .map_true(|_: In<()>| outline()),
358                )
359            }),
360    )
361}
362
363fn button(text: &'static str, offset: f32) -> JonmoBuilder {
364    JonmoBuilder::from((
365        Node {
366            width: Val::Px((ITEM_SIZE / 2) as f32),
367            height: Val::Px((ITEM_SIZE / 2) as f32),
368            justify_content: JustifyContent::Center,
369            border: UiRect::all(Val::Px(1.)),
370            ..default()
371        },
372        BackgroundColor(bevy::color::palettes::basic::GRAY.into()),
373        BorderColor(Color::WHITE),
374        BorderRadius::all(Val::Px(GAP)),
375    ))
376    .child(
377        text_node(text)
378            .with_component::<Node>(move |mut node| node.top = Val::Px(offset))
379            .insert(TextFont::from_font_size(24.)),
380    )
381}
382
383#[derive(Component, Clone)]
384struct Index(usize);
385
386fn row(index: impl Signal<Item = Option<usize>>, items: MutableVec<Data>) -> JonmoBuilder {
387    let row_parent = LazyEntity::new();
388    JonmoBuilder::from((
389        Node {
390            flex_direction: FlexDirection::Row,
391            align_items: AlignItems::Center,
392            column_gap: Val::Px(GAP * 2.),
393            ..default()
394        },
395        random_number_filters(),
396        random_color_filters(),
397        random_shape_filters(),
398    ))
399    .apply(maybe_insert_random_sorted)
400    .entity_sync(row_parent.clone())
401    .child(
402        button("-", -3.)
403            .component_signal(index.map_in(|index| index.map(Index)))
404            .apply(on_click(
405                |click: Trigger<Pointer<Click>>,
406                 rows: Res<Rows>,
407                 indices: Query<&Index>,
408                 mut mutable_vec_datas: Query<&mut MutableVecData<_>>| {
409                    if let Ok(&Index(index)) = indices.get(click.target()) {
410                        rows.0.write(&mut mutable_vec_datas).remove(index);
411                    }
412                },
413            )),
414    )
415    .child(
416        JonmoBuilder::from((Node {
417            flex_direction: FlexDirection::Row,
418            width: Val::Px(108.),
419            height: Val::Percent(100.),
420            column_gap: Val::Px(GAP * 2.),
421            justify_content: JustifyContent::Center,
422            ..default()
423        },))
424        .child(number_toggles(row_parent.clone()))
425        .child(shape_toggles(row_parent.clone()))
426        .child(color_toggles(row_parent.clone())),
427    )
428    .child(
429        JonmoBuilder::from((Node {
430            flex_direction: FlexDirection::Row,
431            align_items: AlignItems::Center,
432            column_gap: Val::Px(GAP),
433            ..default()
434        },))
435        .children_signal_vec(
436            SignalBuilder::from_lazy_entity(row_parent.clone())
437                .has_component::<Sorted>()
438                .dedupe()
439                .switch_signal_vec(move |In(sorted)| {
440                    let base = items.signal_vec().enumerate();
441                    if sorted {
442                        base.sort_by_key(|In((_, Data { number, .. }))| number).left_either()
443                    } else {
444                        base.right_either()
445                    }
446                })
447                .filter_signal(clone!((row_parent) move | In((_, Data { number, .. })) | {
448                    SignalBuilder::from_component_lazy(row_parent.clone())
449                        .dedupe()
450                        .map_in(move |number_filters: NumberFilters| {
451                            number_filters.0.contains(&if number.is_multiple_of(2) {
452                                Parity::Even
453                            } else {
454                                Parity::Odd
455                            })
456                        })
457                        .dedupe()
458                }))
459                .filter_signal(clone!((row_parent) move | In((_, Data { shape, .. })) | {
460                    SignalBuilder::from_component_lazy(row_parent.clone())
461                        .dedupe()
462                        .map_in(move |shape_filters: ShapeFilters| shape_filters.0.contains(&shape))
463                        .dedupe()
464                }))
465                .filter_signal(clone!((row_parent) move | In((_, Data { color, .. })) | {
466                    SignalBuilder::from_component_lazy(row_parent.clone())
467                        .dedupe()
468                        .map_in(move |color_filters: ColorFilters| color_filters.0.contains(&color))
469                        .dedupe()
470                }))
471                .map_in(|(index, data)| item(index.dedupe(), data)),
472        ),
473    )
474}
examples/test.rs (line 36)
35fn ui_root(numbers: MutableVec<i32>, world: &mut World) -> JonmoBuilder {
36    let list_a = MutableVecBuilder::from([1, 2, 3, 4, 5]).spawn(world).signal_vec();
37    let list_b = MutableVecBuilder::from([3, 4, 5]).spawn(world).signal_vec();
38    let map = MutableBTreeMapBuilder::from([(1, 2), (2, 3)]).spawn(world);
39    // map.signal_map().
40    JonmoBuilder::from(Node {
41        height: Val::Percent(100.0),
42        width: Val::Percent(100.0),
43        flex_direction: FlexDirection::Column,
44        align_items: AlignItems::Center,
45        justify_content: JustifyContent::Center,
46        row_gap: Val::Px(10.0),
47        ..default()
48    })
49    // .child_signal(numbers.clone().is_empty().map(|In(len)| item(len as u32)))
50    .children_signal_vec(
51        // MutableVec::from([numbers.signal_vec(), numbers.signal_vec()]).signal_vec()
52        numbers
53            .signal_vec()
54            // SignalBuilder::from_system(|_: In<()>| 1)
55            // SignalBuilder::from_system(|_: In<()>, toggle: Res<ToggleFilter>| toggle.0)
56            // .dedupe()
57            // .switch_signal_vec(move |In(toggle)| {
58            //     if toggle {
59            //         // println!("toggled to A");
60            //         list_a.clone()
61            //     } else {
62            //         // println!("toggled to B");
63            //         list_b.clone()
64            //     }
65            // })
66            // .dedupe()
67            // .to_signal_vec()
68            .filter_signal(|In(n)| {
69                SignalBuilder::from_system(move |_: In<()>, toggle: Res<ToggleFilter>| {
70                    n % 2 == if toggle.0 { 0 } else { 1 }
71                })
72            })
73            // .map_signal(|In(n): In<i32>| {
74            //     SignalBuilder::from_system(move |_: In<()>| n + 1).dedupe()
75            // })
76            // .debug()
77            // .map_in(|n: i32| -n)
78            // .sort_by_cmp()
79            // .flatten()
80            // .chain(numbers)
81            // .intersperse(0)
82            // .sort_by(|In((left, right)): In<(i32, i32)>| left.cmp(&right).reverse())
83            // .sort_by_key(|In(n): In<i32>| -n)
84            // .intersperse_with(|In(index_signal): In<jonmo::signal::Dedupe<jonmo::signal::Source<Option<usize>>>>, world: &mut World| {
85            //     let signal = index_signal.debug().register(world);
86            //     poll_signal(world, *signal)
87            //         .and_then(downcast_any_clone::<Option<usize>>).flatten().unwrap_or_default() as i32
88            // })
89            .map(|In(n)| item(n))
90            // .intersperse_with(
91            //     |index_signal: In<jonmo::signal::Dedupe<jonmo::signal::Source<Option<usize>>>>| {
92            //         JonmoBuilder::from(Node::default()).component_signal(
93            //             index_signal
94            //                 .debug()
95            //                 .map_in(|idx_opt| Text::new(format!("{}", idx_opt.unwrap_or(0)))),
96            //         )
97            //     },
98            // ),
99    )
100}

Trait Implementations§

Source§

impl<T> Clone for MutableVec<T>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<T> Drop for MutableVec<T>

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

impl<T> From<&mut Commands<'_, '_>> for MutableVec<T>
where T: Clone + SSs,

Source§

fn from(commands: &mut Commands<'_, '_>) -> Self

Converts to this type from the input type.
Source§

impl<T> From<&mut World> for MutableVec<T>
where T: Clone + SSs,

Source§

fn from(world: &mut World) -> Self

Converts to this type from the input type.
Source§

impl<T> FromWorld for MutableVec<T>
where T: Clone + SSs,

Source§

fn from_world(world: &mut World) -> Self

Creates Self using data from the given World.

Auto Trait Implementations§

§

impl<T> Freeze for MutableVec<T>

§

impl<T> RefUnwindSafe for MutableVec<T>

§

impl<T> Send for MutableVec<T>

§

impl<T> Sync for MutableVec<T>

§

impl<T> Unpin for MutableVec<T>

§

impl<T> UnwindSafe for MutableVec<T>

Blanket Implementations§

Source§

impl<T> Also for T

Source§

fn also<F>(self, block: F) -> Self
where F: FnOnce(&mut Self),

Apply a function to this value and return the (possibly) modified value.
Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T, Res> Apply<Res> for T
where T: ?Sized,

Source§

fn apply<F>(self, f: F) -> Res
where F: FnOnce(Self) -> Res, Self: Sized,

Apply a function which takes the parameter by value.
Source§

fn apply_ref<F>(&self, f: F) -> Res
where F: FnOnce(&Self) -> Res,

Apply a function which takes the parameter by reference.
Source§

fn apply_mut<F>(&mut self, f: F) -> Res
where F: FnOnce(&mut Self) -> Res,

Apply a function which takes the parameter by mutable reference.
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Converts Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Converts Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Converts &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Converts &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSend for T
where T: Any + Send,

Source§

fn into_any_send(self: Box<T>) -> Box<dyn Any + Send>

Converts Box<Trait> (where Trait: DowncastSend) to Box<dyn Any + Send>, which can then be downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> TypeData for T
where T: 'static + Send + Sync + Clone,

Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V

Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

impl<T> AnyClone for T
where T: Clone + 'static,

Source§

impl<T> ConditionalSend for T
where T: Send,

Source§

impl<T> SSs for T
where T: Send + Sync + 'static,