1use std::sync::atomic::{AtomicUsize, Ordering};
5
6use feather_ui::lua::LuaApp;
7use mlua::{FromLua, Lua, UserData, UserDataFields};
8
9const LAYOUT: &[u8] = include_bytes!("./clock.lua");
10
11#[derive(Debug)]
12struct TimeState {
13 count: AtomicUsize,
14}
15
16impl PartialEq for TimeState {
17 fn eq(&self, other: &Self) -> bool {
18 self.count.load(Ordering::Relaxed) == other.count.load(Ordering::Relaxed)
19 }
20}
21
22impl Clone for TimeState {
23 fn clone(&self) -> Self {
24 Self {
25 count: self.count.load(Ordering::Relaxed).into(),
26 }
27 }
28}
29
30impl UserData for TimeState {
31 fn add_fields<F: UserDataFields<Self>>(f: &mut F) {
32 f.add_field_method_get("time_hour", |_, s| {
33 s.count.fetch_add(1, Ordering::Relaxed);
34 let day = std::time::SystemTime::now()
35 .duration_since(std::time::UNIX_EPOCH)
36 .unwrap()
37 .as_secs()
38 % (24 * 60 * 60);
39 Ok(day / (60 * 60))
40 });
41 f.add_field_method_get("time_min", |_, s| {
42 s.count.fetch_add(1, Ordering::Relaxed);
43 let day = std::time::SystemTime::now()
44 .duration_since(std::time::UNIX_EPOCH)
45 .unwrap()
46 .as_secs()
47 % (24 * 60 * 60);
48 Ok((day / 60) % 60)
49 });
50 f.add_field_method_get("time_sec", |_, s| {
51 s.count.fetch_add(1, Ordering::Relaxed);
52 let day = std::time::SystemTime::now()
53 .duration_since(std::time::UNIX_EPOCH)
54 .unwrap()
55 .as_secs()
56 % (24 * 60 * 60);
57 Ok(day % 60)
58 });
59 }
60}
61
62impl FromLua for TimeState {
63 #[inline]
64 fn from_lua(value: ::mlua::Value, _: &::mlua::Lua) -> ::mlua::Result<Self> {
65 match value {
66 ::mlua::Value::UserData(ud) => Ok(ud.borrow::<Self>()?.clone()),
67 _ => Err(::mlua::Error::FromLuaConversionError {
68 from: value.type_name(),
69 to: stringify!(TimeState).to_string(),
70 message: None,
71 }),
72 }
73 }
74}
75
76fn main() {
77 let lua = Lua::new();
78
79 let (mut app, event_loop) =
80 LuaApp::<TimeState>::new::<()>(&lua, TimeState { count: 0.into() }, Vec::new(), LAYOUT)
81 .unwrap();
82
83 event_loop.run_app(&mut app).unwrap();
84}