grass/dev/public/
strategy.rs1use thiserror::Error;
2use tracing::info;
3
4use crate::dev::{
5 config,
6 strategy::{
7 alias::LocalAliasStrategy,
8 api::{LocalApiStrategy, MockApiStrategy},
9 discovery::LocalDiscoveryStrategy,
10 git::LocalGitStrategy,
11 path::LocalPathStrategy,
12 },
13};
14
15#[derive(Debug)]
16pub struct Api<T>(T);
17
18pub trait AccessApi<T> {
19 fn get_strategy(&self) -> &T;
20}
21
22impl<T> Api<T> {
23 pub fn new(value: T) -> Self {
24 Self(value)
25 }
26}
27
28impl<T> From<T> for Api<T> {
29 fn from(value: T) -> Self {
30 Self(value)
31 }
32}
33
34impl<T: Clone> From<&T> for Api<T> {
35 fn from(value: &T) -> Self {
36 Self(value.clone())
37 }
38}
39
40impl<T> AccessApi<T> for Api<T> {
41 fn get_strategy(&self) -> &T {
42 &self.0
43 }
44}
45
46#[macro_export]
47macro_rules! support_strategy {
48 ($trait_name:ident, $method_name:ident, $strategy_type:ident) => {
49 pub trait $trait_name {
50 type Strategy: $strategy_type;
51
52 fn $method_name(&self) -> &Self::Strategy;
53 }
54
55 impl<T> $crate::dev::public::strategy::Api<T>
56 where
57 T: $trait_name,
58 {
59 pub(crate) fn $method_name(&self) -> &T::Strategy {
60 $crate::dev::public::strategy::AccessApi::get_strategy(self).$method_name()
61 }
62 }
63 };
64}
65
66#[derive(Error, Debug)]
67pub enum LocalStrategyError {
68 #[error("Could not load user configuration\nReason: {reason}")]
69 LoadConfigError { reason: String },
70}
71
72pub fn use_local_strategy_with_default_config<T, U>(closure: T) -> Result<U, LocalStrategyError>
78where
79 T: Fn(Api<LocalApiStrategy>) -> Result<U, LocalStrategyError>,
80{
81 let config = config::load_user_config()
82 .map_err(|error| LocalStrategyError::LoadConfigError {
83 reason: error.to_string(),
84 })?
85 .grass;
86
87 let alias_strategy = LocalAliasStrategy::new(&config);
88 let path_strategy = LocalPathStrategy::new(&config);
89 let discovery_strategy = LocalDiscoveryStrategy::new(&config, &path_strategy);
90 let git_strategy = LocalGitStrategy::new(&path_strategy);
91
92 let api_strategy = LocalApiStrategy::new(
93 &alias_strategy,
94 &discovery_strategy,
95 &git_strategy,
96 &path_strategy,
97 );
98
99 info!("Using local strategy with default config");
100 closure(api_strategy.into())
101}
102
103pub fn use_mock_strategy() -> Api<MockApiStrategy> {
107 Api(MockApiStrategy::default())
108}