start reflect
This commit is contained in:
@@ -24,3 +24,5 @@ bincode = { version = "2.0.0-rc.3", default-features = false, features = [
|
|||||||
simple_logger = "5.0.0"
|
simple_logger = "5.0.0"
|
||||||
rp2040-hal = "0.10.2"
|
rp2040-hal = "0.10.2"
|
||||||
rp2040-pac = "0.6.0"
|
rp2040-pac = "0.6.0"
|
||||||
|
serde = { version = "1.0.216", features = ["derive"] }
|
||||||
|
serde_json = "1.0.133"
|
||||||
|
|||||||
@@ -5,7 +5,11 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
rfe.path = "../../rfe"
|
rfe.path = "../../rfe"
|
||||||
rfe.features = ["std"]
|
rfe.features = ["std", "serde"]
|
||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
simple_logger = "5.0.0"
|
simple_logger = "5.0.0"
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
serde.workspace = true
|
||||||
|
egui = "0.30.0"
|
||||||
|
eframe = "0.30.0"
|
||||||
|
|||||||
+195
-14
@@ -1,30 +1,211 @@
|
|||||||
#![feature(thread_sleep_until)]
|
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release
|
||||||
|
|
||||||
use std::{
|
use std::{
|
||||||
thread::sleep_until,
|
collections::HashMap,
|
||||||
|
fs::write,
|
||||||
|
thread::{sleep, spawn},
|
||||||
time::{Duration, Instant},
|
time::{Duration, Instant},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use anyhow::anyhow;
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use connector::{Connector, UdpConnector};
|
use connector::{Connector, UdpConnector};
|
||||||
use log::*;
|
use log::*;
|
||||||
|
use msg::DsTlmSet;
|
||||||
|
use reflect::*;
|
||||||
|
use rfe::macros::Reflect;
|
||||||
use rfe::*;
|
use rfe::*;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
SimpleLogger::new().init().unwrap();
|
struct TreeNode {
|
||||||
|
name: String,
|
||||||
|
children: Vec<TreeNode>,
|
||||||
|
}
|
||||||
|
|
||||||
let mut udp = UdpConnector::new("127.0.0.1", 7011, "127.0.0.1", 7010)?;
|
impl TreeNode {
|
||||||
|
pub fn new<T: ToString>(name: T, children: Vec<TreeNode>) -> Self {
|
||||||
let mut next_time = Instant::now() + Duration::from_millis(10);
|
Self {
|
||||||
loop {
|
name: name.to_string(),
|
||||||
sleep_until(next_time);
|
children,
|
||||||
|
|
||||||
while let Some(msgs) = udp.recv() {
|
|
||||||
for msg in msgs {
|
|
||||||
info!("got msg {:?}", msg);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
next_time += Duration::from_millis(10);
|
|
||||||
|
pub fn add_child<T: ToString>(&mut self, name: T) -> &mut TreeNode {
|
||||||
|
self.children.push(TreeNode::new(name, Vec::new()));
|
||||||
|
let i = self.children.len() - 1;
|
||||||
|
return &mut self.children[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_add_path(&mut self, path: &str) -> &mut TreeNode {
|
||||||
|
if !path.starts_with(&format!("{}.", self.name)) {
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
let path = path.replace(&format!("{}.", self.name), "");
|
||||||
|
let names = path.split(".");
|
||||||
|
let mut working_tree = self;
|
||||||
|
|
||||||
|
for name in names {
|
||||||
|
let mut index = None;
|
||||||
|
for (i, child) in &mut working_tree.children.iter().enumerate() {
|
||||||
|
if child.name == name {
|
||||||
|
index = Some(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(index) = index {
|
||||||
|
working_tree = &mut working_tree.children[index];
|
||||||
|
} else {
|
||||||
|
working_tree = working_tree.add_child(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
working_tree
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_last(&self) -> bool {
|
||||||
|
self.children.len() == 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_tree(msg_enum: Vec<String>) -> TreeNode {
|
||||||
|
let mut t = TreeNode::new("Msg", Vec::new());
|
||||||
|
for p in msg_enum {
|
||||||
|
let mut x = p
|
||||||
|
.split(" = ")
|
||||||
|
.map(|x| x.split("."))
|
||||||
|
.flatten()
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join(".");
|
||||||
|
|
||||||
|
if x.starts_with(".") {
|
||||||
|
x.remove(0);
|
||||||
|
} else {
|
||||||
|
x = format!("Msg.{}", x);
|
||||||
|
}
|
||||||
|
let s = x.rsplitn(2, ".").collect::<Vec<_>>();
|
||||||
|
|
||||||
|
if s.len() == 2 {
|
||||||
|
t.get_add_path(s[1]).add_child(s[0]);
|
||||||
|
} else {
|
||||||
|
t.add_child(s[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Default, Reflect)]
|
||||||
|
struct TestStruct {
|
||||||
|
counter: i8,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<()> {
|
||||||
|
SimpleLogger::new()
|
||||||
|
.with_level(LevelFilter::Debug)
|
||||||
|
.init()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
info!(
|
||||||
|
"{:?}",
|
||||||
|
msg::Msg::DsCmd(msg::DsCmd::AddTlmSet(DsTlmSet::default()))
|
||||||
|
);
|
||||||
|
info!(
|
||||||
|
"json {}",
|
||||||
|
serde_json::to_string(&msg::Msg::DsCmd(msg::DsCmd::Noop)).unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
|
let mut test = TestStruct::default();
|
||||||
|
info!("{:?}", test);
|
||||||
|
reflect::path_set(&mut test, "counter", ReflectValue::I64(1));
|
||||||
|
info!("{:?}", test);
|
||||||
|
|
||||||
|
// spawn(|| {
|
||||||
|
// let mut udp = UdpConnector::new("127.0.0.1", 7011, "127.0.0.1", 7010).unwrap();
|
||||||
|
|
||||||
|
// let mut next_time = Instant::now() + Duration::from_millis(10);
|
||||||
|
// loop {
|
||||||
|
// sleep(next_time - Instant::now());
|
||||||
|
|
||||||
|
// while let Some(msgs) = udp.recv() {
|
||||||
|
// for msg in msgs {
|
||||||
|
// info!("got msg {:?}", msg);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// next_time += Duration::from_millis(10);
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
|
||||||
|
// let options = eframe::NativeOptions {
|
||||||
|
// viewport: egui::ViewportBuilder::default().with_inner_size([560.0, 480.0]),
|
||||||
|
// ..Default::default()
|
||||||
|
// };
|
||||||
|
// eframe::run_native(
|
||||||
|
// "RFE Ground",
|
||||||
|
// options,
|
||||||
|
// Box::new(|_cc| Ok(Box::<MyApp>::default())),
|
||||||
|
// )
|
||||||
|
// .or(Err(anyhow!("eframe failed")))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// struct MyApp {
|
||||||
|
// command_path: String,
|
||||||
|
// tree: TreeNode,
|
||||||
|
// values: HashMap<String, String>,
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl Default for MyApp {
|
||||||
|
// fn default() -> Self {
|
||||||
|
// let tree = to_tree(msg::Msg::None.enumerate_clean());
|
||||||
|
// Self {
|
||||||
|
// command_path: "Msg".to_string(),
|
||||||
|
// tree,
|
||||||
|
// values: HashMap::new(),
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl eframe::App for MyApp {
|
||||||
|
// fn update(&mut self, ctx: &egui::Context, _frame: &mut eframe::Frame) {
|
||||||
|
// egui::CentralPanel::default().show(ctx, |ui| {
|
||||||
|
// ui.heading(format!("Commands: {}", self.command_path));
|
||||||
|
// if ui.button("X").clicked() {
|
||||||
|
// self.command_path = "Msg".to_string();
|
||||||
|
// }
|
||||||
|
// if self
|
||||||
|
// .command_path
|
||||||
|
// .as_bytes()
|
||||||
|
// .iter()
|
||||||
|
// .filter(|x| **x == b'.')
|
||||||
|
// .count()
|
||||||
|
// >= 2
|
||||||
|
// {
|
||||||
|
// for item in &self.tree.get_add_path(&self.command_path).children {
|
||||||
|
// for c in &item.children {
|
||||||
|
// if c.is_last() {
|
||||||
|
// if !self.values.contains_key(&c.name) {
|
||||||
|
// self.values.insert(c.name.clone(), String::new());
|
||||||
|
// }
|
||||||
|
// let sref = self.values.get_mut(&c.name).unwrap();
|
||||||
|
// ui.horizontal(|ui| {
|
||||||
|
// ui.label(format!("{} : {}", item.name, c.name.clone()));
|
||||||
|
// ui.text_edit_singleline(sref);
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if ui.button("send").clicked() {
|
||||||
|
// info!("sending {}", self.command_path);
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// for item in &self.tree.get_add_path(&self.command_path).children {
|
||||||
|
// if ui.button(item.name.clone()).clicked() {
|
||||||
|
// self.command_path = format!("{}.{}", self.command_path, item.name);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
+2
-1
@@ -7,7 +7,7 @@ edition = "2021"
|
|||||||
default = []
|
default = []
|
||||||
std = ["dep:mio"]
|
std = ["dep:mio"]
|
||||||
rp2040 = ["dep:rp2040-hal", "dep:rp2040-pac"]
|
rp2040 = ["dep:rp2040-hal", "dep:rp2040-pac"]
|
||||||
to_csv = []
|
serde = ["dep:serde"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bincode.workspace = true
|
bincode.workspace = true
|
||||||
@@ -18,3 +18,4 @@ mio = { version = "1.0.2", features = ["net", "os-poll"], optional = true }
|
|||||||
rp2040-hal = { workspace = true, optional = true }
|
rp2040-hal = { workspace = true, optional = true }
|
||||||
rp2040-pac = { workspace = true, optional = true }
|
rp2040-pac = { workspace = true, optional = true }
|
||||||
macros.path = "macros"
|
macros.path = "macros"
|
||||||
|
serde = { workspace = true, optional = true }
|
||||||
|
|||||||
+265
-11
@@ -31,6 +31,25 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let kind_to_default_arms = variants.iter().map(|variant| {
|
||||||
|
let variant_name = &variant.ident;
|
||||||
|
match &variant.fields {
|
||||||
|
Fields::Unit => {
|
||||||
|
quote! {
|
||||||
|
#kind_name::#variant_name => #name::#variant_name,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fields::Unnamed(_) => {
|
||||||
|
quote! {
|
||||||
|
#kind_name::#variant_name => #name::#variant_name(Default::default()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Fields::Named(_) => {
|
||||||
|
panic!("Named fields not supported by Kind");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let kind_arms = variants.iter().map(|variant| {
|
let kind_arms = variants.iter().map(|variant| {
|
||||||
let variant_name = &variant.ident;
|
let variant_name = &variant.ident;
|
||||||
match &variant.fields {
|
match &variant.fields {
|
||||||
@@ -51,9 +70,10 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
|
|||||||
});
|
});
|
||||||
|
|
||||||
let expanded = quote! {
|
let expanded = quote! {
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)]
|
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum #kind_name {
|
pub enum #kind_name {
|
||||||
|
#[default]
|
||||||
#(#kind_enum_arms)*
|
#(#kind_enum_arms)*
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -63,6 +83,12 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
|
|||||||
#(#kind_enum_vec_arms)*
|
#(#kind_enum_vec_arms)*
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn to_default(&self) -> #name {
|
||||||
|
match self {
|
||||||
|
#(#kind_to_default_arms)*
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl #name {
|
impl #name {
|
||||||
@@ -93,7 +119,21 @@ pub fn to_csv_derive(input: TokenStream) -> TokenStream {
|
|||||||
let field_name = field_ident.to_string();
|
let field_name = field_ident.to_string();
|
||||||
|
|
||||||
quote! { {
|
quote! { {
|
||||||
let mut field_csvs: alloc::vec::Vec<String> = (&self.#field_ident as &dyn ToCsv).to_csv();
|
let mut field_csvs: alloc::vec::Vec<alloc::string::String> = (&self.#field_ident as &dyn ToCsv).to_csv();
|
||||||
|
for entry in &mut field_csvs {
|
||||||
|
*entry = format!("{}.{}", #field_name, &entry);
|
||||||
|
}
|
||||||
|
values.extend(field_csvs);
|
||||||
|
} }
|
||||||
|
});
|
||||||
|
|
||||||
|
let arms_enum = fields.iter().map(|field| {
|
||||||
|
let field_ident = field.clone().ident.unwrap();
|
||||||
|
let field_name = field_ident.to_string();
|
||||||
|
|
||||||
|
quote! { {
|
||||||
|
let mut field_csvs: alloc::vec::Vec<alloc::string::String> = (&self.#field_ident as &dyn ToCsv).enumerate();
|
||||||
|
|
||||||
for entry in &mut field_csvs {
|
for entry in &mut field_csvs {
|
||||||
*entry = format!("{}.{}", #field_name, &entry);
|
*entry = format!("{}.{}", #field_name, &entry);
|
||||||
}
|
}
|
||||||
@@ -103,17 +143,23 @@ pub fn to_csv_derive(input: TokenStream) -> TokenStream {
|
|||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl ToCsv for #name {
|
impl ToCsv for #name {
|
||||||
fn to_csv(&self) -> alloc::vec::Vec<String> {
|
fn to_csv(&self) -> alloc::vec::Vec<alloc::string::String> {
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::format;
|
use alloc::format;
|
||||||
|
|
||||||
let mut values:alloc::vec::Vec<String> = alloc::vec::Vec::new();
|
let mut values:alloc::vec::Vec<alloc::string::String> = alloc::vec::Vec::new();
|
||||||
#(#arms)*
|
#(#arms)*
|
||||||
for value in &mut values {
|
|
||||||
*value = format!("{}", value);
|
|
||||||
}
|
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn enumerate(&self) -> alloc::vec::Vec<alloc::string::String> {
|
||||||
|
extern crate alloc;
|
||||||
|
use alloc::format;
|
||||||
|
let mut values:alloc::vec::Vec<alloc::string::String> = alloc::vec::Vec::new();
|
||||||
|
#(#arms_enum)*
|
||||||
|
return values;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,7 +176,7 @@ pub fn to_csv_derive(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
Fields::Unnamed(_) => {
|
Fields::Unnamed(_) => {
|
||||||
quote! {Self::#variant_name(l) => {
|
quote! {Self::#variant_name(l) => {
|
||||||
let mut field_csvs: alloc::vec::Vec<String> = (l as &dyn ToCsv).to_csv();
|
let mut field_csvs: alloc::vec::Vec<alloc::string::String> = (l as &dyn ToCsv).to_csv();
|
||||||
for entry in &mut field_csvs {
|
for entry in &mut field_csvs {
|
||||||
*entry = format!("{}.{}", #variant_name_s, &entry);
|
*entry = format!("{}.{}", #variant_name_s, &entry);
|
||||||
}
|
}
|
||||||
@@ -143,18 +189,226 @@ pub fn to_csv_derive(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let arms_enum = variants.iter().map(|variant| {
|
||||||
|
let variant_name = &variant.ident;
|
||||||
|
let variant_name_s = variant_name.to_string();
|
||||||
|
|
||||||
|
match &variant.fields {
|
||||||
|
Fields::Unit => {
|
||||||
|
quote! { values.push(format!(" = {}::{}", #name_s, #variant_name_s)); }
|
||||||
|
}
|
||||||
|
Fields::Unnamed(var) => {
|
||||||
|
let var_type =
|
||||||
|
if let Some(first_field) = var.unnamed.first() {
|
||||||
|
first_field
|
||||||
|
} else {
|
||||||
|
panic!("Struct has no fields!");
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
let l = #var_type::default();
|
||||||
|
let mut field_csvs: alloc::vec::Vec<alloc::string::String> = (&l as &dyn ToCsv).enumerate();
|
||||||
|
|
||||||
|
for entry in &mut field_csvs {
|
||||||
|
*entry = format!("{}.{}", #variant_name_s, &entry);
|
||||||
|
}
|
||||||
|
values.extend(field_csvs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Fields::Named(_) => {
|
||||||
|
panic!("Named fields not supported by ToCsv");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
impl ToCsv for #name {
|
impl ToCsv for #name {
|
||||||
fn to_csv(&self) -> alloc::vec::Vec<String> {
|
fn to_csv(&self) -> alloc::vec::Vec<alloc::string::String> {
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::format;
|
use alloc::format;
|
||||||
let mut values: alloc::vec::Vec<String> = alloc::vec::Vec::new();
|
let mut values: alloc::vec::Vec<alloc::string::String> = alloc::vec::Vec::new();
|
||||||
|
|
||||||
match self {
|
match self {
|
||||||
#(#arms)*
|
#(#arms)*
|
||||||
}
|
}
|
||||||
return values;
|
return values;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn enumerate(&self) -> alloc::vec::Vec<alloc::string::String> {
|
||||||
|
extern crate alloc;
|
||||||
|
use alloc::format;
|
||||||
|
|
||||||
|
let mut values:alloc::vec::Vec<alloc::string::String> = alloc::vec::Vec::new();
|
||||||
|
#(#arms_enum)*
|
||||||
|
return values;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Data::Union(_data_union) => {
|
||||||
|
return syn::Error::new_spanned(name, "ToCsv not implemented for unions")
|
||||||
|
.to_compile_error()
|
||||||
|
.into();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
TokenStream::from(expanded)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[proc_macro_derive(Reflect)]
|
||||||
|
pub fn reflect_derive(input: TokenStream) -> TokenStream {
|
||||||
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
|
||||||
|
let name = input.ident;
|
||||||
|
let name_s = name.to_string();
|
||||||
|
|
||||||
|
let expanded = match input.data {
|
||||||
|
Data::Struct(data_struct) => {
|
||||||
|
let fields = data_struct.fields;
|
||||||
|
|
||||||
|
let field_arms = fields.iter().map(|field| {
|
||||||
|
let field_ident = field.clone().ident.unwrap();
|
||||||
|
let field_name = field_ident.to_string();
|
||||||
|
|
||||||
|
quote! { {
|
||||||
|
fields.push((#field_name, &mut self.#field_ident as &mut dyn Reflect));
|
||||||
|
} }
|
||||||
|
});
|
||||||
|
|
||||||
|
let arms_enum = fields.iter().map(|field| {
|
||||||
|
let field_ident = field.clone().ident.unwrap();
|
||||||
|
let field_name = field_ident.to_string();
|
||||||
|
|
||||||
|
quote! { {
|
||||||
|
let mut field_csvs: alloc::vec::Vec<alloc::string::String> = (&self.#field_ident as &dyn ToCsv).enumerate();
|
||||||
|
|
||||||
|
for entry in &mut field_csvs {
|
||||||
|
*entry = format!("{}.{}", #field_name, &entry);
|
||||||
|
}
|
||||||
|
values.extend(field_csvs);
|
||||||
|
} }
|
||||||
|
});
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl Reflect for #name {
|
||||||
|
fn reflect_type(&self) -> ReflectType {
|
||||||
|
ReflectType::Structure
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_name(&self) -> &str {
|
||||||
|
#name_s
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
|
||||||
|
let mut fields = Vec::new();
|
||||||
|
#(#field_arms)*
|
||||||
|
fields
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_value(&mut self, value: ReflectValue) {
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_value(&self) -> ReflectValue {
|
||||||
|
ReflectValue::Str("".to_string())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn variants(&self) -> Vec<Box<dyn Reflect>> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Data::Enum(data_enum) => {
|
||||||
|
let variants = data_enum.variants;
|
||||||
|
let arms = variants.iter().map(|variant| {
|
||||||
|
let variant_name = &variant.ident;
|
||||||
|
let variant_name_s = variant_name.to_string();
|
||||||
|
|
||||||
|
match &variant.fields {
|
||||||
|
Fields::Unit => {
|
||||||
|
quote! { Self::#variant_name => values.push(format!(" = {}::{}", #name_s, #variant_name_s)), }
|
||||||
|
// quote! { Self::#variant_name => {}, }
|
||||||
|
}
|
||||||
|
Fields::Unnamed(_) => {
|
||||||
|
quote! {Self::#variant_name(l) => {
|
||||||
|
let mut field_csvs: alloc::vec::Vec<alloc::string::String> = (l as &dyn ToCsv).to_csv();
|
||||||
|
for entry in &mut field_csvs {
|
||||||
|
*entry = format!("{}.{}", #variant_name_s, &entry);
|
||||||
|
}
|
||||||
|
values.extend(field_csvs);
|
||||||
|
},}
|
||||||
|
}
|
||||||
|
Fields::Named(_) => {
|
||||||
|
panic!("Named fields not supported by ToCsv");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
let arms_enum = variants.iter().map(|variant| {
|
||||||
|
let variant_name = &variant.ident;
|
||||||
|
let variant_name_s = variant_name.to_string();
|
||||||
|
|
||||||
|
match &variant.fields {
|
||||||
|
Fields::Unit => {
|
||||||
|
quote! { values.push(format!(" = {}::{}", #name_s, #variant_name_s)); }
|
||||||
|
}
|
||||||
|
Fields::Unnamed(var) => {
|
||||||
|
let var_type =
|
||||||
|
if let Some(first_field) = var.unnamed.first() {
|
||||||
|
first_field
|
||||||
|
} else {
|
||||||
|
panic!("Struct has no fields!");
|
||||||
|
};
|
||||||
|
quote! {
|
||||||
|
{
|
||||||
|
let l = #var_type::default();
|
||||||
|
let mut field_csvs: alloc::vec::Vec<alloc::string::String> = (&l as &dyn ToCsv).enumerate();
|
||||||
|
|
||||||
|
for entry in &mut field_csvs {
|
||||||
|
*entry = format!("{}.{}", #variant_name_s, &entry);
|
||||||
|
}
|
||||||
|
values.extend(field_csvs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
Fields::Named(_) => {
|
||||||
|
panic!("Named fields not supported by ToCsv");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
quote! {
|
||||||
|
impl ToCsv for #name {
|
||||||
|
fn to_csv(&self) -> alloc::vec::Vec<alloc::string::String> {
|
||||||
|
extern crate alloc;
|
||||||
|
use alloc::format;
|
||||||
|
let mut values: alloc::vec::Vec<alloc::string::String> = alloc::vec::Vec::new();
|
||||||
|
|
||||||
|
match self {
|
||||||
|
#(#arms)*
|
||||||
|
}
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn enumerate(&self) -> alloc::vec::Vec<alloc::string::String> {
|
||||||
|
extern crate alloc;
|
||||||
|
use alloc::format;
|
||||||
|
|
||||||
|
let mut values:alloc::vec::Vec<alloc::string::String> = alloc::vec::Vec::new();
|
||||||
|
#(#arms_enum)*
|
||||||
|
return values;
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -10,9 +10,9 @@ pub mod msg;
|
|||||||
mod rfe;
|
mod rfe;
|
||||||
pub use rfe::*;
|
pub use rfe::*;
|
||||||
|
|
||||||
#[cfg(feature = "to_csv")]
|
pub mod reflect;
|
||||||
pub mod to_csv;
|
|
||||||
|
|
||||||
|
pub use macros;
|
||||||
pub mod time;
|
pub mod time;
|
||||||
pub mod utils;
|
pub mod utils;
|
||||||
|
|
||||||
|
|||||||
+9
-10
@@ -1,17 +1,15 @@
|
|||||||
#[cfg(feature = "to_csv")]
|
|
||||||
use crate::to_csv::ToCsv;
|
|
||||||
use crate::utils::PerfData;
|
use crate::utils::PerfData;
|
||||||
use bincode::{Decode, Encode};
|
use bincode::{Decode, Encode};
|
||||||
#[cfg(feature = "to_csv")]
|
|
||||||
use macros::ToCsv;
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
use super::{TlmSetId, TlmSetItem};
|
use super::{TlmSetId, TlmSetItem};
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct DsTlmSet {
|
pub struct DsTlmSet {
|
||||||
pub items: Vec<TlmSetItem>,
|
pub items: Vec<TlmSetItem>,
|
||||||
pub id: TlmSetId,
|
pub id: TlmSetId,
|
||||||
@@ -20,23 +18,24 @@ pub struct DsTlmSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct DsHk {
|
pub struct DsHk {
|
||||||
pub perf: PerfData,
|
pub perf: PerfData,
|
||||||
pub counter: u32,
|
pub counter: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct DsOutData {
|
pub struct DsOutData {
|
||||||
pub counter: u32,
|
pub counter: u32,
|
||||||
pub bytes_written: u32,
|
pub bytes_written: u32,
|
||||||
pub bytes_written_this_cycle: u32,
|
pub bytes_written_this_cycle: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum DsCmd {
|
pub enum DsCmd {
|
||||||
|
#[default]
|
||||||
Noop,
|
Noop,
|
||||||
Reset,
|
Reset,
|
||||||
CloseAll,
|
CloseAll,
|
||||||
|
|||||||
@@ -1,27 +1,25 @@
|
|||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
#[cfg(feature = "to_csv")]
|
|
||||||
use crate::to_csv::ToCsv;
|
|
||||||
use crate::utils::PerfData;
|
use crate::utils::PerfData;
|
||||||
use bincode::{Decode, Encode};
|
use bincode::{Decode, Encode};
|
||||||
#[cfg(feature = "to_csv")]
|
#[cfg(feature = "serde")]
|
||||||
use macros::ToCsv;
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct ExampleHk {
|
pub struct ExampleHk {
|
||||||
pub perf: PerfData,
|
pub perf: PerfData,
|
||||||
pub counter: u32,
|
pub counter: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct ExampleOutData {
|
pub struct ExampleOutData {
|
||||||
pub counter: u32,
|
pub counter: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum ExampleCmd {
|
pub enum ExampleCmd {
|
||||||
|
#[default]
|
||||||
Noop,
|
Noop,
|
||||||
Reset,
|
Reset,
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-8
@@ -1,14 +1,13 @@
|
|||||||
#[cfg(feature = "to_csv")]
|
|
||||||
use crate::to_csv::ToCsv;
|
|
||||||
use crate::utils::PerfData;
|
use crate::utils::PerfData;
|
||||||
use bincode::{Decode, Encode};
|
use bincode::{Decode, Encode};
|
||||||
#[cfg(feature = "to_csv")]
|
|
||||||
use macros::ToCsv;
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct HsHk {
|
pub struct HsHk {
|
||||||
pub perf: PerfData,
|
pub perf: PerfData,
|
||||||
pub counter: u32,
|
pub counter: u32,
|
||||||
@@ -23,14 +22,15 @@ pub struct HsHk {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct HsOutData {
|
pub struct HsOutData {
|
||||||
pub counter: u32,
|
pub counter: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum HsCmd {
|
pub enum HsCmd {
|
||||||
|
#[default]
|
||||||
Noop,
|
Noop,
|
||||||
Reset,
|
Reset,
|
||||||
WatchdogEnableManual(bool),
|
WatchdogEnableManual(bool),
|
||||||
|
|||||||
+18
-17
@@ -15,13 +15,11 @@ mod ds;
|
|||||||
pub use ds::*;
|
pub use ds::*;
|
||||||
|
|
||||||
use crate::time::Timestamp;
|
use crate::time::Timestamp;
|
||||||
#[cfg(feature = "to_csv")]
|
#[cfg(feature = "serde")]
|
||||||
use crate::to_csv::ToCsv;
|
use serde::{Deserialize, Serialize};
|
||||||
#[cfg(feature = "to_csv")]
|
|
||||||
use macros::ToCsv;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct TargetMsg {
|
pub struct TargetMsg {
|
||||||
// instance is FROM for tlm, is TO for cmds
|
// instance is FROM for tlm, is TO for cmds
|
||||||
pub instance: Instance,
|
pub instance: Instance,
|
||||||
@@ -34,18 +32,21 @@ impl TargetMsg {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum Instance {
|
pub enum Instance {
|
||||||
|
#[default]
|
||||||
|
None,
|
||||||
All,
|
All,
|
||||||
Other,
|
Other,
|
||||||
Example,
|
Example,
|
||||||
Example2,
|
Example2,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Kind, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Kind, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum Msg {
|
pub enum Msg {
|
||||||
|
#[default]
|
||||||
None,
|
None,
|
||||||
SubRequest,
|
SubRequest,
|
||||||
SubList(SubList),
|
SubList(SubList),
|
||||||
@@ -66,7 +67,7 @@ pub enum Msg {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
|
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct MsgPacket {
|
pub struct MsgPacket {
|
||||||
pub instance: Instance,
|
pub instance: Instance,
|
||||||
pub msg: Msg,
|
pub msg: Msg,
|
||||||
@@ -91,22 +92,22 @@ impl MsgPacket {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct SubList {
|
pub struct SubList {
|
||||||
pub subs: Vec<TargetMsg>,
|
pub subs: Vec<TargetMsg>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct ReinitAppCmd {
|
pub struct ReinitAppCmd {
|
||||||
app_name: String,
|
app_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TlmSetId = u16;
|
pub type TlmSetId = u16;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct TlmSetItem {
|
pub struct TlmSetItem {
|
||||||
pub target: TargetMsg,
|
pub target: TargetMsg,
|
||||||
pub decimation: u16,
|
pub decimation: u16,
|
||||||
|
|||||||
+9
-10
@@ -1,16 +1,14 @@
|
|||||||
#[cfg(feature = "to_csv")]
|
|
||||||
use crate::to_csv::ToCsv;
|
|
||||||
use crate::utils::PerfData;
|
use crate::utils::PerfData;
|
||||||
use bincode::{Decode, Encode};
|
use bincode::{Decode, Encode};
|
||||||
#[cfg(feature = "to_csv")]
|
|
||||||
use macros::ToCsv;
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
|
#[cfg(feature = "serde")]
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
use super::{TlmSetId, TlmSetItem};
|
use super::{TlmSetId, TlmSetItem};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct ToTlmSet {
|
pub struct ToTlmSet {
|
||||||
pub items: Vec<TlmSetItem>,
|
pub items: Vec<TlmSetItem>,
|
||||||
pub id: TlmSetId,
|
pub id: TlmSetId,
|
||||||
@@ -18,21 +16,22 @@ pub struct ToTlmSet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct ToHk {
|
pub struct ToHk {
|
||||||
pub perf: PerfData,
|
pub perf: PerfData,
|
||||||
pub counter: u32,
|
pub counter: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, Copy, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub struct ToOutData {
|
pub struct ToOutData {
|
||||||
pub counter: u32,
|
pub counter: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
|
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
pub enum ToCmd {
|
pub enum ToCmd {
|
||||||
|
#[default]
|
||||||
Noop,
|
Noop,
|
||||||
Reset,
|
Reset,
|
||||||
AddTlmSet(ToTlmSet),
|
AddTlmSet(ToTlmSet),
|
||||||
|
|||||||
@@ -0,0 +1,376 @@
|
|||||||
|
extern crate alloc;
|
||||||
|
use alloc::boxed::Box;
|
||||||
|
use alloc::string::String;
|
||||||
|
use alloc::vec::Vec;
|
||||||
|
|
||||||
|
pub enum ReflectType {
|
||||||
|
Value,
|
||||||
|
Enumeration,
|
||||||
|
Structure,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum ReflectValue {
|
||||||
|
None,
|
||||||
|
U8(u8),
|
||||||
|
U16(u16),
|
||||||
|
U32(u32),
|
||||||
|
U64(u64),
|
||||||
|
I8(i8),
|
||||||
|
I16(i16),
|
||||||
|
I32(i32),
|
||||||
|
I64(i64),
|
||||||
|
Vec(Vec<ReflectValue>),
|
||||||
|
Str(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ReflectValue {
|
||||||
|
pub fn signed(&self) -> i64 {
|
||||||
|
match self {
|
||||||
|
ReflectValue::None => 0,
|
||||||
|
ReflectValue::U8(v) => *v as i64,
|
||||||
|
ReflectValue::U16(v) => *v as i64,
|
||||||
|
ReflectValue::U32(v) => *v as i64,
|
||||||
|
ReflectValue::U64(v) => *v as i64,
|
||||||
|
ReflectValue::I8(v) => *v as i64,
|
||||||
|
ReflectValue::I16(v) => *v as i64,
|
||||||
|
ReflectValue::I32(v) => *v as i64,
|
||||||
|
ReflectValue::I64(v) => *v as i64,
|
||||||
|
ReflectValue::Vec(_) => 0,
|
||||||
|
ReflectValue::Str(_) => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn unsigned(&self) -> u64 {
|
||||||
|
match self {
|
||||||
|
ReflectValue::None => 0,
|
||||||
|
ReflectValue::U8(v) => *v as u64,
|
||||||
|
ReflectValue::U16(v) => *v as u64,
|
||||||
|
ReflectValue::U32(v) => *v as u64,
|
||||||
|
ReflectValue::U64(v) => *v as u64,
|
||||||
|
ReflectValue::I8(v) => *v as u64,
|
||||||
|
ReflectValue::I16(v) => *v as u64,
|
||||||
|
ReflectValue::I32(v) => *v as u64,
|
||||||
|
ReflectValue::I64(v) => *v as u64,
|
||||||
|
ReflectValue::Vec(_) => 0,
|
||||||
|
ReflectValue::Str(_) => 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Reflect: std::fmt::Debug {
|
||||||
|
fn reflect_type(&self) -> ReflectType;
|
||||||
|
fn type_name(&self) -> &str;
|
||||||
|
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)>;
|
||||||
|
fn set_value(&mut self, value: ReflectValue);
|
||||||
|
fn get_value(&self) -> ReflectValue;
|
||||||
|
fn variants(&self) -> Vec<Box<dyn Reflect>>;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path_set(reflect: &mut dyn Reflect, path: &str, value: ReflectValue) {
|
||||||
|
let mut next = reflect;
|
||||||
|
for p in path.split(".") {
|
||||||
|
let mut index = None;
|
||||||
|
for (i, f) in next.fields().iter().enumerate() {
|
||||||
|
if f.0 == p {
|
||||||
|
index = Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(i) = index {
|
||||||
|
next = next.fields().remove(i).1;
|
||||||
|
} else {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
next.set_value(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn path_get<'a>(reflect: &'a mut dyn Reflect, path: &str) -> Option<&'a mut dyn Reflect> {
|
||||||
|
let mut next = reflect;
|
||||||
|
for p in path.split(".") {
|
||||||
|
let mut index = None;
|
||||||
|
for (i, f) in next.fields().iter().enumerate() {
|
||||||
|
if f.0 == p {
|
||||||
|
index = Some(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(i) = index {
|
||||||
|
next = next.fields().remove(i).1;
|
||||||
|
} else {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(next)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reflect for u8 {
|
||||||
|
fn reflect_type(&self) -> ReflectType {
|
||||||
|
ReflectType::Value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_name(&self) -> &str {
|
||||||
|
"u8"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_value(&mut self, value: ReflectValue) {
|
||||||
|
*self = value.unsigned() as Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_value(&self) -> ReflectValue {
|
||||||
|
ReflectValue::U8(*self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn variants(&self) -> Vec<Box<dyn Reflect>> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Reflect for i8 {
|
||||||
|
fn reflect_type(&self) -> ReflectType {
|
||||||
|
ReflectType::Value
|
||||||
|
}
|
||||||
|
|
||||||
|
fn type_name(&self) -> &str {
|
||||||
|
"i8"
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fields(&mut self) -> Vec<(&str, &mut dyn Reflect)> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_value(&mut self, value: ReflectValue) {
|
||||||
|
*self = value.signed() as Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_value(&self) -> ReflectValue {
|
||||||
|
ReflectValue::I8(*self)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn variants(&self) -> Vec<Box<dyn Reflect>> {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub trait ToCsvClean {
|
||||||
|
// fn to_csv_clean(&self) -> Vec<String>;
|
||||||
|
// fn enumerate_clean(&self) -> Vec<String>;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for u8 {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = u8")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for i8 {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = i8")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for u16 {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = u16")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for i16 {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = i16")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for u32 {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = u32")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for i32 {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = i32")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for u64 {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = u64")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for i64 {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = i64")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for &str {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = String")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for String {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = String")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl ToCsv for bool {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = {}", self)]
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(" = bool")]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<T: ToCsv + Default> ToCsv for Vec<T> {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// self.iter()
|
||||||
|
// .enumerate()
|
||||||
|
// .map(|(i, x)| {
|
||||||
|
// x.to_csv()
|
||||||
|
// .iter()
|
||||||
|
// .map(|a| format!("[{}].{}", i, a))
|
||||||
|
// .collect::<Vec<String>>()
|
||||||
|
// })
|
||||||
|
// .flatten()
|
||||||
|
// .collect()
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// T::default()
|
||||||
|
// .enumerate()
|
||||||
|
// .iter()
|
||||||
|
// .map(|x| format!("[{}].{}", std::any::type_name::<T>(), x))
|
||||||
|
// .collect::<Vec<String>>()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<T: ToCsv + Default, const N: usize> ToCsv for [T; N] {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// self.iter()
|
||||||
|
// .enumerate()
|
||||||
|
// .map(|(i, x)| {
|
||||||
|
// x.to_csv()
|
||||||
|
// .iter()
|
||||||
|
// .map(|a| format!("[{}].{}", i, a))
|
||||||
|
// .collect::<Vec<String>>()
|
||||||
|
// })
|
||||||
|
// .flatten()
|
||||||
|
// .collect()
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// T::default()
|
||||||
|
// .enumerate()
|
||||||
|
// .iter()
|
||||||
|
// .map(|x| format!("[{}].{}", std::any::type_name::<T>(), x))
|
||||||
|
// .collect::<Vec<String>>()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<T1: ToCsv, T2: ToCsv> ToCsv for (T1, T2) {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// let mut csvs = Vec::new();
|
||||||
|
// csvs.extend(self.0.to_csv().iter().map(|x| format!("[0].{}", x)));
|
||||||
|
// csvs.extend(self.1.to_csv().iter().map(|x| format!("[1].{}", x)));
|
||||||
|
// csvs
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(
|
||||||
|
// " = ({}, {})",
|
||||||
|
// std::any::type_name::<T1>(),
|
||||||
|
// std::any::type_name::<T2>()
|
||||||
|
// )]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<T1: ToCsv, T2: ToCsv, T3: ToCsv> ToCsv for (T1, T2, T3) {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// let mut csvs = Vec::new();
|
||||||
|
// csvs.extend(self.0.to_csv().iter().map(|x| format!("[0].{}", x)));
|
||||||
|
// csvs.extend(self.1.to_csv().iter().map(|x| format!("[1].{}", x)));
|
||||||
|
// csvs.extend(self.2.to_csv().iter().map(|x| format!("[2].{}", x)));
|
||||||
|
// csvs
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(
|
||||||
|
// " = ({}, {}, {})",
|
||||||
|
// std::any::type_name::<T1>(),
|
||||||
|
// std::any::type_name::<T2>(),
|
||||||
|
// std::any::type_name::<T2>()
|
||||||
|
// )]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<T1: ToCsv, T2: ToCsv, T3: ToCsv, T4: ToCsv> ToCsv for (T1, T2, T3, T4) {
|
||||||
|
// fn to_csv(&self) -> Vec<String> {
|
||||||
|
// let mut csvs = Vec::new();
|
||||||
|
// csvs.extend(self.0.to_csv().iter().map(|x| format!("[0].{}", x)));
|
||||||
|
// csvs.extend(self.1.to_csv().iter().map(|x| format!("[1].{}", x)));
|
||||||
|
// csvs.extend(self.2.to_csv().iter().map(|x| format!("[2].{}", x)));
|
||||||
|
// csvs.extend(self.3.to_csv().iter().map(|x| format!("[3].{}", x)));
|
||||||
|
// csvs
|
||||||
|
// }
|
||||||
|
// fn enumerate(&self) -> Vec<String> {
|
||||||
|
// vec![format!(
|
||||||
|
// " = ({}, {}, {}, {})",
|
||||||
|
// std::any::type_name::<T1>(),
|
||||||
|
// std::any::type_name::<T2>(),
|
||||||
|
// std::any::type_name::<T2>(),
|
||||||
|
// std::any::type_name::<T3>()
|
||||||
|
// )]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// impl<T: ToCsv> ToCsvClean for T {
|
||||||
|
// fn to_csv_clean(&self) -> Vec<String> {
|
||||||
|
// self.to_csv().iter().map(|x| to_csv_clean(x)).collect()
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn enumerate_clean(&self) -> Vec<String> {
|
||||||
|
// self.enumerate().iter().map(|x| to_csv_clean(x)).collect()
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// fn to_csv_clean(s: &String) -> String {
|
||||||
|
// let s = s.replace(".[", "[");
|
||||||
|
// let s = s.replace(". =", " =");
|
||||||
|
// s
|
||||||
|
// }
|
||||||
@@ -1,151 +0,0 @@
|
|||||||
extern crate alloc;
|
|
||||||
use alloc::format;
|
|
||||||
use alloc::string::String;
|
|
||||||
use alloc::vec;
|
|
||||||
use alloc::vec::Vec;
|
|
||||||
|
|
||||||
pub trait ToCsv {
|
|
||||||
fn to_csv(&self) -> Vec<String>;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ToCsvClean {
|
|
||||||
fn to_csv_clean(&self) -> Vec<String>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for u8 {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for i8 {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for u16 {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for i16 {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for u32 {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for i32 {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for u64 {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for i64 {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for &str {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for String {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ToCsv for bool {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
vec![format!(" = {}", self)]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ToCsv> ToCsv for Vec<T> {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
self.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, x)| {
|
|
||||||
x.to_csv()
|
|
||||||
.iter()
|
|
||||||
.map(|a| format!("[{}].{}", i, a))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ToCsv, const N: usize> ToCsv for [T; N] {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
self.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, x)| {
|
|
||||||
x.to_csv()
|
|
||||||
.iter()
|
|
||||||
.map(|a| format!("[{}].{}", i, a))
|
|
||||||
.collect::<Vec<String>>()
|
|
||||||
})
|
|
||||||
.flatten()
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T1: ToCsv, T2: ToCsv> ToCsv for (T1, T2) {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
let mut csvs = Vec::new();
|
|
||||||
csvs.extend(self.0.to_csv().iter().map(|x| format!("[0].{}", x)));
|
|
||||||
csvs.extend(self.1.to_csv().iter().map(|x| format!("[1].{}", x)));
|
|
||||||
csvs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T1: ToCsv, T2: ToCsv, T3: ToCsv> ToCsv for (T1, T2, T3) {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
let mut csvs = Vec::new();
|
|
||||||
csvs.extend(self.0.to_csv().iter().map(|x| format!("[0].{}", x)));
|
|
||||||
csvs.extend(self.1.to_csv().iter().map(|x| format!("[1].{}", x)));
|
|
||||||
csvs.extend(self.2.to_csv().iter().map(|x| format!("[2].{}", x)));
|
|
||||||
csvs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T1: ToCsv, T2: ToCsv, T3: ToCsv, T4: ToCsv> ToCsv for (T1, T2, T3, T4) {
|
|
||||||
fn to_csv(&self) -> Vec<String> {
|
|
||||||
let mut csvs = Vec::new();
|
|
||||||
csvs.extend(self.0.to_csv().iter().map(|x| format!("[0].{}", x)));
|
|
||||||
csvs.extend(self.1.to_csv().iter().map(|x| format!("[1].{}", x)));
|
|
||||||
csvs.extend(self.2.to_csv().iter().map(|x| format!("[2].{}", x)));
|
|
||||||
csvs.extend(self.3.to_csv().iter().map(|x| format!("[3].{}", x)));
|
|
||||||
csvs
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<T: ToCsv> ToCsvClean for T {
|
|
||||||
fn to_csv_clean(&self) -> Vec<String> {
|
|
||||||
self.to_csv().iter().map(|x| to_csv_clean(x)).collect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_csv_clean(s: &String) -> String {
|
|
||||||
let s = s.replace(".[", "[");
|
|
||||||
let s = s.replace(". =", " =");
|
|
||||||
s
|
|
||||||
}
|
|
||||||
+5
-5
@@ -3,13 +3,13 @@ use crate::Rfe;
|
|||||||
use bincode::{Decode, Encode};
|
use bincode::{Decode, Encode};
|
||||||
|
|
||||||
extern crate alloc;
|
extern crate alloc;
|
||||||
#[cfg(feature = "to_csv")]
|
|
||||||
use crate::to_csv::ToCsv;
|
#[cfg(feature = "serde")]
|
||||||
#[cfg(feature = "to_csv")]
|
use serde::{Deserialize, Serialize};
|
||||||
use macros::ToCsv;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Encode, Decode)]
|
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash, Encode, Decode)]
|
||||||
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
|
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
|
||||||
|
|
||||||
pub struct PerfData {
|
pub struct PerfData {
|
||||||
enter_time: Timestamp,
|
enter_time: Timestamp,
|
||||||
elapsed: u32,
|
elapsed: u32,
|
||||||
|
|||||||
@@ -11,5 +11,5 @@ path = "src/decom.rs"
|
|||||||
anyhow.workspace = true
|
anyhow.workspace = true
|
||||||
log.workspace = true
|
log.workspace = true
|
||||||
simple_logger.workspace = true
|
simple_logger.workspace = true
|
||||||
rfe = { path = "../../rfe", features = ["to_csv"] }
|
rfe = { path = "../../rfe", features = [] }
|
||||||
bincode = { workspace = true, features = ["std"] }
|
bincode = { workspace = true, features = ["std"] }
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ use std::{
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use bincode::decode_from_std_read;
|
use bincode::decode_from_std_read;
|
||||||
use log::*;
|
use log::*;
|
||||||
use rfe::ToCsvClean;
|
use rfe::to_csv::ToCsvClean;
|
||||||
use rfe::{msg::MsgPacket, BINCODE_CONFIG};
|
use rfe::{msg::MsgPacket, BINCODE_CONFIG};
|
||||||
use simple_logger::SimpleLogger;
|
use simple_logger::SimpleLogger;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user