Expose a HashMap in a generic way that disregards the HashMap value - hashmap

I have different structs which all contain a HashMap with String as the key, but with different value types. For example, one struct has a member of type HashMap<String, String>, the other will have a member of type HashMap<String, u8>, and so on.
I want to define a method that can access these HashMap members and do generic actions on them that don't involve the value. For example, I want to count the number of keys, remove a key, check if a key exists, etc. I'm not sure how to implement this behavior.
The best way I had in mind so far is to define a trait that has a method that exposes the HashMap and let each struct implement it. However I don't know how to write this trait and method in a way that "ignores" the value type. I tried using a wildcard (_) but it doesn't work. How do I implement this?
Here is my code (which doesn't compile):
use std::collections::HashMap;
pub trait HashMapContainer {
fn get_hash_map(&self) -> HashMap<String, _>;
}
struct HashMapContainerImpl1 {
map: HashMap<String, String>,
}
impl HashMapContainerImpl1 {
pub fn new() -> HashMapContainerImpl1 {
HashMapContainerImpl1 {
map: HashMap::new(),
}
}
fn internal_logic_on_map(&mut self) {
//....
}
}
impl HashMapContainer for HashMapContainerImpl1 {
fn get_hash_map(&self) -> HashMap<String, _> {
self.map
}
}
struct HashMapContainerImpl2 {
map: HashMap<String, u8>,
}
impl HashMapContainerImpl2 {
pub fn new() -> HashMapContainerImpl2 {
HashMapContainerImpl2 {
map: HashMap::new(),
}
}
fn internal_logic_on_map(&mut self) {
//....
}
}
impl HashMapContainer for HashMapContainerImpl2 {
fn get_hash_map(&self) -> HashMap<String, _> {
self.map
}
}
fn do_generic_actions_on_map(hm_container: &HashMapContainer) {
println!("key count: {}", hm_container.get_hash_map().len());
println!(
"key esists? {}",
hm_container.get_hash_map().get("key1").is_some()
);
hm_container.get_hash_map().remove("key2");
}
fn main() {
let cont1 = HashMapContainerImpl1::new();
let cont2 = HashMapContainerImpl2::new();
do_generic_actions_on_map(cont1);
do_generic_actions_on_map(cont2);
}

With an associated type
The code below using a generic is correct, but after thinking about it, I think that using an associated type might be more suitable here. The trait should look like this:
pub trait HashMapContainer {
type Value;
fn get_hash_map(&self) -> &HashMap<String, Self::Value>;
fn get_hash_map_mut(&mut self) -> &mut HashMap<String, Self::Value>;
}
The difference is, that you now can only implement the trait once for a struct and not multiple times, which is more correct in this case.
The implementations are roughly the same as with the generic type parameter.
impl HashMapContainer for HashMapContainerImpl1 {
type Value = String;
fn get_hash_map(&self) -> &HashMap<String, Self::Value> {
&self.map
}
fn get_hash_map_mut(&mut self) -> &mut HashMap<String, Self::Value> {
&mut self.map
}
}
impl HashMapContainer for HashMapContainerImpl2 {
type Value = u8;
fn get_hash_map(&self) -> &HashMap<String, Self::Value> {
&self.map
}
fn get_hash_map_mut(&mut self) -> &mut HashMap<String, Self::Value> {
&mut self.map
}
}
(Playground)
You can also look at When is it appropriate to use an associated type versus a generic type? which explains the difference between those two pretty good.
With a generic type
This is solvable by introducing a generic type in your HashMapContainer trait.
pub trait HashMapContainer<T> {
fn get_hash_map(&self) -> &HashMap<String, T>;
fn get_hash_map_mut(&mut self) -> &mut HashMap<String, T>;
}
I changed the signature to return a reference to the HashMap. It would be possible to do it without, e.g. by using clone or taking self as value, instead of as reference. I also introduced a _mut version.
The implementation is straight foreword:
impl HashMapContainer<String> for HashMapContainerImpl1 {
fn get_hash_map(&self) -> &HashMap<String, String> {
&self.map
}
fn get_hash_map_mut(&mut self) -> &mut HashMap<String, String> {
&mut self.map
}
}
impl HashMapContainer<u8> for HashMapContainerImpl2 {
fn get_hash_map(&self) -> &HashMap<String, u8> {
&self.map
}
fn get_hash_map_mut(&mut self) -> &mut HashMap<String, u8> {
&mut self.map
}
}

Related

Rust - Casting super trait to trait

I have a container where I can store items implementing the CommonBase trait and I have some other traits (TypeA and TypeB for example, but there can be unknown number of other TypeX traits) with the CommonBase as their super trait. I store objects implementing ItemA to container and I can get a reference to item back from the container, but as reference to the CommonBase.
I want to cast the item back to its original type like this:
fn cast_to<T: SuperTrait>(val: dyn CommonBase) -> Result<T, dyn Error> {...}
Can anyone help please?
Here is my experimental code
use std::error::Error;
use std::rc::Rc;
pub trait CommonBase {
fn to_common(self: &Self);
}
pub trait TypeA: CommonBase {
fn do_a(self: &Self);
}
pub trait TypeB: CommonBase {
fn do_b(self: &Self);
}
pub struct StructA {}
impl CommonBase for StructA {
fn to_common(self: &Self) { todo!() }
}
impl TypeA for StructA {
fn do_a(self: &Self) { todo!() }
}
pub struct StructB {}
impl CommonBase for StructB {
fn to_common(self: &Self) { todo!() }
}
impl TypeB for StructB {
fn do_b(self: &Self) { todo!() }
}
pub struct Container {
items: Vec<Rc<dyn CommonBase>>,
}
impl Container {
pub fn new() -> Container {
Container { items: Vec::new() }
}
pub fn add(self: &mut Self, item: Rc<dyn CommonBase>) {
self.items.push(item);
}
pub fn get(self, idx: usize) -> Rc<dyn CommonBase> {
self.items.get(idx).unwrap().clone()
}
}
fn cast_to<T: CommonBase>(val: Rc<dyn CommonBase>) -> Result<Rc<dyn T>, Box<dyn Error>> {...} // <- some magic is done here
fn main() {
let mut container = Container::new();
let item_a = Rc::new(StructA {});
let item_b = Rc::new(StructB {});
container.add(item_a); // index 0
container.add(item_b); // index 1
let stored_a_as_common: Rc<dyn CommonBase> = container.get_common(0); // actually TypeA
let stored_a: Rc<dyn TypeA> = cast_to(stored_a_as_common).unwrap();
stored_a.do_a();
}
Here is your code with a few additions.
For this, you need std::any::Any.
Each struct subject to dynamic cast should be known as dyn Any in order to try the dynamic cast; this is the purpose of .as_any() and .as_any_mut() in the example.
Using .downcast_ref() or .downcast_mut() requires you target a type, not a trait.
I don't think you can have at the same time two Rcs pointing towards the same struct but declared with different dyn traits.
The best to do, in my opinion, is to only deal with references (wherever they come from, Rc or something else).
You expected an Error when the dynamic cast is impossible, then I wrote the function this way.
Note however that .downcast_ref() returns an Option and this is generally good enough (None means that the cast is impossible); we could simplify the code with just this line val.as_any().downcast_ref::<T>().
use std::error::Error;
use std::rc::Rc;
use std::any::Any;
pub trait CommonBase: Any {
fn to_common(self: &Self);
fn as_any(&self) -> &dyn Any;
fn as_any_mut(&mut self) -> &mut dyn Any;
}
pub trait TypeA: CommonBase {
fn do_a(self: &Self);
}
pub trait TypeB: CommonBase {
fn do_b(self: &Self);
}
pub struct StructA {}
impl CommonBase for StructA {
fn to_common(self: &Self) {
todo!()
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
impl TypeA for StructA {
fn do_a(self: &Self) {
println!("doing a");
}
}
pub struct StructB {}
impl CommonBase for StructB {
fn to_common(self: &Self) {
todo!()
}
fn as_any(&self) -> &dyn Any {
self
}
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}
impl TypeB for StructB {
fn do_b(self: &Self) {
println!("doing b");
}
}
pub struct Container {
items: Vec<Rc<dyn CommonBase>>,
}
impl Container {
pub fn new() -> Container {
Container { items: Vec::new() }
}
pub fn add(
self: &mut Self,
item: Rc<dyn CommonBase>,
) {
self.items.push(item);
}
pub fn get(
&self,
idx: usize,
) -> Rc<dyn CommonBase> {
self.items.get(idx).unwrap().clone()
}
}
fn cast_to<T: CommonBase>(
val: &dyn CommonBase
) -> Result<&T, Box<dyn Error>> {
if let Some(t_ref) = val.as_any().downcast_ref::<T>() {
Ok(t_ref)
} else {
Err("bad cast")?
}
}
#[allow(dead_code)] // unused in this example
fn cast_to_mut<T: CommonBase>(
val: &mut dyn CommonBase
) -> Result<&mut T, Box<dyn Error>> {
if let Some(t_ref) = val.as_any_mut().downcast_mut::<T>() {
Ok(t_ref)
} else {
Err("bad cast")?
}
}
fn main() {
let mut container = Container::new();
let item_a = Rc::new(StructA {});
let item_b = Rc::new(StructB {});
container.add(item_a); // index 0
container.add(item_b); // index 1
let stored_a_as_common: Rc<dyn CommonBase> = container.get(0); // actually TypeA
let stored_a: &dyn TypeA =
cast_to::<StructA>(stored_a_as_common.as_ref()).unwrap();
stored_a.do_a();
let stored_b_as_common: Rc<dyn CommonBase> = container.get(1); // actually TypeB
let stored_b: &dyn TypeB =
cast_to::<StructB>(stored_b_as_common.as_ref()).unwrap();
stored_b.do_b();
}
/*
doing a
doing b
*/

How to define a Vec in Rust to support containing multiple types of structs that implement a same trait?

In c++, I can define a parent class, and the type in vector can just be the father class type. So how to implement that in Rust?
Like for this example:
I defined two types of Integer who both implement the trait Object, now I want to put them in a same vector, is there any way to achieve that?
pub trait Object<T: Object<T>+Clone> {
fn sub(&self, x: &T) -> T {
x.clone() //this is a useless implementation, just for structs don't need to implement this method.
}
}
#[derive(Debug, Copy, Clone)]
pub struct Integer {
val: i32
}
impl Integer {
pub fn get(&self) -> i32 {
self.val
}
pub fn new(val: i32) -> Self {
Integer {
val
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct Int {
val: i32
}
impl Int {
pub fn get(&self) -> i32 {
self.val
}
pub fn new(val: i32) -> Self {
Int {
val
}
}
}
impl Object<Int> for Int {
fn sub(&self, rhs: &Int) -> Int {
Int {
val: self.val - rhs.get()
}
}
}
impl Object<Integer> for Integer {
fn sub(&self, rhs: &Integer) -> Integer {
Integer {
val: self.val - rhs.get()
}
}
}
fn main() {
let mut v: Vec<Box<dyn Object>> = Vec::new();
v.push(Box::new(Integer::new(1)));
v.push(Box::new(Int::new(2)));
}
Thanks a lot.
There are several aspects of your design that don't fit in Rust:
trait Object<T: Object<T>+Clone> doesn't help - Rust doesn't do CRTP, just use Self instead.
for Object to be object-safe (necessary to put it in a vector), it can't be parameterized by type. A type parameter means you get a completely separate trait for each type.
Object::sub() can't return the result by value, because the size of the value can differ for different implementations, so it wouldn't be object-safe. It must return Box<dyn Object> instead.
The code modified as indicated looks like this:
pub trait Object {
fn get(&self) -> i32;
fn sub(&self, x: &dyn Object) -> Box<dyn Object>;
}
#[derive(Debug, Copy, Clone)]
pub struct Integer {
val: i32,
}
impl Integer {
fn new(val: i32) -> Box<dyn Object> {
Box::new(Int { val })
}
}
impl Object for Integer {
fn get(&self) -> i32 {
self.val
}
fn sub(&self, rhs: &dyn Object) -> Box<dyn Object> {
Integer::new(self.val - rhs.get())
}
}
#[derive(Debug, Copy, Clone)]
pub struct Int {
val: i32,
}
impl Int {
fn new(val: i32) -> Box<dyn Object> {
Box::new(Int { val })
}
}
impl Object for Int {
fn get(&self) -> i32 {
self.val
}
fn sub(&self, rhs: &dyn Object) -> Box<dyn Object> {
Int::new(self.val - rhs.get())
}
}
fn main() {
let mut v: Vec<Box<dyn Object>> = vec![];
v.push(Integer::new(1));
v.push(Int::new(2));
v.push(v[0].sub(v[1].as_ref()));
for o in &v {
println!("{}", o.get());
}
}
Playground
I think you can combine trait and provide a blank implementation, then use that in vector
trait TraitA {}
trait TraitB {}
trait CombinedTraitATraitB: TraitA + TraitB {}
impl<T> CombinedTraitATraitB for T where T: TraitA + TraitB {}
let vector: Vec<Box<dyn CombinedTraitATraitB>> = vec![];

Returning a mutable reference to a value behind Arc and Mutex

pub struct ForesterViewModel {
m_tree_lines: Arc<Mutex<Vec<TreeLine>>>,
}
impl ForesterViewModel {
pub fn new() -> ForesterViewModel {
ForesterViewModel {
m_tree_lines: Arc::new(Mutex::new(vec![])),
}
}
pub fn get_the_forest(&mut self) -> &mut Vec<TreeLine> {
???????????????????????????????
}
}
I need help writing the get_the_forest function. I've tried many various things but they all return compilation errors. I need to return a mutable reference to Vec<TreeLine> which is wrapped behind an Arc and a Mutex in self.m_tree_lines.
There is no way of doing this.
You create a concrete MutexGuard object that releases the mutex when it dropped when you call lock; you cannot move a reference out of the scope that contains the guard:
pub fn as_mut(&mut self) -> &Whatever {
let mut guard = self.data.lock().unwrap();
Ok(guard.deref())
drop(guard) // <--- implicitly added here, which would invalidate the ref
}
You also cannot return both the mutex guard and a reference, for more complex reasons (basically rust cannot express that), for the same reason it cannot have a reference and an object in a single structure; see the discussion on Why can't I store a value and a reference to that value in the same struct?
...so basically your best bet is one of two things:
/// Return the mutex guard itself
pub fn get_the_forest(&mut self) -> Result<MutexGuard<Vec<TreeLine>>, TreeLockError> {
Ok(self.m_tree_lines.lock()?)
}
/// Pass a function in, which patches the mutable internal value
pub fn patch_forest(&mut self, patch: impl Fn(&mut Vec<TreeLine>)) -> Result<(), TreeLockError>{
let mut guard = self.m_tree_lines.lock()?;
patch(&mut guard); // <-- patch happens while guard is still alive
Ok(())
}
Full code:
use std::sync::{Arc, Mutex, MutexGuard};
use std::sync::PoisonError;
use std::error::Error;
use std::fmt;
use std::fmt::Formatter;
use std::ops::Deref;
#[derive(Debug, Copy, Clone)]
pub enum TreeLockError {
FailedToLock
}
impl Error for TreeLockError {}
impl fmt::Display for TreeLockError {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f, "{:?}", self)
}
}
impl<T> From<PoisonError<T>> for TreeLockError {
fn from(_: PoisonError<T>) -> Self {
TreeLockError::FailedToLock
}
}
// ---
#[derive(Debug)]
pub struct TreeLine {
pub value: &'static str
}
pub struct ForesterViewModel {
m_tree_lines: Arc<Mutex<Vec<TreeLine>>>,
}
impl ForesterViewModel {
pub fn new() -> ForesterViewModel {
ForesterViewModel {
m_tree_lines: Arc::new(Mutex::new(vec![])),
}
}
pub fn get_the_forest(&mut self) -> Result<MutexGuard<Vec<TreeLine>>, TreeLockError> {
Ok(self.m_tree_lines.lock()?)
}
pub fn patch_forest(&mut self, patch: impl Fn(&mut Vec<TreeLine>)) -> Result<(), TreeLockError>{
let mut guard = self.m_tree_lines.lock()?;
patch(&mut guard);
Ok(())
}
}
fn main() -> Result<(), Box<dyn Error>> {
let mut vm = ForesterViewModel::new();
{
let mut trees = vm.get_the_forest()?;
trees.push(TreeLine{ value: "one"});
trees.push(TreeLine{ value: "two"});
} // <--- Drop the mutable reference here so you can get it again later
// Patch
vm.patch_forest(|trees| {
trees.push(TreeLine{ value: "three"});
});
// ...
let trees = vm.get_the_forest()?;
println!("{:?}", trees.deref());
Ok(())
}

Storing types in a HashMap to dynamically instantiate them

I am trying to store structs in a HashMap keyed by string so that I can later create new objects by string. Think of a REST API where clients can get the server to instantiate a specific object by supplying a name.
use std::collections::HashMap;
struct MyStruct;
impl MyStruct {
pub fn new() -> Self {
Self {}
}
}
struct MyOtherStruct;
impl MyOtherStruct {
pub fn new() -> Self {
Self {}
}
}
fn main() {
let mut h = HashMap::new();
h.insert("MyStruct", MyStruct);
h.insert("MyOtherStruct", MyOtherStruct);
// This is pseudo-code
let obj = h.get("MyStruct").unwrap()::new();
}
As I expected, this doesn't work due to syntax errors:
error: expected one of `.`, `;`, `?`, or an operator, found `::`
--> src/main.rs:25:41
|
25 | let obj = h.get("MyStruct").unwrap()::new();
| ^^ expected one of `.`, `;`, `?`, or an operator here
My second attempt was to store a reference to the new method of each struct instead of the types themselves.
use std::collections::HashMap;
struct MyStruct;
impl MyStruct {
pub fn new() -> Self {
Self {}
}
}
struct MyOtherStruct;
impl MyOtherStruct {
pub fn new() -> Self {
Self {}
}
}
fn main() {
let mut h = HashMap::new();
h.insert("MyStruct", &MyStruct::new);
h.insert("MyOtherStruct", &MyOtherStruct::new);
let obj = h.get("MyStruct").unwrap()();
}
This fails because the fn items have different types and can't be stored in the same HashMap:
error[E0308]: mismatched types
--> src/main.rs:22:31
|
22 | h.insert("MyOtherStruct", &MyOtherStruct::new);
| ^^^^^^^^^^^^^^^^^^^ expected fn item, found a different fn item
|
= note: expected type `&fn() -> MyStruct {MyStruct::new}`
found type `&fn() -> MyOtherStruct {MyOtherStruct::new}`
Since I'm pretty new to Rust, I'm out of ideas. How can I solve this problem?
This is ultimately fundamentally impossible. In Rust, local variables are stored on the stack, which means that they have to have a fixed size, known at compile time. Your construction requires the size of the value on the stack to be determined at runtime.
The closest alternative is to move to trait objects, which introduce a layer of indirection:
use std::collections::HashMap;
trait NewThing {
fn new(&self) -> Box<Thing>;
}
trait Thing {}
struct MyStruct;
impl NewThing for MyStruct {
fn new(&self) -> Box<Thing> {
Box::new(Self {})
}
}
impl Thing for MyStruct {}
struct MyOtherStruct;
impl NewThing for MyOtherStruct {
fn new(&self) -> Box<Thing> {
Box::new(Self {})
}
}
impl Thing for MyOtherStruct {}
fn main() {
let mut h: HashMap<_, Box<NewThing>> = HashMap::new();
h.insert("MyStruct", Box::new(MyStruct));
h.insert("MyOtherStruct", Box::new(MyOtherStruct));
let obj = h["MyStruct"].new();
}
You will find this pattern out in the world, such as in hyper's NewService.
what is [the value of &self of method new] when calling h["MyStruct"].new()
It's an instance of MyStruct or MyOtherStruct. The only reason that the same type can implement both traits is because there's no real unique state for the "factory" and the "instance". In more complicated implementations, these would be two different types.
Using the same type is common for such cases as sharing a reference-counted value.
See also:
Is it possible to have a constructor function in a trait?
Here is a more complex example of #Shepmaster's solution, using different types for Factories and the objects themselves:
use std::collections::HashMap;
trait NewThing {
fn new(&self) -> Box<Thing>;
}
trait Thing {
fn execute(&mut self);
}
// MyStruct
struct MyStructFactory;
impl NewThing for MyStructFactory {
fn new(&self) -> Box<Thing> {
Box::new(MyStruct {test: 12, name: "Test".into()})
}
}
struct MyStruct {
test: i32,
name: String
}
impl Thing for MyStruct {
fn execute(&mut self) {
self.test+=1;
println!("MyStruct {} {}", self.test, self.name);
}
}
// MyOtherStruct
struct MyOtherStructFactory;
impl NewThing for MyOtherStructFactory {
fn new(&self) -> Box<Thing> {
Box::new(MyOtherStruct {my_member: 1})
}
}
struct MyOtherStruct {
my_member: u32
}
impl Thing for MyOtherStruct {
fn execute(&mut self) { println!("MyOtherStruct.my_member: {}", self.my_member); }
}
fn main() {
let mut h: HashMap<_, Box<NewThing>> = HashMap::new();
h.insert("MyStruct", Box::new(MyStructFactory));
h.insert("MyOtherStruct", Box::new(MyOtherStructFactory));
h["MyStruct"].new().execute();
h["MyOtherStruct"].new().execute();
}
You could use std::any::Any to erase the type of the entry. They use Any::downcast<T> to check if the entry at the location matches your type, and get a Ok(Box<T>)

How do I extend an enum-based multi-type container with a remove method?

This question is based on information given in another recent question of mine. I would like to extend the following Container with a remove method that returns ownership of the stored data to the caller. The accompanying unit test should explain its desired behaviour.
In the previous case (see referenced question), I would have used the downcast method on the Box<Any> object, but I don't know how to approach the problem in the case where enums are used instead. I'm grateful for pointers.
use std::any::{Any, TypeId};
use std::collections::HashMap;
trait GroupTrait {
fn borrow<T: Any>(&self) -> Option<&T>;
}
struct Container<G> {
inner: HashMap<TypeId, G>,
}
impl<G> Default for Container<G>
where
G: GroupTrait,
{
fn default() -> Self {
Container {
inner: Default::default(),
}
}
}
impl<G> Container<G>
where
G: GroupTrait,
{
pub fn insert<T: Any + Into<G>>(&mut self, data: T) {
self.inner.insert(TypeId::of::<T>(), data.into());
}
pub fn borrow<T: Any>(&self) -> Option<&T> {
self.inner.get(&TypeId::of::<T>()).and_then(|g| g.borrow())
}
pub fn remove<T: Any>(&mut self) -> Option<T> {
unimplemented!()
}
}
#[cfg(test)]
mod tests {
use super::*;
/// This should be an user-defined type that implements the Any trait.
#[derive(Debug, Clone, PartialEq)]
struct TypeA(u32);
/// This should be an user-defined type that implements the Any trait.
#[derive(Debug, Clone, PartialEq)]
struct TypeB(String);
/// This is the enum that should replace boxed `Any` trait objects. Users also need to supply
/// this enum. Maybe they'll need to implement additional traits to get `borrow` to work.
#[derive(Debug, PartialEq)]
enum Group {
A(TypeA),
B(TypeB),
}
impl From<TypeA> for Group {
fn from(value: TypeA) -> Self {
Group::A(value)
}
}
impl From<TypeB> for Group {
fn from(value: TypeB) -> Self {
Group::B(value)
}
}
impl GroupTrait for Group {
fn borrow<T: Any>(&self) -> Option<&T> {
use self::Group::*;
match *self {
A(ref i) => Any::downcast_ref(i),
B(ref i) => Any::downcast_ref(i),
}
}
}
#[test]
fn insert() {
let mut c: Container<Group> = Default::default();
let data = TypeA(100);
c.insert(data.clone());
assert_eq!(
c.inner.get(&TypeId::of::<TypeA>()),
Some(&Group::A(data.clone()))
);
}
#[test]
fn borrow() {
let mut c: Container<Group> = Default::default();
let data = TypeA(100);
c.insert(data.clone());
let borrowed = c.borrow::<TypeA>();
assert_eq!(borrowed, Some(&data));
}
#[test]
fn remove() {
let mut c: Container<Group> = Default::default();
let data = TypeA(100);
c.insert(data.clone());
assert_eq!(c.remove::<TypeA>(), Some(data));
}
}
As you mentioned in the comments, TryFrom is possible. However, I'd go with Into<Option<T>>:
pub fn remove<T: Any>(&mut self) -> Option<T>
where
G: Into<Option<T>>,
{
self.inner.remove(&TypeId::of::<T>()).and_then(|g| g.into())
}
Playground
I'd choose Into<Option<T>> over TryInto<T> because Into<Option<T>> results in an Option while TryInto<T> results in Result<T, Self::Error>

Resources