Repository navigation
Expand file tree
/
Copy patherror_handling_advanced.script
More file actions
351 lines (296 loc) · 10.8 KB
/
Copy patherror_handling_advanced.script
File metadata and controls
351 lines (296 loc) · 10.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
// Advanced Error Handling Examples for Script Language
// Demonstrating the complete error handling system with advanced methods
// Example 1: Flattening nested Results
fn parse_and_validate(input: string) -> Result<i32, string> {
// Parse the string to an integer
let parsed = parse_integer(input)?;
// Validate the parsed value
if parsed < 0 {
Err("Value must be non-negative")
} else {
Ok(parsed)
}
}
fn process_nested_result(input: string) -> Result<i32, string> {
// This creates a Result<Result<i32, string>, string>
let nested_result = Ok(parse_and_validate(input));
// Flatten it to Result<i32, string>
nested_result.flatten()
}
// Example 2: Transposing between Result and Option
fn find_and_parse(data: [string], target: string) -> Result<Option<i32>, string> {
// Find the target in the array
let found = find_in_array(data, target);
// Transpose Option<Result<i32, string>> to Result<Option<i32>, string>
found.transpose()
}
fn find_in_array(arr: [string], target: string) -> Option<Result<i32, string>> {
for item in arr {
if item == target {
return Some(parse_integer(item));
}
}
None
}
// Example 3: Using inspect for debugging without consuming values
fn debug_pipeline(input: string) -> Result<i32, string> {
parse_integer(input)
.inspect(|val| println("Parsed value: {}", val))
.inspect_err(|err| println("Parse error: {}", err))
.and_then(|val| {
if val > 100 {
Err("Value too large")
} else {
Ok(val * 2)
}
})
.inspect(|val| println("Final value: {}", val))
}
// Example 4: Complex error recovery strategies
fn robust_data_processing(inputs: [string]) -> Result<[i32], string> {
let mut results = [];
let mut errors = [];
for input in inputs {
match parse_integer(input) {
Ok(val) => results.push(val),
Err(e) => {
errors.push(e);
// Continue processing other inputs
}
}
}
if errors.is_empty() {
Ok(results)
} else {
Err(format!("Errors encountered: {}", errors.join(", ")))
}
}
// Example 5: Combining multiple Results with logical operations
fn validate_range(min: string, max: string, value: string) -> Result<i32, string> {
let min_val = parse_integer(min)?;
let max_val = parse_integer(max)?;
let val = parse_integer(value)?;
// Use logical AND to combine validation results
let min_check = if val >= min_val { Ok(val) } else { Err("Value below minimum") };
let max_check = if val <= max_val { Ok(val) } else { Err("Value above maximum") };
min_check.and(max_check)
}
// Example 6: Advanced Option patterns
fn process_optional_data(opt_data: Option<[string]>) -> Option<[i32]> {
opt_data
.inspect(|data| println("Processing {} items", data.len()))
.and_then(|data| {
let mut parsed = [];
for item in data {
match parse_integer(item) {
Ok(val) => parsed.push(val),
Err(_) => return None // Early termination on parse error
}
}
Some(parsed)
})
.inspect(|result| println("Successfully parsed {} values", result.len()))
}
// Example 7: Flattening nested Options
fn get_nested_config() -> Option<Option<string>> {
Some(get_config_value("database.host"))
}
fn get_config_value(key: string) -> Option<string> {
if key == "database.host" {
Some("localhost")
} else {
None
}
}
fn get_database_host() -> Option<string> {
get_nested_config().flatten()
}
// Example 8: Collecting Results into collections
fn parse_all_numbers(inputs: [string]) -> Result<[i32], string> {
let mut results = [];
for input in inputs {
results.push(parse_integer(input)?);
}
Ok(results)
}
// Example 9: Using fold for accumulation with error handling
fn sum_valid_numbers(inputs: [string]) -> Result<i32, string> {
let mut sum = 0;
for input in inputs {
let parsed = parse_integer(input)?;
sum += parsed;
}
Ok(sum)
}
// Example 10: Custom error types and hierarchies
enum ValidationError {
Empty,
TooLong(i32),
InvalidFormat(string),
OutOfRange(i32, i32, i32), // min, max, actual
}
fn validate_username(username: string) -> Result<string, ValidationError> {
if username.is_empty() {
return Err(ValidationError::Empty);
}
if username.len() > 20 {
return Err(ValidationError::TooLong(username.len()));
}
if !username.is_alphanumeric() {
return Err(ValidationError::InvalidFormat(username));
}
Ok(username)
}
fn format_validation_error(err: ValidationError) -> string {
match err {
ValidationError::Empty => "Username cannot be empty",
ValidationError::TooLong(len) => format!("Username too long: {} characters", len),
ValidationError::InvalidFormat(name) => format!("Invalid username format: {}", name),
ValidationError::OutOfRange(min, max, actual) => {
format!("Value {} is not between {} and {}", actual, min, max)
}
}
}
// Example 11: Chaining multiple operations with error propagation
fn process_user_input(input: string) -> Result<string, string> {
let cleaned = clean_input(input)?;
let validated = validate_username(cleaned)
.map_err(|e| format_validation_error(e))?;
let normalized = normalize_case(validated)?;
Ok(format!("Welcome, {}!", normalized))
}
fn clean_input(input: string) -> Result<string, string> {
if input.contains(" ") {
Err("Input contains double spaces")
} else {
Ok(input.trim())
}
}
fn normalize_case(input: string) -> Result<string, string> {
Ok(input.to_lowercase())
}
// Example 12: Performance considerations and best practices
fn efficient_error_handling(large_dataset: [string]) -> Result<[i32], string> {
// Pre-allocate result vector for better performance
let mut results = Vec::with_capacity(large_dataset.len());
// Process in batches to avoid memory issues
let batch_size = 1000;
let mut batch_errors = [];
for i in 0..large_dataset.len() step batch_size {
let end = min(i + batch_size, large_dataset.len());
let batch = large_dataset[i..end];
// Process batch
for item in batch {
match parse_integer(item) {
Ok(val) => results.push(val),
Err(e) => {
batch_errors.push(format!("Item {}: {}", i, e));
// Continue processing instead of failing fast
}
}
}
// Check if we have too many errors
if batch_errors.len() > 100 {
return Err(format!("Too many errors: {}", batch_errors.len()));
}
}
if batch_errors.is_empty() {
Ok(results)
} else {
Err(format!("Batch errors: {}", batch_errors.join("; ")))
}
}
// Helper function (simplified implementation)
fn parse_integer(s: string) -> Result<i32, string> {
if s.is_empty() {
Err("Cannot parse empty string")
} else if s == "invalid" {
Err("Invalid number format")
} else if s.starts_with("-") {
Err("Negative numbers not supported")
} else {
// Simplified: return length as the "parsed" value
Ok(s.len() as i32)
}
}
// Main function demonstrating all examples
fn main() -> Result<(), string> {
println("=== Advanced Error Handling Examples ===");
// Example 1: Flattening
println("\n1. Flattening nested Results:");
match process_nested_result("42") {
Ok(val) => println("Flattened result: {}", val),
Err(e) => println("Error: {}", e),
}
// Example 2: Transposing
println("\n2. Transposing Result and Option:");
let data = ["10", "20", "30"];
match find_and_parse(data, "20") {
Ok(Some(val)) => println("Found and parsed: {}", val),
Ok(None) => println("Not found"),
Err(e) => println("Error: {}", e),
}
// Example 3: Debugging with inspect
println("\n3. Debugging with inspect:");
let _ = debug_pipeline("42");
// Example 4: Robust processing
println("\n4. Robust data processing:");
let inputs = ["10", "invalid", "30", "40"];
match robust_data_processing(inputs) {
Ok(results) => println("Processed: {:?}", results),
Err(e) => println("Processing errors: {}", e),
}
// Example 5: Validation with range
println("\n5. Range validation:");
match validate_range("0", "100", "50") {
Ok(val) => println("Valid value: {}", val),
Err(e) => println("Validation error: {}", e),
}
// Example 6: Optional data processing
println("\n6. Optional data processing:");
let opt_data = Some(["10", "20", "30"]);
match process_optional_data(opt_data) {
Some(results) => println("Processed optional data: {:?}", results),
None => println("Failed to process optional data"),
}
// Example 7: Nested Options
println("\n7. Flattening nested Options:");
match get_database_host() {
Some(host) => println("Database host: {}", host),
None => println("Database host not configured"),
}
// Example 8: Collecting results
println("\n8. Collecting results:");
let numbers = ["1", "2", "3"];
match parse_all_numbers(numbers) {
Ok(parsed) => println("All numbers: {:?}", parsed),
Err(e) => println("Parse error: {}", e),
}
// Example 9: Folding with error handling
println("\n9. Summing valid numbers:");
match sum_valid_numbers(["1", "2", "3"]) {
Ok(sum) => println("Sum: {}", sum),
Err(e) => println("Sum error: {}", e),
}
// Example 10: Custom error types
println("\n10. Custom error validation:");
match validate_username("john_doe") {
Ok(name) => println("Valid username: {}", name),
Err(e) => println("Validation error: {}", format_validation_error(e)),
}
// Example 11: Chaining operations
println("\n11. Chaining operations:");
match process_user_input(" John_Doe ") {
Ok(result) => println("Processed: {}", result),
Err(e) => println("Processing error: {}", e),
}
// Example 12: Performance considerations
println("\n12. Efficient error handling:");
let large_data = ["1", "2", "3", "4", "5"];
match efficient_error_handling(large_data) {
Ok(results) => println("Efficiently processed {} items", results.len()),
Err(e) => println("Efficient processing error: {}", e),
}
println("\n=== All examples completed successfully! ===");
Ok(())
}