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
use std::sync::atomic::{AtomicUsize, Ordering};
use yew::html::IntoPropValue;
use yew::AttrValue;

#[macro_export]
macro_rules! ouia {
    ($framework:literal, $component:literal) => {
        Ouia::with_full(concat!($framework, "/", $component))
    };
    ($component:literal) => {
        ouia!("PF5", $component)
    };
}

pub struct Ouia(OuiaComponentType);

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct OuiaComponentType(&'static str);

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct OuiaSafe(bool);

impl OuiaSafe {
    pub const TRUE: OuiaSafe = OuiaSafe(true);
    pub const FALSE: OuiaSafe = OuiaSafe(false);
}

impl From<bool> for OuiaSafe {
    fn from(value: bool) -> Self {
        Self(value)
    }
}

impl IntoPropValue<OuiaSafe> for bool {
    fn into_prop_value(self) -> OuiaSafe {
        OuiaSafe(self)
    }
}

impl IntoPropValue<AttrValue> for OuiaSafe {
    fn into_prop_value(self) -> AttrValue {
        match self.0 {
            true => AttrValue::Static("true"),
            false => AttrValue::Static("false"),
        }
    }
}

impl IntoPropValue<Option<AttrValue>> for OuiaSafe {
    fn into_prop_value(self) -> Option<AttrValue> {
        Some(self.into_prop_value())
    }
}

impl IntoPropValue<AttrValue> for OuiaComponentType {
    fn into_prop_value(self) -> AttrValue {
        AttrValue::Static(self.0)
    }
}

impl IntoPropValue<Option<AttrValue>> for OuiaComponentType {
    fn into_prop_value(self) -> Option<AttrValue> {
        Some(self.into_prop_value())
    }
}

impl Ouia {
    pub const fn with_full(full_component_name: &'static str) -> Self {
        Self(OuiaComponentType(full_component_name))
    }

    pub fn generated_id(&self) -> String {
        let count = counter();
        format!("OUIA-Generated-{count}")
    }

    pub const fn component_type(&self) -> OuiaComponentType {
        self.0
    }
}

fn counter() -> usize {
    static COUNT: AtomicUsize = AtomicUsize::new(0);
    COUNT.fetch_add(1, Ordering::Relaxed)
}