Howdy, everyone! I am building a simple client-server tcp communication library. The trick is that the client must be a no_std library. We can ignore the socket communication issues with no_std for now.
My issue is that I can't seem to pass any data buffer into the deserialize function because it requires that data buffer to be static. But, my data can't be static. It's ultimately going to come out of a socket.
This is the simplest case I have:
pub fn main() {
// In this example, we'll just use an empty buffer
let mut data = [0 as u8; 100];
/// Now, I deserialize it
let result = serde_json_core::from_slice::<NetworkMessage>(&data);
let message = result.unwrap();
println!("{:?}", message); // Should be an instance of NetworkMessage
}
That gives me the error:
error[E0597]: `data` does not live long enough
--> src/main.rs:40:60
|
40 | let result = serde_json_core::from_slice::<NetworkMessage>(&data);
| ^^^^^
| |
| borrowed value does not live long enough
| cast requires that `data` is borrowed for `'static`
...
109 | }
| - `data` dropped here while still borrowed
I am sure I am missing something obvious. I'm more sure (and open to the idea that) my code needs to be reorganized.
That is where the static lifetime is being brought in. So, I'm looking for alternatives. I cannot use a standard library there, so String is out of the question.
It can be, but not in the way you'd normally do in Rust. What you effectively need is a static mut variable, something that is known in Rust to be unsafe. So what you can do is as follows:
Use a Mutex made from a spin-lock. Write your own or use the spin crate.
Use the lazy_static macro from a crate of the same name.
I think I'm almost there. The issue I've hit is that the lazy_static! macro doesn't have a rule for the mut keyword. And I can't seem to get the static variable to be mutable in order for me to use it.
#[macro_use]
extern crate lazy_static;
use std::borrow::{Borrow, BorrowMut};
use spin::Mutex;
lazy_static! {
static ref DATA: Mutex<[u8; 100]> = Mutex::new([0_u8;100]);
}
pub fn main() {
let result = serde_json_core::from_slice::<NetworkMessage>(DATA.borrow_mut().get_mut());
}
produces
error[E0596]: cannot borrow immutable static item `DATA` as mutable
--> src/main.rs:54:64
|
54 | let result = serde_json_core::from_slice::<NetworkMessage>(DATA.borrow_mut().get_mut());
| ^^^^ cannot borrow as mutable
I have tried borrow() and borrow_mut(). In one instance, the compiler suggested:
= help: trait DerefMut is required to modify through a dereference, but it is not implemented for DATA
EDIT:
And when I try to lock the mutex, I get the original problem. It says that the value is not static:
let mut a = DATA.lock();
let result = serde_json_core::from_slice::<NetworkMessage>(&*a);
The issue is the &'static itself. Having &'static T at some point means the T, in this case the string content and its buffer, should exist and accessible for the entire lifetime of the process. That's why &'static str practically means some string literal or substring of it.
Thank you @Hyeonu that was just the solution I needed. And what's worse, I knew that, lol.
For future googlers, this was the final solution:
#[derive(Serialize, Deserialize, Debug)]
pub struct NetworkMessage<'a> {
pub message: &'a str,
}
pub fn main() {
let mut data = [0 as u8; 100];
// A function that fills data from a TcpStream
let result = serde_json_core::from_slice::<NetworkMessage>(&data);
let nm = result.unwrap();
println!("{:?}", nm.message); // Whatever came off the line
}
Of course it doesn't have one. A static can't be mutable just like that! Since it is accessible globally, then one could create multiple simultaneous mutable borrows to it, creating unsoundness. (Worse yet, it could even be mutated from multiple threads at the same time.)
This is exactly why you shouldn't ignore the first part of @RedDocMD 's advice: you will need a Mutex. You wrap your object in a Mutex, you put the mutex in an apparently non-mutable lazy static, and then the mutex will allow exclusive mutation through its own interface only, which ensures locking (i.e. exclusive borrowing).