I have an array, each element is a struct, I have do something for the struct G1, according to https://serde.rs/remote-derive.html this tutorial. but I got an array when I want to use it for [G1,L].
The ECPDef seems work for G1 struct, but not work for [G1,L], can you help me, plz
Function specified for serde(with
is for a specific type, you can't change its type.
Try this instead:
#[repr(transparent)]
struct G1Wrapper(#[serde(with = "ECPDef")] G1);
and then
c: [G1Wrapper; L]
you can transmute
between [G1Wrapper; L]
and [G1; L]
if you have to.
Another option would be to write your own function for serde(with
that supports arrays.
thanks for your replay but still some error
The SipCipher is a remote struct, it's filed c is [G1;L], if change to [G1Wrapper; L] is that ok? Or there are some other reason
Serde unfortunately does not support generics of arbitrary length; they decided at some point to support [T; 0]: Serialize
without a T: Serialize
bound (and the same for Deserialize) which prevents creating a generic implementation in a backwards compatible way, at least with the current capabilities of rust. (The standard library has the same problem with [T; N]: Default
, so it seems likely that there will be a fix eventually, but it could take years still.)
For now, you'll need to "manually" handle the array, possibly using another crate. For example with
you could use something like
#[serde_as(as = "[FromInto<G1Wrapper>; L]")]
c: [G1; L]
(haven't tested the code)
and even save the need for transmutes, too. (You need to implement From<G1Wrapper> for G1
and From<G1> for G1Wrapper
for this, or alternatively the corresponding Into
implementations. You could also use derive_more for From
and Into
on GTWrapper
if you don't want to write any implementations manually.)
Edit: Actually, the use of FromInto
would introduce an additional Clone
when serializing. If cloning G1
is too much overhead, using the G1Wrapper
with transmute as suggested before might be the better option. You can do
#[serde_as(as = "[_; L]")]
c: [G1Wrapper; L]
(haven't tested the code)
to handle the array.
I want to convert this SipCipher struct defined in https://github.com/Ruby-Protocol/private_ml/blob/main/src/simple_ip.rs which look like
#[derive(Debug)] pub struct SipCipher<const L: usize> { c0: G1, c: [G1; L] }
the G1 is actually a struct called ECP defined in https://github.com/lovesh/miracl_core_generated/blob/master/rust_64/src/bls12381/ecp.rs
So I followed the serde doc https://serde.rs/remote-derive.html to add ECPDef for use in SipCipher.
So now the code will look like #[derive(Serialize,Deserialize)] pub struct SipCipher<const L: usize> { #[serde(with="ECPDef")] c0: G1, #[serde(with="ECPDef")] c: [G1; L] }
but some thing wrong
"mismatched types
expected struct miracl_core::bls12381::ecp::ECP
, found array
note: expected reference &miracl_core::bls12381::ecp::ECP
found reference &'__a [miracl_core::bls12381::ecp::ECP; L]
rustc(E0308)
simple_ip.rs(49, 10): expected struct miracl_core::bls12381::ecp::ECP
, found array"
So can anyone help me? PLZ
Thank you so much for the replay. If I want to remain c:[G1;L], what should I do. I already implement From<G1Wrapper> for G1
and From<G1> for G1Wrapper
. but some new error
cannot find type
FromInto in this scope not found in this scoperustc(E0412)
You need to: use serde_with::FromInto;
thank you so much, you are so nice!!!!
I just noticed that ECPDef
is probably also remote
derived... you can save the unnecessary clone
on serialization by following this pattern
It's probably also more concise, you don't need to define a wrapper type at all. Just implement the necessary trivial impl<'de> DeserializeAs<'de, G1> for ECPDef
and SerializeAs<G1> for ECPDef
and the you can use (as = "[ECPDef; L]")
on an [G1; L]
field.
I am sorry, but I just find out the remote struct ECP impls tostring(). which means the
pub struct SipCipher<const L: usize> { c0: G1, c: [G1; L] }
can be directly into some string like this
impl<const L: usize> SipCipher<L>{
fn getc0(&self) -> String {
self.c0.tostring()
}
fn getc(&self) -> Vec<String>{
let result: Vec<String> = self.c.iter().map(|g| g.tostring()).collect();
result
}}
then I need JSON those string
This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.