use std::sync::Arc;
use claviron::orbit::Counter;
use pyo3::exceptions::{PyRuntimeError, PyValueError};
use pyo3::prelude::*;
#[pyclass(name = "Counter", module = "claviron", frozen)]
pub(crate) struct PythonCounter {
table: Arc<Counter>,
key: String,
}
impl PythonCounter {
pub(crate) fn new(
table: Arc<Counter>,
key: String,
) -> Self {
Self { table, key }
}
}
#[pymethods]
impl PythonCounter {
#[getter]
fn key(&self) -> &str {
&self.key
}
fn get(&self) -> PyResult<Option<i64>> {
self.table.get(&self.key).map_err(error)
}
#[pyo3(signature = (by = 1))]
fn increment(
&self,
by: i64,
) -> PyResult<i64> {
self.table.increment(&self.key, by).map_err(error)
}
#[pyo3(signature = (by = 1))]
fn decrement(
&self,
by: i64,
) -> PyResult<i64> {
self.table.decrement(&self.key, by).map_err(error)
}
fn reset(&self) -> PyResult<()> {
self.table.reset(&self.key).map_err(error)
}
fn __repr__(&self) -> String {
match self.table.get(&self.key) {
Ok(Some(value)) => {
format!("claviron.counter({:?}) = {value}", self.key)
}
_ => format!("claviron.counter({:?})", self.key),
}
}
}
fn error(error: claviron::orbit::counter::Error) -> PyErr {
use claviron::orbit::counter::Error;
match error {
Error::KeyEmpty
| Error::KeyTooLarge { .. }
| Error::NegativeAmount(_) => PyValueError::new_err(error.to_string()),
_ => PyRuntimeError::new_err(error.to_string()),
}
}
#[pyclass(module = "claviron", frozen)]
pub(crate) struct Counters {
table: Arc<Counter>,
}
impl Counters {
pub(crate) fn new(table: Arc<Counter>) -> Self {
Self { table }
}
}
#[pymethods]
impl Counters {
fn counter(
&self,
key: String,
) -> PyResult<PythonCounter> {
self.table.get(&key).map_err(error)?;
Ok(PythonCounter::new(Arc::clone(&self.table), key))
}
}