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
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
//! Abstracts the various ways to provide an initial value to static cell types
//! (e.g., [`Mutex`][1]). It's mostly used through their definer types.
//!
//! [1]: crate::sync::mutex::StaticMutex
use core::{cell::UnsafeCell, marker::PhantomData, mem::MaybeUninit};

use crate::bind::{bind, bind_default, Bind, FnBind};
use r3_core::{
    hunk::Hunk,
    kernel::{cfg::Cfg, traits},
    utils::Init,
};

/// Abstracts the various ways to provide an initial value to static cell types
/// (e.g., [`Mutex`][1]). It's mostly used through their definer types.
///
/// # Stability
///
/// This trait is unstable.
///
/// [1]: crate::sync::mutex::StaticMutex
#[const_trait]
pub trait Source<System> {
    type Target: 'static;

    /// Construct a `Hunk` to store the value.
    ///
    /// `Self::Target` in the returned `Hunk` is safe to access from executable
    /// objects through `MaybeUninit`. The client may grant mutable access to
    /// `Self::Target` through `UnsafeCell` while observing the borrow rules.
    /// <!-- [tag:source_cell] -->
    fn into_unsafe_cell_hunk<C>(
        self,
        cfg: &mut Cfg<C>,
    ) -> Hunk<System, UnsafeCell<MaybeUninit<Self::Target>>>
    where
        C: ~const traits::CfgBase<System = System>;
}

/// A [`Source`][] that provides a hunk initialized by
/// [`Default::default`][].
pub struct DefaultSource<T>(PhantomData<T>);

impl<T> Init for DefaultSource<T> {
    const INIT: Self = Self(PhantomData);
}

impl<System, T> const Source<System> for DefaultSource<T>
where
    System: traits::KernelBase + traits::KernelStatic,
    T: 'static + Default + Send,
{
    type Target = T;

    fn into_unsafe_cell_hunk<C>(
        self,
        cfg: &mut Cfg<C>,
    ) -> Hunk<System, UnsafeCell<MaybeUninit<Self::Target>>>
    where
        C: ~const traits::CfgBase<System = System>,
    {
        TakeBindSource(bind_default(cfg)).into_unsafe_cell_hunk(cfg)
    }
}

/// A [`Source`][] that provides a hunk initialized by a user-provided
/// initializer.
pub struct NewBindSource<Binder, Func> {
    pub binder: Binder,
    pub func: Func,
}

impl<System, Binder, Func> const Source<System> for NewBindSource<Binder, Func>
where
    System: traits::KernelBase + traits::KernelStatic,
    Func: ~const FnBind<Binder>,
    Func::Output: Send,
{
    type Target = Func::Output;

    fn into_unsafe_cell_hunk<C>(
        self,
        cfg: &mut Cfg<C>,
    ) -> Hunk<System, UnsafeCell<MaybeUninit<Self::Target>>>
    where
        C: ~const traits::CfgBase<System = System>,
    {
        let Self { binder, func } = self;
        TakeBindSource(bind(binder, func).finish(cfg)).into_unsafe_cell_hunk(cfg)
    }
}

/// A [`Source`][] that consumes a user-provided binding.
pub struct TakeBindSource<'pool, System, T>(pub(crate) Bind<'pool, System, T>);

impl<System, T> const Source<System> for TakeBindSource<'_, System, T>
where
    System: traits::KernelBase + traits::KernelStatic,
    T: 'static + Send,
{
    type Target = T;

    fn into_unsafe_cell_hunk<C>(
        self,
        cfg: &mut Cfg<C>,
    ) -> Hunk<System, UnsafeCell<MaybeUninit<Self::Target>>>
    where
        C: ~const traits::CfgBase<System = System>,
    {
        // Dummy depenedency to keep the binding alive
        bind((self.0.take_mut(),), |_: &mut _| {})
            .unpure()
            .finish(cfg);

        // Take the raw `Hunk<_, BindData<T>>` and transmute it into `Hunk<_,
        // UnsafeCell<MaybeUninit<T>>>`
        // Safety: The dummy dependency defined above ensures exclusive access
        // to the hunk. `UnsafeCell<MaybeUninit<T>>` has a compatible
        // representation with `BindData<T>`.
        unsafe { self.0.hunk().transmute::<UnsafeCell<MaybeUninit<T>>>() }
    }
}

/// A [`Source`][] that provides a user-provided hunk, assuming the provider
/// upholds the safety rules.
pub struct HunkSource<System, T>(pub(crate) Hunk<System, UnsafeCell<MaybeUninit<T>>>);

impl<System, T> const Source<System> for HunkSource<System, T>
where
    T: 'static,
{
    type Target = T;

    fn into_unsafe_cell_hunk<C>(
        self,
        _: &mut Cfg<C>,
    ) -> Hunk<System, UnsafeCell<MaybeUninit<Self::Target>>>
    where
        C: ~const traits::CfgBase<System = System>,
    {
        self.0
    }
}

#[macropol::macropol] // Replace `$metavariables` in literals and doc comments
macro_rules! impl_source_setter {
    (
        $( #[$($meta:tt)*] )*
        impl $DefinerName:ident<$($Param:tt)*
    ) => {
        impl_source_setter! {
            @iter
            attributes: {{ $( #[$($meta)*] )* }},
            definer_name: {{ $DefinerName }},
            generics: {{ }},
            definer_ty: {{ $DefinerName< }},
            param_template: {{ $($Param)* }},
            concrete_source_var: {{ $ConcreteSource }},
        }
    };

    // Preprocessing
    // -------------------------------------------------------------------
    //
    // These rules consume `param_template` one token tree by one and produce
    // `generics` and `definer_ty`.
    (@iter
        attributes: {$attributes:tt},
        definer_name: {$definer_name:tt},
        generics: {$generics:tt},
        definer_ty: {{ $( $definer_ty:tt )* }},
        param_template: {{> $($rest:tt)* }},
        concrete_source_var: {$concrete_source_var:tt},
    ) => {
        $(
            compile_error!(concat!("Extra token in input: `$&rest`"));
        )*

        impl_source_setter! {
            @end
            attributes: {$attributes},
            definer_name: {$definer_name},
            generics: {$generics},
            definer_ty: {{ $( $definer_ty )* > }},
            concrete_source_var: {$concrete_source_var},
        }
    };

    (@iter
        attributes: {$attributes:tt},
        definer_name: {$definer_name:tt},
        generics: {{ $( $generics:tt )* }},
        definer_ty: {{ $( $definer_ty:tt )* }},
        param_template: {{ #Source $($rest:tt)* }},
        concrete_source_var: {{ $( $concrete_source_var:tt )* }},
    ) => {
        impl_source_setter! {
            @iter
            attributes: {$attributes},
            definer_name: {$definer_name},
            generics: {{ $( $generics )* T }},
            definer_ty: {{ $( $definer_ty )* $( $concrete_source_var )* }},
            param_template: {{ $($rest)* }},
            concrete_source_var: {{ $( $concrete_source_var )* }},
        }
    };

    (@iter
        attributes: {$attributes:tt},
        definer_name: {$definer_name:tt},
        generics: {{ $( $generics:tt )* }},
        definer_ty: {{ $( $definer_ty:tt )* }},
        param_template: {{ $any:tt $($rest:tt)* }},
        concrete_source_var: { $concrete_source_var:tt },
    ) => {
        impl_source_setter! {
            @iter
            attributes: {$attributes},
            definer_name: {$definer_name},
            generics: {{ $( $generics )* $any }},
            definer_ty: {{ $( $definer_ty )* $any }},
            param_template: {{ $($rest)* }},
            concrete_source_var: { $concrete_source_var },
        }
    };

    // Output
    // -------------------------------------------------------------------
    (@end
        attributes: {{
            // When this attribute is present, `init[_bind]` will automatically
            // wrap the output with the specified wrapper type.
            $( #[autowrap($wrap_with:expr, $Wrapper:ident)] )?
            // The opposite of `#[autowrap]`. `$no_autowrap` == `()`
            $( #[no_autowrap$no_autowrap:tt] )?
        }},
        definer_name: {{ $definer_name:ident }},
        // Generic parameters. `#Source` is replaced with `T` here.
        generics: {{ $( $generics:tt )* }},
        // A template for a concrete definer type.
        // `#Source` is replaced with `$ConcreteSource` here.
        definer_ty: {{ $( $definer_ty:tt )* }},
        concrete_source_var: {{ $( $concrete_source_var:tt )* }},
    ) => {
        // The anonymous `const` trick to introduce scoping breaks
        // documentation, unfortunately.
        mod __pr {
            pub use crate::{
                sync::source::{Source, NewBindSource, TakeBindSource, HunkSource},
                bind::{Bind, fn_bind_map, FnBindMap},
                hunk::Hunk,
            };
            pub use core::{cell::UnsafeCell, mem::MaybeUninit};
        }

        macro_rules! Definer {
            ( $( $concrete_source_var )*:ty ) => { $( $definer_ty )* };
        }

        // `#[autowrap]`
        $(
            #[allow(type_alias_bounds)]  // [ref:impl_trait_false_type_alias_bounds]
            type MappedFunc<Func, T: 'static> = __pr::FnBindMap<
                Func,
                impl FnOnce(T) -> $Wrapper<T> + Send + Copy + 'static
            >;
            type AutoWrapped<T> = $Wrapper<T>;
            macro MappedFunc($Func:ty, $T:ty) { MappedFunc<$Func, $T> }
        )?

        // `#[no_autowrap]`
        $(
            type AutoWrapped<T> = T;
            /// $&no_autowrap
            macro MappedFunc($Func:ty, $T:ty) { $Func }
        )?

        /// # Initial Value
        ///
        /// The following methods specify the initial value for the contained
        /// object (`T`).
        ///
        /// If none of the following methods are called, `T` will be constructed
        /// by its [`Default`][] implementation.
        // [tag:default_source_is_default] `DefaultSource<T>` is the default, so
        // the following `impl` block allows up to only one modification to
        // `Self::source`.
        impl<$( $generics )*> Definer!(DefaultSource<AutoWrapped<T>>)
        where
            T: 'static
        {
            /// Use the specified function to provide the initial value.
            ///
            /// The semantics of the method's parameter is similar to that of
            /// [`BindDefiner::init`][1].
            ///
            /// [1]: crate::bind::BindDefiner::init
            pub const fn init<Func>(self, func: Func)
                -> Definer!(__pr::NewBindSource<(), MappedFunc!(Func, T)>)
            where
                // Demand the unchangedness of `Source::Target` so that the
                // initial creation of `Self` doesn't have an unconstrained `T`
                __pr::NewBindSource<(), MappedFunc!(Func, T)>:
                    __pr::Source<System, Target = AutoWrapped<T>>,
            {
                $definer_name {
                    source: __pr::NewBindSource {
                        binder: (),
                        func $( : __pr::fn_bind_map(func, $wrap_with) )?,
                    },
                    ..self
                }
            }

            /// Use the specified function with dependency to provide the
            /// initial value.
            ///
            /// The semantics of the method's parameters is similar to that of
            /// [`BindDefiner::init_with_bind`][1].
            ///
            /// [1]: crate::bind::BindDefiner::init_with_bind
            pub const fn init_with_bind<Binder, Func>(
                self,
                binder: Binder,
                func: Func,
            ) -> Definer!(__pr::NewBindSource<Binder, MappedFunc!(Func, T)>)
            where
                // Demand the unchangedness of `Source::Target` so that the
                // initial creation of `Self` doesn't have an unconstrained `T`
                __pr::NewBindSource<Binder, MappedFunc!(Func, T)>:
                    __pr::Source<System, Target = AutoWrapped<T>>,
            {
                $definer_name {
                    source: __pr::NewBindSource {
                        binder,
                        func $( : __pr::fn_bind_map(func, $wrap_with) )?,
                    },
                    ..self
                }
            }

            /// [Take] the specified binding to use as this object's contents.
            ///
            $(
            /// <div class="admonition-follows"></div>
            ///
            /// > **Warning:** Unlike [`mutex::Definer::take_bind`][1], this
            /// > method expects that `T` is already wrapped by `$&Wrapper` in
            /// > the specified binding.
            ///
            /// [1]: crate::sync::mutex::Definer::take_bind
            /// [2]: crate::bind::Bind::transmute
            )?
            ///
            /// [Take]: crate::bind::Bind::take_mut
            pub const fn take_bind<'pool>(
                self,
                bind: __pr::Bind<'pool, System, AutoWrapped<T>>,
            ) -> Definer!(__pr::TakeBindSource<'pool, System, AutoWrapped<T>>) {
                $definer_name {
                    source: __pr::TakeBindSource(bind),
                    ..self
                }
            }

            /// Use the specified existing hunk as this object's storage.
            ///
            $(
            /// <div class="admonition-follows"></div>
            ///
            /// > **Warning:**
            /// > Unlike [`mutex::Definer::wrap_hunk_unchecked`][1], this
            /// > method expects that `T` is already wrapped by `$&Wrapper` in
            /// > the specified binding. *A care must be taken not to
            /// > accidentally [transmute][2] `T` into `$&Wrapper<T>`* when
            /// > passing a hunk that has the same representation as `T` but
            /// > requires transmutation due to having a different set of
            /// > wrappers, such as `MaybeUninit` and `UnsafeCell`.
            ///
            /// [1]: crate::sync::mutex::Definer::take_bind
            /// [2]: crate::hunk::Hunk::transmute
            )?
            ///
            /// # Safety
            ///
            /// This object grants exclusive access (`&mut T`) to the
            /// `UnsafeCell`'s contents based on the assumption that no accesses
            /// are made through other means, and that `T` is initialized by
            /// the time the boot phase completes.
            pub const unsafe fn wrap_hunk_unchecked<'pool>(
                self,
                hunk: __pr::Hunk<System, __pr::UnsafeCell<__pr::MaybeUninit<AutoWrapped<T>>>>,
            ) -> Definer!(__pr::HunkSource<System, AutoWrapped<T>>)
            {
                $definer_name {
                    source: __pr::HunkSource(hunk),
                    ..self
                }
            }
        }
    };
}