pros_sync/
lib.rs

1//! Synchronous robot code trait for [pros-rs](https://crates.io/crates/pros).
2
3#![no_std]
4
5use pros_core::error::Result;
6
7/// A trait for robot code that runs without the async executor spun up.
8/// This trait isn't recommended. See `AsyncRobot` in [pros-async](https://crates.io/crates/pros-async) for the preferred trait to run robot code.
9pub trait SyncRobot {
10    /// Runs during the operator control period.
11    /// This function may be called more than once.
12    /// For that reason, do not use `Peripherals::take` in this function.
13    fn opcontrol(&mut self) -> Result {
14        Ok(())
15    }
16    /// Runs during the autonomous period.
17    fn auto(&mut self) -> Result {
18        Ok(())
19    }
20    /// Runs continuously during the disabled period.
21    fn disabled(&mut self) -> Result {
22        Ok(())
23    }
24    /// Runs once when the competition system is initialized.
25    fn comp_init(&mut self) -> Result {
26        Ok(())
27    }
28}
29
30#[doc(hidden)]
31#[macro_export]
32macro_rules! __gen_sync_exports {
33    ($rbt:ty) => {
34        pub static mut ROBOT: Option<$rbt> = None;
35
36        #[doc(hidden)]
37        #[no_mangle]
38        extern "C" fn opcontrol() {
39            <$rbt as $crate::SyncRobot>::opcontrol(unsafe {
40                ROBOT
41                    .as_mut()
42                    .expect("Expected initialize to run before opcontrol")
43            })
44            .unwrap();
45        }
46
47        #[doc(hidden)]
48        #[no_mangle]
49        extern "C" fn autonomous() {
50            <$rbt as $crate::SyncRobot>::auto(unsafe {
51                ROBOT
52                    .as_mut()
53                    .expect("Expected initialize to run before opcontrol")
54            })
55            .unwrap();
56        }
57
58        #[doc(hidden)]
59        #[no_mangle]
60        extern "C" fn disabled() {
61            <$rbt as $crate::SyncRobot>::disabled(unsafe {
62                ROBOT
63                    .as_mut()
64                    .expect("Expected initialize to run before opcontrol")
65            })
66            .unwrap();
67        }
68
69        #[doc(hidden)]
70        #[no_mangle]
71        extern "C" fn competition_initialize() {
72            <$rbt as $crate::SyncRobot>::comp_init(unsafe {
73                ROBOT
74                    .as_mut()
75                    .expect("Expected initialize to run before opcontrol")
76            })
77            .unwrap();
78        }
79    };
80}
81
82/// Allows your sync robot code to be executed by the pros kernel.
83/// If your robot struct implements Default then you can just supply this macro with its type.
84/// If not, you can supply an expression that returns your robot type to initialize your robot struct.
85/// The code that runs to create your robot struct will run in the initialize function in PROS.
86///
87/// Example of using the macro with a struct that implements Default:
88/// ```rust
89/// use pros::prelude::*;
90/// #[derive(Default)]
91/// struct ExampleRobot;
92/// impl SyncRobot for ExampleRobot {
93///    asnyc fn opcontrol(&mut self) -> pros::Result {
94///       println!("Hello, world!");
95///      Ok(())
96///   }
97/// }
98/// sync_robot!(ExampleRobot);
99/// ```
100///
101/// Example of using the macro with a struct that does not implement Default:
102/// ```rust
103/// use pros::prelude::*;
104/// struct ExampleRobot {
105///    x: i32,
106/// }
107/// impl SyncRobot for ExampleRobot {
108///     async fn opcontrol(&mut self) -> pros::Result {
109///         println!("Hello, world! {}", self.x);
110///         Ok(())
111///     }
112/// }
113/// impl ExampleRobot {
114///     pub fn new() -> Self {
115///        Self { x: 5 }
116///    }
117/// }
118/// sync_robot!(ExampleRobot, ExampleRobot::new());
119#[macro_export]
120macro_rules! sync_robot {
121    ($rbt:ty) => {
122        $crate::__gen_sync_exports!($rbt);
123
124        #[no_mangle]
125        extern "C" fn initialize() {
126            let robot = Default::default();
127            unsafe {
128                ROBOT = Some(robot);
129            }
130        }
131    };
132    ($rbt:ty, $init:expr) => {
133        $crate::__gen_sync_exports!($rbt);
134
135        #[no_mangle]
136        extern "C" fn initialize() {
137            let robot = $init;
138            unsafe {
139                ROBOT = Some(robot);
140            }
141        }
142    };
143}