intuicio_frontend_simpleton/library/
event.rs

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
use crate::{Array, Function, Reference};
use intuicio_core::{context::Context, registry::Registry, IntuicioStruct};
use intuicio_derive::{intuicio_method, intuicio_methods, IntuicioStruct};

use super::{closure::Closure, promise::Promise};

#[derive(IntuicioStruct, Default)]
#[intuicio(name = "Event", module_name = "event", override_send = false)]
pub struct Event {
    #[intuicio(ignore)]
    pub persistent: Array,
    #[intuicio(ignore)]
    pub oneshot: Array,
}

#[intuicio_methods(module_name = "event")]
impl Event {
    #[intuicio_method()]
    pub fn bind(mut event: Reference, target: Reference) -> Reference {
        let mut event = event.write::<Event>().unwrap();
        if target.read::<Promise>().is_some() {
            event.oneshot.push(target);
        } else {
            event.persistent.push(target);
        }
        Reference::null()
    }

    #[intuicio_method()]
    pub fn bind_once(mut event: Reference, target: Reference) -> Reference {
        let mut event = event.write::<Event>().unwrap();
        event.oneshot.push(target);
        Reference::null()
    }

    #[intuicio_method()]
    pub fn unbind(mut event: Reference, target: Reference) -> Reference {
        let mut event = event.write::<Event>().unwrap();
        if target.is_null() {
            event.persistent.clear();
            event.oneshot.clear();
        } else {
            while let Some(index) = event
                .persistent
                .iter()
                .position(|item| crate::library::reflect::are_same_impl(item, &target))
            {
                event.persistent.swap_remove(index);
            }
            while let Some(index) = event
                .oneshot
                .iter()
                .position(|item| crate::library::reflect::are_same_impl(item, &target))
            {
                event.oneshot.swap_remove(index);
            }
        }
        Reference::null()
    }

    fn dispatch_impl(
        context: &mut Context,
        registry: &Registry,
        target: Reference,
        arguments: Reference,
    ) {
        if target.read::<Function>().is_some() {
            crate::library::reflect::call(context, registry, target, arguments);
        } else if target.read::<Closure>().is_some() {
            Closure::call(context, registry, target, arguments);
        } else if target.read::<Promise>().is_some() {
            Promise::resolve(context, registry, target, arguments);
        }
    }

    #[intuicio_method(use_context, use_registry)]
    pub fn dispatch(
        context: &mut Context,
        registry: &Registry,
        mut event: Reference,
        arguments: Reference,
    ) -> Reference {
        assert!(arguments.read::<Array>().is_some());
        let mut event = event.write::<Event>().unwrap();
        for target in &event.persistent {
            Self::dispatch_impl(context, registry, target.clone(), arguments.clone())
        }
        for target in &event.oneshot {
            Self::dispatch_impl(context, registry, target.clone(), arguments.clone())
        }
        event.oneshot.clear();
        Reference::null()
    }
}

pub fn install(registry: &mut Registry) {
    registry.add_type(Event::define_struct(registry));
    registry.add_function(Event::bind__define_function(registry));
    registry.add_function(Event::bind_once__define_function(registry));
    registry.add_function(Event::unbind__define_function(registry));
    registry.add_function(Event::dispatch__define_function(registry));
}