Skip to content

Instantly share code, notes, and snippets.

@patrickelectric
Created November 21, 2024 16:46
Show Gist options
  • Save patrickelectric/5e00ebd420a96c427be8a8df2f71d499 to your computer and use it in GitHub Desktop.
Save patrickelectric/5e00ebd420a96c427be8a8df2f71d499 to your computer and use it in GitHub Desktop.
Multiple trait same object list
use std::error::Error;
pub trait AnyHardware {
fn as_any(&self) -> &dyn std::any::Any;
fn as_any_mut(&mut self) -> &mut dyn std::any::Any;
fn as_accelerometer_sensor(&mut self) -> Option<&mut dyn AccelerometerSensor> {
None
}
fn as_gyroscope_sensor(&mut self) -> Option<&mut dyn GyroscopeSensor> {
None
}
fn as_magnetometer_sensor(&mut self) -> Option<&mut dyn MagnetometerSensor> {
None
}
}
pub trait AccelerometerSensor: AnyHardware {
fn read_acceleration(&mut self) -> Result<(f32, f32, f32), Box<dyn Error>>;
}
pub trait GyroscopeSensor: AnyHardware {
fn read_angular_velocity(&mut self) -> Result<(f32, f32, f32), Box<dyn Error>>;
}
pub trait MagnetometerSensor: AnyHardware {
fn read_magnetic_field(&mut self) -> Result<(f32, f32, f32), Box<dyn Error>>;
}
struct MyAcc {}
impl MyAcc {
fn new() -> Self {
Self {}
}
}
impl AnyHardware for MyAcc {
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_accelerometer_sensor(&mut self) -> Option<&mut dyn AccelerometerSensor> {
Some(self)
}
}
impl AccelerometerSensor for MyAcc {
fn read_acceleration(&mut self) -> Result<(f32, f32, f32), Box<dyn Error>> {
Ok((1.0, 0.0, 0.0))
}
}
struct MyGyro {}
impl MyGyro {
fn new() -> Self {
Self {}
}
}
impl AnyHardware for MyGyro {
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_gyroscope_sensor(&mut self) -> Option<&mut dyn GyroscopeSensor> {
Some(self)
}
}
impl GyroscopeSensor for MyGyro {
fn read_angular_velocity(&mut self) -> Result<(f32, f32, f32), Box<dyn Error>> {
Ok((0.0, 1.0, 0.0))
}
}
struct MyMag {}
impl MyMag {
fn new() -> Self {
Self {}
}
}
impl AnyHardware for MyMag {
fn as_any(&self) -> &dyn std::any::Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn std::any::Any {
self
}
fn as_magnetometer_sensor(&mut self) -> Option<&mut dyn MagnetometerSensor> {
Some(self)
}
}
impl MagnetometerSensor for MyMag {
fn read_magnetic_field(&mut self) -> Result<(f32, f32, f32), Box<dyn Error>> {
Ok((0.0, 0.0, 1.0))
}
}
struct Navigator {
hardware: Vec<Box<dyn AnyHardware>>,
}
impl Navigator {
fn check_sensors(&mut self) {
for hardware in &mut self.hardware {
if let Some(accel_sensor) = hardware.as_accelerometer_sensor() {
println!("Acceleration: {:?}", accel_sensor.read_acceleration().unwrap());
}
if let Some(gyro_sensor) = hardware.as_gyroscope_sensor() {
println!("Angular Velocity: {:?}", gyro_sensor.read_angular_velocity().unwrap());
}
if let Some(mag_sensor) = hardware.as_magnetometer_sensor() {
println!("Magnetic Field: {:?}", mag_sensor.read_magnetic_field().unwrap());
}
}
}
}
struct NavigatorBuilder {
navigator: Navigator,
}
impl NavigatorBuilder {
pub fn new() -> Self {
Self {
navigator: Navigator {
hardware: Vec::new(),
},
}
}
pub fn with_hardware<S: AnyHardware + 'static>(mut self, sensor: S) -> Self {
self.navigator.hardware.push(Box::new(sensor));
self
}
pub fn build(self) -> Navigator {
self.navigator
}
}
fn main() {
let mut navigator = NavigatorBuilder::new()
.with_hardware(MyAcc::new())
.with_hardware(MyGyro::new())
.with_hardware(MyMag::new())
.build();
navigator.check_sensors();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment