1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
//! Safe and idiomatic Rust wrappers for [RIOT-OS]
//!
//! See [RIOT's documentation on using Rust] for a general introduction to Rust on RIOT, [this
//! crate's README file] on general concepts (such as the interaction between modules here, RIOT
//! modules and features), and the individual modules' documentation entries for details.
//!
//! [RIOT-OS]: https://www.riot-os.org/
//! [RIOT's documentation on using Rust]: https://doc.riot-os.org/using-rust.html
//! [this crate's README file]: https://github.com/RIOT-OS/rust-riot-wrappers

#![no_std]
// for eh_personality; only needed on native
#![cfg_attr(
    all(
        feature = "set_panic_handler",
        target_arch = "x86",
        not(panic = "abort")
    ),
    feature(lang_items)
)]
// Primarily for documentation, see feature docs
#![cfg_attr(feature = "actual_never_type", feature(never_type))]
#![cfg_attr(feature = "nightly_docs", feature(fundamental, doc_auto_cfg))]

/// riot-sys is re-exported here as it is necessary in some places when using it to get values (eg.
/// in [error::NumericError::from_constant]). It is also used in macros such as [static_command!].
///
/// ### Stability
///
/// By directly mapping RIOT APIs, this is more volatile than the rest of riot-wrappers. Use this
/// only where necessary to utilize riot-wrappers APIs.
pub use riot_sys;

/// Re-exporting the cstr macro module because our macros in [shell] use it.
pub use cstr;

pub mod error;

mod helpers;
mod never;
use never::Never;

/// The identifier of the RIOT board the program is being built for (`RIOT_BOARD` in C).
#[doc(alias = "RIOT_BOARD")]
pub const BOARD: &'static str = {
    let b = riot_sys::RIOT_BOARD;
    let Ok(b) = core::ffi::CStr::from_bytes_with_nul(b) else {
        // Could be `.expect()`, but that's not const yet
        // Workaround-For: https://github.com/rust-lang/rust/issues/67441
        panic!("Board names are null-terminated C strings");
    };
    let Ok(b) = b.to_str() else {
        panic!("Board names should be ASCII")
    };
    b
};

/// Name of the RIOT board that is being used
#[deprecated(note = "Access BOARD instead")]
pub const fn board() -> &'static str {
    BOARD
}

/// Cast pointers around before passing them in to functions; this is sometimes needed when a
/// struct is used from bindgen (`riot_sys::*`) but passed to a C2Rust function that uses its own
/// definition (`riot_sys::inline::*`).
///
/// Ideally this'd use what comes out of safe transmutation to statically show castability (or not
/// be needed due to better collaboration between C2Rust and bindgen), but until that's a thing,
/// checking for sizes is the least we can do.
///
/// TBD: Make this into a compile time failure (first attempts failed due to "use of generic
/// parameter from outer function" errors). Anyhow, if the check passes, the function essentially
/// becomes a no-op.
#[inline]
fn inline_cast<A, B>(input: *const A) -> *const B {
    assert_eq!(core::mem::size_of::<A>(), core::mem::size_of::<B>());
    input as _
}

/// `*mut` analogon to [inline_cast]
#[inline]
fn inline_cast_mut<A, B>(input: *mut A) -> *mut B {
    assert_eq!(core::mem::size_of::<A>(), core::mem::size_of::<B>());
    input as _
}

/// `&` analogon to [inline_cast]
#[inline]
#[allow(unused)]
unsafe fn inline_cast_ref<A, B>(input: &A) -> &B {
    assert_eq!(core::mem::size_of::<A>(), core::mem::size_of::<B>());
    core::mem::transmute(input)
}

/// `&mut` analogon to [inline_cast]
#[inline]
#[allow(unused)]
unsafe fn inline_cast_ref_mut<A, B>(input: &mut A) -> &mut B {
    assert_eq!(core::mem::size_of::<A>(), core::mem::size_of::<B>());
    core::mem::transmute(input)
}

#[cfg(riot_module_saul)]
pub mod saul;
#[cfg(riot_module_shell)]
pub mod shell;
pub mod stdio;
pub mod thread;
// internally cfg-gated as it has a no-op implementation
#[cfg(riot_module_gcoap)]
pub mod gcoap;
#[cfg(riot_module_gnrc)]
pub mod gnrc;
// Note that this can also exist without gnrc
#[cfg(riot_module_gnrc_pktbuf)]
pub mod gnrc_pktbuf;
#[cfg(riot_module_gnrc)]
pub mod gnrc_util;
#[cfg(riot_module_periph_i2c)]
pub mod i2c;
#[cfg(riot_module_core_msg)]
pub mod msg;
#[cfg(riot_module_random)]
pub mod random;

#[cfg(riot_module_periph_spi)]
pub mod spi;

#[cfg(riot_module_periph_adc)]
pub mod adc;

#[cfg(riot_module_periph_dac)]
pub mod dac;

#[cfg(riot_module_ztimer)]
pub mod ztimer;

pub mod mutex;
#[cfg(riot_module_pthread)]
pub mod rwlock;

#[cfg(feature = "set_panic_handler")]
mod panic;

#[cfg(riot_module_gcoap)]
pub mod coap_handler;
#[cfg(riot_module_gcoap)]
pub mod coap_message;

#[cfg(riot_module_sock)]
pub mod socket;
#[cfg(all(riot_module_sock_udp, feature = "with_embedded_nal"))]
pub mod socket_embedded_nal;
#[cfg(all(
    riot_module_sock_udp,
    riot_module_sock_aux_local,
    feature = "with_embedded_nal_async"
))]
pub mod socket_embedded_nal_async_udp;
#[cfg(all(riot_module_sock_tcp, feature = "with_embedded_nal"))]
pub mod socket_embedded_nal_tcp;

#[cfg(riot_module_periph_gpio)]
pub mod gpio;

#[cfg(riot_module_bluetil_ad)]
pub mod bluetil;

pub mod nimble {
    #[cfg(riot_module_nimble_host)]
    pub mod uuid;
}

#[cfg(riot_module_ws281x)]
pub mod ws281x;

#[cfg(riot_module_microbit)]
pub mod microbit;

#[cfg(riot_module_vfs)]
pub mod vfs;

mod impl_critical_section;
pub mod interrupt;
#[path = "main_module.rs"]
pub mod main;

pub mod led;

#[cfg(riot_module_auto_init)]
pub mod auto_init;

mod async_helpers;