Countdown interface object in rust no_alloc

⚓ rust    📅 2025-05-20    👤 surdeus    👁️ 4      

surdeus

Warning

This post was published 40 days ago. The information described in this article may have changed.

Im writing a program for Arduino uno that handles a car with engines and many different sensors, and some of the actions take time to execute like travel_cm(amount: u32), which depend on state that is modified by interrupts, and i wanted to implement some kind of Countdown that could be run and return amount left to finish.
In my program there would be some different counters that depend on different objects, and i wanted to have a single counter in my main loop that can be changed depending on action executed.

let countdown = Box<dyn Countdown>;
loop {
  if countdown.check() < 0 {
    //handle next action
     countdown = nextAction.countdown();
  } else {
    //do something in the meanwhile
  }
}

I tried to go about that with closures but working with them proved to be complicated because of their unique types, and because of no allocator i can't use Box<dyn Countdown> to easily handle them. I thought about using some crate that can provide Box<dyn > without heap, also i figured i can do an enum that has every type of countdown closure in it

trait Countdown = Fn() -> i32;
enum Countdowns<A, B, C, D>
where
    A: Countdown,
    B: Countdown,
    C: Countdown,
    D: Countdown,
{
    Left(A),
    Right(B),
    Servo(C),
    Infrared(D),
}

impl<A, B, C, D> Countdowns<A, B, C, D>
where
    A: Countdown,
    B: Countdown,
    C: Countdown,
    D: Countdown,
{
    fn check(&self) -> i32 {
        match self {
            Countdowns::Left(f) => f(),
            Countdowns::Right(f) => f(),
            Countdowns::Servo(f) => f(),
            Countdowns::Infrared(f) => f(),
        }
    }
}

impl CarState {
    fn get_countdown(
        &self,
        typ: i32,
    ) -> Countdowns<impl Countdown , impl Countdown, impl Countdown, impl Countdown> {
        match typ {
            0 => Countdowns::Left(|| self.left),
            1 => Countdowns::Right(|| self.right),
            2 => Countdowns::Servo(|| self.servo),
            _ => Countdowns::Infrared(|| self.ir),
        }
    }
}

Is there an any better, elegant way to go about implementing something like that?
my gihub repo

2 posts - 2 participants

Read full topic

🏷️ rust_feed