use crate::core_relations::{BaseValues, Value};
use crate::sort;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ApiError {
#[error(
"declarations are not available in this execution, so the signature of `{name}` cannot be read"
)]
SchemasUnavailable { name: String },
#[error("no table named `{name}` is registered")]
MissingTable { name: String },
#[error("table `{name}` is a {actual}; this method is only valid for {expected} tables")]
WrongSubtype {
name: String,
expected: &'static str,
actual: &'static str,
},
#[error("table `{table}`: expected {expected} input columns, got {got}")]
WrongArity {
table: String,
expected: usize,
got: usize,
},
}
mod sealed {
pub trait Sealed {}
}
pub trait IntoValue {
fn into_value(self, bv: &BaseValues) -> Value;
}
pub trait FromValue: Sized {
fn from_value(value: Value, bv: &BaseValues) -> Self;
}
pub trait IntoValues: sealed::Sealed {
fn into_values(self, bv: &BaseValues) -> impl Iterator<Item = Value>;
}
pub trait FromValues: Sized + sealed::Sealed {
fn from_values(values: &[Value], bv: &BaseValues) -> Self;
}
macro_rules! impl_value_for_base {
( $( $ty:ty ),+ $(,)? ) => {
$(
impl IntoValue for $ty {
fn into_value(self, bv: &BaseValues) -> Value {
bv.get::<$ty>(self)
}
}
impl FromValue for $ty {
fn from_value(value: Value, bv: &BaseValues) -> Self {
bv.unwrap::<$ty>(value)
}
}
)+
};
}
impl_value_for_base!(i64, bool, (), sort::F, sort::S, sort::Z, sort::Q);
impl IntoValue for String {
fn into_value(self, bv: &BaseValues) -> Value {
bv.get::<sort::S>(self.into())
}
}
impl FromValue for String {
fn from_value(value: Value, bv: &BaseValues) -> Self {
bv.unwrap::<sort::S>(value).0
}
}
impl IntoValue for &str {
fn into_value(self, bv: &BaseValues) -> Value {
bv.get::<sort::S>(self.to_string().into())
}
}
impl IntoValue for f64 {
fn into_value(self, bv: &BaseValues) -> Value {
use ordered_float::OrderedFloat;
bv.get::<sort::F>(OrderedFloat(self).into())
}
}
impl FromValue for f64 {
fn from_value(value: Value, bv: &BaseValues) -> Self {
bv.unwrap::<sort::F>(value).0.0
}
}
impl IntoValue for Value {
fn into_value(self, _bv: &BaseValues) -> Value {
self
}
}
impl FromValue for Value {
fn from_value(value: Value, _bv: &BaseValues) -> Self {
value
}
}
#[derive(Clone, Debug)]
pub struct RawValues(pub Vec<Value>);
impl sealed::Sealed for RawValues {}
impl IntoValues for RawValues {
fn into_values(self, _bv: &BaseValues) -> impl Iterator<Item = Value> {
self.0.into_iter()
}
}
impl sealed::Sealed for Vec<Value> {}
impl FromValues for Vec<Value> {
fn from_values(values: &[Value], _bv: &BaseValues) -> Self {
values.to_vec()
}
}
impl FromValues for () {
fn from_values(_values: &[Value], _bv: &BaseValues) -> Self {}
}
impl<A: IntoValue> sealed::Sealed for A {}
impl<A: IntoValue> IntoValues for A {
fn into_values(self, bv: &BaseValues) -> impl Iterator<Item = Value> {
std::iter::once(self.into_value(bv))
}
}
macro_rules! impl_values_for_tuple {
( $( ($($name:ident),+) ),+ $(,)? ) => {
$(
#[allow(non_snake_case)]
impl<$($name),+> sealed::Sealed for ($($name,)+) {}
#[allow(non_snake_case)]
impl<$($name: IntoValue),+> IntoValues for ($($name,)+) {
fn into_values(self, bv: &BaseValues) -> impl Iterator<Item = Value> {
let ($($name,)+) = self;
[ $( $name.into_value(bv) ),+ ].into_iter()
}
}
#[allow(non_snake_case)]
impl<$($name: FromValue),+> FromValues for ($($name,)+) {
fn from_values(values: &[Value], bv: &BaseValues) -> Self {
let mut iter = values.iter().copied();
let tuple = ( $( $name::from_value(iter.next().expect("FromValues: row shorter than tuple arity"), bv), )+ );
assert!(
iter.next().is_none(),
"FromValues: row longer than tuple arity",
);
tuple
}
}
)+
};
}
impl_values_for_tuple! {
(T1),
(T1, T2),
(T1, T2, T3),
(T1, T2, T3, T4),
(T1, T2, T3, T4, T5),
(T1, T2, T3, T4, T5, T6),
(T1, T2, T3, T4, T5, T6, T7),
(T1, T2, T3, T4, T5, T6, T7, T8),
}