llama-server 0.1.1

Download, embed, and run llama.cpp in your Rust projects
Documentation
use crate::Error;
use crate::http;

use std::fmt;
use std::io;
use std::str::FromStr;

const REPOSITORY: &str = "hecrj/llama-server";

/// A specific build of `llama-server`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Build(u32);

impl Build {
    /// Fetches the latest available [`Build`].
    pub async fn latest() -> Result<Self, Error> {
        use serde::Deserialize;

        #[derive(Deserialize)]
        struct Release {
            tag_name: String,
        }

        let client = http::client();

        let latest_release_url =
            format!("https://api.github.com/repos/{REPOSITORY}/releases/latest");

        let Release { tag_name } = client
            .get(latest_release_url)
            .send()
            .await?
            .error_for_status()?
            .json()
            .await?;

        Ok(tag_name.parse()?)
    }

    /// Creates a new [`Build`] locked to the given number.
    pub fn locked(number: u32) -> Self {
        Self(number)
    }

    /// Returns the number of the [`Build`].
    pub fn number(self) -> u32 {
        self.0
    }

    pub(crate) fn url(self) -> String {
        format!("https://github.com/{REPOSITORY}/releases/download/{self}")
    }
}

impl FromStr for Build {
    type Err = io::Error;

    fn from_str(build: &str) -> Result<Self, Self::Err> {
        if !build.starts_with('b') {
            return Err(io::Error::other(format!("invalid build: {build}")));
        }

        build
            .trim_start_matches('b')
            .parse()
            .map(Self)
            .map_err(io::Error::other)
    }
}

impl fmt::Display for Build {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "b{}", self.0)
    }
}