use std::sync::Arc;
use dwn_core::{
message::{Message, descriptor::Descriptor},
reply::Reply,
store::{DataStore, RecordStore},
};
use reqwest::StatusCode;
use tracing::debug;
use xdid::core::did::Did;
pub use dwn_core as core;
pub mod stores {
#[cfg(feature = "native_db")]
pub use dwn_native_db::*;
}
mod actor;
mod handlers;
pub use actor::*;
use crate::handlers::validation::ValidationResult;
#[derive(Clone)]
pub struct Dwn {
pub data_store: Arc<dyn DataStore>,
pub record_store: Arc<dyn RecordStore>,
}
impl<T: DataStore + RecordStore + Clone + 'static> From<T> for Dwn {
fn from(value: T) -> Self {
Self::new(Arc::new(value.clone()), Arc::new(value))
}
}
struct ProcessContext<'a> {
pub rs: &'a dyn RecordStore,
pub ds: &'a dyn DataStore,
pub validation: ValidationResult,
pub target: &'a Did,
pub msg: Message,
}
impl Dwn {
pub fn new(data_store: Arc<dyn DataStore>, record_store: Arc<dyn RecordStore>) -> Self {
Self {
data_store,
record_store,
}
}
pub async fn process_message(
&self,
target: &Did,
msg: Message,
) -> Result<Option<Reply>, StatusCode> {
let validation = match handlers::validation::validate_message(&msg).await {
Ok(a) => a,
Err(e) => {
debug!("Failed to validate message: {:?}", e);
return Err(StatusCode::BAD_REQUEST);
}
};
let ctx = ProcessContext {
rs: self.record_store.as_ref(),
ds: self.data_store.as_ref(),
validation,
target,
msg,
};
let res = match &ctx.msg.descriptor {
Descriptor::ProtocolsConfigure(_) => {
handlers::protocols::configure::handle(ctx).await?;
None
}
Descriptor::ProtocolsQuery(_) => handlers::protocols::query::handle(ctx)
.await
.map(|v| Some(Reply::ProtocolsQuery(v)))?,
Descriptor::RecordsDelete(_) => {
handlers::records::delete::handle(ctx).await?;
None
}
Descriptor::RecordsQuery(_) => handlers::records::query::handle(ctx)
.await
.map(|v| Some(Reply::RecordsQuery(v)))?,
Descriptor::RecordsRead(_) => handlers::records::read::handle(ctx)
.await
.map(|v| Some(Reply::RecordsRead(Box::new(v))))?,
Descriptor::RecordsSync(_) => handlers::records::sync::handle(ctx)
.await
.map(|v| Some(Reply::RecordsSync(Box::new(v))))?,
Descriptor::RecordsWrite(_) => {
handlers::records::write::handle(ctx).await?;
None
}
};
Ok(res)
}
}