use crate::cap::{Auth, Cap};
use crate::error::{BotError, DispatchCertainty};
use crate::stability::{ReadFailure, read_stable_file};
use crate::verb;
#[derive(Debug)]
pub struct JsonStore {
path: std::path::PathBuf,
caps: Vec<Cap>,
}
#[derive(PartialEq, Debug, Clone)]
#[non_exhaustive]
pub struct DataState {
changed: bool,
raw: String,
}
impl DataState {
#[must_use]
pub fn new(changed: bool, raw: impl Into<String>) -> Self {
Self {
changed,
raw: raw.into(),
}
}
#[must_use]
pub fn changed(&self) -> bool {
self.changed
}
#[must_use]
pub fn raw(&self) -> &str {
&self.raw
}
}
impl JsonStore {
pub fn new(path: impl Into<std::path::PathBuf>) -> Self {
Self {
path: path.into(),
caps: vec![Cap::fs()],
}
}
}
impl verb::Observe for JsonStore {
type Output = DataState;
fn required_caps(&self) -> &[Cap] {
&self.caps
}
async fn poll(&self, call: (Auth, ())) -> Result<DataState, BotError> {
call.0.check(self.required_caps())?;
let path = self.path.clone();
let domain = self.domain_id().to_owned();
let reading = read_stable_file(&path)
.await
.map_err(|failure| match failure {
ReadFailure::Unstable(unstable) => {
BotError::UnstableObservation { domain, unstable }
}
ReadFailure::Unreadable { cause } => BotError::DomainError {
domain,
certainty: DispatchCertainty::NotDelivered,
cause: cause.to_string(),
},
})?;
let raw = String::from_utf8(reading.bytes().to_vec()).map_err(|error| {
let refusal = BotError::DomainError {
domain: self.domain_id().to_owned(),
certainty: DispatchCertainty::NotDelivered,
cause: error.to_string(),
};
lgwks_std::trace::debug!(
error = ?Some(&refusal),
"poll: returning an error to the caller"
);
refusal
})?;
Ok(DataState::new(false, raw))
}
fn domain_id(&self) -> &str {
"data::json_store"
}
}
impl verb::Query for JsonStore {
type Input = ();
type Output = DataState;
fn required_caps(&self) -> &[Cap] {
&self.caps
}
async fn query(&self, call: (Auth, &())) -> Result<DataState, BotError> {
let (auth, _) = call;
verb::Observe::poll(self, (auth, ())).await
}
fn domain_id(&self) -> &str {
"data::json_store"
}
}
pub fn json_store(path: impl Into<std::path::PathBuf>) -> JsonStore {
JsonStore::new(path)
}