I'm using a field of the struct ClientError (implemented in the Solana client):
#[derive(Error, Debug)]
#[error("{kind}")]
pub struct ClientError {
pub request: Option<rpc_request::RpcRequest>,
#[source]
pub kind: ClientErrorKind,
}
Below is how it's used in my code:
Err(err: ClientError) => {
if let MyError(myError) = err.kind {
...
}
return Err(custom_error(err, ...));
}
Which gives me the error:
use of partially moved value: `err`
partial move occurs because value has type `CustomType`, which does not implement the `Copy` trait
How can I solve this partial move error? I have seen this SO answer: Struct with partial move errors. But suggests using &'static str which isn't valid for me & I don't want to use Rc<Mutex<..>> either.
Related
I Have a substrate pallet implementation as follows
#[pallet::storage]
#[pallet::getter(fn get_payload)]
pub(super) type Payload<T: Config> = StorageMap<
_,
Blake2_128Concat,
Vec<u8>,
Messages<T>
>;
#[derive(Clone, Decode, Encode, Eq, PartialEq, Debug)]
pub struct Messages<T: Config> {
pub meta: Option<Vec<u8>>,
pub header: Option<Vec<u8>>,
}
#[pallet::weight(0)]
pub fn update(
origin: OriginFor<T>,
key: Vec<u8>,
header: Vec<u8>,
) -> DispatchResultWithPostInfo {
let origin_account = ensure_signed(origin)?;
let mut payload = Payload::<T>::get(key.clone());
match payload {
Some(mut val) => {
println!("{:?}",val.header);
<Payload<T>>::mutate(val, val.header=header)
},
None => println!("Not found")
}
and in the update function, when I tried to mutate it throws the following error
the trait `EncodeLike<Vec<u8>>` is not implemented for `Messages<T>`
The struct which corresponds to the Messages derived from Encode and Decode. Documentation is unclear on how to fix this. How to fix this issue?
The error message is correct, Messages<T> doesn't encode like a Vec<u8> and somewhere you try to use Mesages<T> where it only takes something that encodes like a Vec<u8>.
In <Payload<T>>::mutate call: the first argument must be something that encode like Vec<u8> and you give a variable of type Messages<T, it is an error. instead you probably wants to write <Payload<T>>::mutate(key.clone, ..)
I'm implementing a simple task queue using redis in Rust, but am struggling to deserialize the returned values from redis into my custom types.
In total I thought of 3 approches:
Deserializing using serde-redis
Manually implementing the FromRedisValue trait
Serializing to String using serde-json > sending as string > then deserializing from string
The 3rd approach worked but feels artificial. I'd like to figure out either 1 or 2, both of which I'm failing at.
Approach 1 - serde-redis
I have a simple Task definition:
#[derive(Debug, PartialEq, serde::Deserialize, serde::Serialize)]
pub struct Task {
pub id: u32,
pub desc: String,
}
which I'm trying to receive into a worker:
use serde_redis::RedisDeserialize;
pub fn execute_task(conn: &mut Connection) {
let task: Task = redis::cmd("LPOP")
.arg("task_q")
.query::<Task>(conn)
.unwrap()
.deserialize()
.unwrap();
println!("... executing task {} ...", task.id);
}
but I'm getting the following error:
error[E0277]: the trait bound `Task: FromRedisValue` is not satisfied
--> src/bin/worker.rs:38:10
|
38 | .query::<Task>(conn)
| ^^^^^ the trait `FromRedisValue` is not implemented for `Task`
error[E0599]: no method named `deserialize` found for struct `Task` in the current scope
--> src/bin/worker.rs:40:10
|
40 | .deserialize()
| ^^^^^^^^^^^ method not found in `Task`
So clearly I integrated the crate wrong, as it's not working. The documentation is super brief and the source code way over my head as a beginner - what could I be missing?
Approach 2 - manually implementing FromRedisValue
My naive approach:
impl FromRedisValue for Task {
fn from_redis_value(v: &Value) -> RedisResult<Self> {
let t = Task {
id: v.id,
desc: v.desc,
};
RedisResult::Ok(t)
}
fn from_redis_values(items: &[Value]) -> RedisResult<Vec<Self>> {
let tasks = items
.into_iter()
.map(|v| Task {
id: v.id,
desc: v.desc,
})
.collect();
RedisResult::Ok(tasks)
}
}
The errors I'm getting:
error[E0609]: no field `id` on type `&Value`
--> src/redis_tut.rs:203:19
|
203 | id: v.id,
| ^^
error[E0609]: no field `desc` on type `&Value`
--> src/redis_tut.rs:204:21
|
204 | desc: v.desc,
| ^^^^
// ...the same for the vector implementation
So clearly redis's Value doesn't have / know of the fields I want for Task. What's the right way to do this?
Redis doesn't define structured serialization formats. It mostly store strings and integers. So you have to choose or define your format for your struct.
A popular one is JSON, as you noticed, but if you just want to (de)serialize simple pairs of (id, description), it's not very readable nor convenient.
In such a case, you can define your own format, for example the id and the description with a dash in between:
#[derive(Debug, PartialEq)]
pub struct Task {
pub id: u32,
pub desc: String,
}
// assume a task is defined as "<id>-<desc>"
impl FromRedisValue for Task {
fn from_redis_value(v: &Value) -> RedisResult<Self> {
let v: String = from_redis_value(v)?;
if let Some((id, desc)) = v.split_once('-') {
if let Ok(id) = id.parse() {
Ok(Task {
id,
desc: desc.to_string(),
})
} else {
Err((ErrorKind::TypeError, "bad first token").into())
}
} else {
Err((ErrorKind::TypeError, "missing dash").into())
}
}
}
I actually wrote a crate for this kind of Problem, it provides Derive Macros that implements the redis::FromRedisValue and redis::ToRedisArgs traits from mitsuhiko / redis-rs for any struct in which every field's type also implements ToRedisArgs. Check it out redis-redive.
I am very new to Rust (just a couple of days). Of course, I am already getting stuck with the concept of ownership.
I have a rather lengthy problem, so here are all the relevant declarations I used:
pub struct ThePrimaryStruct<'a> {
frames: Vec<Frame<'a>>,
stack: Vec<Object<'a>>,
ip: usize
}
pub struct FunctionObject<'a> {
pub min_arity: i32,
pub max_arity: i32,
pub chunk: Chunk<'a>,
pub name: &'a str,
}
pub struct Frame<'a> {
pub function: FunctionObject<'a>,
// ... other struct members
}
pub struct Chunk<'a> {
pub codes: Vec<OpCode>, // OpCode is an enum
pub locations: Vec<(i64, i64)>,
pub constants: Vec<Object<'a>>
}
pub enum Object<'a> {
Function(FunctionObject<'a>),
// Other enum variants
}
The above code is not the problem. The problem arises when I implement the following method for ThePrimaryStruct:
pub(crate) fn the_function(&mut self, source: &'a str) -> SomeResult {
// `Compiler::compile()` returns a FunctionObject struct.
let func: FunctionObject = Compiler::compile(source);
// The enum variant `Object::Function` takes ownership of `func`
// The code works fine up until this point.
self.stack.push(Object::Function(func));
self.frames.push(Frame {
// The struct member `function` should have the
// exact same value as the one we just pushed into
// the `self.stack` vector.
function: func, // <---- Source of conflict
// ... other struct members
});
self.run() // self.run() returns `SomeResult`
}
Running this results in the error:
error[E0382]: use of moved value: `func`
|
37 | let func: FunctionObject = Compiler::compile(source);
| ---- move occurs because `func` has type `FunctionObject<'_>`, which does not implement the `Copy` trait
...
40 | self.stack.push(Object::Function(func));
| ---- value moved here
...
44 | function: func,
| ^^^^ value used here after move
I understand why this error occurs (or at least I think I understand): The Object::Function variant takes ownership of func, which is then dropped from memory when we are done pushing the object into self.stack. This then creates a conflict with the initialization of the Frame struct because I am trying to use a value that no longer exists.
I have tried implementing the Copy trait for the struct FunctionObject, but that creates even more problems because FunctionObject has a member of type Chunk<'a> which itself has vector members.
EDIT:
Cloning definitely solves the problem. However, by cloning the FunctionObject I would be duplicating the data inside the chunk which could be of an arbitrarily long size. Referencing the FunctionObject in both the stack with Object::Function(&func) and in the frame with Frame { function: &func, ... } then results in a 'func' does not live long enough error.
Is there something fundamentally wrong with what I am trying to do?
You seem to have a FunctionObject that you want to store both in stack and frame.
A better solution might be to not store the FunctionObject directly on the stack and frame, but use smart pointers instead.
I will show you a solution using Rc, however, you seem to be making a compiler, so you might want a different data structure to store your function objects in, like an arena.
The following code includes only the changes I made to your original, but you can also have a look on the playground where I got it to compile:
pub struct Frame<'a> {
pub function: std::rc::Rc<FunctionObject<'a>>,
// ... other struct members
}
pub enum Object<'a> {
Function(std::rc::Rc<FunctionObject<'a>>),
// Other enum variants
}
pub(crate) fn the_function(&mut self, source: &'a str) -> SomeResult {
// `Compiler::compile()` returns a FunctionObject struct.
let func: FunctionObject = Compiler::compile(source);
let func = std::rc::Rc::new(func);
// The enum variant `Object::Function` takes ownership of `func`
// The code works fine up until this point.
self.stack.push(Object::Function(func.clone()));
self.frames.push(Frame {
// The struct member `function` should have the
// exact same value as the one we just pushed into
// the `self.stack` vector.
function: func, // <---- No longer source of conflict
// ... other struct members
});
self.run() // self.run() returns `SomeResult`
}
Rc manages an object by reference counting.
When the last Rc is dropped, the value (FunctionObject) will also be dropped.
Using .clone() on func makes a copy of the reference and increments the count, but doesn't copy the underlying object.
I am trying to use Encode::encode on structs with a derived implementation, but I am getting this error:
error[E0599]: no method named `encode` found for type `AnimalCollection<Animal>` in the current scope
--> src/main.rs:42:57
|
13 | struct AnimalCollection<A: AnimalTrait> {
| --------------------------------------- method `encode` not found for this
...
42 | println!("animal collection encoded = {:?}",animals.encode());
| ^^^^^^
|
= note: the method `encode` exists but the following trait bounds were not satisfied:
`AnimalCollection<Animal> : _IMPL_DECODE_FOR_Animal::_parity_codec::Encode`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `encode`, perhaps you need to implement it:
candidate #1: `_IMPL_DECODE_FOR_Animal::_parity_codec::Encode`
This is the code:
use indexmap::map::IndexMap;
use parity_codec;
use parity_codec::{Decode, Encode};
#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)]
struct Animal {
name: String,
cell: u32,
}
trait AnimalTrait: Encode + Decode {}
impl AnimalTrait for Animal {}
#[derive(Clone, PartialEq, Eq, Encode, Decode, Debug)]
struct AnimalCollection<A: AnimalTrait> {
animals: IndexMap<String, A>,
}
impl<A: AnimalTrait> AnimalCollection<A> {
fn new() -> AnimalCollection<A> {
AnimalCollection {
animals: IndexMap::new(),
}
}
fn add(&mut self, name: String, a: A) {
self.animals.insert(name, a);
}
}
fn main() {
let a = Animal {
name: String::from("Tiger"),
cell: 10,
};
println!("animal struct encoded = {:?}", a.encode());
let mut animals = AnimalCollection::<Animal>::new();
animals.add(
String::from("Dog"),
Animal {
name: String::from("Dog"),
cell: 1,
},
);
animals.add(
String::from("Cat"),
Animal {
name: String::from("Cat"),
cell: 2,
},
);
println!("animal collection encoded = {:?}", animals.encode());
}
Why isn't it working despite that I have #[derive]d all the traits automatically? How do I fix it?
Since I am deriving the Encode and Decode traits, I shouldn't really implement anything on my own, or should I?
I tested this code and it works on the Animal struct but doesn't work on the AnimalCollection struct. I also tried to implement the Encode trait on AnimalCollection but immediately got "conflicting implementation" error, so I am kind of stuck on how to solve this.
Cargo.toml is a bit tricky, you need to use derive feature:
[package]
name = "encmap"
version = "0.0.1"
edition = "2018"
[dependencies]
parity-codec = { version = "3.3", features = ["derive"] }
indexmap = "1.0.2"
I'm trying to understand the difference between the case where structs contain simple types vs. when they contain other structs. All guides/examples/... seem to use only basic types as fields and this works:
struct Something {
some: i32,
numbers: i32,
}
But this results in error:
struct Something {
reader: Reader,
writer: Writer,
}
On the current master: error: explicit lifetime bound required
So what's the solution here? Something is constructed with both reader and writer and is returned from that function - reader and writer themselves are not copied anywhere else.
Reader and Writer are traits and not other structs this is why that code does not work.
What you want to do does work with other structs as you can see here:
fn main() {
#[deriving(Show)]
struct OtherStruct {
s: uint,
}
#[deriving(Show)]
struct Something {
reader: OtherStruct,
}
println!("{}" , Something { reader : OtherStruct { s : 10 } });
}
For the actual Reader that you want to use you can have a look here.