Consider annotating `ItemChange` with `#[derive(Hash)]` but it doesn't work - rust

I am trying to create a struct that has a hashmap of changed values.
Example:
#[derive(Debug, Clone, Eq, PartialEq)]
struct ItemChange {
time: i64,
metadata: HashMap<String, String>,
changed_metadata: HashMap<String, String>,
user_defined_description: String,
description: String,
}
#[derive(Debug, Clone)]
pub struct ProductItem {
id: String,
/// Ordered change_history by date
change_history: HashMap<ItemChange, i64>,
}
impl ProductItem {
pub fn add_change(&self, change: ItemChange, date: i64) {
self.change_history.insert(); // <-- change_history doesn't have insert :(
}
}
The code doesn't compile with an error saying
58 | struct ItemChange {
| ----------------- doesn't satisfy `ItemChange: Hash`
...
97 | self.change_history.insert();
| ^^^^^^
|
= note: the following trait bounds were not satisfied:
`ItemChange: Hash`
help: consider annotating `ItemChange` with `#[derive(Hash)]`
What am I doing wrong?

Related

How can I implement From<Vec<MyType>> for Vec<MyOtherType>?

I have two identical structs in two different modules:
Module data has struct data::Branch:
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Branch {
pub id: Uuid,
pub name: String,
pub parents: Vec<Branch>,
pub children: Vec<Branch>,
}
And module graphql has struct graphql::Branch:
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Branch {
pub id: Uuid,
pub name: String,
pub parents: Vec<Branch>,
pub children: Vec<Branch>,
}
I can not figure it out how to implement impl From<Vec<data::Branch>> for Vec<Branch> in graphql module?
impl From<data::branch::Branch> for Branch {
fn from(branch: data::branch::Branch) -> Branch {
Branch {
id: branch.id,
name: branch.name,
content: branch.name,
parents: branch.parents.into(),
children: branch.children.into(),
created_at: branch.created_at,
updated_at: branch.updated_at,
}
}
}
impl From<Vec<data::branch::Branch>> for Vec<Branch> {
fn from(_: Vec<data::branch::Branch>) -> Self {
todo!();
}
}
I have faced this error and don't know how to handle it.
error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> src/graphql/branch/branch.rs:64:1
|
64 | impl From<Vec<data::branch::Branch>> for Vec<Branch> {
| ^^^^^-------------------------------^^^^^-----------
| | | |
| | | `Vec` is not defined in the current crate
| | `Vec` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
As I understand now simple generic function can easily handle such case. Thank you #kmdreko for your help.
It works for me. The only problem is that the compiler suggests implementing From<Vec<data::Branch>> for Vec<Branch>, but you can't do it, and this is a little bit confusing if you don't know rust well)
rust playground.
mod data {
#[derive(Debug, Clone, Default)]
pub struct Branch {
pub id: String,
pub name: String,
pub parents: Vec<Branch>,
pub children: Vec<Branch>,
}
}
#[derive(Debug, Clone)]
pub struct Branch {
pub id: String,
pub name: String,
pub parents: Vec<Branch>,
pub children: Vec<Branch>,
}
impl From<data::Branch> for Branch {
fn from(branch: data::Branch) -> Branch {
Branch {
id: branch.id.clone(),
name: branch.name.clone(),
parents: convert_from_vec(branch.parents.clone()),
children: convert_from_vec(branch.children.clone()),
}
}
}
fn convert_from_vec<T, U>(v: Vec<U>) -> Vec<T>
where
T: From<U>,
{
v.into_iter().map(T::from).collect()
}
fn main() {
let branch = data::Branch::default();
let branch: Branch = branch.into();
}

Why this borrowing error if I'm using `&self` in this function?

I have this code (PLAYGROUND HERE):
#[derive(Debug, Default, Clone)]
pub struct BaseFile {
pub id: Option<String>,
pub location: String,
pub size: u64,
}
impl BaseFile {
pub fn filename(&self) -> String {
"CALCULATED_FILENAME".to_string()
}
}
#[derive(Debug, Default, Clone)]
pub struct AdvancedFile {
pub id: Option<String>,
pub filename: String,
pub size: u64,
}
impl AdvancedFile {
pub fn from_base(
id: Option<String>,
filename: String,
size: u64,
) -> Self {
Self {
id,
filename,
size,
}
}
}
impl From<BaseFile> for AdvancedFile {
fn from(base_file: BaseFile) -> Self {
Self::from_base(
base_file.id,
base_file.filename(),
base_file.size,
)
}
}
#[tokio::main]
async fn main() {
let domain_file = BaseFile {
id: None,
location: "new_location".to_string(),
size: 123,
};
dbg!(domain_file);
}
with this error:
error[E0382]: borrow of partially moved value: `base_file`
--> src/main.rs:39:13
|
38 | base_file.id,
| ------------ value partially moved here
39 | base_file.filename(),
| ^^^^^^^^^^^^^^^^^^^^ value borrowed here after partial move
|
= note: partial move occurs because `base_file.id` has type `Option<String>`, which does not implement the `Copy` trait
Why this error if I'm using &self in pub fn filename(&self) -> String {?
Since that object is being ripped apart and reassembled, you may need to capture the parts before you do that:
// Capture any values that depend on `base_name` being intact
let filename = base_name.filename();
Self::from_base(
base_file.id,
filename,
base_file.size,
)

Rust clippy check raise error `mutable_key_type` when use bytes as key's field

The following codeļ¼š
use bytes::Bytes;
use std::collections::HashSet;
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Id {
value: Vec<u8>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Id2 {
value: Bytes,
}
pub struct IdSet {
pub set: HashSet<Id>,
}
impl IdSet {
pub fn insert(&mut self, id: Id) {
self.set.insert(id);
}
pub fn insert_all(&mut self, ids: HashSet<Id>) {
self.set.extend(ids);
}
}
pub struct IdSet2 {
pub set: HashSet<Id2>,
}
impl IdSet2 {
pub fn insert(&mut self, id: Id2) {
self.set.insert(id);
}
pub fn insert_all(&mut self, ids: HashSet<Id2>) {
self.set.extend(ids);
}
}
cargo clippy raise an error:
Checking playground v0.0.1 (/playground)
error: mutable key type
--> src/lib.rs:37:39
|
37 | pub fn insert_all(&mut self, ids: HashSet<Id2>) {
| ^^^^^^^^^^^^
|
= note: `#[deny(clippy::mutable_key_type)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#mutable_key_type
HashSet<Id> as param is alright, but HashSet<Id2> as param is an error, Why?
This is rust playground URL: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=36529bbb847be2342e6e4ef8a44d4fe9

Rust - value of type cannot be built from `std::iter::Iterator<>`

I have struct from which I want to extract the data.
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RunResult {
pub runs: Vec<RunDetails>,
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct RunDetails {
pub details: String,
pub name: String,
pub id: String,
pub type: String,
}
I am getting the data which got inserted in above struct in the variable result which I am iterating below
let my_result:RunResult = result
.runs
.into_iter()
.filter(|line| line.details.contains(&"foo"))
.collect();
I am getting the error as
value of type `RunResult` cannot be built from `std::iter::Iterator<Item=RunDetails>`
I want to get the record where type=OK, details contains foo with highest id.
How can I achieve this?
Check out the documentation for collect here.
Your struct RunResult should implement FromIterator<RunDetails>.
Try adding this (untested by me):
impl FromIterator<RunDetails> for RunResult {
fn from_iter<I: IntoIterator<Item=RunDetails>>(iter: I) -> Self {
Self {
runs: Vec::from_iter(iter);
}
}
}

Using Option<T> with Diesel's Insertable trait

I have the following model:
use diesel::prelude::*;
use crate::schema::category;
#[derive(Debug, Identifiable, Queryable)]
#[table_name = "category"]
pub struct Category {
pub id: i64,
pub name: String,
pub description: String,
pub parent_id: Option<i64>,
}
#[derive(Debug, Insertable)]
#[table_name = "category"]
pub struct NewCategory<'a> {
pub name: &'a str,
pub description: &'a str,
pub parent_id: &'a Option<i64>,
}
and schema.rs:
table! {
category (id) {
id -> Integer,
name -> Text,
description -> Text,
parent_id -> Nullable<Integer>,
}
}
However, when I try to compile this code, I get the following errors:
error[E0277]: the trait bound `std::option::Option<i64>: diesel::Expression` is not satisfied
--> src/models/categories.rs:15:17
|
15 | #[derive(Debug, Insertable)]
| ^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `std::option::Option<i64>`
|
= note: required because of the requirements on the impl of `diesel::Expression` for `&std::option::Option<i64>`
error[E0277]: the trait bound `std::option::Option<i64>: diesel::Expression` is not satisfied
--> src/models/categories.rs:15:17
|
15 | #[derive(Debug, Insertable)]
| ^^^^^^^^^^ the trait `diesel::Expression` is not implemented for `std::option::Option<i64>`
|
= note: required because of the requirements on the impl of `diesel::Expression` for `&'a std::option::Option<i64>`
What do I need to get this to work? I've looked around, but the only similar issue that I've found is when someone had more than 16 columns in their table, which is not the case here.
Modify pub parent_id: &'a Option<i64> to place the &'a inside of the Option: pub parent_id: Option<&'a i64>.

Resources