use nameth::nameth;
use self::diagnostics::trace;
use super::XAttribute;
use super::builder::AttributeValueDiff;
use super::builder::aggregate_attribute;
use super::id::XAttributeId;
use super::name::XAttributeName;
use super::value::XAttributeValue;
use crate::element::template::LiveElement;
use crate::prelude::diagnostics;
pub trait AttributeValueDiffStore {
fn set(&mut self, attribute_id: &XAttributeId, value: AttributeValueDiff);
fn aggregate_attribute(&self, index: usize) -> Option<Option<impl AsRef<str>>>;
}
#[nameth]
pub struct DynamicBackend<'t> {
element: &'t LiveElement,
}
impl<'t> DynamicBackend<'t> {
pub fn new(element: &'t LiveElement) -> Self {
Self { element }
}
}
impl AttributeValueDiffStore for DynamicBackend<'_> {
fn set(&mut self, attribute_id: &XAttributeId, value: AttributeValueDiff) {
*self.element.attributes.borrow_mut().get_mut(attribute_id) = value;
trace!(
"{DYNAMIC_BACKEND} attribute is now {:?}",
self.element
.attributes
.borrow()
.get_chunk(attribute_id.index)
);
}
fn aggregate_attribute(&self, index: usize) -> Option<Option<impl AsRef<str>>> {
aggregate_attribute(self.element.attributes.borrow().get_chunk(index))
}
}
#[nameth]
pub struct StaticBackend {
values: Vec<AttributeValueDiff>,
}
impl StaticBackend {
pub fn new(chunk: &Chunk<'_>) -> Self {
Self {
values: Vec::with_capacity(chunk.attributes.len()),
}
}
}
impl AttributeValueDiffStore for StaticBackend {
fn set(&mut self, attribute_id: &XAttributeId, value: AttributeValueDiff) {
if cfg!(feature = "diagnostics") {
assert!(
attribute_id.sub_index == self.values.len(),
"{STATIC_BACKEND} sub_index error. attribute_id.sub_index:{} != self.values.len():{}",
attribute_id.sub_index,
self.values.len()
);
}
self.values.push(value);
trace!("{STATIC_BACKEND} attribute is now {:?}", self.values);
}
fn aggregate_attribute(&self, _index: usize) -> Option<Option<impl AsRef<str>>> {
aggregate_attribute(&self.values)
}
}
#[nameth]
pub struct SingleBackend {
value: AttributeValueDiff,
}
impl Default for SingleBackend {
fn default() -> Self {
Self {
value: AttributeValueDiff::Undefined,
}
}
}
impl AttributeValueDiffStore for SingleBackend {
fn set(&mut self, attribute_id: &XAttributeId, value: AttributeValueDiff) {
if cfg!(feature = "diagnostics") {
assert!(
attribute_id.sub_index == 0,
"{SINGLE_BACKEND} sub_index error. attribute_id.sub_index:{} != 0",
attribute_id.sub_index,
);
}
self.value = value;
trace!("{SINGLE_BACKEND} attribute is now {:?}", self.value);
}
fn aggregate_attribute(&self, _index: usize) -> Option<Option<impl AsRef<str>>> {
match &self.value {
AttributeValueDiff::Undefined => None,
AttributeValueDiff::Same { .. } => None,
AttributeValueDiff::Null => Some(None),
AttributeValueDiff::Value(value) => Some(Some(value.as_str())),
}
}
}
pub struct Chunk<'t> {
pub chunk_kind: ChunkKind,
pub name: XAttributeName,
pub index: usize,
pub attributes: &'t mut [XAttribute],
}
#[derive(Debug)]
pub enum ChunkKind {
Dynamic,
Static,
Single,
}
impl ChunkKind {
pub fn of(chunk: &[XAttribute]) -> ChunkKind {
for attribute in chunk {
if let XAttributeValue::Dynamic { .. } = &attribute.value {
return ChunkKind::Dynamic;
}
}
if chunk.len() == 1 {
ChunkKind::Single
} else {
ChunkKind::Static
}
}
}