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
use crate::dart_handle::{DartHandle, UnverifiedDartHandle};
use crate::dart_types::DartType;
use crate::dart_unwrap;
use std::cell::Cell;
use std::ops::Deref;
use std::thread::LocalKey;

#[derive(Clone, Debug)]
pub struct Boolean {
    handle: UnverifiedDartHandle,
    value: Cell<Option<bool>>,
}

impl Boolean {
    pub fn new(value: bool) -> Self {
        let handle = UnverifiedDartHandle::new_bool(value);
        Self {
            handle,
            value: Cell::new(Some(value)),
        }
    }

    #[inline]
    pub fn value(&self) -> bool {
        if let Some(x) = self.value.get() {
            x
        } else {
            let value = dart_unwrap!(self.handle.get_bool());
            self.value.set(Some(value));
            value
        }
    }
}

impl std::ops::Not for Boolean {
    type Output = bool;
    fn not(self) -> bool {
        !self.value()
    }
}

impl From<bool> for Boolean {
    fn from(x: bool) -> Self {
        Self::new(x)
    }
}

thread_local! {
    #[allow(non_upper_case_globals)]
    pub static BoolType: UnverifiedDartHandle = {
        let b = UnverifiedDartHandle::const_false();
        b.get_instance_type().unwrap()
    };
}

impl DartType for Boolean {
    const THIS: &'static LocalKey<UnverifiedDartHandle> = &BoolType;
}

impl Deref for Boolean {
    type Target = UnverifiedDartHandle;
    fn deref(&self) -> &Self::Target {
        &self.handle
    }
}

unsafe impl DartHandle for Boolean {
    fn handle(&self) -> dart_sys::Dart_Handle {
        self.handle.handle()
    }
    fn safe_handle(&self) -> UnverifiedDartHandle {
        self.handle
    }
    fn from_handle(handle: UnverifiedDartHandle) -> Result<Self, UnverifiedDartHandle> {
        if handle.is_boolean() {
            Ok(Self {
                handle,
                value: Cell::new(None),
            })
        } else {
            Err(handle)
        }
    }
}