Skip to content

Commit 7bc06c0

Browse files
authored
Merge pull request #80 from nrc/kv-ref-into
Don't implement From<&'static str> for Key and Value
2 parents e8b04a9 + 0ed7c8a commit 7bc06c0

File tree

9 files changed

+102
-73
lines changed

9 files changed

+102
-73
lines changed

examples/raw.rs

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
// Copyright 2018 TiKV Project Authors. Licensed under Apache-2.0.
22

33
#![feature(async_await, await_macro)]
4-
#![type_length_limit = "3081103"]
4+
#![type_length_limit = "8165158"]
55

66
mod common;
77

88
use crate::common::parse_args;
9-
use tikv_client::{raw::Client, Config, Key, KvPair, Result, Value};
9+
use tikv_client::{raw::Client, Config, Key, KvPair, Result, ToOwnedRange, Value};
1010

1111
const KEY: &str = "TiKV";
1212
const VALUE: &str = "Rust";
@@ -35,7 +35,7 @@ async fn main() -> Result<()> {
3535
// place.
3636
//
3737
// Here we set the key `TiKV` to have the value `Rust` associated with it.
38-
client.put(KEY, VALUE).await.unwrap(); // Returns a `tikv_client::Error` on failure.
38+
client.put(KEY.to_owned(), VALUE.to_owned()).await.unwrap(); // Returns a `tikv_client::Error` on failure.
3939
println!("Put key {:?}, value {:?}.", KEY, VALUE);
4040

4141
// Unlike a standard Rust HashMap all calls take owned values. This is because under the hood
@@ -47,33 +47,36 @@ async fn main() -> Result<()> {
4747
//
4848
// It is best to pass a `Vec<u8>` in terms of explictness and speed. `String`s and a few other
4949
// types are supported as well, but it all ends up as `Vec<u8>` in the end.
50-
let value: Option<Value> = client.get(KEY).await?;
51-
assert_eq!(value, Some(Value::from(VALUE)));
52-
println!("Get key {:?} returned value {:?}.", Key::from(KEY), value);
50+
let value: Option<Value> = client.get(KEY.to_owned()).await?;
51+
assert_eq!(value, Some(Value::from(VALUE.to_owned())));
52+
println!("Get key `{}` returned value {:?}.", KEY, value);
5353

5454
// You can also set the `ColumnFamily` used by the request.
5555
// This is *advanced usage* and should have some special considerations.
56-
client.delete(KEY).await.expect("Could not delete value");
57-
println!("Key: {:?} deleted", Key::from(KEY));
56+
client
57+
.delete(KEY.to_owned())
58+
.await
59+
.expect("Could not delete value");
60+
println!("Key: `{}` deleted", KEY);
5861

5962
// Here we check if the key has been deleted from the key-value store.
6063
let value: Option<Value> = client
61-
.get(KEY)
64+
.get(KEY.to_owned())
6265
.await
6366
.expect("Could not get just deleted entry");
6467
assert!(value.is_none());
6568

6669
// You can ask to write multiple key-values at the same time, it is much more
6770
// performant because it is passed in one request to the key-value store.
6871
let pairs = vec![
69-
KvPair::from(("k1", "v1")),
70-
KvPair::from(("k2", "v2")),
71-
KvPair::from(("k3", "v3")),
72+
KvPair::from(("k1".to_owned(), "v1".to_owned())),
73+
KvPair::from(("k2".to_owned(), "v2".to_owned())),
74+
KvPair::from(("k3".to_owned(), "v3".to_owned())),
7275
];
7376
client.batch_put(pairs).await.expect("Could not put pairs");
7477

7578
// Same thing when you want to retrieve multiple values.
76-
let keys = vec![Key::from("k1"), Key::from("k2")];
79+
let keys = vec![Key::from("k1".to_owned()), Key::from("k2".to_owned())];
7780
let values = client
7881
.batch_get(keys.clone())
7982
.await
@@ -86,12 +89,15 @@ async fn main() -> Result<()> {
8689
let end = "k2";
8790
let pairs = client
8891
.with_key_only(true)
89-
.scan(start..=end, 10)
92+
.scan((start..=end).to_owned(), 10)
9093
.await
9194
.expect("Could not scan");
9295

9396
let keys: Vec<_> = pairs.into_iter().map(|p| p.key().clone()).collect();
94-
assert_eq!(&keys, &[Key::from("k1"), Key::from("k2")]);
97+
assert_eq!(
98+
&keys,
99+
&[Key::from("k1".to_owned()), Key::from("k2".to_owned())]
100+
);
95101
println!("Scaning from {:?} to {:?} gives: {:?}", start, end, keys);
96102

97103
// Cleanly exit.

src/kv/bound_range.rs

Lines changed: 57 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
use super::Key;
44
#[cfg(test)]
55
use proptest_derive::Arbitrary;
6+
use std::borrow::Borrow;
67
use std::cmp::{Eq, PartialEq};
78
use std::convert::TryFrom;
89
use std::ops::{Bound, Range, RangeFrom, RangeInclusive};
@@ -26,25 +27,25 @@ use crate::{Error, Result};
2627
/// use std::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive, RangeFrom, RangeFull, Bound};
2728
/// # use std::convert::TryInto;
2829
///
29-
/// let explict_range: Range<Key> = Range { start: Key::from("Rust"), end: Key::from("TiKV") };
30+
/// let explict_range: Range<Key> = Range { start: Key::from("Rust".to_owned()), end: Key::from("TiKV".to_owned()) };
3031
/// let from_explict_range: BoundRange = explict_range.into();
3132
///
32-
/// let range: Range<&str> = "Rust".."TiKV";
33+
/// let range: Range<String> = "Rust".to_owned().."TiKV".to_owned();
3334
/// let from_range: BoundRange = range.into();
3435
/// assert_eq!(from_explict_range, from_range);
3536
///
36-
/// let range: RangeInclusive<&str> = "Rust"..="TiKV";
37+
/// let range: RangeInclusive<String> = "Rust".to_owned()..="TiKV".to_owned();
3738
/// let from_range: BoundRange = range.into();
3839
/// assert_eq!(
3940
/// from_range,
40-
/// (Bound::Included(Key::from("Rust")), Bound::Included(Key::from("TiKV"))),
41+
/// (Bound::Included(Key::from("Rust".to_owned())), Bound::Included(Key::from("TiKV".to_owned()))),
4142
/// );
4243
///
43-
/// let range_from: RangeFrom<&str> = "Rust"..;
44+
/// let range_from: RangeFrom<String> = "Rust".to_owned()..;
4445
/// let from_range_from: BoundRange = range_from.into();
4546
/// assert_eq!(
4647
/// from_range_from,
47-
/// (Bound::Included(Key::from("Rust")), Bound::Unbounded),
48+
/// (Bound::Included(Key::from("Rust".to_owned())), Bound::Unbounded),
4849
/// );
4950
/// ```
5051
///
@@ -75,24 +76,24 @@ impl BoundRange {
7576
/// The **end** of a scan is exclusive, unless appended with an '\0', then it is inclusive.
7677
///
7778
/// ```rust
78-
/// use tikv_client::{BoundRange, Key};
79+
/// use tikv_client::{BoundRange, Key, ToOwnedRange};
7980
/// // Exclusive
8081
/// let range = "a".."z";
8182
/// assert_eq!(
82-
/// BoundRange::from(range).into_keys(),
83-
/// (Key::from("a"), Some(Key::from("z"))),
83+
/// BoundRange::from(range.to_owned()).into_keys(),
84+
/// (Key::from("a".to_owned()), Some(Key::from("z".to_owned()))),
8485
/// );
8586
/// // Inclusive
8687
/// let range = "a"..="z";
8788
/// assert_eq!(
88-
/// BoundRange::from(range).into_keys(),
89-
/// (Key::from("a"), Some(Key::from("z\0"))),
89+
/// BoundRange::from(range.to_owned()).into_keys(),
90+
/// (Key::from("a".to_owned()), Some(Key::from("z\0".to_owned()))),
9091
/// );
9192
/// // Open
92-
/// let range = "a"..;
93+
/// let range = "a".to_owned()..;
9394
/// assert_eq!(
9495
/// BoundRange::from(range).into_keys(),
95-
/// (Key::from("a"), None),
96+
/// (Key::from("a".to_owned()), None),
9697
/// );
9798
// ```
9899
pub fn into_keys(self) -> (Key, Option<Key>) {
@@ -116,6 +117,7 @@ impl BoundRange {
116117
}
117118
}
118119

120+
// FIXME `==` should not `clone`
119121
impl<T: Into<Key> + Clone> PartialEq<(Bound<T>, Bound<T>)> for BoundRange {
120122
fn eq(&self, other: &(Bound<T>, Bound<T>)) -> bool {
121123
self.from == convert_to_bound_key(other.0.clone())
@@ -180,6 +182,48 @@ impl<T: Into<Key> + Eq> TryFrom<(Bound<T>, Bound<T>)> for BoundRange {
180182
}
181183
}
182184

185+
/// A convenience trait for converting ranges of borrowed types into a `BoundRange`.
186+
pub trait ToOwnedRange {
187+
/// Transform a borrowed range of some form into an owned `BoundRange`.
188+
fn to_owned(self) -> BoundRange;
189+
}
190+
191+
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for Range<&U> {
192+
fn to_owned(self) -> BoundRange {
193+
From::from(Range {
194+
start: self.start.to_owned(),
195+
end: self.end.to_owned(),
196+
})
197+
}
198+
}
199+
200+
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for RangeFrom<&U> {
201+
fn to_owned(self) -> BoundRange {
202+
From::from(RangeFrom {
203+
start: self.start.to_owned(),
204+
})
205+
}
206+
}
207+
208+
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for RangeInclusive<&U> {
209+
fn to_owned(self) -> BoundRange {
210+
let (from, to) = self.into_inner();
211+
From::from(RangeInclusive::new(from.to_owned(), to.to_owned()))
212+
}
213+
}
214+
215+
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for (&U, Option<&U>) {
216+
fn to_owned(self) -> BoundRange {
217+
From::from((self.0.to_owned(), self.1.map(|u| u.to_owned())))
218+
}
219+
}
220+
221+
impl<T: Into<Key> + Borrow<U>, U: ToOwned<Owned = T> + ?Sized> ToOwnedRange for (&U, &U) {
222+
fn to_owned(self) -> BoundRange {
223+
From::from((self.0.to_owned(), self.1.to_owned()))
224+
}
225+
}
226+
183227
fn convert_to_bound_key<K: Into<Key>>(b: Bound<K>) -> Bound<Key> {
184228
match b {
185229
Bound::Included(k) => Bound::Included(k.into()),

src/kv/key.rs

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,26 +6,21 @@ use proptest::{arbitrary::any_with, collection::size_range};
66
#[cfg(test)]
77
use proptest_derive::Arbitrary;
88
use std::ops::Bound;
9-
use std::{fmt, str, u8};
9+
use std::{fmt, u8};
1010

1111
/// The key part of a key/value pair.
1212
///
1313
/// In TiKV, keys are an ordered sequence of bytes. This has an advantage over choosing `String` as
1414
/// valid `UTF-8` is not required. This means that the user is permitted to store any data they wish,
1515
/// as long as it can be represented by bytes. (Which is to say, pretty much anything!)
1616
///
17-
/// This type also implements `From` for many types. With one exception, these are all done without
18-
/// reallocation. Using a `&'static str`, like many examples do for simplicity, has an internal
19-
/// allocation cost.
20-
///
21-
/// This type wraps around an owned value, so it should be treated it like `String` or `Vec<u8>`
22-
/// over a `&str` or `&[u8]`.
17+
/// This type wraps around an owned value, so it should be treated it like `String` or `Vec<u8>`.
2318
///
2419
/// ```rust
2520
/// use tikv_client::Key;
2621
///
2722
/// let static_str: &'static str = "TiKV";
28-
/// let from_static_str = Key::from(static_str);
23+
/// let from_static_str = Key::from(static_str.to_owned());
2924
///
3025
/// let string: String = String::from(static_str);
3126
/// let from_string = Key::from(string);
@@ -104,12 +99,6 @@ impl From<String> for Key {
10499
}
105100
}
106101

107-
impl From<&'static str> for Key {
108-
fn from(v: &'static str) -> Key {
109-
Key(v.as_bytes().to_vec())
110-
}
111-
}
112-
113102
impl Into<Vec<u8>> for Key {
114103
fn into(self) -> Vec<u8> {
115104
self.0

src/kv/kvpair.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ use std::{fmt, str};
99
///
1010
/// ```rust
1111
/// # use tikv_client::{Key, Value, KvPair};
12-
/// let key = "key";
13-
/// let value = "value";
14-
/// let constructed = KvPair::new(key, value);
12+
/// let key = "key".to_owned();
13+
/// let value = "value".to_owned();
14+
/// let constructed = KvPair::new(key.clone(), value.clone());
1515
/// let from_tuple = KvPair::from((key, value));
1616
/// assert_eq!(constructed, from_tuple);
1717
/// ```

src/kv/mod.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
// Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
22
use std::{fmt, u8};
33

4+
mod bound_range;
45
mod key;
5-
pub use key::Key;
6-
mod value;
7-
pub use value::Value;
86
mod kvpair;
7+
mod value;
8+
9+
pub use bound_range::{BoundRange, ToOwnedRange};
10+
pub use key::Key;
911
pub use kvpair::KvPair;
10-
mod bound_range;
11-
pub use bound_range::BoundRange;
12+
pub use value::Value;
1213

1314
struct HexRepr<'a>(pub &'a [u8]);
1415

src/kv/value.rs

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,13 @@ use std::{fmt, str, u8};
1313
/// as valid `UTF-8` is not required. This means that the user is permitted to store any data they wish,
1414
/// as long as it can be represented by bytes. (Which is to say, pretty much anything!)
1515
///
16-
/// This type also implements `From` for many types. With one exception, these are all done without
17-
/// reallocation. Using a `&'static str`, like many examples do for simplicity, has an internal
18-
/// allocation cost.
19-
///
20-
/// This type wraps around an owned value, so it should be treated it like `String` or `Vec<u8>`
21-
/// over a `&str` or `&[u8]`.
16+
/// This type wraps around an owned value, so it should be treated it like `String` or `Vec<u8>`.
2217
///
2318
/// ```rust
2419
/// use tikv_client::Value;
2520
///
2621
/// let static_str: &'static str = "TiKV";
27-
/// let from_static_str = Value::from(static_str);
22+
/// let from_static_str = Value::from(static_str.to_owned());
2823
///
2924
/// let string: String = String::from(static_str);
3025
/// let from_string = Value::from(string);
@@ -73,12 +68,6 @@ impl From<String> for Value {
7368
}
7469
}
7570

76-
impl From<&'static str> for Value {
77-
fn from(v: &'static str) -> Value {
78-
Value(v.as_bytes().to_vec())
79-
}
80-
}
81-
8271
impl Into<Vec<u8>> for Value {
8372
fn into(self) -> Vec<u8> {
8473
self.0

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,4 @@ pub use crate::errors::ErrorKind;
100100
#[doc(inline)]
101101
pub use crate::errors::Result;
102102
#[doc(inline)]
103-
pub use crate::kv::{BoundRange, Key, KvPair, Value};
103+
pub use crate::kv::{BoundRange, Key, KvPair, ToOwnedRange, Value};

src/raw/client.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ impl Client {
137137
/// # futures::executor::block_on(async {
138138
/// let connect = Client::connect(Config::default());
139139
/// let client = connect.await.unwrap();
140-
/// let get_request = client.with_cf("write").get("foo");
140+
/// let get_request = client.with_cf("write").get("foo".to_owned());
141141
/// # });
142142
/// ```
143143
pub fn with_cf(&self, cf: impl Into<ColumnFamily>) -> Client {
@@ -157,12 +157,12 @@ impl Client {
157157
///
158158
/// ```rust,no_run
159159
/// # #![feature(async_await)]
160-
/// # use tikv_client::{Config, raw::Client};
160+
/// # use tikv_client::{Config, raw::Client, ToOwnedRange};
161161
/// # use futures::prelude::*;
162162
/// # futures::executor::block_on(async {
163163
/// let connect = Client::connect(Config::default());
164164
/// let client = connect.await.unwrap();
165-
/// let scan_request = client.with_key_only(true).scan("TiKV"..="TiDB", 2);
165+
/// let scan_request = client.with_key_only(true).scan(("TiKV"..="TiDB").to_owned(), 2);
166166
/// # });
167167
/// ```
168168
pub fn with_key_only(&self, key_only: bool) -> Client {

0 commit comments

Comments
 (0)