waterui_core/
extract.rs

1//! This module provides mechanisms for extracting values from the Environment.
2//!
3//! It defines the `Extractor` trait for types that can be extracted from an
4//! Environment, along with implementations for common types.
5//! The `Use<T>` wrapper provides a convenient way to extract specific types
6//! from the environment.
7
8use core::any::type_name;
9use core::ops::{Deref, DerefMut};
10
11use crate::Environment;
12use alloc::format;
13use anyhow::Error;
14/// A trait for extracting values from an Environment.
15///
16/// Types implementing this trait can be extracted from an Environment instance.
17/// This is useful for dependency injection and accessing shared resources.
18pub trait Extractor: 'static + Sized {
19    /// Attempts to extract an instance of `Self` from the given environment.
20    ///
21    /// # Errors
22    /// Returns an error if extraction fails, for example if the required value is not present in the environment.
23    fn extract(env: &Environment) -> Result<Self, Error>;
24}
25
26/// Wrapper struct for values that need to be used from the Environment.
27///
28/// This wrapper enables extracting values by type from an Environment.
29#[derive(Debug, Clone, PartialEq, Eq)]
30pub struct Use<T: 'static>(pub T);
31
32impl Extractor for Environment {
33    /// Extracts the Environment itself by creating a clone.
34    fn extract(env: &Environment) -> Result<Self, Error> {
35        Ok(env.clone())
36    }
37}
38
39impl<T> Deref for Use<T> {
40    type Target = T;
41
42    fn deref(&self) -> &Self::Target {
43        &self.0
44    }
45}
46
47impl<T> DerefMut for Use<T> {
48    fn deref_mut(&mut self) -> &mut Self::Target {
49        &mut self.0
50    }
51}
52
53impl<T: Extractor> Extractor for Option<T> {
54    /// Converts a regular extraction into an optional extraction.
55    ///
56    /// This implementation allows for graceful handling of extraction failures
57    /// by converting the error case into a `None` value.
58    fn extract(env: &Environment) -> Result<Self, Error> {
59        Ok(Extractor::extract(env).ok())
60    }
61}
62
63impl<T: 'static + Clone> Extractor for Use<T> {
64    /// Extracts a value of type T from the Environment.
65    ///
66    /// # Errors
67    /// Returns an error if the requested type is not present in the Environment.
68    fn extract(env: &Environment) -> Result<Self, Error> {
69        env.get::<T>().map_or_else(
70            || {
71                Err(Error::msg(format!(
72                    "Environment value `{}` not found",
73                    type_name::<T>()
74                )))
75            },
76            |value| Ok(Self(value.clone())),
77        )
78    }
79}