romm-cli 0.22.0

Rust-based CLI and TUI for the ROMM API
Documentation
use crate::types::RomList;

use super::Endpoint;

/// Retrieve ROMs with optional filters.
#[derive(Debug, Default, Clone)]
pub struct GetRoms {
    pub search_term: Option<String>,
    pub platform_id: Option<u64>,
    /// Manual collection filter (`GET /api/roms?collection_id=`).
    pub collection_id: Option<u64>,
    /// Smart collection filter (`GET /api/roms?smart_collection_id=`).
    pub smart_collection_id: Option<u64>,
    /// Virtual (autogenerated) collection filter (`GET /api/roms?virtual_collection_id=`).
    pub virtual_collection_id: Option<String>,
    pub limit: Option<u32>,
    pub offset: Option<u32>,
}

impl Endpoint for GetRoms {
    type Output = RomList;

    fn method(&self) -> &'static str {
        "GET"
    }

    fn path(&self) -> String {
        "/api/roms".into()
    }

    fn query(&self) -> Vec<(String, String)> {
        let mut q = Vec::new();

        if let Some(term) = &self.search_term {
            q.push(("search_term".into(), term.clone()));
        }

        // RomM API expects "platform_ids" (plural); repeat param for multiple values.
        if let Some(pid) = self.platform_id {
            q.push(("platform_ids".into(), pid.to_string()));
        }

        if let Some(cid) = self.collection_id {
            q.push(("collection_id".into(), cid.to_string()));
        }

        if let Some(sid) = self.smart_collection_id {
            q.push(("smart_collection_id".into(), sid.to_string()));
        }

        if let Some(ref vid) = self.virtual_collection_id {
            q.push(("virtual_collection_id".into(), vid.clone()));
        }

        if let Some(limit) = self.limit {
            q.push(("limit".into(), limit.to_string()));
        }

        if let Some(offset) = self.offset {
            q.push(("offset".into(), offset.to_string()));
        }

        q
    }
}

/// Retrieve a single ROM by ID.
#[derive(Debug, Clone)]
pub struct GetRom {
    pub id: u64,
}

impl Endpoint for GetRom {
    type Output = crate::types::Rom;

    fn method(&self) -> &'static str {
        "GET"
    }

    fn path(&self) -> String {
        format!("/api/roms/{}", self.id)
    }
}

#[cfg(test)]
mod tests {
    use super::{Endpoint, GetRoms};

    #[test]
    fn get_roms_query_sends_collection_id() {
        let ep = GetRoms {
            collection_id: Some(7),
            limit: Some(100),
            ..Default::default()
        };
        let q = ep.query();
        assert!(q.iter().any(|(k, v)| k == "collection_id" && v == "7"));
        assert!(!q.iter().any(|(k, _)| k == "smart_collection_id"));
    }

    #[test]
    fn get_roms_query_sends_smart_collection_id() {
        let ep = GetRoms {
            smart_collection_id: Some(3),
            limit: Some(50),
            ..Default::default()
        };
        let q = ep.query();
        assert!(q
            .iter()
            .any(|(k, v)| k == "smart_collection_id" && v == "3"));
        assert!(!q.iter().any(|(k, _)| k == "collection_id"));
        assert!(!q.iter().any(|(k, _)| k == "virtual_collection_id"));
    }

    #[test]
    fn get_roms_query_sends_virtual_collection_id() {
        let ep = GetRoms {
            virtual_collection_id: Some("recent".into()),
            limit: Some(10),
            ..Default::default()
        };
        let q = ep.query();
        assert!(q
            .iter()
            .any(|(k, v)| k == "virtual_collection_id" && v == "recent"));
        assert!(!q.iter().any(|(k, _)| k == "collection_id"));
    }
}