1mod dependencies;
2mod dependency_types;
3mod lexer;
4
5pub use dependencies::LexDependencies;
6pub use dependencies::ModeData;
7pub use dependency_types::Dependency;
8pub use dependency_types::DependencyContext;
9pub use dependency_types::DependencyIndex;
10pub use dependency_types::DependencyListRange;
11pub use dependency_types::ImportAttributes;
12pub use dependency_types::Mode;
13pub use dependency_types::Range;
14pub use dependency_types::UrlRangeKind;
15pub use dependency_types::ValueAtRuleImportItem;
16pub use dependency_types::Warning;
17pub use dependency_types::WarningKind;
18pub use lexer::{Lexer, Pos, Token, TokenFlags, TokenKind, TokenWithTrivia, Trivia};
19
20pub trait HandleWarning<'s> {
21 fn handle_warning(&mut self, warning: Warning<'s>);
22}
23
24impl<'s, F: FnMut(Warning<'s>)> HandleWarning<'s> for F {
25 fn handle_warning(&mut self, warning: Warning<'s>) {
26 self(warning);
27 }
28}
29
30pub fn lex_dependencies<'s>(
31 input: &'s str,
32 mode: Mode,
33 mut handle_dependency: impl FnMut(&Dependency<'s>),
34 handle_warning: impl HandleWarning<'s>,
35) -> DependencyContext<'s> {
36 let mut lexer = Lexer::new(input);
37 let mut visitor = LexDependencies::new(handle_warning, mode);
38 visitor.lex_streaming(&mut lexer);
39 let dependency_context = visitor.into_dependency_context();
40 for dependency in dependency_context.iter() {
41 handle_dependency(dependency);
42 }
43 dependency_context
44}
45
46pub fn collect_dependencies(input: &str, mode: Mode) -> (DependencyContext<'_>, Vec<Warning<'_>>) {
47 let mut warnings = Vec::with_capacity(estimate_warning_capacity(input.len(), mode));
48 let mut lexer = Lexer::new(input);
49 let mut visitor = LexDependencies::new(|v| warnings.push(v), mode);
50 visitor.lex_streaming(&mut lexer);
51 (visitor.into_dependency_context(), warnings)
52}
53
54fn estimate_warning_capacity(input_len: usize, mode: Mode) -> usize {
55 let warning_rate = match mode {
56 Mode::Pure => (1, 256),
57 _ => (1, 512),
58 };
59
60 estimate_capacity(input_len, warning_rate.0, warning_rate.1, 2, 512)
61}
62
63#[inline]
64fn estimate_capacity(
65 input_len: usize,
66 numerator: usize,
67 denominator: usize,
68 minimum: usize,
69 maximum: usize,
70) -> usize {
71 input_len
72 .saturating_mul(numerator)
73 .checked_div(denominator)
74 .unwrap_or(0)
75 .clamp(minimum, maximum)
76}