Get Each Field Attributes Using Darling Crate - rust

Considering this code:
#[derive(MyMacro)]
struct Point {
#[myattr(test1(arg1 = 0, arg2 = 10))]
x: u8,
#[myattr(test2(arg1 = "Hello, World!")]
y: u8,
}
How can I get each field attributes when iterating over fields and map to a struct deriving from darling traits?

Related

How to serialize an option with serde?

I have created a serialize_foo function that can serialize the Foo struct.
struct Foo(i32) <- The Foo struct looks like this.
The Foo struct is used in another struct Bar that looks like this:
struct Bar {
#[serde(serialize_with = "serialize_foo")]
pub x: Foo,
#[serde(serialize_with = "serialize_foo")]
pub y: Option<Foo>
}
The x field can be serialized with the serialize_foo function, but the y field can't. It is because it is an Option.
How should I serialize an Option, should there be a new function serialize_foo_option, but what would the function do if the value is None.
There are multiple ways to solve this problem but this one fits me the best.
I created a new function called serialize_foo_option that looks like the following:
pub fn serialize_foo_option<S>(
maybe_foo: &Option<Foo>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
let mut map = serializer.serialize_map(some_len)?;
if let Some(foo) = maybe_foo {
map.serialize_entry("key", &foo)?;
}
map.end()
}
This way if None is provided nothing is serialized.

type constructor: what does struct b(i32) in rust? [duplicate]

The Rust book mentions that "it is almost always better to use a struct than a tuple struct." Other than the newtype pattern, are there any other advantages of having unnamed fields? Seems to me like the newtype pattern is the only useful case of having tuple structs.
They are very similar to each other.
Given the following definitions
struct TupleStruct(i32, i32);
struct NormalStruct {
a: i32,
b: i32,
}
we can construct instances of structs and tuple structs as follows
let ts = TupleStruct(1, 2);
let ns = NormalStruct { a: 1, b: 2 };
// shortcut to initialize the fields of a struct using the values of the
// fields of another struct
let ns2 = NormalStruct { a: 5, ..ns };
let ts2 = TupleStruct { 0: 1, ..ts }; // for TupleStruct it needs curly brackets
// and implicit field names
Assignments work as follows
let TupleStruct(x, y) = ts;
println!("x: {}, y: {}", x, y);
let NormalStruct { a, b } = ns;
println!("a: {}, b: {}", a, b);
A tuple struct's fields have implicit names (0, 1, ...). Hence, accessing fields is performed as follows
println!("Accessing ns by name - {}{}", ns.a, ns.b);
println!("accessing ts by name - {}{}", ts.0, ts.1);
At least for documentation purposes, it's almost always clearer to assign explicit names to the fields of the struct. That's why in the Rust community I've seen many argue for always using a normal struct.
However, there might be cases where the fields of the struct are inherently "anonymous", one notable case being the "newtype" (tuple struct with one field) where you're only wrapping an inner type.
In that case, naming the inner field does not arguably provide any additional information.
struct Inches {
inner: i32,
}
vs
struct Inches(i32);
The section on structs on the Rust book has more info on newtypes.

How do I load SQLX records to Vec of structs in Rust

I have a table named instruments with the following fields:
id,
instrument_token (integer)
tradingsymbol (nullable string field)
I have defined a Rust struct as below
pub struct Instrument {
pub id: i64,
pub instrument_token: i32,
pub tradingsymbol: Option<String>,
}
I query and create a Vec<Instrument> inside a function as follows using SQLX
let records = sqlx::query!(r"select * from instruments").fetch_all(&app_context.db_connection).await?;
let mut all_instruments: Vec<Instrument> = Vec::new();
for rec in records {
all_instruments.push(Instrument {
id: rec.id,
instrument_token: rec.instrument_token,
tradingsymbol: rec.tradingsymbol,
});
}
Here &app_context.db_connection is &pool instance.
Is this there a better way to load records to a struct using SQLX.
If yes how?
If your record and data type have the same field names and types, you can use query_as! instead:
let records: Vec<Instrument> =
sqlx::query_as!(Instrument, r"select * from instruments")
.fetch_all(&app_context.db_connection)
.await?;

How to deserialize a TOML table containing an array of tables

Take the following TOML data:
[[items]]
foo = 10
bar = 100
[[items]]
foo = 12
bar = 144
And the following rust code:
use serde_derive::Deserialize;
use toml::from_str;
use toml::value::Table;
#[derive(Deserialize)]
struct Item {
foo: String,
bar: String
}
fn main() {
let items_string: &str = "[[items]]\nfoo = 10\nbar = 100\n\n[[items]]\nfoo = 12\nbar = 144\n";
let items_table: Table = from_str(items_string).unwrap();
let items: Vec<Item> = items_table["items"].as_array().unwrap().to_vec();
// Uncomment this line to print the table
// println!("{:?}", items_table);
}
As you can see by yourself, the program does not compile, giving this error in return:
expected struct Item, found enum toml::value::Value
I understand its meaning, but I don't know how I could solve this and achieve what I wanted to do in the first place: cast a child array of a parent table into an array of structs and NOT into an array of tables.
You can parse into the pre-defined TOML types such as Table, but these types don't know about types outside of the pre-defined ones. Those types are mostly used when the actual type of the data is unknown, or unimportant.
In your case that means that the TOML Table type doesn't know about your Item type and cannot be made to know about it.
However you can easily parse into a different type:
use serde_derive::Deserialize;
use std::collections::HashMap;
use toml::from_str;
#[derive(Deserialize, Debug)]
struct Item {
foo: u64,
bar: u64,
}
fn main() {
let items_string: &str = "[[items]]\nfoo = 10\nbar = 100\n\n[[items]]\nfoo = 12\nbar = 144\n";
let items_table: HashMap<String, Vec<Item>> = from_str(items_string).unwrap();
let items: &[Item] = &items_table["items"];
println!("{:?}", items_table);
println!("{:?}", items);
}
(Permalink to the playground)

Is there a feature to put default names in tuples for better code completion and suggestions?

Is there a feature to put default names in tuples for better code completion and suggestions? The names would not be obligatory, just a hint.
Something like:
struct Rect(width: i32, height: i32);
let r: Rect = (1, 2);
let (a, b) = r; // names while destructuring can be anything
There are three ways to define a struct (The book Chapter 5).
Declaring an empty (zero-sized) struct
struct Foo;
Declaring a tuple struct
struct Bar(i32, u32, String);
Declaring a struct with named fields
struct Baz {
first: i32,
second: u32,
third: String,
}
There is no other way.
Destructuring works for all three variants.
let a = Foo;
let Bar(f, s, t) = Bar(3, 5, String::from("Hallo"));
let Baz { first, second, third } = Baz { first: 3, second: 5, third: String::from("Hello") };
(Playground)

Resources