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
// Copyright (C) 2026 Kan-Ru Chen <kanru@kanru.info>
//
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//! Functions for adding context to errors.
//!
//! This module provides the core functions that enable context propagation:
//! [`expect_error`] for use with [`scoped_error::Error`](crate::Error) or custom
//! error types, and [`expect_error_fn`] for advanced use cases.
//!
//! These functions work by:
//! 1. Executing a closure that returns `Result<T, Frame>`
//! 2. If the result is `Err`, attaching the context message and location
//! 3. Returning `Result<T, E>` where `E` is the target error type
//!
//! # How It Works
//!
//! The `?` operator automatically converts errors to `Frame` via the
//! `From` impl in [`error`](crate::error), capturing the source location.
//! The conversion functions then wrap this context with an additional message.
use Cow;
use crateFrame;
use crateWithContext;
/// Low-level function for adding context with a custom error constructor.
///
/// This function is the foundation for other conversion functions. It allows
/// complete control over how the final error is constructed.
///
/// # Type Parameters
///
/// - `F`: A function that constructs the target error type `E`
/// - `T`: The success type
/// - `E`: The target error type (must implement [`WithContext`])
///
/// # Example
///
/// ```
/// # use scoped_error::impl_context_error;
/// use scoped_error::{expect_error_fn, WithContext, Frame};
///
/// # impl_context_error!(MyError);
/// # impl MyError {
/// # fn new(msg: &'static str) -> MyError {
/// # MyError { message: msg.into(), source: None, location: None }
/// # }
/// # }
///
/// # fn operation_that_might_fail() -> Result<(), MyError> { Ok(()) }
///
/// fn do_work() -> Result<(), MyError> {
/// let err = || MyError::new("custom");
///
/// expect_error_fn(err, || {
/// operation_that_might_fail()?;
/// Ok(())
/// })
/// }
/// ```
/// Add context to errors, returning a custom error type.
///
/// # Type Parameters
///
/// - `T`: The success type
/// - `E`: The custom error type
///
/// # Example
///
/// The simplest way to add context is using it with the ready to use
/// [`scoped_error::Error`](crate::Error) type when you don't need a custom error type.
///
/// ```
/// use scoped_error::{Error, expect_error};
///
/// fn read_file() -> Result<String, Error> {
/// expect_error("Failed to read configuration", || {
/// let cfg = std::fs::read_to_string("config.toml")?;
/// Ok(cfg)
/// })
/// }
/// ```
///
/// Use this function with custom error types that implement
/// `From<(Cow<'static, str>, Frame)>`. The [`impl_context_error!`](crate::impl_context_error)
/// macro generates this implementation for you.
///
/// ```
/// use scoped_error::{expect_error, impl_context_error};
///
/// impl_context_error!(MyError);
///
/// fn do_work() -> Result<String, MyError> {
/// expect_error("Failed to do work", || {
/// let cfg = std::fs::read_to_string("config.toml")?;
/// Ok(cfg)
/// })
/// }
/// ```