hedl_cli/batch/results.rs
1// Dweve HEDL - Hierarchical Entity Data Language
2//
3// Copyright (c) 2025 Dweve IP B.V. and individual contributors.
4//
5// SPDX-License-Identifier: Apache-2.0
6//
7// Licensed under the Apache License, Version 2.0 (the "License");
8// you may not use this file except in compliance with the License.
9// You may obtain a copy of the License in the LICENSE file at the
10// root of this repository or at: http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Batch processing result types.
19
20use crate::error::CliError;
21use std::path::PathBuf;
22
23/// Result of processing a single file in a batch operation.
24///
25/// Contains the file path and either a success value or an error.
26///
27/// # Type Parameters
28///
29/// * `T` - The success type returned by the operation
30#[derive(Debug, Clone)]
31pub struct FileResult<T> {
32 /// The file path that was processed
33 pub path: PathBuf,
34 /// The result of processing (Ok or Err)
35 pub result: Result<T, CliError>,
36}
37
38impl<T> FileResult<T> {
39 /// Create a successful file result.
40 pub fn success(path: PathBuf, value: T) -> Self {
41 Self {
42 path,
43 result: Ok(value),
44 }
45 }
46
47 /// Create a failed file result.
48 #[must_use]
49 pub fn failure(path: PathBuf, error: CliError) -> Self {
50 Self {
51 path,
52 result: Err(error),
53 }
54 }
55
56 /// Check if the result is successful.
57 pub fn is_success(&self) -> bool {
58 self.result.is_ok()
59 }
60
61 /// Check if the result is a failure.
62 pub fn is_failure(&self) -> bool {
63 self.result.is_err()
64 }
65}
66
67/// Aggregated results from a batch processing operation.
68///
69/// Contains all individual file results and provides statistics.
70///
71/// # Type Parameters
72///
73/// * `T` - The success type returned by the operation
74#[derive(Debug, Clone)]
75pub struct BatchResults<T> {
76 /// Individual results for each processed file
77 pub results: Vec<FileResult<T>>,
78 /// Total processing time in milliseconds
79 pub elapsed_ms: u128,
80}
81
82impl<T> BatchResults<T> {
83 /// Create new batch results from a vector of file results.
84 #[must_use]
85 pub fn new(results: Vec<FileResult<T>>, elapsed_ms: u128) -> Self {
86 Self {
87 results,
88 elapsed_ms,
89 }
90 }
91
92 /// Get the total number of files processed.
93 #[must_use]
94 pub fn total_files(&self) -> usize {
95 self.results.len()
96 }
97
98 /// Get the number of successfully processed files.
99 #[must_use]
100 pub fn success_count(&self) -> usize {
101 self.results.iter().filter(|r| r.is_success()).count()
102 }
103
104 /// Get the number of failed files.
105 #[must_use]
106 pub fn failure_count(&self) -> usize {
107 self.results.iter().filter(|r| r.is_failure()).count()
108 }
109
110 /// Check if all files were processed successfully.
111 #[must_use]
112 pub fn all_succeeded(&self) -> bool {
113 self.results.iter().all(FileResult::is_success)
114 }
115
116 /// Check if any files failed.
117 #[must_use]
118 pub fn has_failures(&self) -> bool {
119 self.results.iter().any(FileResult::is_failure)
120 }
121
122 /// Get an iterator over successful results.
123 pub fn successes(&self) -> impl Iterator<Item = &FileResult<T>> {
124 self.results.iter().filter(|r| r.is_success())
125 }
126
127 /// Get an iterator over failed results.
128 pub fn failures(&self) -> impl Iterator<Item = &FileResult<T>> {
129 self.results.iter().filter(|r| r.is_failure())
130 }
131
132 /// Get processing throughput in files per second.
133 #[must_use]
134 pub fn throughput(&self) -> f64 {
135 if self.elapsed_ms == 0 {
136 0.0
137 } else {
138 (self.total_files() as f64) / (self.elapsed_ms as f64 / 1000.0)
139 }
140 }
141}