the trait `PartialEq<Option<_>>` is not implemented - rust

I have a struct where I've derived a couple of things.
#[derive(PartialEq, Debug)]
struct Subscriber {
id: u16,
up_speed: u32,
down_speed: u32
}
However, when I try to use PartialEq, I get told it is not implemented.
for (id, subscriber) in &new_hashmap {
let original_subscriber = original_hashmap.get(id).unwrap();
if original_subscriber == None {
changed_hashmap.insert(subscriber.id, subscriber);
} else if subscriber != original_subscriber {
changed_hashmap.insert(subscriber.id, subscriber);
}
}
Here's the compiler error.
error[E0277]: can't compare `&Subscriber` with `Option<_>`
--> src/main.rs:34:32
|
34 | if original_subscriber == None {
| ^^ no implementation for `&Subscriber == Option<_>`
|
= help: the trait `PartialEq<Option<_>>` is not implemented for `&Subscriber`
= help: the trait `PartialEq` is implemented for `Subscriber`
If I rewrite it to not put original_subscriber into its own variable, then it works.
for (id, subscriber) in &new_hashmap {
if original_hashmap.get(id) == None {
changed_hashmap.insert(subscriber.id, subscriber);
} else if subscriber != original_hashmap.get(id).unwrap() {
changed_hashmap.insert(subscriber.id, subscriber);
}
}
The rest of the code is essentially doing the following.
Create HashMap of 2 Subscriber instances.
Create another HashMap of 3 Subscriber instances, 1 of which is new, 1 of which is the same, and 1 of which has the same key but an updated value.
That is original_hashmap HashMap and new_hashmap.
The goal is to get a third HashMap of items in new_hashmap that are new to original_hashmap or have changed values.

your code does not work for 2 reasons.
If you derive PartialEq it will only work for Subscriber == Subscriber checks. You need to implement PartialEq<Type>
You are using a reference when comparing. This means you need to implement PartialEq for &Subscriber and not subscriber
This should do the trick
#[derive(PartialEq, Debug)]
struct Subscriber {
id: u16,
up_speed: u32,
down_speed: u32,
}
let subscriber = Subscriber {
id: 1,
up_speed: 100,
down_speed: 100,
};
impl PartialEq<Option<Subscriber>> for &Subscriber {
fn eq(&self, other: &Option<Subscriber>) -> bool {
match other {
Some(other) => return other == *self,
None => return false,
}
}
}
if &subscriber == None {
println!("None");
} else {
println!("Some");
}
But I am not sure if this is really what you want. I will try to implement the same and edit my answer afterwards
I suppose that's what you want to implement
use std::collections::HashMap;
#[derive(Debug, PartialEq)]
struct Subscriber {
id: u16,
up_speed: u32,
down_speed: u32,
}
impl Subscriber {
fn new(id: u16, up_speed: u32, down_speed: u32) -> Subscriber {
Subscriber {
id,
up_speed,
down_speed,
}
}
}
fn main() {
let mut old_map = HashMap::new();
old_map.insert(1, Subscriber::new(1, 1, 1));
old_map.insert(2, Subscriber::new(2, 2, 2));
let mut new_map = HashMap::new();
new_map.insert(0, Subscriber::new(0, 0, 0)); //new
new_map.insert(1, Subscriber::new(1, 1, 1)); //Same
new_map.insert(2, Subscriber::new(3, 3, 3)); //Same key but different value
let mut changed_map = HashMap::new();
//
for (key, subscriber) in &new_map {
if old_map.contains_key(&key) {
if old_map[&key] != *subscriber {
changed_map.insert(key, subscriber);
}
} else {
changed_map.insert(key, subscriber);
}
}
println!("{:?}", changed_map);
}
It will return
{2: Subscriber { id: 3, up_speed: 3, down_speed: 3 }, 0: Subscriber { id: 0, up_speed: 0, down_speed: 0 }}
I used the deref operator to avoid impl PartialEq<Subscriber> for &Subscriber but you could have done that as well

Related

What is the alternative of downcasting a trait object in this situation?

I have a Companion trait that encompasses a base trait for Components such as Health. I store a list of Companion using trait objects because all companions must at least implement the Companion trait. However not all companions will use the subtype Health trait.
Now the heal command only accepts a list of Health traits, so I need to filter out, remap and downcast all the base Companion traits so that it supports the Health traits.
I understand this is bad design. How can I implement the same behavior without having to downcast the trait objects to a specific component? Note: I cannot have a large struct which includes all the subtypes into one type.
Here's the code I have so far:
type CompanionId = Uuid;
fn main() {
let mut companion_storage: HashMap<CompanionId, Box<dyn Companion>> = HashMap::new();
let companion_id: CompanionId = Uuid::new_v4();
companion_storage.insert(
companion_id,
Box::new(Cheetah {
...
}),
);
let mut player = Player {
...,
companions: Vec::new(),
};
player.companions.push(companion_id);
'GameLoop: loop {
let input = poll_input().trim().to_lowercase();
match input.as_str() {
// TODO: Extract healing component here.
"heal" => heal_command(companion_id, companion_storage.into_iter().filter(|(companion_id, companion)| {
// QUESTION: How do I filter out Companions without the Health trait here so they can automatically be downcasted and mapped?
}).collect()),
"q" => {
break 'GameLoop;
}
"s" => {
status_command(&player, &companion_storage); // SAME PROBLEM HERE
}
_ => println!("Unknown command"),
}
}
}
struct Player {
id: u8,
name: String,
companions: Vec<CompanionId>,
}
trait Companion {
...
}
trait Health: Companion {
...
}
trait Status: Health {}
struct Cheetah {
id: CompanionId,
name: String,
current_health: f32,
max_health: f32,
}
impl Companion for Cheetah {
...
}
impl Health for Cheetah {
...
}
fn heal_command(
companion_id: CompanionId,
companion_storage: &mut HashMap<CompanionId, Box<dyn Health>>,
) {
let companion = companion_storage.get_mut(&companion_id).unwrap();
companion.heal_max();
println!("Healed to max.");
}
fn status_command(player: &Player, companion_storage: &mut HashMap<CompanionId, Box<dyn Status>>) {
println!("Status for {}: ", player.name);
println!("===============================");
print!("Companions: ");
for companion_id in &player.companions {
let companion = companion_storage.get(companion_id).unwrap();
print!(
"{} [{}/{}], ",
companion.name(),
companion.health(),
companion.max_health()
);
}
println!();
println!("===============================");
}
Is this code a better alternative?
type CompanionId = Uuid;
fn main() {
let mut companion_storage: HashMap<CompanionId, Companion> = HashMap::new();
let companion_id: CompanionId = Uuid::new_v4();
companion_storage.insert(
companion_id,
Companion {
id: companion_id,
name: "Cheetah".to_string(),
health: Some(Box::new(RegularHealth {
current_health: 50.0,
max_health: 50.0,
})),
},
);
let mut player = Player {
id: 0,
name: "FyiaR".to_string(),
companions: Vec::new(),
};
player.companions.push(companion_id);
'GameLoop: loop {
let input = poll_input().trim().to_lowercase();
match input.as_str() {
// TODO: Extract healing component here.
"heal" => {
let companion = companion_storage.get_mut(&companion_id).unwrap();
match companion.health_mut() {
None => {
println!("The selected companion doesn't have health associated with it.");
}
Some(health) => {
heal_command(health);
println!("{} was healed to max.", companion.name);
}
}
}
"q" => {
break 'GameLoop;
}
"s" => {
status_command(&player, &companion_storage); // SAME PROBLEM HERE
}
_ => println!("Unknown command"),
}
}
}
struct Player {
id: u8,
name: String,
companions: Vec<CompanionId>,
}
struct Companion {
id: CompanionId,
name: String,
health: Option<Box<dyn Health>>,
}
struct RegularHealth {
current_health: f32,
max_health: f32,
}
trait Health {
...
}
impl Companion {
fn health_mut(&mut self) -> Option<&mut dyn Health> {
match self.health.as_mut() {
None => None,
Some(health) => Some(health.as_mut()),
}
}
fn health(&self) -> Option<&dyn Health> {
match self.health.as_ref() {
None => None,
Some(health) => Some(health.as_ref()),
}
}
}
impl Health for RegularHealth {
...
}
fn heal_command(health: &mut dyn Health) {
health.heal_max();
}
fn status_command(player: &Player, companion_storage: &HashMap<CompanionId, Companion>) {
println!("Status for {}: ", player.name);
println!("===============================");
print!("Companions: ");
for companion_id in &player.companions {
let companion = companion_storage.get(companion_id).unwrap();
match companion.health.as_ref() {
None => {}
Some(health) => {
print!(
"{} [{}/{}], ",
companion.name,
health.health(),
health.max_health()
);
}
}
}
println!();
println!("===============================");
}

How to iterate through FnvHashMap in Rust

I have two FnvHashMap which is declared like first: FnvHashMap<(i32, i32), Employee>
second: FnvHashMap<(i32, i32), Employee>
Where Employee is
pub struct Employee {
pub emp_id: i32,
pub lang_id: i32,
pub dept_id: f64,
pub description: String,
}
I need to iterate through 'first' FnvHashMap and see if there is a matching record(emp_id and lang_id) in 'second' FnvHashMap
I may not need to consider dept_id and description
Thanks in Advance.
New code after implementing nested loop
for (_, employee1) in &first {
for (_, employee2) in &second {
if employee1.emp_id == employee2.emp_id && employee1.lang_id == employee2.lang_id {
values.push(OldNew {
old: employee2,
new: employee1,
});
}
}
}
let new = first
.into_iter()
.filter(|(a, _)| !old.contains_key(a))
.map(|(_, a)| a)
.collect();
let deleted = second
.iter()
.filter(|(a, _)| !new.contains_key(a))
.map(|(&a, _)| a)
.collect();
Changes {
deleted,
new,
values,
}
pub struct Changes<T, I> {
pub deleted: Vec<I>,
pub new: Vec<T>,
pub values: Vec<OldNew<T>>,
}
expected struct `organization::models::employee_stat::Employee`, found `&organization::models::employee_stat::Employee`
Simply make two nested for loops to iterate through both maps and then compare the values you need from the two iterations of the loops, for example
for (_, employee1) in &first {
for (_, employee2) in &second {
if employee1.emp_id == employee2.emp_id && employee1.lang_id == employee2.lang_id {
/* Code here to run if a matching value is found */
}
}
}

Rust first step, how to create a Option<Box<T>> from &mut self?

I'm learning Rust for a few days and honestly some concepts are really difficult to understand and apply. I started to rewrite a small part of a component in order to compare the legendary speed of Rust and learn by a concrete project. It's a component to measure time and monitor the program during the execution. It will be a dynamic library used by another program.
My question :
1) How to create an Option<Box<T>> from &mut self ? (fn add_son)
extern crate winapi;
extern crate user32;
extern crate kernel32;
struct KpiMethod{
element : String,
line : u32,
nb_occ : u32,
counter_start : i64,
counter_end : i64,
total_time: i64,
kpi_fils : Vec<KpiMethod>,
kpi_father : Option<Box<KpiMethod>>
}
impl KpiMethod {
pub fn new(_element: String, _line: u32, _father: Option<Box<KpiMethod>>) -> KpiMethod {
KpiMethod{
element : _element,
line : _line,
nb_occ : 1,
counter_start : get_counter(),
counter_end : 0,
total_time: 0,
kpi_fils : Vec::new(),
kpi_father : _father
}
}
pub fn add_son(&mut self, _element: String, _line: u32) -> KpiMethod{
//How create a Option<Box<KpiMethod>> of an existing KpiMethod (self) ?
let mut kpimet = KpiMethod::new(_element, _line, Some(Box::new(self)));
//Do I need a mutable self to push ?
self.kpi_fils.push(kpimet);
kpimet
}
pub fn find_son(&mut self, _element: String, _line: u32) -> Option<&KpiMethod> {
//which is the good and speed method to find a son with key (element,line) ?
for elem in self.kpi_fils.iter_mut() {
if elem.element == _element && elem.line == _line {
//why do I put a return here to fix error ?
return Some(elem)
}
}
None
}
}
pub struct KpiAgent{
kpi_Method : Vec<KpiMethod>,
current_Method : Option<Box<KpiMethod>>,
counter_start : i64,
counter_end : i64,
date_start : String,
date_end : String,
auto_consommation : u64,
}
impl KpiAgent {
pub fn new() -> KpiAgent {
KpiAgent{
kpi_Method: Vec::new(),
current_Method: None,
counter_start: 0,
counter_end: 0,
date_start: String::from(""),
date_end: String::from(""),
auto_consommation: 0
}
}
pub fn method_start(&mut self, element: String, line: u32){
match self.current_Method {
None => {
self.current_Method = Some(Box::new(KpiMethod::new(element, line, None)));
if self.counter_start == 0 {
self.counter_start = get_counter();
}
},
Some(method) => {
let metfils = method.find_son(element, line);
match metfils {
None => {
self.current_Method = Some(Box::new(method.add_son(element, line)));
},
Some(son) => {
son.nb_occ += 1;
son.counter_start = get_counter();
}
}
},
}
}
pub fn method_end(&mut self, element: String, line: u32){
match self.current_Method{
Some(met) => {
met.counter_end = get_counter();
self.counter_end = met.counter_end;
met.total_time += met.counter_end - met.counter_start;
self.current_Method = met.kpi_father;
}
}
}
}
pub fn get_counter() -> i64 {
let mut counter: i64 = 0;
unsafe{
kernel32::QueryPerformanceCounter(&mut counter);
}
counter
}
pub fn main() {
let mut met = KpiMethod::new("1c".to_string(), 1, None);
met.add_son("2c".to_string(),2);
met.add_son("3c".to_string(),3);
met.add_son("4c".to_string(),4);
let _toto = met.find_son("3c".to_string(),3);
match _toto{
None => println!("Not found"),
Some(x) => println!("{}",x.element),
}
let mut agent = KpiAgent::new();
agent.method_start("test".to_string(),2);
agent.method_end("test".to_string(),10);
}

How to do error handling of nested `.iter()`s?

I am trying to do error handling when using .iter() in combination with .flat_map, which has an .iter().map() within it.
The scenario is getting all the Events that belong to a set of organisations, where the nested .iter().map() is used to get the participants of each event, combine that with the event and return an EventResponse stuct.
A non-specific-scenario way of describing the issue would be 'How to get Result<Vec<T>, err> from nested flat_map of Result<Vec<T>, err>, which has nested map of Result<T, err>'
Below is an abstracted/simplified version of the code I'm using, that gives me the same errors as my actual code.
struct Event {
id: usize,
}
#[derive(Debug)]
struct EventResponse {
id: usize,
participants: Vec<i32>,
}
fn main() {
let orgs = vec![1, 3, 14, 12];
let events: Result<Vec<EventResponse>, &str> = orgs
.iter()
.flat_map::<Result<Vec<EventResponse>, &str>, _>(|org_id| {
get_events_for(*org_id)
.map_err(|_| "That Org id does not exist")
.map(|events| {
events
.iter()
.map::<Result<EventResponse, &str>, _>(|event| {
get_event_with_participants(event)
.map(|event_response| event_response)
.map_err(|_| "Participants for that event were not found")
})
.collect()
})
})
.collect();
}
fn get_events_for(id: usize) -> Result<Vec<Event>, ()> {
// pretend we are checking against a database of existing org ids, if the org id does not exist, then return an error
if id == 3 {
Ok(vec![Event { id }])
} else {
Err(())
}
}
fn get_event_with_participants(event: &Event) -> Result<EventResponse, ()> {
//pretend the participants are fetched from a database
let foundParticipants = true;
if foundParticipants {
Ok(EventResponse {
id: event.id,
participants: vec![1, 2, 5],
})
} else {
Err(())
}
}
Playground
The type annotations are to show what is expected to be returned at each stage. I expect events to be of type Result<Vec<EventResponse>, &str> but I am getting 2 errors:
error[E0277]: a collection of type `std::vec::Vec<EventResponse>` cannot be built from an iterator over elements of type `std::result::Result<EventResponse, &str>`
--> example.rs:27:26
|
27 | .collect()
| ^^^^^^^ a collection of type `std::vec::Vec<EventResponse>` cannot be built from `std::iter::Iterator<Item=std::result::Result<EventResponse, &str>>`
|
= help: the trait `std::iter::FromIterator<std::result::Result<EventResponse, &str>>` is not implemented for `std::vec::Vec<EventResponse>`
error[E0277]: a collection of type `std::result::Result<std::vec::Vec<EventResponse>, &str>` cannot be built from an iterator over elements of type `std::vec::Vec<EventResponse>`
--> example.rs:30:10
|
30 | .collect();
| ^^^^^^^ a collection of type `std::result::Result<std::vec::Vec<EventResponse>, &str>` cannot be built from `std::iter::Iterator<Item=std::vec::Vec<EventResponse>>`
|
= help: the trait `std::iter::FromIterator<std::vec::Vec<EventResponse>>` is not implemented for `std::result::Result<std::vec::Vec<EventResponse>, &str>`
EDIT: The get_events_for function cannot be modified, however, the get_event_with_participants function can be modified, if that helps.
Being interested in the problem, I tried to implement this with map and try_fold. Using flat_map directly didn't work for me, as I couldn't get around the fact that the first inner loop has to produce a Result. I moved the error messages into the functions, but that could easily be undone if you explicitly wanted to avoid it.
struct Event {
id: usize,
}
#[derive(Debug)]
struct EventResponse {
id: usize,
participants: Vec<i32>,
}
fn main() {
let orgs = vec![1, 3, 14, 12];
let events: Result<Vec<EventResponse>, &str> = orgs
.iter()
.map(|org_id| {
get_events_for(*org_id)?
.iter()
.map(get_event_with_participants)
.collect::<Result<Vec<_>, _>>()
})
.collect::<Result<Vec<_>, _>>()
.map(|org_responses| org_responses.into_iter().flatten().collect());
}
fn get_events_for(id: usize) -> Result<Vec<Event>, &'static str> {
// pretend we are checking against a database of existing org ids, if the org id does not exist, then return an error
if id == 3 {
Ok(vec![Event { id }])
} else {
Err("That Org id does not exist")
}
}
fn get_event_with_participants(event: &Event) -> Result<EventResponse, &'static str> {
//pretend the participants are fetched from a database
let foundParticipants = true;
if foundParticipants {
Ok(EventResponse {
id: event.id,
participants: vec![1, 2, 5],
})
} else {
Err("Participants for that event were not found")
}
}
For try_fold, the main function would become:
fn main() {
let orgs = vec![1, 3, 14, 12];
let events: Result<Vec<EventResponse>, &str> =
orgs.iter().try_fold(Vec::new(), |mut responses, &org| {
responses = get_events_for(org)?
.into_iter()
.try_fold(responses, |mut responses, event| {
let response = get_event_with_participants(&event)?;
responses.push(response);
Ok(responses)
})?;
Ok(responses)
});
}
Personally I'm a fan of the map version, as modifying a Vec using try_fold feels awkward since you have to return the accumulator despite modifying the Vec directly.
Another version to consider is to just use loops, which appears to be far simpler in this situation since you can use the ? operator for errors:
fn main() {
let orgs = vec![1, 3, 14, 12];
let events = get_all_responses(orgs);
}
fn get_all_responses(
orgs: impl IntoIterator<Item = usize>,
) -> Result<Vec<EventResponse>, &'static str> {
let mut responses = Vec::new();
for org in orgs.into_iter() {
for event in get_events_for(org)? {
responses.push(get_event_with_participants(&event)?)
}
}
Ok(responses)
}

How to ensure my function will receive a Vec of valid length?

Is it possible to specify that a function's Vec argument has a certain length? Consider the possible values of a dice:
fn new(d_type: DiceType, face_vals: /*Vec<u32> with len() == 2/4/6/8/10/12/20*/) -> Dice {...}
I am writing something that lets you create a polyhedral dice (usual RPG sizes: 2, 4, 6, etc.) with specified face values. I remember that when you call a Rust function without the unsafe keyword the users should be able to call it however they like without fear of failure so simply checking for validity in the function and returning some "you messed up" error is bad Rust.
How can I achieve this?
This is a part of the code I am working on:
pub enum DiceType {
D2,
D4,
D6,
D8,
D10,
D10P,
D12,
D20,
}
pub struct Dice {
dice_type: DiceType,
face_count: usize,
face_values: Vec<u32>,
}
impl Dice {
pub fn new(d_type: DiceType, face_vals: Vec<u32>) -> Dice {
let mut retval;
//Reject if not a valid dice type 2, 4, 6, 8, 10, 12, or 20
//I really shouldn't be doing this should I?
if Dice::valid_dice(d_type, face_vals) {
retval = Dice {
dice_type: d_type,
face_count: face_vals.len(),
face_values: face_vals,
}
} else {
//User wont know they got an error
//Really shouldn't need to go here. How do I avoid needing
//error checking?
retval = Dice {
dice_type: None,
face_count: 2,
face_values: face_vals,
};
}
retval
}
}
Answer
The accepted answer shows a good use of results to return a value but the response got me thinking on how to make the code more flexible while still having a hard cap that could guarantee overflow safety for a single roll so I cut out a bunch of code and came up with the following which should let you generate any dice roll between 1-10,000 per roll with multipliers for extra rolls.
const MAX_FACE_VALUE: u32 = 100000;
const MAX_FACE_COUNT: u32 = 10000;
const MAX_ROLL_COUNT: u32 = 9999;
pub struct Dice {
face_count: usize,
face_values: Vec<u32>,
}
impl Dice {
pub fn new(mut face_vals: Vec<u32>) -> Self {
//User may not have values greater than 100,000
//Index access is safe since we use the for _ in _
for x in 0..face_vals.len() {
if face_vals[x] > MAX_FACE_VALUE {
//Enforce the limit
face_vals[x] = MAX_FACE_VALUE;
}
}
//User may not have more than 10,000 faces
if face_vals.len() > MAX_FACE_COUNT as usize {
let new_vals: Vec<u32> = face_vals.split_off(MAX_FACE_COUNT as usize);
Dice {
face_count: MAX_FACE_COUNT as usize,
face_values: new_vals,
}
} else if face_vals.len() == 0 {
//No 0 sided dice allowed
Dice {
face_count: 1,
face_values: vec![1],
}
} else {
//Normal range
Dice {
face_count: face_vals.len(),
face_values: face_vals,
}
}
}
}
You should use an enum that has variants with corresponding arrays of a fixed length:
#[derive(Clone, Copy)]
pub enum Dice {
D2([u32; 2]),
D4([u32; 4]),
D6([u32; 6]),
D8([u32; 8]),
D10([u32; 10]),
D10P([u32; 10]),
D12([u32; 12]),
D20([u32; 20]),
}
Then you cannot have invalid value:
fn take_a_dice(_dice: Dice) {
//
}
fn main() {
take_a_dice(Dice::D4([1, 2, 4, 8]));
}
You should use a Result to be able to account for possible erroneous inputs:
use std::cmp::Ordering;
#[derive(Clone, Copy)]
pub enum DiceType {
D2,
D4,
D6,
D8,
D10,
D10P,
D12,
D20
}
pub struct Dice {
dice_type: DiceType,
// no need for face_count, it's a method of DiceType
face_values: Vec<u32>
}
// an error for invalid face value inputs
enum DiceError {
TooFewFaceValues,
TooManyFaceValues
}
impl DiceType {
fn face_count(&self) -> usize {
match self {
DiceType::D2 => 2,
DiceType::D4 => 4,
_ => unimplemented!() // TODO: account for all the other variants
}
}
}
impl Dice {
fn new(dice_type: DiceType, face_values: &[u32]) -> Result<Self, DiceError> {
match face_values.len().cmp(&dice_type.face_count()) {
Ordering::Less => Err(DiceError::TooFewFaceValues),
Ordering::Greater => Err(DiceError::TooManyFaceValues),
Ordering::Equal => Ok(
Dice {
dice_type,
face_values: Vec::from(face_values)
}
)
}
}
}

Resources