I’m working on the database component of my app. The idea is to describe objects using a Record
structure which stores an identifier for fetching the object, and also specifies the object type.
struct Record<'a, Object> {
id: &'a str
// TODO: another field for the object type?
}
Record
should not store the object itself—just its type. A RecordFetcher
would then use this information to retrieve an object from the database and cast it to the specified type.
trait RecordFetcher {
fn fetch_object_for_record<Object>(record: Record<Object>) -> Option<Object>;
}
The Rust compiler refuses to build this code because of the unused generic parameter in Record
’s declaration, and I’m confused about how to include this information in the structure.
1 | struct Record<'a, Object> {
| ^^^^^^ unused parameter
|
= help: consider removing `Object`, referring to it in a field, or using a marker such as `PhantomData`
= help: if you intended `Object` to be a const parameter, use `const Object: usize` instead
I mostly work with Swift, so here’s a functioning example of what I’m trying to achieve. Object.Type
here is a metatype: it specifies the type without requiring an instance of it.
struct Record<Object> {
let id: String
let objectType: Object.Type // <- metatype
}
protocol RecordFetcher {
func fetchObject<Object>(for record: Record<Object>) -> Object?
}
Is there a way to achieve the same result in Rust?
In Rust typically you can utilize enums for this. A good example is
serde_json
's Value enum type. Another similar example would bemysql
's Value enum type. In Rust each enum variant can have associated data of an arbitrary data type. So enums allow you to solve the problem with different types for the ID (in case you do not always have string IDs) or the value itself. That doesn't give you all you ask for though, only part of the solution.Rust doesn't have reflection (read this), so I'm not aware of an easy, automated way to achieve the mapping between an object type and an enum variant (holding the actual object value).