use std::fmt;
use async_trait::async_trait;
use tc_error::*;
use tc_state::State;
use tc_transact::TxnId;
use tc_value::Value;
use tcgeneric::*;
use crate::txn::Txn;
use system::System;
use userspace::UserSpace;
pub use userspace::{Class, Library, Service, CLASS, LIB, SERVICE};
mod system;
mod userspace;
#[async_trait]
pub trait Dispatch {
async fn get(&self, txn: &Txn, path: &[PathSegment], key: Value) -> TCResult<State>;
async fn put(&self, txn: &Txn, path: &[PathSegment], key: Value, value: State) -> TCResult<()>;
async fn post(&self, txn: &Txn, path: &[PathSegment], data: State) -> TCResult<State>;
async fn delete(&self, txn: &Txn, path: &[PathSegment], key: Value) -> TCResult<()>;
async fn finalize(&self, txn_id: TxnId);
}
pub struct Kernel {
system: System,
userspace: Option<UserSpace>,
}
impl Kernel {
pub fn bootstrap() -> Self {
Self {
system: System,
userspace: None,
}
}
pub fn with_userspace(class: Class, library: Library, service: Service) -> Self {
Self {
system: System,
userspace: Some(UserSpace::new(class, library, service)),
}
}
}
#[async_trait]
impl Dispatch for Kernel {
async fn get(&self, txn: &Txn, path: &[PathSegment], key: Value) -> TCResult<State> {
if let Some(userspace) = &self.userspace {
if userspace.handles(path) {
return userspace.get(txn, path, key).await;
}
}
self.system.get(txn, path, key).await
}
async fn put(&self, txn: &Txn, path: &[PathSegment], key: Value, value: State) -> TCResult<()> {
if let Some(userspace) = &self.userspace {
if userspace.handles(path) {
return userspace.put(txn, path, key, value).await;
}
}
self.system.put(txn, path, key, value).await
}
async fn post(&self, txn: &Txn, path: &[PathSegment], data: State) -> TCResult<State> {
if let Some(userspace) = &self.userspace {
if userspace.handles(path) {
return userspace.post(txn, path, data).await;
}
}
self.system.post(txn, path, data).await
}
async fn delete(&self, txn: &Txn, path: &[PathSegment], key: Value) -> TCResult<()> {
if let Some(userspace) = &self.userspace {
if userspace.handles(path) {
return userspace.delete(txn, path, key).await;
}
}
self.system.delete(txn, path, key).await
}
async fn finalize(&self, txn_id: TxnId) {
if let Some(userspace) = &self.userspace {
userspace.finalize(txn_id).await
}
}
}
impl fmt::Debug for Kernel {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("host kernel")
}
}