1use std::str::FromStr;
2
3use email_address::EmailAddress;
4use isolang;
5use my_country::Country;
6use phonenumber::PhoneNumber;
7use serde::{Deserialize, Deserializer, Serialize, Serializer};
8use serde_json::Value;
9use time::Month;
10use url::Url;
11
12#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
13pub struct Locale {
14 pub country: Country,
15 pub language: isolang::Language,
16}
17
18pub struct Identity {
19 pub authentication_token: String,
20 pub session_cookie: String,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize)]
25#[serde(rename_all = "camelCase")]
26pub struct ProfileView {
27 pub certification_view: CertificationView,
28 pub course_view: CourseView,
29 pub education_view: EducationView,
30 pub entity_urn: Option<String>,
31 pub honor_view: HonorView,
32 pub language_view: LanguageView,
33 pub organization_view: OrganizationView,
34 pub patent_view: PatentView,
35 pub position_group_view: PositionGroupView,
36 pub position_view: PositionView,
37 pub primary_locale: Locale,
38 pub profile: Profile,
39 pub project_view: ProjectView,
40 pub publication_view: PublicationView,
41 pub skill_view: SkillView,
42 pub summary_treasury_media_count: u32,
43 pub summary_treasury_medias: Vec<Value>,
44 pub test_score_view: TestScoreView,
45 pub volunteer_cause_view: VolunteerCauseView,
46 pub volunteer_experience_view: VolunteerExperienceView,
47 #[serde(skip)]
48 pub skills: Vec<Skill>,
49}
50
51#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53pub struct PersonName {
54 pub first: String,
55 pub last: String,
56}
57
58impl PersonName {
59 pub fn full_name(&self) -> String {
60 format!("{} {}", self.first, self.last)
61 }
62}
63
64#[derive(Debug, Clone, PartialEq, Serialize)]
65pub struct Address {
66 pub raw: String,
67 pub street: Option<String>,
68 pub city: Option<String>,
69 pub state: Option<String>,
70 pub country: Option<Country>,
71 pub postal_code: Option<String>,
72}
73
74impl Address {
75 pub fn parse(raw_address: &str) -> Self {
76 let parts: Vec<&str> = raw_address.split(',').map(|s| s.trim()).collect();
77 Self {
78 raw: raw_address.to_string(),
79 street: parts.get(0).map(|s| s.to_string()),
80 city: parts.get(1).map(|s| s.to_string()),
81 state: parts.get(2).map(|s| s.to_string()),
82 country: None, postal_code: None, }
85 }
86}
87
88impl<'de> Deserialize<'de> for Address {
90 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
91 where
92 D: Deserializer<'de>,
93 {
94 let raw = String::deserialize(deserializer)?;
95 Ok(Address::parse(&raw))
96 }
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
101#[serde(rename_all = "camelCase")]
102pub struct Profile {
103 pub entity_urn: Option<String>,
104
105 pub first_name: Option<String>,
106 pub last_name: Option<String>,
107 pub headline: Option<String>,
108 pub summary: Option<String>,
109
110 pub industry_name: Option<String>,
111 pub industry_urn: Option<String>,
112
113 pub geo_country_name: Option<String>,
114 pub geo_country_urn: Option<String>,
115 pub geo_location_name: Option<String>,
116 pub geo_location_backfilled: Option<bool>,
117 pub geo_location: Option<GeoLocation>,
118
119 pub address: Option<Address>,
120 pub birth_date: Option<BirthDate>,
121
122 pub default_locale: Option<Locale>,
123 pub supported_locales: Option<Vec<Locale>>,
124
125 pub location: Option<Location>,
126 pub location_name: Option<String>,
127
128 pub mini_profile: Option<MiniProfile>,
129 pub profile_picture: Option<ProfilePicture>,
130 pub profile_picture_original_image: Option<VectorImageContainer>,
131
132 pub show_education_on_profile_top_card: Option<bool>,
133 pub student: Option<bool>,
134 pub elt: Option<bool>,
135
136 pub version_tag: Option<String>,
137
138 #[serde(skip)]
139 pub profile_id: String,
140
141 #[serde(skip)]
142 pub contact: ContactInfo,
143}
144
145impl Profile {
146 pub fn get_full_name(&self) -> Option<String> {
148 match (&self.first_name, &self.last_name) {
149 (Some(first), Some(last)) => Some(format!("{} {}", first, last)),
150 (Some(first), None) => Some(first.clone()),
151 (None, Some(last)) => Some(last.clone()),
152 (None, None) => None,
153 }
154 }
155
156 pub fn get_profile_image_url(&self) -> Option<Url> {
158 self.profile_picture_original_image
159 .as_ref()
160 .and_then(|container| container.vector_image.as_ref())
161 .and_then(|vector_image| {
162 if let (Some(root_url), Some(artifact)) =
163 (&vector_image.root_url, vector_image.artifacts.first())
164 {
165 let full_url = format!(
166 "{}{}",
167 root_url,
168 artifact
169 .file_identifying_url_path_segment
170 .as_deref()
171 .unwrap_or("")
172 );
173 Url::parse(&full_url).ok()
174 } else {
175 None
176 }
177 })
178 }
179
180 pub fn get_profile_id(&self) -> Option<String> {
182 self.entity_urn
183 .as_ref()
184 .and_then(|urn| urn.split(':').last().map(|id| id.to_string()))
185 }
186}
187
188#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
189pub struct GeoLocation {
190 pub geo_urn: Option<String>,
191 pub postal_code: Option<String>,
192}
193
194#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
195pub struct BirthDate {
196 pub day: Option<u8>,
197 pub month: Option<Month>,
198 pub year: Option<u16>,
199}
200
201impl FromStr for BirthDate {
202 type Err = String;
203
204 fn from_str(s: &str) -> Result<Self, Self::Err> {
205 let parts: Vec<&str> = s.split('-').collect();
206
207 match parts.len() {
208 3 => {
209 let year = parts[0].parse::<u16>().ok();
210 let month = parts[1]
211 .parse::<u8>()
212 .ok()
213 .and_then(|m| Month::try_from(m).ok()); let day = parts[2].parse::<u8>().ok();
215
216 Ok(BirthDate { day, month, year })
217 }
218 _ => Err(format!("Invalid date format: {}", s)),
219 }
220 }
221}
222
223impl BirthDate {
224 pub fn as_date(&self) -> Option<time::Date> {
226 if let (Some(year), Some(month), Some(day)) = (self.year, self.month, self.day) {
227 let month = Month::try_from(month).ok()?;
228 time::Date::from_calendar_date(year as i32, month, day).ok()
229 } else {
230 None
231 }
232 }
233}
234
235#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
237pub struct Paging {
238 pub count: u32,
239 pub links: Vec<Value>,
240 pub start: u32,
241 pub total: u32,
242}
243
244#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
246#[serde(rename_all = "camelCase")]
247pub struct CertificationView {
248 pub elements: Vec<Certification>,
249 pub entity_urn: Option<String>,
250 pub paging: Paging,
251 pub profile_id: String,
252}
253
254#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
255#[serde(rename_all = "camelCase")]
256pub struct Certification {
257 pub entity_urn: Option<String>,
258 pub name: String,
259 pub company: Option<MiniCompany>,
260 pub authority: Option<String>,
261 pub license_number: Option<String>,
262 pub time_period: Option<TimePeriod>,
263 pub url: Option<Url>,
264}
265
266#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
268#[serde(rename_all = "camelCase")]
269pub struct CourseView {
270 pub elements: Vec<Course>,
271 pub entity_urn: Option<String>,
272 pub paging: Paging,
273 pub profile_id: String,
274}
275
276#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
277pub struct Course {
278 pub entity_urn: Option<String>,
279 pub name: String,
280 pub number: Option<String>,
281}
282
283#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
285#[serde(rename_all = "camelCase")]
286pub struct HonorView {
287 pub elements: Vec<Honor>,
288 pub entity_urn: Option<String>,
289 pub paging: Paging,
290 pub profile_id: String,
291}
292
293#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
294#[serde(rename_all = "camelCase")]
295pub struct Honor {
296 pub entity_urn: Option<String>,
297 pub title: String,
298 pub issuer: Option<String>,
299 pub issue_date: Option<YearMonth>,
300 pub description: Option<String>,
301 pub occupation: Option<String>,
302}
303
304#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
306#[serde(rename_all = "camelCase")]
307pub struct LanguageView {
308 pub elements: Vec<Language>,
309 pub entity_urn: Option<String>,
310 pub paging: Paging,
311 pub profile_id: String,
312}
313
314#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
315pub struct Language {
316 pub entity_urn: Option<String>,
317 pub name: String,
318 pub proficiency: Option<LanguageProficiency>,
319}
320
321#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
322pub enum LanguageProficiency {
323 #[serde(rename = "NATIVE_OR_BILINGUAL")]
324 NativeOrBilingual,
325 #[serde(rename = "FULL_PROFESSIONAL")]
326 FullProfessional,
327 #[serde(rename = "PROFESSIONAL_WORKING")]
328 ProfessionalWorking,
329 #[serde(rename = "LIMITED_WORKING")]
330 LimitedWorking,
331 #[serde(rename = "ELEMENTARY")]
332 Elementary,
333}
334
335#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
337#[serde(rename_all = "camelCase")]
338pub struct Experience {
339 pub entity_urn: Option<String>,
340 pub title: Option<String>,
341 pub company_name: Option<String>,
342 pub company_urn: Option<String>,
343 pub company: Option<CompanyInfo>,
344 pub description: Option<String>,
345 pub time_period: Option<TimePeriod>,
346 pub geo_location_name: Option<String>,
347 pub geo_urn: Option<String>,
348 pub location_name: Option<String>,
349 pub region: Option<String>,
350}
351
352impl Experience {
353 pub fn get_company_logo_url(&self) -> Option<Url> {
355 self.company
356 .as_ref()
357 .and_then(|company| company.mini_company.as_ref())
358 .and_then(|mini| mini.logo.as_ref())
359 .and_then(|container| container.vector_image.as_ref())
360 .and_then(|vector_image| {
361 if let (Some(root_url), Some(artifact)) =
362 (&vector_image.root_url, vector_image.artifacts.first())
363 {
364 let full_url = format!(
365 "{}{}",
366 root_url,
367 artifact
368 .file_identifying_url_path_segment
369 .as_deref()
370 .unwrap_or("")
371 );
372 Url::parse(&full_url).ok()
373 } else {
374 None
375 }
376 })
377 }
378
379 pub fn is_current(&self) -> bool {
381 self.time_period
382 .as_ref()
383 .map(|tp| tp.end_date.is_none())
384 .unwrap_or(false)
385 }
386}
387
388#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
389#[serde(rename_all = "camelCase")]
390pub struct CompanyInfo {
391 pub employee_count_range: Option<EmployeeCountRange>,
392 pub industries: Vec<String>,
393 pub mini_company: Option<MiniCompany>,
394}
395
396#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
397pub struct EmployeeCountRange {
398 pub start: u32,
399 pub end: u32,
400}
401
402#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
403#[serde(rename_all = "camelCase")]
404pub struct MiniCompany {
405 pub active: bool,
406 pub dash_company_urn: Option<String>,
407 pub entity_urn: Option<String>,
408 pub logo: Option<VectorImageContainer>,
409 pub name: String,
410 pub object_urn: String,
411 pub showcase: bool,
412 pub tracking_id: String,
413 pub universal_name: Option<String>,
414}
415
416#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
418#[serde(rename_all = "camelCase")]
419pub struct Education {
420 pub entity_urn: Option<String>,
421 pub school_name: Option<String>,
422 pub school_urn: Option<String>,
423 pub school: Option<SchoolInfo>,
424 pub degree_name: Option<String>,
425 pub degree_urn: Option<String>,
426 pub field_of_study: Option<String>,
427 pub field_of_study_urn: Option<String>,
428 pub activities: Option<String>,
429 pub description: Option<String>,
430 pub grade: Option<String>,
431 pub time_period: Option<TimePeriod>,
432 pub honors: Option<Vec<String>>,
433 pub test_scores: Option<Vec<String>>,
434}
435
436impl Education {
437 pub fn get_school_logo_url(&self) -> Option<Url> {
439 self.school
440 .as_ref()
441 .and_then(|school| school.logo.as_ref())
442 .and_then(|container| container.vector_image.as_ref())
443 .and_then(|vector_image| {
444 if let (Some(root_url), Some(artifact)) =
445 (&vector_image.root_url, vector_image.artifacts.first())
446 {
447 let full_url = format!(
448 "{}{}",
449 root_url,
450 artifact
451 .file_identifying_url_path_segment
452 .as_deref()
453 .unwrap_or("")
454 );
455 Url::parse(&full_url).ok()
456 } else {
457 None
458 }
459 })
460 }
461
462 pub fn get_activities_list(&self) -> Vec<String> {
464 self.activities
465 .as_ref()
466 .map(|activities| {
467 activities
468 .split('\n')
469 .filter_map(|activity| {
470 let trimmed = activity.trim().trim_start_matches("- ");
471 if trimmed.is_empty() {
472 None
473 } else {
474 Some(trimmed.to_string())
475 }
476 })
477 .collect()
478 })
479 .unwrap_or_default()
480 }
481}
482
483#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
484#[serde(rename_all = "camelCase")]
485pub struct SchoolInfo {
486 pub active: bool,
487 pub entity_urn: Option<String>,
488 pub logo: Option<VectorImageContainer>,
489 pub object_urn: String,
490 pub school_name: String,
491 pub tracking_id: String,
492}
493
494#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
496#[serde(rename_all = "camelCase")]
497pub struct TestScoreView {
498 pub elements: Vec<TestScore>,
499 pub entity_urn: Option<String>,
500 pub paging: Paging,
501 pub profile_id: String,
502}
503
504#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
505#[serde(rename_all = "camelCase")]
506pub struct TestScore {
507 pub entity_urn: Option<String>,
508 pub name: String,
509 pub score: String,
510 pub date: Option<YearMonth>,
511 pub description: Option<String>,
512 pub occupation: Option<String>,
513}
514
515#[derive(Debug, Default, Clone, PartialEq, Serialize, Deserialize)]
517pub struct ContactInfo {
518 pub email_address: Option<EmailAddress>,
519 pub websites: Vec<Website>,
520 pub twitter: Vec<String>,
521 pub phone_numbers: Vec<PhoneNumber>,
522 pub birthdate: Option<BirthDate>,
523 pub ims: Option<Vec<Value>>,
524}
525
526#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
527pub struct Website {
528 pub url: Option<Url>,
529 pub label: Option<String>,
530}
531
532#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
534#[serde(rename_all = "camelCase")]
535pub struct PositionGroupView {
536 pub elements: Vec<PositionGroup>,
537 pub entity_urn: Option<String>,
538 pub paging: Paging,
539 pub profile_id: String,
540}
541
542#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
543#[serde(rename_all = "camelCase")]
544pub struct PositionGroup {
545 pub entity_urn: Option<String>,
546 pub name: String,
547 pub mini_company: Option<MiniCompany>,
548 pub paging: Paging,
549 pub positions: Vec<Experience>,
550 pub time_period: Option<TimePeriod>,
551 pub region: Option<String>,
552}
553
554#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
556#[serde(rename_all = "camelCase")]
557pub struct PositionView {
558 pub elements: Vec<Experience>,
559 pub entity_urn: Option<String>,
560 pub paging: Paging,
561 pub profile_id: String,
562}
563
564#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
566#[serde(rename_all = "camelCase")]
567pub struct EducationView {
568 pub elements: Vec<Education>,
569 pub entity_urn: Option<String>,
570 pub paging: Paging,
571 pub profile_id: String,
572}
573
574#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
576#[serde(rename_all = "camelCase")]
577pub struct SkillView {
578 pub elements: Vec<Skill>,
579 pub entity_urn: Option<String>,
580 pub paging: Paging,
581 pub profile_id: String,
582}
583
584#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
585pub struct Skill {
586 pub entity_urn: Option<String>,
587 pub name: String,
588}
589
590#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
592#[serde(rename_all = "camelCase")]
593pub struct VolunteerExperienceView {
594 pub elements: Vec<VolunteerExperience>,
595 pub entity_urn: Option<String>,
596 pub paging: Paging,
597 pub profile_id: String,
598}
599
600#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
601#[serde(rename_all = "camelCase")]
602pub struct VolunteerExperience {
603 pub entity_urn: Option<String>,
604 pub role: String,
605 pub company_name: Option<String>,
606 pub company_urn: Option<String>,
607 pub company: Option<CompanyInfo>,
608 pub cause: Option<String>,
609 pub description: Option<String>,
610 pub time_period: Option<TimePeriod>,
611 pub region: Option<String>,
612}
613
614#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
616#[serde(rename_all = "camelCase")]
617pub struct VolunteerCauseView {
618 pub elements: Vec<VolunteerCause>,
619 pub entity_urn: Option<String>,
620 pub paging: Paging,
621 pub profile_id: String,
622}
623
624#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
625#[serde(rename_all = "camelCase")]
626pub struct VolunteerCause {
627 pub cause_name: String,
628 pub cause_type: String,
629}
630
631#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
633#[serde(rename_all = "camelCase")]
634pub struct OrganizationView {
635 pub elements: Vec<Value>,
636 pub entity_urn: Option<String>,
637 pub paging: Paging,
638 pub profile_id: String,
639}
640
641#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
642#[serde(rename_all = "camelCase")]
643pub struct PatentView {
644 pub elements: Vec<Value>,
645 pub entity_urn: Option<String>,
646 pub paging: Paging,
647 pub profile_id: String,
648}
649
650#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
652#[serde(rename_all = "camelCase")]
653pub struct ProjectView {
654 pub elements: Vec<Project>,
655 pub entity_urn: Option<String>,
656 pub paging: Paging,
657 pub profile_id: String,
658}
659
660#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
661#[serde(rename_all = "camelCase")]
662pub struct Project {
663 pub entity_urn: Option<String>,
664 pub title: Option<String>,
665 pub description: Option<String>,
666 pub members: Vec<ProjectMember>,
667 pub time_period: Option<TimePeriod>,
668}
669
670#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
671#[serde(rename_all = "camelCase")]
672pub struct ProjectMember {
673 pub entity_urn: Option<String>,
674 pub profile_urn: Option<String>,
675 pub member: Option<MiniProfile>,
676}
677
678#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
679#[serde(rename_all = "camelCase")]
680pub struct PublicationView {
681 pub elements: Vec<Value>,
682 pub entity_urn: Option<String>,
683 pub paging: Paging,
684 pub profile_id: String,
685}
686
687#[derive(Debug, PartialEq, Clone, Serialize, Deserialize)]
688#[serde(rename_all = "camelCase")]
689pub struct Location {
690 pub basic_location: Option<BasicLocation>,
691}
692
693#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
694#[serde(rename_all = "camelCase")]
695pub struct BasicLocation {
696 pub country_code: Option<String>,
697 pub postal_code: Option<String>,
698}
699
700#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
701#[serde(rename_all = "camelCase")]
702pub struct MiniProfile {
703 pub dash_entity_urn: Option<String>,
704 pub entity_urn: Option<String>,
705 pub object_urn: Option<String>,
706 pub public_identifier: Option<String>,
707 pub first_name: Option<String>,
708 pub last_name: Option<String>,
709 pub occupation: Option<String>,
710 pub tracking_id: Option<String>,
711 pub picture: Option<VectorImageContainer>,
712}
713
714#[derive(Debug, Clone, PartialEq, Default, Serialize, Deserialize)]
715#[serde(rename_all = "camelCase")]
716pub struct ProfilePicture {
717 pub display_image: Option<String>,
718 pub original_image: Option<String>,
719 pub photo_filter_edit_info: Option<PhotoFilterEditInfo>,
720}
721
722#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
723#[serde(rename_all = "camelCase")]
724pub struct PhotoFilterEditInfo {
725 pub top_left: Option<Point>,
726 pub top_right: Option<Point>,
727 pub bottom_left: Option<Point>,
728 pub bottom_right: Option<Point>,
729 pub brightness: Option<f32>,
730 pub contrast: Option<f32>,
731 pub saturation: Option<f32>,
732 pub vignette: Option<f32>,
733 pub photo_filter_type: Option<String>,
734}
735
736#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
737#[serde(rename_all = "camelCase")]
738pub struct Point {
739 pub x: f32,
740 pub y: f32,
741}
742
743#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
744#[serde(rename_all = "camelCase")]
745pub struct VectorImageContainer {
746 pub vector_image: Option<VectorImage>,
747}
748
749#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
750#[serde(rename_all = "camelCase")]
751pub struct VectorImage {
752 pub root_url: Option<String>,
753 pub artifacts: Vec<ImageArtifact>,
754}
755
756#[derive(Debug, PartialEq, Clone, Default, Serialize, Deserialize)]
757#[serde(rename_all = "camelCase")]
758pub struct ImageArtifact {
759 pub height: u32,
760 pub width: u32,
761 pub expires_at: Option<u64>,
762 pub file_identifying_url_path_segment: Option<String>,
763}
764
765#[derive(Debug, PartialEq, Serialize, Clone, Deserialize)]
766pub struct TimePeriod {
767 pub start_date: Option<YearMonth>,
768 pub end_date: Option<YearMonth>,
769}
770
771#[derive(Debug, PartialEq, Clone)]
772pub struct YearMonth {
773 pub year: i32,
774 pub month: Month,
775}
776
777impl Serialize for YearMonth {
778 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
779 where
780 S: Serializer,
781 {
782 use serde::ser::SerializeStruct;
783
784 let mut s = serializer.serialize_struct("YearMonth", 2)?;
785 s.serialize_field("year", &self.year)?;
786 s.serialize_field("month", &(self.month as u8))?;
787 s.end()
788 }
789}
790
791impl<'de> Deserialize<'de> for YearMonth {
792 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
793 where
794 D: Deserializer<'de>,
795 {
796 #[derive(Deserialize)]
797 struct Raw {
798 year: i32,
799 month: u8,
800 }
801
802 let raw = Raw::deserialize(deserializer)?;
803 let month = Month::try_from(raw.month)
804 .map_err(|_| serde::de::Error::custom("invalid month value"))?;
805
806 Ok(YearMonth {
807 year: raw.year,
808 month,
809 })
810 }
811}
812
813#[derive(Debug, Clone, Serialize, Deserialize)]
814pub struct Connection {
815 pub urn_id: String,
816 pub public_id: String,
817 pub distance: String,
818}
819#[derive(Debug, Clone, Serialize, Deserialize)]
820pub struct MemberBadges {
821 pub premium: bool,
822 pub open_link: bool,
823 pub influencer: bool,
824 pub job_seeker: bool,
825}
826#[derive(Debug, Clone, Serialize, Deserialize)]
827pub struct PersonSearchResult {
828 pub urn_id: String,
829 pub public_id: String,
830 pub distance: String,
831}
832
833#[derive(Debug, Clone, Serialize, Deserialize)]
834pub struct Invitation {
835 pub entity_urn: Option<String>,
836 pub shared_secret: String,
837}
838
839pub struct UniformResourceName {
840 pub namespace: String, pub id: String,
842}
843
844#[derive(Debug, Clone, Serialize, Deserialize)]
845pub struct NetworkInfo {
846 pub followers_count: u64,
847}
848
849#[derive(Debug, Clone, Serialize, Deserialize)]
850pub struct School {
851 pub name: String,
852}
853
854#[derive(Debug, Clone, Serialize, Deserialize)]
855pub struct Company {
856 pub name: String,
857}
858
859#[derive(Debug, Clone, Serialize, Deserialize)]
860pub struct Conversation {
861 pub id: String,
862}
863
864#[derive(Debug, Clone, Serialize, Deserialize)]
865pub struct ConversationDetails {
866 pub id: String,
867}
868
869#[derive(Debug, Clone, Default)]
871pub struct SearchPeopleParams {
872 pub keywords: Option<String>,
873 pub connection_of: Option<String>,
874 pub network_depth: Option<String>,
875 pub current_company: Option<Vec<String>>,
876 pub past_companies: Option<Vec<String>>,
877 pub nonprofit_interests: Option<Vec<String>>,
878 pub profile_languages: Option<Vec<String>>,
879 pub regions: Option<Vec<String>>,
880 pub industries: Option<Vec<String>>,
881 pub schools: Option<Vec<String>>,
882 pub include_private_profiles: bool,
883 pub limit: Option<usize>,
884}