Sebastian ThielAddress Copilot review0b0e9f89 months agoHistory
217 lines · 6.2 KB · Rust
RawDownload
// Copyright 2025 FastLabs Developers//// Licensed under the Apache License, Version 2.0 (the "License");// you may not use this file except in compliance with the License.// You may obtain a copy of the License at////     http://www.apache.org/licenses/LICENSE-2.0//// Unless required by applicable law or agreed to in writing, software// distributed under the License is distributed on an "AS IS" BASIS,// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.// See the License for the specific language governing permissions and// limitations under the License. use crate::exn::Exn; /// A trait bound of the supported error type of [`Exn`].pub trait ErrorExt: std::error::Error + Send + Sync + 'static {    /// Raise this error as a new exception.    #[track_caller]    fn raise(self) -> Exn<Self>    where        Self: Sized,    {        Exn::new(self)    }     /// Raise this error as a child of a new exception with the given context error.    ///    /// This is a shorthand for `self.raise().raise(context)` — it wraps `self` in an [`Exn`]    /// and immediately nests it under a new `Exn<T>` headed by `context`.    ///    /// ```rust,ignore    /// // Instead of:    /// io_err.raise().raise(message("could not read file"))    ///    /// // Write:    /// io_err.and_raise(message("could not read file"))    /// ```    #[track_caller]    fn and_raise<T: std::error::Error + Send + Sync + 'static>(self, context: T) -> Exn<T>    where        Self: Sized,    {        Exn::new(self).raise(context)    }     /// Raise this error as a new exception, with type erasure.    #[track_caller]    fn raise_erased(self) -> Exn    where        Self: Sized,    {        Exn::new(self).erased()    }     /// Raise this error as a new exception, with `sources` as causes.    #[track_caller]    fn raise_all<T, I>(self, sources: I) -> Exn<Self>    where        Self: Sized,        T: std::error::Error + Send + Sync + 'static,        I: IntoIterator,        I::Item: Into<Exn<T>>,    {        Exn::raise_all(sources, self)    }} impl<T> ErrorExt for T where T: std::error::Error + Send + Sync + 'static {} /// An extension trait for [`Option`] to provide raising new exceptions on `None`.pub trait OptionExt {    /// The `Some` type.    type Some;     /// Construct a new [`Exn`] on the `None` variant.    fn ok_or_raise<A, F>(self, err: F) -> Result<Self::Some, Exn<A>>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A;     /// Construct a new [`Exn`] on the `None` variant, with type erasure.    fn ok_or_raise_erased<A, F>(self, err: F) -> Result<Self::Some, Exn>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A;} impl<T> OptionExt for Option<T> {    type Some = T;     #[track_caller]    fn ok_or_raise<A, F>(self, err: F) -> Result<T, Exn<A>>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A,    {        match self {            Some(v) => Ok(v),            None => Err(Exn::new(err())),        }    }     #[track_caller]    fn ok_or_raise_erased<A, F>(self, err: F) -> Result<T, Exn>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A,    {        self.ok_or_raise(err).map_err(Exn::erased)    }} /// An extension trait for [`Result`] to provide context information on [`Exn`]s.pub trait ResultExt {    /// The `Ok` type.    type Success;     /// The `Err` type that would be wrapped in an [`Exn`].    type Error: std::error::Error + Send + Sync + 'static;     /// Raise a new exception on the [`Exn`] inside the [`Result`].    ///    /// Apply [`Exn::raise`] on the `Err` variant, refer to it for more information.    fn or_raise<A, F>(self, err: F) -> Result<Self::Success, Exn<A>>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A;     /// Raise a new exception on the [`Exn`] inside the [`Result`], but erase its type.    ///    /// Apply [`Exn::erased`] on the `Err` variant, refer to it for more information.    fn or_erased(self) -> Result<Self::Success, Exn>;     /// Raise a new exception on the [`Exn`] inside the [`Result`], and type-erase the result.    ///    /// Apply [`Exn::raise`] and [`Exn::erased`] on the `Err` variant, refer to it for more information.    fn or_raise_erased<A, F>(self, err: F) -> Result<Self::Success, Exn>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A;} impl<T, E> ResultExt for Result<T, E>where    E: std::error::Error + Send + Sync + 'static,{    type Success = T;    type Error = E;     #[track_caller]    fn or_raise<A, F>(self, err: F) -> Result<Self::Success, Exn<A>>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A,    {        match self {            Ok(v) => Ok(v),            Err(e) => Err(Exn::new(e).raise(err())),        }    }     #[track_caller]    fn or_erased(self) -> Result<Self::Success, Exn> {        match self {            Ok(v) => Ok(v),            Err(e) => Err(Exn::new(e).erased()),        }    }     #[track_caller]    fn or_raise_erased<A, F>(self, err: F) -> Result<Self::Success, Exn>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A,    {        self.or_raise(err).map_err(Exn::erased)    }} impl<T, E> ResultExt for Result<T, Exn<E>>where    E: std::error::Error + Send + Sync + 'static,{    type Success = T;    type Error = E;     #[track_caller]    fn or_raise<A, F>(self, err: F) -> Result<Self::Success, Exn<A>>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A,    {        match self {            Ok(v) => Ok(v),            Err(e) => Err(e.raise(err())),        }    }     #[track_caller]    fn or_erased(self) -> Result<Self::Success, Exn> {        match self {            Ok(v) => Ok(v),            Err(e) => Err(e.erased()),        }    }     #[track_caller]    fn or_raise_erased<A, F>(self, err: F) -> Result<Self::Success, Exn>    where        A: std::error::Error + Send + Sync + 'static,        F: FnOnce() -> A,    {        self.or_raise(err).map_err(Exn::erased)    }}