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
// Copyright 2017 The Exonum Team // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. use std::marker::PhantomData; use std::fmt; /// `ContextKey` provides strongly typed access to data inside `Context`. /// See `exonum::fabric::keys` for keys used by the exonum itself. pub struct ContextKey<T> { // These fields are public so that `context_key` // macro works outside of this crate. It should be // replaced with `const fn`, once it is stable. #[doc(hidden)] pub __name: &'static str, #[doc(hidden)] pub __phantom: PhantomData<T>, } // We need explicit `impl Copy` because derive won't work if `T: !Copy`. impl<T> Copy for ContextKey<T> {} // Bug in clippy, fixed on master branch. // spell-checker:ignore expl #[cfg_attr(feature = "cargo-clippy", allow(expl_impl_clone_on_copy))] impl<T> Clone for ContextKey<T> { fn clone(&self) -> Self { ContextKey { __name: self.__name, __phantom: self.__phantom, } } } impl<T> fmt::Debug for ContextKey<T> { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { write!(fmt, "ContextKey({:?})", self.__name) } } impl<T> ContextKey<T> { /// Name of this key. pub fn name(&self) -> &str { self.__name } } /// Constructs a `ContextKey` from a given name. /// /// # Examples /// /// ``` /// #[macro_use] /// extern crate exonum; /// use exonum::helpers::fabric::ContextKey; /// /// const NAME: ContextKey<String> = context_key!("name"); /// # fn main() {} /// ``` #[macro_export] macro_rules! context_key { ($name:expr) => {{ $crate::helpers::fabric::ContextKey { __name: $name, __phantom: ::std::marker::PhantomData } }} } #[test] fn key_is_copy() { const K: ContextKey<Vec<String>> = context_key!("k"); let x = K; let y = x; assert_eq!(x.name(), y.name()); }