crate::ix!(); pub struct Resume { contact_info: ContactInfo, abstract_text: String, work_experience: Vec, education: Vec, skills: Option, projects: Option, certifications: Option, languages: Option, interests: Option, } impl RenderLatex for Resume { fn latex(&self) -> String { let contact_info = self.contact_info().render_latex_snippet(); let abstract_section = format!(indoc! {r#" \section*{{Abstract}} {} "#}, self.abstract_text()); let mut sections = vec![self.begin_document(), contact_info, abstract_section]; if let Some(work_section) = render_latex_section(&self.work_experience, "Work Experience") { sections.push(work_section); } if let Some(education_section) = render_latex_section(&self.education, "Education") { sections.push(education_section); } if let Some(skills_section) = self.skills.as_ref().map(|skills| skills.render_latex_snippet()) { sections.push(skills_section); } if let Some(projects_section) = self.projects.as_ref().map(|projects| projects.render_latex_snippet()) { sections.push(projects_section); } if let Some(certifications_section) = self.certifications.as_ref().map(|certifications| certifications.render_latex_snippet()) { sections.push(certifications_section); } if let Some(languages_section) = self.languages.as_ref().map(|languages| languages.render_latex_snippet()) { sections.push(languages_section); } if let Some(interests_section) = self.interests.as_ref().map(|interests| interests.render_latex_snippet()) { sections.push(interests_section); } sections.push(self.end_document()); sections.join("\n") } } impl Resume { pub fn builder() -> ResumeBuilder { ResumeBuilder::default() } pub fn contact_info(&self) -> &ContactInfo { &self.contact_info } pub fn abstract_text(&self) -> &str { &self.abstract_text } pub fn work_experience(&self) -> &[ResumeWorkExperience] { &self.work_experience } pub fn education(&self) -> &[ResumeEducationInfo] { &self.education } pub fn skills(&self) -> &Option { &self.skills } pub fn projects(&self) -> &Option { &self.projects } pub fn certifications(&self) -> &Option { &self.certifications } pub fn languages(&self) -> &Option { &self.languages } pub fn interests(&self) -> &Option { &self.interests } pub fn has_work_experience(&self) -> bool { !self.work_experience.is_empty() } pub fn has_education(&self) -> bool { !self.education.is_empty() } pub fn has_skills(&self) -> bool { self.skills.is_some() && !self.skills.as_ref().unwrap().is_empty() } pub fn has_projects(&self) -> bool { self.projects.is_some() && !self.projects.as_ref().unwrap().is_empty() } pub fn has_certifications(&self) -> bool { self.certifications.is_some() && !self.certifications.as_ref().unwrap().is_empty() } pub fn has_languages(&self) -> bool { self.languages.is_some() && !self.languages.as_ref().unwrap().is_empty() } pub fn has_interests(&self) -> bool { self.interests.is_some() && !self.interests.as_ref().unwrap().is_empty() } } #[derive(Default)] pub struct ResumeBuilder { contact_info: Option, abstract_text: Option, work_experience: Vec, education: Vec, skills: Option, projects: Option, certifications: Option, languages: Option, interests: Option, } impl ResumeBuilder { pub fn new() -> Self { Self::default() } pub fn contact_info(mut self, contact_info: ContactInfo) -> Self { self.contact_info = Some(contact_info); self } pub fn abstract_text(mut self, abstract_text: String) -> Self { self.abstract_text = Some(abstract_text); self } pub fn work_experience(mut self, work_experience: Vec) -> Self { self.work_experience = work_experience; self } pub fn education(mut self, education: Vec) -> Self { self.education = education; self } pub fn skills(mut self, skills: Vec) -> Self { if skills.is_empty() { self.skills = None; return self; } self.skills = Some(ResumeSkills::from(skills)); self } pub fn projects(mut self, projects: Vec) -> Self { if projects.is_empty() { self.projects = None; return self; } self.projects = Some(ResumeProjects::from(projects)); self } pub fn certifications(mut self, certifications: Vec) -> Self { if certifications.is_empty() { self.certifications = None; return self; } self.certifications = Some(ResumeCertifications::from(certifications)); self } pub fn languages(mut self, languages: Vec) -> Self { if languages.is_empty() { self.languages = None; return self; } self.languages = Some(ResumeLanguages::from(languages)); self } pub fn interests(mut self, interests: Vec) -> Self { if interests.is_empty() { self.interests = None; return self; } self.interests = Some(ResumeInterests::from(interests)); self } pub fn build(self) -> Result { Ok(Resume { contact_info: self.contact_info.ok_or("ContactInfo is required")?, abstract_text: self.abstract_text.ok_or("Abstract text is required")?, work_experience: self.work_experience, education: self.education, skills: self.skills, projects: self.projects, certifications: self.certifications, languages: self.languages, interests: self.interests, }) } }