1use std::error::Error as StdError;
2use std::time::Duration;
3
4use crate::{Error, Handle, IntoResult, ffi};
5
6pub(crate) type Callback = Box<
7 dyn FnMut(&mut TimerHandle) -> Result<(), Box<dyn StdError>> + 'static,
8>;
9
10pub struct TimerHandle {
15 handle: Handle<ffi::uv_timer_t, Callback>,
16}
17
18impl TimerHandle {
19 fn new() -> Result<Self, Error> {
20 let handle = Handle::new(|uv_loop, handle| unsafe {
21 ffi::uv_timer_init(uv_loop, handle.as_mut_ptr())
22 })?;
23
24 Ok(Self { handle })
25 }
26
27 pub fn start<Cb, R>(
32 timeout: Duration,
33 repeat: Duration,
34 mut callback: Cb,
35 ) -> Result<Self, Error>
36 where
37 Cb: FnMut(&mut Self) -> R + 'static,
38 R: IntoResult<()>,
39 R::Error: StdError + 'static,
40 {
41 let mut timer = Self::new()?;
42
43 let callback: Callback = Box::new(move |timer| {
44 callback(timer)
46 .into_result()
47 .map_err(|err| Box::new(err) as Box<dyn StdError>)
48 });
49
50 unsafe { timer.handle.set_data(callback) };
51
52 let retv = unsafe {
53 ffi::uv_timer_start(
54 timer.handle.as_mut_ptr(),
55 Some(timer_cb as _),
56 timeout.as_millis() as u64,
57 repeat.as_millis() as u64,
58 )
59 };
60
61 if retv < 0 {
62 return Err(Error::TimerStart);
63 }
64
65 Ok(timer)
66 }
67
68 pub fn once<Cb, R>(timeout: Duration, callback: Cb) -> Result<Self, Error>
71 where
72 Cb: FnOnce() -> R + 'static,
73 R: IntoResult<()>,
74 R::Error: StdError + 'static,
75 {
76 let mut callback = Some(callback);
77
78 Self::start(timeout, Duration::from_millis(0), move |timer| {
79 let res = callback.take().unwrap()();
80 timer.stop().unwrap();
81 res
82 })
83 }
84
85 pub fn stop(&mut self) -> Result<(), Error> {
87 let retv = unsafe { ffi::uv_timer_stop(self.handle.as_mut_ptr()) };
88
89 if retv < 0 {
90 return Err(Error::TimerStop);
91 }
92
93 Ok(())
94 }
95}
96
97extern "C" fn timer_cb(ptr: *mut ffi::uv_timer_t) {
98 let handle: Handle<_, Callback> = unsafe { Handle::from_raw(ptr) };
99
100 let callback = unsafe { handle.get_data() };
101
102 if !callback.is_null() {
103 let mut handle = TimerHandle { handle };
104 let callback = unsafe { &mut *callback };
105
106 if let Err(_err) = callback(&mut handle) {
107 }
109 }
110}