0

In C++, one way to handle designing a program that needs to read multiple file formats is a Repository of Factories of Strategies. Generally the Repository part is a Singleton. The Factory takes care of building a Strategy which handles the file format. Furthermore, the Repository can be populated via static initialization, such that each Factory can register itself to the Repository before main() is executed.

I'm struggling to see how to implement a similar system, without the Singleton component, in Rust. I'd like to be able to register Factories to some kind of file reader repository, ideally at static initialization time, with the added option for other modules or plug-ins to be able to add their own file readers at runtime.

What I'm looking for is a Rust version of something like this (which is simplified):

class Repo : boost::non_copyable {
public:
    static Repo& instance();
    void registerFactory(std::unique_ptr<FileFactory> factory, std::string extension);
};

template<class T>
class Factory {
public:
    std::unique_ptr<T> build(std::string path) { return std::make_unique<T>(path); }
}

class AudioFile {
public:
    AudioFile(std::string path);
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Tim
  • 4,560
  • 2
  • 40
  • 64
  • 3
    There is no life before main in Rust. – Boiethios Jul 03 '17 at 08:42
  • @Boiethios, thanks I hadn't realized that. What's the idiomatic `Rust` way to do this kind of thing then? – Tim Jul 03 '17 at 08:45
  • I'd say with initialization at compile-time (with the macro system), but I see that you want a plugin system. A lot of project do some work at compile time (see Rocket and Diesel for example) to generate the right code. – Boiethios Jul 03 '17 at 08:49
  • A good question is: what kind of plugin do you want to implement? – Boiethios Jul 03 '17 at 08:50
  • I'm writing a program that will deal with audio files. Some of the files are simple and I'll process them with built-in parsers, like `wav` and `aiff`. In other cases I might want to use a library, like `FLAC`, and in others, that might depend on the platform. For instance, `CoreAudio` on `macOS` handles many formats. In `C++` I'd have designed this as I described, which gives lots of flexibility, but I don't see how to do this in `Rust`. – Tim Jul 03 '17 at 08:54
  • @Stargateur, I've read a bit about `Singleton` and `Rust` and I'm reasonably convinced by the argument that `Singleton`s are to be avoided when possible, so I'd like to do it without `Singleton` if at all possible. – Tim Jul 03 '17 at 08:55
  • Are the possible formats fixed? Or can the program be configured to load different formats via dynamic linking? – E_net4 Jul 03 '17 at 09:12
  • 3
    Could you describe the problem you are trying to solve without using the words "singleton," "factory" or "repository"? – BurntSushi5 Jul 03 '17 at 09:20
  • @BurntSushi5, I could but it would take many more words and amount to the same thing. – Tim Jul 03 '17 at 09:22
  • @E_net4, I'd like the option to add formats via plug-ins or whatever, so no, not a fixed list. – Tim Jul 03 '17 at 09:23
  • Well then, if [this](https://stackoverflow.com/q/44708483/1233251) question doesn't help, I think nothing will. Sounds like a duplicate too. – E_net4 Jul 03 '17 at 09:24
  • So in Rust the typical way to do build this for a fixed list of types would be a set of if/else clauses? – Tim Jul 03 '17 at 09:27
  • Not really. You could leverage the power of macros to generate the necessary code, as mentioned by Boiethios. Projects such as Rocket and Diesel rely on this. For dynamic plugins however, there is no standard or conventional approach. – E_net4 Jul 03 '17 at 09:39
  • 1
    "*I could but it would take many more words and amount to the same thing*" On the other hand, it might not amount to the same thing – people might actually be able to _help_ you... – ildjarn Jul 03 '17 at 10:26
  • 2
    I think what multiple commenters are trying to tell you is that there's a chance you've encountered the [XY-Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem), meaning you are asking for a solution to a problem that you encountered while solving your actual problem, instead of asking for a solution to your actual problem – oli_obk Jul 03 '17 at 11:19
  • 2
    @Tim I'll take a shot in the dark. I don't know if this satisfies what you're trying to do, but it's the closest transliteration I could make of your C++ code. http://play.integer32.com/?gist=9f2fca703e68af601a36954c62c4878d&version=stable – BurntSushi5 Jul 03 '17 at 13:57
  • @BurntSushi5, thanks, that's very helpful. If you were to write that up as an answer I'd be happy to give you the points. – Tim Jul 03 '17 at 19:44
  • @Shepmaster Manishearth I don't think this is a duplicate, but the question could be a lot better. The global singleton aspect of this question seems least interesting. The more interesting bits are probably the virtual dispatch. – BurntSushi5 Jul 03 '17 at 23:37
  • 1
    @Tim Thanks. Glad it was helpful. To be clear, I had to guess at a number of things that were implied by your question, and it was quite difficult. It would be most appreciated if you could open a new question that doesn't use the words "singleton" or "factory," and instead describes the actual problem you're trying to solve. For example, I might start with, "I need to store a bunch of values with different types but a common interface in a single global registry that can be dynamically modified." Bonus points for saying why you need a global registry without referring to another language. – BurntSushi5 Jul 03 '17 at 23:39
  • @BurntSushi5, thanks I'll do that. – Tim Jul 03 '17 at 23:47
  • Hopefully this question enjoys a better reception: https://stackoverflow.com/questions/44895392/extensible-registry-of-types :) – Tim Jul 04 '17 at 00:36

0 Answers0