start reflect

This commit is contained in:
Jacob Weaver
2024-12-17 16:13:03 -06:00
parent 5401d624bd
commit c9ad723e79
17 changed files with 904 additions and 239 deletions
+2
View File
@@ -24,3 +24,5 @@ bincode = { version = "2.0.0-rc.3", default-features = false, features = [
simple_logger = "5.0.0"
rp2040-hal = "0.10.2"
rp2040-pac = "0.6.0"
serde = { version = "1.0.216", features = ["derive"] }
serde_json = "1.0.133"
+5 -1
View File
@@ -5,7 +5,11 @@ edition = "2021"
[dependencies]
rfe.path = "../../rfe"
rfe.features = ["std"]
rfe.features = ["std", "serde"]
anyhow.workspace = true
simple_logger = "5.0.0"
log.workspace = true
serde_json.workspace = true
serde.workspace = true
egui = "0.30.0"
eframe = "0.30.0"
+193 -12
View File
@@ -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::{
thread::sleep_until,
collections::HashMap,
fs::write,
thread::{sleep, spawn},
time::{Duration, Instant},
};
use anyhow::anyhow;
use anyhow::Result;
use connector::{Connector, UdpConnector};
use log::*;
use msg::DsTlmSet;
use reflect::*;
use rfe::macros::Reflect;
use rfe::*;
use serde::{Deserialize, Serialize};
use simple_logger::SimpleLogger;
fn main() -> Result<()> {
SimpleLogger::new().init().unwrap();
#[derive(Debug, Clone, Serialize, Deserialize)]
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 {
Self {
name: name.to_string(),
children,
}
}
let mut next_time = Instant::now() + Duration::from_millis(10);
loop {
sleep_until(next_time);
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];
}
while let Some(msgs) = udp.recv() {
for msg in msgs {
info!("got msg {:?}", msg);
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);
}
}
next_time += Duration::from_millis(10);
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
View File
@@ -7,7 +7,7 @@ edition = "2021"
default = []
std = ["dep:mio"]
rp2040 = ["dep:rp2040-hal", "dep:rp2040-pac"]
to_csv = []
serde = ["dep:serde"]
[dependencies]
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-pac = { workspace = true, optional = true }
macros.path = "macros"
serde = { workspace = true, optional = true }
+265 -11
View File
@@ -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 variant_name = &variant.ident;
match &variant.fields {
@@ -51,9 +70,10 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
});
let expanded = quote! {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum #kind_name {
#[default]
#(#kind_enum_arms)*
}
@@ -63,6 +83,12 @@ pub fn kind_derive(input: TokenStream) -> TokenStream {
#(#kind_enum_vec_arms)*
]
}
pub fn to_default(&self) -> #name {
match self {
#(#kind_to_default_arms)*
}
}
}
impl #name {
@@ -93,7 +119,21 @@ pub fn to_csv_derive(input: TokenStream) -> TokenStream {
let field_name = field_ident.to_string();
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 {
*entry = format!("{}.{}", #field_name, &entry);
}
@@ -103,17 +143,23 @@ pub fn to_csv_derive(input: TokenStream) -> TokenStream {
quote! {
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;
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)*
for value in &mut values {
*value = format!("{}", value);
}
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(_) => {
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 {
*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! {
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;
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 {
#(#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;
}
}
}
}
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
View File
@@ -10,9 +10,9 @@ pub mod msg;
mod rfe;
pub use rfe::*;
#[cfg(feature = "to_csv")]
pub mod to_csv;
pub mod reflect;
pub use macros;
pub mod time;
pub mod utils;
+9 -10
View File
@@ -1,17 +1,15 @@
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
use crate::utils::PerfData;
use bincode::{Decode, Encode};
#[cfg(feature = "to_csv")]
use macros::ToCsv;
extern crate alloc;
use alloc::string::String;
use alloc::vec::Vec;
use super::{TlmSetId, TlmSetItem};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct DsTlmSet {
pub items: Vec<TlmSetItem>,
pub id: TlmSetId,
@@ -20,23 +18,24 @@ pub struct DsTlmSet {
}
#[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 perf: PerfData,
pub counter: u32,
}
#[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 counter: u32,
pub bytes_written: u32,
pub bytes_written_this_cycle: u32,
}
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum DsCmd {
#[default]
Noop,
Reset,
CloseAll,
+7 -9
View File
@@ -1,27 +1,25 @@
extern crate alloc;
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
use crate::utils::PerfData;
use bincode::{Decode, Encode};
#[cfg(feature = "to_csv")]
use macros::ToCsv;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[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 perf: PerfData,
pub counter: u32,
}
#[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 counter: u32,
}
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ExampleCmd {
#[default]
Noop,
Reset,
}
+8 -8
View File
@@ -1,14 +1,13 @@
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
use crate::utils::PerfData;
use bincode::{Decode, Encode};
#[cfg(feature = "to_csv")]
use macros::ToCsv;
extern crate alloc;
use alloc::vec::Vec;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[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 perf: PerfData,
pub counter: u32,
@@ -23,14 +22,15 @@ pub struct HsHk {
}
#[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 counter: u32,
}
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum HsCmd {
#[default]
Noop,
Reset,
WatchdogEnableManual(bool),
+18 -17
View File
@@ -15,13 +15,11 @@ mod ds;
pub use ds::*;
use crate::time::Timestamp;
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
#[cfg(feature = "to_csv")]
use macros::ToCsv;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TargetMsg {
// instance is FROM for tlm, is TO for cmds
pub instance: Instance,
@@ -34,18 +32,21 @@ impl TargetMsg {
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Instance {
#[default]
None,
All,
Other,
Example,
Example2,
}
#[derive(Debug, Clone, PartialEq, Kind, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Kind, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Msg {
#[default]
None,
SubRequest,
SubList(SubList),
@@ -66,7 +67,7 @@ pub enum Msg {
}
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct MsgPacket {
pub instance: Instance,
pub msg: Msg,
@@ -91,22 +92,22 @@ impl MsgPacket {
}
}
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct SubList {
pub subs: Vec<TargetMsg>,
}
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ReinitAppCmd {
app_name: String,
}
pub type TlmSetId = u16;
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct TlmSetItem {
pub target: TargetMsg,
pub decimation: u16,
+9 -10
View File
@@ -1,16 +1,14 @@
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
use crate::utils::PerfData;
use bincode::{Decode, Encode};
#[cfg(feature = "to_csv")]
use macros::ToCsv;
extern crate alloc;
use alloc::vec::Vec;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use super::{TlmSetId, TlmSetItem};
#[derive(Debug, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Eq, Hash, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct ToTlmSet {
pub items: Vec<TlmSetItem>,
pub id: TlmSetId,
@@ -18,21 +16,22 @@ pub struct ToTlmSet {
}
#[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 perf: PerfData,
pub counter: u32,
}
#[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 counter: u32,
}
#[derive(Debug, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "to_csv", derive(ToCsv))]
#[derive(Debug, Default, Clone, PartialEq, Encode, Decode)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum ToCmd {
#[default]
Noop,
Reset,
AddTlmSet(ToTlmSet),
+376
View File
@@ -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
// }
-151
View File
@@ -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
View File
@@ -3,13 +3,13 @@ use crate::Rfe;
use bincode::{Decode, Encode};
extern crate alloc;
#[cfg(feature = "to_csv")]
use crate::to_csv::ToCsv;
#[cfg(feature = "to_csv")]
use macros::ToCsv;
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
#[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 {
enter_time: Timestamp,
elapsed: u32,
+1 -1
View File
@@ -11,5 +11,5 @@ path = "src/decom.rs"
anyhow.workspace = true
log.workspace = true
simple_logger.workspace = true
rfe = { path = "../../rfe", features = ["to_csv"] }
rfe = { path = "../../rfe", features = [] }
bincode = { workspace = true, features = ["std"] }
+1 -1
View File
@@ -12,7 +12,7 @@ use std::{
use anyhow::Result;
use bincode::decode_from_std_read;
use log::*;
use rfe::ToCsvClean;
use rfe::to_csv::ToCsvClean;
use rfe::{msg::MsgPacket, BINCODE_CONFIG};
use simple_logger::SimpleLogger;