pub mod error;
pub mod value;
pub use error::{Error, Result};
pub use value::{MaybeRow, Row, Value};
pub type Timestamp = u64;
#[derive(Debug, Clone, Default)]
pub struct LookupOptions {
pub columns: Vec<String>,
pub timestamp: Option<Timestamp>,
}
#[derive(Debug, Clone, Default)]
pub struct SelectOptions {
pub timestamp: Option<Timestamp>,
pub limit: Option<u64>,
}
pub trait TableClient {
fn transport(&self) -> Transport;
fn lookup_rows(
&self,
path: &str,
keys: &[Row],
options: &LookupOptions,
) -> Result<Vec<MaybeRow>>;
fn select_rows(&self, query: &str, options: &SelectOptions) -> Result<Vec<Row>>;
fn insert_rows(&self, path: &str, rows: &[Row]) -> Result<()>;
fn delete_rows(&self, path: &str, keys: &[Row]) -> Result<()>;
fn start_transaction(&self) -> Result<Box<dyn TableTransaction + '_>>;
}
pub trait TableTransaction {
fn id(&self) -> String;
fn lookup_rows(
&self,
path: &str,
keys: &[Row],
options: &LookupOptions,
) -> Result<Vec<MaybeRow>>;
fn select_rows(&self, query: &str, options: &SelectOptions) -> Result<Vec<Row>>;
fn insert_rows(&self, path: &str, rows: &[Row]) -> Result<()>;
fn delete_rows(&self, path: &str, keys: &[Row]) -> Result<()>;
fn ping(&self) -> Result<()>;
fn commit(self: Box<Self>) -> Result<()>;
fn abort(self: Box<Self>) -> Result<()>;
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Transport {
Http,
Rpc,
}
impl std::fmt::Display for Transport {
fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
formatter.write_str(match self {
Self::Http => "HTTP",
Self::Rpc => "RPC",
})
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn the_interface_is_object_safe() {
struct Nothing;
impl TableClient for Nothing {
fn transport(&self) -> Transport {
Transport::Http
}
fn lookup_rows(&self, _: &str, _: &[Row], _: &LookupOptions) -> Result<Vec<MaybeRow>> {
Ok(Vec::new())
}
fn select_rows(&self, _: &str, _: &SelectOptions) -> Result<Vec<Row>> {
Ok(Vec::new())
}
fn insert_rows(&self, _: &str, _: &[Row]) -> Result<()> {
Ok(())
}
fn delete_rows(&self, _: &str, _: &[Row]) -> Result<()> {
Ok(())
}
fn start_transaction(&self) -> Result<Box<dyn TableTransaction + '_>> {
Err(Error::Unsupported {
transport: Transport::Http,
what: "transactions in this stub",
})
}
}
let client: Box<dyn TableClient> = Box::new(Nothing);
assert_eq!(client.transport(), Transport::Http);
assert!(
client
.lookup_rows("//tmp/t", &[], &LookupOptions::default())
.is_ok()
);
}
#[test]
fn transport_names_itself() {
assert_eq!(Transport::Http.to_string(), "HTTP");
assert_eq!(Transport::Rpc.to_string(), "RPC");
}
}