1 // Copyright 2023 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 //! Common utilities used by other modules within this crate.
15 
16 use handle_map::HandleLike;
17 
18 /// Type-level predicate for handle types which uniformly hold a lock
19 /// for longer than some other handle type in API calls.
20 ///
21 /// Largely an informative marker trait used to indicate the
22 /// lock ordering on types.
23 #[allow(dead_code)]
24 pub(crate) trait LocksLongerThan<H: HandleLike>: HandleLike {}
25 
26 /// Trait which canonicalizes the relationship between FFI
27 /// tagged-unions and their tags
28 pub trait FfiEnum {
29     /// The [FFI-safe] type of tags used to identify
30     /// variants of this tagged union.
31     type Kind;
32 
33     /// Returns the tag for this FFI-safe tagged union.
kind(&self) -> Self::Kind34     fn kind(&self) -> Self::Kind;
35 }
36 
37 /// Declares a method of the given name which attempts to cast
38 /// the enclosing enum to the payload held under the given
39 /// variant name, yielding a result of the given type wrapped
40 /// in an `Option::Some`.
41 ///
42 /// If the enclosing enum turns out to not be the requested
43 /// variant, the generated method will return `None`.
44 #[macro_export]
45 macro_rules! declare_enum_cast {
46     ($projection_method_name:ident, $variant_enum_name:ident, $variant_type_name:ty) => {
47         #[doc = concat!("Attempts to cast `self` to the `", stringify!($variant_enum_name),
48           "` variant, returning `None` in the \ncase where the passed value is of a different enum variant.")]
49         pub fn $projection_method_name(self) -> Option<$variant_type_name> {
50             match self {
51                 Self::$variant_enum_name(x) => Some(x),
52                 _ => None,
53             }
54         }
55     }
56 }
57