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
// Copyright 2024 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Common context abstractions.

/// A pair of core and bindings contexts.
///
/// This trait exists so implementers can be agnostic on the storage of the
/// contexts, since all we need from a context pair is mutable references from
/// both contexts.
pub trait ContextPair {
    /// The core context type held by this pair.
    type CoreContext;
    /// The bindings context type held by this pair.
    type BindingsContext;

    /// Gets a mutable reference to both contexts.
    fn contexts(&mut self) -> (&mut Self::CoreContext, &mut Self::BindingsContext);

    /// Gets a mutable reference to the core context.
    fn core_ctx(&mut self) -> &mut Self::CoreContext {
        let (core_ctx, _) = self.contexts();
        core_ctx
    }

    /// Gets a mutable reference to the bindings context.
    fn bindings_ctx(&mut self) -> &mut Self::BindingsContext {
        let (_, bindings_ctx) = self.contexts();
        bindings_ctx
    }
}

impl<'a, C> ContextPair for &'a mut C
where
    C: ContextPair,
{
    type CoreContext = C::CoreContext;
    type BindingsContext = C::BindingsContext;
    fn contexts(&mut self) -> (&mut Self::CoreContext, &mut Self::BindingsContext) {
        C::contexts(self)
    }
}

/// A type that provides a context implementation.
///
/// This trait allows for [`CtxPair`] to hold context implementations
/// agnostically of the storage method and how they're implemented. For example,
/// tests usually create API structs with a mutable borrow to contexts, while
/// the core context exposed to bindings is implemented on an owned [`CoreCtx`]
/// type.
///
/// The shape of this trait is equivalent to [`core::ops::DerefMut`] but we
/// decide against using that because of the automatic dereferencing semantics
/// the compiler provides around implementers of `DerefMut`.
pub trait ContextProvider {
    /// The context provided by this `ContextProvider`.
    type Context: Sized;

    /// Gets a mutable borrow to this context.
    fn context(&mut self) -> &mut Self::Context;
}

impl<'a, T: Sized> ContextProvider for &'a mut T {
    type Context = T;

    fn context(&mut self) -> &mut Self::Context {
        &mut *self
    }
}

/// A concrete implementation of [`ContextPair`].
///
///
/// `CtxPair` provides a [`ContextPair`] implementation when `CC` and `BC` are
/// [`ContextProvider`] and using their respective targets as the `CoreContext`
/// and `BindingsContext` associated types.
pub struct CtxPair<CC, BC> {
    /// The core context.
    pub core_ctx: CC,
    /// The bindings context.
    pub bindings_ctx: BC,
}

impl<CC, BC> ContextPair for CtxPair<CC, BC>
where
    CC: ContextProvider,
    BC: ContextProvider,
{
    type CoreContext = CC::Context;
    type BindingsContext = BC::Context;

    fn contexts(&mut self) -> (&mut Self::CoreContext, &mut Self::BindingsContext) {
        let Self { core_ctx, bindings_ctx } = self;
        (core_ctx.context(), bindings_ctx.context())
    }
}

/// A marker trait indicating that the implementor is not a test context.
///
/// This trait allows us to sidestep some blanket `Handler` implementations that
/// are provided by core types and overridden in specific test contexts.
///
/// See [this issue] for details on why this is needed in some other cases.
///
/// [this issue]: https://github.com/rust-lang/rust/issues/97811
pub trait NonTestCtxMarker {}