claude-api 0.5.3

Type-safe Rust client for the Anthropic API
Documentation
//! Build-time code generation for bundled pricing rates.
//!
//! Reads `pricing.toml` and emits `$OUT_DIR/pricing_data.rs` with a
//! `bundled_rates()` function returning a `Vec<(ModelId, ModelPricing)>`.
//! `pricing.rs` includes the generated file when the `pricing` feature
//! is enabled.

use std::env;
use std::fmt::Write as _;
use std::fs;
use std::path::PathBuf;

#[derive(serde::Deserialize)]
struct Manifest {
    models: Vec<ModelEntry>,
}

#[derive(serde::Deserialize)]
struct ModelEntry {
    id: String,
    input_per_mtok: f64,
    output_per_mtok: f64,
    web_search_per_request: f64,
    cache_creation_5m_per_mtok: Option<f64>,
    cache_creation_1h_per_mtok: Option<f64>,
    cache_read_per_mtok: Option<f64>,
}

fn main() {
    println!("cargo:rerun-if-changed=pricing.toml");
    println!("cargo:rerun-if-changed=build.rs");

    let toml_text =
        fs::read_to_string("pricing.toml").expect("build.rs: failed to read pricing.toml");
    let manifest: Manifest =
        toml::from_str(&toml_text).expect("build.rs: failed to parse pricing.toml");

    let mut out = String::new();
    out.push_str("// Generated by build.rs from pricing.toml. Do not edit.\n");
    // FP arithmetic on cache multipliers can produce values like
    // 0.30000000000000004; clippy's unreadable_literal complains. Allow
    // it here -- the generated file is opaque to users.
    out.push_str("#[allow(clippy::unreadable_literal)]\n");
    out.push_str("pub(crate) fn bundled_rates() -> Vec<(crate::types::ModelId, crate::pricing::ModelPricing)> {\n");
    out.push_str("    vec![\n");

    for m in &manifest.models {
        let cache_short = m
            .cache_creation_5m_per_mtok
            .unwrap_or(m.input_per_mtok * 1.25);
        let cache_long = m
            .cache_creation_1h_per_mtok
            .unwrap_or(m.input_per_mtok * 2.0);
        let cache_read = m.cache_read_per_mtok.unwrap_or(m.input_per_mtok * 0.1);

        writeln!(
            out,
            "        (\n            crate::types::ModelId::from(\"{id}\"),\n            crate::pricing::ModelPricing {{\n                input_per_mtok: {input}_f64,\n                output_per_mtok: {output}_f64,\n                cache_creation_5m_per_mtok: {c5m}_f64,\n                cache_creation_1h_per_mtok: {c1h}_f64,\n                cache_read_per_mtok: {cr}_f64,\n                web_search_per_request: {ws}_f64,\n            }},\n        ),",
            id = m.id,
            input = m.input_per_mtok,
            output = m.output_per_mtok,
            c5m = cache_short,
            c1h = cache_long,
            cr = cache_read,
            ws = m.web_search_per_request,
        )
        .expect("write to String never fails");
    }

    out.push_str("    ]\n");
    out.push_str("}\n");

    let out_dir: PathBuf = env::var_os("OUT_DIR")
        .expect("build.rs: OUT_DIR not set")
        .into();
    let dest = out_dir.join("pricing_data.rs");
    fs::write(&dest, out).expect("build.rs: failed to write pricing_data.rs");
}