pdk-classy 1.9.1-alpha.2

PDK Classy
Documentation
// Copyright (c) 2026, Salesforce, Inc.,
// All rights reserved.
// For full license text, see the LICENSE.txt file

use std::convert::Infallible;

use crate::{all_the_tuples, BoxError};

use self::extractability::{Direct, Extractability};

mod private {
    pub trait Sealed {}
}

/// Trait that defines the extractability of a type.
pub mod extractability {
    use super::private::Sealed;

    /// Trait that defines the extractability of a type.
    pub trait Extractability: Sealed {}

    /// The type can be extracted from the context directly.
    pub enum Direct {}
    impl Sealed for Direct {}
    impl Extractability for Direct {}

    /// The type can be extracted in a context from contexts of higher hierarchy.
    pub enum Transitive {}
    impl Sealed for Transitive {}
    impl Extractability for Transitive {}
}

/// Extract data from the given context.
pub trait FromContext<C, E: Extractability = Direct>: Sized {
    type Error: Into<BoxError>;

    fn from_context(context: &C) -> Result<Self, Self::Error>;

    fn from_context_always(context: &C) -> Self
    where
        Self: FromContext<C, E, Error = Infallible>,
    {
        // Infallible never fails
        Self::from_context(context).unwrap()
    }
}

pub trait Extract<T> {
    type Error;

    fn extract(&self) -> Result<T, Self::Error>;

    fn extract_always(&self) -> T
    where
        Self: Extract<T, Error = Infallible>,
    {
        self.extract().unwrap()
    }
}

impl<C, T> Extract<T> for C
where
    T: FromContext<C>,
{
    type Error = T::Error;

    fn extract(&self) -> Result<T, Self::Error> {
        T::from_context(self)
    }
}

impl<T, C> FromContext<C> for Option<T>
where
    T: FromContext<C>,
{
    type Error = Infallible;

    fn from_context(context: &C) -> Result<Self, Self::Error> {
        Ok(T::from_context(context).ok())
    }
}

impl<T, C> FromContext<C> for Result<T, T::Error>
where
    T: FromContext<C>,
{
    type Error = Infallible;

    fn from_context(context: &C) -> Result<Self, Self::Error> {
        Ok(T::from_context(context))
    }
}

impl<C> FromContext<C> for () {
    type Error = Infallible;

    fn from_context(_: &C) -> Result<Self, Self::Error> {
        Ok(())
    }
}

macro_rules! impl_from_context {
    (
        $($ty:ident),*
    ) => {
        #[allow(non_snake_case)]
        impl<C, $($ty, )* > FromContext<C> for ($($ty,)*)
        where
            $( $ty: FromContext<C>, )*
        {
            type Error = BoxError;

            fn from_context(context: &C) -> Result<Self, Self::Error> {
                $(
                    let $ty = $ty::from_context(context).map_err(|err| err.into())?;
                )*

                Ok(($($ty,)*))
            }
        }
    }
}

all_the_tuples!(impl_from_context);