use super::facets::FacetSet;
use super::{PrimitiveTypeCode, XmlTypeCode};
use crate::ids::{NameId, SimpleTypeKey, TypeKey};
use crate::parser::location::SourceRef;
use crate::schema::model::DerivationSet;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SimpleTypeVariety {
Atomic,
List,
Union,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
pub enum SimpleTypeDerivationMethod {
#[default]
Restriction,
List,
Union,
}
#[derive(Debug, Clone)]
pub enum SimpleTypeRef {
Resolved(SimpleTypeKey),
Unresolved {
namespace: Option<NameId>,
local_name: NameId,
},
BuiltIn(BuiltInType),
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum BuiltInType {
AnySimpleType,
AnyAtomicType,
UntypedAtomic,
String,
Boolean,
Decimal,
Float,
Double,
Duration,
DateTime,
Time,
Date,
GYearMonth,
GYear,
GMonthDay,
GDay,
GMonth,
HexBinary,
Base64Binary,
AnyURI,
QName,
NOTATION,
NormalizedString,
Token,
Language,
NMTOKEN,
NMTOKENS,
Name,
NCName,
ID,
IDREF,
IDREFS,
ENTITY,
ENTITIES,
Integer,
NonPositiveInteger,
NegativeInteger,
Long,
Int,
Short,
Byte,
NonNegativeInteger,
UnsignedLong,
UnsignedInt,
UnsignedShort,
UnsignedByte,
PositiveInteger,
YearMonthDuration,
DayTimeDuration,
DateTimeStamp,
XsError,
}
impl BuiltInType {
#[inline]
pub fn local_name(&self) -> &'static str {
self.type_code()
.local_name()
.expect("BuiltInType always has a local name")
}
#[inline]
pub fn type_code(&self) -> XmlTypeCode {
XmlTypeCode::from(*self)
}
#[inline]
pub fn primitive_type_code(&self) -> Option<PrimitiveTypeCode> {
PrimitiveTypeCode::from_type_code(self.type_code())
}
#[inline]
pub fn is_primitive(&self) -> bool {
matches!(
self,
Self::String
| Self::Boolean
| Self::Decimal
| Self::Float
| Self::Double
| Self::Duration
| Self::DateTime
| Self::Time
| Self::Date
| Self::GYearMonth
| Self::GYear
| Self::GMonthDay
| Self::GDay
| Self::GMonth
| Self::HexBinary
| Self::Base64Binary
| Self::AnyURI
| Self::QName
| Self::NOTATION
)
}
#[inline]
pub fn is_list(&self) -> bool {
matches!(self, Self::NMTOKENS | Self::IDREFS | Self::ENTITIES)
}
#[inline]
pub fn is_xsd11(&self) -> bool {
matches!(
self,
Self::AnyAtomicType
| Self::UntypedAtomic
| Self::YearMonthDuration
| Self::DayTimeDuration
| Self::DateTimeStamp
| Self::XsError
)
}
pub fn from_local_name(name: &str) -> Option<BuiltInType> {
XmlTypeCode::from_local_name(name).and_then(|code| Self::try_from(code).ok())
}
pub fn all() -> impl Iterator<Item = BuiltInType> {
[
Self::AnySimpleType,
Self::AnyAtomicType,
Self::UntypedAtomic,
Self::String,
Self::Boolean,
Self::Decimal,
Self::Float,
Self::Double,
Self::Duration,
Self::DateTime,
Self::Time,
Self::Date,
Self::GYearMonth,
Self::GYear,
Self::GMonthDay,
Self::GDay,
Self::GMonth,
Self::HexBinary,
Self::Base64Binary,
Self::AnyURI,
Self::QName,
Self::NOTATION,
Self::NormalizedString,
Self::Token,
Self::Language,
Self::NMTOKEN,
Self::NMTOKENS,
Self::Name,
Self::NCName,
Self::ID,
Self::IDREF,
Self::IDREFS,
Self::ENTITY,
Self::ENTITIES,
Self::Integer,
Self::NonPositiveInteger,
Self::NegativeInteger,
Self::Long,
Self::Int,
Self::Short,
Self::Byte,
Self::NonNegativeInteger,
Self::UnsignedLong,
Self::UnsignedInt,
Self::UnsignedShort,
Self::UnsignedByte,
Self::PositiveInteger,
Self::YearMonthDuration,
Self::DayTimeDuration,
Self::DateTimeStamp,
Self::XsError,
]
.into_iter()
}
}
impl From<BuiltInType> for XmlTypeCode {
fn from(builtin: BuiltInType) -> Self {
match builtin {
BuiltInType::AnySimpleType => XmlTypeCode::AnySimpleType,
BuiltInType::AnyAtomicType => XmlTypeCode::AnyAtomicType,
BuiltInType::UntypedAtomic => XmlTypeCode::UntypedAtomic,
BuiltInType::String => XmlTypeCode::String,
BuiltInType::Boolean => XmlTypeCode::Boolean,
BuiltInType::Decimal => XmlTypeCode::Decimal,
BuiltInType::Float => XmlTypeCode::Float,
BuiltInType::Double => XmlTypeCode::Double,
BuiltInType::Duration => XmlTypeCode::Duration,
BuiltInType::DateTime => XmlTypeCode::DateTime,
BuiltInType::Time => XmlTypeCode::Time,
BuiltInType::Date => XmlTypeCode::Date,
BuiltInType::GYearMonth => XmlTypeCode::GYearMonth,
BuiltInType::GYear => XmlTypeCode::GYear,
BuiltInType::GMonthDay => XmlTypeCode::GMonthDay,
BuiltInType::GDay => XmlTypeCode::GDay,
BuiltInType::GMonth => XmlTypeCode::GMonth,
BuiltInType::HexBinary => XmlTypeCode::HexBinary,
BuiltInType::Base64Binary => XmlTypeCode::Base64Binary,
BuiltInType::AnyURI => XmlTypeCode::AnyUri,
BuiltInType::QName => XmlTypeCode::QName,
BuiltInType::NOTATION => XmlTypeCode::Notation,
BuiltInType::NormalizedString => XmlTypeCode::NormalizedString,
BuiltInType::Token => XmlTypeCode::Token,
BuiltInType::Language => XmlTypeCode::Language,
BuiltInType::NMTOKEN => XmlTypeCode::NmToken,
BuiltInType::NMTOKENS => XmlTypeCode::NmTokens,
BuiltInType::Name => XmlTypeCode::Name,
BuiltInType::NCName => XmlTypeCode::NCName,
BuiltInType::ID => XmlTypeCode::Id,
BuiltInType::IDREF => XmlTypeCode::IdRef,
BuiltInType::IDREFS => XmlTypeCode::IdRefs,
BuiltInType::ENTITY => XmlTypeCode::Entity,
BuiltInType::ENTITIES => XmlTypeCode::Entities,
BuiltInType::Integer => XmlTypeCode::Integer,
BuiltInType::NonPositiveInteger => XmlTypeCode::NonPositiveInteger,
BuiltInType::NegativeInteger => XmlTypeCode::NegativeInteger,
BuiltInType::Long => XmlTypeCode::Long,
BuiltInType::Int => XmlTypeCode::Int,
BuiltInType::Short => XmlTypeCode::Short,
BuiltInType::Byte => XmlTypeCode::Byte,
BuiltInType::NonNegativeInteger => XmlTypeCode::NonNegativeInteger,
BuiltInType::UnsignedLong => XmlTypeCode::UnsignedLong,
BuiltInType::UnsignedInt => XmlTypeCode::UnsignedInt,
BuiltInType::UnsignedShort => XmlTypeCode::UnsignedShort,
BuiltInType::UnsignedByte => XmlTypeCode::UnsignedByte,
BuiltInType::PositiveInteger => XmlTypeCode::PositiveInteger,
BuiltInType::YearMonthDuration => XmlTypeCode::YearMonthDuration,
BuiltInType::DayTimeDuration => XmlTypeCode::DayTimeDuration,
BuiltInType::DateTimeStamp => XmlTypeCode::DateTimeStamp,
BuiltInType::XsError => XmlTypeCode::Error,
}
}
}
impl TryFrom<XmlTypeCode> for BuiltInType {
type Error = ();
fn try_from(code: XmlTypeCode) -> Result<Self, Self::Error> {
match code {
XmlTypeCode::AnySimpleType => Ok(BuiltInType::AnySimpleType),
XmlTypeCode::AnyAtomicType => Ok(BuiltInType::AnyAtomicType),
XmlTypeCode::UntypedAtomic => Ok(BuiltInType::UntypedAtomic),
XmlTypeCode::String => Ok(BuiltInType::String),
XmlTypeCode::Boolean => Ok(BuiltInType::Boolean),
XmlTypeCode::Decimal => Ok(BuiltInType::Decimal),
XmlTypeCode::Float => Ok(BuiltInType::Float),
XmlTypeCode::Double => Ok(BuiltInType::Double),
XmlTypeCode::Duration => Ok(BuiltInType::Duration),
XmlTypeCode::DateTime => Ok(BuiltInType::DateTime),
XmlTypeCode::Time => Ok(BuiltInType::Time),
XmlTypeCode::Date => Ok(BuiltInType::Date),
XmlTypeCode::GYearMonth => Ok(BuiltInType::GYearMonth),
XmlTypeCode::GYear => Ok(BuiltInType::GYear),
XmlTypeCode::GMonthDay => Ok(BuiltInType::GMonthDay),
XmlTypeCode::GDay => Ok(BuiltInType::GDay),
XmlTypeCode::GMonth => Ok(BuiltInType::GMonth),
XmlTypeCode::HexBinary => Ok(BuiltInType::HexBinary),
XmlTypeCode::Base64Binary => Ok(BuiltInType::Base64Binary),
XmlTypeCode::AnyUri => Ok(BuiltInType::AnyURI),
XmlTypeCode::QName => Ok(BuiltInType::QName),
XmlTypeCode::Notation => Ok(BuiltInType::NOTATION),
XmlTypeCode::NormalizedString => Ok(BuiltInType::NormalizedString),
XmlTypeCode::Token => Ok(BuiltInType::Token),
XmlTypeCode::Language => Ok(BuiltInType::Language),
XmlTypeCode::NmToken => Ok(BuiltInType::NMTOKEN),
XmlTypeCode::NmTokens => Ok(BuiltInType::NMTOKENS),
XmlTypeCode::Name => Ok(BuiltInType::Name),
XmlTypeCode::NCName => Ok(BuiltInType::NCName),
XmlTypeCode::Id => Ok(BuiltInType::ID),
XmlTypeCode::IdRef => Ok(BuiltInType::IDREF),
XmlTypeCode::IdRefs => Ok(BuiltInType::IDREFS),
XmlTypeCode::Entity => Ok(BuiltInType::ENTITY),
XmlTypeCode::Entities => Ok(BuiltInType::ENTITIES),
XmlTypeCode::Integer => Ok(BuiltInType::Integer),
XmlTypeCode::NonPositiveInteger => Ok(BuiltInType::NonPositiveInteger),
XmlTypeCode::NegativeInteger => Ok(BuiltInType::NegativeInteger),
XmlTypeCode::Long => Ok(BuiltInType::Long),
XmlTypeCode::Int => Ok(BuiltInType::Int),
XmlTypeCode::Short => Ok(BuiltInType::Short),
XmlTypeCode::Byte => Ok(BuiltInType::Byte),
XmlTypeCode::NonNegativeInteger => Ok(BuiltInType::NonNegativeInteger),
XmlTypeCode::UnsignedLong => Ok(BuiltInType::UnsignedLong),
XmlTypeCode::UnsignedInt => Ok(BuiltInType::UnsignedInt),
XmlTypeCode::UnsignedShort => Ok(BuiltInType::UnsignedShort),
XmlTypeCode::UnsignedByte => Ok(BuiltInType::UnsignedByte),
XmlTypeCode::PositiveInteger => Ok(BuiltInType::PositiveInteger),
XmlTypeCode::YearMonthDuration => Ok(BuiltInType::YearMonthDuration),
XmlTypeCode::DayTimeDuration => Ok(BuiltInType::DayTimeDuration),
XmlTypeCode::DateTimeStamp => Ok(BuiltInType::DateTimeStamp),
XmlTypeCode::Error => Ok(BuiltInType::XsError),
_ => Err(()),
}
}
}
#[derive(Debug, Clone)]
pub struct SimpleTypeDef {
pub name: Option<NameId>,
pub target_namespace: Option<NameId>,
pub source: Option<SourceRef>,
pub variety: SimpleTypeVariety,
pub derivation_method: SimpleTypeDerivationMethod,
pub base_type: Option<SimpleTypeRef>,
pub item_type: Option<SimpleTypeRef>,
pub member_types: Vec<SimpleTypeRef>,
pub facets: FacetSet,
pub type_code: XmlTypeCode,
pub primitive_type: Option<PrimitiveTypeCode>,
pub final_derivation: DerivationSet,
pub id: Option<String>,
}
impl SimpleTypeDef {
pub fn new_restriction(
name: Option<NameId>,
target_namespace: Option<NameId>,
base_type: SimpleTypeRef,
) -> Self {
Self {
name,
target_namespace,
source: None,
variety: SimpleTypeVariety::Atomic,
derivation_method: SimpleTypeDerivationMethod::Restriction,
base_type: Some(base_type),
item_type: None,
member_types: Vec::new(),
facets: FacetSet::new(),
type_code: XmlTypeCode::None,
primitive_type: None,
final_derivation: DerivationSet::empty(),
id: None,
}
}
pub fn new_list(
name: Option<NameId>,
target_namespace: Option<NameId>,
item_type: SimpleTypeRef,
) -> Self {
Self {
name,
target_namespace,
source: None,
variety: SimpleTypeVariety::List,
derivation_method: SimpleTypeDerivationMethod::List,
base_type: None,
item_type: Some(item_type),
member_types: Vec::new(),
facets: FacetSet::new(),
type_code: XmlTypeCode::None,
primitive_type: None, final_derivation: DerivationSet::empty(),
id: None,
}
}
pub fn new_union(
name: Option<NameId>,
target_namespace: Option<NameId>,
member_types: Vec<SimpleTypeRef>,
) -> Self {
Self {
name,
target_namespace,
source: None,
variety: SimpleTypeVariety::Union,
derivation_method: SimpleTypeDerivationMethod::Union,
base_type: None,
item_type: None,
member_types,
facets: FacetSet::new(),
type_code: XmlTypeCode::None,
primitive_type: None, final_derivation: DerivationSet::empty(),
id: None,
}
}
pub fn new_builtin(
name: NameId,
target_namespace: Option<NameId>,
builtin: BuiltInType,
) -> Self {
let type_code = builtin.type_code();
let primitive_type = builtin.primitive_type_code();
let variety = if builtin.is_list() {
SimpleTypeVariety::List
} else {
SimpleTypeVariety::Atomic
};
let derivation_method = if builtin.is_list() {
SimpleTypeDerivationMethod::List
} else {
SimpleTypeDerivationMethod::Restriction
};
Self {
name: Some(name),
target_namespace,
source: None,
variety,
derivation_method,
base_type: None, item_type: None, member_types: Vec::new(),
facets: default_facets_for_builtin(builtin),
type_code,
primitive_type,
final_derivation: DerivationSet::empty(),
id: None,
}
}
pub fn is_anonymous(&self) -> bool {
self.name.is_none()
}
pub fn is_global(&self) -> bool {
self.name.is_some()
}
pub fn is_atomic(&self) -> bool {
self.variety == SimpleTypeVariety::Atomic
}
pub fn is_list(&self) -> bool {
self.variety == SimpleTypeVariety::List
}
pub fn is_union(&self) -> bool {
self.variety == SimpleTypeVariety::Union
}
pub fn is_restriction(&self) -> bool {
self.derivation_method == SimpleTypeDerivationMethod::Restriction
}
pub fn get_primitive_type(&self) -> Option<PrimitiveTypeCode> {
self.primitive_type
}
pub fn get_type_code(&self) -> XmlTypeCode {
self.type_code
}
pub fn type_key(&self, key: SimpleTypeKey) -> TypeKey {
TypeKey::Simple(key)
}
}
pub fn default_facets_for_builtin(builtin: BuiltInType) -> FacetSet {
effective_arena_facets_for_builtin(builtin)
}
pub fn effective_arena_facets_for_builtin(builtin: BuiltInType) -> FacetSet {
use super::facets::{FacetFixed, WhitespaceMode};
let mut facets = FacetSet::new();
match builtin {
BuiltInType::String => {
facets.set_whitespace(WhitespaceMode::Preserve, FacetFixed::Default, None);
}
BuiltInType::NormalizedString => {
facets.set_whitespace(WhitespaceMode::Replace, FacetFixed::Default, None);
}
BuiltInType::AnySimpleType | BuiltInType::AnyAtomicType | BuiltInType::XsError => {}
_ => {
facets.set_whitespace(WhitespaceMode::Collapse, FacetFixed::Fixed, None);
}
}
if let Some((lo, hi)) = integer_hierarchy_bounds(builtin) {
facets.set_fraction_digits(0, FacetFixed::Fixed, None);
if let Some(v) = lo {
facets.set_min_inclusive(v, FacetFixed::Default, None);
}
if let Some(v) = hi {
facets.set_max_inclusive(v, FacetFixed::Default, None);
}
}
if matches!(
builtin,
BuiltInType::IDREFS | BuiltInType::NMTOKENS | BuiltInType::ENTITIES
) {
facets.set_min_length(1, FacetFixed::Default, None);
}
facets
}
fn integer_hierarchy_bounds(builtin: BuiltInType) -> Option<(Option<String>, Option<String>)> {
let bounds = match builtin {
BuiltInType::Integer => (None, None),
BuiltInType::NonPositiveInteger => (None, Some("0".to_string())),
BuiltInType::NegativeInteger => (None, Some("-1".to_string())),
BuiltInType::NonNegativeInteger => (Some("0".to_string()), None),
BuiltInType::PositiveInteger => (Some("1".to_string()), None),
BuiltInType::Long => (Some(i64::MIN.to_string()), Some(i64::MAX.to_string())),
BuiltInType::Int => (Some(i32::MIN.to_string()), Some(i32::MAX.to_string())),
BuiltInType::Short => (Some(i16::MIN.to_string()), Some(i16::MAX.to_string())),
BuiltInType::Byte => (Some(i8::MIN.to_string()), Some(i8::MAX.to_string())),
BuiltInType::UnsignedLong => (Some("0".to_string()), Some(u64::MAX.to_string())),
BuiltInType::UnsignedInt => (Some("0".to_string()), Some(u32::MAX.to_string())),
BuiltInType::UnsignedShort => (Some("0".to_string()), Some(u16::MAX.to_string())),
BuiltInType::UnsignedByte => (Some("0".to_string()), Some(u8::MAX.to_string())),
_ => return None,
};
Some(bounds)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_builtin_type_names() {
assert_eq!(BuiltInType::String.local_name(), "string");
assert_eq!(BuiltInType::Integer.local_name(), "integer");
assert_eq!(BuiltInType::DateTime.local_name(), "dateTime");
assert_eq!(BuiltInType::AnyURI.local_name(), "anyURI");
assert_eq!(BuiltInType::NMTOKEN.local_name(), "NMTOKEN");
assert_eq!(BuiltInType::UntypedAtomic.local_name(), "untypedAtomic");
assert_eq!(
BuiltInType::YearMonthDuration.local_name(),
"yearMonthDuration"
);
}
#[test]
fn test_builtin_type_parsing() {
assert_eq!(
BuiltInType::from_local_name("string"),
Some(BuiltInType::String)
);
assert_eq!(
BuiltInType::from_local_name("integer"),
Some(BuiltInType::Integer)
);
assert_eq!(
BuiltInType::from_local_name("untypedAtomic"),
Some(BuiltInType::UntypedAtomic)
);
assert_eq!(
BuiltInType::from_local_name("yearMonthDuration"),
Some(BuiltInType::YearMonthDuration)
);
assert_eq!(BuiltInType::from_local_name("nonExistent"), None);
assert_eq!(BuiltInType::from_local_name("anyType"), None);
}
#[test]
fn test_builtin_is_primitive() {
assert!(BuiltInType::String.is_primitive());
assert!(BuiltInType::Decimal.is_primitive());
assert!(BuiltInType::Duration.is_primitive());
assert!(!BuiltInType::Integer.is_primitive()); assert!(!BuiltInType::NCName.is_primitive()); assert!(!BuiltInType::AnySimpleType.is_primitive()); assert!(!BuiltInType::NMTOKENS.is_primitive()); }
#[test]
fn test_builtin_is_list() {
assert!(BuiltInType::NMTOKENS.is_list());
assert!(BuiltInType::IDREFS.is_list());
assert!(BuiltInType::ENTITIES.is_list());
assert!(!BuiltInType::NMTOKEN.is_list());
assert!(!BuiltInType::String.is_list());
}
#[test]
fn test_builtin_is_xsd11() {
assert!(BuiltInType::AnyAtomicType.is_xsd11());
assert!(BuiltInType::UntypedAtomic.is_xsd11());
assert!(BuiltInType::YearMonthDuration.is_xsd11());
assert!(BuiltInType::DayTimeDuration.is_xsd11());
assert!(BuiltInType::DateTimeStamp.is_xsd11());
assert!(!BuiltInType::String.is_xsd11());
assert!(!BuiltInType::DateTime.is_xsd11());
}
#[test]
fn test_builtin_type_code() {
assert_eq!(BuiltInType::String.type_code(), XmlTypeCode::String);
assert_eq!(BuiltInType::Integer.type_code(), XmlTypeCode::Integer);
assert_eq!(BuiltInType::NMTOKEN.type_code(), XmlTypeCode::NmToken);
assert_eq!(BuiltInType::AnyURI.type_code(), XmlTypeCode::AnyUri);
}
#[test]
fn test_builtin_primitive_type_code() {
assert_eq!(
BuiltInType::String.primitive_type_code(),
Some(PrimitiveTypeCode::String)
);
assert_eq!(
BuiltInType::NCName.primitive_type_code(),
Some(PrimitiveTypeCode::String)
);
assert_eq!(
BuiltInType::Integer.primitive_type_code(),
Some(PrimitiveTypeCode::Decimal)
);
assert_eq!(
BuiltInType::Duration.primitive_type_code(),
Some(PrimitiveTypeCode::Duration)
);
assert_eq!(
BuiltInType::YearMonthDuration.primitive_type_code(),
Some(PrimitiveTypeCode::Duration)
);
assert_eq!(BuiltInType::AnySimpleType.primitive_type_code(), None);
assert_eq!(BuiltInType::NMTOKENS.primitive_type_code(), None);
}
#[test]
fn test_builtin_to_xml_type_code_conversion() {
assert_eq!(XmlTypeCode::from(BuiltInType::String), XmlTypeCode::String);
assert_eq!(
XmlTypeCode::from(BuiltInType::NOTATION),
XmlTypeCode::Notation
);
assert_eq!(XmlTypeCode::from(BuiltInType::AnyURI), XmlTypeCode::AnyUri);
assert_eq!(
XmlTypeCode::from(BuiltInType::NMTOKEN),
XmlTypeCode::NmToken
);
}
#[test]
fn test_xml_type_code_to_builtin_conversion() {
assert_eq!(
BuiltInType::try_from(XmlTypeCode::String),
Ok(BuiltInType::String)
);
assert_eq!(
BuiltInType::try_from(XmlTypeCode::Notation),
Ok(BuiltInType::NOTATION)
);
assert_eq!(
BuiltInType::try_from(XmlTypeCode::AnyUri),
Ok(BuiltInType::AnyURI)
);
assert_eq!(
BuiltInType::try_from(XmlTypeCode::NmToken),
Ok(BuiltInType::NMTOKEN)
);
assert!(BuiltInType::try_from(XmlTypeCode::None).is_err());
assert!(BuiltInType::try_from(XmlTypeCode::Element).is_err());
assert!(BuiltInType::try_from(XmlTypeCode::AnyType).is_err());
}
#[test]
fn test_builtin_roundtrip_conversion() {
for builtin in BuiltInType::all() {
let code = XmlTypeCode::from(builtin);
let back = BuiltInType::try_from(code).expect("Should convert back");
assert_eq!(back, builtin, "Roundtrip failed for {:?}", builtin);
}
}
#[test]
fn test_builtin_all_count() {
assert_eq!(BuiltInType::all().count(), 51);
}
#[test]
fn test_simple_type_restriction() {
let st = SimpleTypeDef::new_restriction(
Some(NameId(1)),
Some(NameId(2)),
SimpleTypeRef::BuiltIn(BuiltInType::String),
);
assert_eq!(st.variety, SimpleTypeVariety::Atomic);
assert_eq!(
st.derivation_method,
SimpleTypeDerivationMethod::Restriction
);
assert!(st.is_global());
assert!(st.is_atomic());
assert!(st.is_restriction());
assert!(st.base_type.is_some());
assert_eq!(st.type_code, XmlTypeCode::None); assert!(st.primitive_type.is_none()); }
#[test]
fn test_simple_type_list() {
let st = SimpleTypeDef::new_list(None, None, SimpleTypeRef::BuiltIn(BuiltInType::Integer));
assert_eq!(st.variety, SimpleTypeVariety::List);
assert_eq!(st.derivation_method, SimpleTypeDerivationMethod::List);
assert!(st.is_anonymous());
assert!(st.is_list());
assert!(st.item_type.is_some());
assert!(st.primitive_type.is_none()); }
#[test]
fn test_simple_type_union() {
let st = SimpleTypeDef::new_union(
Some(NameId(1)),
None,
vec![
SimpleTypeRef::BuiltIn(BuiltInType::String),
SimpleTypeRef::BuiltIn(BuiltInType::Integer),
],
);
assert_eq!(st.variety, SimpleTypeVariety::Union);
assert_eq!(st.derivation_method, SimpleTypeDerivationMethod::Union);
assert!(st.is_union());
assert_eq!(st.member_types.len(), 2);
assert!(st.primitive_type.is_none()); }
#[test]
fn test_simple_type_builtin_atomic() {
let st = SimpleTypeDef::new_builtin(NameId(1), Some(NameId(2)), BuiltInType::String);
assert_eq!(st.variety, SimpleTypeVariety::Atomic);
assert_eq!(
st.derivation_method,
SimpleTypeDerivationMethod::Restriction
);
assert!(st.is_atomic());
assert_eq!(st.type_code, XmlTypeCode::String);
assert_eq!(st.primitive_type, Some(PrimitiveTypeCode::String));
}
#[test]
fn test_simple_type_builtin_list() {
let st = SimpleTypeDef::new_builtin(NameId(1), Some(NameId(2)), BuiltInType::NMTOKENS);
assert_eq!(st.variety, SimpleTypeVariety::List);
assert_eq!(st.derivation_method, SimpleTypeDerivationMethod::List);
assert!(st.is_list());
assert_eq!(st.type_code, XmlTypeCode::NmTokens);
assert!(st.primitive_type.is_none()); }
#[test]
fn test_simple_type_builtin_derived() {
let st = SimpleTypeDef::new_builtin(NameId(1), Some(NameId(2)), BuiltInType::Integer);
assert_eq!(st.type_code, XmlTypeCode::Integer);
assert_eq!(st.primitive_type, Some(PrimitiveTypeCode::Decimal));
}
#[test]
fn test_simple_type_derivation_method_default() {
assert_eq!(
SimpleTypeDerivationMethod::default(),
SimpleTypeDerivationMethod::Restriction
);
}
#[test]
fn test_simple_type_variety_copy() {
let variety = SimpleTypeVariety::Atomic;
let copy = variety;
assert_eq!(variety, copy);
}
#[test]
fn test_default_facets() {
let string_facets = default_facets_for_builtin(BuiltInType::String);
assert!(string_facets.whitespace.is_some());
let int_facets = default_facets_for_builtin(BuiltInType::Integer);
assert!(int_facets.whitespace.is_some());
}
#[test]
fn test_simple_type_helper_methods() {
let restriction = SimpleTypeDef::new_restriction(
Some(NameId(1)),
None,
SimpleTypeRef::BuiltIn(BuiltInType::String),
);
assert!(restriction.is_atomic());
assert!(!restriction.is_list());
assert!(!restriction.is_union());
assert!(restriction.is_restriction());
let list = SimpleTypeDef::new_list(None, None, SimpleTypeRef::BuiltIn(BuiltInType::String));
assert!(!list.is_atomic());
assert!(list.is_list());
assert!(!list.is_union());
let union = SimpleTypeDef::new_union(
None,
None,
vec![SimpleTypeRef::BuiltIn(BuiltInType::String)],
);
assert!(!union.is_atomic());
assert!(!union.is_list());
assert!(union.is_union());
}
#[test]
fn test_simple_type_get_type_code() {
let st = SimpleTypeDef::new_builtin(NameId(1), None, BuiltInType::DateTime);
assert_eq!(st.get_type_code(), XmlTypeCode::DateTime);
}
#[test]
fn test_simple_type_get_primitive_type() {
let st = SimpleTypeDef::new_builtin(NameId(1), None, BuiltInType::NCName);
assert_eq!(st.get_primitive_type(), Some(PrimitiveTypeCode::String));
let list_st = SimpleTypeDef::new_builtin(NameId(2), None, BuiltInType::IDREFS);
assert_eq!(list_st.get_primitive_type(), None);
}
}