From 03afec5dc3a8f754270a73cdf24642b0916e7420 Mon Sep 17 00:00:00 2001 From: Guillaume Binet Date: Sun, 30 Jun 2024 17:18:48 -0500 Subject: [PATCH] Added an indirection in the copperlist to add metadata. --- copper/src/copperlist.rs | 235 ++++++------------ copper/src/curuntime.rs | 9 +- copper/src/cutask.rs | 10 +- copper_clock/src/lib.rs | 3 +- copper_derive/src/lib.rs | 97 +++++--- .../test/copper_log_index/lock.mdb | Bin 8192 -> 8192 bytes copper_traits/src/lib.rs | 6 + examples/cu_rp_gpio/Cargo.toml | 3 +- examples/cu_rp_gpio/src/lib.rs | 4 +- examples/v4lsrc/Cargo.toml | 3 +- examples/v4lsrc/src/lib.rs | 23 +- 11 files changed, 171 insertions(+), 222 deletions(-) diff --git a/copper/src/copperlist.rs b/copper/src/copperlist.rs index 840aaa5eb..831dd9cdb 100644 --- a/copper/src/copperlist.rs +++ b/copper/src/copperlist.rs @@ -5,34 +5,46 @@ use bincode_derive::{Decode, Encode}; use std::iter::{Chain, Rev}; use std::slice::{Iter as SliceIter, IterMut as SliceIterMut}; +use copper_traits::CopperListPayload; + const MAX_TASKS: usize = 512; #[derive(Debug, Encode, Decode)] -struct CopperLiskMask { +pub struct CopperLiskMask { #[allow(dead_code)] mask: [u128; MAX_TASKS / 128 + 1], } #[derive(Debug, Encode, Decode)] -enum CopperListState { +pub enum CopperListState { Free, + Initialized, ProcessingTasks(CopperLiskMask), BeingSerialized, } #[derive(Debug, Encode, Decode)] -struct CopperList { +pub struct CopperList { state: CopperListState, - payload: P, // This is generated from the runtime. + pub payload: P, // This is generated from the runtime. +} + +impl CopperList

{ + // This is not the usual way to create a CopperList, this is just for testing. + fn new(payload: P) -> Self { + CopperList { + state: CopperListState::Initialized, + payload, + } + } } /// This structure maintains the entire memory needed by Copper for one loop for the inter tasks communication within a process. /// T is typically a Tuple of various types of messages that are exchanged between tasks. #[derive(Debug)] -pub struct CuListsManager { +pub struct CuListsManager { #[allow(dead_code)] - copper_list_states: [CopperListState; N], - data: Box<[T; N]>, + data: Box<[CopperList

; N]>, length: usize, insertion_index: usize, } @@ -49,25 +61,15 @@ pub type AscIter<'a, T> = Chain, SliceIter<'a, T>>; /// An mutable ascending iterator over `CircularQueue`. pub type AscIterMut<'a, T> = Chain, SliceIterMut<'a, T>>; -impl PartialEq for CuListsManager { - fn eq(&self, other: &Self) -> bool { - if self.len() != other.len() { - return false; - } - other.iter().zip(self.iter()).all(|(a, b)| a == b) - } -} - -impl CuListsManager { +impl CuListsManager { pub fn new() -> Self { let data = unsafe { - let layout = std::alloc::Layout::new::<[T; N]>(); - let ptr = std::alloc::alloc_zeroed(layout) as *mut [T; N]; + let layout = std::alloc::Layout::new::<[CopperList

; N]>(); + let ptr = std::alloc::alloc_zeroed(layout) as *mut [CopperList

; N]; Box::from_raw(ptr) }; const INITIAL_SLSTATE: CopperListState = CopperListState::Free; CuListsManager { - copper_list_states: [INITIAL_SLSTATE; N], data, length: 0, insertion_index: 0, @@ -104,7 +106,7 @@ impl CuListsManager { } #[inline] - pub fn create(&mut self) -> Option<&mut T> { + pub fn create(&mut self) -> Option<&mut CopperList

> { if self.is_full() { return None; } @@ -116,7 +118,7 @@ impl CuListsManager { } #[inline] - pub fn pop(&mut self) -> Option<&mut T> { + pub fn pop(&mut self) -> Option<&mut CopperList

> { if self.length == 0 { return None; } @@ -134,7 +136,7 @@ impl CuListsManager { /// The iterator goes from the most recently pushed items to the oldest ones. /// #[inline] - pub fn iter(&self) -> Iter { + pub fn iter(&self) -> Iter> { let (a, b) = self.data[0..self.length].split_at(self.insertion_index); a.iter().rev().chain(b.iter().rev()) } @@ -144,7 +146,7 @@ impl CuListsManager { /// The iterator goes from the most recently pushed items to the oldest ones. /// #[inline] - pub fn iter_mut(&mut self) -> IterMut { + pub fn iter_mut(&mut self) -> IterMut> { let (a, b) = self.data.split_at_mut(self.insertion_index); a.iter_mut().rev().chain(b.iter_mut().rev()) } @@ -154,7 +156,7 @@ impl CuListsManager { /// The iterator goes from the least recently pushed items to the newest ones. /// #[inline] - pub fn asc_iter(&self) -> AscIter { + pub fn asc_iter(&self) -> AscIter> { let (a, b) = self.data.split_at(self.insertion_index); b.iter().chain(a.iter()) } @@ -164,7 +166,7 @@ impl CuListsManager { /// The iterator goes from the least recently pushed items to the newest ones. /// #[inline] - pub fn asc_iter_mut(&mut self) -> AscIterMut { + pub fn asc_iter_mut(&mut self) -> AscIterMut> { let (a, b) = self.data.split_at_mut(self.insertion_index); b.iter_mut().chain(a.iter_mut()) } @@ -179,194 +181,109 @@ mod tests { let q = CuListsManager::::new(); assert!(q.is_empty()); - assert_eq!(q.iter().next(), None); + assert!(q.iter().next().is_none()); } #[test] fn partially_full_queue() { let mut q = CuListsManager::::new(); - *q.create().unwrap() = 1; - *q.create().unwrap() = 2; - *q.create().unwrap() = 3; + q.create().unwrap().payload = 1; + q.create().unwrap().payload = 2; + q.create().unwrap().payload = 3; assert!(!q.is_empty()); assert_eq!(q.len(), 3); - let res: Vec<_> = q.iter().map(|&x| x).collect(); + let res: Vec = q.iter().map(|x| x.payload).collect(); assert_eq!(res, [3, 2, 1]); } #[test] fn full_queue() { - let mut q = CuListsManager::<_, 5>::new(); - *q.create().unwrap() = 1; - *q.create().unwrap() = 2; - *q.create().unwrap() = 3; - *q.create().unwrap() = 4; - *q.create().unwrap() = 5; + let mut q = CuListsManager::::new(); + q.create().unwrap().payload = 1; + q.create().unwrap().payload = 2; + q.create().unwrap().payload = 3; + q.create().unwrap().payload = 4; + q.create().unwrap().payload = 5; assert_eq!(q.len(), 5); - let res: Vec<_> = q.iter().map(|&x| x).collect(); + let res: Vec<_> = q.iter().map(|x| x.payload).collect(); assert_eq!(res, [5, 4, 3, 2, 1]); } #[test] fn over_full_queue() { - let mut q = CuListsManager::<_, 5>::new(); - *q.create().unwrap() = 1; - *q.create().unwrap() = 2; - *q.create().unwrap() = 3; - *q.create().unwrap() = 4; - *q.create().unwrap() = 5; - assert_eq!(q.create(), None); + let mut q = CuListsManager::::new(); + q.create().unwrap().payload = 1; + q.create().unwrap().payload = 2; + q.create().unwrap().payload = 3; + q.create().unwrap().payload = 4; + q.create().unwrap().payload = 5; + assert!(q.create().is_none()); assert_eq!(q.len(), 5); - let res: Vec<_> = q.iter().map(|&x| x).collect(); + let res: Vec<_> = q.iter().map(|x| x.payload).collect(); assert_eq!(res, [5, 4, 3, 2, 1]); } #[test] fn clear() { - let mut q = CuListsManager::<_, 5>::new(); - *q.create().unwrap() = 1; - *q.create().unwrap() = 2; - *q.create().unwrap() = 3; - *q.create().unwrap() = 4; - *q.create().unwrap() = 5; - assert_eq!(q.create(), None); + let mut q = CuListsManager::::new(); + q.create().unwrap().payload = 1; + q.create().unwrap().payload = 2; + q.create().unwrap().payload = 3; + q.create().unwrap().payload = 4; + q.create().unwrap().payload = 5; + assert!(q.create().is_none()); assert_eq!(q.len(), 5); q.clear(); assert_eq!(q.len(), 0); - assert_eq!(q.iter().next(), None); + assert!(q.iter().next().is_none()); - *q.create().unwrap() = 1; - *q.create().unwrap() = 2; - *q.create().unwrap() = 3; + q.create().unwrap().payload = 1; + q.create().unwrap().payload = 2; + q.create().unwrap().payload = 3; assert_eq!(q.len(), 3); - let res: Vec<_> = q.iter().map(|&x| x).collect(); + let res: Vec<_> = q.iter().map(|x| x.payload).collect(); assert_eq!(res, [3, 2, 1]); } #[test] fn mutable_iterator() { - let mut q = CuListsManager::<_, 5>::new(); - *q.create().unwrap() = 1; - *q.create().unwrap() = 2; - *q.create().unwrap() = 3; - *q.create().unwrap() = 4; - *q.create().unwrap() = 5; + let mut q = CuListsManager::::new(); + q.create().unwrap().payload = 1; + q.create().unwrap().payload = 2; + q.create().unwrap().payload = 3; + q.create().unwrap().payload = 4; + q.create().unwrap().payload = 5; for x in q.iter_mut() { - *x *= 2; + x.payload *= 2; } - let res: Vec<_> = q.iter().map(|&x| x).collect(); + let res: Vec<_> = q.iter().map(|x| x.payload).collect(); assert_eq!(res, [10, 8, 6, 4, 2]); } #[test] fn zero_sized() { - let mut q = CuListsManager::<_, 5>::new(); - *q.create().unwrap() = (); - *q.create().unwrap() = (); - *q.create().unwrap() = (); + let mut q = CuListsManager::<(), 5>::new(); + *q.create().unwrap() = CopperList::new(()); + *q.create().unwrap() = CopperList::new(()); + *q.create().unwrap() = CopperList::new(()); assert_eq!(q.len(), 3); let mut iter = q.iter(); - assert_eq!(iter.next(), Some(&())); - assert_eq!(iter.next(), Some(&())); - assert_eq!(iter.next(), Some(&())); - assert_eq!(iter.next(), None); - } - - #[test] - fn empty_queue_eq() { - let q1 = CuListsManager::::new(); - let q2 = CuListsManager::::new(); - assert_eq!(q1, q2); - } - - #[test] - fn partially_full_queue_eq() { - let mut q1 = CuListsManager::::new(); - *q1.create().unwrap() = 1; - *q1.create().unwrap() = 2; - *q1.create().unwrap() = 3; - - let mut q2 = CuListsManager::::new(); - *q2.create().unwrap() = 1; - *q2.create().unwrap() = 2; - assert_ne!(q1, q2); - - *q2.create().unwrap() = 3; - assert_eq!(q1, q2); - - *q2.create().unwrap() = 4; - assert_ne!(q1, q2); - } - - #[test] - fn full_queue_eq() { - let mut q1 = CuListsManager::::new(); - *q1.create().unwrap() = 1; - *q1.create().unwrap() = 2; - *q1.create().unwrap() = 3; - *q1.create().unwrap() = 4; - *q1.create().unwrap() = 5; - - let mut q2 = CuListsManager::::new(); - *q2.create().unwrap() = 1; - *q2.create().unwrap() = 2; - *q2.create().unwrap() = 3; - *q2.create().unwrap() = 4; - *q2.create().unwrap() = 5; - - assert_eq!(q1, q2); - } - - #[test] - fn clear_eq() { - let mut q1 = CuListsManager::::new(); - *q1.create().unwrap() = 1; - *q1.create().unwrap() = 2; - *q1.create().unwrap() = 3; - *q1.create().unwrap() = 4; - *q1.create().unwrap() = 5; - q1.clear(); - - let mut q2 = CuListsManager::::new(); - assert_eq!(q1, q2); - - *q2.create().unwrap() = 1; - q2.clear(); - assert_eq!(q1, q2); - } - - #[test] - fn zero_sized_eq() { - let mut q1 = CuListsManager::<_, 3>::new(); - *q1.create().unwrap() = (); - *q1.create().unwrap() = (); - *q1.create().unwrap() = (); - - let mut q2 = CuListsManager::<_, 3>::new(); - *q2.create().unwrap() = (); - *q2.create().unwrap() = (); - assert_ne!(q1, q2); - - *q2.create().unwrap() = (); - assert_eq!(q1, q2); - - q2.create(); - assert_eq!(q1, q2); - - q2.create(); - assert_eq!(q1, q2); + assert_eq!(iter.next().unwrap().payload, ()); + assert_eq!(iter.next().unwrap().payload, ()); + assert_eq!(iter.next().unwrap().payload, ()); + assert!(iter.next().is_none()); } #[test] diff --git a/copper/src/curuntime.rs b/copper/src/curuntime.rs index 02612430c..bcdb9348c 100644 --- a/copper/src/curuntime.rs +++ b/copper/src/curuntime.rs @@ -3,30 +3,31 @@ use crate::config::{CuConfig, NodeId}; use crate::config::{Node, NodeInstanceConfig}; use crate::copperlist::CuListsManager; use crate::CuResult; +use copper_traits::CopperListPayload; use petgraph::prelude::*; /// This is the main structure that will be injected as a member of the Application struct. /// CT is the tuple of all the tasks in order of execution. /// CL is the type of the copper list, representing the input/output messages for all the tasks. -pub struct CuRuntime { +pub struct CuRuntime { /// The tuple of all the tasks in order of execution. pub task_instances: CT, /// Copper lists hold in order all the input/output messages for all the tasks. - pub copper_lists: CuListsManager, + pub copper_lists: CuListsManager, /// The base clock the runtime will be using to record time. pub clock: RobotClock, } /// To be able to share the clock we make the runtime a clock provider.:w -impl ClockProvider for CuRuntime { +impl ClockProvider for CuRuntime { fn get_clock(&self) -> RobotClock { self.clock.clone() } } -impl CuRuntime { +impl CuRuntime { pub fn new( clock: RobotClock, config: &CuConfig, diff --git a/copper/src/cutask.rs b/copper/src/cutask.rs index c031377f4..dd8e24646 100644 --- a/copper/src/cutask.rs +++ b/copper/src/cutask.rs @@ -1,20 +1,20 @@ use copper_clock::RobotClock; -use serde::{Deserialize, Serialize}; use std::fmt; use std::fmt::{Display, Formatter}; use crate::clock::OptionCuTime; use crate::config::NodeInstanceConfig; use crate::CuResult; +use bincode_derive::{Decode, Encode}; // Everything that is stateful in copper for zero copy constraints need to be restricted to this trait. -pub trait CuMsgPayload: Default + Serialize + for<'a> Deserialize<'a> + Sized {} +pub trait CuMsgPayload: Default + bincode::Encode + bincode::Decode + Sized {} // Also anything that follows this contract can be a payload (blanket implementation) -impl CuMsgPayload for T where T: Default + Serialize + for<'a> Deserialize<'a> + Sized {} +impl CuMsgPayload for T where T: Default + bincode::Encode + bincode::Decode + Sized {} /// CuMsgMetadata is a structure that contains metadata common to all CuMsgs. -#[derive(Debug, PartialEq, Default)] +#[derive(Debug, Default, Encode, Decode)] pub struct CuMsgMetadata { /// The time before the process method is called. pub before_process: OptionCuTime, @@ -33,7 +33,7 @@ impl Display for CuMsgMetadata { } /// CuMsg is the envelope holding the msg payload and the metadata between tasks. -#[derive(Debug, PartialEq)] +#[derive(Debug, Encode, Decode)] pub struct CuMsg where T: CuMsgPayload, diff --git a/copper_clock/src/lib.rs b/copper_clock/src/lib.rs index 5ab73e3b3..1dab5c8d8 100644 --- a/copper_clock/src/lib.rs +++ b/copper_clock/src/lib.rs @@ -4,6 +4,7 @@ use bincode::enc::Encode; use bincode::enc::Encoder; use bincode::error::{DecodeError, EncodeError}; use bincode::BorrowDecode; +use bincode_derive::{Decode, Encode}; use core::ops::{Add, Sub}; pub use quanta::Instant; use quanta::{Clock, Mock}; @@ -105,7 +106,7 @@ impl Display for CuDuration { pub type CuTime = CuDuration; /// Homebrewed Option to avoid using 128bits just to represent an Option. -#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +#[derive(Clone, Copy, Debug, PartialEq, Encode, Decode)] pub struct OptionCuTime(CuTime); const NONE_VALUE: u64 = 0xFFFFFFFFFFFFFFFF; diff --git a/copper_derive/src/lib.rs b/copper_derive/src/lib.rs index 490640765..b2a78ccc0 100644 --- a/copper_derive/src/lib.rs +++ b/copper_derive/src/lib.rs @@ -73,7 +73,7 @@ pub fn copper_runtime(args: TokenStream, input: TokenStream) -> TokenStream { println!("[build runtime field]"); // add that to a new field let runtime_field: Field = parse_quote! { - copper_runtime: _CuRuntime + copper_runtime: _CuRuntime }; let name = &item_struct.ident; @@ -110,53 +110,77 @@ pub fn copper_runtime(args: TokenStream, input: TokenStream) -> TokenStream { let runtime_plan_code: Vec<_> = runtime_plan .iter() .map(|step| { - - println!("{} -> {} as {:?}. Input={:?}, Output={:?}", step.node.get_id(), step.node.get_type(), step.task_type, step.input_msg_type, step.output_msg_type); + println!( + "{} -> {} as {:?}. Input={:?}, Output={:?}", + step.node.get_id(), + step.node.get_type(), + step.task_type, + step.input_msg_type, + step.output_msg_type + ); let node_index = int2index(step.node_id); let task_instance = quote! { self.copper_runtime.task_instances.#node_index }; - let comment_str = format!("/// {} ({:?}) I:{:?} O:{:?}",step.node.get_id(), step.task_type, step.input_msg_type, step.output_msg_type); + let comment_str = format!( + "/// {} ({:?}) I:{:?} O:{:?}", + step.node.get_id(), + step.task_type, + step.input_msg_type, + step.output_msg_type + ); let comment_tokens: proc_macro2::TokenStream = parse_str(&comment_str).unwrap(); let process_call = match step.task_type { CuTaskType::Source => { - let output_culist_index = int2index(step.culist_output_index.expect("Src task should have an output message index.")); + let output_culist_index = int2index( + step.culist_output_index + .expect("Src task should have an output message index."), + ); quote! { - { - #comment_tokens - let cumsg_output = &mut culist.#output_culist_index; - cumsg_output.metadata.before_process = self.copper_runtime.clock.now().into(); - #task_instance.process(&self.copper_runtime.clock, cumsg_output)?; - cumsg_output.metadata.after_process = self.copper_runtime.clock.now().into(); + { + #comment_tokens + let cumsg_output = &mut payload.#output_culist_index; + cumsg_output.metadata.before_process = self.copper_runtime.clock.now().into(); + #task_instance.process(&self.copper_runtime.clock, cumsg_output)?; + cumsg_output.metadata.after_process = self.copper_runtime.clock.now().into(); + } } } - }, CuTaskType::Sink => { - let input_culist_index = int2index(step.culist_input_index.expect("Sink task should have an input message index.")); + let input_culist_index = int2index( + step.culist_input_index + .expect("Sink task should have an input message index."), + ); quote! { - { - #comment_tokens - let cumsg_input = &mut culist.#input_culist_index; - #task_instance.process(&self.copper_runtime.clock, cumsg_input)?; + { + #comment_tokens + let cumsg_input = &mut payload.#input_culist_index; + #task_instance.process(&self.copper_runtime.clock, cumsg_input)?; + } } } - }, CuTaskType::Regular => { { - let input_culist_index = int2index(step.culist_input_index.expect("Sink task should have an input message index.")); - let output_culist_index = int2index(step.culist_output_index.expect("Src task should have an output message index.")); - quote! { - { - #comment_tokens - let cumsg_input = &mut culist.#input_culist_index; - let cumsg_output = &mut culist.#output_culist_index; - cumsg_output.metadata.before_process = self.copper_runtime.clock.now().into(); - #task_instance.process(&self.copper_runtime.clock, cumsg_input, cumsg_output)?; - cumsg_output.metadata.after_process = self.copper_runtime.clock.now().into(); - } + let input_culist_index = int2index( + step.culist_input_index + .expect("Sink task should have an input message index."), + ); + let output_culist_index = int2index( + step.culist_output_index + .expect("Src task should have an output message index."), + ); + quote! { + { + #comment_tokens + let cumsg_input = &mut payload.#input_culist_index; + let cumsg_output = &mut payload.#output_culist_index; + cumsg_output.metadata.before_process = self.copper_runtime.clock.now().into(); + #task_instance.process(&self.copper_runtime.clock, cumsg_input, cumsg_output)?; + cumsg_output.metadata.after_process = self.copper_runtime.clock.now().into(); + } + } } } - }, }; process_call @@ -188,14 +212,15 @@ pub fn copper_runtime(args: TokenStream, input: TokenStream) -> TokenStream { let culist_indices = (0..(culist_size as u32)).map(int2index); let collect_metadata_function = quote! { pub fn collect_metadata<'a>(culist: &'a CuList) -> [&'a _CuMsgMetadata; #culist_size] { - [#( &culist.#culist_indices.metadata, )*] + [#( &culist.payload.#culist_indices.metadata, )*] } }; println!("[build the run method]"); let run_method = quote! { pub fn run(&mut self, iterations: u32) -> _CuResult<()> { - let culist = self.copper_runtime.copper_lists.create().expect("Ran out of space for copper lists"); // FIXME: error handling. + let mut culist = self.copper_runtime.copper_lists.create().expect("Ran out of space for copper lists"); // FIXME: error handling. + let payload = &mut culist.payload; for _ in 0..iterations { #(#runtime_plan_code)* } @@ -229,14 +254,16 @@ pub fn copper_runtime(args: TokenStream, input: TokenStream) -> TokenStream { use copper::cutask::CuTask as _CuTask; use copper::cutask::CuMsg as _CuMsg; use copper::cutask::CuMsgMetadata as _CuMsgMetadata; + use copper::copperlist::CopperList as _CopperList; use copper::clock::RobotClock as _RobotClock; use copper::clock::OptionCuTime as _OptionCuTime; // This is the heart of everything. // CuTasks is the list of all the tasks types. - // CuList is the list of all the messages types. + // CuList is a CopperList with the list of all the messages types as payload. pub type CuTasks = #task_types_tuple; - pub type CuList = #msgs_types_tuple; + pub type CuPayload = #msgs_types_tuple; + pub type CuList = _CopperList; // This generates a way to get the metadata of every single message of a culist at low cost #collect_metadata_function @@ -253,7 +280,7 @@ pub fn copper_runtime(args: TokenStream, input: TokenStream) -> TokenStream { let config = _read_configuration(#config_file)?; Ok(#name { - copper_runtime: _CuRuntime::::new(clock, &config, tasks_instanciator)? + copper_runtime: _CuRuntime::::new(clock, &config, tasks_instanciator)? }) } diff --git a/copper_log_reader/test/copper_log_index/lock.mdb b/copper_log_reader/test/copper_log_index/lock.mdb index b92473317ec6da554434f072742bb6fe75aa0e4f..cca78c4d22fac6e04d815eb919b6402d76011ac9 100644 GIT binary patch delta 37 scmZp0XmFTd!N@c*P<8N|!* CopperListPayload for T where T: bincode::Encode + bincode::Decode + Sized {} diff --git a/examples/cu_rp_gpio/Cargo.toml b/examples/cu_rp_gpio/Cargo.toml index 5e7655739..91b91b70b 100644 --- a/examples/cu_rp_gpio/Cargo.toml +++ b/examples/cu_rp_gpio/Cargo.toml @@ -12,5 +12,6 @@ copper-log-derive = { path = "../../copper_log_derive" } copper-log-runtime = { path = "../../copper_log_runtime" } copper-log = { path = "../../copper_log" } rppal = "0.18.0" -serde = { version = "1.0.203", features = ["derive"] } +bincode_derive = "2.0.0-rc.3" +bincode = { version = "2.0.0-rc.3" } lazy_static = "1.4.0" \ No newline at end of file diff --git a/examples/cu_rp_gpio/src/lib.rs b/examples/cu_rp_gpio/src/lib.rs index 5d1ccbe08..32dcdfe5d 100644 --- a/examples/cu_rp_gpio/src/lib.rs +++ b/examples/cu_rp_gpio/src/lib.rs @@ -25,7 +25,9 @@ pub struct RPGpio { pin: u8, } -#[derive(Debug, Clone, Copy, Default, serde::Serialize, serde::Deserialize, PartialEq)] +#[derive( + Debug, Clone, Copy, Default, bincode_derive::Encode, bincode_derive::Decode, PartialEq, +)] pub struct RPGpioMsg { pub on: bool, pub creation: copper::clock::OptionCuTime, diff --git a/examples/v4lsrc/Cargo.toml b/examples/v4lsrc/Cargo.toml index e9a8b5f8a..d97a28631 100644 --- a/examples/v4lsrc/Cargo.toml +++ b/examples/v4lsrc/Cargo.toml @@ -11,5 +11,6 @@ copper_plugin_type = "driver" [dependencies] copper = { path = "../../copper" } -serde = { version = "1.0.202", features = ["derive"] } +bincode_derive = "2.0.0-rc.3" +bincode = { version = "2.0.0-rc.3" } linux-video = { version = "0.1.1" } \ No newline at end of file diff --git a/examples/v4lsrc/src/lib.rs b/examples/v4lsrc/src/lib.rs index 84eb44884..bebeb23ca 100644 --- a/examples/v4lsrc/src/lib.rs +++ b/examples/v4lsrc/src/lib.rs @@ -1,16 +1,14 @@ +use copper::clock::RobotClock; use linux_video::types::*; use linux_video::{Device, Stream}; -use serde::{Deserialize, Serialize}; -use copper::clock::RobotClock; +use bincode_derive::{Decode, Encode}; use copper::config::NodeInstanceConfig; use copper::cutask::{CuMsg, CuSrcTask, CuTaskLifecycle}; -use copper::serde::arrays; use copper::CuResult; -#[derive(Serialize, Deserialize)] +#[derive(Decode, Encode)] pub struct ImageMsg { - #[serde(with = "arrays")] pub buffer: [[u8; 1920]; 1200], } @@ -22,15 +20,6 @@ impl Default for ImageMsg { } } -impl PartialEq for ImageMsg { - fn eq(&self, other: &Self) -> bool { - self.buffer - .iter() - .flatten() - .eq(other.buffer.iter().flatten()) - } -} - impl ImageMsg { fn copy_from(&mut self, buff_src: &[u8]) { let mut x = 0usize; @@ -97,7 +86,11 @@ impl CuTaskLifecycle for Video4LinuxSource { impl CuSrcTask for Video4LinuxSource { type Output = ImageMsg; - fn process(&mut self, _clock: &RobotClock, empty_msg: &mut CuMsg) -> CuResult<()> { + fn process( + &mut self, + _clock: &RobotClock, + empty_msg: &mut CuMsg, + ) -> CuResult<()> { let stream = self.stream.as_ref().unwrap(); if let Ok(buffer) = stream.next() { let buffer = buffer.lock();