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}