mod kind;
mod spec;
#[cfg(test)]
mod tests;
mod value;
pub use kind::{Color, PropertyValueKind, Rectangle, Scalar, Shadow, Size, Transform, Vector2};
pub use spec::{PropertySpec, RawPropertySpec};
pub use value::{PropertyValue, TransformValue};
pub const OPACITY: PropertySpec<Scalar> =
PropertySpec::new(PropertyKey::new("aura", "opacity"), 10);
pub const TRANSLATE: PropertySpec<Vector2> =
PropertySpec::new(PropertyKey::new("aura", "translate"), 19);
pub const SCALE: PropertySpec<Scalar> = PropertySpec::new(PropertyKey::new("aura", "scale"), 20);
pub const WIDTH: PropertySpec<Scalar> = PropertySpec::new(PropertyKey::new("aura", "width"), 30);
pub const HEIGHT: PropertySpec<Scalar> = PropertySpec::new(PropertyKey::new("aura", "height"), 31);
pub const PADDING: PropertySpec<Scalar> =
PropertySpec::new(PropertyKey::new("aura", "padding"), 40);
pub const RADIUS: PropertySpec<Scalar> = PropertySpec::new(PropertyKey::new("aura", "radius"), 50);
pub const BACKGROUND: PropertySpec<Color> =
PropertySpec::new(PropertyKey::new("aura", "background"), 60);
pub const BORDER_COLOR: PropertySpec<Color> =
PropertySpec::new(PropertyKey::new("aura", "border-color"), 70);
pub const TEXT_COLOR: PropertySpec<Color> =
PropertySpec::new(PropertyKey::new("aura", "text-color"), 80);
pub const SHADOW: PropertySpec<Shadow> = PropertySpec::new(PropertyKey::new("aura", "shadow"), 90);
#[derive(Debug, Clone, PartialEq)]
pub struct PropertySnapshot {
entries: Vec<PropertyEntry>,
}
impl<K: PropertyValueKind> From<Vec<(PropertySpec<K>, K::Inner)>> for PropertySnapshot {
fn from(value: Vec<(PropertySpec<K>, K::Inner)>) -> Self {
Self {
entries: value
.into_iter()
.map(|(spec, value)| PropertyEntry::new(spec, value))
.collect(),
}
}
}
impl<K: PropertyValueKind> From<(PropertySpec<K>, K::Inner)> for PropertySnapshot {
fn from(value: (PropertySpec<K>, K::Inner)) -> Self {
Self {
entries: vec![PropertyEntry::new(value.0, value.1)],
}
}
}
impl From<Vec<PropertyEntry>> for PropertySnapshot {
fn from(entries: Vec<PropertyEntry>) -> Self {
Self { entries }
}
}
impl PropertySnapshot {
#[must_use]
pub const fn new() -> Self {
Self {
entries: Vec::new(),
}
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.entries.is_empty()
}
#[must_use]
pub fn entries(&self) -> &[PropertyEntry] {
&self.entries
}
pub(crate) fn sort_by_composition_key(&mut self) {
self.entries
.sort_by_key(|entry| entry.spec.composition_order());
}
pub fn merge(&mut self, other: Self) {
self.merge_unsorted(other);
self.sort_by_composition_key();
}
#[must_use]
pub fn find_property(&self, property: &RawPropertySpec) -> Option<&PropertyEntry> {
self.entries.iter().find(|entry| entry.spec == *property)
}
pub(crate) fn push(&mut self, entry: PropertyEntry) {
self.entries.push(entry);
}
pub(crate) fn with_capacity(capacity: usize) -> Self {
Self {
entries: Vec::with_capacity(capacity),
}
}
pub(crate) fn merge_unsorted(&mut self, other: Self) {
other.entries.into_iter().for_each(|snapshot| {
if let Some(entry) = self.find_property_mut(&snapshot.spec) {
entry.value = snapshot.value;
} else {
self.entries.push(snapshot);
}
});
}
fn find_property_mut(&mut self, property: &RawPropertySpec) -> Option<&mut PropertyEntry> {
self.entries
.iter_mut()
.find(|entry| entry.spec == *property)
}
}
impl Default for PropertySnapshot {
fn default() -> Self {
Self::new()
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct PropertyEntry {
spec: RawPropertySpec,
value: PropertyValue,
}
impl PropertyEntry {
#[must_use]
pub fn new<K: PropertyValueKind>(spec: PropertySpec<K>, value: K::Inner) -> Self {
Self {
spec: spec.raw(),
value: K::wrap(value),
}
}
#[must_use]
pub fn spec(&self) -> &RawPropertySpec {
&self.spec
}
#[must_use]
pub fn value(&self) -> &PropertyValue {
&self.value
}
pub(crate) fn new_unchecked(spec: RawPropertySpec, value: PropertyValue) -> Self {
Self { spec, value }
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PropertyKey {
namespace: &'static str,
name: &'static str,
}
impl PropertyKey {
#[must_use]
pub const fn new(namespace: &'static str, name: &'static str) -> Self {
Self { namespace, name }
}
#[must_use]
pub const fn namespace(&self) -> &'static str {
self.namespace
}
#[must_use]
pub const fn name(&self) -> &'static str {
self.name
}
}