use crate::{Result, Error};
use crate::{grammar, grammar::Rule};
use crate::parse;
use itertools::Itertools;
use std::fmt;
use std::iter;
use std::str::FromStr;
pub use std::time::Duration;
pub type DateTime = chrono::DateTime<chrono::FixedOffset>;
pub type Date = chrono::NaiveDate;
#[derive(PartialEq)]
pub enum Value {
String(String),
Base64(Vec<u8>),
Date(Date),
DateTime(DateTime),
Duration(Duration),
Number(i128),
Decimal(f64),
Boolean(bool),
Null
}
impl fmt::Display for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self {
Value::String(text) => write!(f, "\"{}\"", text),
Value::Base64(data) => write!(f, "{:x?}", data),
Value::Date(date) => write!(f, "{}", date),
Value::DateTime(dtime) => write!(f, "{}", dtime),
Value::Duration(dur) => write!(f, "{:#?}", dur),
Value::Number(num) => write!(f, "{}", num),
Value::Decimal(dec) => write!(f, "{}", dec),
Value::Boolean(val) => write!(f, "{}", val),
Value::Null => write!(f, "null"),
}
}
}
impl fmt::Debug for Value {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl FromStr for Value {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
grammar::parse(Rule::value, s).and_then(parse::value)
}
}
impl From<String> for Value {
fn from(v: String) -> Self {Value::String(v)}
}
impl From<&str> for Value {
fn from(v: &str) -> Self {Value::String(v.to_string())}
}
impl From<Vec<u8>> for Value {
fn from(v: Vec<u8>) -> Self {Value::Base64(v)}
}
impl From<Date> for Value {
fn from(v: Date) -> Self {Value::Date(v)}
}
impl From<DateTime> for Value {
fn from(v: DateTime) -> Self {Value::DateTime(v)}
}
impl From<Duration> for Value {
fn from(v: Duration) -> Self {Value::Duration(v)}
}
impl From<i128> for Value {
fn from(v: i128) -> Self {Value::Number(v)}
}
impl From<f64> for Value {
fn from(v: f64) -> Self {Value::Decimal(v)}
}
impl From<bool> for Value {
fn from(v: bool) -> Self {Value::Boolean(v)}
}
#[derive(PartialEq)]
pub struct Attribute {
pub name: String,
pub value: Value,
}
impl Attribute {
pub fn new(name: String, value: Value) -> Self {
Attribute {
name,
value,
}
}
}
impl fmt::Display for Attribute {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}: {}", self.name, self.value)
}
}
impl fmt::Debug for Attribute {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(&self, f)
}
}
impl FromStr for Attribute {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
grammar::parse(Rule::attribute, s).and_then(parse::attribute)
}
}
impl From<(String, Value)> for Attribute {
fn from((k, v): (String, Value)) -> Self {
Attribute {
name: k,
value: v,
}
}
}
impl From<Attribute> for (String, Value) {
fn from(attr: Attribute) -> Self {
(attr.name, attr.value)
}
}
#[derive(Debug, PartialEq)]
pub struct Tag {
pub namespace: Option<String>,
pub name: String,
pub values: Vec<Value>,
pub attrs: Vec<Attribute>,
pub tags: Vec<Tag>,
}
impl Tag {
pub fn new(name: String) -> Self {
Tag {
namespace: None,
name,
values: Vec::new(),
attrs: Vec::new(),
tags: Vec::new(),
}
}
pub fn namespace(mut self, namespace: String) -> Self {
self.namespace = Some(namespace);
self
}
pub fn values(mut self, mut values: Vec<Value>) -> Self {
self.values.append(&mut values);
self
}
pub fn attrs(mut self, attrs: Vec<Attribute>) -> Self {
self.attrs.extend(attrs.into_iter().map(|a| a.into()));
self
}
pub fn tags(mut self, mut tags: Vec<Tag>) -> Self {
self.tags.append(&mut tags);
self
}
pub fn attr<'a, 'b>(&'a self, name: &'b str) -> Option<&'a Attribute> {
self.attrs.iter().find(|a| a.name == name)
}
pub fn attr_mut<'a, 'b>(&'a mut self, name: &'b str)
-> Option<&'a mut Attribute> {
self.attrs.iter_mut().find(|a| a.name == name)
}
pub fn tag<'a, 'b>(&'a self, name: &'b str) -> Option<&'a Tag> {
self.tags.iter().find(|t| t.name == name)
}
pub fn tag_mut<'a, 'b>(&'a mut self, name: &'b str)
-> Option<&'a mut Tag> {
self.tags.iter_mut().find(|t| t.name == name)
}
}
impl fmt::Display for Tag {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f,
"tag \"{}\": {}{}",
self.namespace.iter()
.chain(iter::once(&self.name))
.format(":"),
self.values.iter().map(|v| v.to_string())
.chain(self.attrs.iter().map(|a| format!("[{}]", a)))
.format(", "),
self.tags.iter().format_with("", |t, f| f(&format_args!(
"\n* {}", t.to_string().replace('\n', "\n ")))),
)
}
}
impl FromStr for Tag {
type Err = Error;
fn from_str(s: &str) -> Result<Self> {
grammar::parse(Rule::tag, s).and_then(parse::tag)
}
}