|
1 | 1 | // Copyright 2019 TiKV Project Authors. Licensed under Apache-2.0.
|
2 | 2 |
|
3 |
| -use std::ops::{ |
4 |
| - Bound, Deref, DerefMut, Range, RangeFrom, RangeFull, RangeInclusive, RangeTo, RangeToInclusive, |
5 |
| -}; |
| 3 | +use std::cmp::{Eq, PartialEq}; |
| 4 | +use std::convert::TryFrom; |
| 5 | +use std::ops::{Bound, Deref, DerefMut, Range, RangeFrom, RangeInclusive}; |
6 | 6 | use std::{fmt, str, u8};
|
7 | 7 |
|
8 | 8 | use crate::{Error, Result};
|
@@ -68,6 +68,36 @@ impl Key {
|
68 | 68 | pub(crate) fn into_inner(self) -> Vec<u8> {
|
69 | 69 | self.0
|
70 | 70 | }
|
| 71 | + |
| 72 | + #[inline] |
| 73 | + fn zero_terminated(&self) -> bool { |
| 74 | + self.0.last().map(|i| *i == 0).unwrap_or(false) |
| 75 | + } |
| 76 | + |
| 77 | + #[inline] |
| 78 | + fn push_zero(&mut self) { |
| 79 | + self.0.push(0) |
| 80 | + } |
| 81 | + |
| 82 | + #[inline] |
| 83 | + fn into_lower_bound(mut self) -> Bound<Key> { |
| 84 | + if self.zero_terminated() { |
| 85 | + self.0.pop().unwrap(); |
| 86 | + Bound::Excluded(self) |
| 87 | + } else { |
| 88 | + Bound::Included(self) |
| 89 | + } |
| 90 | + } |
| 91 | + |
| 92 | + #[inline] |
| 93 | + fn into_upper_bound(mut self) -> Bound<Key> { |
| 94 | + if self.zero_terminated() { |
| 95 | + self.0.pop().unwrap(); |
| 96 | + Bound::Included(self) |
| 97 | + } else { |
| 98 | + Bound::Excluded(self) |
| 99 | + } |
| 100 | + } |
71 | 101 | }
|
72 | 102 |
|
73 | 103 | impl From<Vec<u8>> for Key {
|
@@ -320,171 +350,180 @@ impl fmt::Debug for KvPair {
|
320 | 350 | }
|
321 | 351 | }
|
322 | 352 |
|
323 |
| -/// A convenience trait for expressing ranges. |
| 353 | +/// A struct for expressing ranges. This type is semi-opaque and is not really meant for users to |
| 354 | +/// deal with directly. Most functions which operate on ranges will accept any types which |
| 355 | +/// implement `Into<BoundRange>`. |
324 | 356 | ///
|
325 | 357 | /// In TiKV, keys are an ordered sequence of bytes. This means we can have ranges over those
|
326 | 358 | /// bytes. Eg `001` is before `010`.
|
327 | 359 | ///
|
328 |
| -/// This trait has implementations for common range types like `a..b`, `a..=b` where `a` and `b` |
329 |
| -/// `impl Into<Key>`. You could implement this for your own types. |
| 360 | +/// `Into<BoundRange>` has implementations for common range types like `a..b`, `a..=b` where `a` and `b` |
| 361 | +/// `impl Into<Key>`. You can implement `Into<BoundRange>` for your own types by using `try_from`. |
| 362 | +/// |
| 363 | +/// Invariant: a range may not be unbounded below. |
330 | 364 | ///
|
331 | 365 | /// ```rust
|
332 |
| -/// use tikv_client::{KeyRange, Key}; |
| 366 | +/// use tikv_client::{BoundRange, Key}; |
333 | 367 | /// use std::ops::{Range, RangeInclusive, RangeTo, RangeToInclusive, RangeFrom, RangeFull, Bound};
|
| 368 | +/// # use std::convert::TryInto; |
334 | 369 | ///
|
335 | 370 | /// let explict_range: Range<Key> = Range { start: Key::from("Rust"), end: Key::from("TiKV") };
|
336 |
| -/// let from_explict_range = explict_range.into_bounds(); |
| 371 | +/// let from_explict_range: BoundRange = explict_range.into(); |
337 | 372 | ///
|
338 | 373 | /// let range: Range<&str> = "Rust".."TiKV";
|
339 |
| -/// let from_range = range.into_bounds(); |
| 374 | +/// let from_range: BoundRange = range.into(); |
340 | 375 | /// assert_eq!(from_explict_range, from_range);
|
341 | 376 | ///
|
342 | 377 | /// let range: RangeInclusive<&str> = "Rust"..="TiKV";
|
343 |
| -/// let from_range = range.into_bounds(); |
| 378 | +/// let from_range: BoundRange = range.into(); |
344 | 379 | /// assert_eq!(
|
| 380 | +/// from_range, |
345 | 381 | /// (Bound::Included(Key::from("Rust")), Bound::Included(Key::from("TiKV"))),
|
346 |
| -/// from_range |
347 | 382 | /// );
|
348 | 383 | ///
|
349 | 384 | /// let range_from: RangeFrom<&str> = "Rust"..;
|
350 |
| -/// let from_range_from = range_from.into_bounds(); |
| 385 | +/// let from_range_from: BoundRange = range_from.into(); |
351 | 386 | /// assert_eq!(
|
352 |
| -/// (Bound::Included(Key::from("Rust")), Bound::Unbounded), |
353 | 387 | /// from_range_from,
|
354 |
| -/// ); |
355 |
| -/// |
356 |
| -/// let range_to: RangeTo<&str> = .."TiKV"; |
357 |
| -/// let from_range_to = range_to.into_bounds(); |
358 |
| -/// assert_eq!( |
359 |
| -/// (Bound::Unbounded, Bound::Excluded(Key::from("TiKV"))), |
360 |
| -/// from_range_to, |
361 |
| -/// ); |
362 |
| -/// |
363 |
| -/// let range_to_inclusive: RangeToInclusive<&str> = ..="TiKV"; |
364 |
| -/// let from_range_to_inclusive = range_to_inclusive.into_bounds(); |
365 |
| -/// assert_eq!( |
366 |
| -/// (Bound::Unbounded, Bound::Included(Key::from("TiKV"))), |
367 |
| -/// from_range_to_inclusive, |
368 |
| -/// ); |
369 |
| -/// |
370 |
| -/// let range_full: RangeFull = ..; |
371 |
| -/// let from_range_full = range_full.into_bounds(); |
372 |
| -/// assert_eq!( |
373 |
| -/// (Bound::Unbounded, Bound::Unbounded), |
374 |
| -/// from_range_full |
| 388 | +/// (Bound::Included(Key::from("Rust")), Bound::Unbounded), |
375 | 389 | /// );
|
376 | 390 | /// ```
|
377 | 391 | ///
|
378 |
| -/// **But, you should not need to worry about all this:** Many functions accept a `impl KeyRange` |
| 392 | +/// **But, you should not need to worry about all this:** Most functions which operate |
| 393 | +/// on ranges will accept any types which implement `Into<BoundRange>`. |
379 | 394 | /// which means all of the above types can be passed directly to those functions.
|
380 |
| -pub trait KeyRange: Sized { |
381 |
| - fn into_bounds(self) -> (Bound<Key>, Bound<Key>); |
| 395 | +#[derive(Clone, Debug, Eq, PartialEq)] |
| 396 | +pub struct BoundRange { |
| 397 | + from: Bound<Key>, |
| 398 | + to: Bound<Key>, |
| 399 | +} |
| 400 | + |
| 401 | +impl BoundRange { |
| 402 | + /// Create a new BoundRange. |
| 403 | + /// |
| 404 | + /// The caller must ensure that `from` is not `Unbounded`. |
| 405 | + fn new(from: Bound<Key>, to: Bound<Key>) -> BoundRange { |
| 406 | + // Debug assert because this function is private. |
| 407 | + debug_assert!(from != Bound::Unbounded); |
| 408 | + BoundRange { from, to } |
| 409 | + } |
| 410 | + |
382 | 411 | /// Ranges used in scanning TiKV have a particularity to them.
|
383 | 412 | ///
|
384 | 413 | /// The **start** of a scan is inclusive, unless appended with an '\0', then it is exclusive.
|
385 | 414 | ///
|
386 | 415 | /// The **end** of a scan is exclusive, unless appended with an '\0', then it is inclusive.
|
387 | 416 | ///
|
388 | 417 | /// ```rust
|
389 |
| - /// use tikv_client::{KeyRange, Key}; |
| 418 | + /// use tikv_client::{BoundRange, Key}; |
390 | 419 | /// // Exclusive
|
391 | 420 | /// let range = "a".."z";
|
392 | 421 | /// assert_eq!(
|
393 |
| - /// range.into_keys().unwrap(), |
394 |
| - /// (Key::from("a"), Some(Key::from("z"))) |
| 422 | + /// BoundRange::from(range).into_keys(), |
| 423 | + /// (Key::from("a"), Some(Key::from("z"))), |
395 | 424 | /// );
|
396 | 425 | /// // Inclusive
|
397 | 426 | /// let range = "a"..="z";
|
398 | 427 | /// assert_eq!(
|
399 |
| - /// range.into_keys().unwrap(), |
400 |
| - /// (Key::from("a"), Some(Key::from("z\0"))) |
| 428 | + /// BoundRange::from(range).into_keys(), |
| 429 | + /// (Key::from("a"), Some(Key::from("z\0"))), |
401 | 430 | /// );
|
402 | 431 | /// // Open
|
403 | 432 | /// let range = "a"..;
|
404 | 433 | /// assert_eq!(
|
405 |
| - /// range.into_keys().unwrap(), |
406 |
| - /// (Key::from("a"), None) |
| 434 | + /// BoundRange::from(range).into_keys(), |
| 435 | + /// (Key::from("a"), None), |
407 | 436 | /// );
|
408 | 437 | // ```
|
409 |
| - fn into_keys(self) -> Result<(Key, Option<Key>)> { |
410 |
| - range_to_keys(self.into_bounds()) |
411 |
| - } |
412 |
| -} |
413 |
| - |
414 |
| -fn range_to_keys(range: (Bound<Key>, Bound<Key>)) -> Result<(Key, Option<Key>)> { |
415 |
| - let start = match range.0 { |
416 |
| - Bound::Included(v) => v, |
417 |
| - Bound::Excluded(mut v) => { |
418 |
| - v.0.push(b"\0"[0]); |
419 |
| - v |
420 |
| - } |
421 |
| - Bound::Unbounded => Err(Error::invalid_key_range())?, |
422 |
| - }; |
423 |
| - let end = match range.1 { |
424 |
| - Bound::Included(mut v) => { |
425 |
| - v.0.push(b"\0"[0]); |
426 |
| - Some(v) |
427 |
| - } |
428 |
| - Bound::Excluded(v) => Some(v), |
429 |
| - Bound::Unbounded => None, |
430 |
| - }; |
431 |
| - Ok((start, end)) |
432 |
| -} |
433 |
| - |
434 |
| -impl<T: Into<Key>> KeyRange for Range<T> { |
435 |
| - fn into_bounds(self) -> (Bound<Key>, Bound<Key>) { |
436 |
| - ( |
437 |
| - Bound::Included(self.start.into()), |
438 |
| - Bound::Excluded(self.end.into()), |
| 438 | + pub fn into_keys(self) -> (Key, Option<Key>) { |
| 439 | + let start = match self.from { |
| 440 | + Bound::Included(v) => v, |
| 441 | + Bound::Excluded(mut v) => { |
| 442 | + v.push_zero(); |
| 443 | + v |
| 444 | + } |
| 445 | + Bound::Unbounded => unreachable!(), |
| 446 | + }; |
| 447 | + let end = match self.to { |
| 448 | + Bound::Included(mut v) => { |
| 449 | + v.push_zero(); |
| 450 | + Some(v) |
| 451 | + } |
| 452 | + Bound::Excluded(v) => Some(v), |
| 453 | + Bound::Unbounded => None, |
| 454 | + }; |
| 455 | + (start, end) |
| 456 | + } |
| 457 | +} |
| 458 | + |
| 459 | +impl<T: Into<Key> + Clone> PartialEq<(Bound<T>, Bound<T>)> for BoundRange { |
| 460 | + fn eq(&self, other: &(Bound<T>, Bound<T>)) -> bool { |
| 461 | + self.from == convert_to_bound_key(other.0.clone()) |
| 462 | + && self.to == convert_to_bound_key(other.1.clone()) |
| 463 | + } |
| 464 | +} |
| 465 | + |
| 466 | +impl<T: Into<Key>> From<Range<T>> for BoundRange { |
| 467 | + fn from(other: Range<T>) -> BoundRange { |
| 468 | + BoundRange::new( |
| 469 | + Bound::Included(other.start.into()), |
| 470 | + Bound::Excluded(other.end.into()), |
439 | 471 | )
|
440 | 472 | }
|
441 | 473 | }
|
442 | 474 |
|
443 |
| -impl<T: Into<Key>> KeyRange for RangeFrom<T> { |
444 |
| - fn into_bounds(self) -> (Bound<Key>, Bound<Key>) { |
445 |
| - (Bound::Included(self.start.into()), Bound::Unbounded) |
| 475 | +impl<T: Into<Key>> From<RangeFrom<T>> for BoundRange { |
| 476 | + fn from(other: RangeFrom<T>) -> BoundRange { |
| 477 | + BoundRange::new(Bound::Included(other.start.into()), Bound::Unbounded) |
446 | 478 | }
|
447 | 479 | }
|
448 | 480 |
|
449 |
| -impl KeyRange for RangeFull { |
450 |
| - fn into_bounds(self) -> (Bound<Key>, Bound<Key>) { |
451 |
| - (Bound::Unbounded, Bound::Unbounded) |
| 481 | +impl<T: Into<Key>> From<RangeInclusive<T>> for BoundRange { |
| 482 | + fn from(other: RangeInclusive<T>) -> BoundRange { |
| 483 | + let (start, end) = other.into_inner(); |
| 484 | + BoundRange::new(Bound::Included(start.into()), Bound::Included(end.into())) |
452 | 485 | }
|
453 | 486 | }
|
454 | 487 |
|
455 |
| -impl<T: Into<Key>> KeyRange for RangeInclusive<T> { |
456 |
| - fn into_bounds(self) -> (Bound<Key>, Bound<Key>) { |
457 |
| - let (start, end) = self.into_inner(); |
458 |
| - (Bound::Included(start.into()), Bound::Included(end.into())) |
459 |
| - } |
460 |
| -} |
| 488 | +impl<T: Into<Key>> From<(T, Option<T>)> for BoundRange { |
| 489 | + fn from(other: (T, Option<T>)) -> BoundRange { |
| 490 | + let to = match other.1 { |
| 491 | + None => Bound::Unbounded, |
| 492 | + Some(to) => to.into().into_upper_bound(), |
| 493 | + }; |
461 | 494 |
|
462 |
| -impl<T: Into<Key>> KeyRange for RangeTo<T> { |
463 |
| - fn into_bounds(self) -> (Bound<Key>, Bound<Key>) { |
464 |
| - (Bound::Unbounded, Bound::Excluded(self.end.into())) |
| 495 | + BoundRange::new(other.0.into().into_lower_bound(), to) |
465 | 496 | }
|
466 | 497 | }
|
467 | 498 |
|
468 |
| -impl<T: Into<Key>> KeyRange for RangeToInclusive<T> { |
469 |
| - fn into_bounds(self) -> (Bound<Key>, Bound<Key>) { |
470 |
| - (Bound::Unbounded, Bound::Included(self.end.into())) |
| 499 | +impl<T: Into<Key>> From<(T, T)> for BoundRange { |
| 500 | + fn from(other: (T, T)) -> BoundRange { |
| 501 | + BoundRange::new( |
| 502 | + other.0.into().into_lower_bound(), |
| 503 | + other.1.into().into_upper_bound(), |
| 504 | + ) |
471 | 505 | }
|
472 | 506 | }
|
473 | 507 |
|
474 |
| -impl<T: Into<Key>> KeyRange for (Bound<T>, Bound<T>) { |
475 |
| - fn into_bounds(self) -> (Bound<Key>, Bound<Key>) { |
476 |
| - (convert_to_bound_key(self.0), convert_to_bound_key(self.1)) |
| 508 | +impl<T: Into<Key> + Eq> TryFrom<(Bound<T>, Bound<T>)> for BoundRange { |
| 509 | + type Error = Error; |
| 510 | + |
| 511 | + fn try_from(bounds: (Bound<T>, Bound<T>)) -> Result<BoundRange> { |
| 512 | + if bounds.0 == Bound::Unbounded { |
| 513 | + Err(Error::invalid_key_range()) |
| 514 | + } else { |
| 515 | + Ok(BoundRange::new( |
| 516 | + convert_to_bound_key(bounds.0), |
| 517 | + convert_to_bound_key(bounds.1), |
| 518 | + )) |
| 519 | + } |
477 | 520 | }
|
478 | 521 | }
|
479 | 522 |
|
480 |
| -fn convert_to_bound_key<K>(b: Bound<K>) -> Bound<Key> |
481 |
| -where |
482 |
| - K: Into<Key>, |
483 |
| -{ |
484 |
| - use std::ops::Bound::*; |
| 523 | +fn convert_to_bound_key<K: Into<Key>>(b: Bound<K>) -> Bound<Key> { |
485 | 524 | match b {
|
486 |
| - Included(k) => Included(k.into()), |
487 |
| - Excluded(k) => Excluded(k.into()), |
488 |
| - Unbounded => Unbounded, |
| 525 | + Bound::Included(k) => Bound::Included(k.into()), |
| 526 | + Bound::Excluded(k) => Bound::Excluded(k.into()), |
| 527 | + Bound::Unbounded => Bound::Unbounded, |
489 | 528 | }
|
490 | 529 | }
|
0 commit comments