Problem with serde serialize of slice of structs

Hello everyone,

I currently try to port some code from go to rust and I am running into something I don't quite understand. I want to have data structure which contains a slice of other structures and serialize them with serde (cbor to be exact). Unfortunately the compiler is not convinced that the Serialize trait for type B is really implemented. Here is the simplest example I could come up with which shows my problem:

extern crate serde;

use serde::{Deserialize, Serialize};

#[derive(Debug, Serialize, Deserialize)]
pub struct A<'a> {
    pub b_s: &'a [B<'a>],
}

#[derive(Debug, Serialize, Deserialize)]
pub struct B<'a> {
    pub value: &'a [u8],
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0277]: the trait bound `&'a [B<'a>]: serde::Deserialize<'_>` is not satisfied
 --> src/lib.rs:8:3
  |
8 |   pub b_s: &'a [B<'a>],
  |   ^^^ the trait `serde::Deserialize<'_>` is not implemented for `&'a [B<'a>]`
  |
  = help: the following implementations were found:
            <&'a [u8] as serde::Deserialize<'de>>
            <[T; 0] as serde::Deserialize<'de>>
            <[T; 10] as serde::Deserialize<'de>>
            <[T; 11] as serde::Deserialize<'de>>
          and 30 others
  = note: required by `serde::de::SeqAccess::next_element`

error[E0277]: the trait bound `&'a [B<'a>]: serde::Deserialize<'_>` is not satisfied
 --> src/lib.rs:8:3
  |
8 |   pub b_s: &'a [B<'a>],
  |   ^^^ the trait `serde::Deserialize<'_>` is not implemented for `&'a [B<'a>]`
  |
  = help: the following implementations were found:
            <&'a [u8] as serde::Deserialize<'de>>
            <[T; 0] as serde::Deserialize<'de>>
            <[T; 10] as serde::Deserialize<'de>>
            <[T; 11] as serde::Deserialize<'de>>
          and 30 others
  = note: required by `serde::de::MapAccess::next_value`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
error: Could not compile `playground`.

To learn more, run the command again with --verbose.

At least for me, as a beginner, this compiler error message is not really helpful. I guess that &'a [B<'a>] is another type than B<'a>, but I also don't know how to implement Serialize for &'a [B<'a>].

Any help is appreciated. In the long run this code also need to work in no_std environments, but for now just getting it to work would also help so much.

Thanks in advance.

You can't deserialize into a reference, remember references are just views into some other data

Rule of thumb is: if you had slice in Golang, you probably want Vec in Rust. In Rust the slice, or [T] is not a kind of collection type. It really is a memory chunk which consists of zero or more value of same type, placed directly next to each other. As it doesn't care about the heap memory, even stack-allocated fixed-size C-like arrays can be used as slice. Definition really matters!

Though people usually call it just "slice" , &[T] actually is a "refference to slice". Just like other references &[T] doesn't own the slice. Instead, it just references the slice owned by someone else.

By definition a slice's size can't be determined at compile time, as its length can only be known at runtime. In Rust we call such types "Unsized type". They exist in type system, but cannot be placed on the variable as Rust doesn't allows dynamic stack frame. Instead, you can use some wrapper types to use them. Stack-allocated array is a one way, but their size must be known at compile time. In most case the Vec<T>, or the growable array should be your mate. There also is Box<[T]>, but you can't easily modify it's length after construction.

4 Likes

Thank you so much for your explanation. Now slices in rust make bit more sense to me. Coming from Go this was actually a bit confusing for me.
I will now try to implement my code for "normal" rust targets, and then try to optimize this for no_std use. This going to be a learning experience :slight_smile:

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.