use std::any::Any;
use std::cmp::Ordering;
use std::rc::Rc;
use decimal;
use crate::xdmerror::{Error, ErrorKind};
pub type Sequence = Vec<Rc<Item>>;
pub trait SequenceTrait {
fn to_string(&self) -> String;
fn to_xml(&self) -> String;
fn to_json(&self) -> String;
fn to_bool(&self) -> bool;
fn to_int(&self) -> Result<i64, Error>;
fn new_document(&mut self, d: Rc<dyn Document>);
fn new_node(&mut self, d: Rc<dyn Node>);
fn new_value(&mut self, v: Value);
fn add(&mut self, i: &Rc<Item>);
}
impl SequenceTrait for Sequence {
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_json(&self) -> String {
let mut r = String::new();
for i in self {
r.push_str(i.to_json().as_str())
}
r
}
fn new_document(&mut self, d: Rc<dyn Document>) {
self.push(Rc::new(Item::Document(d)));
}
fn new_node(&mut self, n: Rc<dyn Node>) {
self.push(Rc::new(Item::Node(n)));
}
fn new_value(&mut self, v: Value) {
self.push(Rc::new(Item::Value(v)));
}
fn add(&mut self, i: &Rc<Item>) {
self.push(Rc::clone(i));
}
fn to_bool(&self) -> bool {
if self.len() == 0 {
false
} else {
match *self[0] {
Item::Document(_) |
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 {
Result::Err(Error{kind: ErrorKind::TypeError, message: String::from("type error: sequence is not a singleton")})
}
}
}
#[derive(Clone)]
pub enum Item {
Document(Rc<dyn Document>),
Node(Rc<dyn Node>),
Function,
Value(Value),
}
#[derive(Copy, Clone)]
pub enum Operator {
Equal,
NotEqual,
LessThan,
LessThanEqual,
GreaterThan,
GreaterThanEqual,
Is,
Before,
After,
}
impl Operator {
pub fn to_string(&self) -> &str {
match self {
Operator::Equal => "=",
Operator::NotEqual => "!=",
Operator::LessThan => "<",
Operator::LessThanEqual => "<=",
Operator::GreaterThan => ">",
Operator::GreaterThanEqual => ">=",
Operator::Is => "is",
Operator::Before => "<<",
Operator::After => ">>",
}
}
}
impl Item {
pub fn to_string(&self) -> String {
match self {
Item::Document(d) => d.to_string(),
Item::Node(n) => n.to_string(),
Item::Function => "".to_string(),
Item::Value(v) => v.to_string(),
}
}
pub fn to_xml(&self) -> String {
match self {
Item::Document(d) => d.to_xml(),
Item::Node(n) => n.to_xml(),
Item::Function => "".to_string(),
Item::Value(v) => v.to_string(),
}
}
pub fn to_json(&self) -> String {
match self {
Item::Document(d) => d.to_json(),
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::Document(_) |
Item::Node(_) => true,
Item::Function => false,
Item::Value(v) => v.to_bool(),
}
}
pub fn to_int(&self) -> Result<i64, Error> {
match self {
Item::Document(_) |
Item::Node(_) => Result::Err(Error{kind: ErrorKind::TypeError, message: String::from("type error: item is a node")}),
Item::Function => Result::Err(Error{kind: ErrorKind::TypeError, message: 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::Document(_) |
Item::Node(_) => f64::NAN,
Item::Function => f64::NAN,
Item::Value(v) => v.to_double(),
}
}
pub fn to_name(&self) -> QualifiedName {
match self {
Item::Node(i) => i.to_name(),
_ => QualifiedName::new(None, None, "".to_string())
}
}
pub fn compare(&self, other: &Item, op: Operator) -> Result<bool, Error> {
match self {
Item::Value(v) => {
v.compare(other, op)
}
Item::Node(_) => {
other.compare(&Item::Value(Value::String(self.to_string())), op)
}
_ => {
Result::Err(Error{kind: ErrorKind::TypeError, message: String::from("type error")})
}
}
}
pub fn is_element_node(&self) -> bool {
match self {
Item::Node(n) => {
match n.node_type() {
NodeType::Element => true,
_ => false,
}
}
_ => false,
}
}
pub fn get_root_element(&self) -> Option<Rc<dyn Node>> {
match self {
Item::Document(d) => {
match d.get_root_element() {
Some(n) => Some(n),
_ => None,
}
}
_ => None,
}
}
pub fn item_type(&self) -> &'static str {
match self {
Item::Document(_) => "Document",
Item::Node(_) => "Node",
Item::Function => "Function",
Item::Value(v) => v.value_type(),
}
}
}
pub trait Document {
fn to_string(&self) -> String;
fn to_xml(&self) -> String;
fn to_json(&self) -> String;
fn to_bool(&self) -> bool {
true
}
fn to_int(&self) -> Result<i64, Error> {
Result::Err(Error{kind: ErrorKind::TypeError, message: String::from("type error: document")})
}
fn to_double(&self) -> f64 {
f64::NAN
}
fn to_name(&self) -> QualifiedName {
QualifiedName::new(None, None, String::new())
}
fn parent(&self) -> Option<Rc<dyn Node>> {
None
}
fn children(&self) -> Vec<Rc<dyn Node>>;
fn get_root_element(&self) -> Option<Rc<dyn Node>>;
fn new_element(&self, name: &str, ns: Option<&str>) -> Result<Rc<dyn Node>, Error>;
fn new_text(&self, c: &str) -> Result<Rc<dyn Node>, Error>;
fn set_root_element(&mut self, r: &dyn Any) -> Result<(), Error>;
}
pub trait Node: Any {
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
fn to_string(&self) -> String;
fn to_xml(&self) -> String;
fn to_json(&self) -> String;
fn to_bool(&self) -> bool {
true
}
fn to_int(&self) -> Result<i64, Error>;
fn to_double(&self) -> f64;
fn to_name(&self) -> QualifiedName;
fn doc(&self) -> Option<Rc<dyn Document>> {
None
}
fn node_type(&self) -> NodeType;
fn parent(&self) -> Option<Rc<dyn Node>>;
fn ancestors(&self) -> Vec<Rc<dyn Node>>;
fn children(&self) -> Vec<Rc<dyn Node>>;
fn descendants(&self) -> Vec<Rc<dyn Node>>;
fn get_following_sibling(&self) -> Option<Rc<dyn Node>>;
fn following_siblings(&self) -> Vec<Rc<dyn Node>>;
fn get_preceding_sibling(&self) -> Option<Rc<dyn Node>>;
fn preceding_siblings(&self) -> Vec<Rc<dyn Node>>;
fn attribute(&self, _name: &str) -> Option<String> {
None
}
fn is_element(&self) -> bool {
false
}
fn add_child(&self, c: &dyn Any) -> Result<(), Error>;
fn add_text_child(&self, t: String) -> Result<(), Error>;
}
#[derive(Clone, Debug)]
pub struct QualifiedName {
nsuri: Option<String>,
prefix: Option<String>,
localname: String,
}
impl QualifiedName {
pub fn new(nsuri: Option<String>, prefix: Option<String>, localname: String) -> QualifiedName {
QualifiedName{nsuri, prefix, localname}
}
pub fn get_nsuri(&self) -> Option<String> {
self.nsuri.clone()
}
pub fn get_nsuri_ref(&self) -> Option<&str> {
match self.nsuri {
Some(ref n) => {
Some(&n)
}
None => None,
}
}
pub fn get_prefix(&self) -> Option<String> {
self.prefix.clone()
}
pub fn get_localname(&self) -> String {
self.localname.clone()
}
}
struct Ancestor {
node: Rc<dyn Node>,
}
impl Iterator for Ancestor {
type Item = Rc<dyn Node>;
fn next(&mut self) -> Option<Self::Item> {
match self.node.parent() {
Some(n) => {
self.node = self.node.parent().unwrap();
Some(n)
}
None => None,
}
}
}
struct FollowingSibling {
node: Rc<dyn Node>,
}
impl Iterator for FollowingSibling {
type Item = Rc<dyn Node>;
fn next(&mut self) -> Option<Self::Item> {
match self.node.get_following_sibling() {
Some(n) => {
self.node = self.node.get_following_sibling().unwrap();
Some(n)
}
None => None,
}
}
}
struct PrecedingSibling {
node: Rc<dyn Node>,
}
impl Iterator for PrecedingSibling {
type Item = Rc<dyn Node>;
fn next(&mut self) -> Option<Self::Item> {
match self.node.get_preceding_sibling() {
Some(n) => {
self.node = self.node.get_preceding_sibling().unwrap();
Some(n)
}
None => None,
}
}
}
#[derive(Copy, Clone, Debug)]
pub enum NodeType {
Document,
Element,
Text,
Attribute,
Comment,
ProcessingInstruction,
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::Unknown => "--None--",
}
}
}
impl PartialEq for Value {
fn eq(&self, other: &Value) -> bool {
match self {
Value::String(s) => s.eq(&other.to_string()),
Value::Boolean(b) => match other {
Value::Boolean(c) => b == c,
_ => false, },
Value::Decimal(d) => match other {
Value::Decimal(e) => d == e,
_ => false, },
Value::Integer(i) => match other {
Value::Integer(j) => i == j,
_ => false, },
Value::Double(d) => match other {
Value::Double(e) => d == e,
_ => false, },
_ => false, }
}
}
impl PartialOrd for Value {
fn partial_cmp(&self, other: &Value) -> Option<Ordering> {
match self {
Value::String(s) => {
let o: String = other.to_string();
s.partial_cmp(&o)
},
Value::Boolean(_) => None,
Value::Decimal(d) => match other {
Value::Decimal(e) => d.partial_cmp(e),
_ => None, }
Value::Integer(d) => match other {
Value::Integer(e) => d.partial_cmp(e),
_ => None, }
Value::Double(d) => match other {
Value::Double(e) => d.partial_cmp(e),
_ => None, }
_ => None,
}
}
}
#[derive(Clone)]
pub enum Value {
AnyType,
Untyped,
AnySimpleType,
IDREFS,
NMTOKENS,
ENTITIES,
Numeric,
AnyAtomicType,
UntypedAtomic,
Duration,
Time,
Decimal(decimal::d128),
Float(f32),
Double(f64),
Integer(i64),
NonPositiveInteger(NonPositiveInteger),
NegativeInteger(NegativeInteger),
Long(i64),
Int(i32),
Short(i16),
Byte(i8),
NonNegativeInteger(NonNegativeInteger),
UnsignedLong(u64),
UnsignedInt(u32),
UnsignedShort(u16),
UnsignedByte(u8),
PositiveInteger(PositiveInteger),
DateTime,
DateTimeStamp,
Date,
String(String),
NormalizedString(NormalizedString),
Token,
Language,
NMTOKEN,
Name,
NCName,
ID,
IDREF,
ENTITY,
Boolean(bool),
}
impl Value {
pub fn to_string(&self) -> String {
match self {
Value::String(s) => s.to_string(),
Value::NormalizedString(s) => s.value.to_string(),
Value::Decimal(d) => d.to_string(),
Value::Float(f) => f.to_string(),
Value::Double(d) => d.to_string(),
Value::Integer(i) => i.to_string(),
Value::Long(l) => l.to_string(),
Value::Short(s) => s.to_string(),
Value::Int(i) => i.to_string(),
Value::Byte(b) => b.to_string(),
Value::UnsignedLong(l) => l.to_string(),
Value::UnsignedShort(s) => s.to_string(),
Value::UnsignedInt(i) => i.to_string(),
Value::UnsignedByte(b) => b.to_string(),
Value::NonPositiveInteger(i) => i.value().to_string(),
Value::NonNegativeInteger(i) => i.value().to_string(),
Value::PositiveInteger(i) => i.value().to_string(),
Value::NegativeInteger(i) => i.value().to_string(),
_ => "".to_string(),
}
}
pub fn to_bool(&self) -> bool {
match &self {
Value::Boolean(b) => *b == true,
Value::String(t) => {
t.len() != 0
},
Value::NormalizedString(s) => s.value.len() != 0,
Value::Double(n) => *n != 0.0,
Value::Integer(i) => *i != 0,
_ => false
}
}
pub fn to_int(&self) -> Result<i64, Error> {
match &self {
Value::String(s) => {
match s.parse::<i64>() {
Ok(i) => Ok(i),
Err(e) => Result::Err(Error{kind: ErrorKind::Unknown, message: format!("type conversion error: {}", e)}),
}
}
Value::Integer(i) => Ok(*i),
_ => Result::Err(Error{kind: ErrorKind::Unknown, message: String::from("type error (conversion not implemented)")})
}
}
pub fn to_double(&self) -> f64 {
match &self {
Value::String(s) => {
match s.parse::<f64>() {
Ok(i) => i,
Err(_) => f64::NAN,
}
}
Value::Integer(i) => (*i) as f64,
Value::Double(d) => *d,
_ => f64::NAN,
}
}
pub fn compare(&self, other: &Item, op: Operator) -> Result<bool, Error> {
match &self {
Value::Boolean(b) => {
let c = other.to_bool();
match op {
Operator::Equal => Ok(*b == c),
Operator::NotEqual => Ok(*b != c),
Operator::LessThan => Ok(*b < c),
Operator::LessThanEqual => Ok(*b <= c),
Operator::GreaterThan => Ok(*b > c),
Operator::GreaterThanEqual => Ok(*b >= c),
Operator::Is |
Operator::Before |
Operator::After => Result::Err(Error{kind: ErrorKind::Unknown, message: String::from("type error")})
}
}
Value::Integer(i) => {
match other.to_int() {
Ok(j) => {
match op {
Operator::Equal => Ok(*i == j),
Operator::NotEqual => Ok(*i != j),
Operator::LessThan => Ok(*i < j),
Operator::LessThanEqual => Ok(*i <= j),
Operator::GreaterThan => Ok(*i > j),
Operator::GreaterThanEqual => Ok(*i >= j),
Operator::Is |
Operator::Before |
Operator::After => Result::Err(Error{kind: ErrorKind::Unknown, message: String::from("type error")})
}
}
Result::Err(e) => Result::Err(e)
}
}
Value::Double(d) => {
let e = other.to_double();
match op {
Operator::Equal => Ok(*d == e),
Operator::NotEqual => Ok(*d != e),
Operator::LessThan => Ok(*d < e),
Operator::LessThanEqual => Ok(*d <= e),
Operator::GreaterThan => Ok(*d > e),
Operator::GreaterThanEqual => Ok(*d >= e),
Operator::Is |
Operator::Before |
Operator::After => Result::Err(Error{kind: ErrorKind::Unknown, message: String::from("type error")})
}
}
Value::String(s) => {
let t = other.to_string();
match op {
Operator::Equal => Ok(s.to_string() == t),
Operator::NotEqual => Ok(s.to_string() != t),
Operator::LessThan => Ok(s.to_string() < t),
Operator::LessThanEqual => Ok(s.to_string() <= t),
Operator::GreaterThan => Ok(s.to_string() > t),
Operator::GreaterThanEqual => Ok(s.to_string() >= t),
Operator::Is |
Operator::Before |
Operator::After => Result::Err(Error{kind: ErrorKind::Unknown, message: String::from("type error")})
}
}
_ => Result::Err(Error{kind: ErrorKind::Unknown, message: format!("comparing type \"{}\" is not yet implemented", self.value_type())})
}
}
pub fn value_type(&self) -> &'static str {
match &self {
Value::AnyType => "AnyType",
Value::Untyped => "Untyped",
Value::AnySimpleType => "AnySimpleType",
Value::IDREFS => "IDREFS",
Value::NMTOKENS => "NMTOKENS",
Value::ENTITIES => "ENTITIES",
Value::Numeric => "Numeric",
Value::AnyAtomicType => "AnyAtomicType",
Value::UntypedAtomic => "UntypedAtomic",
Value::Duration => "Duration",
Value::Time => "Time",
Value::Decimal(_) => "Decimal",
Value::Float(_) => "Float",
Value::Double(_) => "Double",
Value::Integer(_) => "Integer",
Value::NonPositiveInteger(_) => "NonPositiveInteger",
Value::NegativeInteger(_) => "NegativeInteger",
Value::Long(_) => "Long",
Value::Int(_) => "Int",
Value::Short(_) => "Short",
Value::Byte(_) => "Byte",
Value::NonNegativeInteger(_) => "NonNegativeInteger",
Value::UnsignedLong(_) => "UnsignedLong",
Value::UnsignedInt(_) => "UnsignedInt",
Value::UnsignedShort(_) => "UnsignedShort",
Value::UnsignedByte(_) => "UnsignedByte",
Value::PositiveInteger(_) => "PositiveInteger",
Value::DateTime => "DateTime",
Value::DateTimeStamp => "DateTimeStamp",
Value::Date => "Date",
Value::String(_) => "String",
Value::NormalizedString(_) => "NormalizedString",
Value::Token => "Token",
Value::Language => "Language",
Value::NMTOKEN => "NMTOKEN",
Value::Name => "Name",
Value::NCName => "NCName",
Value::ID => "ID",
Value::IDREF => "IDREF",
Value::ENTITY => "ENTITY",
Value::Boolean(_) => "boolean",
}
}
}
pub struct NonPositiveInteger {
value: i64,
}
impl NonPositiveInteger {
pub fn new(v: i64) -> Result<Self, Error> {
if v > 0 {
let e = Error {
kind: ErrorKind::TypeError,
message: String::from("nonPositiveInteger must be zero or less"),
};
Err(e)
} else {
let n = NonPositiveInteger {
value: v,
};
Ok(n)
}
}
pub fn value(&self) -> i64 {
self.value
}
}
impl Clone for NonPositiveInteger {
fn clone(&self) -> Self {
NonPositiveInteger::new(self.value).expect("unable to clone NonPositiveInteger")
}
}
pub struct PositiveInteger {
value: i64,
}
impl PositiveInteger {
pub fn new(v: i64) -> Result<Self, Error> {
if v <= 0 {
let e = Error {
kind: ErrorKind::TypeError,
message: String::from("PositiveInteger must be greater than zero"),
};
Err(e)
} else {
let n = PositiveInteger {
value: v,
};
Ok(n)
}
}
pub fn value(&self) -> i64 {
self.value
}
}
impl Clone for PositiveInteger {
fn clone(&self) -> Self {
PositiveInteger::new(self.value).expect("unable to clone PositiveInteger")
}
}
pub struct NonNegativeInteger {
value: i64,
}
impl NonNegativeInteger {
pub fn new(v: i64) -> Result<Self, Error> {
if v < 0 {
let e = Error {
kind: ErrorKind::TypeError,
message: String::from("nonNegativeInteger must be zero or greater"),
};
Err(e)
} else {
let n = NonNegativeInteger {
value: v,
};
Ok(n)
}
}
pub fn value(&self) -> i64 {
self.value
}
}
impl Clone for NonNegativeInteger {
fn clone(&self) -> Self {
NonNegativeInteger::new(self.value).expect("unable to clone NonNegativeInteger")
}
}
pub struct NegativeInteger {
value: i64,
}
impl NegativeInteger {
pub fn new(v: i64) -> Result<Self, Error> {
if v >= 0 {
let e = Error {
kind: ErrorKind::TypeError,
message: String::from("NegativeInteger must be less than zero"),
};
Err(e)
} else {
let n = NegativeInteger {
value: v,
};
Ok(n)
}
}
pub fn value(&self) -> i64 {
self.value
}
}
impl Clone for NegativeInteger {
fn clone(&self) -> Self {
NegativeInteger::new(self.value).expect("unable to clone NegativeInteger")
}
}
pub struct NormalizedString {
value: String,
}
impl NormalizedString {
pub fn new(v: &str) -> Result<Self, Error> {
let n: &[_] = &['\n', '\r', '\t'];
match v.find(n) {
None => Ok(NormalizedString{value: v.to_string()}),
_ => Err(Error {
kind: ErrorKind::TypeError,
message: String::from("value is not a normalized string"),
})
}
}
pub fn value(self) -> String {
self.value.to_string()
}
}
impl Clone for NormalizedString {
fn clone(&self) -> Self {
NormalizedString::new(&self.value.clone()).expect("unable to clone NormalizedString")
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn normalizedstring_valid_empty() {
assert_eq!(NormalizedString::new("").expect("invalid NormalizedString").value, "");
}
#[test]
fn normalizedstring_valid() {
assert_eq!(NormalizedString::new("notinvalid").expect("invalid NormalizedString").value, "notinvalid");
}
#[test]
fn normalizedstring_valid_spaces() {
assert_eq!(NormalizedString::new("not an invalid string").expect("invalid NormalizedString").value, "not an invalid string");
}
#[test]
fn normalizedstring_invalid_tab() {
let r = NormalizedString::new("contains tab character");
assert!(match r {
Ok(_) => panic!("string contains tab character"),
Err(_) => true,
})
}
#[test]
fn normalizedstring_invalid_newline() {
let r = NormalizedString::new("contains newline\ncharacter");
assert!(match r {
Ok(_) => panic!("string contains newline character"),
Err(_) => true,
})
}
#[test]
fn normalizedstring_invalid_cr() {
let r = NormalizedString::new("contains carriage return\rcharacter");
assert!(match r {
Ok(_) => panic!("string contains cr character"),
Err(_) => true,
})
}
#[test]
fn normalizedstring_invalid_all() {
let r = NormalizedString::new("contains all\rforbidden\ncharacters");
assert!(match r {
Ok(_) => panic!("string contains at least one forbidden character"),
Err(_) => true,
})
}
#[test]
fn nonpositiveinteger_valid() {
assert_eq!(NonPositiveInteger::new(-10).expect("invalid NonPositiveInteger").value, -10);
}
#[test]
fn nonpositiveinteger_valid_zero() {
assert_eq!(NonPositiveInteger::new(0).expect("invalid NonPositiveInteger").value, 0);
}
#[test]
fn nonpositiveinteger_invalid() {
let r = NonPositiveInteger::new(10);
assert!(match r {
Ok(_) => panic!("10 is not a nonPositiveInteger"),
Err(_) => true,
})
}
#[test]
fn positiveinteger_valid() {
assert_eq!(PositiveInteger::new(10).expect("invalid PositiveInteger").value, 10);
}
#[test]
fn positiveinteger_invalid_zero() {
let r = PositiveInteger::new(0);
assert!(match r {
Ok(_) => panic!("0 is not a PositiveInteger"),
Err(_) => true,
})
}
#[test]
fn positiveinteger_invalid() {
let r = PositiveInteger::new(-10);
assert!(match r {
Ok(_) => panic!("-10 is not a PositiveInteger"),
Err(_) => true,
})
}
#[test]
fn nonnegativeinteger_valid() {
assert_eq!(NonNegativeInteger::new(10).expect("invalid NonNegativeInteger").value, 10);
}
#[test]
fn nonnegativeinteger_valid_zero() {
assert_eq!(NonNegativeInteger::new(0).expect("invalid NonNegativeInteger").value, 0);
}
#[test]
fn nonnegativeinteger_invalid() {
let r = NonNegativeInteger::new(-10);
assert!(match r {
Ok(_) => panic!("-10 is not a NonNegativeInteger"),
Err(_) => true,
})
}
#[test]
fn negativeinteger_valid() {
assert_eq!(NegativeInteger::new(-10).expect("invalid NegativeInteger").value, -10);
}
#[test]
fn negativeinteger_invalid_zero() {
let r = NegativeInteger::new(0);
assert!(match r {
Ok(_) => panic!("0 is not a NegativeInteger"),
Err(_) => true,
})
}
#[test]
fn negativeinteger_invalid() {
let r = NegativeInteger::new(10);
assert!(match r {
Ok(_) => panic!("10 is not a NegativeInteger"),
Err(_) => true,
})
}
#[test]
fn string_stringvalue() {
assert_eq!(Value::String("foobar".to_string()).to_string(), "foobar")
}
#[test]
fn decimal_stringvalue() {
assert_eq!(Value::Decimal(decimal::d128!(001.23)).to_string(), "1.23")
}
#[test]
fn float_stringvalue() {
assert_eq!(Value::Float(001.2300_f32).to_string(), "1.23")
}
#[test]
fn nonpositiveinteger_stringvalue() {
let npi = NonPositiveInteger::new(-00123).expect("invalid nonPositiveInteger");
let i = Value::NonPositiveInteger(npi);
assert_eq!(i.to_string(), "-123")
}
#[test]
fn nonnegativeinteger_stringvalue() {
let nni = NonNegativeInteger::new(00123).expect("invalid nonNegativeInteger");
let i = Value::NonNegativeInteger(nni);
assert_eq!(i.to_string(), "123")
}
#[test]
fn normalizedstring_stringvalue() {
let ns = NormalizedString::new("foobar").expect("invalid normalizedString");
let i = Value::NormalizedString(ns);
assert_eq!(i.to_string(), "foobar")
}
#[test]
fn bool_value_string_empty() {
assert_eq!(Item::Value(Value::String("".to_string())).to_bool(), false)
}
#[test]
fn bool_value_string_nonempty() {
assert_eq!(Item::Value(Value::String("false".to_string())).to_bool(), true)
}
#[test]
fn bool_value_int_zero() {
assert_eq!(Item::Value(Value::Integer(0)).to_bool(), false)
}
#[test]
fn bool_value_int_nonzero() {
assert_eq!(Item::Value(Value::Integer(42)).to_bool(), true)
}
#[test]
fn int_value_string() {
match Item::Value(Value::String("1".to_string())).to_int() {
Ok(i) => assert_eq!(i, 1),
Err(_) => {
panic!("to_int() failed")
}
}
}
#[test]
fn double_value_string() {
assert_eq!(Item::Value(Value::String("2.0".to_string())).to_double(), 2.0)
}
#[test]
fn value_to_bool_string() {
assert_eq!(Value::String("2".to_string()).to_bool(), true)
}
#[test]
fn value_to_int_string() {
assert_eq!(Value::String("2".to_string()).to_int().expect("cannot convert to integer"), 2)
}
#[test]
fn value_to_double_string() {
assert_eq!(Value::String("3.0".to_string()).to_double(), 3.0)
}
#[test]
fn value_compare_eq() {
assert_eq!(Value::String("3".to_string()).compare(&Item::Value(Value::Double(3.0)), Operator::Equal).expect("unable to compare"), true)
}
#[test]
fn value_compare_ne() {
assert_eq!(Value::String("3".to_string()).compare(&Item::Value(Value::Double(3.0)), Operator::NotEqual).expect("unable to compare"), false)
}
#[test]
fn sequence() {
let _s = Sequence::new();
assert!(true)
}
#[test]
fn sequence_one() {
let mut s = Sequence::new();
s.new_value(Value::String("one".to_string()));
let mut t = Sequence::new();
t.add(&s[0]);
assert!(Rc::ptr_eq(&s[0], &t[0]))
}
#[test]
fn op_equal() {
assert_eq!(Operator::Equal.to_string(), "=")
}
#[test]
fn op_notequal() {
assert_eq!(Operator::NotEqual.to_string(), "!=")
}
#[test]
fn op_lt() {
assert_eq!(Operator::LessThan.to_string(), "<")
}
#[test]
fn op_ltequal() {
assert_eq!(Operator::LessThanEqual.to_string(), "<=")
}
#[test]
fn op_gt() {
assert_eq!(Operator::GreaterThan.to_string(), ">")
}
#[test]
fn op_gtequal() {
assert_eq!(Operator::GreaterThanEqual.to_string(), ">=")
}
#[test]
fn op_is() {
assert_eq!(Operator::Is.to_string(), "is")
}
#[test]
fn op_before() {
assert_eq!(Operator::Before.to_string(), "<<")
}
#[test]
fn op_after() {
assert_eq!(Operator::After.to_string(), ">>")
}
}