how to define multi parameter with from function in rust - rust

Now I want to map object from Favorites to FavMusicResponse, the Favorites object was selected from database and the FavMusicResponse entity was return to the client. I define the map function like this way in FavMusicResponse:
impl From<&Favorites> for FavMusicResponse {
fn from(f: &Favorites, music: Music) -> Self {
Self{
id: f.id,
song_id: None,
created_time: f.created_time,
updated_time: f.updated_time,
user_id: 0,
source_id: "".to_string(),
like_status: 0,
source: 0,
playlist_id: 0,
play_count: 0,
fetched_download_url: None,
downloaded: None,
music: Default::default()
}
}
}
most of the fields from Favorites fields are the same with FavMusicResponse, the only difference is that music was passed from another entity. This is my FavMusicResponse define:
#[derive( Serialize, Queryable, Deserialize,Default, Clone)]
pub struct FavMusicResponse{
pub id: i64,
pub song_id: Option<i64>,
pub created_time: i64,
pub updated_time: i64,
pub user_id: i64,
pub source_id: String,
pub like_status: i32,
pub source: i32,
pub playlist_id: i64,
pub play_count: i32,
pub fetched_download_url: Option<i32>,
pub downloaded: Option<i32>,
pub music: Music
}
the compiler tell me that from expected 1 parameter, found 2, what should I do do pass 2 or more parameter into the composite function in rust? I invoke the function like this way:
let filtered_music:Vec<_> = musics.iter()
.filter(|item| item.source_id == fav.source_id)
.map(|item|FavMusicResponse::from(fav,item.clone()))
.collect();
I want to passed two entity and composite to the finally FavMusicResponse entity. what should I do to make it work like that? This is my minimal reproduce that could run in rust playground to figure out where is going wrong:
fn main() {
let music = Music{
id: 1
};
let favMusic = Favorites{
id: 1
};
let musicRes = FavMusicResponse::from(favMusic,music);
}
pub struct Music {
pub id: i64
}
pub struct Favorites {
pub id: i64
}
pub struct FavMusicResponse {
pub id: i64,
pub music:Music
}
impl From<Favorites> for FavMusicResponse {
fn from(f: Favorites, music: Music) -> Self {
Self{
id: f.id,
music: music
}
}
}

From trait can't take two parameters only one, it's define that way, the only solution if you really want to use From trait is to transform your two parameter into one, a quick solution is to use a tuple:
impl From<(Favorites, Music)> for FavMusicResponse {
fn from((f, music): (Favorites, Music)) -> Self {
Self {
id: f.id,
music,
}
}
}
// let musicRes = FavMusicResponse::from((favMusic, music));
That said you could also just have a new() method on your type:
impl FavMusicResponse {
fn new(f: Favorites, music: Music) -> Self {
Self {
id: f.id,
music,
}
}
}
// let musicRes = FavMusicResponse::new(favMusic, music);

Related

how to handle the moved exception in a loop in rust

I want to map entity from one Vec(this entity list search from database) into another Vec(this response entity list return to frontend) in rust, this is my code:
fn main() {
let musics:Vec<Music> = Vec::new();
for x in 0..10 {
let filtered_music:Vec<Music> = musics.into_iter()
.filter(|item| item.source_id == "1")
.collect();
let resp = MusicRes{
music: take(filtered_music, 0).unwrap()
};
}
}
fn take<T>(mut vec: Vec<T>, index: usize) -> Option<T> {
if index < vec.len() {
Some(vec.swap_remove(index))
} else {
None
}
}
pub struct Music {
pub id: i64,
pub name: String,
pub artists: String,
pub album_id: i64,
pub publishtime: i64,
pub status: i32,
pub duration: i32,
pub source_id: String,
pub source: i32,
pub created_time: i64,
pub updated_time:i64,
pub album: String,
pub fetched_download_url: i32
}
pub struct MusicRes {
pub music:Music
}
this code give me tips that musics was moved. I could change the musics to &musics, but the returned response need to Music. How to handle this situation properly?
I'm not exactly sure what your requirements are, ie. what's the point of the 0..10 then taking the 0th element, but you could do something like this:
let musics: Vec<_> = musics
.into_iter()
.take(10)
.filter(|m| m.source_id == "1")
.map(|m| MusicRes { music: m })
.collect();

Simplest way to match multiple fields of a struct against `None`

I have a Rust struct like this:
pub struct SomeMapping {
pub id: String,
pub other_id: Option<String>,
pub yet_another_id: Option<String>,
pub very_different_id: Option<String>
}
What is the simplest way to check if all optional ids are not set? I know the syntax like
if let Some(x) = option_value {...}
to extract a value from an Option, but I don't get how to use this in a concise way to check multiple values for None.
You can destructure a structure in pattern matching like so:
pub struct SomeMapping {
pub id: String,
pub other_id: Option<String>,
pub yet_another_id: Option<String>,
pub very_different_id: Option<String>,
}
fn main() {
let x = SomeMapping {
id: "R".to_string(),
other_id: Some("u".to_string()),
yet_another_id: Some("s".to_string()),
very_different_id: Some("t".to_string()),
};
if let SomeMapping {
id: a,
other_id: Some(b),
yet_another_id: Some(c),
very_different_id: Some(d),
} = x {
println!("{} {} {} {}", a, b, c, d);
}
}
It is documented in the Rust book chapter 18.

Why does variable need to continue living after output is consumed?

use std::cell::RefCell;
use std::collections::VecDeque;
// minimum reproducible example for stack overflow question
// which is essentially the whole thing b/c all of these types
// depend on each other
// this is an implementation of Monopoly Deal (see http://monopolydealrules.com/)
// but the only relevant part to the question is in main(), around line 400
// card.rs
pub trait Card {
fn value(&self) -> i32;
fn kind(&self) -> CardKind;
}
pub enum CardKind {
Money,
Action,
Property,
Building,
}
// property.rs
pub struct PropertySet {
color: Color,
properties: Vec<Property>,
house: bool,
hotel: bool,
}
impl PropertySet {
pub fn rent(&self) -> i32 {
unimplemented!() // stub
}
pub fn color(&self) -> Color {
self.color
}
pub fn properties(&self) -> &Vec<Property> {
&self.properties
}
pub fn is_full(&self) -> bool {
self.properties().len() == self.color.set_size() as usize
}
pub fn is_empty(&self) -> bool {
self.properties().len() == 0
}
pub fn add(&mut self, property: Property) -> Result<(), PropertySetAddError> {
if !property.matches(self.color) {
return Err(PropertySetAddError {
property,
kind: PropertySetAddErrorKind::WrongColor,
});
}
if self.properties.len() + 1 < self.color.set_size() as usize {
self.properties.push(property);
Ok(())
} else {
Err(PropertySetAddError {
property,
kind: PropertySetAddErrorKind::SetFull,
})
}
}
fn remove(&mut self, index: usize) -> Property {
self.properties.remove(index)
}
}
pub struct PropertySetAddError {
property: Property,
kind: PropertySetAddErrorKind,
}
pub enum PropertySetAddErrorKind {
WrongColor,
SetFull,
}
pub enum Property {
Basic { name: String, color: Color },
Wild { colors: [Color; 2], value: i32 },
Any,
}
impl Card for Property {
fn value(&self) -> i32 {
unimplemented!() // stub
}
fn kind(&self) -> CardKind {
CardKind::Property
}
}
impl Property {
pub fn matches(&self, color: Color) -> bool {
unimplemented!() // stub
}
}
#[derive(Eq, PartialEq, Hash, Copy, Clone)]
pub enum Color {
Red,
Orange,
Yellow,
Green,
LightBlue,
DarkBlue,
Magenta,
Brown,
Utility,
Railroad,
}
impl Color {
pub fn set_size(&self) -> i32 {
unimplemented!() // stub
}
}
// money.rs
#[derive(PartialOrd, Ord, PartialEq, Eq, Hash)]
pub struct Money(pub i32);
impl Card for Money {
fn value(&self) -> i32 {
self.0
}
fn kind(&self) -> CardKind {
CardKind::Money
}
}
#[derive(Copy, Clone, Hash, Eq, PartialEq)]
pub struct Id(pub usize);
pub struct Possessions {
bank: Vec<Money>,
hand: Vec<Box<dyn Card>>,
properties: Vec<PropertySet>,
}
// brain.rs
pub trait Brain {
fn act(&self, state: &GameState, possessions: &mut Possessions) -> Vec<Effect>;
fn react(
&self,
state: &GameState,
possessions: &mut Possessions,
effect: &Effect,
) -> Vec<Effect>;
}
pub struct Human {}
impl Human {
pub fn new() -> Human {
Human {}
}
}
impl Brain for Human {
fn act(&self, state: &GameState, possessions: &mut Possessions) -> Vec<Effect> {
unimplemented!()
}
fn react(
&self,
state: &GameState,
possessions: &mut Possessions,
effect: &Effect,
) -> Vec<Effect> {
unimplemented!()
}
}
// action.rs
pub enum Action {
Rent { colors: [Color; 2] },
AnyRent,
DoubleRent,
DealBreaker,
DebtCollector,
Birthday,
SayNo,
PassGo,
SlyDeal,
ForcedDeal,
}
impl Card for Action {
fn value(&self) -> i32 {
unimplemented!() // stub
}
fn kind(&self) -> CardKind {
CardKind::Action
}
}
impl Action {
pub fn effect<'a>(
&self,
source: Id,
target: ActionTarget<'a>,
) -> Result<Effect<'a>, EffectError> {
unimplemented!() // stub
}
}
pub enum ActionTarget<'a> {
None,
Player {
player: Id,
},
Set {
/// The player that this action is targeted against
player: Id,
/// Can be a set that player owns, such as in the case of Deal Breaker, or it
/// can be a set that the source owns, such as in the case of rent cards
set: &'a PropertySet,
},
Property {
player: Id,
property: (&'a PropertySet, usize),
},
Swap {
player: Id,
take: (&'a PropertySet, usize),
give: (&'a PropertySet, usize),
},
}
// effect.rs
#[derive(Clone)]
pub enum Effect<'a> {
// swaps properties with another player
Swap {
source: Id,
target: Id,
give: (&'a PropertySet, usize),
take: (&'a PropertySet, usize),
},
// steals properties from another player
Steal {
source: Id,
target: Id,
set: &'a PropertySet,
indices: Vec<usize>,
},
// charges another player
Charge {
source: Id,
target: Option<Id>,
amount: i32,
reason: ChargeReason,
},
// cancels prior effect
Cancel {
source: Id,
target: Id,
},
// pass Go, credit $2M
Go {
source: Id,
},
}
#[derive(Clone)]
pub enum ChargeReason {
Rent,
Birthday,
DebtCollector,
}
pub enum EffectError {
/// The target supplied was not valid for this action.
InvalidTarget,
/// You tried to charge rent for a color, but the specified set isn't that color
NoProperty,
}
// player.rs
pub struct Player {
pub id: Id,
pub name: String,
pub possessions: Possessions,
pub brain: Box<dyn Brain>,
}
impl Player {
pub fn new(id: Id, name: String, brain: Box<dyn Brain>) -> Player {
Player {
id,
possessions: Possessions {
bank: vec![],
hand: vec![],
properties: vec![],
},
name,
brain,
}
}
pub fn id(&self) -> Id {
self.id
}
pub fn bank(&self) -> &Vec<Money> {
&self.possessions.bank
}
pub fn properties(&self) -> &Vec<PropertySet> {
&self.possessions.properties
}
pub fn name(&self) -> &str {
&self.name
}
pub fn brain(&self) -> &Box<dyn Brain> {
&self.brain
}
pub fn act(&mut self, state: &GameState) -> Vec<Effect> {
self.brain.act(state, &mut self.possessions)
}
pub fn react(&mut self, state: &GameState, effect: &Effect) -> Vec<Effect> {
self.brain.react(state, &mut self.possessions, effect)
}
}
// state.rs
pub struct GameState {
pub players: Vec<RefCell<Player>>,
pub current: Id,
pub stack: Vec<Box<dyn Card>>,
}
impl GameState {
pub fn next(&mut self) {
self.current = Id((self.current.0 + 1) % self.players.len())
}
pub fn current_player(&self) -> &RefCell<Player> {
self.players.get(self.current.0).unwrap()
}
pub fn get_player(&self, id: Id) -> Option<&RefCell<Player>> {
self.players.get(id.0)
}
}
// deck.rs
pub fn create_deck() -> Vec<Box<dyn Card>> {
vec![
// ...
]
}
// main.rs
pub fn main() {
let brain = Human::new(); // Human implements Brain
let me = Player::new(Id(0), "Ibi".to_owned(), Box::new(brain));
let current = me.id();
let players = vec![RefCell::new(me)];
let stack = create_deck(); // returns Vec<Box<dyn Card>>
let mut state = GameState {
players,
stack,
current,
};
while !state.players.iter().any(|player| {
player
.borrow()
.properties()
.iter()
.filter(|&set| set.is_full())
.count()
>= 3
}) {
// ...
let mut effects = VecDeque::new();
{
let mut current_player = state.current_player().borrow_mut();
let action = current_player.act(&state);
effects.extend(action);
}
// let all other players react to effects until no more reactions are generated
while !effects.is_empty() {
let effect = effects.pop_front().unwrap();
// ...
}
}
}
I can't get this code to compile; it says that current_player does not live long enough and complains that it is dropped at the end of the block. Why does current_player need to survive beyond the end of the block? My understanding is that it returns a Vec<Effect> which my method now owns, and then that vector is consumed by extend() and the values it contained are now owned by effects, so why is current_player still necessary?

Use trait as interface for database entity

I am trying to make an Entity interface for dynamically mapping a database result into a Rust struct:
pub trait Entity {
fn map(&self, Result<QueryResult>) -> Self;
}
pub struct DbQuery<T> {
pub sql: String,
pub params: Vec<Value>,
pub limit: i32,
pub paged: Option<Pagination>,
pub entity: T,
}
pub struct Settings {
pub name: String,
pub value: Option<String>,
}
impl Entity for Settings {
fn map(&self, result: Result<QueryResult>) -> Settings {
// ...
Settings {
name: "hello".to_string(),
value: None,
}
}
}
impl DbMapper {
// ...
pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> {
println!("query find SQL: {}", query.sql);
let mut stmt = &self.pool.prepare(query.sql).unwrap();
let ret = Vec::new();
for row in stmt.execute(query.params).unwrap() {
ret.push(query.entity.map(row.unwrap()));
}
Some(ret)
}
}
But I get an error:
error: no method named map found for type T in the current scope
ret.push(query.entity.map(row.unwrap())); |
note: the method map exists but the following trait
bounds were not satisfied: T : std::iter::Iterator = help: items
from traits can only be used if the trait is implemented and in scope;
the following traits define an item map, perhaps you need to
implement one of them: = help: candidate #1:
models::holders::database::Entity = help: candidate #2:
std::iter::Iterator
Here is a version of your code that runs on the playground and replicates your issue:
pub struct QueryResult;
pub struct Value;
pub struct Pagination;
pub struct DbMapper;
pub trait Entity {
fn map(&self, Result<QueryResult, ()>) -> Self;
}
pub struct DbQuery<T> {
pub sql: String,
pub params: Vec<Value>,
pub limit: i32,
pub paged: Option<Pagination>,
pub entity: T,
}
pub struct Settings {
pub name: String,
pub value: Option<String>,
}
impl Entity for Settings {
fn map(&self, result: Result<QueryResult, ()>) -> Settings {
// ...
Settings {
name: "hello".to_string(),
value: None,
}
}
}
impl DbMapper {
// ...
pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>> {
println!("query find SQL: {}", query.sql);
// ########## attempt to call map()
let _ = query.entity.map(Ok(QueryResult {}));
let ret = Vec::new();
Some(ret)
}
}
fn main() {}
The problem is that T in the DbQuery<T> argument in the find method has no idea that T is an Entity type. So we need to tell it:
pub fn find<T>(&self, query: DbQuery<T>) -> Option<Vec<T>>
where T: Entity
{
// ... code here ...
}
This now compiles and runs.
The compiler now knows that T is an Entity of some description, and it can call the map method on it.

Derive attribute for specific fields only, like serde does

Using derive syntax, can I implement traits like Hash or PartialEq using specific fields, not all of them?
It could look like:
#[derive(Debug, Hash, Eq, PartialEq)]
struct MyStruct {
id: i32,
name: String,
#[derive(hash_skip, eq_skip)]
aux_data1: f64,
#[derive(hash_skip, eq_skip)]
aux_data2: f64,
#[derive(hash_skip, eq_skip)]
aux_data3: String,
}
I want the hash method to only use id, and name and no others.
The serde library allows something like this for serialization.
No, there is no such feature in Rust at this moment. What I would suggest is to use the implementation for tuples available for these traits, like this:
use std::hash::{Hash, Hasher};
#[derive(Debug)]
struct MyStruct {
id: i32,
name: String,
aux_data1: f64,
aux_data2: f64,
aux_data3: String,
}
impl Hash for MyStruct {
fn hash<H>(&self, state: &mut H) where H: Hasher {
(&self.id, &self.name).hash(state);
}
}
impl PartialEq for MyStruct {
fn eq(&self, other: &Self) -> bool {
(&self.id, &self.name) == (&other.id, &other.name)
}
}
Edit: or as #Shepmaster suggested in a comment below, you can create a key function which returns a tuple of all useful fields and use it.
impl MyStruct {
fn key(&self) -> (&i32, &String) {
(&self.id, &self.name)
}
}
impl Hash for MyStruct {
fn hash<H>(&self, state: &mut H) where H: Hasher {
self.key().hash(state);
}
}
impl PartialEq for MyStruct {
fn eq(&self, other: &Self) -> bool {
self.key() == other.key()
}
}
This is possible by using derivative.
Example:
use derivative::Derivative;
#[derive(Derivative)]
#[derivative(Hash, PartialEq)]
struct Foo {
foo: u8,
#[derivative(Hash="ignore")]
#[derivative(PartialEq="ignore")]
bar: u8,
}

Resources