Share memory data by REST parameters in Rust - rust

my "main" file
mod router;
mod student;
use std::sync::Arc;
use crate::router::init_router;
use crate::router::Memory;
use actix_web::{App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv::dotenv().ok();
let repo = Arc::new(Memory::repository());
let host = std::env::var("SERVER.HOST").unwrap_or("127.0.0.1".to_string());
let port = std::env::var("SERVER.PORT").unwrap_or("8080".to_string());
let url = format!("{}:{}", host, port);
println!("url: {}", &url);
HttpServer::new(move || {
App::new()
.data(repo.clone()) // shared
.configure(init_router)
})
.bind(&url)?
.run()
.await
}
my file: "router.rs"
use std::sync::Arc;
use crate::student::Student;
use actix_web::{get, web, HttpResponse, Responder};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Memory {
pub students: Vec<Student>,
}
impl Memory {
fn new() -> Self {
Memory {
students: Vec::new(),
}
}
pub fn repository() -> Self{
Self {
students: vec![
{Student::new("1".to_string(), "Daniel".to_string(), 19)},
{Student::new("2".to_string(), "Lucia".to_string(), 17)},
{Student::new("3".to_string(), "Juan".to_string(), 14)}
]
}
}
}
#[get("/studen/list/all")]
async fn list_all(repo: web::Data<Arc<Memory>>) -> impl Responder {
HttpResponse::Ok().json(repo)
}
pub fn init_router(config: &mut web::ServiceConfig) {
config.service(list_all);
}
and my file: "student.rs"
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Student{
pub id: String,
pub nombre: String,
pub calificacion: u32,
}
impl Student{
pub fn new(id: String, nombre: String, calificacion: u32) -> Self{
Self{id, nombre, calificacion}
}
}
so I want to show all students in a json via the following path: 127.0.0.1:3000/student/list/all
but i have the following error
| HttpResponse::Ok().json(repo)
| ^^^^ the trait Serialize is not implemented for Data<Arc<Memory>>
I still can't pass this data by parameter of a GET method, I need a little help please to display it in json. It is necessary because later I will need this data by parameter to add or remove.

(Note that you typed #[get("/studen/list/all")] instead of #[get("/student/list/all")] in your original code.)
You don't want to serialize the Data<Arc<Memory>> to JSON, you only want to serialize the Memory. To do so, you can dereference the Data<Arc<Memory>> to get an Arc<Arc<Memory>>, then dereference the Arcs twice to get a Memory. Then, you add a reference as to not require cloning the resulting Memory. So, you replace
HttpResponse::Ok().json(repo)
with
HttpResponse::Ok().json(&***repo)
However, Data is already a wrapper around an Arc, so no Arc<Memory> in the is required. If you want to edit the Memory eventually, you'll have to add a Mutex inside. So, you'll have to obtain a lock on repo before serializing it.

Related

How do you generate a struct dynamically at compile time in Rust?

I have the following:
struct Health {
health: f32,
}
struct Position {
position: Vec2,
}
struct Collections {
healths: Vec<Health>,
positions: Vec<Position>,
}
I would like to generate the Collections struct automatically; I am thinking using a macro?
I thought perhaps I could mark each struct I want to include with a custom attribute and then have a macro which builds the Collections struct.
How could I do this?
To be able to do something like custom attributes you need to write a proc_macro, that can do almost anything you need with your code.
For a simpler solution you may try with a normal macro_rules. For that you will need to enclose your type definitions into a macro that does the parsing, and emits back the type definition plus the extra code you need, in your case the Container class.
Something like this:
macro_rules! collectables {
(
$(
#[collection=$fname:ident]
$(#[$attr:meta])?
$vis:vis struct $name:ident $def:tt
)*
) => {
// The struct definitions
$(
$(#[$attr])?
$vis struct $name $def
)*
// The container
#[derive(Default, Debug)]
pub struct Collections {
$(
$fname: Vec<$name>,
)*
}
};
}
Now you can use the macro to build your original code (playground):
collectables!{
#[collection=healths]
#[derive(Debug)]
struct Health {
health: f32,
}
#[collection=positions]
#[derive(Debug)]
struct Position {
position: (f32, f32),
}
}
Note that as written the #[collection=xxx] attribute is mandatory and must be the first in every struct definition.
So I managed to solve this problem using a proc_macro. Each struct which is to be included in the final Storage struct is marked with the Component derive attribute. The Storage struct is then built with the storage!() macro.
use lazy_static::lazy_static;
use proc_macro::TokenStream;
use quote::quote;
use std::sync::Mutex;
use syn::{parse_macro_input, parse_str, DeriveInput, ExprType};
lazy_static! {
static ref COMPONENTS: Mutex<Vec<String>> = Mutex::new(Vec::new());
}
#[proc_macro_derive(Component)]
pub fn component(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput); ‣DeriveInput
let ident = input.ident; ‣Ident
COMPONENTS.lock().unwrap().push(ident.to_string());
let expanded = quote! { ‣TokenStream
impl component::Component for #ident {}
};
TokenStream::from(expanded)
}
#[proc_macro]
pub fn storage(_input: TokenStream) -> TokenStream {
println!("Building Storage with: {:?}", COMPONENTS.lock().unwrap());
let mut fields = Vec::new(); ‣Vec<ExprType>
for type_name in COMPONENTS.lock().unwrap().iter() { ‣&String
let field = parse_str::<ExprType>( ‣ExprType
format!("{}s: Vec<{}>", type_name.to_lowercase(), type_name).as_str(),
) ‣Result<ExprType, Error>
.expect("Could not parse component field type");
fields.push(field);
}
let expanded = quote! { ‣TokenStream
#[derive(Serialize, Deserialize, Debug, Default)]
struct Storage {
#(#fields),*
}
};
TokenStream::from(expanded)
}
#[derive(Debug, Serialize, Deserialize, Component)]
struct Health {
health: f32,
}
#[derive(Debug, Serialize, Deserialize, Component)]
pub struct Age {
pub age: u64,
}
storage!();

Capture original payload through serde

I wonder whether there's a way to preserve the original String using serde_json? Consider this example:
#[derive(Debug, Serialize, Deserialize)]
struct User {
#[serde(skip)]
pub raw: String,
pub id: u64,
pub login: String,
}
{
"id": 123,
"login": "johndoe"
}
My structure would end up containing such values:
User {
raw: String::from(r#"{"id": 123,"login": "johndoe"}"#),
id: 1,
login: String::from("johndoe")
}
Currently, I'm doing that by deserializing into Value, then deserializing this value into the User structure and assigning Value to the raw field, but that doesn't seem right, perhaps there's a better way to do so?
This solution uses the RawValue type from serde_json to first get the original input string. Then a new Deserializer is created from that String to deserialize the User type.
This solution can work with readers, by using Box<serde_json::value::RawValue> as an intermediary type and it can also work with struct which borrow from the input, by using &'de serde_json::value::RawValue as the intermediary. You can test it in the solution by (un-)commenting the borrow field.
use std::marker::PhantomData;
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(remote = "Self")]
struct User<'a> {
#[serde(skip)]
pub raw: String,
pub id: u64,
pub login: String,
// Test for borrowing input data
// pub borrow: &'a str,
#[serde(skip)]
pub ignored: PhantomData<&'a ()>,
}
impl serde::Serialize for User<'_> {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
Self::serialize(self, serializer)
}
}
impl<'a, 'de> serde::Deserialize<'de> for User<'a>
where
'de: 'a,
{
fn deserialize<D: serde::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
use serde::de::Error;
// Deserializing a `&'a RawValue` would also work here
// but then you loose support for deserializing from readers
let raw: Box<serde_json::value::RawValue> = Box::deserialize(deserializer)?;
// Use this line instead if you have a struct which borrows from the input
// let raw = <&'de serde_json::value::RawValue>::deserialize(deserializer)?;
let mut raw_value_deserializer = serde_json::Deserializer::from_str(raw.get());
let mut user =
User::deserialize(&mut raw_value_deserializer).map_err(|err| D::Error::custom(err))?;
user.raw = raw.get().to_string();
Ok(user)
}
}
fn main() {
// Test serialization
let u = User {
raw: String::new(),
id: 456,
login: "USERNAME".to_string(),
// Test for borrowing input data
// borrow: "foobar",
ignored: PhantomData,
};
let json = serde_json::to_string(&u).unwrap();
println!("{}", json);
// Test deserialization
let u2: User = serde_json::from_str(&json).unwrap();
println!("{:#?}", u2);
}
Test on the Playground.

RUST find value in web::Data<Arc<>>

my "main" file
mod router;
mod student;
use std::sync::Arc;
use crate::router::init_router;
use crate::router::Memory;
use actix_web::{App, HttpServer};
#[actix_web::main]
async fn main() -> std::io::Result<()> {
dotenv::dotenv().ok();
let repo = Arc::new(Memory::repository());
let host = std::env::var("SERVER.HOST").unwrap_or("127.0.0.1".to_string());
let port = std::env::var("SERVER.PORT").unwrap_or("8080".to_string());
let url = format!("{}:{}", host, port);
println!("url: {}", &url);
HttpServer::new(move || {
App::new()
.data(repo.clone()) // shared
.configure(init_router)
})
.bind(&url)?
.run()
.await
}
my file: "router.rs"
use std::sync::Arc;
use crate::student::Student;
use actix_web::{get, web, HttpResponse, Responder};
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Memory {
pub students: Vec<Student>,
}
impl Memory {
fn new() -> Self {
Memory {
students: Vec::new(),
}
}
pub fn repository() -> Self{
Self {
students: vec![
{Student::new("1".to_string(), "Daniel".to_string(), 19)},
{Student::new("2".to_string(), "Lucia".to_string(), 17)},
{Student::new("3".to_string(), "Juan".to_string(), 14)}
]
}
}
}
#[get("/student/list/all")]
async fn list_all(repo: web::Data<Arc<Memory>>) -> impl Responder {
HttpResponse::Ok().json(&***repo)
}
#[get("/student/list/by-id/{id_student}")]
async fn list_by_id(web::Path(id_student): web::Path<String>, repo: web::Data<Arc<Memory>>) -> impl Responder {
HttpResponse::Ok().json(&***repo.students.into_iter().find(|x| *x.id == id_student))
}
pub fn init_router(config: &mut web::ServiceConfig) {
config.service(list_all);
config.service(list_by_id);
}
and my file: "student.rs"
use serde::{Serialize, Deserialize};
#[derive(Serialize, Deserialize)]
pub struct Student{
pub id: String,
pub nombre: String,
pub calificacion: u32,
}
impl Student{
pub fn new(id: String, nombre: String, calificacion: u32) -> Self{
Self{id, nombre, calificacion}
}
}
I want to show a student in the following path: 127.0.0.1:3000/student/list/by-id/1
but i have the following error
error[E0614]: type `std::vec::IntoIter<Student>` cannot be dereferenced
--> src\router.rs:43:33
|
43 | HttpResponse::Ok().json((&***repo.lock().unwrap().students.into_iter()).find(|x| *x.id == id_student))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
because I get the error, I don't know what is wrong. Please I need help I am new to this programming language.
The dot operating will smartly dereference the pointer, so the following will compile:
&repo.students.iter().find(|x| *x.id == id_student)
the Arc will be dereferenced when accessing students from repo, which will give a reference to the Vec, and .iter() will give you a non-consuming iterator, which you can then map over (.into_iter() will require the Vec to be copied and consumed)

How to properly solve lifetime inferences in struct?

The Rust playground code is here.
I have a struct of Token which has lifetime 'tok, and a scanner has lifetime 'lexer. I'm using both of them in another struct Parser, then I had a problem:
pub struct Token<'tok> {
pub value: Cow<'tok, str>,
pub line: usize,
}
pub struct Scanner {
pub source: Vec<char>,
pub current: usize,
pub line: usize,
}
pub struct Parser<'lexer> {
pub curr: &'lexer Token<'lexer>,
pub prev: &'lexer Token<'lexer>,
scanner: &'lexer mut Scanner,
}
impl <'lexer> Parser<'lexer> {
pub fn advance(&mut self) {
self.prev = self.curr;
self.curr = &self.scanner.next(); // cannot inference lifetime
}
}
I think the problem is Token has lifetime 'tok, and the borrow checker doesn't know the relation between 'tok and 'lexer so it can't inference proper lifetime.
However, I can avoid the problem by modifying it into the updated code:
pub struct Parser<'lexer> {
pub curr: Token<'lexer>,
pub prev: Token<'lexer>,
scanner: &'lexer mut Scanner,
}
impl <'lexer> Parser<'lexer> {
pub fn advance(&mut self) {
let prev = std::mem::replace(&mut self.curr, self.scanner.next());
self.prev = prev;
}
}
And with Token produced by next() is static:
impl Scanner {
pub fn next(&mut self) -> Token<'static> {
Token {
value: Cow::from(""),
line: 0,
}
}
}
It does compile but I think it's not ideal because all tokens are cloned from scanner into parser(they are not references anymore) and living until end of Parser's life. So memory usage is doubled. Is there a more proper way to deal with this?
Actualy your code structure is not ideal to deal with the borrow checker here why:
Token struct should be owned, the struct itself do not require any allocations (as the token is owned some indrection are required to allow prev <-> next switching)
None of the Parser or Lexer should own the base data so it will be easy to bound proper lifetime
In our case Vec<Char> is not a friendly type to work with (we do not need to own the data and this will be harder to make the comipler understand lifetimes), instead we're going to use an &'str but you could reproduce the exact behaviours with an &[char])
Here is an example that compile just fine
pub struct Token<'source> {
pub value: Cow<'source, str>,
pub line: usize,
}
pub struct Scanner<'source> {
pub source: &'source str,
pub current: usize,
pub line: usize,
}
pub struct Parser<'source> {
pub curr: Option<Token<'source>>,
pub prev: Option<Token<'source>>,
scanner: Scanner<'source>,
}
impl <'source>Scanner<'source> {
pub fn next(&'source /* DONT Forget to bound 'source to `self` */ self) -> Token<'source> {
Token {
value: Cow::from(self.source), /* `self.source` is bound to `'source` so the compiler understand that the token lifetime is the same than the source's one */
line: 0,
}
}
}
impl <'lexer> Parser<'lexer> {
pub fn advance(&'lexer mut self) {
self.prev = self.curr.take();
self.curr = Some(self.scanner.next());
}
}

Mutable Arc in Rust

Earlier I had a Sync + Send trait SyncMessenger:
trait Messenger {
fn send_message(&self, user_id: UserId, text: &str);
}
trait SyncMessenger: Messenger + Sync + Send {}
It's implementation:
pub struct DiscordMessenger {
discord: Arc<Discord>, // (Discord is Sync and Send already)
}
impl Messenger for DiscordMessenger {
fn send_message(&self, user_id: UserId, text: &str) {
self.discord.send_message(user_id, text, false);
}
}
impl SyncMessenger for DiscordMessenger {}
And using it:
struct Bot {
messenger: Arc<SyncMessenger>,
}
impl Bot {
pub fn new() -> Bot {
Bot { messenger: Arc::new(DiscordMessenger::new()) }
}
fn messenger(&self) -> Arc<SyncMessenger> {
self.messenger.clone()
}
}
struct PingCommand {
fn fire(&mut self, bot: &mut Bot) {
bot.messenger().send_message(UserId(0), "Pong");
}
}
Everything worked fine. Now I want to implement TestMessenger which does not really send a message through a network but toggles a flag in Self instead:
#[cfg(test)]
struct TestMessenger {
pub message_sent: bool,
}
impl Messenger for TestMessenger {
fn send_message(&mut self, user_id: UserId, text: &str) { // we have `&mut self` here
self.message_sent = true;
}
}
So I need to change send_message(&self) to send_message(&mut self) everywhere (in traits and in implementations). I did that but after I can't compile my user code:
struct PingCommand {
fn fire(&mut self, bot: &mut Bot) {
bot.messenger().send_message(UserId(0), "Pong");
}
}
Gives error:
|
12 | let _ = bot.messenger().send_message(UserId(0),
| ^^^^^^^^^^^^^^^ cannot borrow as mutable
error: aborting due to previous error
I have found something that works but it looks very ugly to me (and requires unwrap() which I would like to avoid):
let _ = Arc::get_mut(&mut bot.messenger()).unwrap().send_message(UserId(0),
So the question here is how to do that as much simple as possible, without unwrap()s, static methods like Arc::get_mut? Why simple fn messenger(&self) -> Arc<SyncMessenger> is not possible to call mut methods?
You can use interior mutability to change data behind immutable references.
use std::cell::Cell;
struct TestMessenger {
pub message_sent: Cell<bool>,
}
impl Messenger for TestMessenger {
fn send_message(&self, user_id: UserId, text: &str) {
self.message_sent.set(true);
}
}
This struct is for single-treaded case. You'll need std::sync::Mutex instead of Cell to have Sync for TestMessenger.
Note that trait methods implemented should be strictly checked for compliance: send_message(&mut self, user_id: UserId, text: &str) is not compliant with send_message(&self, user_id: UserId, text: &str) due to the former's mutable reference to self, and the compiler would eventually complain.
Therefore, interior mutability is required here, so that state changes may happen behind an immutable reference. In this case, since you're dealing with other thread-safe components, you may consider using the thread-safe AtomicBool.
use std::sync::atomic::AtomicBool;
#[cfg(test)]
struct TestMessenger {
pub message_sent: AtomicBool,
}
impl Messenger for TestMessenger {
fn send_message(&self, user_id: UserId, text: &str) { // we have `&mut self` here
self.message_sent.store(true, Ordering::AcqRel);
}
}

Resources