use crate::{MAX_SIGNALS_PER_MESSAGE, Signal, compat::Vec};
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Signals {
signals: Vec<Signal, { MAX_SIGNALS_PER_MESSAGE }>,
}
impl From<&[Signal]> for Signals {
fn from(signals: &[Signal]) -> Self {
Self::from_slice(signals)
}
}
#[cfg(feature = "std")]
impl From<std::vec::Vec<Signal>> for Signals {
fn from(signals: std::vec::Vec<Signal>) -> Self {
Self::from_slice(&signals)
}
}
impl From<Vec<Signal, { MAX_SIGNALS_PER_MESSAGE }>> for Signals {
fn from(signals: Vec<Signal, { MAX_SIGNALS_PER_MESSAGE }>) -> Self {
Self::from_slice(signals.as_slice())
}
}
impl Signals {
pub(crate) fn from_slice(signals: &[Signal]) -> Self {
let count = signals.len().min(MAX_SIGNALS_PER_MESSAGE);
let signals_vec: Vec<Signal, { MAX_SIGNALS_PER_MESSAGE }> =
signals.iter().take(count).cloned().collect();
Self {
signals: signals_vec,
}
}
#[inline]
#[must_use = "iterator is lazy and does nothing unless consumed"]
pub fn iter(&self) -> impl Iterator<Item = &Signal> + '_ {
self.signals.iter()
}
#[inline]
#[must_use = "return value should be used"]
pub fn len(&self) -> usize {
self.signals.len()
}
#[inline]
#[must_use = "return value should be used"]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[inline]
#[must_use = "return value should be used"]
pub fn at(&self, index: usize) -> Option<&Signal> {
self.signals.get(index)
}
#[must_use = "return value should be used"]
pub fn find(&self, name: &str) -> Option<&Signal> {
self.iter().find(|s| s.name() == name)
}
#[must_use = "return value should be used"]
pub(crate) fn find_mut(&mut self, name: &str) -> Option<&mut Signal> {
self.signals.iter_mut().find(|s| s.name() == name)
}
}
#[cfg(test)]
mod tests {
use super::Signals;
use crate::{Parser, Signal};
#[cfg(feature = "std")]
mod test_from_slice {
use super::*;
#[test]
fn test_signals_from_slice() {
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signal2 = Signal::parse(
&mut Parser::new(b"SG_ Signal2 : 8|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1, signal2]);
assert_eq!(signals.len(), 2);
assert!(!signals.is_empty());
assert_eq!(signals.at(0).unwrap().name(), "Signal1");
assert_eq!(signals.at(1).unwrap().name(), "Signal2");
}
#[test]
fn test_signals_from_signals_slice_empty() {
let signals = Signals::from_slice(&[]);
assert_eq!(signals.len(), 0);
assert!(signals.is_empty());
assert!(signals.at(0).is_none());
}
#[test]
fn test_signals_from_slice_multiple() {
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signal2 = Signal::parse(
&mut Parser::new(b"SG_ Signal2 : 8|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signal3 = Signal::parse(
&mut Parser::new(b"SG_ Signal3 : 16|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1, signal2, signal3]);
assert_eq!(signals.len(), 3);
assert_eq!(signals.at(0).unwrap().name(), "Signal1");
assert_eq!(signals.at(1).unwrap().name(), "Signal2");
assert_eq!(signals.at(2).unwrap().name(), "Signal3");
}
}
mod test_iter {
use super::*;
#[test]
fn test_signals_iter() {
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
)
.unwrap();
let signal2 = Signal::parse(
&mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1, signal2]);
let mut iter = signals.iter();
assert_eq!(iter.next().unwrap().name(), "RPM");
assert_eq!(iter.next().unwrap().name(), "Temp");
assert!(iter.next().is_none());
}
#[test]
fn test_signals_iter_empty() {
let signals = Signals::from_slice(&[]);
let mut iter = signals.iter();
assert!(iter.next().is_none());
}
#[test]
fn test_signals_iter_multiple() {
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signal2 = Signal::parse(
&mut Parser::new(b"SG_ Signal2 : 8|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signal3 = Signal::parse(
&mut Parser::new(b"SG_ Signal3 : 16|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1, signal2, signal3]);
let mut iter = signals.iter();
assert_eq!(iter.next().unwrap().name(), "Signal1");
assert_eq!(iter.next().unwrap().name(), "Signal2");
assert_eq!(iter.next().unwrap().name(), "Signal3");
assert!(iter.next().is_none());
}
}
mod test_len {
use super::*;
#[test]
fn test_signals_len() {
let signals = Signals::from_slice(&[]);
assert_eq!(signals.len(), 0);
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1]);
assert_eq!(signals.len(), 1);
}
}
mod test_is_empty {
use super::*;
#[test]
fn test_signals_is_empty() {
let signals = Signals::from_slice(&[]);
assert!(signals.is_empty());
assert_eq!(signals.len(), 0);
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1]);
assert!(!signals.is_empty());
}
}
mod test_at {
use super::*;
#[test]
fn test_signals_at() {
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
)
.unwrap();
let signal2 = Signal::parse(
&mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1, signal2]);
assert_eq!(signals.at(0).unwrap().name(), "RPM");
assert_eq!(signals.at(1).unwrap().name(), "Temp");
assert!(signals.at(2).is_none());
}
#[test]
fn test_signals_at_out_of_bounds() {
let signal = Signal::parse(
&mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal]);
assert!(signals.at(0).is_some());
assert_eq!(signals.at(0).unwrap().name(), "RPM");
assert!(signals.at(1).is_none());
assert!(signals.at(100).is_none());
assert!(signals.at(usize::MAX).is_none());
}
}
mod test_find {
use super::*;
#[test]
fn test_signals_find() {
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
)
.unwrap();
let signal2 = Signal::parse(
&mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1, signal2]);
assert_eq!(signals.find("RPM").unwrap().name(), "RPM");
assert_eq!(signals.find("Temp").unwrap().name(), "Temp");
assert!(signals.find("Nonexistent").is_none());
}
#[test]
fn test_signals_find_case_sensitive() {
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ RPM : 0|16@0+ (0.25,0) [0|8000] \"rpm\"").unwrap(),
)
.unwrap();
let signal2 = Signal::parse(
&mut Parser::new(b"SG_ Temp : 16|8@0- (1,-40) [-40|215] \"\xC2\xB0C\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1, signal2]);
assert!(signals.find("RPM").is_some());
assert_eq!(signals.find("RPM").unwrap().name(), "RPM");
assert!(signals.find("rpm").is_none());
assert!(signals.find("Rpm").is_none());
assert!(signals.find("Temp").is_some());
assert_eq!(signals.find("Temp").unwrap().name(), "Temp");
assert!(signals.find("Nonexistent").is_none());
assert!(signals.find("").is_none());
}
#[test]
fn test_signals_find_empty_collection() {
let signals = Signals::from_slice(&[]);
assert!(signals.find("RPM").is_none());
assert!(signals.find("").is_none());
}
#[test]
fn test_signals_find_not_found() {
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1]);
assert!(signals.find("Nonexistent").is_none());
assert!(signals.find("").is_none());
assert!(signals.find("signal1").is_none()); }
#[test]
fn test_signals_find_first_match() {
let signal1 = Signal::parse(
&mut Parser::new(b"SG_ Signal1 : 0|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signal2 = Signal::parse(
&mut Parser::new(b"SG_ Signal1 : 8|8@0+ (1,0) [0|255] \"\"").unwrap(),
)
.unwrap();
let signals = Signals::from_slice(&[signal1, signal2]);
let found = signals.find("Signal1");
assert!(found.is_some());
assert_eq!(found.unwrap().start_bit(), 0); }
}
}