weavatrix_scan/scanner/content_visit/
api.rs1use super::{
2 ChangedContentVisitOutcome, CompactScanReport, ContentVisitControl, ContentVisitEvent,
3 ContentVisitMode, ContentVisitReport, FinishedContentVisit, Result, Scanner,
4 apply_total_bytes_limit, discover_compact, finish_content_report, run_workers,
5 visit_changed_content_plan, visit_content_direct,
6};
7use crate::watch::WatchPlan;
8
9impl Scanner {
10 pub fn visit_content<Factory, Visitor>(self, factory: Factory) -> Result<ContentVisitReport>
34 where
35 Factory: Fn(usize) -> Visitor + Send + Sync + 'static,
36 Visitor:
37 for<'event> FnMut(ContentVisitEvent<'event>) -> ContentVisitControl + Send + 'static,
38 {
39 self.visit_content_with_root(0, factory)
40 }
41
42 pub fn visit_content_manifest<Factory, Visitor>(
57 self,
58 factory: Factory,
59 ) -> Result<CompactScanReport>
60 where
61 Factory: Fn(usize) -> Visitor + Send + Sync + 'static,
62 Visitor:
63 for<'event> FnMut(ContentVisitEvent<'event>) -> ContentVisitControl + Send + 'static,
64 {
65 self.visit_content_with_root_mode_finished(0, ContentVisitMode::Revision, factory)
66 .map(FinishedContentVisit::into_manifest)
67 }
68
69 pub fn visit_content_streaming<Factory, Visitor>(
84 self,
85 factory: Factory,
86 ) -> Result<ContentVisitReport>
87 where
88 Factory: Fn(usize) -> Visitor + Send + Sync + 'static,
89 Visitor:
90 for<'event> FnMut(ContentVisitEvent<'event>) -> ContentVisitControl + Send + 'static,
91 {
92 self.visit_content_with_root_mode(0, ContentVisitMode::Streaming, factory)
93 }
94
95 pub fn visit_changed_content<Factory, Visitor>(
112 self,
113 plan: &WatchPlan,
114 factory: Factory,
115 ) -> Result<ChangedContentVisitOutcome>
116 where
117 Factory: Fn(usize) -> Visitor + Send + Sync + 'static,
118 Visitor:
119 for<'event> FnMut(ContentVisitEvent<'event>) -> ContentVisitControl + Send + 'static,
120 {
121 visit_changed_content_plan(self, plan, ContentVisitMode::Revision, factory)
122 }
123
124 pub fn visit_changed_content_streaming<Factory, Visitor>(
131 self,
132 plan: &WatchPlan,
133 factory: Factory,
134 ) -> Result<ChangedContentVisitOutcome>
135 where
136 Factory: Fn(usize) -> Visitor + Send + Sync + 'static,
137 Visitor:
138 for<'event> FnMut(ContentVisitEvent<'event>) -> ContentVisitControl + Send + 'static,
139 {
140 visit_changed_content_plan(self, plan, ContentVisitMode::Streaming, factory)
141 }
142
143 pub(crate) fn visit_content_with_root<Factory, Visitor>(
144 self,
145 root_index: usize,
146 factory: Factory,
147 ) -> Result<ContentVisitReport>
148 where
149 Factory: Fn(usize) -> Visitor + Send + Sync + 'static,
150 Visitor:
151 for<'event> FnMut(ContentVisitEvent<'event>) -> ContentVisitControl + Send + 'static,
152 {
153 self.visit_content_with_root_mode(root_index, ContentVisitMode::Revision, factory)
154 }
155
156 pub(crate) fn visit_content_with_root_mode<Factory, Visitor>(
157 self,
158 root_index: usize,
159 mode: ContentVisitMode,
160 factory: Factory,
161 ) -> Result<ContentVisitReport>
162 where
163 Factory: Fn(usize) -> Visitor + Send + Sync + 'static,
164 Visitor:
165 for<'event> FnMut(ContentVisitEvent<'event>) -> ContentVisitControl + Send + 'static,
166 {
167 self.visit_content_with_root_mode_finished(root_index, mode, factory)
168 .map(|finished| finished.report)
169 }
170
171 fn visit_content_with_root_mode_finished<Factory, Visitor>(
172 self,
173 root_index: usize,
174 mode: ContentVisitMode,
175 factory: Factory,
176 ) -> Result<FinishedContentVisit>
177 where
178 Factory: Fn(usize) -> Visitor + Send + Sync + 'static,
179 Visitor:
180 for<'event> FnMut(ContentVisitEvent<'event>) -> ContentVisitControl + Send + 'static,
181 {
182 if self.options.limits.max_total_bytes.is_none()
183 && self.options.content_discovery == crate::ContentDiscoveryMode::Streaming
184 && !self.runtime.is_worker_thread()
185 {
186 return visit_content_direct(self, root_index, mode, factory);
187 }
188 let mut discovery_options = self.options.clone();
189 discovery_options.detect_binary_files = true;
190 let (mut evidence, mut files, scan_runtime) =
191 discover_compact(&self.root, &discovery_options, &self.runtime)?;
192 files.sort_unstable_by(|left, right| left.relative.cmp(&right.relative));
193 apply_total_bytes_limit(&mut evidence, &mut files, &self.options);
194 let discovered = u64::try_from(files.len()).unwrap_or(u64::MAX);
195
196 let cancellation = self.options.cancellation.clone().unwrap_or_default();
197 let mut visit_options = self.options.clone();
198 visit_options.cancellation = Some(cancellation.clone());
199 let workers = visit_options
200 .content_visit_worker_count(files.len())
201 .min(self.runtime.parallelism())
202 .max(1);
203 let worker_reports = run_workers(
204 evidence.root.clone(),
205 files,
206 visit_options,
207 &scan_runtime,
208 &self.runtime,
209 workers,
210 root_index,
211 mode,
212 factory,
213 )?;
214
215 Ok(finish_content_report(
216 evidence,
217 discovered,
218 worker_reports,
219 mode,
220 ))
221 }
222}