use std::hash::{Hash, Hasher};
use std::sync::Arc;
pub trait HashTO {
fn hash_to(&self, &mut Hasher);
}
struct HashProxy<'a> {
pub hasher: &'a mut Hasher,
}
impl<'a> Hasher for HashProxy<'a> {
fn finish(&self) -> u64 {
self.hasher.finish()
}
fn write(&mut self, bytes: &[u8]) {
self.hasher.write(bytes)
}
}
impl<T: Hash> HashTO for T {
fn hash_to(&self, h: &mut Hasher) {
self.hash(&mut HashProxy { hasher: h })
}
}
pub type Type = Arc<self::types::TypeT>;
pub type Value = Arc<self::values::ValueT>;
pub mod types {
use super::values;
use super::super::RowIter;
use std::any::Any;
use std::fmt;
use std::sync::Arc;
use std::hash::{Hash, Hasher};
use super::HashTO;
use super::Type;
use super::Value;
#[macro_export]
macro_rules! typet_inner {
() => {
fn inner(&self) -> &::std::any::Any {
self as &::std::any::Any
}
}
}
#[macro_export]
macro_rules! typet_inner_eq {
() => {
fn inner_eq(&self, other : &TypeT) -> bool {
let other_self = match other.inner().downcast_ref() {
Some(x) => x,
None => return false
};
self == other_self
}
}
}
#[macro_export]
macro_rules! typet_boiler {
() => {
typet_inner!();
typet_inner_eq!();
fn large_unique(&self) -> bool {
false
}
}
}
pub trait TypeT: Sync + Send + HashTO + Any {
fn name(&self) -> Option<&'static str>;
fn extract(&self, &mut RowIter) -> Option<Value>;
fn repr(&self) -> Vec<::std::string::String>;
fn inner(&self) -> &Any;
fn inner_eq(&self, other: &TypeT) -> bool;
fn large_unique(&self) -> bool;
}
impl Hash for TypeT {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.hash_to(hasher)
}
}
impl fmt::Debug for TypeT {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "[Name: {:?}, Repr: {:?}]", self.name(), self.repr())
}
}
impl Eq for TypeT {}
impl PartialEq for TypeT {
fn eq(&self, t: &TypeT) -> bool {
self.inner_eq(t)
}
}
#[derive(Debug,Clone,Hash,PartialEq)]
pub struct Trap;
impl TypeT for Trap {
typet_boiler!();
fn name(&self) -> Option<&'static str> {
Some("trap")
}
fn extract(&self, _rows: &mut RowIter) -> Option<Value> {
panic!("Tried to extract from a trap")
}
fn repr(&self) -> Vec<::std::string::String> {
panic!("Tried to observe the representation of a trap")
}
}
impl Trap {
pub fn new() -> Arc<Self> {
Arc::new(Trap)
}
}
#[derive(Debug,Clone,Hash,PartialEq)]
pub struct Tuple {
elements: Vec<Type>,
}
impl Tuple {
pub fn new(elems: Vec<Type>) -> Arc<Self> {
Arc::new(Tuple { elements: elems })
}
}
impl TypeT for Tuple {
typet_boiler!();
fn name(&self) -> Option<&'static str> {
None
}
fn extract(&self, rows: &mut RowIter) -> Option<Value> {
let mut out = Vec::new();
for elem in self.elements.iter() {
match elem.extract(rows) {
Some(v) => out.push(v),
None => return None,
}
}
Some(values::Tuple::new(out))
}
fn repr(&self) -> Vec<::std::string::String> {
self.elements.iter().flat_map(|elem| elem.repr()).collect()
}
}
#[derive(Debug,Clone,Hash)]
pub struct List {
elem: Type,
}
impl List {
pub fn new(elem: Type) -> Arc<Self> {
Arc::new(List { elem: elem })
}
}
impl PartialEq for List {
fn eq(&self, other: &Self) -> bool {
*self.elem == *other.elem
}
}
impl TypeT for List {
typet_boiler!();
fn name(&self) -> Option<&'static str> {
None
}
fn extract(&self, _rows: &mut RowIter) -> Option<Value> {
panic!("List support disabled, will be re-enabled via arrays maybe")
}
fn repr(&self) -> Vec<::std::string::String> {
panic!("List support disabled, will be re-enabled via arrays maybe")
}
}
pub fn default_types() -> Vec<Type> {
vec![Arc::new(UInt64),
Arc::new(String),
Arc::new(Bytes),
Arc::new(LargeBytes),
Arc::new(Bool)]
}
#[derive(Debug,Clone,Hash,PartialEq)]
pub struct Bool;
impl TypeT for Bool {
typet_boiler!();
fn name(&self) -> Option<&'static str> {
Some("bool")
}
fn extract(&self, rows: &mut RowIter) -> Option<Value> {
rows.next().map(|b| values::Bool::new(b) as Value)
}
fn repr(&self) -> Vec<::std::string::String> {
vec!["bool".to_string()]
}
}
#[derive(Debug,Clone,Hash,PartialEq)]
pub struct UInt64;
impl TypeT for UInt64 {
typet_boiler!();
fn name(&self) -> Option<&'static str> {
Some("uint64")
}
fn extract(&self, rows: &mut RowIter) -> Option<Value> {
rows.next().map(|x: i64| values::UInt64::new(x as u64) as Value)
}
fn repr(&self) -> Vec<::std::string::String> {
vec!["int8".to_string()]
}
}
#[derive(Debug,Clone,Hash,PartialEq)]
pub struct String;
impl TypeT for String {
typet_boiler!();
fn name(&self) -> Option<&'static str> {
Some("string")
}
fn extract(&self, rows: &mut RowIter) -> Option<Value> {
rows.next().map(|s| values::String::new(s) as Value)
}
fn repr(&self) -> Vec<::std::string::String> {
vec!["varchar".to_string()]
}
}
#[derive(Debug,Clone,Hash,PartialEq)]
pub struct Bytes;
impl TypeT for Bytes {
typet_boiler!();
fn name(&self) -> Option<&'static str> {
Some("bytes")
}
fn extract(&self, rows: &mut RowIter) -> Option<Value> {
rows.next().map(|b| values::Bytes::new(b) as Value)
}
fn repr(&self) -> Vec<::std::string::String> {
vec!["bytea".to_string()]
}
}
#[derive(Debug,Clone,Hash,PartialEq)]
pub struct LargeBytes;
impl TypeT for LargeBytes {
typet_inner!();
typet_inner_eq!();
fn large_unique(&self) -> bool {
true
}
fn name(&self) -> Option<&'static str> {
Some("largebytes")
}
fn extract(&self, rows: &mut RowIter) -> Option<Value> {
rows.next().map(|v| values::Bytes::new(v) as Value)
}
fn repr(&self) -> Vec<::std::string::String> {
vec!["bytea".to_string()]
}
}
}
pub mod values {
use postgres::types::ToSql;
use std::any::Any;
use super::HashTO;
use std::sync::Arc;
use std::hash::{Hash, Hasher};
use std::fmt;
use super::Type;
use super::Value;
use super::types;
use std::cmp::Ordering;
#[macro_export]
macro_rules! valuet_boiler {
() => {
fn inner(&self) -> &::std::any::Any {
self as &::std::any::Any
}
fn inner_eq(&self, other : &ValueT) -> bool {
let other_typed = match other.inner().downcast_ref::<Self>() {
Some(x) => x,
None => return false
};
self == other_typed
}
fn inner_ord(&self, other : &ValueT) -> Option<::std::cmp::Ordering> {
other.inner().downcast_ref::<Self>().and_then(|other_typed|{
self.partial_cmp(other_typed)
})
}
}
}
pub trait ValueT: Sync + Send + HashTO + fmt::Debug + fmt::Display + Any {
fn type_(&self) -> Type;
fn get(&self) -> &Any;
fn to_sql(&self) -> Vec<&ToSql>;
fn inner(&self) -> &Any;
fn inner_eq(&self, other: &ValueT) -> bool;
fn inner_ord(&self, &ValueT) -> Option<Ordering>;
}
impl Hash for ValueT {
fn hash<H: Hasher>(&self, hasher: &mut H) {
self.hash_to(hasher)
}
}
pub trait ToValue {
fn to_value(self) -> Value;
}
impl Eq for ValueT {}
impl PartialEq for ValueT {
fn eq(&self, other: &ValueT) -> bool {
self.inner_eq(other)
}
}
impl PartialOrd for ValueT {
fn partial_cmp(&self, other: &ValueT) -> Option<Ordering> {
self.inner_ord(other)
}
}
#[derive(Debug,Clone,PartialEq,Hash,PartialOrd,Eq)]
pub struct List {
elements: Vec<Value>,
}
impl fmt::Display for List {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "[")?;
let mut first = true;
for elem in self.elements.iter() {
if !first {
write!(fmt, ", ")?;
first = false;
}
write!(fmt, "{}", elem)?;
}
write!(fmt, "]")
}
}
impl ValueT for List {
fn type_(&self) -> Type {
match self.elements.first() {
Some(e) => types::List::new(e.type_()),
None => types::List::new(Arc::new(types::UInt64)),
}
}
fn get(&self) -> &Any {
&self.elements as &Any
}
fn to_sql(&self) -> Vec<&ToSql> {
panic!("List SQL disabled")
}
valuet_boiler!();
}
impl List {
pub fn new(elements: Vec<Value>) -> Arc<Self> {
Arc::new(List { elements: elements })
}
}
#[derive(Debug,Clone,PartialEq,PartialOrd,Hash)]
pub struct Tuple {
elements: Vec<Value>,
}
impl fmt::Display for Tuple {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "(")?;
let mut first = true;
for elem in self.elements.iter() {
if !first {
write!(fmt, ", ")?;
first = false;
}
write!(fmt, "{}", elem)?;
}
write!(fmt, ")")
}
}
impl ValueT for Tuple {
fn type_(&self) -> Type {
types::Tuple::new(self.elements
.iter()
.map(|val| val.type_())
.collect())
}
fn get(&self) -> &Any {
&self.elements as &Any
}
fn to_sql(&self) -> Vec<&ToSql> {
self.elements.iter().flat_map(|val| val.to_sql()).collect()
}
valuet_boiler!();
}
impl Tuple {
pub fn new(elements: Vec<Value>) -> Arc<Self> {
Arc::new(Tuple { elements: elements })
}
}
#[derive(Debug,PartialEq,PartialOrd,Hash)]
pub struct Bool {
val: bool,
}
impl Bool {
pub fn new(b: bool) -> Arc<Self> {
Arc::new(Bool { val: b })
}
}
impl fmt::Display for Bool {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", self.val)
}
}
impl ValueT for Bool {
fn type_(&self) -> Type {
Arc::new(types::Bool)
}
fn get(&self) -> &Any {
&self.val as &Any
}
fn to_sql(&self) -> Vec<&ToSql> {
vec![&self.val]
}
valuet_boiler!();
}
impl ToValue for bool {
fn to_value(self) -> Value {
Bool::new(self)
}
}
impl ToValue for u64 {
fn to_value(self) -> Value {
UInt64::new(self)
}
}
impl ToValue for ::std::string::String {
fn to_value(self) -> Value {
String::new(self)
}
}
impl ToValue for Vec<u8> {
fn to_value(self) -> Value {
Bytes::new(self)
}
}
pub struct LargeBWrap {
pub inner: Vec<u8>,
}
impl ToValue for LargeBWrap {
fn to_value(self) -> Value {
LargeBytes::new(self.inner)
}
}
impl<T: ToValue> ToValue for Vec<T> {
fn to_value(self) -> Value {
List::new(self.into_iter().map(|x| x.to_value()).collect())
}
}
macro_rules! to_value_tuple {
($($slot:ident),*) => {
#[allow(non_snake_case)]
impl <$($slot : ToValue),*> ToValue for ($($slot),*) {
fn to_value(self) -> Value {
let ($($slot),*) = self;
Tuple::new(vec![$($slot.to_value()),*])
}
}
};
}
to_value_tuple!(A, B);
to_value_tuple!(A, B, C);
to_value_tuple!(A, B, C, D);
to_value_tuple!(A, B, C, D, E);
to_value_tuple!(A, B, C, D, E, F);
to_value_tuple!(A, B, C, D, E, F, G);
to_value_tuple!(A, B, C, D, E, F, G, H);
impl ToValue for &'static str {
fn to_value(self) -> Value {
String::new(self.to_string())
}
}
#[derive(Debug,PartialEq,PartialOrd,Hash)]
pub struct UInt64 {
val: u64,
sql: i64,
}
impl fmt::Display for UInt64 {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{}", self.val)
}
}
impl ValueT for UInt64 {
fn type_(&self) -> Type {
Arc::new(types::UInt64)
}
fn get(&self) -> &Any {
&self.val as &Any
}
fn to_sql(&self) -> Vec<&ToSql> {
vec![&self.sql]
}
valuet_boiler!();
}
impl UInt64 {
pub fn new(val: u64) -> Arc<Self> {
Arc::new(UInt64 {
val: val,
sql: val as i64,
})
}
}
#[derive(Debug,PartialEq,PartialOrd,Hash)]
pub struct String {
val: ::std::string::String,
}
impl fmt::Display for String {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{:?}", self.val)
}
}
impl ValueT for String {
fn type_(&self) -> Type {
Arc::new(types::String)
}
fn get(&self) -> &Any {
&self.val as &Any
}
fn to_sql(&self) -> Vec<&ToSql> {
vec![&self.val as &ToSql]
}
valuet_boiler!();
}
impl String {
pub fn new(val: ::std::string::String) -> Arc<Self> {
Arc::new(String { val: val })
}
}
#[derive(Debug,PartialEq,PartialOrd,Hash)]
pub struct Bytes {
val: Vec<u8>,
}
impl ValueT for Bytes {
fn type_(&self) -> Type {
Arc::new(types::Bytes)
}
fn get(&self) -> &Any {
&self.val as &Any
}
fn to_sql(&self) -> Vec<&ToSql> {
vec![&self.val as &ToSql]
}
valuet_boiler!();
}
impl fmt::Display for Bytes {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "{:?}", self.val)
}
}
impl Bytes {
pub fn new(val: Vec<u8>) -> Arc<Self> {
Arc::new(Bytes { val: val })
}
}
#[derive(Debug,PartialEq,PartialOrd,Hash)]
pub struct LargeBytes {
val: Vec<u8>,
}
impl ValueT for LargeBytes {
fn type_(&self) -> Type {
Arc::new(types::LargeBytes)
}
fn get(&self) -> &Any {
&self.val as &Any
}
fn to_sql(&self) -> Vec<&ToSql> {
vec![&self.val as &ToSql]
}
valuet_boiler!();
}
impl fmt::Display for LargeBytes {
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
write!(fmt, "(large)")
}
}
impl LargeBytes {
pub fn new(val: Vec<u8>) -> Arc<Self> {
Arc::new(LargeBytes { val: val })
}
}
}