I have the following struct:
#[derive(Debug)]
pub struct Entry {
pub index: usize,
pub name: String,
pub filename_offset: u64,
pub entry_type: EntryType,
}
#[derive(Debug)]
pub enum EntryType {
File {
file_offset: u64,
length: usize,
},
Directory {
parent_index: usize,
next_index: usize,
},
}
Entry
is an entry in a GameCube ROM file system table which describes a file or directory. I defined various methods for Entry
such as Entry::read_filename
and Entry::write_to_disk
. However, I have some methods that don't make sense to be available to both regular files and directories. For example, Entry::iter_contents
iterates over all of a directory's child entries.
I want to be able to define certain methods such as Entry::iter_contents
only for entries where entry_type
is a certain variant.
I tried turning EntryType
into a trait and made a DirectoryEntryInfo
and FileEntryInfo
struct, which both implemented EntryType
.
Sadly, there were some problems with this approach. I have a Vec<Entry>
elsewhere and with this change it would become Vec<Entry<EntryType>>
. Using a trait like this, I have no way to downcast Entry<EntryList>
to Entry<DirectoryEntryInfo>
. I also tried doing something with Any
, as that is the only way I am aware of to downcast in Rust, but I was only able to cast entry_type
, not the entire Entry
itself.
Ultimately, I'd like to end up with something similar to this:
impl<T: EntryType> Entry<T> {
pub fn as_dir(&self) -> Option<Entry<DirectoryEntryInfo>> { ... }
pub fn as_file(&self) -> Option<Entry<FileEntryInfo>> { ... }
...
}
impl Entry<DirectoryEntryInfo> {
...
}
impl Entry<FileEntryInfo> {
...
}
This way, I could access all of the entries fields without knowing whether or not it's a directory or file, as well as be able to cast it to a type that would provide me with all of the Entry
fields in addition to methods based on the type parameter like Entry::iter_contents
.
Is there a good way to do this without something like RFC 1450?
I'm aware that enum variants are not their own types and cannot be used as type parameters. I am just looking for an alternate way to conditionally define a method for a struct and still be able to have a way to store any variant of this struct in something like a Vec
. This article is extremely close to what I am trying to do. However, using the example from it, there is no way to store a MyEnum<Bool>
without knowing whether that Bool
is True
or False
at compile time. Being able to downcast something like MyEnum<Box<Bool>>
to MyEnum<False>
would fix this, but I'm not aware of anything like that in Rust.
See Question&Answers more detail:
os