Exercise: Builder Type

In this example, we will implement a complex data type that owns all of its data. We will use the “builder pattern” to support building a new value piece-by-piece, using convenience functions.

Fill in the missing pieces.

  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.         todo!("1")
  26.     }
  27. }
  28. /// A builder for a Package. Use `build()` to create the `Package` itself.
  29. struct PackageBuilder(Package);
  30. impl PackageBuilder {
  31.     fn new(name: impl Into<String>) -> Self {
  32.         todo!("2")
  33.     }
  34.     /// Set the package version.
  35.     fn version(mut self, version: impl Into<String>) -> Self {
  36.         self.0.version = version.into();
  37.         self
  38.     }
  39.     /// Set the package authors.
  40.     fn authors(mut self, authors: Vec<String>) -> Self {
  41.         todo!("3")
  42.     }
  43.     /// Add an additional dependency.
  44.     fn dependency(mut self, dependency: Dependency) -> Self {
  45.         todo!("4")
  46.     }
  47.     /// Set the language. If not set, language defaults to None.
  48.     fn language(mut self, language: Language) -> Self {
  49.         todo!("5")
  50.     }
  51.     fn build(self) -> Package {
  52.         self.0
  53.     }
  54. }
  55. fn main() {
  56.     let base64 = PackageBuilder::new("base64").version("0.13").build();
  57.     println!("base64: {base64:?}");
  58.     let log =
  59.         PackageBuilder::new("log").version("0.4").language(Language::Rust).build();
  60.     println!("log: {log:?}");
  61.     let serde = PackageBuilder::new("serde")
  62.         .authors(vec!["djmitche".into()])
  63.         .version(String::from("4.0"))
  64.         .dependency(base64.as_dependency())
  65.         .dependency(log.as_dependency())
  66.         .build();
  67.     println!("serde: {serde:?}");
  68. }