zrx_diagnostic/diagnostic/report/
convert.rs

1// Copyright (c) Zensical LLC <https://zensical.org>
2
3// SPDX-License-Identifier: MIT
4// Third-party contributions licensed under CLA
5
6// Permission is hereby granted, free of charge, to any person obtaining a copy
7// of this software and associated documentation files (the "Software"), to
8// deal in the Software without restriction, including without limitation the
9// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10// sell copies of the Software, and to permit persons to whom the Software is
11// furnished to do so, subject to the following conditions:
12
13// The above copyright notice and this permission notice shall be included in
14// all copies or substantial portions of the Software.
15
16// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
19// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22// IN THE SOFTWARE.
23
24// ----------------------------------------------------------------------------
25
26//! Report conversions.
27
28use std::error::Error;
29use std::result::Result;
30
31use super::Report;
32
33// ----------------------------------------------------------------------------
34// Traits
35// ----------------------------------------------------------------------------
36
37/// Conversion into [`Report`]
38///
39/// This trait is generic over the [`Ok`] and [`Err`] variants of any result,
40/// which means downstream consumers can implement this trait for custom types,
41/// allowing them to convert any type into a report. It's primarily intended to
42/// support adding diagnostics to fallible as well as infallible methods.
43///
44/// Note that the trait implementations provided here may not include sufficient
45/// trait bounds, which makes explicit annotations necessary in some cases. For
46/// this reason, downstream crates are recommended to provide their own custom
47/// implementation of this trait, adding additional trait bounds on `T`.
48pub trait IntoReport<T, E>
49where
50    E: Error,
51{
52    /// Converts into a report.
53    ///
54    /// # Errors
55    ///
56    /// Note that this method never returns an error by itself, as this trait is
57    /// primarily provided for wrapping values returned from infallible methods.
58    /// Consequentially, this trait isn't named `TryIntoReport`, as it's not
59    /// falling under Rust's try-semantics.
60    fn into_report(self) -> Result<Report<T>, E>;
61}
62
63// ----------------------------------------------------------------------------
64// Blanket implementations
65// ----------------------------------------------------------------------------
66
67impl<T, E> IntoReport<T, E> for T
68where
69    E: Error,
70{
71    /// Creates a report from a value `T` and wraps it in a result.
72    ///
73    /// # Examples
74    ///
75    /// ```
76    /// use std::io::Error;
77    /// use zrx_diagnostic::report::IntoReport;
78    ///
79    /// // Define function returning a value
80    /// fn f() -> impl IntoReport<i32, Error> {
81    ///     42
82    /// }
83    ///
84    /// // Invoke function and create report
85    /// let res = f().into_report();
86    /// ```
87    #[inline]
88    fn into_report(self) -> Result<Report<T>, E> {
89        Ok(Report::new(self))
90    }
91}
92
93impl<T, E> IntoReport<T, E> for Result<T, E>
94where
95    E: Error,
96{
97    /// Creates a report from a value `T` in a result.
98    ///
99    /// # Examples
100    ///
101    /// ```
102    /// use std::io::Error;
103    /// use zrx_diagnostic::report::IntoReport;
104    ///
105    /// // Define function returning a result
106    /// fn f() -> impl IntoReport<i32, Error> {
107    ///     Ok(42)
108    /// }
109    ///
110    /// // Invoke function and create report
111    /// let res = f().into_report();
112    /// ```
113    #[inline]
114    fn into_report(self) -> Result<Report<T>, E> {
115        self.map(Report::new)
116    }
117}
118
119impl<T, E> IntoReport<T, E> for Result<Report<T>, E>
120where
121    E: Error,
122{
123    /// Returns the report in a result as is.
124    #[inline]
125    fn into_report(self) -> Result<Report<T>, E> {
126        self
127    }
128}