feedparser_rs/options.rs
1//! Parser configuration options
2//!
3//! This module provides configuration options for customizing feed parsing behavior.
4//! Options control features like URL resolution, HTML sanitization, and resource limits.
5
6use crate::limits::ParserLimits;
7
8/// Parser configuration options
9///
10/// Controls various aspects of feed parsing behavior including URL resolution,
11/// HTML sanitization, and resource limits for `DoS` protection.
12///
13/// # Examples
14///
15/// ```
16/// use feedparser_rs::ParseOptions;
17///
18/// // Default options (recommended for most use cases)
19/// let options = ParseOptions::default();
20/// assert!(options.resolve_relative_uris);
21/// assert!(options.sanitize_html);
22///
23/// // Custom options for restricted environment
24/// let custom = ParseOptions {
25/// resolve_relative_uris: true,
26/// sanitize_html: false, // Trust feed content
27/// limits: feedparser_rs::ParserLimits::strict(),
28/// };
29/// ```
30#[derive(Debug, Clone)]
31pub struct ParseOptions {
32 /// Whether to resolve relative URLs to absolute URLs
33 ///
34 /// When `true`, relative URLs in links, images, and other resources
35 /// are converted to absolute URLs using the feed's base URL.
36 ///
37 /// Default: `true`
38 ///
39 /// # Examples
40 ///
41 /// ```
42 /// use feedparser_rs::ParseOptions;
43 ///
44 /// let mut options = ParseOptions::default();
45 /// options.resolve_relative_uris = false; // Keep relative URLs
46 /// ```
47 pub resolve_relative_uris: bool,
48
49 /// Whether to sanitize HTML content in feed entries
50 ///
51 /// When `true`, HTML content in titles, summaries, and content blocks
52 /// is sanitized to remove potentially dangerous elements and attributes
53 /// (scripts, iframes, etc.) while preserving safe formatting.
54 ///
55 /// Default: `true`
56 ///
57 /// # Security
58 ///
59 /// Disabling HTML sanitization is **not recommended** unless you fully
60 /// trust the feed source and have other security measures in place.
61 ///
62 /// # Examples
63 ///
64 /// ```
65 /// use feedparser_rs::ParseOptions;
66 ///
67 /// let mut options = ParseOptions::default();
68 /// options.sanitize_html = false; // Disable for trusted feeds
69 /// ```
70 pub sanitize_html: bool,
71
72 /// Parser limits for `DoS` protection
73 ///
74 /// Controls maximum allowed sizes for collections, text fields,
75 /// and overall feed size to prevent resource exhaustion attacks.
76 ///
77 /// Default: `ParserLimits::default()`
78 ///
79 /// # Examples
80 ///
81 /// ```
82 /// use feedparser_rs::{ParseOptions, ParserLimits};
83 ///
84 /// let options = ParseOptions {
85 /// limits: ParserLimits::strict(), // Use stricter limits
86 /// ..Default::default()
87 /// };
88 /// ```
89 pub limits: ParserLimits,
90}
91
92impl Default for ParseOptions {
93 /// Creates default parse options
94 ///
95 /// Default configuration:
96 /// - `resolve_relative_uris`: `true`
97 /// - `sanitize_html`: `true`
98 /// - `limits`: `ParserLimits::default()`
99 ///
100 /// These defaults are suitable for most use cases and provide
101 /// good security and compatibility.
102 fn default() -> Self {
103 Self {
104 resolve_relative_uris: true,
105 sanitize_html: true,
106 limits: ParserLimits::default(),
107 }
108 }
109}
110
111impl ParseOptions {
112 /// Creates permissive parse options
113 ///
114 /// Suitable for trusted feeds where you want maximum compatibility
115 /// and performance:
116 /// - `resolve_relative_uris`: `true`
117 /// - `sanitize_html`: `false`
118 /// - `limits`: `ParserLimits::permissive()`
119 ///
120 /// # Security Warning
121 ///
122 /// Use only with trusted feed sources!
123 ///
124 /// # Examples
125 ///
126 /// ```
127 /// use feedparser_rs::ParseOptions;
128 ///
129 /// let options = ParseOptions::permissive();
130 /// assert!(!options.sanitize_html);
131 /// ```
132 #[must_use]
133 pub const fn permissive() -> Self {
134 Self {
135 resolve_relative_uris: true,
136 sanitize_html: false,
137 limits: ParserLimits::permissive(),
138 }
139 }
140
141 /// Creates strict parse options
142 ///
143 /// Suitable for untrusted feeds in resource-constrained environments:
144 /// - `resolve_relative_uris`: `false` (preserve original URLs)
145 /// - `sanitize_html`: `true` (remove dangerous content)
146 /// - `limits`: `ParserLimits::strict()` (tight resource limits)
147 ///
148 /// # Examples
149 ///
150 /// ```
151 /// use feedparser_rs::ParseOptions;
152 ///
153 /// let options = ParseOptions::strict();
154 /// assert!(options.sanitize_html);
155 /// assert!(!options.resolve_relative_uris);
156 /// ```
157 #[must_use]
158 pub const fn strict() -> Self {
159 Self {
160 resolve_relative_uris: false,
161 sanitize_html: true,
162 limits: ParserLimits::strict(),
163 }
164 }
165}
166
167#[cfg(test)]
168mod tests {
169 use super::*;
170
171 #[test]
172 fn test_default_options() {
173 let options = ParseOptions::default();
174 assert!(options.resolve_relative_uris);
175 assert!(options.sanitize_html);
176 assert_eq!(options.limits.max_entries, 10_000);
177 }
178
179 #[test]
180 fn test_permissive_options() {
181 let options = ParseOptions::permissive();
182 assert!(options.resolve_relative_uris);
183 assert!(!options.sanitize_html);
184 assert_eq!(options.limits.max_entries, 100_000);
185 }
186
187 #[test]
188 fn test_strict_options() {
189 let options = ParseOptions::strict();
190 assert!(!options.resolve_relative_uris);
191 assert!(options.sanitize_html);
192 assert_eq!(options.limits.max_entries, 1_000);
193 }
194
195 #[test]
196 fn test_custom_options() {
197 let options = ParseOptions {
198 resolve_relative_uris: false,
199 sanitize_html: false,
200 limits: ParserLimits::permissive(),
201 };
202 assert!(!options.resolve_relative_uris);
203 assert!(!options.sanitize_html);
204 assert_eq!(options.limits.max_entries, 100_000);
205 }
206
207 #[test]
208 fn test_options_clone() {
209 let options1 = ParseOptions::default();
210 let options2 = options1.clone();
211 assert_eq!(
212 options1.resolve_relative_uris,
213 options2.resolve_relative_uris
214 );
215 assert_eq!(options1.sanitize_html, options2.sanitize_html);
216 }
217
218 #[test]
219 fn test_options_debug() {
220 let options = ParseOptions::default();
221 let debug_str = format!("{options:?}");
222 assert!(debug_str.contains("ParseOptions"));
223 assert!(debug_str.contains("resolve_relative_uris"));
224 assert!(debug_str.contains("sanitize_html"));
225 }
226}