Introduce ToOwnedRange to make handling ranges a bit nicer

Signed-off-by: Nick Cameron <nrc@ncameron.org>
This commit is contained in:
Nick Cameron 2019-06-26 14:58:57 +12:00
parent 426d596709
commit 0ed7c8afe3
6 changed files with 55 additions and 12 deletions

View File

@ -6,7 +6,7 @@
mod common; mod common;
use crate::common::parse_args; use crate::common::parse_args;
use tikv_client::{raw::Client, Config, Key, KvPair, Result, Value}; use tikv_client::{raw::Client, Config, Key, KvPair, Result, ToOwnedRange, Value};
const KEY: &str = "TiKV"; const KEY: &str = "TiKV";
const VALUE: &str = "Rust"; const VALUE: &str = "Rust";
@ -89,7 +89,7 @@ async fn main() -> Result<()> {
let end = "k2"; let end = "k2";
let pairs = client let pairs = client
.with_key_only(true) .with_key_only(true)
.scan(start.to_owned()..=end.to_owned(), 10) .scan((start..=end).to_owned(), 10)
.await .await
.expect("Could not scan"); .expect("Could not scan");

View File

@ -3,6 +3,7 @@
use super::Key; use super::Key;
#[cfg(test)] #[cfg(test)]
use proptest_derive::Arbitrary; use proptest_derive::Arbitrary;
use std::borrow::Borrow;
use std::cmp::{Eq, PartialEq}; use std::cmp::{Eq, PartialEq};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ops::{Bound, Range, RangeFrom, RangeInclusive}; use std::ops::{Bound, Range, RangeFrom, RangeInclusive};
@ -75,17 +76,17 @@ impl BoundRange {
/// The **end** of a scan is exclusive, unless appended with an '\0', then it is inclusive. /// The **end** of a scan is exclusive, unless appended with an '\0', then it is inclusive.
/// ///
/// ```rust /// ```rust
/// use tikv_client::{BoundRange, Key}; /// use tikv_client::{BoundRange, Key, ToOwnedRange};
/// // Exclusive /// // Exclusive
/// let range = "a".to_owned().."z".to_owned(); /// let range = "a".."z";
/// assert_eq!( /// assert_eq!(
/// BoundRange::from(range).into_keys(), /// BoundRange::from(range.to_owned()).into_keys(),
/// (Key::from("a".to_owned()), Some(Key::from("z".to_owned()))), /// (Key::from("a".to_owned()), Some(Key::from("z".to_owned()))),
/// ); /// );
/// // Inclusive /// // Inclusive
/// let range = "a".to_owned()..="z".to_owned(); /// let range = "a"..="z";
/// assert_eq!( /// assert_eq!(
/// BoundRange::from(range).into_keys(), /// BoundRange::from(range.to_owned()).into_keys(),
/// (Key::from("a".to_owned()), Some(Key::from("z\0".to_owned()))), /// (Key::from("a".to_owned()), Some(Key::from("z\0".to_owned()))),
/// ); /// );
/// // Open /// // Open
@ -181,6 +182,48 @@ impl<T: Into<Key> + Eq> TryFrom<(Bound<T>, Bound<T>)> for BoundRange {
} }
} }
/// A convenience trait for converting ranges of borrowed types into a `BoundRange`.
pub trait ToOwnedRange {
/// Transform a borrowed range of some form into an owned `BoundRange`.
fn to_owned(self) -> BoundRange;
}
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for Range<&U> {
fn to_owned(self) -> BoundRange {
From::from(Range {
start: self.start.to_owned(),
end: self.end.to_owned(),
})
}
}
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for RangeFrom<&U> {
fn to_owned(self) -> BoundRange {
From::from(RangeFrom {
start: self.start.to_owned(),
})
}
}
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for RangeInclusive<&U> {
fn to_owned(self) -> BoundRange {
let (from, to) = self.into_inner();
From::from(RangeInclusive::new(from.to_owned(), to.to_owned()))
}
}
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for (&U, Option<&U>) {
fn to_owned(self) -> BoundRange {
From::from((self.0.to_owned(), self.1.map(|u| u.to_owned())))
}
}
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for (&U, &U) {
fn to_owned(self) -> BoundRange {
From::from((self.0.to_owned(), self.1.to_owned()))
}
}
fn convert_to_bound_key<K: Into<Key>>(b: Bound<K>) -> Bound<Key> { fn convert_to_bound_key<K: Into<Key>>(b: Bound<K>) -> Bound<Key> {
match b { match b {
Bound::Included(k) => Bound::Included(k.into()), Bound::Included(k) => Bound::Included(k.into()),

View File

@ -6,7 +6,7 @@ use proptest::{arbitrary::any_with, collection::size_range};
#[cfg(test)] #[cfg(test)]
use proptest_derive::Arbitrary; use proptest_derive::Arbitrary;
use std::ops::Bound; use std::ops::Bound;
use std::{fmt, str, u8}; use std::{fmt, u8};
/// The key part of a key/value pair. /// The key part of a key/value pair.
/// ///

View File

@ -6,7 +6,7 @@ mod key;
mod kvpair; mod kvpair;
mod value; mod value;
pub use bound_range::BoundRange; pub use bound_range::{BoundRange, ToOwnedRange};
pub use key::Key; pub use key::Key;
pub use kvpair::KvPair; pub use kvpair::KvPair;
pub use value::Value; pub use value::Value;

View File

@ -100,4 +100,4 @@ pub use crate::errors::ErrorKind;
#[doc(inline)] #[doc(inline)]
pub use crate::errors::Result; pub use crate::errors::Result;
#[doc(inline)] #[doc(inline)]
pub use crate::kv::{BoundRange, Key, KvPair, Value}; pub use crate::kv::{BoundRange, Key, KvPair, ToOwnedRange, Value};

View File

@ -157,12 +157,12 @@ impl Client {
/// ///
/// ```rust,no_run /// ```rust,no_run
/// # #![feature(async_await)] /// # #![feature(async_await)]
/// # use tikv_client::{Config, raw::Client}; /// # use tikv_client::{Config, raw::Client, ToOwnedRange};
/// # use futures::prelude::*; /// # use futures::prelude::*;
/// # futures::executor::block_on(async { /// # futures::executor::block_on(async {
/// let connect = Client::connect(Config::default()); /// let connect = Client::connect(Config::default());
/// let client = connect.await.unwrap(); /// let client = connect.await.unwrap();
/// let scan_request = client.with_key_only(true).scan("TiKV".to_owned()..="TiDB".to_owned(), 2); /// let scan_request = client.with_key_only(true).scan(("TiKV"..="TiDB").to_owned(), 2);
/// # }); /// # });
/// ``` /// ```
pub fn with_key_only(&self, key_only: bool) -> Client { pub fn with_key_only(&self, key_only: bool) -> Client {