steam-cli 0.1.0

Local-first Steam CLI for tags, search, app details, and user library data.
use serde::Serialize;

use crate::cli::OutputFormat;
use crate::error::AppError;
use crate::models::{DataSource, Envelope, ErrorBody, Meta, Pagination};

pub fn clamp_limit(limit: usize) -> usize {
    limit.clamp(1, 100)
}

pub fn build_pagination(
    limit: usize,
    offset: usize,
    returned: usize,
    total: Option<usize>,
) -> Pagination {
    let has_more = match total {
        Some(t) => offset.saturating_add(returned) < t,
        None => returned == limit,
    };
    Pagination {
        limit,
        offset,
        returned,
        has_more,
        total,
    }
}

pub fn print_success<T: Serialize>(
    format: OutputFormat,
    data: T,
    pagination: Option<Pagination>,
    source: DataSource,
    cached: bool,
    human: impl FnOnce(&T),
) {
    match format {
        OutputFormat::Human => human(&data),
        OutputFormat::Json => {
            let envelope = Envelope {
                ok: true,
                data: Some(data),
                pagination,
                meta: Meta {
                    version: "1.0.0",
                    source,
                    cached,
                },
                error: None,
            };
            println!(
                "{}",
                serde_json::to_string_pretty(&envelope).unwrap_or_else(|_| "{}".to_string())
            );
        }
    }
}

pub fn print_error(format: OutputFormat, error: AppError) {
    match format {
        OutputFormat::Human => {
            eprintln!("Error [{}]: {}", error.code(), error);
        }
        OutputFormat::Json => {
            let envelope: Envelope<serde_json::Value> = Envelope {
                ok: false,
                data: None,
                pagination: None,
                meta: Meta {
                    version: "1.0.0",
                    source: DataSource::Internal,
                    cached: false,
                },
                error: Some(ErrorBody {
                    code: error.code(),
                    message: error.to_string(),
                }),
            };
            eprintln!(
                "{}",
                serde_json::to_string_pretty(&envelope).unwrap_or_else(|_| "{}".to_string())
            );
        }
    }
}