Le système de modules de Rust est en fait incroyablement flexible et vous permettra d'exposer le type de structure que vous souhaitez tout en masquant la structure de votre code dans des fichiers.
Je pense que la clé ici est de l'utiliser pub use, ce qui vous permettra de réexporter des identifiants à partir d'autres modules. Il existe un précédent pour cela dans la std::iocaisse de Rust où certains types de sous-modules sont réexportés pour être utilisés dansstd::io .
Edit (2019-08-25): la partie suivante de la réponse a été écrite il y a un certain temps. Il explique comment configurer une telle structure de module avec rustcseul. Aujourd'hui, on utilise généralement Cargo pour la plupart des cas d'utilisation. Bien que ce qui suit soit toujours valide, certaines parties de celui-ci (par exemple #![crate_type = ...]) peuvent sembler étranges. Ce n'est pas la solution recommandée.
Pour adapter votre exemple, nous pourrions commencer par cette structure de répertoires:
src/
lib.rs
vector.rs
main.rs
Voici votre main.rs:
extern crate math;
use math::vector;
fn main() {
println!("{:?}", vector::VectorA::new());
println!("{:?}", vector::VectorB::new());
}
Et votre src/lib.rs:
#[crate_id = "math"];
#[crate_type = "lib"];
pub mod vector; // exports the module defined in vector.rs
Et enfin src/vector.rs,:
// exports identifiers from private sub-modules in the current
// module namespace
pub use self::vector_a::VectorA;
pub use self::vector_b::VectorB;
mod vector_b; // private sub-module defined in vector_b.rs
mod vector_a { // private sub-module defined in place
#[derive(Debug)]
pub struct VectorA {
xs: Vec<i64>,
}
impl VectorA {
pub fn new() -> VectorA {
VectorA { xs: vec![] }
}
}
}
Et c'est là que la magie opère. Nous avons défini un sous-module math::vector::vector_aqui a une implémentation d'un type spécial de vecteur. Mais nous ne voulons pas que les clients de votre bibliothèque se soucient de l'existence d'un vector_asous-module. Au lieu de cela, nous aimerions le rendre disponible dans le math::vectormodule. Ceci est fait avec pub use self::vector_a::VectorA, qui réexporte l' vector_a::VectorAidentifiant dans le module courant.
Mais vous avez demandé comment faire cela pour pouvoir mettre vos implémentations vectorielles spéciales dans différents fichiers. C'est ce que fait la mod vector_b;ligne. Il demande au compilateur Rust de rechercher un vector_b.rsfichier pour l'implémentation de ce module. Et bien sûr, voici notre src/vector_b.rsfichier:
#[derive(Debug)]
pub struct VectorB {
xs: Vec<i64>,
}
impl VectorB {
pub fn new() -> VectorB {
VectorB { xs: vec![] }
}
}
Du point de vue du client, le fait que VectorAet VectorBsoient définis dans deux modules différents dans deux fichiers différents est complètement opaque.
Si vous êtes dans le même répertoire que main.rs, vous devriez pouvoir l'exécuter avec:
rustc src/lib.rs
rustc -L . main.rs
./main
En général, le chapitre "Crates and Modules" du livre Rust est assez bon. Il existe de nombreux exemples.
Enfin, le compilateur Rust recherche également automatiquement les sous-répertoires. Par exemple, le code ci-dessus fonctionnera inchangé avec cette structure de répertoire:
src/
lib.rs
vector/
mod.rs
vector_b.rs
main.rs
Les commandes à compiler et à exécuter restent également les mêmes.