What does the Value::into method from the serde_json crate do? - rust

This piece of code calls val.into() function where val is a serde_json::Value enum, but I can't find any description of into function in the Rust docs.
pub fn parse(&self, s: &str) -> Result<RpcObject, ReadError> {
let val = serde_json::from_str::<Value>(&s)?;
if !val.is_object() {
Err(ReadError::NotObject)
} else {
Ok(val.into())
}
}

Into is a trait with the single method into. Into is implemented for every type that implements From:
impl<T, U> Into<U> for T
where
U: From<T>,
serde_json::Value implements many different versions of From
impl From<i8> for Value
impl From<i16> for Value
impl From<i32> for Value
impl From<i64> for Value
impl From<isize> for Value
impl From<u8> for Value
impl From<u16> for Value
impl From<u32> for Value
impl From<u64> for Value
impl From<usize> for Value
impl From<f32> for Value
impl From<f64> for Value
impl From<bool> for Value
impl From<String> for Value
impl<'a> From<&'a str> for Value
impl<'a> From<Cow<'a, str>> for Value
impl From<Map<String, Value>> for Value
impl<T: Into<Value>> From<Vec<T>> for Value
impl<'a, T: Clone + Into<Value>> From<&'a [T]> for Value
These two traits are used to provide conversions between types that cannot fail. The traits TryFrom and TryInto allow for fallible conversions starting in Rust 1.34.
See also:
When should I implement std::convert::From vs std::convert::Into?
From and Into in Rust by Example
An astute reader will have noticed that what I showed above actually allows you to convert to a serde_json::Value. Technically, the original code converts to a RpcObject from a Value. Somewhere in your code there is impl From<serde_json::Value> for RpcObject, but since that implementation isn't provided, I can't link to any useful documentation for that, but the pattern is the same.

Related

How to return a box to self?

I'm new to rust and I experience difficulties to develop my personal first project.
To get the essential my code looks like this:
pub trait MyTrait {
type Out: MyTrait;
fn foo(&self) -> Box<Self::Out>;
}
pub struct MyStruct<T: MyTrait>(Box<T>);
impl<T: MyTrait> MyTrait for MyStruct<T> {
type Out = Self <>;
fn foo(&self) -> Box<Self::Out> {
Box::new(self)
}
}
The error message I get is :
expected struct MyStruct<T> found reference &MyStruct<T>
I tried many things but I can't find how to return a box to self...
I have another question: actually MyTrait extends another trait and I have many struct that implement MyTrait so in my code I have many impl, one for each trait by struct and I find it really verbose, isn't it possible to implement all methods (from a trait and all its parents) at once (like in java) ? Or is there syntactic sugar to implement methods with closures ?
Thanks
Box needs to own self. You cannot pass a reference into it, it has to be the actual self object.
This works:
pub trait MyTrait {
type Out: MyTrait;
fn foo(self) -> Box<Self::Out>;
}
pub struct MyStruct<T: MyTrait>(Box<T>);
impl<T: MyTrait> MyTrait for MyStruct<T> {
type Out = Self;
fn foo(self) -> Box<Self::Out> {
Box::new(self)
}
}
Further remarks:
I'm unsure why you need that function, but it seems to me like you are trying to downcast from a boxed dyn trait to an actual type.
Sadly, this won't work this way. It's impossible for the compiler to figure out which type was the original type if your Box<dyn MyTrait> doesn't contain that information any more. That's why you need the Out associated type here, but you probably didn't yet realize that this means you can no longer store a Box<dyn MyTrait> object. It's now a Box<dyn MyTrait<Out = MyStruct>> object, which cannot be mixed with other MyTrait types any more.
If you really want to achieve that, there are several options. RTTI is one option, with the Any trait.
Another one would be a Visitor pattern, which could resolve this:
pub trait Visitor {
fn visit_mystruct(&mut self, s: &mut MyStruct);
}
pub struct MyVisitor;
impl Visitor for MyVisitor {
fn visit_mystruct(&mut self, s: &mut MyStruct) {
println!("Visited MyStruct: {:?}", s.0);
}
}
pub trait MyTrait {
fn visit(&mut self, visitor: &mut dyn Visitor);
}
pub struct MyStruct(i32);
impl MyTrait for MyStruct {
fn visit(&mut self, visitor: &mut dyn Visitor) {
visitor.visit_mystruct(self);
}
}
fn main() {
let mut obj: Box<dyn MyTrait> = Box::new(MyStruct(42)) as Box<dyn MyTrait>;
let mut visitor = MyVisitor;
// Here is no information any more about the actual type of `obj`.
// Visitor gets the type resolved again
obj.visit(&mut visitor);
}
Visited MyStruct: 42
A visitor pattern is especially useful in cases like tree structures, because it can be recursively applied to children. It is commonly used in compilers.
Another alternative would be to use an Enum instead of a Box<dyn Trait>.
Although those are all just based on assumptions now.

How to extend IntoIterator by another trait?

I'm trying to define a trait that extends IntoIterator, to achieve something similar to the code bellow, but "associated type defaults are unstable" (https://github.com/rust-lang/rust/issues/29661).
Is there another way to achieve it?
pub trait MyTrait : IntoIterator{
type Item = i32;
fn foo(&self);
}
pub fn run<M: MyTrait>(my : M){
my.foo();
for a in my {
println!("{}", a);
}
}
I think what you want is this:
trait MyTrait: IntoIterator<Item = i32> {
fn foo(&self);
}
This means: everything that implements your trait also implements IntoIterator where the Item is i32. Or put differently: all implementors of MyTrait can also be turned into an iterator over i32s.

Implementing Borrow trait for a type with a lifetime

I'm trying to use. strongly typed wrapper for a "keys" in my program, so that I don't mistake arbitrary strings for a Key. I have:
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Key(String);
I have a HashMap<Key, _>, and I want to lookup values with a reference to a key type (i.e. not having to own the string). It seems like what I need to do is:
create a "ref" type for my Key:
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct KeyRef<'a>(&'a String);
(in reality I'd want KeyRef<'a>(&'a str), but using String makes for a clearer example)
implement Borrow<KeyRef<'_>> for Key
I've tried my best, here's a playground link
My most explicit attempt (annotating all lifetimes) is:
impl<'a> Borrow<KeyRef<'a>> for Key {
fn borrow<'b>(&'b self) -> &'b KeyRef<'a> where 'b: 'a {
let string_ref : &'a String = &self.0;
let key_ref : &'a KeyRef<'a> = &KeyRef(string_ref);
key_ref
}
}
Which gives me the error: "lifetime parameters or bounds on method borrow do not match the trait declaration".
Intuitively it feels like this should be possible:
KeyRef holds a reference of lifetime 'a, so any value of KeyRef cannot outlive 'a.
In fn borrow<'b>(&'b self), 'b can't be greater than 'a due to the above
But the compiler doesn't seem to like my explicit attempt to demonstrate that (with where 'b: 'a), and leaving it off I get "cannot infer an appropriate lifetime for borrow expression due to conflicting requirements"
As far as I understand your situation, you are needlessly overcomplicating things. A straightforward implementation:
use std::collections::HashMap;
use std::borrow::Borrow;
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
struct Key(String);
impl Borrow<str> for Key {
fn borrow(&self) -> &str {
&self.0
}
}
impl Borrow<String> for Key {
fn borrow(&self) -> &String {
&self.0
}
}
fn main() {
let mut map = HashMap::new();
map.insert(Key("one".to_owned()), 1);
// Because Key is Borrow<String>
println!("{:?}", map.get("one".to_owned()));
// Because Key is Borrow<str>
println!("{:?}", map.get("one"));
}

What's the difference between `impl<T> Trait for T where T: Trait2` and `impl Trait for dyn Trait2`?

When extending traits defined in other crates, there seem to be two ways to default implement a new trait.
The original definition of a trait is
pub trait Trait1 {
fn f1(&self);
}
In order to extend the functionality of this trait, we define a trait Trait2,
pub trait Trait2 {
fn f2(&self);
}
Now, because we want the functionality to be available by default, we can implement the following
impl<T> Trait2 for T
where
T: Trait1,
{
pub fn f2(&self) {
self.f1()
}
}
impl Trait2 for dyn Trait1 {
pub fn f2(&self) {
self.f1()
}
}
What I have observed is that, when mixing with trait objects, both of these implementations are required.
I understand that the impl<T> one is for concrete classes where as other is for dyn objects. Is that correct? Is there any way to share the default implementation here for both of these types? In my scenario, I had to copy and paste the whole implementation with just the change of the first line.
If I understood your question correctly, just add the unsized (?Sized) bound to T:
impl<T> Trait2 for T where T: Trait1 + ?Sized
This implements Trait2 for unsized types (eg. dyn Trait1) that implement Trait1 as well. By default, all type parameters are sized, and hence do not match unsized types.
Playground

Reference to generic trait with asscociated type as struct field

I am struggling to convince Rust to accept a reference to an instance implementing a generic trait with associated type as a value of struct field. Could you please give some clues what is wrong in the code below.
trait TraitA{}
trait TraitB{
type As: TraitA;
}
struct StructA;
impl TraitA for StructA{}
struct StructB;
impl TraitB for StructB{
type As = StructA;
}
struct StructC<'a> {
r: &'a (dyn TraitB<As = (dyn TraitA)> + 'a),
}
fn main(){
let x = StructB;
let z = StructC {
r: &x,
};
}
Playground
About posted compiler error
The problem caused be the fact that TCPtransport does not implement
Transport<.., Configuration=(dyn TransportConfiguration<SyncReq>>,
instead it implements
Transport<.., Configuration=TcpTranportCfg>, and later one cannot be casted to former:
playground
Possible solution: Add new trait (Basically to strip associated type info):
trait SyncReqTransport{
...
}
impl<T> SyncReqTransport<SyncReq> for T
where
T: Transport<SyncReq>, // I Removed other parameters for simplicity
<T as Transport<SyncReq>>::Config: TransportConfiguration<SyncReq>
{
...
}
And change DAG to
pub struct DAG<'a, T> {
request_transport: &'a (dyn SyncReqTransport + 'a),
}
Another problem
sr_transport being created on stack, and later reference to it being returned from
the function it is created, which is illegal.

Resources