1use std::io::{BufRead, BufReader};
12
13use crate::ast::Document;
14use crate::error::VexyError;
15use crate::parser::config::StreamingConfig;
16use crate::parser::streaming::StreamingParser;
17
18pub struct Parser {
20 preserve_whitespace: bool,
22 preserve_comments: bool,
24 expand_entities: bool,
26
27 streaming_config: StreamingConfig,
29}
30
31impl Parser {
32 pub fn new() -> Self {
34 Self {
35 preserve_whitespace: false,
36 preserve_comments: true,
37 expand_entities: true,
38 streaming_config: StreamingConfig::default(),
39 }
40 }
41
42 pub fn with_streaming_config(config: StreamingConfig) -> Self {
44 Self {
45 preserve_whitespace: false,
46 preserve_comments: true,
47 expand_entities: true,
48 streaming_config: config,
49 }
50 }
51
52 pub fn preserve_whitespace(mut self, preserve: bool) -> Self {
54 self.preserve_whitespace = preserve;
55 self
56 }
57
58 pub fn preserve_comments(mut self, preserve: bool) -> Self {
60 self.preserve_comments = preserve;
61 self
62 }
63
64 pub fn expand_entities(mut self, expand: bool) -> Self {
66 self.expand_entities = expand;
67 self
68 }
69
70 pub fn streaming_config(mut self, config: StreamingConfig) -> Self {
72 self.streaming_config = config;
73 self
74 }
75
76 pub fn parse_svg_string(input: &str) -> Result<Document<'static>, VexyError> {
78 let parser = Self::new();
79 parser.parse(input)
80 }
81
82 pub fn parse(&self, input: &str) -> Result<Document<'static>, VexyError> {
85 if input.len() > self.streaming_config.buffer_size * 4 {
87 return self.parse_streaming_from_str(input);
88 }
89
90 self.parse_internal(input)
91 }
92
93 fn parse_internal(&self, input: &str) -> Result<Document<'static>, VexyError> {
95 let mut streaming_parser = StreamingParser::new(
96 BufReader::new(input.as_bytes()),
97 self.streaming_config.clone(),
98 self.preserve_whitespace,
99 self.preserve_comments,
100 self.expand_entities,
101 None,
102 );
103 streaming_parser.parse()
104 }
105
106 pub fn parse_streaming<R: BufRead>(&self, reader: R) -> Result<Document<'static>, VexyError> {
108 let mut streaming_parser = StreamingParser::new(
109 reader,
110 self.streaming_config.clone(),
111 self.preserve_whitespace,
112 self.preserve_comments,
113 self.expand_entities,
114 None,
115 );
116 streaming_parser.parse()
117 }
118
119 fn parse_streaming_from_str(&self, input: &str) -> Result<Document<'static>, VexyError> {
121 let cursor = std::io::Cursor::new(input);
122 let buf_reader = BufReader::with_capacity(self.streaming_config.buffer_size, cursor);
123 self.parse_streaming(buf_reader)
124 }
125}
126
127impl Default for Parser {
128 fn default() -> Self {
129 Self::new()
130 }
131}
132
133pub fn parse_svg(input: &str) -> Result<Document<'static>, VexyError> {
135 Parser::new().parse(input)
136}
137
138pub fn parse_svg_streaming<R: BufRead>(reader: R) -> Result<Document<'static>, VexyError> {
140 Parser::new().parse_streaming(reader)
141}
142
143pub fn parse_svg_file<P: AsRef<std::path::Path>>(path: P) -> Result<Document<'static>, VexyError> {
145 let file = std::fs::File::open(&path)?;
146 let metadata = file.metadata()?;
147
148 let parser = Parser::new();
149
150 if metadata.len() > 1024 * 1024 {
152 let buf_reader = BufReader::with_capacity(128 * 1024, file);
153 parser.parse_streaming(buf_reader)
154 } else {
155 let content = std::fs::read_to_string(path)?;
156 parser.parse(&content)
157 }
158}