1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
//! Parameter normalization utilities for dioxus-provider
use Debug;
use Hash;
/// Trait for normalizing different parameter formats to work with providers
///
/// This trait allows the `use_provider` hook to accept parameters in different formats:
/// - `()` for no parameters
/// - `(param,)` for single parameter in tuple (e.g., `(42,)`)
/// - Common primitive types directly (e.g., `42`, `"foo".to_string()`)
/// - Custom types that implement the required bounds directly
///
/// # Custom Parameter Types
///
/// Custom types can be used directly as provider parameters by implementing the required bounds:
/// - `Clone + PartialEq + Hash + Debug + Send + Sync + 'static`
///
/// Use the `provider_param!` macro for convenience:
///
/// ```rust
/// use dioxus_provider::{prelude::*, provider_param};
///
/// #[derive(Clone, PartialEq, Eq, Hash, Debug)]
/// struct UserId(u32);
/// provider_param!(UserId); // Enable direct usage
///
/// #[provider]
/// async fn fetch_user(user_id: UserId) -> Result<User, String> { ... }
///
/// // Now you can use it directly:
/// let user = use_provider(fetch_user(), UserId(42));
/// ```
///
/// # Usage and Ambiguity
///
/// - If your provider expects a single parameter, you can pass it directly or as a single-element tuple.
/// - **Note:** Tuple syntax `(param,)` has priority over direct parameter syntax for types that implement both.
/// - For string parameters, both `String` and `&str` are supported directly.
///
/// # Examples
///
/// ```rust
/// use dioxus_provider::prelude::*;
///
/// #[provider]
/// async fn fetch_user(user_id: u32) -> Result<User, String> { ... }
///
/// // All of these are valid:
/// let user = use_provider(fetch_user(), 42); // direct primitive
/// let user = use_provider(fetch_user(), (42,)); // single-element tuple
/// let user = use_provider(fetch_user(), "foo".to_string()); // String
/// ```
/// Sealed trait to control which types can be used directly as provider parameters
///
/// This prevents conflicts between the blanket implementation and the tuple implementation.
/// Types that implement this trait (along with the required bounds) can be used directly
/// as provider parameters without requiring tuple wrappers.
// Implementation for no parameters: () -> ()
// Implementation for tuple parameters: (Param,) -> Param
// This has higher priority than the blanket implementation due to Rust's orphan rules
// Blanket implementation for direct parameters
// This allows any type that implements the required bounds AND the sealed trait
// to be used directly as a provider parameter
/// Macro to enable a custom type to be used directly as a provider parameter
///
/// This macro implements the sealed `DirectParam` trait for your type, allowing it
/// to be used with the blanket `IntoProviderParam` implementation.
///
/// # Requirements
///
/// Your type must implement:
/// - `Clone + PartialEq + Hash + Debug + Send + Sync + 'static`
///
/// # Example
///
/// ```rust
/// use dioxus_provider::{prelude::*, provider_param};
///
/// #[derive(Clone, PartialEq, Eq, Hash, Debug)]
/// struct UserId(u32);
///
/// #[derive(Clone, PartialEq, Eq, Hash, Debug)]
/// struct ProductId(String);
///
/// // Enable direct usage as provider parameters
/// provider_param!(UserId);
/// provider_param!(ProductId);
///
/// #[provider]
/// async fn fetch_user(user_id: UserId) -> Result<User, String> { ... }
///
/// #[provider]
/// async fn fetch_product(product_id: ProductId) -> Result<Product, String> { ... }
///
/// // Now you can use them directly:
/// let user = use_provider(fetch_user(), UserId(42));
/// let product = use_provider(fetch_product(), ProductId("abc".to_string()));
/// ```