Fixes for master + Range sketch

This commit is contained in:
Steven Fackler
2013-10-28 22:35:52 -07:00
parent 42555b7a09
commit c5a41e5b7e
4 changed files with 267 additions and 59 deletions

2
lib.rs
View File

@@ -65,7 +65,7 @@ fn main() {
#[warn(missing_doc)];
#[feature(macro_rules, struct_variant)];
#[feature(macro_rules, struct_variant, globs)];
extern mod extra;

View File

@@ -3,8 +3,6 @@
use std::str;
use std::rt::io::{Decorator, Reader, Writer};
use std::rt::io::extensions::{ReaderUtil, ReaderByteConversions,
WriterByteConversions};
use std::rt::io::mem::{MemWriter, MemReader};
use std::mem;
use std::vec;
@@ -129,7 +127,7 @@ trait WriteString {
impl<W: Writer> WriteString for W {
fn write_string(&mut self, s: &str) {
self.write(s.as_bytes());
self.write_u8_(0);
self.write_u8(0);
}
}
@@ -149,56 +147,56 @@ impl<W: Writer> WriteMessage for W {
buf.write_string(portal);
buf.write_string(statement);
buf.write_be_i16_(formats.len() as i16);
buf.write_be_i16(formats.len() as i16);
for format in formats.iter() {
buf.write_be_i16_(*format);
buf.write_be_i16(*format);
}
buf.write_be_i16_(values.len() as i16);
buf.write_be_i16(values.len() as i16);
for value in values.iter() {
match *value {
None => {
buf.write_be_i32_(-1);
buf.write_be_i32(-1);
}
Some(ref value) => {
buf.write_be_i32_(value.len() as i32);
buf.write_be_i32(value.len() as i32);
buf.write(*value);
}
}
}
buf.write_be_i16_(result_formats.len() as i16);
buf.write_be_i16(result_formats.len() as i16);
for format in result_formats.iter() {
buf.write_be_i16_(*format);
buf.write_be_i16(*format);
}
}
CancelRequest { code, process_id, secret_key } => {
buf.write_be_i32_(code);
buf.write_be_i32_(process_id);
buf.write_be_i32_(secret_key);
buf.write_be_i32(code);
buf.write_be_i32(process_id);
buf.write_be_i32(secret_key);
}
Close { variant, name } => {
ident = Some('C');
buf.write_u8_(variant);
buf.write_u8(variant);
buf.write_string(name);
}
Describe { variant, name } => {
ident = Some('D');
buf.write_u8_(variant);
buf.write_u8(variant);
buf.write_string(name);
}
Execute { portal, max_rows } => {
ident = Some('E');
buf.write_string(portal);
buf.write_be_i32_(max_rows);
buf.write_be_i32(max_rows);
}
Parse { name, query, param_types } => {
ident = Some('P');
buf.write_string(name);
buf.write_string(query);
buf.write_be_i16_(param_types.len() as i16);
buf.write_be_i16(param_types.len() as i16);
for ty in param_types.iter() {
buf.write_be_i32_(*ty);
buf.write_be_i32(*ty);
}
}
PasswordMessage { password } => {
@@ -210,12 +208,12 @@ impl<W: Writer> WriteMessage for W {
buf.write_string(query);
}
StartupMessage { version, parameters } => {
buf.write_be_i32_(version);
buf.write_be_i32(version);
for &(ref k, ref v) in parameters.iter() {
buf.write_string(k.as_slice());
buf.write_string(v.as_slice());
}
buf.write_u8_(0);
buf.write_u8(0);
}
Sync => {
ident = Some('S');
@@ -226,12 +224,12 @@ impl<W: Writer> WriteMessage for W {
}
match ident {
Some(ident) => self.write_u8_(ident as u8),
Some(ident) => self.write_u8(ident as u8),
None => ()
}
// add size of length value
self.write_be_i32_((buf.inner_ref().len() + mem::size_of::<i32>())
self.write_be_i32((buf.inner_ref().len() + mem::size_of::<i32>())
as i32);
self.write(buf.inner());
}
@@ -245,7 +243,7 @@ impl<R: Reader> ReadString for R {
fn read_string(&mut self) -> ~str {
let mut buf = ~[];
loop {
let byte = self.read_u8_();
let byte = self.read_u8();
if byte == 0 {
break;
}
@@ -265,9 +263,9 @@ impl<R: Reader> ReadMessage for R {
fn read_message(&mut self) -> BackendMessage {
debug!("Reading message");
let ident = self.read_u8_();
let ident = self.read_u8();
// subtract size of length value
let len = self.read_be_i32_() as uint - mem::size_of::<i32>();
let len = self.read_be_i32() as uint - mem::size_of::<i32>();
let mut buf = MemReader::new(self.read_bytes(len));
let ret = match ident as char {
@@ -275,7 +273,7 @@ impl<R: Reader> ReadMessage for R {
'2' => BindComplete,
'3' => CloseComplete,
'A' => NotificationResponse {
pid: buf.read_be_i32_(),
pid: buf.read_be_i32(),
channel: buf.read_string(),
payload: buf.read_string()
},
@@ -284,8 +282,8 @@ impl<R: Reader> ReadMessage for R {
'E' => ErrorResponse { fields: read_fields(&mut buf) },
'I' => EmptyQueryResponse,
'K' => BackendKeyData {
process_id: buf.read_be_i32_(),
secret_key: buf.read_be_i32_()
process_id: buf.read_be_i32(),
secret_key: buf.read_be_i32()
},
'n' => NoData,
'N' => NoticeResponse { fields: read_fields(&mut buf) },
@@ -297,7 +295,7 @@ impl<R: Reader> ReadMessage for R {
},
't' => read_parameter_description(&mut buf),
'T' => read_row_description(&mut buf),
'Z' => ReadyForQuery { state: buf.read_u8_() },
'Z' => ReadyForQuery { state: buf.read_u8() },
ident => fail!("Unknown message identifier `{}`", ident)
};
assert!(buf.eof());
@@ -309,7 +307,7 @@ impl<R: Reader> ReadMessage for R {
fn read_fields(buf: &mut MemReader) -> ~[(u8, ~str)] {
let mut fields = ~[];
loop {
let ty = buf.read_u8_();
let ty = buf.read_u8();
if ty == 0 {
break;
}
@@ -321,11 +319,11 @@ fn read_fields(buf: &mut MemReader) -> ~[(u8, ~str)] {
}
fn read_data_row(buf: &mut MemReader) -> BackendMessage {
let len = buf.read_be_i16_() as uint;
let len = buf.read_be_i16() as uint;
let mut values = vec::with_capacity(len);
do len.times() {
let val = match buf.read_be_i32_() {
let val = match buf.read_be_i32() {
-1 => None,
len => Some(buf.read_bytes(len as uint))
};
@@ -336,7 +334,7 @@ fn read_data_row(buf: &mut MemReader) -> BackendMessage {
}
fn read_auth_message(buf: &mut MemReader) -> BackendMessage {
match buf.read_be_i32_() {
match buf.read_be_i32() {
0 => AuthenticationOk,
2 => AuthenticationKerberosV5,
3 => AuthenticationCleartextPassword,
@@ -349,29 +347,29 @@ fn read_auth_message(buf: &mut MemReader) -> BackendMessage {
}
fn read_parameter_description(buf: &mut MemReader) -> BackendMessage {
let len = buf.read_be_i16_() as uint;
let len = buf.read_be_i16() as uint;
let mut types = vec::with_capacity(len);
do len.times() {
types.push(buf.read_be_i32_());
types.push(buf.read_be_i32());
}
ParameterDescription { types: types }
}
fn read_row_description(buf: &mut MemReader) -> BackendMessage {
let len = buf.read_be_i16_() as uint;
let len = buf.read_be_i16() as uint;
let mut types = vec::with_capacity(len);
do len.times() {
types.push(RowDescriptionEntry {
name: buf.read_string(),
table_oid: buf.read_be_i32_(),
column_id: buf.read_be_i16_(),
type_oid: buf.read_be_i32_(),
type_size: buf.read_be_i16_(),
type_modifier: buf.read_be_i32_(),
format: buf.read_be_i16_()
table_oid: buf.read_be_i32(),
column_id: buf.read_be_i16(),
type_oid: buf.read_be_i32(),
type_size: buf.read_be_i16(),
type_modifier: buf.read_be_i32(),
format: buf.read_be_i16()
});
}

View File

@@ -6,11 +6,12 @@ use extra::time::Timespec;
use extra::json;
use extra::json::Json;
use extra::uuid::Uuid;
use std::rt::io::Decorator;
use std::rt::io::extensions::{WriterByteConversions, ReaderByteConversions};
use std::rt::io::{Reader, Writer, Decorator};
use std::rt::io::mem::{MemWriter, BufReader};
use std::str;
pub mod range;
/// A Postgres OID
pub type Oid = i32;
@@ -170,17 +171,17 @@ macro_rules! from_option_impl(
from_map_impl!(PgBool, bool, |buf| { buf[0] != 0 })
from_option_impl!(bool)
from_conversions_impl!(PgChar, i8, read_i8_)
from_conversions_impl!(PgChar, i8, read_i8)
from_option_impl!(i8)
from_conversions_impl!(PgInt2, i16, read_be_i16_)
from_conversions_impl!(PgInt2, i16, read_be_i16)
from_option_impl!(i16)
from_conversions_impl!(PgInt4, i32, read_be_i32_)
from_conversions_impl!(PgInt4, i32, read_be_i32)
from_option_impl!(i32)
from_conversions_impl!(PgInt8, i64, read_be_i64_)
from_conversions_impl!(PgInt8, i64, read_be_i64)
from_option_impl!(i64)
from_conversions_impl!(PgFloat4, f32, read_be_f32_)
from_conversions_impl!(PgFloat4, f32, read_be_f32)
from_option_impl!(f32)
from_conversions_impl!(PgFloat8, f64, read_be_f64_)
from_conversions_impl!(PgFloat8, f64, read_be_f64)
from_option_impl!(f64)
from_map_impl!(PgVarchar | PgText | PgCharN, ~str, |buf| {
@@ -208,7 +209,7 @@ from_option_impl!(Uuid)
from_map_impl!(PgTimestamp | PgTimestampZ, Timespec, |buf| {
let mut rdr = BufReader::new(buf.as_slice());
let t = rdr.read_be_i64_();
let t = rdr.read_be_i64();
let mut sec = t / USEC_PER_SEC + TIME_SEC_CONVERSION;
let mut usec = t % USEC_PER_SEC;
@@ -282,17 +283,17 @@ impl ToSql for bool {
}
to_option_impl!(PgBool, bool)
to_conversions_impl!(PgChar, i8, write_i8_)
to_conversions_impl!(PgChar, i8, write_i8)
to_option_impl!(PgChar, i8)
to_conversions_impl!(PgInt2, i16, write_be_i16_)
to_conversions_impl!(PgInt2, i16, write_be_i16)
to_option_impl!(PgInt2, i16)
to_conversions_impl!(PgInt4, i32, write_be_i32_)
to_conversions_impl!(PgInt4, i32, write_be_i32)
to_option_impl!(PgInt4, i32)
to_conversions_impl!(PgInt8, i64, write_be_i64_)
to_conversions_impl!(PgInt8, i64, write_be_i64)
to_option_impl!(PgInt8, i64)
to_conversions_impl!(PgFloat4, f32, write_be_f32_)
to_conversions_impl!(PgFloat4, f32, write_be_f32)
to_option_impl!(PgFloat4, f32)
to_conversions_impl!(PgFloat8, f64, write_be_f64_)
to_conversions_impl!(PgFloat8, f64, write_be_f64)
to_option_impl!(PgFloat8, f64)
impl ToSql for ~str {
@@ -353,7 +354,7 @@ impl ToSql for Timespec {
let t = (self.sec - TIME_SEC_CONVERSION) * USEC_PER_SEC
+ self.nsec as i64 / NSEC_PER_USEC;
let mut buf = MemWriter::new();
buf.write_be_i64_(t);
buf.write_be_i64(t);
(Binary, Some(buf.inner()))
}
}

209
types/range.rs Normal file
View File

@@ -0,0 +1,209 @@
#[allow(missing_doc)];
enum BoundSide {
Upper,
Lower
}
trait BoundSided {
// param is a hack to get around lack of hints for self type
fn side(_: Option<Self>) -> BoundSide;
}
pub struct UpperBound;
pub struct LowerBound;
impl BoundSided for UpperBound {
fn side(_: Option<UpperBound>) -> BoundSide {
Upper
}
}
impl BoundSided for LowerBound {
fn side(_: Option<LowerBound>) -> BoundSide {
Lower
}
}
pub enum BoundType {
Inclusive,
Exclusive
}
pub struct RangeBound<S, T> {
value: T,
type_: BoundType
}
impl<S: BoundSided, T: Ord> Ord for RangeBound<S, T> {
fn lt(&self, other: &RangeBound<S, T>) -> bool {
match (BoundSided::side(None::<S>), self.type_, other.type_) {
(Upper, Exclusive, Inclusive)
| (Lower, Inclusive, Exclusive) => self.value <= other.value,
_ => self.value < other.value
}
}
}
impl<S: BoundSided, T: Ord> RangeBound<S, T> {
pub fn new(value: T, type_: BoundType) -> RangeBound<S, T> {
RangeBound { value: value, type_: type_ }
}
pub fn in_bounds(&self, value: &T) -> bool {
match (self.type_, BoundSided::side(None::<S>)) {
(Inclusive, Upper) if value <= &self.value => true,
(Exclusive, Upper) if value < &self.value => true,
(Inclusive, Lower) if value >= &self.value => true,
(Exclusive, Lower) if value > &self.value => true,
_ => false
}
}
}
#[deriving(Eq)]
pub enum RangeComparison {
Above,
Within,
Below
}
pub struct Range<T> {
lower: Option<RangeBound<LowerBound, T>>,
upper: Option<RangeBound<UpperBound, T>>,
}
impl<T: Ord> Range<T> {
pub fn new(lower: Option<RangeBound<LowerBound, T>>,
upper: Option<RangeBound<UpperBound, T>>) -> Range<T> {
match (&lower, &upper) {
(&Some(ref lower), &Some(ref upper)) =>
assert!(lower.value <= upper.value),
_ => {}
}
Range { lower: lower, upper: upper }
}
pub fn cmp(&self, value: &T) -> RangeComparison {
let lower = do self.lower.as_ref().map_default(true) |b| {
b.in_bounds(value)
};
let upper = do self.upper.as_ref().map_default(true) |b| {
b.in_bounds(value)
};
match (lower, upper) {
(true, false) => Above,
(true, true) => Within,
(false, true) => Below,
_ => unreachable!()
}
}
pub fn contains(&self, value: &T) -> bool {
self.cmp(value) == Within
}
}
#[cfg(test)]
mod test {
use super::*;
use std::int;
#[test]
fn test_range_bound_lower_lt() {
fn check(val1: int, inc1: BoundType, val2: int, inc2: BoundType, expected: bool) {
let a: RangeBound<LowerBound, int> = RangeBound::new(val1, inc1);
let b: RangeBound<LowerBound, int> = RangeBound::new(val2, inc2);
assert_eq!(expected, a < b);
}
check(1, Inclusive, 2, Exclusive, true);
check(1, Exclusive, 2, Inclusive, true);
check(1, Inclusive, 1, Exclusive, true);
check(2, Inclusive, 1, Inclusive, false);
check(2, Exclusive, 1, Exclusive, false);
check(1, Exclusive, 1, Inclusive, false);
check(1, Exclusive, 1, Exclusive, false);
check(1, Inclusive, 1, Inclusive, false);
}
#[test]
fn test_range_bound_upper_lt() {
fn check(val1: int, inc1: BoundType, val2: int, inc2: BoundType, expected: bool) {
let a: RangeBound<UpperBound, int> = RangeBound::new(val1, inc1);
let b: RangeBound<UpperBound, int> = RangeBound::new(val2, inc2);
assert_eq!(expected, a < b);
}
check(1, Inclusive, 2, Exclusive, true);
check(1, Exclusive, 2, Exclusive, true);
check(1, Exclusive, 1, Inclusive, true);
check(2, Inclusive, 1, Inclusive, false);
check(2, Exclusive, 1, Exclusive, false);
check(1, Inclusive, 1, Exclusive, false);
check(1, Inclusive, 1, Inclusive, false);
check(1, Exclusive, 1, Exclusive, false);
}
#[test]
fn test_range_bound_lower_in_bounds() {
fn check(bound: int, inc: BoundType, val: int, expected: bool) {
let b: RangeBound<LowerBound, int> = RangeBound::new(bound, inc);
assert_eq!(expected, b.in_bounds(&val));
}
check(1, Inclusive, 1, true);
check(1, Exclusive, 1, false);
check(1, Inclusive, 2, true);
check(1, Inclusive, 0, false);
}
#[test]
fn test_range_bound_upper_in_bounds() {
fn check(bound: int, inc: BoundType, val: int, expected: bool) {
let b: RangeBound<UpperBound, int> = RangeBound::new(bound, inc);
assert_eq!(expected, b.in_bounds(&val));
}
check(1, Inclusive, 1, true);
check(1, Exclusive, 1, false);
check(1, Inclusive, 2, false);
check(1, Inclusive, 0, true);
}
#[test]
fn test_range_cmp() {
let r = Range::new(Some(RangeBound::new(1, Inclusive)),
Some(RangeBound::new(3, Inclusive)));
assert_eq!(Above, r.cmp(&4));
assert_eq!(Within, r.cmp(&3));
assert_eq!(Within, r.cmp(&2));
assert_eq!(Within, r.cmp(&1));
assert_eq!(Below, r.cmp(&0));
let r = Range::new(Some(RangeBound::new(1, Exclusive)),
Some(RangeBound::new(3, Exclusive)));
assert_eq!(Above, r.cmp(&4));
assert_eq!(Above, r.cmp(&3));
assert_eq!(Within, r.cmp(&2));
assert_eq!(Below, r.cmp(&1));
assert_eq!(Below, r.cmp(&0));
let r = Range::new(None, Some(RangeBound::new(3, Inclusive)));
assert_eq!(Above, r.cmp(&4));
assert_eq!(Within, r.cmp(&2));
assert_eq!(Within, r.cmp(&int::min_value));
let r = Range::new(Some(RangeBound::new(1, Inclusive)), None);
assert_eq!(Within, r.cmp(&int::max_value));
assert_eq!(Within, r.cmp(&4));
assert_eq!(Below, r.cmp(&0));
let r = Range::new(None, None);
assert_eq!(Within, r.cmp(&int::max_value));
assert_eq!(Within, r.cmp(&0));
assert_eq!(Within, r.cmp(&int::min_value));
}
}