reticulum-pyrs 0.1.0

A rust wrapper for the python rns and lxmf libraries
Documentation
use anyhow::{Result, anyhow};
use log::{error, info};
use pyo3::prelude::*;
use std::fmt::{Debug, Display, LowerHex};

#[derive(Clone, Copy, FromPyObject, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct LongHash([u8; 32]);

impl LongHash {
    /// Create a new LongHash from a slice. The slice must be of size 32, or it will error.
    pub fn new(b: &[u8]) -> Result<Self> {
        if b.len() == 32 {
            let mut buf = [0; 32];
            buf.copy_from_slice(b);
            Ok(Self(buf))
        } else {
            Err(anyhow!("Slice should be 32 bytes long!"))
        }
    }

    pub fn from_hex_str(hex: &str) -> Result<Self> {
        let hash = hex::decode(hex)?;
        if hash.len() == 32 {
            let mut bytes: [u8; 32] = [0; 32];
            bytes.copy_from_slice(&hash[..32]);
            Ok(Self(bytes))
        } else {
            Err(anyhow!(
                "hex string is wrong length -- it should be 32 bytes (64 ascii chars)"
            ))
        }
    }

    pub fn tiny_hash(&self) -> String {
        format!("{self:x}")[..7].to_string()
    }

    pub fn value(&self) -> [u8; 32] {
        self.0
    }
}

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

impl Debug for LongHash {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{self:x}")
    }
}

impl LowerHex for LongHash {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let hex = hex::encode(self.0);
        write!(f, "{hex}")?;
        Ok(())
    }
}

#[derive(Clone, Copy, FromPyObject, PartialEq, Eq, Hash, PartialOrd, Ord)]
pub struct ShortHash([u8; 16]);

impl ShortHash {
    /// Create a new LongHash from a slice. The slice should be of size 16, or it will error.
    pub fn new(b: &[u8]) -> Result<Self> {
        if b.len() == 16 {
            let mut buf = [0; 16];
            buf.copy_from_slice(b);
            Ok(Self(buf))
        } else {
            Err(anyhow!("Slice should be 16 bytes long!"))
        }
    }

    pub fn from_hex_str(hex: &str) -> Result<Self> {
        let hash = hex::decode(hex)?;
        if hash.len() == 16 {
            let mut bytes: [u8; 16] = [0; 16];
            bytes.copy_from_slice(&hash[..16]);
            Ok(Self(bytes))
        } else {
            Err(anyhow!(
                "hex string is wrong length -- it should be 16 bytes (32 ascii chars)"
            ))
        }
    }

    pub fn tiny_hash(&self) -> String {
        format!("{self:x}")[..7].to_string()
    }

    pub fn value(&self) -> [u8; 16] {
        self.0
    }
}

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

impl Debug for ShortHash {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{self:x}")
    }
}

impl LowerHex for ShortHash {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        let hex = hex::encode(self.0);
        write!(f, "{hex}")?;
        Ok(())
    }
}

#[pyclass]
pub(crate) struct StdOutLog;

#[pymethods]
impl StdOutLog {
    pub(crate) fn write(&self, data: &str) {
        let data = data.trim();
        if !data.is_empty() {
            info!("python: {data:?}");
        }
    }
}

#[pyclass]
pub(crate) struct StdErrLog;

#[pymethods]
impl StdErrLog {
    pub(crate) fn write(&self, data: &str) {
        let data = data.trim();
        if !data.is_empty() {
            error!("python: {data:?}");
        }
    }
}