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.