heapless icon indicating copy to clipboard operation
heapless copied to clipboard

Heapless String doesn't implement From trait

Open lvanasse opened this issue 1 year ago • 7 comments

Hi, I'm fairly new to Rust, so I apologize in advance if my issue is not clear or not exact.

I've being trying to use serde-json-core with Zenoh and I get this error when I try to publish a simple struct with a String and an u64.

error[E0277]: the trait bound `Value: From<serde_json_core::heapless::String<_>>` is not satisfied
   --> src/nodes/node_example2.rs:39:27
    |
39  |             publisher.put(serde_json_core::to_string(&node_msg_example.into()).unwrap()).res_sync().unwrap();
    |                       --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<serde_json_core::heapless::String<_>>` is not implemented for `Value`
    |                       |
    |                       required by a bound introduced by this call
    |
    = help: the following other types implement trait `From<T>`:
              <Value as From<isize>>
              <Value as From<i8>>
              <Value as From<i16>>
              <Value as From<i32>>
              <Value as From<i64>>
              <Value as From<usize>>
              <Value as From<u8>>
              <Value as From<u16>>
            and 13 others
    = note: required for `serde_json_core::heapless::String<_>` to implement `Into<Value>`
note: required by a bound in `Publisher::<'a>::put`
   --> /home/ludovic/.cargo/registry/src/index.crates.io-6f17d22bba15001f/zenoh-0.10.1-rc/src/publication.rs:415:20
    |
413 |     pub fn put<IntoValue>(&self, value: IntoValue) -> Publication
    |            --- required by a bound in this associated function
414 |     where
415 |         IntoValue: Into<Value>,
    |                    ^^^^^^^^^^^ required by this bound in `Publisher::<'a>::put`

For more information about this error, try `rustc --explain E0277`.

From my understanding, the String implementation in heapless needs to satisfied the From trait. Although maybe I didn't create my
string properly or didn't give it properly to Zenoh function. If you have any insight into that, it would be much appreciated.

Here's what I'm trying to publish on Zenoh:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct NodeMsgExample<'a> {
    pub msg_str: &'a str,
    pub msg_random_num: u64,
}

And here's the code I'm using to publish the NodeMsgExample:

let mut config = Config::default();
config.transport.shared_memory.set_enabled(true).unwrap();
println!("Opening session...");
let session = zenoh::open(config).res_sync().unwrap();

let publisher = session
    .declare_publisher("test/node")
    .congestion_control(CongestionControl::Block)
    .res_sync()
    .unwrap();

let node_msg_example = NodeMsgExample {
    msg_str: "node_2",
    msg_random_num: self.n,
};
loop {
    println!(
        "Publish on node 2: {str} {num}",
        str = node_msg_example.msg_str,
        num = node_msg_example.msg_random_num
    );

    // publisher.put(serde_json_core::to_string(&node_msg_example).unwrap()).res_sync().unwrap();
    publisher.put(serde_json_core::to_string(&node_msg_example).unwrap()).res_sync().unwrap();
    thread::sleep(Duration::from_secs(1));
}

If you need more information from me, don't hesitate to ask.

Thanks in advance, cheers!

lvanasse avatar Jan 26 '24 21:01 lvanasse

I was not able to reproduce this. I put my code here: https://github.com/newAM/heapless-issue-450

I did use the latest (unreleased) git version of serde_json_core because the current release is using an older heapless (0.7), which might be why I couldn't reproduce it.

Can you share your heapless/serde/serde_json_core versions?

newAM avatar Jan 27 '24 17:01 newAM

Hi @newAM, thanks a lot for your quick answer.

I've reused the same version as you've proposed in your repository. Which are:

heapless = { version = "0.8.0", features = ["serde"] }
serde = { version = "1.0.196", features = ["derive"] }
serde-json-core = { git = "https://github.com/rust-embedded-community/serde-json-core", rev = "9327a14e74ad3b4fd37a9ac34e72b61aa5fcc9bf" }

But I still get this error:

error[E0277]: the trait bound `Value: From<serde_json_core::heapless::String<_>>` is not satisfied
   --> src/nodes/node_example2.rs:38:27
    |
38  |             publisher.put(serde_json_core::to_string(&node_msg_example).unwrap()).res_sync().unwrap();
    |                       --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<serde_json_core::heapless::String<_>>` is not implemented for `Value`
    |                       |
    |                       required by a bound introduced by this call
    |
    = help: the following other types implement trait `From<T>`:
              <Value as From<isize>>
              <Value as From<i8>>
              <Value as From<i16>>
              <Value as From<i32>>
              <Value as From<i64>>
              <Value as From<usize>>
              <Value as From<u8>>
              <Value as From<u16>>
            and 13 others
    = note: required for `serde_json_core::heapless::String<_>` to implement `Into<Value>`
note: required by a bound in `Publisher::<'a>::put`
   --> /home/ludovic/.cargo/registry/src/index.crates.io-6f17d22bba15001f/zenoh-0.10.1-rc/src/publication.rs:415:20
    |
413 |     pub fn put<IntoValue>(&self, value: IntoValue) -> Publication
    |            --- required by a bound in this associated function
414 |     where
415 |         IntoValue: Into<Value>,
    |                    ^^^^^^^^^^^ required by this bound in `Publisher::<'a>::put`

For more information about this error, try `rustc --explain E0277`.

Maybe something that could help, is that I'm using Zenoh put function from a publisher: https://docs.rs/zenoh/0.10.0-rc/zenoh/publication/struct.Publisher.html#method.put

Maybe I'm not understanding the error correctly? Maybe the issue might be with serde-json-core?

Sorry, I'm a bit confused :confused:

lvanasse avatar Jan 29 '24 15:01 lvanasse

Ah I see the issue now, zenoh doesn't implement conversion from heapless types for Value: https://docs.rs/zenoh/0.10.1-rc/zenoh/value/struct.Value.html

Try converting the heapless String to a str first.

I'm on my phone now so I can't easily provide an example. If this doesn't help let me know and I'll provide a code example when I have a proper keyboard.

newAM avatar Jan 29 '24 15:01 newAM

@newAM sadly I still get the same error.

Here's what I'm using now:

use serde::{Deserialize, Serialize};

#[derive(Serialize, Deserialize)]
pub struct NodeMsgExample<'a> {
    pub msg_str: &'a str,
    pub msg_random_num: u64,
}

From my understanding, this would be a statically allocated string when I create my NodeMsgExample struct (?). Which, I don't think I'm allocating anything static here? Although there might be some Rust black magic going on.

let mut config = Config::default();
config.transport.shared_memory.set_enabled(true).unwrap();
println!("Opening session...");
let session = zenoh::open(config).res_sync().unwrap();

let publisher = session
    .declare_publisher("test/node")
    .congestion_control(CongestionControl::Block)
    .res_sync()
    .unwrap();

let node_msg_example = NodeMsgExample {
    msg_str: "node_2",
    msg_random_num: self.n,
};
loop {
    println!(
        "Publish on node 2: {str} {num}",
        str = node_msg_example.msg_str,
        num = node_msg_example.msg_random_num
    );

    publisher.put(serde_json_core::to_string(&node_msg_example).unwrap()).res_sync().unwrap();
    thread::sleep(Duration::from_secs(1));
}

Again, sorry for my lack of expertise in Rust, I'm learning as I go :sweat_smile:

lvanasse avatar Jan 29 '24 16:01 lvanasse

No worries :)

Currently the type going into publisher.put is heapless::String, but zenoh::value::Value doesn't implement From<heapless::String>, instead try serde_json_core::to_string(&node_msg_example).unwrap().as_str(), the final .as_str() changes the representation to a &str.

newAM avatar Jan 30 '24 01:01 newAM

Hi @newAM, sorry for the delayed response, and thanks a lot for the response. I really appreciate the help! :)

Here's what the code looks like now:

publisher.put(serde_json_core::to_string(&node_msg_example).unwrap().as_str()).res_sync().unwrap();

But it seems that serde_json_core::to_string requires the length of the string(?), here's the output of cargo build:

Compiling lux-iron-bird v0.1.0 (/home/ludovic/Code/lux-iron-bird-software)
error[E0282]: type annotations needed
  --> src/nodes/node_example2.rs:38:27
   |
38 |             publisher.put(serde_json_core::to_string(&node_msg_example).unwrap().as_str()).res_sync().unwrap();
   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the const parameter `N` declared on the function `to_string`
   |
help: consider specifying the generic arguments
   |
38 |             publisher.put(serde_json_core::to_string::<NodeMsgExample<'_>, N>(&node_msg_example).unwrap().as_str()).res_sync().unwrap();
   |                                                     +++++++++++++++++++++++++

For more information about this error, try `rustc --explain E0282`.
error: could not compile `lux-iron-bird` (bin "lux-iron-bird") due to previous error

It feels like I would need to add the string length information somewhere in the structure definition.

lvanasse avatar Jan 31 '24 15:01 lvanasse

That's correct, the heapless types need a size for the static buffer they use, it's a little bit more clear what's going on when expanding the code:

#[derive(serde::Serialize, serde::Deserialize)]
pub struct NodeMsgExample<'a> {
    pub msg_str: &'a str,
    pub msg_random_num: u64,
}

fn main() {
    let node_msg_example = NodeMsgExample {
        msg_str: "node_2",
        msg_random_num: 123456,
    };

    let json_heapless: heapless::String<32> =
        serde_json_core::to_string(&node_msg_example).unwrap();

    let json_str: &str = json_heapless.as_str();

    let value = zenoh::value::Value::from(json_str);
}

newAM avatar Feb 04 '24 22:02 newAM

Sorry for the delay @newAM, this works for me! Thank you very much for all your help, it is very much appreciated!

lvanasse avatar Apr 01 '24 18:04 lvanasse