Fixes for master + Range sketch
This commit is contained in:
2
lib.rs
2
lib.rs
@@ -65,7 +65,7 @@ fn main() {
|
||||
|
||||
#[warn(missing_doc)];
|
||||
|
||||
#[feature(macro_rules, struct_variant)];
|
||||
#[feature(macro_rules, struct_variant, globs)];
|
||||
|
||||
extern mod extra;
|
||||
|
||||
|
||||
82
message.rs
82
message.rs
@@ -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()
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -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
209
types/range.rs
Normal 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));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user