diff --git a/lib/xml_schema_validator/src/lib.rs b/lib/xml_schema_validator/src/lib.rs index 2f400f0..8c39441 100644 --- a/lib/xml_schema_validator/src/lib.rs +++ b/lib/xml_schema_validator/src/lib.rs @@ -8,6 +8,7 @@ mod python; mod schema; mod token; +use std::sync::Arc; use error::Error; use token::*; @@ -26,8 +27,11 @@ impl XmlSchemaValidator { /// Create a new validator with the given schema text pub fn new(schema_text: &str) -> Result { let schema: schema::XsSchema = quick_xml::de::from_str(schema_text)?; - let current_tokens = schema.xs_element.iter().map(|element| { - Token::StartOfFile(StartOfFile::new(element.clone())) + let schema_arc = Arc::new(schema); + + let current_tokens = schema_arc.xs_element.iter().map(|element| { + let element_arc = Arc::new(element.clone()); + Token::StartOfFile(StartOfFile::new(element_arc)) }).collect(); Ok(Self { @@ -46,7 +50,7 @@ impl XmlSchemaValidator { /// Append a single character to the validator fn append_char(&mut self, c: char) -> Result<()> { let mut new_tokens = vec![]; - for token in self.current_tokens.clone() { + for token in self.current_tokens.drain(..) { new_tokens.append(&mut token.append(c)); } if new_tokens.is_empty() { diff --git a/lib/xml_schema_validator/src/token/element_close_end.rs b/lib/xml_schema_validator/src/token/element_close_end.rs index 74566f9..1fc96da 100644 --- a/lib/xml_schema_validator/src/token/element_close_end.rs +++ b/lib/xml_schema_validator/src/token/element_close_end.rs @@ -1,6 +1,6 @@ use crate::*; -/// Represents +/// Represents the end of a closing element tag #[derive(Clone, Debug)] pub struct ElementCloseEnd { } @@ -11,7 +11,7 @@ impl ElementCloseEnd { } } - pub fn append(&self, c: char) -> Vec { + pub fn append(self, c: char) -> Vec { if '>' == c { vec![Token::EndOfFile(EndOfFile::new())] } else { diff --git a/lib/xml_schema_validator/src/token/element_close_name.rs b/lib/xml_schema_validator/src/token/element_close_name.rs index 8b4ac89..391f627 100644 --- a/lib/xml_schema_validator/src/token/element_close_name.rs +++ b/lib/xml_schema_validator/src/token/element_close_name.rs @@ -1,3 +1,4 @@ +use std::sync::Arc; use crate::*; /// Represents a closing element tag that is in the process of being parsed @@ -5,22 +6,22 @@ use crate::*; #[derive(Clone, Debug)] pub struct ElementCloseName { /// The element that was previously opened and is now being closed - element: schema::XsElement, + element: Arc, /// Current buffer of characters processed for the element name buffer: String, } impl ElementCloseName { /// Create a new instance with the given buffer - pub fn new(element: schema::XsElement, buffer: String) -> Self { + pub fn new(element: Arc, buffer: String) -> Self { Self { element, buffer, } } - pub fn append(&self, c: char) -> Vec { - let new_buffer = self.buffer.clone() + &c.to_string(); + pub fn append(self, c: char) -> Vec { + let new_buffer = self.buffer + &c.to_string(); // If still building the element name if self.element.name.starts_with(&new_buffer) { @@ -39,7 +40,7 @@ impl ElementCloseName { } else { // Still building the element name vec![Token::ElementCloseName(ElementCloseName::new( - self.element.clone(), + Arc::clone(&self.element), new_buffer, ))] } diff --git a/lib/xml_schema_validator/src/token/element_close_start.rs b/lib/xml_schema_validator/src/token/element_close_start.rs index 328f4cc..7e52c80 100644 --- a/lib/xml_schema_validator/src/token/element_close_start.rs +++ b/lib/xml_schema_validator/src/token/element_close_start.rs @@ -1,31 +1,32 @@ +use std::sync::Arc; use crate::*; /// Represents the start of an XML element closing tag (the ', has_slash: bool, } impl ElementCloseStart { - pub fn new(element: schema::XsElement) -> Self { + pub fn new(element: Arc) -> Self { Self { element, has_slash: false, } } - pub fn append(&self, c: char) -> Vec { + pub fn append(self, c: char) -> Vec { if !self.has_slash && '/' == c { vec![Token::ElementCloseStart(Self { - element: self.element.clone(), + element: Arc::clone(&self.element), has_slash: true, })] } else { if self.element.name.starts_with(c) { vec![Token::ElementCloseName(ElementCloseName::new( - self.element.clone(), + Arc::clone(&self.element), c.to_string(), ))] } else { diff --git a/lib/xml_schema_validator/src/token/element_open_end.rs b/lib/xml_schema_validator/src/token/element_open_end.rs index 5f7387e..467b0bb 100644 --- a/lib/xml_schema_validator/src/token/element_open_end.rs +++ b/lib/xml_schema_validator/src/token/element_open_end.rs @@ -1,19 +1,20 @@ +use std::sync::Arc; use crate::*; /// Represents a fully opened XML element, containing the schema element reference #[derive(Clone, Debug)] pub struct ElementOpenEnd { - element: schema::XsElement, + element: Arc, } impl ElementOpenEnd { - pub fn new(element: schema::XsElement) -> Self { + pub fn new(element: Arc) -> Self { Self { element, } } - pub fn append(&self, c: char) -> Vec { + pub fn append(self, c: char) -> Vec { // Check if the element allows text content (mixed="true") let allows_text = self.element.xs_complex_type.mixed .as_ref() @@ -23,10 +24,10 @@ impl ElementOpenEnd { if allows_text { if c.is_whitespace() { vec![Token::Whitespace(Whitespace::new( - vec![Token::TextContent(TextContent::new(self.element.clone()))] + vec![Token::TextContent(TextContent::new(Arc::clone(&self.element)))] ))] } else { - vec![Token::TextContent(TextContent::new(self.element.clone()))] + vec![Token::TextContent(TextContent::new(Arc::clone(&self.element)))] } } else { vec![] diff --git a/lib/xml_schema_validator/src/token/element_open_name.rs b/lib/xml_schema_validator/src/token/element_open_name.rs index 25bd28e..bd221a8 100644 --- a/lib/xml_schema_validator/src/token/element_open_name.rs +++ b/lib/xml_schema_validator/src/token/element_open_name.rs @@ -1,14 +1,15 @@ +use std::sync::Arc; use crate::*; /// Represents an XML element that is in the process of being opened, containing the text buffer and schema element reference #[derive(Clone, Debug)] pub struct ElementOpenName { buffer: String, - element: schema::XsElement, + element: Arc, } impl ElementOpenName { - pub fn new(element: schema::XsElement, buffer: String) -> Result { + pub fn new(element: Arc, buffer: String) -> Result { if element.name.starts_with(buffer.as_str()) { Ok(Self { buffer, @@ -19,19 +20,19 @@ impl ElementOpenName { } } - pub fn append(&self, c: char) -> Vec { - let buffer = self.buffer.clone() + &c.to_string(); + pub fn append(self, c: char) -> Vec { + let buffer = self.buffer + &c.to_string(); if self.element.name.starts_with(buffer.as_str()) { vec![Token::ElementName(ElementOpenName { buffer, - element: self.element.clone(), + element: Arc::clone(&self.element), })] } else if c.is_whitespace() { vec![Token::Whitespace(Whitespace::new( - vec![Token::ElementOpen(ElementOpenEnd::new(self.element.clone()))] + vec![Token::ElementOpen(ElementOpenEnd::new(Arc::clone(&self.element)))] ))] } else if '>' == c { - vec![Token::ElementOpen(ElementOpenEnd::new(self.element.clone()))] + vec![Token::ElementOpen(ElementOpenEnd::new(Arc::clone(&self.element)))] } else { vec![] } diff --git a/lib/xml_schema_validator/src/token/element_open_start.rs b/lib/xml_schema_validator/src/token/element_open_start.rs index b832076..683fed1 100644 --- a/lib/xml_schema_validator/src/token/element_open_start.rs +++ b/lib/xml_schema_validator/src/token/element_open_start.rs @@ -1,20 +1,21 @@ +use std::sync::Arc; use crate::*; /// Represents an XML element that is in the process of being opened, containing the text buffer and schema element reference #[derive(Clone, Debug)] pub struct ElementOpenStart { - element: schema::XsElement, + element: Arc, } impl ElementOpenStart { - pub fn new(element: schema::XsElement) -> Self { + pub fn new(element: Arc) -> Self { Self { element, } } - pub fn append(&self, c: char) -> Vec { - let element_name = ElementOpenName::new(self.element.clone(), c.to_string()); + pub fn append(self, c: char) -> Vec { + let element_name = ElementOpenName::new(Arc::clone(&self.element), c.to_string()); if let Ok(element_name) = element_name { vec![Token::ElementName(element_name)] } else { diff --git a/lib/xml_schema_validator/src/token/end_of_file.rs b/lib/xml_schema_validator/src/token/end_of_file.rs index 4b17cfb..124abda 100644 --- a/lib/xml_schema_validator/src/token/end_of_file.rs +++ b/lib/xml_schema_validator/src/token/end_of_file.rs @@ -1,6 +1,6 @@ use crate::*; -/// Represents the final state at the end of an XML file, containing a reference to the root element schema +/// Represents the final state at the end of an XML file #[derive(Clone, Debug)] pub struct EndOfFile { } @@ -10,7 +10,7 @@ impl EndOfFile { Self {} } - pub fn append(&self, _c: char) -> Vec { + pub fn append(self, _c: char) -> Vec { vec![] } } \ No newline at end of file diff --git a/lib/xml_schema_validator/src/token/mod.rs b/lib/xml_schema_validator/src/token/mod.rs index 9f8def0..0e6dbfa 100644 --- a/lib/xml_schema_validator/src/token/mod.rs +++ b/lib/xml_schema_validator/src/token/mod.rs @@ -36,7 +36,7 @@ pub enum Token { } impl Token { - pub fn append(&self, c: char) -> Vec { + pub fn append(self, c: char) -> Vec { match self { Token::ElementCloseEnd(element_close_end) => element_close_end.append(c), Token::ElementCloseName(element_close_name) => element_close_name.append(c), diff --git a/lib/xml_schema_validator/src/token/start_of_file.rs b/lib/xml_schema_validator/src/token/start_of_file.rs index 8e4bc64..27e3232 100644 --- a/lib/xml_schema_validator/src/token/start_of_file.rs +++ b/lib/xml_schema_validator/src/token/start_of_file.rs @@ -1,19 +1,20 @@ +use std::sync::Arc; use crate::*; /// Represents the initial state at the start of an XML file, containing a reference to the root element schema #[derive(Clone, Debug)] pub struct StartOfFile { - element: schema::XsElement, + element: Arc, } impl StartOfFile { - pub fn new(element: schema::XsElement) -> Self { + pub fn new(element: Arc) -> Self { Self { element } } - pub fn append(&self, c: char) -> Vec { + pub fn append(self, c: char) -> Vec { if '<' == c { - vec![Token::ElementStart(ElementOpenStart::new(self.element.clone()))] + vec![Token::ElementStart(ElementOpenStart::new(Arc::clone(&self.element)))] } else { vec![] } diff --git a/lib/xml_schema_validator/src/token/text_content.rs b/lib/xml_schema_validator/src/token/text_content.rs index 1b80991..033776d 100644 --- a/lib/xml_schema_validator/src/token/text_content.rs +++ b/lib/xml_schema_validator/src/token/text_content.rs @@ -1,14 +1,15 @@ +use std::sync::Arc; use crate::*; /// Represents the text content within an XML element #[derive(Clone, Debug)] pub struct TextContent { - element: schema::XsElement, + element: Arc, buffer: String, } impl TextContent { - pub fn new(element: schema::XsElement) -> Self { + pub fn new(element: Arc) -> Self { Self { element, buffer: String::new(), @@ -16,20 +17,20 @@ impl TextContent { } /// Create a new TextContent with the given initial buffer - pub fn with_buffer(element: schema::XsElement, buffer: String) -> Self { + pub fn with_buffer(element: Arc, buffer: String) -> Self { Self { element, buffer, } } - pub fn append(&self, c: char) -> Vec { + pub fn append(self, c: char) -> Vec { if c == '<' { - vec![Token::ElementCloseStart(ElementCloseStart::new(self.element.clone()))] + vec![Token::ElementCloseStart(ElementCloseStart::new(Arc::clone(&self.element)))] } else { vec![Token::TextContent(TextContent::with_buffer( - self.element.clone(), - self.buffer.clone() + &c.to_string(), + Arc::clone(&self.element), + self.buffer + &c.to_string(), ))] } } diff --git a/lib/xml_schema_validator/src/token/whitespace.rs b/lib/xml_schema_validator/src/token/whitespace.rs index 5ea4376..71f432c 100644 --- a/lib/xml_schema_validator/src/token/whitespace.rs +++ b/lib/xml_schema_validator/src/token/whitespace.rs @@ -13,14 +13,14 @@ impl Whitespace { } } - pub fn append(&self, c: char) -> Vec { + pub fn append(self, c: char) -> Vec { if c.is_whitespace() { vec![Token::Whitespace(Self { - next: self.next.clone() + next: self.next })] } else { let mut tokens = vec![]; - for token in self.next.iter() { + for token in self.next { tokens.append(&mut token.append(c)) } tokens