Rust serde_json serializer for pretty print of ([u8; 32])


#1

I want to get the pretty print in Rust for ([u8; 32]), but can’t make it build successfully. Especially I’m confused by the 1st build error at line 10: “expected array of 32 elements”. Could somebody help?

extern crate serde;
extern crate serde_json;

#[macro_use]
extern crate serde_derive;

use serde_json::Error;
use serde::{Serializer, Deserialize, Deserializer};

#[derive(Serialize, Deserialize)]
struct OneFactor(
    #[serde(serialize_with = "buffer_to_hex", deserialize_with = "hex_to_buffer")]
    [u8; 32]
);
...

And I put the full code into the Rust Playground for your easier check.

The build errors:

   Compiling playground v0.0.1 (file:///playground)
error[E0308]: match arms have incompatible types
  --> src/main.rs:10:21
   |
10 | #[derive(Serialize, Deserialize)]
   |                     -----------
   |                     |
   |                     expected array of 32 elements, found struct `std::vec::Vec`
   |                     match arm with an incompatible type
   |                     in this macro invocation
   |
   = note: expected type `[u8; 32]`
              found type `std::vec::Vec<u8>`

error[E0308]: match arms have incompatible types
  --> src/main.rs:10:21
   |
10 | #[derive(Serialize, Deserialize)]
   |                     -----------
   |                     |
   |                     expected array of 32 elements, found struct `std::vec::Vec`
   |                     match arm with an incompatible type
   |                     in this macro invocation
   |
   = note: expected type `[u8; 32]`
              found type `std::vec::Vec<u8>`

error[E0599]: no method named `to_hex` found for type `&[u8]` in the current scope
  --> src/main.rs:21:45
   |
21 |   serializer.serialize_str(&buffer.as_ref().to_hex())
   |                                             ^^^^^^
   |
   = help: did you mean `to_vec`?

error[E0599]: no function or associated item named `from_hex` found for type `std::vec::Vec<_>` in the current scope
  --> src/main.rs:30:24
   |
30 |     .and_then(|string| Vec::from_hex(&string).map_err(|err| Error::custom(err.to_string())))
   |                        ^^^^^^^^^^^^^ function or associated item not found in `std::vec::Vec<_>`

error: aborting due to 4 previous errors

#2

Looks like the problem is that serde expects hex_to_buffer to return Result<[u8; 32], D::Error>, but your function returns Result<Vec<u8>, D::Error> instead.


#3

A slight reinterpretation, fixed.

  1. Your struct contains a [u8; 32], while the deserialization function returns a Vec<u8>. They’re not interchangeable.

  2. It’s not immediately clear where from_hex() and to_hex() come from; I guessed rustc_serialize, which is the predecessor of Serde, and long obsolete.

  3. In Rust, fixed-size arrays are still a bit cumbersome until const generics land, so Vec and slices are easier to work with. My code exchanged [u8; 32] with Vec<u8> in the struct.


#4

That’s great! Thanks very much @inejge

Is it possible to keep the struct as ([u8; 32]) but modify the from_hex() and to_hex() ? because my data struct can’t be modified in that existing project.


#5

It might be if you write your own versions. You could also re-use those functions, but copy to/from a [u8; 32] as needed (it’s inefficient, but might be tolerable, depending on your use case.)


#6

thanks, that would be a solution, but lower efficiency. I like to have a better solution, still searching on the web.


#7

I tried and finally make the to_hex() direction works :slight_smile: http://play.integer32.com/?gist=05fef4638189f1bf860920bd623149da&version=stable&mode=debug&edition=2015

the reverse direction from_hex() still need help ~