use qualname::{NamespacePrefix, NamespaceUri, QName};
use crate::item;
use crate::output::OutputDefinition;
use crate::validators::{Schema, ValidationError};
use crate::value::{Operator, Value};
use crate::xdmerror::{Error, ErrorKind};
use crate::xmldecl::{DTD, XMLDecl};
use std::cmp::Ordering;
use std::fmt;
use std::fmt::Formatter;
use std::rc::Rc;
pub type Sequence<N> = Vec<Item<N>>;
pub trait SequenceTrait<N: Node> {
fn to_string(&self) -> String;
fn to_xml(&self) -> String;
fn to_xml_with_options(&self, od: &OutputDefinition) -> String;
fn to_json(&self) -> String;
fn to_bool(&self) -> bool;
fn to_int(&self) -> Result<i64, Error>;
fn push_node(&mut self, n: &N);
fn push_value(&mut self, v: &Rc<Value>);
fn push_item(&mut self, i: &Item<N>);
}
impl<N: Node> SequenceTrait<N> for Sequence<N> {
fn to_string(&self) -> String {
let mut r = String::new();
for i in self {
r.push_str(i.to_string().as_str())
}
r
}
fn to_xml(&self) -> String {
let mut r = String::new();
for i in self {
r.push_str(i.to_xml().as_str())
}
r
}
fn to_xml_with_options(&self, od: &OutputDefinition) -> String {
let mut r = String::new();
for i in self {
r.push_str(i.to_xml_with_options(od).as_str())
}
r
}
fn to_json(&self) -> String {
let mut r = String::new();
for i in self {
r.push_str(i.to_json().as_str())
}
r
}
fn push_node(&mut self, n: &N) {
self.push(Item::Node(n.clone()));
}
fn push_value(&mut self, v: &Rc<Value>) {
self.push(Item::Value(Rc::clone(v)));
}
fn push_item(&mut self, i: &Item<N>) {
self.push(i.clone());
}
fn to_bool(&self) -> bool {
if self.is_empty() {
false
} else {
match self[0] {
Item::Node(..) => true,
_ => {
if self.len() == 1 {
self[0].to_bool()
} else {
false }
}
}
}
}
fn to_int(&self) -> Result<i64, Error> {
if self.len() == 1 {
self[0].to_int()
} else {
Err(Error::new(
ErrorKind::TypeError,
String::from("type error: sequence is not a singleton"),
))
}
}
}
impl<N: Node> From<Value> for Sequence<N> {
fn from(v: Value) -> Self {
vec![Item::Value(Rc::new(v))]
}
}
impl<N: Node> From<Item<N>> for Sequence<N> {
fn from(i: Item<N>) -> Self {
vec![i]
}
}
#[derive(Copy, Clone, Eq, PartialEq, Debug, Default)]
pub enum NodeType {
Document,
Element,
Text,
Attribute,
Comment,
ProcessingInstruction,
Reference,
Namespace,
#[default]
Unknown,
}
impl NodeType {
pub fn to_string(&self) -> &'static str {
match self {
NodeType::Document => "Document",
NodeType::Element => "Element",
NodeType::Attribute => "Attribute",
NodeType::Text => "Text",
NodeType::ProcessingInstruction => "Processing-Instruction",
NodeType::Comment => "Comment",
NodeType::Reference => "Reference",
NodeType::Namespace => "Namespace",
NodeType::Unknown => "--None--",
}
}
}
impl fmt::Display for NodeType {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str(self.to_string())
}
}
#[derive(Clone)]
pub enum Item<N: Node> {
Node(N),
Function,
Value(Rc<Value>),
}
impl<N: item::Node> fmt::Display for Item<N> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
let result = match self {
Item::Node(n) => n.to_string(),
Item::Function => "".to_string(),
Item::Value(v) => v.to_string(),
};
f.write_str(result.as_str())
}
}
impl<N: Node> Item<N> {
pub fn to_xml(&self) -> String {
match self {
Item::Node(n) => n.to_xml(),
Item::Function => "".to_string(),
Item::Value(v) => v.to_string(),
}
}
pub fn to_xml_with_options(&self, od: &OutputDefinition) -> String {
match self {
Item::Node(n) => n.to_xml_with_options(od),
Item::Function => "".to_string(),
Item::Value(v) => v.to_string(),
}
}
pub fn to_json(&self) -> String {
match self {
Item::Node(n) => n.to_json(),
Item::Function => "".to_string(),
Item::Value(v) => v.to_string(),
}
}
pub fn to_bool(&self) -> bool {
match self {
Item::Node(..) => true,
Item::Function => false,
Item::Value(v) => v.to_bool(),
}
}
pub fn to_int(&self) -> Result<i64, Error> {
match self {
Item::Node(..) => Result::Err(Error::new(
ErrorKind::TypeError,
String::from("type error: item is a node"),
)),
Item::Function => Result::Err(Error::new(
ErrorKind::TypeError,
String::from("type error: item is a function"),
)),
Item::Value(v) => match v.to_int() {
Ok(i) => Ok(i),
Err(e) => Result::Err(e),
},
}
}
pub fn to_double(&self) -> f64 {
match self {
Item::Node(..) => f64::NAN,
Item::Function => f64::NAN,
Item::Value(v) => v.to_double(),
}
}
pub fn name(&self) -> Option<QName> {
match self {
Item::Node(n) => n.name(),
_ => None,
}
}
pub fn compare(&self, other: &Item<N>, op: Operator) -> Result<bool, Error> {
match self {
Item::Value(v) => match other {
Item::Value(w) => v.compare(w, op),
Item::Node(..) => v.compare(&Value::from(other.to_string()), op),
_ => Result::Err(Error::new(ErrorKind::TypeError, String::from("type error"))),
},
Item::Node(..) => {
other.compare(&Item::Value(Rc::new(Value::from(self.to_string()))), op)
}
_ => Result::Err(Error::new(ErrorKind::TypeError, String::from("type error"))),
}
}
pub fn is_node(&self) -> bool {
matches!(self, Item::Node(_))
}
pub fn is_element_node(&self) -> bool {
match self {
Item::Node(n) => matches!(n.node_type(), NodeType::Element),
_ => false,
}
}
pub fn add_attribute(&self, a: N) -> Result<(), Error> {
match self {
Item::Node(n) => match n.node_type() {
NodeType::Element => n.add_attribute(a),
_ => Ok(()),
},
_ => Ok(()),
}
}
pub fn item_type(&self) -> &'static str {
match self {
Item::Node(..) => "Node",
Item::Function => "Function",
Item::Value(v) => v.value_type(),
}
}
pub fn shallow_copy(&self) -> Result<Self, Error> {
match self {
Item::Value(v) => Ok(Item::Value(v.clone())),
Item::Node(n) => Ok(Item::Node(n.shallow_copy()?)),
_ => Result::Err(Error::new(
ErrorKind::NotImplemented,
"not implemented".to_string(),
)),
}
}
pub fn deep_copy(&self) -> Result<Self, Error> {
match self {
Item::Value(v) => Ok(Item::Value(v.clone())),
Item::Node(n) => Ok(Item::Node(n.deep_copy()?)),
_ => Result::Err(Error::new(
ErrorKind::NotImplemented,
"not implemented".to_string(),
)),
}
}
}
impl<N: Node> fmt::Debug for Item<N> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Item::Node(n) => {
write!(
f,
"node type item ({:?})",
n )
}
Item::Function => {
write!(f, "function type item")
}
Item::Value(v) => {
write!(f, "value type item ({})", v)
}
}
}
}
pub trait Node: Clone + PartialEq + fmt::Debug {
type NodeIterator: Iterator<Item = Self>;
fn new_document() -> Self;
fn node_type(&self) -> NodeType;
fn name(&self) -> Option<QName>;
fn value(&self) -> Rc<Value>;
fn to_qname(&self, name: impl AsRef<str>) -> Result<QName, Error>;
fn to_prefixed_name(&self) -> String;
fn to_namespace_prefix(&self, nsuri: &NamespaceUri) -> Result<Option<NamespacePrefix>, Error>;
fn to_namespace_uri(&self, prefix: &Option<NamespacePrefix>) -> Result<NamespaceUri, Error>;
fn as_namespace_prefix(&self) -> Result<Option<&NamespacePrefix>, Error>;
fn as_namespace_uri(&self) -> Result<&NamespaceUri, Error>;
fn is_in_scope(&self) -> bool;
fn get_id(&self) -> String;
fn to_string(&self) -> String;
fn to_xml(&self) -> String;
fn to_xml_with_options(&self, od: &OutputDefinition) -> String;
fn to_json(&self) -> String {
String::new()
}
fn is_same(&self, other: &Self) -> bool;
fn is_attached(&self) -> bool;
fn document_order(&self) -> Vec<usize>;
fn cmp_document_order(&self, other: &Self) -> Ordering;
fn is_element(&self) -> bool {
self.node_type() == NodeType::Element
}
fn is_unattached(&self) -> bool;
fn is_id(&self) -> bool;
fn is_idrefs(&self) -> bool;
fn child_iter(&self) -> Self::NodeIterator;
fn first_child(&self) -> Option<Self>
where
Self: Sized,
{
self.child_iter().next()
}
fn ancestor_iter(&self) -> Self::NodeIterator;
fn parent(&self) -> Option<Self>
where
Self: Sized,
{
self.ancestor_iter().next()
}
fn owner_document(&self) -> Self;
fn descend_iter(&self) -> Self::NodeIterator;
fn next_iter(&self) -> Self::NodeIterator;
fn prev_iter(&self) -> Self::NodeIterator;
fn attribute_iter(&self) -> Self::NodeIterator;
fn get_attribute(&self, a: &QName) -> Rc<Value>;
fn get_attribute_node(&self, a: &QName) -> Option<Self>;
fn new_element(&self, qn: QName) -> Result<Self, Error>;
fn new_text(&self, v: Rc<Value>) -> Result<Self, Error>;
fn new_attribute(&self, qn: QName, v: Rc<Value>) -> Result<Self, Error>;
fn new_comment(&self, v: Rc<Value>) -> Result<Self, Error>;
fn new_processing_instruction(&self, qn: Rc<Value>, v: Rc<Value>) -> Result<Self, Error>;
fn new_namespace(
&self,
ns: NamespaceUri,
prefix: Option<NamespacePrefix>,
in_scope: bool,
) -> Result<Self, Error>;
fn push(&mut self, n: Self) -> Result<(), Error>;
fn pop(&mut self) -> Result<(), Error>;
fn insert_before(&mut self, n: Self) -> Result<(), Error>;
fn add_attribute(&self, att: Self) -> Result<(), Error>;
fn shallow_copy(&self) -> Result<Self, Error>;
fn deep_copy(&self) -> Result<Self, Error>;
fn get_canonical(&self) -> Result<Self, Error>;
fn xmldecl(&self) -> XMLDecl;
fn set_xmldecl(&mut self, d: XMLDecl) -> Result<(), Error>;
fn add_namespace(&self, ns: Self) -> Result<(), Error>;
fn eq(&self, other: &Self) -> bool {
match self.node_type() {
NodeType::Document => {
if other.node_type() == NodeType::Document {
self.child_iter()
.zip(other.child_iter())
.fold(true, |mut acc, (c, d)| {
if acc {
acc = Node::eq(&c, &d);
acc
} else {
acc
}
})
} else {
false
}
}
NodeType::Element => {
if other.node_type() == NodeType::Element {
if self.name() == other.name() {
let mut at_names: Vec<QName> =
self.attribute_iter().map(|a| a.name().unwrap()).collect();
if at_names.len() == other.attribute_iter().count() {
at_names.sort();
if at_names.iter().fold(true, |mut acc, qn| {
if acc {
acc = self.get_attribute(qn) == other.get_attribute(qn);
acc
} else {
acc
}
}) {
self.child_iter().zip(other.child_iter()).fold(
true,
|mut acc, (c, d)| {
if acc {
acc = Node::eq(&c, &d);
acc
} else {
acc
}
},
)
} else {
false
}
} else {
false
}
} else {
false
}
} else {
false
}
}
NodeType::Text => {
if other.node_type() == NodeType::Text {
self.value() == other.value()
} else {
false
}
}
NodeType::ProcessingInstruction => {
if other.node_type() == NodeType::ProcessingInstruction {
self.name() == other.name() && self.value() == other.value()
} else {
false
}
}
_ => self.node_type() == other.node_type(), }
}
fn namespace_iter(&self) -> Self::NodeIterator;
fn get_dtd(&self) -> Option<DTD>;
fn set_dtd(&self, dtd: DTD) -> Result<(), Error>;
fn validate(&self, schema: Schema) -> Result<(), ValidationError>;
fn unattached(&self) -> Vec<Self>;
}