obd2/src/commands/macros.rs
Robert Sammelson 13b9041511
Add the remaining service $00 PIDs up to $20
Also restructure the code to implement get_dtcs and get_dtc_info by
implementing GetObd2Values on the data types they return. This brings
them in line with every other getter function besides get_vin.
2023-05-21 01:53:12 -04:00

134 lines
3.7 KiB
Rust

macro_rules! trait_func {
{
$(#[$attr:meta])*
fn $name:ident($service:expr) -> $retrieve_type:ty;
} => {
$(#[$attr])*
fn $name(&mut self) -> Result<Vec<$retrieve_type>>;
};
{
$(#[$attr:meta])*
fn $name:ident($service:expr, $pid:expr) -> $retrieve_type:ty;
} => {
$(#[$attr])*
fn $name(&mut self) -> Result<Vec<$retrieve_type>>;
};
{
$(#[$attr:meta])*
fn $name:ident($service:expr, $pid:expr, $map:expr) -> $retrieve_type:ty;
} => {
$(#[$attr])*
fn $name(&mut self) -> Result<Vec<$retrieve_type>>;
};
{
$(#[$attr:meta])*
fn $name:ident<$retrieve_type:ty>($service:expr, $pid:expr, $map:expr) -> $out_type:ty;
} => {
$(#[$attr])*
fn $name(&mut self) -> Result<Vec<$out_type>>;
};
}
macro_rules! impl_func {
{
$(#[$attr:meta])*
fn $name:ident($service:expr) -> $retrieve_type:ty;
} => {
fn $name(&mut self) -> Result<Vec<$retrieve_type>> {
<$retrieve_type>::get_obd2_val_mode(self, $service)
}
};
{
$(#[$attr:meta])*
fn $name:ident($service:expr, $pid:expr) -> $retrieve_type:ty;
} => {
fn $name(&mut self) -> Result<Vec<$retrieve_type>> {
<$retrieve_type>::get_obd2_val(self, $service, $pid)
}
};
{
$(#[$attr:meta])*
fn $name:ident($service:expr, $pid:expr, $map:expr) -> $retrieve_type:ty;
} => {
fn $name(&mut self) -> Result<Vec<$retrieve_type>> {
$map(<$retrieve_type>::get_obd2_val(self, $service, $pid))
}
};
{
$(#[$attr:meta])*
fn $name:ident<$retrieve_type:ty>($service:expr, $pid:expr, $map:expr) -> $out_type:ty;
} => {
fn $name(&mut self) -> Result<Vec<$out_type>> {
Ok(
<$retrieve_type>::get_obd2_val(self, $service, $pid)?
.into_iter()
.map(|v| $map(v.into()))
.collect()
)
}
};
}
macro_rules! func {
{
$(#[$attr:meta])*
trait $trait_name:ident;
$({
$(
$(#[$f_attr_inner:meta])*
fn $f_name:ident($self:ident, $f_service:expr$(, $f_pid:expr)?) -> $f_output:ty
$inside:block
)+
})?
$(
$(#[$attr_inner:meta])*
fn $name:ident$(<$retrieve_type:ty>)?($service:expr$(, $pid:expr$(, $map:expr)?)?) -> $output:ty;
)*
} => {
$(#[$attr])*
pub trait $trait_name: private::Sealed {
$($(
$(#[$f_attr_inner])*
fn $f_name(&mut self) -> $f_output;
)+)?
$(
trait_func! {
$(#[$attr_inner])*
///
#[doc=concat!(
"Details: service ", $service,
$(", PID ", $pid,)?
", read type: `", decode_type!($output $(, $retrieve_type)?), "`"
)]
fn $name$(<$retrieve_type>)?($service$(, $pid$(, $map)?)?) -> $output;
}
)*
}
impl<T: Obd2Device> $trait_name for T {
$($(
fn $f_name(&mut $self) -> $f_output
$inside
)+)?
$(
impl_func! {
$(#[$attr_inner])*
fn $name$(<$retrieve_type>)?($service$(, $pid$(, $map)?)?) -> $output;
}
)*
}
};
}
macro_rules! decode_type {
($_:ty, $t:ty) => {
stringify!($t)
};
($t:ty) => {
stringify!($t)
};
}