1#![no_std]
6#![doc(html_root_url = "https://docs.rs/pebble-sys/0.0.1")]
7#![feature(extern_types)]
8#![warn(clippy::pedantic)]
9#![allow(clippy::match_bool)]
10#![allow(clippy::module_name_repetitions)]
12
13use core::panic::PanicInfo;
14use foundation::logging::app_log;
15use standard_c::memory::c_str;
16
17pub mod prelude {
18 pub use super::standard_c::prelude::*;
19}
20
21#[panic_handler]
22fn panic(_info: &PanicInfo) -> ! {
23 unsafe {
24 let panic = &*("### PANIC ###\0" as *const str as *const _ as *const c_str);
25 let todo = &*("TODO: Output trace somehow.\0" as *const str as *const _ as *const c_str);
26 app_log(1, panic, -1, todo);
27 }
28 loop {}
29}
30
31extern "C" {
32 type ExternData;
34}
35
36pub mod foundation {
37 pub mod app {
38 extern "C" {
39 pub fn app_event_loop();
40 }
41 }
42
43 pub mod logging {
44 use crate::standard_c::memory::{c_str, int};
45
46 extern "C" {
49 pub fn app_log(
50 log_level: u8,
51 src_filename: &c_str,
52 src_line_number: int,
53 fmt: &c_str,
54 ...
55 );
56 }
57 }
58
59 pub mod resources {
60 use crate::standard_c::memory::void;
61
62 #[derive(Copy, Clone)]
63 #[repr(transparent)]
64 pub struct ResHandle(*const void);
65
66 extern "C" {
67 pub fn resource_get_handle(resource_id: u32) -> ResHandle;
68 pub fn resource_size(h: ResHandle) -> usize;
69 pub fn resource_load(h: ResHandle, buffer: *mut u8, max_length: usize) -> usize;
70 pub fn resource_load_byte_range(
71 h: ResHandle,
72 start_offset: u32,
73 buffer: *mut u8,
74 num_bytes: usize,
75 ) -> usize;
76 }
77 }
78}
79
80pub mod graphics {
81 pub mod graphics_types {
82 #[repr(C)]
83 pub struct GPoint {
84 pub x: i16,
85 pub y: i16,
86 }
87
88 #[repr(C)]
89 pub struct GRect {
90 pub origin: GPoint,
91 pub size: GSize,
92 }
93
94 #[repr(C)]
95 pub struct GSize {
96 pub w: i16,
97 pub h: i16,
98 }
99
100 #[repr(C)]
101 pub union GColor8 {
102 pub argb: u8,
103 }
104
105 pub type GColor = GColor8;
106
107 extern "C" {
108 pub type GBitmap;
109 pub type GBitmapSequence;
110 pub type GContext;
111 }
112
113 pub mod color_definitions {
114 use super::GColor8;
115
116 macro_rules! colors {
117 ($name:ident = $value:literal $(, $further_name:ident = $further_value:literal)*$(,)?) => {
118 pub const $name: GColor8 = GColor8 {
119 argb: $value,
120 };
121 $(colors!($further_name = $further_value);)*
122 };
123 }
124
125 colors! {
126 BLUE_MOON = 0b_11_00_01_11,
127 MELON = 0b_11_11_10_10,
128 YELLOW = 0b_11_11_11_00,
129 }
130 }
131 }
132}
133
134pub mod user_interface {
135 pub mod clicks {
136 use crate::standard_c::memory::void;
137
138 #[repr(C)] pub enum ButtonId {
140 _A, }
142
143 #[repr(transparent)]
144 pub struct ClickRecognizerRef(*mut void);
145 pub type ClickHandler = extern "C" fn(recognizer: ClickRecognizerRef, context: *mut void);
146 pub type ClickConfigProvider = extern "C" fn(context: *mut void);
147 }
148
149 pub mod layers {
150 use super::window::Window;
151 use crate::{
152 graphics::graphics_types::{GContext, GPoint, GRect},
153 standard_c::memory::void,
154 };
155 use core::ptr::NonNull;
156
157 pub type LayerUpdateProc = extern "C" fn(layer: NonNull<Layer>, NonNull<GContext>);
158
159 extern "C" {
160 pub type Layer;
161
162 pub fn layer_create(frame: GRect) -> *mut Layer;
163 pub fn layer_create_with_data(frame: GRect, data_size: usize) -> *mut Layer;
164 pub fn layer_destroy(layer: &'static mut Layer);
165 pub fn layer_mark_dirty(layer: NonNull<Layer>);
166 pub fn layer_set_update_proc(
167 layer: NonNull<Layer>,
168 update_proc: Option<LayerUpdateProc>, );
170 pub fn layer_set_frame(layer: NonNull<Layer>, frame: GRect);
171 pub fn layer_get_frame(layer: NonNull<Layer>) -> GRect;
172 pub fn layer_set_bounds(layer: NonNull<Layer>, bounds: GRect);
173 pub fn layer_get_bounds(layer: NonNull<Layer>) -> GRect;
174 pub fn layer_convert_point_to_screen(layer: NonNull<Layer>, point: GPoint) -> GPoint;
175 pub fn layer_convert_rect_to_screen(layer: NonNull<Layer>, rect: GRect) -> GRect;
176 pub fn layer_get_window(layer: NonNull<Layer>) -> *mut Window;
177 pub fn layer_remove_from_parent(child: NonNull<Layer>);
178 pub fn layer_remove_child_layers(parent: NonNull<Layer>);
179 pub fn layer_add_child(parent: NonNull<Layer>, child: NonNull<Layer>);
180 pub fn layer_insert_below_sibling(
181 layer_to_insert: NonNull<Layer>,
182 below_sibling_layer: NonNull<Layer>,
183 );
184 pub fn layer_insert_above_sibling(
185 layer_to_insert: NonNull<Layer>,
186 above_sibling_layer: NonNull<Layer>,
187 );
188 pub fn layer_set_hidden(layer: NonNull<Layer>, hidden: bool);
189 pub fn layer_get_hidden(layer: NonNull<Layer>) -> bool;
190 pub fn layer_set_clips(layer: NonNull<Layer>, clips: bool);
191 pub fn layer_get_clips(layer: NonNull<Layer>) -> bool;
192 pub fn layer_get_data(layer: NonNull<Layer>) -> NonNull<void>;
193
194 }
196 }
197
198 pub mod vibes {
199 use core::marker::PhantomData;
200
201 #[repr(C)]
202 pub struct VibePattern<'a> {
203 pub durations: *const u32,
206 pub num_segments: u32,
208 pub phantom: PhantomData<&'a u32>,
209 }
210
211 extern "C" {
212 pub fn vibes_cancel();
213 pub fn vibes_short_pulse();
214 pub fn vibes_long_pulse();
215 pub fn vibes_double_pulse();
216 pub fn vibes_enqueue_custom_pattern(pattern: VibePattern);
217 }
218 }
219
220 pub mod window {
221 use super::{
222 clicks::{ButtonId, ClickConfigProvider, ClickHandler},
223 layers::Layer,
224 };
225 use crate::{graphics::graphics_types::GColor8, standard_c::memory::void};
226 use core::ptr::NonNull;
227
228 #[repr(C)]
229 pub struct WindowHandlers {
230 pub load: Option<WindowHandler>,
231 pub appear: Option<WindowHandler>,
232 pub disappear: Option<WindowHandler>,
233 pub unload: Option<WindowHandler>,
234 }
235
236 pub type WindowHandler = extern "C" fn(window: &mut Window);
237
238 extern "C" {
239 pub type Window;
240
241 pub fn window_create() -> Option<&'static mut Window>;
242 pub fn window_destroy(window: &'static mut Window);
243 pub fn window_set_click_config_provider(
244 window: &mut Window,
245 click_config_provider: Option<ClickConfigProvider>,
246 );
247 pub fn window_set_click_config_provider_with_context(
248 window: &mut Window,
249 click_config_provider: Option<ClickConfigProvider>,
250 context: *mut void,
251 );
252 pub fn window_get_click_config_provider(window: &Window)
253 -> Option<ClickConfigProvider>;
254 pub fn window_get_click_config_context(window: &Window) -> *mut void;
255 pub fn window_set_window_handlers(window: &mut Window, handlers: WindowHandlers);
256
257 pub fn window_get_root_layer(window: &Window) -> &mut Layer;
259
260 pub fn window_set_background_color(window: &mut Window, background_color: GColor8);
261 pub fn window_is_loaded(window: &mut Window) -> bool;
262 pub fn window_set_user_data(window: &mut Window, data: *mut void);
263 pub fn window_get_user_data(window: &Window) -> *mut void;
264 pub fn window_single_click_subscribe(button_id: ButtonId, handler: ClickHandler);
265 pub fn window_single_repeating_click_subscribe(
266 button_id: ButtonId,
267 repeat_interval_ms: u16,
268 handler: ClickHandler,
269 );
270 pub fn window_multi_click_subscribe(
271 button_id: ButtonId,
272 min_clicks: u8,
273 max_clicks: u8,
274 timeout: u16,
275 last_click_only: bool,
276 handler: ClickHandler,
277 );
278 pub fn window_long_click_subscribe(
279 button_id: ButtonId,
280 delay_ms: u16,
281 down_handler: ClickHandler,
282 up_handler: ClickHandler,
283 );
284 pub fn window_raw_click_subscribe(
285 button_id: ButtonId,
286 down_handler: ClickHandler,
287 up_handler: ClickHandler,
288 context: Option<NonNull<void>>,
289 );
290 pub fn window_set_click_context(button_id: ButtonId, context: *mut void);
291 }
292
293 pub mod number_window {
294 use super::Window;
299 use crate::{
300 standard_c::memory::{c_str, void},
301 ExternData,
302 };
303 use core::{
304 marker::PhantomData,
305 ops::{Deref, DerefMut},
306 };
307
308 #[repr(C)]
310 pub struct NumberWindowCallbacks {
311 pub incremented: Option<NumberWindowCallback>,
313 pub decremented: Option<NumberWindowCallback>,
315 pub selected: Option<NumberWindowCallback>,
317 }
318
319 pub type NumberWindowCallback =
321 for<'a> extern "C" fn(number_window: &'a mut NumberWindow<'a>, context: &mut void);
322
323 #[repr(transparent)]
330 pub struct NumberWindow<'a>(PhantomData<&'a ()>, ExternData);
331
332 extern "C" {
333 pub fn number_window_create<'a>(
334 label: &'a c_str,
335 callbacks: NumberWindowCallbacks,
336 callback_context: &'static mut void,
337 ) -> Option<&'a mut NumberWindow<'a>>;
338
339 pub fn number_window_destroy(number_window: &'static mut NumberWindow);
340 pub fn number_window_set_label<'a>(
341 number_window: &mut NumberWindow<'a>,
342 label: &'a c_str,
343 );
344 pub fn number_window_set_max(number_window: &mut NumberWindow, max: i32);
345 pub fn number_window_set_min(number_window: &mut NumberWindow, min: i32);
346 pub fn number_window_set_value(number_window: &mut NumberWindow, value: i32);
347 pub fn number_window_set_step_size(number_window: &mut NumberWindow, step: i32);
348 pub fn number_window_get_value(number_window: &NumberWindow) -> i32;
349 pub fn number_window_get_window<'a>(
350 number_window: &'a NumberWindow<'a>,
351 ) -> &'a Window;
352 #[allow(clashing_extern_declarations)]
353 #[link_name = "number_window_get_window"]
354 pub fn number_window_get_window_mut<'a>(
355 number_window: &'a mut NumberWindow<'a>,
356 ) -> &'a mut Window;
357 }
358
359 impl<'a> Deref for NumberWindow<'a> {
360 type Target = Window;
361
362 fn deref(&self) -> &Self::Target {
363 unsafe { &*(self as *const _ as *const Self::Target) }
364 }
365 }
366
367 impl<'a> DerefMut for NumberWindow<'a> {
368 fn deref_mut(&mut self) -> &mut Self::Target {
369 unsafe { &mut *(self as *mut _ as *mut Self::Target) }
370 }
371 }
372 }
373 }
374
375 pub mod window_stack {
376 use super::window::Window;
377 use core::ptr::NonNull;
378
379 extern "C" {
380 pub fn window_stack_push(window: &'static mut Window, animated: bool);
381 pub fn window_stack_pop(animated: bool) -> Option<NonNull<Window>>;
382 pub fn window_stack_pop_all(animated: bool);
383 pub fn window_stack_remove(window: &mut Window, animated: bool) -> bool;
384 pub fn window_stack_get_top_window() -> Option<NonNull<Window>>;
385 pub fn window_stack_contains_window(window: &mut Window) -> bool;
386 }
387 }
388}
389
390pub mod standard_c {
391 pub mod prelude {
392 pub use super::memory::prelude::*;
393 }
394
395 pub mod memory {
396 #![allow(non_camel_case_types)]
397
398 use core::convert::TryFrom;
399
400 pub mod prelude {
401 pub use super::{
402 CastUncheckedExt, CastUncheckedMutExt, OptionCastUncheckedMutExt, UpcastExt,
403 UpcastMutExt,
404 };
405 }
406
407 pub type int = i32;
408
409 extern "C" {
410 pub type c_str;
411
412 pub type void;
419
420 pub fn malloc(size: usize) -> Option<&'static mut void>;
421 pub fn calloc(count: usize, size: usize) -> Option<&'static mut void>;
422 pub fn realloc(ptr: *mut void, size: usize) -> Option<&'static mut void>;
423 pub fn free(ptr: &'static mut void);
424 pub fn memcmp(ptr1: &void, ptr2: &void, n: usize) -> int;
425 pub fn memcpy(dest: &mut void, src: &void, n: usize) -> *mut void;
426 pub fn memmove(dest: *mut void, src: *const void, n: usize) -> *mut void;
427 pub fn memset(dest: &mut void, c: int, n: usize) -> *mut void;
428 }
429
430 impl<'a, T> From<&'a mut T> for &'a mut void {
431 fn from(src: &'a mut T) -> Self {
432 unsafe { &mut *(src as *mut _ as *mut void) }
433 }
434 }
435
436 impl<'a, T> From<&'a T> for &'a void {
437 fn from(src: &'a T) -> Self {
438 unsafe { &*(src as *const _ as *const void) }
439 }
440 }
441
442 pub trait CastUncheckedExt<'a> {
443 unsafe fn cast_unchecked<T>(self) -> &'a T;
449 }
450
451 pub trait CastUncheckedMutExt<'a> {
452 unsafe fn cast_unchecked_mut<T>(self) -> &'a mut T;
458 }
459
460 pub trait OptionCastUncheckedMutExt<'a> {
461 unsafe fn cast_unchecked_mut<T>(self) -> Option<&'a mut T>;
467 }
468
469 pub trait UpcastExt<'a> {
470 type Output;
471
472 fn upcast(self) -> Self::Output;
473 }
474
475 pub trait UpcastMutExt<'a> {
476 type Output;
477
478 fn upcast_mut(self) -> Self::Output;
479 }
480
481 impl<'a> CastUncheckedExt<'a> for &'a void {
482 unsafe fn cast_unchecked<T>(self) -> &'a T {
483 &*(self as *const _ as *const T)
484 }
485 }
486
487 impl<'a> CastUncheckedMutExt<'a> for &'a mut void {
488 unsafe fn cast_unchecked_mut<T>(self) -> &'a mut T {
489 &mut *(self as *mut _ as *mut T)
490 }
491 }
492
493 impl<'a> OptionCastUncheckedMutExt<'a> for Option<&'a mut void> {
494 unsafe fn cast_unchecked_mut<T>(self) -> Option<&'a mut T> {
495 self.map(|void_ref| &mut *(void_ref as *mut _ as *mut T))
496 }
497 }
498
499 impl<'a, T> UpcastMutExt<'a> for Option<&'a mut T> {
500 type Output = Option<&'a mut void>;
501
502 fn upcast_mut(self) -> Self::Output {
503 self.map(|t_ref| t_ref.into())
504 }
505 }
506
507 impl<'a, T> UpcastExt<'a> for &'a T {
508 type Output = &'a void;
509
510 fn upcast(self) -> Self::Output {
511 self.into()
512 }
513 }
514
515 impl<'a, T> UpcastMutExt<'a> for &'a mut T {
516 type Output = &'a mut void;
517
518 fn upcast_mut(self) -> Self::Output {
519 self.into()
520 }
521 }
522
523 impl c_str {
524 pub fn ref_from_str(text: &str) -> Result<&Self, ()> {
530 match text.ends_with('\0') {
531 true => Ok(unsafe { &*(text as *const _ as *const c_str) }),
532 false => Err(()),
533 }
534 }
535 }
536
537 impl<'a> TryFrom<&'a str> for &'a c_str {
538 type Error = ();
539
540 fn try_from(value: &'a str) -> Result<Self, Self::Error> {
541 match value.ends_with('\0') {
542 true => Ok(unsafe { &*(value as *const _ as *const c_str) }),
543 false => Err(()),
544 }
545 }
546 }
547 }
548}