spair 0.0.9

A framework for single-page application in Rust
Documentation
enum AttributeValue {
    EventListener(Option<Box<dyn crate::events::Listener>>),
    String(String),
    SelectedValue(Option<String>),
    Bool(bool),
    I32(i32),
    U32(u32),
    F64(f64),
}

impl Clone for AttributeValue {
    fn clone(&self) -> Self {
        match self {
            Self::EventListener(_) => Self::EventListener(None),
            Self::String(v) => Self::String(v.clone()),
            Self::SelectedValue(v) => Self::SelectedValue(v.clone()),
            Self::Bool(v) => Self::Bool(*v),
            Self::I32(v) => Self::I32(*v),
            Self::U32(v) => Self::U32(*v),
            Self::F64(v) => Self::F64(*v),
        }
    }
}

impl std::fmt::Debug for AttributeValue {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
        match self {
            Self::EventListener(_) => f.write_str("EventListener(...)"),
            Self::String(value) => value.fmt(f),
            Self::SelectedValue(value) => value.fmt(f),
            Self::Bool(value) => value.fmt(f),
            Self::I32(value) => value.fmt(f),
            Self::U32(value) => value.fmt(f),
            Self::F64(value) => value.fmt(f),
        }
    }
}

#[derive(Default, Debug, Clone)]
pub struct AttributeValueList(Vec<AttributeValue>);

impl AttributeValueList {
    pub fn store_listener(&mut self, index: usize, listener: Box<dyn crate::events::Listener>) {
        if index < self.0.len() {
            self.0[index] = AttributeValue::EventListener(Some(listener));
        } else {
            self.0.push(AttributeValue::EventListener(Some(listener)));
        }
    }

    pub fn check_bool_attribute(&mut self, index: usize, value: bool) -> bool {
        match self.0.get_mut(index) {
            None => {
                self.0.push(AttributeValue::Bool(value));
                true
            }
            Some(a) => match a {
                AttributeValue::Bool(old_value) if value == *old_value => false,
                AttributeValue::Bool(old_value) => {
                    *old_value = value;
                    true
                }
                _ => panic!("Spair's internal error, expected an AttributeValue::Bool?"),
            },
        }
    }

    pub fn check_i32_attribute(&mut self, index: usize, value: i32) -> bool {
        match self.0.get_mut(index) {
            None => {
                self.0.push(AttributeValue::I32(value));
                true
            }
            Some(a) => match a {
                AttributeValue::I32(old_value) if value == *old_value => false,
                AttributeValue::I32(old_value) => {
                    *old_value = value;
                    true
                }
                _ => panic!("Spair's internal error, expected an AttributeValue::I32?"),
            },
        }
    }

    pub fn check_u32_attribute(&mut self, index: usize, value: u32) -> bool {
        match self.0.get_mut(index) {
            None => {
                self.0.push(AttributeValue::U32(value));
                true
            }
            Some(a) => match a {
                AttributeValue::U32(old_value) if value == *old_value => false,
                AttributeValue::U32(old_value) => {
                    *old_value = value;
                    true
                }
                _ => panic!("Spair's internal error, expected an AttributeValue::U32?"),
            },
        }
    }

    pub fn check_f64_attribute(&mut self, index: usize, value: f64) -> bool {
        match self.0.get_mut(index) {
            None => {
                self.0.push(AttributeValue::F64(value));
                true
            }
            Some(a) => match a {
                AttributeValue::F64(old_value)
                    if (value - *old_value).abs() < std::f64::EPSILON =>
                {
                    false
                }
                AttributeValue::F64(old_value) => {
                    *old_value = value;
                    true
                }
                _ => panic!("Spair's internal error, expected an AttributeValue::F64?"),
            },
        }
    }

    pub fn check_str_attribute(&mut self, index: usize, value: &str) -> bool {
        match self.0.get_mut(index) {
            None => {
                self.0.push(AttributeValue::String(value.to_string()));
                true
            }
            Some(a) => match a {
                AttributeValue::String(old_value) if value == *old_value => false,
                AttributeValue::String(old_value) => {
                    *old_value = value.to_string();
                    true
                }
                _ => panic!("Spair's internal error, expected an AttributeValue::String?"),
            },
        }
    }

    pub fn check_optional_str_attribute(&mut self, index: usize, value: Option<&str>) -> bool {
        match self.0.get_mut(index) {
            None => {
                self.0.push(AttributeValue::SelectedValue(
                    value.map(ToString::to_string),
                ));
                true
            }
            Some(a) => match a {
                AttributeValue::SelectedValue(old_value) if value == old_value.as_deref() => false,
                AttributeValue::SelectedValue(old_value) => {
                    *old_value = value.map(ToString::to_string);
                    true
                }
                _ => panic!("Spair's internal error, expected an AttributeValue::SelectedValue?"),
            },
        }
    }

    pub fn check_str_attribute_and_return_old_value(
        &mut self,
        index: usize,
        value: &str,
    ) -> (bool, Option<String>) {
        match self.0.get_mut(index) {
            None => {
                self.0.push(AttributeValue::String(value.to_string()));
                (true, None)
            }
            Some(a) => match a {
                AttributeValue::String(old_value) if value == *old_value => (false, None),
                AttributeValue::String(old_value) => {
                    let mut value = value.to_string();
                    std::mem::swap(&mut value, old_value);
                    (true, Some(value))
                }
                _ => panic!("Spair's internal error, expected an AttributeValue::String"),
            },
        }
    }
}