use std::fmt::Write;
use crate::{TagOpening, Empty, Sum};
pub trait Attributes {
fn write_attributes<'a, 't, W: Write>(self, w: &mut TagOpening<'a, 't, W>) -> std::fmt::Result;
} impl<A: Attributes, B: Attributes> Attributes for Sum<A, B> {
fn write_attributes<'a, 't, W: Write>(self, w: &mut TagOpening<'a, 't, W>) -> std::fmt::Result {
self.0.write_attributes(w)?;
self.1.write_attributes(w)?;
Ok(())
}
}
impl<I: IntoIterator<Item = (Name, Value)>, Name, Value> Attributes for I
where
Name: AttributeName,
Value: AttributeValue,
{
fn write_attributes<'a, 't, W: Write>(self, w: &mut TagOpening<'a, 't, W>) -> std::fmt::Result {
for (n, v) in self {
w.attr(n, v)?;
}
Ok(())
}
}
impl Attributes for Empty {
fn write_attributes<'a, 't, W: Write>(self, _w: &mut TagOpening<'a, 't, W>) -> std::fmt::Result {
Ok(())
}
}
pub fn is_valid_attribute_name(name: &str) -> bool {
if name.is_empty() {
return false;
}
if name.trim() != name {
return false;
}
let mut chars = name.chars();
let first_char = chars.next().unwrap();
if !first_char.is_ascii_alphabetic() {
return false;
}
for c in chars {
if !c.is_ascii_alphanumeric() && c != '-' && c != '_' {
return false;
}
}
true
}
pub trait AttributeName {
fn is_valid_attribute_name(&self) -> bool;
fn write_attribute_name(self, w: &mut impl Write) -> std::fmt::Result;
}
impl AttributeName for &str {
fn is_valid_attribute_name(&self) -> bool {
is_valid_attribute_name(self)
}
fn write_attribute_name(self, w: &mut impl Write) -> std::fmt::Result {
w.write_str(self)
}
}
impl AttributeName for &&str {
fn is_valid_attribute_name(&self) -> bool {
is_valid_attribute_name(self)
}
fn write_attribute_name(self, w: &mut impl Write) -> std::fmt::Result {
w.write_str(*self)
}
}
impl AttributeName for String {
fn is_valid_attribute_name(&self) -> bool {
is_valid_attribute_name(&self)
}
fn write_attribute_name(self, w: &mut impl Write) -> std::fmt::Result {
w.write_str(&self)
}
}
impl AttributeName for &String {
fn is_valid_attribute_name(&self) -> bool {
is_valid_attribute_name(self)
}
fn write_attribute_name(self, w: &mut impl Write) -> std::fmt::Result {
w.write_str(self)
}
}
pub trait AttributeValue {
fn is_unit(&self) -> bool {
false
}
fn write_attribute_value(self, w: &mut impl Write) -> std::fmt::Result;
}
impl AttributeValue for &str {
fn is_unit(&self) -> bool {
false
}
fn write_attribute_value(self, w: &mut impl Write) -> std::fmt::Result {
w.write_str(self)
}
}
impl AttributeValue for &&str {
fn is_unit(&self) -> bool {
false
}
fn write_attribute_value(self, w: &mut impl Write) -> std::fmt::Result {
w.write_str(*self)
}
}
impl AttributeValue for String {
fn is_unit(&self) -> bool {
false
}
fn write_attribute_value(self, w: &mut impl Write) -> std::fmt::Result {
w.write_str(&self)
}
}
impl AttributeValue for &String {
fn is_unit(&self) -> bool {
false
}
fn write_attribute_value(self, w: &mut impl Write) -> std::fmt::Result {
w.write_str(self)
}
}
impl AttributeValue for () {
fn is_unit(&self) -> bool {
true
}
fn write_attribute_value(self, _w: &mut impl Write) -> std::fmt::Result {
Ok(())
}
}