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
use super::{message_channel::MessageChannelTickerFactory, timers::*};
use crate::ticker::*;
use crate::{NamedTicker, TickerFactory};
use wasm_bindgen::JsValue;
use wasm_bindgen::__rt::Lazy;

pub(crate) enum SelectedTicker {
    MessageChannel,
    Immediate,
    Timeout,
    AnimationFrame,
    None,
}

pub(crate) static SELECTED_TICKER: Lazy<SelectedTicker> = Lazy::new(|| {
    if MessageChannelTicker::check() {
        SelectedTicker::MessageChannel
    } else if ImmediateTicker::check() {
        SelectedTicker::Immediate
    } else if TimeoutTicker::check() {
        SelectedTicker::Timeout
    } else if AnimationFrameTicker::check() {
        SelectedTicker::AnimationFrame
    } else {
        SelectedTicker::None
    }
});

/// Automatically construct an available [Ticker](crate::Ticker)
/// wrapped by [AutoTicker].
///
/// Detecting order:
/// - [MessageChannelTicker]
/// - [ImmediateTicker]
/// - [TimeoutTicker]
/// - [AnimationFrameTicker]
#[derive(Clone, Copy)]
pub struct AutoTickerFactory;
impl TickerFactory for AutoTickerFactory {
    type Output = AutoTicker;

    fn new(task: impl FnMut() + 'static) -> Result<Self::Output, JsValue> {
        match *SELECTED_TICKER {
            SelectedTicker::None => Err(JsValue::from_str("No available implementation detected")),
            SelectedTicker::MessageChannel => Result::map(
                MessageChannelTickerFactory::new(task),
                AutoTicker::MessageChannel,
            ),
            SelectedTicker::Immediate => {
                Result::map(ImmediateTickerFactory::new(task), AutoTicker::Immediate)
            }
            SelectedTicker::Timeout => {
                Result::map(TimeoutTickerFactory::new(task), AutoTicker::Timeout)
            }
            SelectedTicker::AnimationFrame => Result::map(
                AnimationFrameTickerFactory::new(task),
                AutoTicker::AnimationFrame,
            ),
        }
    }
}