Radish alpha
r
rad:z39mP9rQAaGmERfUMPULfPUi473tY
Radicle terminal user interface
Radicle
Git
radicle-tui bin state.rs
use std::path::PathBuf;
use std::{fmt::Display, fs};

use anyhow::Result;

use serde::{Deserialize, Serialize};

use radicle::cob::ObjectId;
use radicle::identity::RepoId;

use crate::settings;

/// Converts bytes to a deserializable type.
pub fn from_json<'a, D>(bytes: &'a [u8]) -> Result<D>
where
    D: Deserialize<'a>,
{
    Ok(serde_json::from_slice(bytes)?)
}

/// Converts serializable type to bytes.
pub fn to_json<S>(state: S) -> Result<Vec<u8>>
where
    S: Serialize,
{
    Ok(serde_json::to_vec(&state)?)
}

/// Trait for state readers.
pub trait ReadState {
    fn read(&self) -> Result<Vec<u8>>;
}

/// Trait for state writers.
pub trait WriteState: ReadState {
    fn write(&self, bytes: &[u8]) -> Result<()>;
}

/// A state storage that reads from and writes to a file.
pub struct FileStore {
    path: PathBuf,
}

impl FileStore {
    pub fn new(filename: impl ToString) -> Result<Self, anyhow::Error> {
        match settings::get_state_path() {
            Ok(path) => {
                fs::create_dir_all(path.clone())?;
                Ok(Self {
                    path: PathBuf::from(format!(
                        "{}/{}.json",
                        path.to_string_lossy(),
                        filename.to_string()
                    )),
                })
            }
            Err(err) => Err(anyhow::Error::from(err)),
        }
    }
}

impl ReadState for FileStore {
    fn read(&self) -> Result<Vec<u8>> {
        let path = PathBuf::from(&self.path);

        Ok(fs::read(path)?)
    }
}

impl WriteState for FileStore {
    fn write(&self, contents: &[u8]) -> Result<()> {
        let path = PathBuf::from(&self.path);

        Ok(fs::write(path, contents)?)
    }
}

pub struct FileIdentifier {
    id: String,
}

impl FileIdentifier {
    pub fn new(command: &str, operation: &str, rid: &RepoId, id: Option<&ObjectId>) -> Self {
        let id = match id {
            Some(id) => format!("{command}-{operation}-{rid}-{id}"),
            _ => format!("{command}-{operation}-{rid}"),
        };
        let id = format!("{:x}", md5::compute(id));

        Self { id }
    }
}

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