How to use following data structure of solidity in substrate? - substrate

How to use following data structure of solidity in substrate?
struct SortitionSumTree {
uint K;
uint[] stack;
uint[] nodes;
mapping(bytes32 => uint) IDsToTreeIndexes;
mapping(uint => bytes32) nodeIndexesToIDs;
}
/* Storage */
struct SortitionSumTrees {
mapping(bytes32 => SortitionSumTree) sortitionSumTrees;
}
Should I use BTreeMap instead of mapping of solidity in the struct?
https://paritytech.github.io/substrate/master/sp_std/collections/btree_map/struct.BTreeMap.html
#[derive(PartialEq, Eq, PartialOrd, Ord, Default, Clone, Encode, Decode, TypeInfo)]
#[cfg_attr(feature = "std", derive(Debug))]
pub struct SortitionSumTree {
pub k: u128,
pub stack: u128,
pub nodes: u128,
pub ids_to_tree_indexes: BTreeMap<Vec<u8>, u128>,
pub node_indexes_to_ids: BTreeMap<u128, Vec<u8>>,
}
#[pallet::storage]
#[pallet::getter(fn sortition_sum_trees)]
pub type SortitionSumTrees<T> = StorageMap<_,Blake2_128Concat, Vec<u8>, SortitionSumTree>;
Is it right way of doing it in substrate?

Related

How to Sort Vector of Structs by Chronos DateTime Field?

I have this struct
pub struct Items {
pub symbol: String,
pub price: f64,
pub date: DateTime<Utc>,
}
I have a vector of these structs. I would like to sort them by date. How would I go about doing that? I tried deriving PartialEq, Ord, Eq, etc... but Rust complains about the float fields.
The easiest way is to use one of the provides sort functions implemented for Vec like sort_by, sort_by_key, or sort_by_key_cached.
// Using sort_by
foo_items.sort_by(|a, b| a.date.cmp(&b.date));
// Using sort_by_key
foo_items.sort_by_key(|x| x.date);
// Using sort_by_key_cached (Faster if key is very large)
foo_items.sort_by_cached_key(|x| x.date);
And don't forget you always have the option to manually implement traits that are normally derived.
use std::cmp::Ordering;
impl PartialEq for Items {
fn eq(&self, other: &Self) -> bool {
// idk what symbol is, but use it anyway
self.symbol == other.symbol && self.date == other.date
}
}
impl Eq for Items {}
impl PartialOrd for Items {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.date.partial_cmp(&other.date)
}
}
impl Ord for Items {
fn cmp(&self, other: &Self) -> Ordering {
self.date.cmp(&other.date)
}
}
#[derive(Debug)]
pub struct S {
pub s: f64,
}
fn main() {
let mut v = vec![S{s:0.3}, S{s:1.3}, S{s:7.3}];
v.sort_by(|a, b| a.s.partial_cmp(&b.s).unwrap());
println!("{:#?}",v);
}

WMI releases my implementation of IWbemQuerySink too many times (ExecQueryAsync): refcount turns negative

I've implemented the IWbemQuerySink in rust, in order to use ExecQueryAsync. Code is available in this pull request but I'll post the relevant bits here.
TLDR;
WMI is calling Release() 5 times on my QuerySink implementation, 1 which is understandable, and 4 which are not... There is only 1 call to AddRef by WMI, so the question is: where do this 4 other calls to Release comes from and is there a way to prevent them from happening?
With a lot of details
Here is a simplified implementation, it is working great:
use winapi::{
um::wbemcli::{
{IWbemClassObject,IWbemObjectSink, IWbemObjectSinkVtbl},
WBEM_S_NO_ERROR,
},
shared::{
ntdef::HRESULT,
wtypes::BSTR,
},
ctypes::{
c_long,
},
};
use com_impl::{ComImpl, VTable, Refcount};
use wio::com::ComPtr;
#[repr(C)]
#[derive(ComImpl)]
#[interfaces(IWbemObjectSink)]
pub struct QuerySink {
vtbl: VTable<IWbemObjectSinkVtbl>,
refcount: Refcount,
}
impl QuerySink {
pub fn new() -> ComPtr<IWbemObjectSink> {
let ptr = QuerySink::create_raw();
let ptr = ptr as *mut IWbemObjectSink;
unsafe { ComPtr::from_raw(ptr) }
}
}
// AddRef and Release methods are provided by com_impl
#[com_impl::com_impl]
unsafe impl IWbemObjectSink for QuerySink {
pub unsafe fn indicate(
&self,
_lObjectCount: c_long,
_apObjArray: *mut *mut IWbemClassObject
) -> HRESULT {
WBEM_S_NO_ERROR as i32
}
pub unsafe fn set_status(
&self,
_lFlags: c_long,
_hResult: HRESULT,
_strParam: BSTR,
_pObjParam: *mut IWbemClassObject
) -> HRESULT {
WBEM_S_NO_ERROR as i32
}
}
Let's try to use it in a simple call to ExecQueryAsync:
pub fn exec_async_query_native_wrapper(
&self,
query: impl AsRef<str>,
) -> Result<(), WMIError> {
let query_language = BStr::from_str("WQL")?;
let query = BStr::from_str(query.as_ref())?;
let p_sink: ComPtr<IWbemObjectSink> = QuerySink::new();
unsafe {
check_hres((*self.svc()).ExecQueryAsync(
query_language.as_bstr(),
query.as_bstr(),
WBEM_FLAG_BIDIRECTIONAL as i32,
ptr::null_mut(),
p_sink.as_raw(),
))?;
}
Ok(())
}
When executing it in a test, this code panics because the release function is called too many times, and the Refcount becomes negative:
attempt to subtract with overflow', C:\Users\apennamen\.cargo\registry\src\github.com-1ecc6299db9ec823\com-impl-0.1.1\src\lib.rs:139:9
stack backtrace:
0: std::panicking::begin_panic_handler
at /rustc/b32e6e6ac8921035177256ab6806e6ab0d4b9b94\/library\std\src\panicking.rs:493
1: core::panicking::panic_fmt
at /rustc/b32e6e6ac8921035177256ab6806e6ab0d4b9b94\/library\core\src\panicking.rs:92
2: core::panicking::panic
at /rustc/b32e6e6ac8921035177256ab6806e6ab0d4b9b94\/library\core\src\panicking.rs:50
3: com_impl::Refcount::release
at C:\Users\apennamen\.cargo\registry\src\github.com-1ecc6299db9ec823\com-impl-0.1.1\src\lib.rs:139
4: wmi::query_sink::QuerySink::__com_impl__IUnknown__Release
at .\src\query_sink.rs:31
5: CoMarshalInterface
6: CoMarshalInterface
.....
After some tests, I found that the Release method is called 4 times more than it should be by WMI. So when adding 4 calls to AddRef, the code works just fine. This is of course not satisfying as maybe tomorrow it will be 5 calls, or 10 or 2...
I don't know how to handle this problem, hopefully someone else ran into it
This is a hacky working code:
pub fn exec_async_query_native_wrapper(
&self,
query: impl AsRef<str>,
) -> Result<(), WMIError> {
let query_language = BStr::from_str("WQL")?;
let query = BStr::from_str(query.as_ref())?;
let p_sink: ComPtr<IWbemObjectSink> = QuerySink::new();
unsafe {
// FIXME hack the RefCount
for _ in 0..4 { p_sink.AddRef(); }
check_hres((*self.svc()).ExecQueryAsync(
query_language.as_bstr(),
query.as_bstr(),
WBEM_FLAG_BIDIRECTIONAL as i32,
ptr::null_mut(),
p_sink.as_raw(),
))?;
}
Ok(())
}
}
Thank you for reading this far :)
EDIT :
Here is the expanded macro code:
#[cfg(feature = "async-query")]
pub(crate) mod query_sink {
use winapi::{
um::wbemcli::{
{IWbemClassObject, IWbemObjectSink, IWbemObjectSinkVtbl}, WBEM_S_NO_ERROR,
WBEM_STATUS_COMPLETE,
},
shared::{
ntdef::HRESULT,
wtypes::BSTR,
winerror::{E_POINTER, E_FAIL},
},
ctypes::{c_long},
};
use com_impl::{ComImpl, VTable, Refcount};
use log::{trace, warn};
use std::ptr::NonNull;
use wio::com::ComPtr;
use crate::result_enumerator::IWbemClassWrapper;
use crate::WMIError;
/// Implementation for [IWbemObjectSink](https://learn.microsoft.com/en-us/windows/win32/api/wbemcli/nn-wbemcli-iwbemobjectsink).
/// This [Sink](https://en.wikipedia.org/wiki/Sink_(computing))
/// receives asynchronously the result of the query,
/// through Indicate calls. When finished,the SetStatus method
/// is called.
/// # <https://learn.microsoft.com/fr-fr/windows/win32/wmisdk/example--getting-wmi-data-from-the-local-computer-asynchronously>
#[repr(C)]
#[interfaces(IWbemObjectSink)]
pub struct QuerySink {
vtbl: VTable<IWbemObjectSinkVtbl>,
refcount: Refcount,
}
impl QuerySink {
fn create_raw() -> *mut Self {
Box::into_raw(Box::new(QuerySink {
vtbl: <Self as com_impl::BuildVTable<_>>::static_vtable(),
refcount: Default::default(),
}))
}
}
unsafe impl com_impl::BuildVTable<winapi::um::unknwnbase::IUnknownVtbl> for QuerySink {
const VTBL: winapi::um::unknwnbase::IUnknownVtbl = winapi::um::unknwnbase::IUnknownVtbl {
AddRef: Self::__com_impl__IUnknown__AddRef,
Release: Self::__com_impl__IUnknown__Release,
QueryInterface: Self::__com_impl__IUnknown__QueryInterface,
};
fn static_vtable() -> com_impl::VTable<winapi::um::unknwnbase::IUnknownVtbl> {
com_impl::VTable::new(&Self::VTBL)
}
}
#[allow(non_snake_case)]
impl QuerySink {
#[inline(never)]
unsafe extern "system" fn __com_impl__IUnknown__AddRef(
this: *mut winapi::um::unknwnbase::IUnknown,
) -> u32 {
let this = &*(this as *const Self);
this.refcount.add_ref()
}
#[inline(never)]
unsafe extern "system" fn __com_impl__IUnknown__Release(
this: *mut winapi::um::unknwnbase::IUnknown,
) -> u32 {
let ptr = this as *mut Self;
let count = (*ptr).refcount.release();
if count == 0 {
Box::from_raw(ptr);
}
count
}
#[inline(never)]
unsafe extern "system" fn __com_impl__IUnknown__QueryInterface(
this: *mut winapi::um::unknwnbase::IUnknown,
riid: *const winapi::shared::guiddef::IID,
ppv: *mut *mut winapi::ctypes::c_void,
) -> winapi::shared::winerror::HRESULT {
if ppv.is_null() {
return winapi::shared::winerror::E_POINTER;
}
if winapi::shared::guiddef::IsEqualIID(
&*riid,
&<winapi::um::unknwnbase::IUnknown as winapi::Interface>::uuidof(),
) || winapi::shared::guiddef::IsEqualIID(
&*riid,
&<IWbemObjectSink as winapi::Interface>::uuidof(),
) {
*ppv = this as *mut winapi::ctypes::c_void;
winapi::shared::winerror::S_OK
} else {
*ppv = std::ptr::null_mut();
winapi::shared::winerror::E_NOINTERFACE
}
}
}
impl QuerySink {
pub fn new() -> ComPtr<IWbemObjectSink> {
let ptr = QuerySink::create_raw();
let ptr = ptr as *mut IWbemObjectSink;
unsafe { ComPtr::from_raw(ptr) }
}
}
unsafe impl com_impl::BuildVTable<IWbemObjectSinkVtbl> for QuerySink {
const VTBL: IWbemObjectSinkVtbl = IWbemObjectSinkVtbl {
parent: <Self as com_impl::BuildVTable<_>>::VTBL,
Indicate: Self::__com_impl_stub__IWbemObjectSink__Indicate,
SetStatus: Self::__com_impl_stub__IWbemObjectSink__SetStatus,
};
fn static_vtable() -> com_impl::VTable<IWbemObjectSinkVtbl> {
com_impl::VTable::new(&Self::VTBL)
}
}
#[allow(non_snake_case)]
impl QuerySink {
#[inline(never)]
unsafe extern "system" fn __com_impl_stub__IWbemObjectSink__Indicate(
this: *mut IWbemObjectSink,
__com_arg_0: c_long,
__com_arg_1: *mut *mut IWbemClassObject,
) -> HRESULT {
let this = &*(this as *const Self);
Self::__com_impl_body__IWbemObjectSink__Indicate(this, __com_arg_0, __com_arg_1)
}
#[inline(never)]
unsafe extern "system" fn __com_impl_stub__IWbemObjectSink__SetStatus(
this: *mut IWbemObjectSink,
__com_arg_0: c_long,
__com_arg_1: HRESULT,
__com_arg_2: BSTR,
__com_arg_3: *mut IWbemClassObject,
) -> HRESULT {
let this = &*(this as *const Self);
Self::__com_impl_body__IWbemObjectSink__SetStatus(
this,
__com_arg_0,
__com_arg_1,
__com_arg_2,
__com_arg_3,
)
}
#[inline(always)]
unsafe extern "system" fn __com_impl_body__IWbemObjectSink__Indicate(
&self,
lObjectCount: c_long,
apObjArray: *mut *mut IWbemClassObject,
) -> HRESULT {
WBEM_S_NO_ERROR as i32
}
#[inline(always)]
unsafe extern "system" fn __com_impl_body__IWbemObjectSink__SetStatus(
&self,
lFlags: c_long,
_hResult: HRESULT,
_strParam: BSTR,
_pObjParam: *mut IWbemClassObject,
) -> HRESULT {
WBEM_S_NO_ERROR as i32
}
}
}

How do I implement a trait for an enum and its respective variants?

I'm trying to use enum variants to capture data which is heterogeneous in nature (has different collections of fields) but which is of the same "type" from a protocol perspective. However, I'm not sure how to implement subtype-specific methods and traits. Here is a minimal example of how I can create an enumeration of Data and I can use enum variant constructors to specify the types, but if I implement a trait on the variant, calling that function is not something I've figured out how to do.
use std::fmt;
enum Data {
N(NData),
S(SData),
}
struct NData {
numeric: u32,
}
impl fmt::Display for NData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.numeric)
}
}
struct SData {
stringy: Vec<String>,
}
fn main() {
let d_n: Data = Data::N(NData { numeric: 0x0 });
let n = NData { numeric: 0xff };
// Fails, fmt::Display not implemented for Data
println!("{}", d_n);
// Just fine!
println!("{}", n);
}
One possible solution could be to implement your trait for the variants as well as for the enum, which as you can see here only calls the specific implementations of the variants:
use std::fmt;
struct NData {
numeric: u32,
}
impl fmt::Display for NData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.numeric)
}
}
struct SData {
strings: Vec<String>,
}
impl fmt::Display for SData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.strings)
}
}
enum Data {
N(NData),
S(SData),
}
impl fmt::Display for Data {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Data::N(n_data) => n_data.fmt(f),
Data::S(s_data) => s_data.fmt(f),
}
}
}
fn main() {
let n = NData { numeric: 0xff };
let s = SData { strings: vec!["hello".to_string(), "world".to_string()] };
println!("{}", n);
println!("{}", s);
let d_n = Data::N(n);
let d_s = Data::S(s);
println!("{}", d_n);
println!("{}", d_s);
}
Which will produce the following output:
255
["hello", "world"]
255
["hello", "world"]

C+11-Like Type Decay in Rust

In C++11, you can decay a generic type to a value type, removing reference/rvalue semantics and cv-qualifiers, e.g.
decay<int>::type // type is `int`
decay<const int&>::type // type is `int`
decay<int&&>::type // type is `int`
Is there a known mechanism to achieve the same in Rust, that strips reference modifiers, lifetimes and the mut qualifier? e.g.:
decay<u32>::type <--- type is `u32`
decay<&u32>::type <--- type is `u32`
decay<&mut u32>::type <--- type is `u32`
decay<&static u32>::type <--- type is `u32`
For background, I'm trying to write a macro that generates a struct that stores the values of a bunch of function arguments matched by the macro. e.g., the macro might contain the args foo: i32, bar: &Vec<String>, and the resultant struct should be:
struct GeneratedStruct {
foo: i32,
bar: Vec<String>,
}
As suggested by Matthieu M. and kennytm in comments, you can define a trait and use specialization (an unstable feature as of Rust 1.15.0) to achieve this.
#![feature(specialization)]
use std::any::TypeId;
trait Decay {
type Type;
}
impl<T> Decay for T {
default type Type = T;
}
impl<'a, T> Decay for &'a T {
type Type = <T as Decay>::Type;
}
impl<'a, T> Decay for &'a mut T {
type Type = <T as Decay>::Type;
}
fn foo<T: 'static>() {
println!("{:?}", TypeId::of::<T>());
}
fn bar<T>() where <T as Decay>::Type: 'static {
println!("{:?}", TypeId::of::<<T as Decay>::Type>());
}
fn main() {
foo::<<i32 as Decay>::Type>();
foo::<<&i32 as Decay>::Type>();
foo::<<&mut i32 as Decay>::Type>();
foo::<<&&i32 as Decay>::Type>();
bar::<i32>();
bar::<&i32>();
bar::<&mut i32>();
bar::<&&i32>();
}

How to return a reference from a trait when combining types into enum

I am a bit stuck (except by duplicating my memory (see DupKeyEAB in playpen), I got this trait:
pub trait KeyVal : Send + Sync + 'static {
type Key : Clone + Debug + 'static;
fn get_key(&self) -> Self::Key;
fn get_key_ref<'a>(&'a self) -> &'a Self::Key;
}
My problem is that I need something like (to avoid using clone each time I access the key) :
pub trait KeyVal : Send + Sync + 'static {
type Key : Clone + Debug + 'static;
type KeyRef<'_> : Debug;
fn get_key(&self) -> Self::Key;
fn get_key_ref<'a>(&'a self) -> Self::KeyRef<'a>;
}
or directly (with KeyRef as a trait)
fn get_key_ref<'a,K : KeyRef<'a>>(&'a self) -> K;
or
fn get_key_ref<'a>(&'a self) -> KeyRef<'a>;
All those notations are obviously pretty invalid, but it illustrate that I need to return a reference with the same lifetime as the struct implementing my trait but at the same time the reference could not simply be &'a but also a enum with the same lifetime.
That way when using get_key_ref on simple struct my KeyRef is simply &'aKey and when using get_key_ref on enum combining multiple trait implementation (see EnumAB) I could use a wrapper enum over the reference to the key : like KeyABRef<'a>.
impl EnumAB {
fn get_key_ok<'a>(&'a self) -> KeyABRef<'a> {
match self {
&EnumAB::A(ref a) => KeyABRef::A(a.get_key_ref()),
&EnumAB::B(ref b) => KeyABRef::B(b.get_key_ref()),
}
}
}
Yet I cannot include this function in my trait.
I wonder if anyone got a solution for this kind of need (KeyVal need to be 'static)?
My original test code was :
use std::fmt::Debug;
use std::thread;
pub trait KeyVal : Send + Sync + 'static {
type Key : Clone + Debug + 'static;
fn get_key(&self) -> Self::Key;
fn get_key_ref<'a>(&'a self) -> &'a Self::Key;
}
pub fn do_something_with_spawn<KV : KeyVal> (kv : KV) {
thread::spawn ( move || {
println!("{:?}", kv.get_key_ref());
});
}
#[derive(Debug)]
pub struct StructA (usize);
#[derive(Debug)]
pub struct StructB (String);
#[derive(Debug)]
pub enum EnumAB {
A(StructA),
B(StructB),
}
impl KeyVal for StructA {
type Key = usize;
// type KeyRef<'_> = &'_ usize;
fn get_key(&self) -> Self::Key {
self.0.clone()
}
fn get_key_ref<'a>(&'a self) -> &'a Self::Key {
&self.0
}
}
impl KeyVal for StructB {
type Key = String;
// type KeyRef<'_> = &'_ String;
fn get_key(&self) -> Self::Key {
self.0.clone()
}
fn get_key_ref<'a>(&'a self) -> &'a Self::Key {
&self.0
}
}
#[derive(Clone,Debug)]
pub enum KeyAB {
A(usize),
B(String),
}
#[derive(Clone,Debug)]
pub enum KeyABRef<'a> {
A(&'a usize),
B(&'a String),
}
impl KeyVal for EnumAB {
type Key = KeyAB;
// type KeyRef<'_> = KeyABRef<'_>
fn get_key(&self) -> Self::Key {
match self {
&EnumAB::A(ref a) => KeyAB::A(a.get_key()),
&EnumAB::B(ref b) => KeyAB::B(b.get_key()),
}
}
fn get_key_ref<'a>(&'a self) -> &'a Self::Key {
panic!("cannot");
}
}
impl EnumAB {
fn get_key_ok<'a>(&'a self) -> KeyABRef<'a> {
match self {
&EnumAB::A(ref a) => KeyABRef::A(a.get_key_ref()),
&EnumAB::B(ref b) => KeyABRef::B(b.get_key_ref()),
}
}
}
#[derive(Debug)]
pub struct DupKeyEAB (KeyAB, EnumAB);
impl KeyVal for DupKeyEAB {
type Key = KeyAB;
fn get_key(&self) -> Self::Key {
self.0.clone()
}
fn get_key_ref<'a>(&'a self) -> &'a Self::Key {
&self.0
}
}
fn main () {
let d2 = StructB("hello".to_string());
let d3 = EnumAB::A(StructA(3));
println!("{:?}",d2.get_key());
println!("{:?}",d3.get_key());
println!("{:?}",d2.get_key_ref());
println!("{:?}",d3.get_key_ok());
do_something_with_spawn(d3);
}
I agree with A.B. that your motivation is unclear, so any help we can provide is guessing at best. That being said, here's a guess that uses Borrow:
use std::borrow::Borrow;
trait KeyVal<'a> {
type Key: Borrow<Self::KeyRef>;
type KeyRef: 'a;
fn get_key(&self) -> Self::Key;
fn get_key_ref(&'a self) -> &'a Self::KeyRef;
}
struct Example(u8);
impl<'a> KeyVal<'a> for Example {
type Key = u8;
type KeyRef = u8;
fn get_key(&self) -> Self::Key {
self.0
}
fn get_key_ref(&'a self) -> &'a Self::KeyRef {
&self.0
}
}
fn main() {
let e = Example(42);
println!("{:?}", e.get_key());
println!("{:p}", e.get_key_ref());
}
The other piece is type KeyRef: 'a, which indicates that the type chosen must outlive 'a.
You don't need Borrow though, I suppose:
trait KeyVal<'a> {
type Key;
type KeyRef: 'a;
fn get_key(&self) -> Self::Key;
fn get_key_ref(&'a self) -> Self::KeyRef;
}
#[derive(Debug)]
struct Example(u8);
#[derive(Debug)]
struct RefWrapper<'a>(&'a u8);
impl<'a> KeyVal<'a> for Example {
type Key = u8;
type KeyRef = RefWrapper<'a>;
fn get_key(&self) -> Self::Key {
self.0
}
fn get_key_ref(&'a self) -> Self::KeyRef {
RefWrapper(&self.0)
}
}
fn main() {
let e = Example(42);
println!("{:?}", e.get_key());
println!("{:?}", e.get_key_ref());
}
Using Shepmaster's solution (plus HRTB for spawn), it becomes :
use std::fmt::Debug;
use std::thread;
pub trait KeyVal<'a> : Send + Sync + 'static {
type Key : Clone + Debug + 'static;
type KeyRef : Debug + 'a;
fn get_key(&self) -> Self::Key;
fn get_key_ref(&'a self) -> Self::KeyRef;
}
pub fn do_something_with_spawn<KV> (kv : KV)
where for <'a> KV : KeyVal<'a> {
thread::spawn ( move || {
println!("{:?}", kv.get_key_ref());
});
}
#[derive(Debug)]
pub struct StructA (usize);
#[derive(Debug)]
pub struct StructB (String);
#[derive(Debug)]
pub enum EnumAB {
A(StructA),
B(StructB),
}
impl<'a> KeyVal<'a> for StructA {
type Key = usize;
type KeyRef = &'a usize;
fn get_key(&self) -> Self::Key {
self.0.clone()
}
fn get_key_ref(&'a self) -> Self::KeyRef {
&self.0
}
}
impl<'a> KeyVal<'a> for StructB {
type Key = String;
type KeyRef = &'a String;
fn get_key(&self) -> Self::Key {
self.0.clone()
}
fn get_key_ref(&'a self) -> Self::KeyRef {
&self.0
}
}
#[derive(Clone,Debug)]
pub enum KeyAB {
A(usize),
B(String),
}
#[derive(Clone,Debug)]
pub enum KeyABRef<'a> {
A(&'a usize),
B(&'a String),
}
impl<'a> KeyVal<'a> for EnumAB {
type Key = KeyAB;
type KeyRef = KeyABRef<'a>;
fn get_key(&self) -> Self::Key {
match self {
&EnumAB::A(ref a) => KeyAB::A(a.get_key()),
&EnumAB::B(ref b) => KeyAB::B(b.get_key()),
}
}
fn get_key_ref(&'a self) -> Self::KeyRef {
match self {
&EnumAB::A(ref a) => KeyABRef::A(a.get_key_ref()),
&EnumAB::B(ref b) => KeyABRef::B(b.get_key_ref()),
}
}
}
fn main () {
let d2 = StructB("hello".to_string());
let d3 = EnumAB::A(StructA(3));
println!("{:?}",d2.get_key());
println!("{:?}",d3.get_key());
println!("{:?}",d2.get_key_ref());
println!("{:?}",d3.get_key_ref());
do_something_with_spawn(d3);
}

Resources