Reputation: 19
So building a little project to learn Rust and was wondering what the best way would be to define a vector with a hashmap
The way to data is going to be structured in the end is as follows:
[
{
id: "USER_ID",
firstname: "First Name",
lastname: "Last Name",
email: "Email",
errors: [ { type: "...", message: "cannot update user" } ],
}
]
So I was thinking I'd write out my project as follows
src/parser.rs
pub struct Parser<T> {
pub parsed_log: Vec<HashMap<String, T>>,
}
// pub trait ReturnProperties {
// fn return_parsed_logs(&self) -> Vec<HashMap<String, T>>;
// }
impl<T: Clone> Parser<T> {
/// handle upsert will parse the upsert lines into a users vector
/// it will also match the errors with the user id
// will implement later
//pub fn handle_upsert(...) {}
pub fn return_parsed_logs(self) -> Vec<HashMap<String, T, RandomState>> {
self.parsed_log.to_vec()
}
}
src/main.rs
fn main() {
// why does this keep returning
// cannot find type `T` in this scope??
let log_parser: parser::Parser<T> = Parser {
parsed_log: vec![]
};
}
Am I doing this all wrong? I feel like trying to force rust to behave like an OOP language (where i came from) but it's not having it. Any pointers? What did I get totally wrong here?
Upvotes: 0
Views: 54
Reputation: 42217
// why does this keep returning // cannot find type `T` in this scope?? let log_parser: parser::Parser<T> = Parser { parsed_log: vec![] };
Because there's no type T
in this scope? When you declare a type, the T
is a placeholder (which is declared as such, that's what e.g. the <T: Clone>
does before the typename in the impl
block), but when you're using the type you need to provide either an actual thing, or a type which was declared somewhere in scope (usually on the function such that the caller can provide that type).
Note that you can often ask Rust to infer types e.g. sometimes you will see
let foo: Vec<_> = bar.collect();
this lets rustc know you want to collect() to a Vec
, but lets it infer the item type (because it's unambiguous).
Here however there's nothing to constrain T
, no information rustc can use to decide what it could or would be.
Though I think your entire thinking is mistaken: in Rust, a generic T
will be replaced by a single concrete type. But that's not what the initial structure shows, 4 of the items map to strings, but the 5th maps to an array of sub-structures. That won't fit into a T
, the keys have completely different values. Why are your even using a HashMap
and generics for this, why not a struct or enum?
Upvotes: 1