Global application state with FLTK library - user-interface

I'm writing an application using the fltk library.
The architecture of the application involves a global state that stores which page to display now (viewer) and store the viewer data.
There are buttons that sends a message to update and changes the global state indicating which viewer to display now.
#[derive(Clone, Copy)]
enum Message {
Update
}
#[derive(Clone, Copy)]
struct GlobalState {
viewer: Viewer,
}
impl GlobalState {
fn set_viewer(&mut self, v: Viewer) {
self.viewer = v;
}
}
#[derive(Clone, Copy)]
enum Viewer {
Page1,
Page2
}
fn main() {
let mut gs = GlobalState {viewer: Viewer::Page1};
let app = app::App::default().with_scheme(app::Scheme::Gtk);
let (s, r) = app::channel::<Message>();
let mut wind = Window::default().with_size(800, 600);
left_side(&mut gs);
let mut col = Column::new(155,70,800 - 150,600 - 65,None);
s.send(Message::Update);
col.end();
wind.end();
wind.show();
while app.wait() {
if let Some(msg) = r.recv() {
match msg {
Message::Update => {
match gs.viewer {
Viewer::Page1 => {
col.clear();
let view = view_ohm();
col.add(&view);
},
Viewer::Page2 => {
col.clear();
let view = view_ohm();
col.add(&view);
},
_ => ()
}
}
_ => (),
}
}
}
}
fn left_side(gs: &mut GlobalState) {
let btn_width = 130;
let btn_height = 30;
let (s, r) = app::channel::<Message>();
let mut grp = Group::default().with_size(65, 600);
let mut col = Pack::default()
.with_size(btn_width, 600)
.center_of_parent()
.with_type(PackType::Vertical);
col.set_spacing(2);
let mut btn = Button::new(0, 0, btn_width, btn_height, "Page 1");
btn.emit(s, Message::Update);
btn.set_callback(|_| {
gs.set_viewer(Viewer::Page1)
});
let mut btn = Button::new(0, 0, btn_width, btn_height, "Page 2");
btn.emit(s, Message::Update);
btn.set_callback(|_| {
gs.set_viewer(Viewer::Page2)
});
col.end();
grp.end();
}
Questions:
the code doesn't compile with error:
error[E0521]: borrowed data escapes outside of function
--> src/main.rs:89:5
|
74 | fn left_side(gs: &mut GlobalState) {
| -- - let's call the lifetime of this reference `'1`
| |
| `gs` is a reference that is only valid in the function body
...
89 | / btn.set_callback(|_| {
90 | | gs.set_viewer(Viewer::Page1)
91 | | });
| | ^
| | |
| |______`gs` escapes the function body here
| argument requires that `'1` must outlive `'static`
error[E0524]: two closures require unique access to `*gs` at the same time
--> src/main.rs:95:22
|
89 | btn.set_callback(|_| {
| - --- first closure is constructed here
| _____|
| |
90 | | gs.set_viewer(Viewer::Page1)
| | -- first borrow occurs due to use of `*gs` in closure
91 | | });
| |______- argument requires that `*gs` is borrowed for `'static`
...
95 | btn.set_callback(|_| {
| ^^^ second closure is constructed here
96 | gs.set_viewer(Viewer::Page2)
| -- second borrow occurs due to use of `*gs` in closure
my application architecture working or is there a better one? The application has several pages (one page one viewer) and each viewer has its own global state and the data that is stored in it and processes this data.
What is the best way to store viewer data in the global state?

This code wraps your GlobalState in an Rc<RefCell<GlobalState>>:
#[derive(Clone, Copy)]
enum Message {
Update
}
#[derive(Clone, Copy)]
struct GlobalState {
viewer: Viewer,
}
impl GlobalState {
fn set_viewer(&mut self, v: Viewer) {
self.viewer = v;
}
}
#[derive(Clone, Copy)]
enum Viewer {
Page1,
Page2
}
fn main() {
let mut gs = Rc::new(RefCell::new(GlobalState {viewer: Viewer::Page1}));
let app = app::App::default().with_scheme(app::Scheme::Gtk);
let (s, r) = app::channel::<Message>();
let mut wind = Window::default().with_size(800, 600);
left_side(gs.clone());
let mut col = Column::new(155,70,800 - 150,600 - 65,None);
col.end();
wind.end();
wind.show();
while app.wait() {
if let Some(msg) = r.recv() {
match msg {
Message::Update => {
let gs = gs.borrow();
match gs.viewer {
Viewer::Page1 => {
col.clear();
let view = view_ohm();
col.add(&view);
},
Viewer::Page2 => {
col.clear();
let view = view_ohm();
col.add(&view);
},
_ => ()
}
}
_ => (),
}
}
}
}
fn left_side(gs: Rc<RefCell<GlobalState>>) {
let btn_width = 130;
let btn_height = 30;
let s = app::Sender::get();
let mut grp = Group::default().with_size(65, 600);
let mut col = Pack::default()
.with_size(btn_width, 600)
.center_of_parent()
.with_type(PackType::Vertical);
col.set_spacing(2);
let mut btn = Button::new(0, 0, btn_width, btn_height, "Page 1");
btn.set_callback({
let gs = gs.clone();
move |_| {
gs.borrow_mut().set_viewer(Viewer::Page1);
s.send(Message::Update);
}});
let mut btn = Button::new(0, 0, btn_width, btn_height, "Page 2");
btn.set_callback(move |_| {
gs.borrow_mut().set_viewer(Viewer::Page2);
s.send(Message::Update);
});
col.end();
grp.end();
}

Related

Unable to read from NEAR's rocksDB

I'm trying to iterate through NEAR's RocksDB,
I've downloaded the small backup from s3 and using the code below to iterate through col33 (transactions)
But it doesn't print anything as RocksDB would be empty (but it is not obviously),
could you please point me out what I'm doing wrong?
Thanks
use std::env;
use rocksdb::{ColumnFamilyDescriptor, DB, IteratorMode, Options};
fn col_name(col: i32) -> String {
format!("col{}", col)
}
fn main() {
println!("Hello, RocksDB!");
let args: Vec<String> = env::args().collect();
let path = if args.len() > 1 {
args.get(1).unwrap().clone()
} else {
String::from("./data")
};
println!("data dir={}", &path);
let opts = Options::default();
let mut cfs:Vec<ColumnFamilyDescriptor> = Vec::new();
for col in 33..34 {
cfs.push(
rocksdb::ColumnFamilyDescriptor::new(col_name(col),opts.clone()));
}
let db = DB::open_cf_descriptors_read_only(
&opts,&path, cfs, false,
).unwrap();
let iter = db.iterator(IteratorMode::Start);
for (key, value) in iter {
println!("Saw {:?} {:?}", key, value);
let k = String::from_utf8(key.to_vec()).unwrap();
let v = String::from_utf8(value.to_vec()).unwrap();
println!("Saw {:?} {:?}", k, v);
}
let _ = DB::destroy(&Options::default(), &path);
}
I've found what was wrong,
as Asad Awadia mentioned, I'm using iterator over default column family here.
I've used iterator_cf instead and got some data:
let cf_handle = db.cf_handle("col33").unwrap();
let iter = db.iterator_cf(cf_handle, IteratorMode::Start);

How to Filter out a Vec of Strings From a Vec of Structs Rust

I have a working solution to filtering out an input vec of strings compared to a vector of a struct. However, my code seems complicated and I tried simplify the code using a iter::filter(https://doc.rust-lang.org/stable/std/iter/struct.Filter.html). This caused issues because the iterator gave back values that were references and could not be directly used. It seems like my understanding of the iter and what can be done in a structs vector needs refreshing. Below is the simplified filtering code that works:
#[derive(Debug)]
pub struct Widget {
name: String,
pin: u16,
}
impl Widget{
pub fn new(widget_name: String, widget_pin: String) -> Widget {
let widget_pin_u16 = widget_pin.parse::<u16>().expect("Unable to parse");
let nw = Widget {
name: widget_name,
pin: widget_pin_u16
};
return nw
}
}
pub struct WidgetHolder {
widgets: Vec<Widget>,
widget_holder_name: String
}
impl WidgetHolder {
fn add_widgets(&mut self, valid_widgets_found: Vec<String>) {
let mut widgets_to_add: Vec<String> = Vec::new();
for widget in valid_widgets_found {
// The string musy be compared to pin field, so we're converting
let widget_offset = widget
.clone()
.parse::<u16>()
.expect("Unable to parse widget base into int.");
// If it doesnt exist in our widgetHolder widgets vector, then lets add it.
let mut widget_exists = false;
for existing_widget in &self.widgets {
if widget_offset == existing_widget.pin {
widget_exists = true;
break;
}
}
if !widget_exists {
widgets_to_add.push(widget.clone());
}
}
if widgets_to_add.is_empty() {
return;
}
for widget in widgets_to_add {
let loaded_widget = Widget::new(self.widget_holder_name.clone(), widget);
self.widgets.push(loaded_widget);
}
}
}
pub fn main() {
let init_vec = Vec::new();
let mut wh = WidgetHolder {
widgets: init_vec,
widget_holder_name: "MyWidget".to_string()
};
let vec1 = vec!["1".to_string(), "2".to_string(), "3".to_string()];
wh.add_widgets(vec1);
println!("{:?}", wh.widgets);
let vec2 = vec!["2".to_string(), "3".to_string(), "4".to_string()];
wh.add_widgets(vec2);
println!("{:?}", wh.widgets);
}
Is there a way I can clean up this code without having to use so many data structures and loops? The filter api looks clean but does it work with a vector inside of a struct that I am trying to mutate(append to it)?
EDIT
After trying to get a stack trace, I actually got the filter to work...
fn add_widgets(&mut self, valid_widgets_found: Vec<String>) {
let widgets_to_add: Vec<String> = valid_widgets_found.into_iter()
.filter(|widget_pin| {
let widget_offset = widget_pin.clone().parse::<u16>().expect("Unable to parse widget base into int.");
let mut widget_exists = false;
for existing_widget in &self.widgets {
if widget_offset == existing_widget.pin {
widget_exists = true;
break;
}
}
!widget_exists
})
.collect();
if widgets_to_add.is_empty() {
return;
}
for widget in widgets_to_add {
let loaded_widget = Widget::new(self.widget_holder_name.clone(), widget);
self.widgets.push(loaded_widget);
}
}
I figured out the answer. Seemed like a syntax error when I initially tried it. For anyone who's looking for a filter example in the future:
fn add_widgets(&mut self, valid_widgets_found: Vec<String>) {
let widgets_to_add: Vec<String> = valid_widgets_found.into_iter()
.filter(|widget_pin| {
let widget_offset = widget_pin.clone().parse::<u16>().expect("Unable to parse widget base into int.");
let mut widget_exists = false;
for existing_widget in &self.widgets {
if widget_offset == existing_widget.pin {
widget_exists = true;
break;
}
}
!widget_exists
})
.collect();
if widgets_to_add.is_empty() {
return;
}
for widget in widgets_to_add {
let loaded_widget = Widget::new(self.widget_holder_name.clone(), widget);
self.widgets.push(loaded_widget);
}
}

Iterative filter function that modifies tree like structure

I have a structure like
struct Node {
pub id: String,
pub dis: String,
pub parent: Option<NodeRefNodeRefWeak>,
pub children: Vec<NodeRef>,
}
pub type NodeRef = Rc<RefCell<Node>>;
pub type NodeRefNodeRefWeak = Weak<RefCell<Node>>;
I also have a start of a function that can iterate this structure to
pull out a match on a node id but it has issues.
What I would like is for this function to return the parent node of the whole tree with ONLY the branches that have a match somewhere on the branch.
Children past the search node can be removed.
Ie a function that filters all other nodes out of the tree.
For example with my rust playground link I would like it to return
level0_node_#1 (level0_node_#1)
level1_node_4 (level1_node_4)
level2_node_4_3 (level2_node_4_3)
level3_node_4_3_2 (level3_node_4_3_2)
However, using the recursive approach as below causes real issue with already borrowed errors when trying to remove branches etc.
Is there a way to achieve this filter function?
I have a test in the Rust playground.
fn tree_filter_node_objects<F>(node: &NodeRef, f: F) -> Vec<NodeRef>
where F: Fn(&str) -> bool + Copy {
let mut filtered_nodes: Vec<NodeRef> = vec![];
let mut borrow = node.borrow_mut();
if f(&borrow.id) {
filtered_nodes.push(node.clone());
}
for n in borrow.children.iter() {
let children_filtered = tree_filter_node_objects(n, f);
for c in children_filtered.iter() {
filtered_nodes.push(c.clone());
}
}
filtered_nodes
}
In the end I used this iterative approach.
pub fn tree_filter_node_dfs<F>(root: &NodeRef, f: F) -> Vec<NodeRef>
where F: Fn(&BmosHaystackObject) -> bool + Copy {
let mut filtered_nodes: Vec<NodeRef> = vec![];
let mut cur_node: Option<NodeRef> = Some(root.clone());
let mut last_visited_child: Option<NodeRef> = None;
let mut next_child: Option<NodeRef>;
let mut run_visit: bool = true;
while cur_node.is_some() {
if run_visit {
let n = cur_node.as_ref().unwrap();
if f(&n.borrow().object) {
}
}
if last_visited_child.is_none() {
let children = cur_node.as_ref().unwrap().borrow().children.clone();
if children.len() > 0 {
next_child = Some(children[0].clone());
}
else {
next_child = None;
}
}
else {
next_child = tree_filter_node_get_next_sibling(last_visited_child.as_ref().unwrap());
}
if next_child.is_some() {
last_visited_child = None;
cur_node = next_child;
run_visit = true;
}
else {
last_visited_child = cur_node;
cur_node = tree_node_parent_node(&last_visited_child.clone().unwrap().clone());
run_visit = false;
}
}
filtered_nodes
}

Select from a list of sockets using futures

I am trying out the yet-unstable async-await syntax in nightly Rust 1.38 with futures-preview = "0.3.0-alpha.16" and runtime = "0.3.0-alpha.6". It feels really cool, but the docs are (yet) scarce and I got stuck.
To go a bit beyond the basic examples I would like to create an app that:
Accepts TCP connections on a given port;
Broadcasts all the data received from any connection to all active connections.
Existing docs and examples got me this far:
#![feature(async_await)]
#![feature(async_closure)]
use futures::{
prelude::*,
select,
future::select_all,
io::{ReadHalf, WriteHalf, Read},
};
use runtime::net::{TcpListener, TcpStream};
use std::io;
async fn read_stream(mut reader: ReadHalf<TcpStream>) -> (ReadHalf<TcpStream>, io::Result<Box<[u8]>>) {
let mut buffer: Vec<u8> = vec![0; 1024];
match reader.read(&mut buffer).await {
Ok(len) => {
buffer.truncate(len);
(reader, Ok(buffer.into_boxed_slice()))
},
Err(err) => (reader, Err(err)),
}
}
#[runtime::main]
async fn main() -> std::io::Result<()> {
let mut listener = TcpListener::bind("127.0.0.1:8080")?;
println!("Listening on {}", listener.local_addr()?);
let mut incoming = listener.incoming().fuse();
let mut writers: Vec<WriteHalf<TcpStream>> = vec![];
let mut reads = vec![];
loop {
select! {
maybe_stream = incoming.select_next_some() => {
let (mut reader, writer) = maybe_stream?.split();
writers.push(writer);
reads.push(read_stream(reader).fuse());
},
maybe_read = select_all(reads.iter()) => {
match maybe_read {
(reader, Ok(data)) => {
for writer in writers {
writer.write_all(data).await.ok(); // Ignore errors here
}
reads.push(read_stream(reader).fuse());
},
(reader, Err(err)) => {
let reader_addr = reader.peer_addr().unwrap();
writers.retain(|writer| writer.peer_addr().unwrap() != reader_addr);
},
}
}
}
}
}
This fails with:
error: recursion limit reached while expanding the macro `$crate::dispatch`
--> src/main.rs:36:9
|
36 | / select! {
37 | | maybe_stream = incoming.select_next_some() => {
38 | | let (mut reader, writer) = maybe_stream?.split();
39 | | writers.push(writer);
... |
55 | | }
56 | | }
| |_________^
|
= help: consider adding a `#![recursion_limit="128"]` attribute to your crate
= note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)
This is very confusing. Maybe I am using select_all() in a wrong way? Any help in making it work is appreciated!
For completeness, my Cargo.toml:
[package]
name = "async-test"
version = "0.1.0"
authors = ["xxx"]
edition = "2018"
[dependencies]
runtime = "0.3.0-alpha.6"
futures-preview = { version = "=0.3.0-alpha.16", features = ["async-await", "nightly"] }
In case someone is following, I hacked it together finally. This code works:
#![feature(async_await)]
#![feature(async_closure)]
#![recursion_limit="128"]
use futures::{
prelude::*,
select,
stream,
io::ReadHalf,
channel::{
oneshot,
mpsc::{unbounded, UnboundedSender},
}
};
use runtime::net::{TcpListener, TcpStream};
use std::{
io,
net::SocketAddr,
collections::HashMap,
};
async fn read_stream(
addr: SocketAddr,
drop: oneshot::Receiver<()>,
mut reader: ReadHalf<TcpStream>,
sender: UnboundedSender<(SocketAddr, io::Result<Box<[u8]>>)>
) {
let mut drop = drop.fuse();
loop {
let mut buffer: Vec<u8> = vec![0; 1024];
select! {
result = reader.read(&mut buffer).fuse() => {
match result {
Ok(len) => {
buffer.truncate(len);
sender.unbounded_send((addr, Ok(buffer.into_boxed_slice())))
.expect("Channel error");
if len == 0 {
return;
}
},
Err(err) => {
sender.unbounded_send((addr, Err(err))).expect("Channel error");
return;
}
}
},
_ = drop => {
return;
},
}
}
}
enum Event {
Connection(io::Result<TcpStream>),
Message(SocketAddr, io::Result<Box<[u8]>>),
}
#[runtime::main]
async fn main() -> std::io::Result<()> {
let mut listener = TcpListener::bind("127.0.0.1:8080")?;
eprintln!("Listening on {}", listener.local_addr()?);
let mut writers = HashMap::new();
let (sender, receiver) = unbounded();
let connections = listener.incoming().map(|maybe_stream| Event::Connection(maybe_stream));
let messages = receiver.map(|(addr, maybe_message)| Event::Message(addr, maybe_message));
let mut events = stream::select(connections, messages);
loop {
match events.next().await {
Some(Event::Connection(Ok(stream))) => {
let addr = stream.peer_addr().unwrap();
eprintln!("New connection from {}", addr);
let (reader, writer) = stream.split();
let (drop_sender, drop_receiver) = oneshot::channel();
writers.insert(addr, (writer, drop_sender));
runtime::spawn(read_stream(addr, drop_receiver, reader, sender.clone()));
},
Some(Event::Message(addr, Ok(message))) => {
if message.len() == 0 {
eprintln!("Connection closed by client: {}", addr);
writers.remove(&addr);
continue;
}
eprintln!("Received {} bytes from {}", message.len(), addr);
if &*message == b"quit\n" {
eprintln!("Dropping client {}", addr);
writers.remove(&addr);
continue;
}
for (&other_addr, (writer, _)) in &mut writers {
if addr != other_addr {
writer.write_all(&message).await.ok(); // Ignore errors
}
}
},
Some(Event::Message(addr, Err(err))) => {
eprintln!("Error reading from {}: {}", addr, err);
writers.remove(&addr);
},
_ => panic!("Event error"),
}
}
}
I use a channel and spawn a reading task for each client. Special care had to be taken to ensure that readers get dropped with writers: this is why oneshot future is used. When oneshot::Sender is dropped, the oneshot::Receiver future resolves to canceled state, which is a notification mechanism for a reading task to know it is time to halt. To demonstrate that it works, we drop a client as soon as we get "quit" message.
Sadly, there is a (seemingly useless) warning regarding an unused JoinHandle from the runtime::spawn call, and I don't really know how to eliminate it.

Is there a way to directly access a field value in an enum struct without pattern matching?

I wish that enums in Rust can be used like Haskell's productive type. I want to
access a field's value directly
assign a field's value directly or make a clone with the changing value.
Directly means that not using too long pattern matching code, but just could access like let a_size = a.size.
In Haskell:
data TypeAB = A {size::Int, name::String} | B {size::Int, switch::Bool} deriving Show
main = do
let a = A 1 "abc"
let b = B 1 True
print (size a) -- could access a field's value directly
print (name a) -- could access a field's value directly
print (switch b) -- could access a field's value directly
let aa = a{size=2} -- could make a clone directly with the changing value
print aa
I tried two styles of Rust enum definition like
Style A:
#[derive(Debug)]
enum EntryType {
A(TypeA),
B(TypeB),
}
#[derive(Debug)]
struct TypeA {
size: u32,
name: String,
}
#[derive(Debug)]
struct TypeB {
size: u32,
switch: bool,
}
fn main() {
let mut ta = TypeA {
size: 3,
name: "TAB".to_string(),
};
println!("{:?}", &ta);
ta.size = 2;
ta.name = "TCD".to_string();
println!("{:?}", &ta);
let mut ea = EntryType::A(TypeA {
size: 1,
name: "abc".to_string(),
});
let mut eb = EntryType::B(TypeB {
size: 1,
switch: true,
});
let vec_ab = vec![&ea, &eb];
println!("{:?}", &ea);
println!("{:?}", &eb);
println!("{:?}", &vec_ab);
// Want to do like `ta.size = 2` for ea
// Want to do like `ta.name = "bcd".to_string()` for ea
// Want to do like `tb.switch = false` for eb
// ????
println!("{:?}", &ea);
println!("{:?}", &eb);
println!("{:?}", &vec_ab);
}
Style B:
#[derive(Debug)]
enum TypeCD {
TypeC { size: u32, name: String },
TypeD { size: u32, switch: bool },
}
fn main() {
// NOTE: Rust requires representative struct name before each constructor
// TODO: Check constructor name can be duplicated
let mut c = TypeCD::TypeC {
size: 1,
name: "abc".to_string(),
};
let mut d = TypeCD::TypeD {
size: 1,
switch: true,
};
let vec_cd = vec![&c, &d];
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
// Can't access a field's value like
// let c_size = c.size
let c_size = c.size; // [ERROR]: No field `size` on `TypeCD`
let c_name = c.name; // [ERROR]: No field `name` on `TypeCD`
let d_switch = d.switch; // [ERROR]: No field `switch` on `TypeCD`
// Can't change a field's value like
// c.size = 2;
// c.name = "cde".to_string();
// d.switch = false;
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
}
I couldn't access/assign values directly in any style. Do I have to implement functions or a trait just to access a field's value? Is there some way of deriving things to help this situation?
What about style C:
#[derive(Debug)]
enum Color {
Green { name: String },
Blue { switch: bool },
}
#[derive(Debug)]
struct Something {
size: u32,
color: Color,
}
fn main() {
let c = Something {
size: 1,
color: Color::Green {
name: "green".to_string(),
},
};
let d = Something {
size: 2,
color: Color::Blue { switch: true },
};
let vec_cd = vec![&c, &d];
println!("{:?}", &c);
println!("{:?}", &d);
println!("{:?}", &vec_cd);
let _ = c.size;
}
If all variant have something in common, why separate them?
Of course, I need to access not common field too.
This would imply that Rust should define what to do when the actual type at runtime doesn't contain the field you required. So, I don't think Rust would add this one day.
You could do it yourself. It will require some lines of code, but that matches the behavior of your Haskell code. However, I don't think this is the best thing to do. Haskell is Haskell, I think you should code in Rust and not try to code Haskell by using Rust. That a general rule, some feature of Rust come directly from Haskell, but what you want here is very odd in my opinion for Rust code.
#[derive(Debug)]
enum Something {
A { size: u32, name: String },
B { size: u32, switch: bool },
}
impl Something {
fn size(&self) -> u32 {
match self {
Something::A { size, .. } => *size,
Something::B { size, .. } => *size,
}
}
fn name(&self) -> &String {
match self {
Something::A { name, .. } => name,
Something::B { .. } => panic!("Something::B doesn't have name field"),
}
}
fn switch(&self) -> bool {
match self {
Something::A { .. } => panic!("Something::A doesn't have switch field"),
Something::B { switch, .. } => *switch,
}
}
fn new_size(&self, size: u32) -> Something {
match self {
Something::A { name, .. } => Something::A {
size,
name: name.clone(),
},
Something::B { switch, .. } => Something::B {
size,
switch: *switch,
},
}
}
// etc...
}
fn main() {
let a = Something::A {
size: 1,
name: "Rust is not haskell".to_string(),
};
println!("{:?}", a.size());
println!("{:?}", a.name());
let b = Something::B {
size: 1,
switch: true,
};
println!("{:?}", b.switch());
let aa = a.new_size(2);
println!("{:?}", aa);
}
I think there is currently no built-in way of accessing size directly on the enum type. Until then, enum_dispatch or a macro-based solution may help you.

Resources