1use crate::api_models::*;
2use thiserror::Error;
3use serde::{Serialize, Deserialize};
4
5pub type Result<A> = std::result::Result<A, ClassifyError>;
6
7#[derive(Debug, PartialEq)]
8pub enum ClassifyResult {
9 SingleWorkSummary(Box<SingleWorkSummary>),
10 MultiWork(MultiWork),
12}
13
14#[derive(Error, Debug)]
15pub enum ClassifyError {
16 #[error("No input. The method requires an input argument.")]
17 NoInput,
18 #[error("Invalid input. The standard number argument is invalid.")]
19 InvalidInput,
20 #[error("Unexpected error.")]
21 UnexpectedError,
22 #[error("Unexpected response code.")]
23 UnexpectedResponseCode,
24 #[error("Parsing Error: {0}")]
25 XmlParsingError(#[from] serde_xml_rs::Error),
26 #[error("Network Error: {0}")]
27 IoError(#[from] reqwest::Error),
28}
29
30#[derive(Debug, Default, PartialEq, Serialize, Deserialize)]
31pub struct ClassificationRecommendation {
32 most_popular: Vec<String>,
33 most_recent: Vec<String>,
34 latest_edition: Vec<String>,
35}
36
37#[derive(Debug, PartialEq, Serialize, Deserialize)]
38pub struct Recommendations {
39 pub dewie_decimal: ClassificationRecommendation,
40 pub library_of_congress: ClassificationRecommendation,
41}
42
43#[derive(Debug, PartialEq, Serialize, Deserialize)]
44pub struct SingleWorkSummary {
45 pub work: Work,
46 pub recommendations: Recommendations,
47}
48
49#[derive(Debug, PartialEq, Serialize, Deserialize)]
50pub struct MultiWork {
51 pub works: Vec<Work>,
52}
53
54fn push_if_some<A>(c: &mut Vec<A>, opts: Vec<Option<A>>) {
55 for opt in opts.into_iter().flatten() {
56 c.push(opt)
57 }
58}
59
60impl From<crate::api_models::RecommendationDataHolder> for ClassificationRecommendation {
61 fn from(recommendations: crate::api_models::RecommendationDataHolder) -> Self {
62 let mut result = ClassificationRecommendation::default();
63 for recommendation in recommendations.recommendations {
64 match recommendation {
65 RecommendationData::MostPopular(most_popular) => push_if_some(
66 &mut result.most_popular,
67 vec![most_popular.nsfa, most_popular.sfa],
68 ),
69 RecommendationData::MostRecent(most_recent) => push_if_some(
70 &mut result.most_recent,
71 vec![most_recent.nsfa, most_recent.sfa],
72 ),
73 RecommendationData::LatestEdition(latest_edition) => push_if_some(
74 &mut result.latest_edition,
75 vec![latest_edition.nsfa, latest_edition.sfa],
76 ),
77 }
78 }
79 result
80 }
81}
82
83impl From<crate::api_models::Recommendations> for Recommendations {
84 fn from(recommendations: crate::api_models::Recommendations) -> Self {
85 Recommendations {
86 dewie_decimal: recommendations.ddc.into(),
87 library_of_congress: recommendations.lcc.into(),
88 }
89 }
90}
91
92impl From<Classify> for SingleWorkSummary {
93 fn from(classify: Classify) -> Self {
94 SingleWorkSummary {
95 work: classify.work.unwrap(),
96 recommendations: classify.recommendations.unwrap().into(),
97 }
98 }
99}
100
101impl From<Classify> for MultiWork {
102 fn from(classify: Classify) -> Self {
103 MultiWork {
104 works: classify.works.unwrap().works,
105 }
106 }
107}
108
109impl From<Classify> for Result<Option<ClassifyResult>> {
110 fn from(classify: Classify) -> Self {
111 match classify.response.code {
112 100 => Err(ClassifyError::NoInput),
113 101 => Err(ClassifyError::InvalidInput),
114 102 => Ok(None),
115 0 => Ok(Some(ClassifyResult::SingleWorkSummary(Box::new(
116 classify.into(),
117 )))),
118 4 => Ok(Some(ClassifyResult::MultiWork(classify.into()))),
119 _ => Err(ClassifyError::UnexpectedResponseCode),
120 }
121 }
122}