open-library-api-rs 0.1.0

Async Rust client for the Open Library API
Documentation
// v0.0.1
use url::Url;

use crate::client::OpenLibraryClient;
use crate::error::Result;
use crate::models::common::{CoverKey, ImageSize};
use crate::models::covers::CoverMeta;
use crate::validation::validate_author_id;

impl OpenLibraryClient {
    /// Build a cover image URL without making an HTTP request.
    ///
    /// Example: `cover_url(CoverKey::Id, "5428012", ImageSize::Large)`
    /// → `https://covers.openlibrary.org/b/id/5428012-L.jpg`
    pub fn cover_url(&self, key: CoverKey, value: &str, size: ImageSize) -> Url {
        let path = format!(
            "b/{}/{}-{}.jpg",
            key.as_str(),
            value,
            size.as_str()
        );
        // Parsing here is safe because we control all components.
        self.covers_url.join(&path).expect("cover URL construction failed")
    }

    /// Build an author photo URL without making an HTTP request.
    ///
    /// `olid` must be a valid author OLID (e.g. `"OL23919A"`).
    pub fn author_photo_url(&self, olid: &str, size: ImageSize) -> Result<Url> {
        validate_author_id(olid)?;
        let path = format!("a/olid/{olid}-{}.jpg", size.as_str());
        Ok(self.covers_url.join(&path).expect("author photo URL construction failed"))
    }

    /// Fetch JSON metadata for a cover image.
    ///
    /// Note: the covers API returns an object whose single key is the bibkey.
    pub async fn cover_meta(
        &self,
        key: CoverKey,
        value: &str,
    ) -> Result<Vec<CoverMeta>> {
        let path = format!("b/{}/{}.json", key.as_str(), value);
        let url = self.covers_url.join(&path)?;
        // The response is { "KEY:VALUE": [...] } — we extract the inner array.
        let raw: serde_json::Value = self.get_covers_json(url).await?;
        let metas: Vec<CoverMeta> = raw
            .as_object()
            .and_then(|m| m.values().next())
            .and_then(|v| serde_json::from_value(v.clone()).ok())
            .unwrap_or_default();
        Ok(metas)
    }
}