xml/
common.rs

1//! Contains common types and functions used throughout the library.
2
3use std::fmt;
4
5/// Represents a position inside some textual document.
6#[derive(Copy, Clone, PartialEq, Eq)]
7pub struct TextPosition {
8    /// Row, counting from 0
9    pub row: u64,
10    /// Column, counting from 0
11    pub column: u64,
12}
13
14impl TextPosition {
15    /// Creates a new position initialized to the beginning of the document
16    #[inline]
17    pub fn new() -> TextPosition {
18        TextPosition { row: 0, column: 0 }
19    }
20
21    /// Advances the position in a line
22    #[inline]
23    pub fn advance(&mut self, count: u8) {
24        self.column += count as u64;
25    }
26
27    /// Advances the position in a line to the next tab position
28    #[inline]
29    pub fn advance_to_tab(&mut self, width: u8) {
30        let width = width as u64;
31        self.column += width - self.column % width
32    }
33
34    /// Advances the position to the beginning of the next line
35    #[inline]
36    pub fn new_line(&mut self) {
37        self.column = 0;
38        self.row += 1;
39    }
40}
41
42impl fmt::Debug for TextPosition {
43    #[inline]
44    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
45        write!(f, "{}:{}", self.row + 1, self.column + 1)
46    }
47}
48
49impl fmt::Display for TextPosition {
50    #[inline]
51    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
52        write!(f, "{}:{}", self.row + 1, self.column + 1)
53    }
54}
55
56/// Get the position in the document corresponding to the object
57///
58/// This trait is implemented by parsers, lexers and errors.
59pub trait Position {
60    /// Returns the current position or a position corresponding to the object.
61    fn position(&self) -> TextPosition;
62}
63
64impl Position for TextPosition {
65    #[inline]
66    fn position(&self) -> TextPosition {
67        *self
68    }
69}
70
71/// XML version enumeration.
72#[derive(Copy, Clone, PartialEq, Eq)]
73pub enum XmlVersion {
74    /// XML version 1.0.
75    Version10,
76
77    /// XML version 1.1.
78    Version11
79}
80
81impl fmt::Display for XmlVersion {
82    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
83        match *self {
84            XmlVersion::Version10 => write!(f, "1.0"),
85            XmlVersion::Version11 => write!(f, "1.1")
86        }
87    }
88}
89
90impl fmt::Debug for XmlVersion {
91    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
92        fmt::Display::fmt(self, f)
93    }
94}
95
96/// Checks whether the given character is a white space character (`S`)
97/// as is defined by XML 1.1 specification, [section 2.3][1].
98///
99/// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-common-syn
100pub fn is_whitespace_char(c: char) -> bool {
101    match c {
102        '\x20' | '\x09' | '\x0d' | '\x0a' => true,
103        _ => false
104    }
105}
106
107/// Checks whether the given string is compound only by white space
108/// characters (`S`) using the previous is_whitespace_char to check
109/// all characters of this string
110pub fn is_whitespace_str(s: &str) -> bool {
111    s.chars().all(is_whitespace_char)
112}
113
114/// Checks whether the given character is a name start character (`NameStartChar`)
115/// as is defined by XML 1.1 specification, [section 2.3][1].
116///
117/// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-common-syn
118pub fn is_name_start_char(c: char) -> bool {
119    match c {
120        ':' | 'A'...'Z' | '_' | 'a'...'z' |
121        '\u{C0}'...'\u{D6}' | '\u{D8}'...'\u{F6}' | '\u{F8}'...'\u{2FF}' |
122        '\u{370}'...'\u{37D}' | '\u{37F}'...'\u{1FFF}' |
123        '\u{200C}'...'\u{200D}' | '\u{2070}'...'\u{218F}' |
124        '\u{2C00}'...'\u{2FEF}' | '\u{3001}'...'\u{D7FF}' |
125        '\u{F900}'...'\u{FDCF}' | '\u{FDF0}'...'\u{FFFD}' |
126        '\u{10000}'...'\u{EFFFF}' => true,
127        _ => false
128    }
129}
130
131/// Checks whether the given character is a name character (`NameChar`)
132/// as is defined by XML 1.1 specification, [section 2.3][1].
133///
134/// [1]: http://www.w3.org/TR/2006/REC-xml11-20060816/#sec-common-syn
135pub fn is_name_char(c: char) -> bool {
136    match c {
137        _ if is_name_start_char(c) => true,
138        '-' | '.' | '0'...'9' | '\u{B7}' |
139        '\u{300}'...'\u{3F6}' | '\u{203F}'...'\u{2040}' => true,
140        _ => false
141    }
142}