open_library/
models.rs

1use crate::models::identifiers::OpenLibraryIdentifier;
2use serde::de::Error;
3use serde::{Deserialize, Deserializer, Serialize, Serializer};
4use std::fmt::{Display, Formatter};
5use std::str::FromStr;
6
7pub mod account;
8pub mod authors;
9pub mod books;
10pub mod identifiers;
11pub mod works;
12
13#[cfg(test)]
14mod tests;
15
16#[derive(Clone, Debug, Eq, PartialEq)]
17pub enum OpenLibraryResource {
18    Author(String),
19    Book(String),
20    Work(String),
21}
22
23impl OpenLibraryResource {
24    pub fn value(&self) -> String {
25        match self {
26            OpenLibraryResource::Author(value) => value,
27            OpenLibraryResource::Book(value) => value,
28            OpenLibraryResource::Work(value) => value,
29        }
30        .clone()
31    }
32}
33
34impl Display for OpenLibraryResource {
35    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
36        let x = match self {
37            OpenLibraryResource::Author(value) => format!("/authors/{}", value),
38            OpenLibraryResource::Book(value) => format!("/books/{}", value),
39            OpenLibraryResource::Work(value) => format!("/works/{}", value),
40        };
41
42        write!(f, "{}", x)?;
43        Ok(())
44    }
45}
46
47impl<'de> Deserialize<'de> for OpenLibraryResource {
48    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
49    where
50        D: Deserializer<'de>,
51    {
52        let value: String = Deserialize::deserialize(deserializer).map_err(D::Error::custom)?;
53
54        let chunks = value
55            .split('/')
56            .filter(|str| !str.is_empty())
57            .collect::<Vec<&str>>();
58
59        let resource = match chunks.get(0) {
60            Some(string) => Ok(*string),
61            None => Err(D::Error::custom(format!(
62                "Supplied identifier string has improper format {}",
63                &value
64            ))),
65        }?;
66
67        let identifier = match chunks.get(1) {
68            Some(string) => Ok(*string),
69            None => Err(D::Error::custom(format!(
70                "Supplied identifier string has improper format {}",
71                &value
72            ))),
73        }?;
74
75        match resource {
76            "authors" => Ok(OpenLibraryResource::Author(identifier.to_string())),
77            "books" => Ok(OpenLibraryResource::Book(identifier.to_string())),
78            "works" => Ok(OpenLibraryResource::Work(identifier.to_string())),
79            _ => Err(D::Error::custom("Could not parse into Resource")),
80        }
81    }
82}
83
84impl Serialize for OpenLibraryResource {
85    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86    where
87        S: Serializer,
88    {
89        serializer.serialize_str(self.to_string().as_str())
90    }
91}
92
93impl From<OpenLibraryResource> for OpenLibraryIdentifier {
94    fn from(resource: OpenLibraryResource) -> Self {
95        Self::from_str(&resource.value()).unwrap()
96    }
97}
98
99#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
100pub struct Link {
101    #[serde(skip_serializing_if = "String::is_empty")]
102    url: String,
103    #[serde(skip_serializing_if = "String::is_empty")]
104    title: String,
105}
106
107#[derive(Clone, Deserialize, Debug, Eq, Hash, PartialEq, Serialize)]
108#[serde(rename_all = "lowercase")]
109pub enum LinkName {
110    Author,
111    #[serde(rename = "self")]
112    Itself,
113    Next,
114}
115
116pub trait OpenLibraryModel {}