Skip to main content

netstack3_base/
uninstantiable.rs

1// Copyright 2022 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5//! A collection of uninstantiable types.
6//!
7//! These uninstantiable types can be used to satisfy trait bounds in
8//! uninstantiable situations. Different parts of core provide implementations
9//! of their local traits on these types, so they can be used in uninstantiable
10//! contexts.
11
12use core::marker::PhantomData;
13
14use explicit::UnreachableExt as _;
15
16use crate::{
17    BidirectionalConverter, CoreTimerContext, CoreTxMetadataContext, CounterContext, Device,
18    DeviceIdContext, ResourceCounterContext, TimerBindingsTypes, TxMetadataBindingsTypes,
19};
20
21/// An uninstantiable type.
22#[derive(Clone, Copy)]
23pub struct Uninstantiable(!);
24
25impl AsRef<!> for Uninstantiable {
26    fn as_ref(&self) -> &! {
27        &self.0
28    }
29}
30
31impl<I, O> BidirectionalConverter<I, O> for Uninstantiable {
32    fn convert_back(&self, _: O) -> I {
33        self.uninstantiable_unreachable()
34    }
35    fn convert(&self, _: I) -> O {
36        self.uninstantiable_unreachable()
37    }
38}
39
40/// An uninstantiable type that wraps an instantiable type, `A`.
41///
42/// This type can be used to more easily implement traits where `A` already
43/// implements the trait.
44// TODO(https://github.com/rust-lang/rust/issues/118212): Simplify the trait
45// implementations once Rust supports function delegation. Those impls are
46// spread among the core crates.
47pub struct UninstantiableWrapper<A>(!, PhantomData<A>);
48
49impl<A> AsRef<!> for UninstantiableWrapper<A> {
50    fn as_ref(&self) -> &! {
51        let Self(never, _marker) = self;
52        &never
53    }
54}
55
56impl<T, BT, C> CoreTimerContext<T, BT> for UninstantiableWrapper<C>
57where
58    BT: TimerBindingsTypes,
59    C: CoreTimerContext<T, BT>,
60{
61    fn convert_timer(dispatch_id: T) -> BT::DispatchId {
62        C::convert_timer(dispatch_id)
63    }
64}
65
66impl<P, C> CounterContext<C> for UninstantiableWrapper<P> {
67    fn counters(&self) -> &C {
68        self.uninstantiable_unreachable()
69    }
70}
71
72impl<P, R, C> ResourceCounterContext<R, C> for UninstantiableWrapper<P> {
73    fn per_resource_counters(&self, _resource: &R) -> &C {
74        self.uninstantiable_unreachable()
75    }
76}
77
78impl<T, BT, C> CoreTxMetadataContext<T, BT> for UninstantiableWrapper<C>
79where
80    BT: TxMetadataBindingsTypes,
81{
82    fn convert_tx_meta(&self, _tx_meta: T) -> BT::TxMetadata {
83        self.uninstantiable_unreachable()
84    }
85}
86
87impl<D: Device, C: DeviceIdContext<D>> DeviceIdContext<D> for UninstantiableWrapper<C> {
88    type DeviceId = C::DeviceId;
89    type WeakDeviceId = C::WeakDeviceId;
90}
91
92impl<A: Iterator> Iterator for UninstantiableWrapper<A> {
93    type Item = A::Item;
94
95    fn next(&mut self) -> Option<Self::Item> {
96        self.uninstantiable_unreachable()
97    }
98}