RUST EXCERCISE - CAR MANUFACTURER

CAR MANUFACTURER

EXCERCISE: 


SOLUTION:

  • Create a new binary package called manufacturers:
  • cargo run --build manufacturers
  • Add rust analyser to vscode settings.json.
  • Go to crates.io, search for serde, reqwest and tokio.
  • Copy their version and paste it in cargo.toml.
  • serde_json = "1.0"
    reqwest = { version = "0.11", features = ["josn"] }
    tokio = { version = "1", features = ["full"] }
    
  • Run cargo-watch with a parameter BMW passed into it:
  • cargo-watch -qc -x'run -- BMW' -x clippy

  • #![deny(clippy::all)]
    use std::env;
    
    const API_URL: &str = "https://vpic.nhtsa.dot.gov/api/vehicles/getallmanufacturers?format=json";
    
    struct Manufacturer<'a>{
      name: Option<&'a str>,
      country: Option<&'a str>,
      common_name: Option<&'a str>,
    }
    
    trait Contains {
      fn contains(&self, needle: &str) -> bool;
    }
    
    impl<'a> Contains for Manufacturer<'a>{
      fn contains(&self, needle: &str) -> bool {
         self.name.unwrap_or_default().contains(needle) 
         || self.common_name.unwrap_or_default().contains(needle)
         || self.country.unwrap_or_default().contains(needle)
      }
    }
    
    impl<'a> Manufacturer<'a>{
      fn description(&self) -> String{
         let name: &str = self.name.unwrap_or_default();
         let common_name: &str = self.name.unwrap_or_default();
         let country: &str = self.name.unwrap_or_default();
         format!(
            "\tName: {} \n\tCommon Name: {}\n\tCountry: {}",
            name, common_name, country
         )
      }
    }
    
    #[tokio::main]
    async fn main() -> Result<(), Box<dyn std::error::Error>> {
      let args: Vec<String> = env::args().collect();
      if args.len() < 2 {
        println!("Usage: {} <search term>", args[0]);
        return Ok(());
      }
      let keyword: &String = &args[1];
      let client = reqwest::Client::new();
      let res = client
            .get(API_URL)
            .send()
            .await?
            .json::<serde_json::Value>()
            .await?;
       let manufacturer_json = res
             .as_object()
             .unwrap()
             .iter()
             .find(|(key, _)| key == &"Results")
             .unwrap()
             .1
             .as_array()
             .unwrap()
             .iter();
        let manufacturers = manufacturer_json.map(|manufacturer_json|{
          let object = manufacturer_json.as_object().unwrap();
          let country = object.get("Country").unwrap().as_str();
          let name = object.get("Mfr_Name").unwrap().as_str();
          let common_name = object.get("Mfr_CommonName").unwrap().as_str();
          Manufacturer {
           name,
           common_name,
           country
         }
        }); 
        let found_manufacturer = manufacturers
          .filter(|manufacturer| manufacturer.contains(keyword))
          .collect::<Vec<_>>();
    
        if found_manufacturer.is_empty(){
           Err("No Manufacturer found".into())
        }
        else{
          println!("Found {} manufacturer:", found_manufacturer.len());
          for( index, manu) in found_manufacturer.iter().enumerate(){
             println!("Manufactuere # {}", index +1);
             println!("{}", manu.description());
          }
          Ok(())
        }
    }

Comments