pub use callback::Callback;
use std::fmt;
mod callback;
pub struct Attribute<NS, ATT, VAL, EVENT, MSG> {
pub(crate) namespace: Option<NS>,
pub(crate) name: ATT,
pub(crate) value: Vec<AttValue<VAL, EVENT, MSG>>,
}
impl<NS, ATT, VAL, EVENT, MSG> Clone for Attribute<NS, ATT, VAL, EVENT, MSG>
where
NS: Clone,
ATT: Clone,
VAL: Clone,
{
fn clone(&self) -> Self {
Attribute {
namespace: self.namespace.clone(),
name: self.name.clone(),
value: self.value.clone(),
}
}
}
impl<NS, ATT, VAL, EVENT, MSG> PartialEq for Attribute<NS, ATT, VAL, EVENT, MSG>
where
NS: PartialEq,
ATT: PartialEq,
VAL: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
self.namespace == other.namespace
&& self.name == other.name
&& self.value == other.value
}
}
impl<NS, ATT, VAL, EVENT, MSG> fmt::Debug
for Attribute<NS, ATT, VAL, EVENT, MSG>
where
NS: fmt::Debug,
ATT: fmt::Debug,
VAL: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Attribute")
.field("namespace", &self.namespace)
.field("name", &self.name)
.field("value", &self.value)
.finish()
}
}
pub enum AttValue<VAL, EVENT, MSG> {
Plain(VAL),
Callback(Callback<EVENT, MSG>),
}
impl<VAL, EVENT, MSG> Clone for AttValue<VAL, EVENT, MSG>
where
VAL: Clone,
{
fn clone(&self) -> Self {
match self {
AttValue::Plain(value) => AttValue::Plain(value.clone()),
AttValue::Callback(cb) => AttValue::Callback(cb.clone()),
}
}
}
impl<VAL, EVENT, MSG> fmt::Debug for AttValue<VAL, EVENT, MSG>
where
VAL: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
AttValue::Plain(value) => {
f.debug_tuple("Plain").field(value).finish()
}
AttValue::Callback(cb) => {
f.debug_tuple("Callback").field(cb).finish()
}
}
}
}
impl<VAL, EVENT, MSG> PartialEq for AttValue<VAL, EVENT, MSG>
where
VAL: PartialEq,
{
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(AttValue::Plain(val), AttValue::Plain(other)) => *val == *other,
(AttValue::Callback(cb), AttValue::Callback(other)) => {
*cb == *other
}
_ => false,
}
}
}
impl<VAL, EVENT, MSG> From<VAL> for AttValue<VAL, EVENT, MSG> {
fn from(value: VAL) -> Self {
AttValue::Plain(value)
}
}
impl<NS, ATT, VAL, EVENT, MSG> Attribute<NS, ATT, VAL, EVENT, MSG> {
pub fn new(namespace: Option<NS>, name: ATT, value: VAL) -> Self {
Attribute {
name,
value: vec![AttValue::from(value)],
namespace,
}
}
pub fn with_multiple_values(
namespace: Option<NS>,
name: ATT,
value: Vec<VAL>,
) -> Self {
Attribute {
name,
value: value.into_iter().map(AttValue::from).collect(),
namespace,
}
}
pub fn name(&self) -> &ATT {
&self.name
}
pub fn value(&self) -> &[AttValue<VAL, EVENT, MSG>] {
&self.value
}
pub fn namespace(&self) -> Option<&NS> {
self.namespace.as_ref()
}
pub fn get_plain(&self) -> Vec<&VAL> {
self.value.iter().filter_map(|v| v.get_plain()).collect()
}
}
impl<NS, ATT, VAL, EVENT, MSG> Attribute<NS, ATT, VAL, EVENT, MSG>
where
EVENT: 'static,
MSG: 'static,
{
pub fn map_msg<F, MSG2>(
self,
func: F,
) -> Attribute<NS, ATT, VAL, EVENT, MSG2>
where
F: Fn(MSG) -> MSG2 + 'static,
MSG2: 'static,
{
let cb = Callback::from(func);
self.map_callback(cb)
}
pub fn map_callback<MSG2>(
self,
cb: Callback<MSG, MSG2>,
) -> Attribute<NS, ATT, VAL, EVENT, MSG2>
where
MSG2: 'static,
{
Attribute {
name: self.name,
value: self
.value
.into_iter()
.map(|v| v.map_callback(cb.clone()))
.collect(),
namespace: self.namespace,
}
}
pub fn get_callback(&self) -> Vec<&Callback<EVENT, MSG>> {
self.value.iter().filter_map(|v| v.get_callback()).collect()
}
}
impl<VAL, EVENT, MSG> AttValue<VAL, EVENT, MSG> {
pub fn get_plain(&self) -> Option<&VAL> {
match self {
AttValue::Plain(plain) => Some(plain),
AttValue::Callback(_) => None,
}
}
}
impl<VAL, EVENT, MSG> AttValue<VAL, EVENT, MSG>
where
EVENT: 'static,
MSG: 'static,
{
pub fn map_callback<MSG2>(
self,
cb: Callback<MSG, MSG2>,
) -> AttValue<VAL, EVENT, MSG2>
where
MSG2: 'static,
{
match self {
AttValue::Plain(plain) => AttValue::Plain(plain),
AttValue::Callback(att_cb) => {
AttValue::Callback(att_cb.map_callback(cb))
}
}
}
pub fn get_callback(&self) -> Option<&Callback<EVENT, MSG>> {
match self {
AttValue::Plain(_) => None,
AttValue::Callback(cb) => Some(cb),
}
}
pub fn is_callback(&self) -> bool {
match self {
AttValue::Plain(_) => false,
AttValue::Callback(_) => true,
}
}
}
pub fn on<NS, ATT, VAL, EVENT, MSG>(
name: ATT,
cb: Callback<EVENT, MSG>,
) -> Attribute<NS, ATT, VAL, EVENT, MSG> {
Attribute {
namespace: None,
name,
value: vec![AttValue::Callback(cb)],
}
}
#[inline]
pub fn attr<NS, ATT, VAL, EVENT, MSG>(
name: ATT,
value: VAL,
) -> Attribute<NS, ATT, VAL, EVENT, MSG> {
attr_ns(None, name, value)
}
#[inline]
pub fn attr_ns<NS, ATT, VAL, EVENT, MSG>(
namespace: Option<NS>,
name: ATT,
value: VAL,
) -> Attribute<NS, ATT, VAL, EVENT, MSG> {
Attribute::new(namespace, name, value)
}
pub fn merge_attributes_of_same_name<NS, ATT, VAL, EVENT, MSG>(
attributes: &[&Attribute<NS, ATT, VAL, EVENT, MSG>],
) -> Vec<Attribute<NS, ATT, VAL, EVENT, MSG>>
where
NS: fmt::Debug,
ATT: PartialEq + Clone + fmt::Debug,
VAL: fmt::Debug + Clone,
{
let mut merged: Vec<Attribute<NS, ATT, VAL, EVENT, MSG>> = vec![];
for att in attributes {
if let Some(existing) =
merged.iter_mut().find(|m_att| m_att.name == att.name)
{
existing.value.extend(att.value.clone());
} else {
merged.push(Attribute {
namespace: None,
name: att.name.clone(),
value: att.value.clone(),
});
}
}
merged
}
pub fn group_attributes_per_name<'a, NS, ATT, VAL, EVENT, MSG>(
attributes: &'a [Attribute<NS, ATT, VAL, EVENT, MSG>],
) -> Vec<(&'a ATT, Vec<&'a Attribute<NS, ATT, VAL, EVENT, MSG>>)>
where
NS: fmt::Debug,
ATT: PartialEq + fmt::Debug,
VAL: fmt::Debug,
{
let mut grouped: Vec<(&ATT, Vec<&Attribute<NS, ATT, VAL, EVENT, MSG>>)> =
vec![];
for attr in attributes {
if let Some(existing) = grouped
.iter_mut()
.find(|(g_att, _)| **g_att == attr.name)
.map(|(_, attr)| attr)
{
existing.push(attr);
} else {
grouped.push((&attr.name, vec![attr]))
}
}
grouped
}