Solution

  1. #[derive(Debug)]
  2. enum Language {
  3.     Rust,
  4.     Java,
  5.     Perl,
  6. }
  7. #[derive(Clone, Debug)]
  8. struct Dependency {
  9.     name: String,
  10.     version_expression: String,
  11. }
  12. /// A representation of a software package.
  13. #[derive(Debug)]
  14. struct Package {
  15.     name: String,
  16.     version: String,
  17.     authors: Vec<String>,
  18.     dependencies: Vec<Dependency>,
  19.     language: Option<Language>,
  20. }
  21. impl Package {
  22.     /// Return a representation of this package as a dependency, for use in
  23.     /// building other packages.
  24.     fn as_dependency(&self) -> Dependency {
  25.         Dependency {
  26.             name: self.name.clone(),
  27.             version_expression: self.version.clone(),
  28.         }
  29.     }
  30. }
  31. /// A builder for a Package. Use `build()` to create the `Package` itself.
  32. struct PackageBuilder(Package);
  33. impl PackageBuilder {
  34.     fn new(name: impl Into<String>) -> Self {
  35.         Self(Package {
  36.             name: name.into(),
  37.             version: "0.1".into(),
  38.             authors: vec![],
  39.             dependencies: vec![],
  40.             language: None,
  41.         })
  42.     }
  43.     /// Set the package version.
  44.     fn version(mut self, version: impl Into<String>) -> Self {
  45.         self.0.version = version.into();
  46.         self
  47.     }
  48.     /// Set the package authors.
  49.     fn authors(mut self, authors: Vec<String>) -> Self {
  50.         self.0.authors = authors;
  51.         self
  52.     }
  53.     /// Add an additional dependency.
  54.     fn dependency(mut self, dependency: Dependency) -> Self {
  55.         self.0.dependencies.push(dependency);
  56.         self
  57.     }
  58.     /// Set the language. If not set, language defaults to None.
  59.     fn language(mut self, language: Language) -> Self {
  60.         self.0.language = Some(language);
  61.         self
  62.     }
  63.     fn build(self) -> Package {
  64.         self.0
  65.     }
  66. }
  67. fn main() {
  68.     let base64 = PackageBuilder::new("base64").version("0.13").build();
  69.     println!("base64: {base64:?}");
  70.     let log =
  71.         PackageBuilder::new("log").version("0.4").language(Language::Rust).build();
  72.     println!("log: {log:?}");
  73.     let serde = PackageBuilder::new("serde")
  74.         .authors(vec!["djmitche".into()])
  75.         .version(String::from("4.0"))
  76.         .dependency(base64.as_dependency())
  77.         .dependency(log.as_dependency())
  78.         .build();
  79.     println!("serde: {serde:?}");
  80. }