serde_closure
serde_closure copied to clipboard
How to serialize and Deserialize closure?
Hello, I am trying to do it.
You wrote:
you either need to specify the precise type you're deserializing without naming it (which is possible but not particularly practical)
How to do it(to deserialize)?
I use serde_traitobject and write this code
use serde_traitobject as st;
let one:usize = 1;
let two:usize = 2;
let plus_one = Fn!(|x: usize| x + one + two);
let s: st::Box<dyn serde_traitobject::Fn(usize) -> usize> = st::Box::new(plus_one);
let serialized = serde_json::to_string(&s).unwrap();
println!("{}",serialized);
let deserialized: st::Box<dyn serde_traitobject::Fn(usize) -> usize> = serde_json::from_str(serialized.as_str()).unwrap();
And I have error:
the trait bound `&usize: main::_IMPL_DESERIALIZE_FOR_MyStruct::_serde::Deserialize<'_>` is not satisfied
What should I do?
Can I create struct with two or more closures and serialize and deserialize it? Without Box<dyn ... Fn> just Box<MyStructTrait>?
Hi @TrionProg, thanks for filing an issue!
I think the problem is that the closure here needs to be a move
closure to take ownership of the captured variables (one
and two
), rather than take references to them. This is because it's not possible to deserialize to a reference (your error message shows it's trying to deserialize to a &usize
, which isn't possible).
This should work:
let plus_one = Fn!(move |x: usize| x + one + two);
Can I create struct with two or more closures and serialize and deserialize it? Without Box<dyn ... Fn> just Box?
Boxing the closure's trait object, i.e. Box<dyn ... Fn>
, is necessary in most use cases. A struct containing multiple closures could look like:
struct MultipleClosures {
a: Box<dyn st::Fn(usize) -> usize>,
b: Box<dyn st::Fn(usize) -> usize>,
}
Hello. Hm. Yes, I've forgotten move. And now it works.
Unfortunately I need use 2 boxes in the struct, + 1 box for this struct. Later, I hope, I will try to optimize it to MultipleClosures<F1,F2>, this should be simmilar to error_impl in failure library:
Box<Inner<Fail>>
struct Inner<E:Fail> {
backtrace
error:E
}
Thank you for your fantastic library!
Hello. Ohh, not all is right. I can not show the code -- it has a lot of garbage and I can not understand anything that happens -- All works, but then I implement Trait, I have a lot of problems like Self: traitobject::Sealed is not satisfied.
Can you give me an example how to: Create trait(MyTrait), that wants Self(MultipleClosures) be serializable (by your library). And Just create MultipleClosures, insert it in Box<dyn MyTrait>and it will serialize and deserialize it. MultipleClosures has one generic as parameter, It should not be stored in this struct, for example, closure a returns it.
Okey. I am making experiment. Minimal example of same error.
#![feature(unboxed_closures)]
extern crate serde;
extern crate serde_traitobject;
#[macro_use]
extern crate serde_closure;
#[macro_use]
extern crate serde_derive;
use serde_traitobject::FnOnce as FnOnceTO;
use serde_traitobject::Box as BoxTO;
use serde_traitobject::{
Serialize as SerializeTO,
Deserialize as DeserializeTO
};
use serde_derive::{Serialize, Deserialize};
use std::marker::PhantomData;
pub trait BlockTrait: SerializeTO + DeserializeTO{
fn exec(&mut self) -> bool;
}
#[derive(Serialize, Deserialize)]
struct TwoClosures<T> where
T:'static
{
inner: Option<TwoClosuresInner<T>>
}
#[derive(Serialize, Deserialize)]
struct TwoClosuresInner<T> where
T:'static
{
#[serde(with = "serde_traitobject")]
a: Box<FnOnceTO() -> T>,
#[serde(with = "serde_traitobject")]
b: Box<FnOnceTO(T) -> bool>,
_phantom_data:PhantomData<T>
}
impl<T> TwoClosures<T> where
{
fn new<A, B>(a:A, b:B) -> Self where
A: FnOnceTO() -> T + 'static,
B: FnOnceTO(T) -> bool + 'static
{
let inner = TwoClosuresInner {
a: Box::new(a),
b: Box::new(b),
_phantom_data: PhantomData
};
TwoClosures {
inner: Some(inner)
}
}
}
impl<T> BlockTrait for TwoClosures<T> {
fn exec(&mut self) -> bool {
let inner = self.inner.extract();
let t = (inner.a)();
(inner.b)(t)
}
}
fn main() {
let tc = TwoClosures::new(
FnOnce!(|| 8usize),
FnOnce!(move|v|v==8),
);
let tc_box:BoxTO<dyn BlockTrait> = BoxTO::new(tc);
let serialized = serde_json::to_string(&tc_box).unwrap();
println!("{}",serialized);
}
And errors. It wants T to be serializable, but it is 'static.
error[E0277]: the trait bound `TwoClosures<T>: serde_traitobject::serialize::Sealed` is not satisfied
--> src\main.rs:67:9
|
67 | impl<T> BlockTrait for TwoClosures<T> {
| ^^^^^^^^^^ the trait `serde_traitobject::serialize::Sealed` is not implemented for `TwoClosures<T>`
error[E0277]: the trait bound `T: serde::Serialize` is not satisfied
--> src\main.rs:67:9
|
67 | impl<T> BlockTrait for TwoClosures<T> {
| - ^^^^^^^^^^ the trait `serde::Serialize` is not implemented for `T`
| |
| help: consider restricting this bound: `T: serde::Serialize`
|
= note: required because of the requirements on the impl of `serde::Serialize` for `TwoClosures<T>`
= note: required because of the requirements on the impl of `serde_traitobject::Serialize` for `TwoClosures<T>`
error[E0277]: the trait bound `T: serde::Deserialize<'_>` is not satisfied
--> src\main.rs:67:9
|
67 | impl<T> BlockTrait for TwoClosures<T> {
| - ^^^^^^^^^^ the trait `serde::Deserialize<'_>` is not implemented for `T`
| |
| help: consider restricting this bound: `T: serde::Deserialize<'_>`
|
= note: required because of the requirements on the impl of `for<'de> serde::Deserialize<'de>` for `TwoClosures<T>`
= note: required because of the requirements on the impl of `serde::de::DeserializeOwned` for `TwoClosures<T>`
= note: required because of the requirements on the impl of `serde_traitobject::Deserialize` for `TwoClosures<T>`
UPD.
I want to do not haul this 'de, but I try:
pub trait BlockTrait<'de>: Serialize + Deserialize<'de>{
fn exec(&mut self) -> bool;
}
impl<'de, T> BlockTrait<'de> for TwoClosures<T> {
fn exec(&mut self) -> bool {
let inner = self.inner.extract();
let t = (inner.a)();
(inner.b)(t)
}
}
And it wants T:Serialize, T:Deserialize =(
And second question: how to serialize struct TwoClosures by may hands without derive?
To make that minimal example work, you need to add #[serde(bound = "")]
like this:
#[derive(Serialize, Deserialize)]
#[serde(bound = "")]
struct TwoClosures<T> where
T:'static
{
inner: Option<TwoClosuresInner<T>>
}
Without it, serde is generating:
impl<T> Serialize for TwoClosures<T> where T: Serialize { ... }
Though as actually T
itself is never serialized, the bound is unnecessary. Adding #[serde(bound = "")]
makes serde generate this:
impl<T> Serialize for TwoClosures<T> { ... }
which then enables your program to compile.
And second question: how to serialize struct TwoClosures by may hands without derive?
The serde guide to implementing Serialize and Deserialize are helpful here. The easiest way to serialize/deserialize them manually is as tuples.
Hello. Hm.. It works! Thanks.
About Box in structures. What I should to use std::Box or s_to::Box? What is differense? Now it is using std::Box and it works, but maybe I should use s_to::Box. But how I remember I was unable to serialize std::Box manually.
Long live to new problems!
My manual serialization worked.
I am adding new generic M
pub trait BlockTrait<M:MyTrait>: SerializeTO + DeserializeTO{
fn exec(&mut self, m:&mut M) -> bool;
}
pub trait MyTrait {}
struct TwoClosures<T, M> where
T:'static,
M:MyTrait + 'static
{
inner: DataContainer<TwoClosuresInner<T, M>>
}
struct TwoClosuresInner<T, M> where
T:'static,
M:MyTrait + 'static
{
a: BoxTO<FnOnceTO(&mut M) -> T>,
b: BoxTO<FnOnceTO(T) -> bool>,
}
And I have this problem:
error[E0277]: the trait bound `dyn for<'r> serde_traitobject::FnOnce<(&'r mut M,), Output = T>: serde::Serialize` is not satisfied
--> src\main.rs:107:32
|
107 | s.serialize_field("a", &inner.a)?;
| ^^^^^^^^ the trait `serde::Serialize` is not implemented for `dyn for<'r> serde_traitobject::FnOnce<(&'r mut M,), Output = T>`
|
= help: the following implementations were found:
<(dyn serde_traitobject::FnOnce<Args, Output = Output> + 'static) as serde::Serialize>
<(dyn serde_traitobject::FnOnce<Args, Output = Output> + std::marker::Send + 'static) as serde::Serialize>
= note: required because of the requirements on the impl of `serde::Serialize` for `std::boxed::Box<dyn for<'r> serde_traitobject::FnOnce<(&'r mut M,), Output = T>>`
And something about Deser.
The fragment of code:
impl<T,M> Serialize for TwoClosures<T,M> where
//T:'static,
M:MyTrait
{
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
use crate::serde::ser::SerializeStruct;
let inner = self.inner.get();
let mut s = serializer.serialize_struct("TwoClosures", 2)?;
s.serialize_field("a", &inner.a)?;
s.serialize_field("b", &inner.b)?;
s.end()
}
}
It may be solved by using BoxTO instead of Box, but without M it worked! Very strange...
And I want M to be Serial and Deserial -able. How to mark it in trait MyBlock
or trait MyTrait
? Note: Other difficult code works by #derive , but I have problems with manual serialization