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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
// SPDX-License-Identifier: Apache-2.0
/// Trait for types that have a null/sentinel value.
///
/// This trait allows multiformats types to define a "null" or sentinel value,
/// similar to `Option::None` but for types where a discriminated union isn't
/// appropriate. Common examples include null CIDs, null signatures, or
/// default/uninitialized identifiers.
///
/// # Use Cases
///
/// - Defining "zero" values for custom ID types
/// - Creating null/empty multiformats objects
/// - Sentinel values in data structures
/// - Default initialization for resource handles
///
/// # Thread Safety
///
/// This trait is `Send + Sync` safe when implemented on thread-safe types.
///
/// # Examples
///
/// ```rust
/// use multi_trait::Null;
///
/// #[derive(Debug, PartialEq)]
/// struct UserId(u64);
///
/// impl Null for UserId {
/// fn null() -> Self {
/// UserId(0)
/// }
///
/// fn is_null(&self) -> bool {
/// self.0 == 0
/// }
/// }
///
/// let null_user = UserId::null();
/// assert!(null_user.is_null());
///
/// let valid_user = UserId(42);
/// assert!(!valid_user.is_null());
/// ```
///
/// # Implementation Guidelines
///
/// The null value should be consistent and deterministic. For a given type:
/// - `T::null()` should always return the same logical value
/// - `T::null().is_null()` should always return `true`
/// - The null value should be a valid instance of the type
/// Fallible version of [`Null`] for types where null value creation can fail.
///
/// This trait is useful when:
/// - Null value creation requires allocation
/// - Validation is needed during null value construction
/// - Construction can fail in constrained environments
/// - External resources are needed to create the null value
///
/// # Relationship to `Null`
///
/// While [`Null`] provides infallible null value creation, `TryNull` handles
/// cases where construction might fail. If your type's null value is always
/// constructible, prefer implementing [`Null`] instead.
///
/// # Thread Safety
///
/// This trait is `Send + Sync` safe when implemented on thread-safe types
/// with thread-safe error types.
///
/// # Examples
///
/// ```rust
/// use multi_trait::TryNull;
///
/// #[derive(Debug)]
/// struct BufferId(Vec<u8>);
///
/// impl TryNull for BufferId {
/// type Error = std::collections::TryReserveError;
///
/// fn try_null() -> Result<Self, Self::Error> {
/// let mut vec = Vec::new();
/// vec.try_reserve(1)?;
/// vec.push(0);
/// Ok(BufferId(vec))
/// }
///
/// fn is_null(&self) -> bool {
/// self.0.len() == 1 && self.0[0] == 0
/// }
/// }
///
/// match BufferId::try_null() {
/// Ok(null_buf) => assert!(null_buf.is_null()),
/// Err(e) => eprintln!("Failed to create null buffer: {}", e),
/// }
/// ```
///
/// # Implementation Guidelines
///
/// - The error type should describe why null creation failed
/// - If `try_null()` succeeds, the result should satisfy `is_null()`
/// - The null value should be consistent across successful calls