use prost_types::{ListValue, Value};
use google_cloud_googleapis::spanner::v1::key_range::{EndKeyType, StartKeyType};
use google_cloud_googleapis::spanner::v1::KeyRange as InternalKeyRange;
use google_cloud_googleapis::spanner::v1::KeySet as InternalKeySet;
use crate::statement::ToKind;
#[derive(Clone)]
pub struct Key {
pub(crate) values: ListValue,
}
#[derive(Clone)]
pub struct KeySet {
pub(crate) inner: InternalKeySet,
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum RangeKind {
ClosedOpen,
ClosedClosed,
OpenClosed,
OpenOpen,
}
#[derive(Clone)]
pub struct KeyRange {
pub(crate) start: Key,
pub(crate) end: Key,
pub kind: RangeKind,
}
pub fn all_keys() -> KeySet {
KeySet {
inner: InternalKeySet {
keys: vec![],
ranges: vec![],
all: true,
},
}
}
impl From<KeySet> for InternalKeySet {
fn from(key_set: KeySet) -> Self {
key_set.inner
}
}
impl KeyRange {
pub fn new(start: Key, end: Key, kind: RangeKind) -> KeyRange {
KeyRange { start, end, kind }
}
}
impl From<KeyRange> for InternalKeyRange {
fn from(key_range: KeyRange) -> Self {
let (start, end) = match key_range.kind {
RangeKind::ClosedClosed => (
Some(StartKeyType::StartClosed(key_range.start.values)),
Some(EndKeyType::EndClosed(key_range.end.values)),
),
RangeKind::ClosedOpen => (
Some(StartKeyType::StartClosed(key_range.start.values)),
Some(EndKeyType::EndOpen(key_range.end.values)),
),
RangeKind::OpenClosed => (
Some(StartKeyType::StartOpen(key_range.start.values)),
Some(EndKeyType::EndClosed(key_range.end.values)),
),
RangeKind::OpenOpen => (
Some(StartKeyType::StartOpen(key_range.start.values)),
Some(EndKeyType::EndOpen(key_range.end.values)),
),
};
InternalKeyRange {
start_key_type: start,
end_key_type: end,
}
}
}
impl From<KeyRange> for KeySet {
fn from(key_range: KeyRange) -> Self {
KeySet {
inner: InternalKeySet {
keys: vec![],
ranges: vec![key_range.into()],
all: false,
},
}
}
}
impl Key {
pub fn new(value: &dyn ToKind) -> Key {
Key::composite(&[value])
}
pub fn composite(values: &[&dyn ToKind]) -> Key {
Key {
values: ListValue {
values: values
.iter()
.map(|x| Value {
kind: Some(x.to_kind()),
})
.collect(),
},
}
}
}
impl From<Key> for KeySet {
fn from(key: Key) -> Self {
KeySet {
inner: InternalKeySet {
keys: vec![key.values],
ranges: vec![],
all: false,
},
}
}
}
impl From<Vec<Key>> for KeySet {
fn from(keys: Vec<Key>) -> Self {
let keys = keys.into_iter().map(|key| key.values).collect();
KeySet {
inner: InternalKeySet {
keys,
ranges: vec![],
all: false,
},
}
}
}
#[cfg(test)]
mod tests {
use prost_types::value::Kind;
use google_cloud_googleapis::spanner::*;
use crate::key::*;
#[test]
fn test_key_new() {
let mut key = Key::new(&true);
match key.values.values.pop().unwrap().kind.unwrap() {
Kind::BoolValue(s) => assert!(s),
_ => panic!("invalid kind"),
}
}
#[test]
fn test_key_keys() {
let mut key = Key::composite(&[&true, &1, &"aaa"]);
match key.values.values.pop().unwrap().kind.unwrap() {
Kind::StringValue(s) => assert_eq!(s, "aaa"),
_ => panic!("invalid kind"),
}
}
#[test]
fn test_key_one() {
let mut key = Key::new(&1);
match key.values.values.pop().unwrap().kind.unwrap() {
Kind::StringValue(s) => assert_eq!(s, "1"),
_ => panic!("invalid kind"),
}
}
#[test]
fn test_key_range() {
let start = Key::new(&1);
let end = Key::new(&100);
let range = KeyRange::new(start, end, RangeKind::ClosedClosed);
let raw_range: v1::KeyRange = range.into();
match raw_range.start_key_type.unwrap() {
v1::key_range::StartKeyType::StartClosed(mut v) => match v.values.pop().unwrap().kind.unwrap() {
Kind::StringValue(v) => assert_eq!(v, "1"),
_ => panic!("invalid start kind"),
},
_ => panic!("invalid start key trype"),
}
match raw_range.end_key_type.unwrap() {
v1::key_range::EndKeyType::EndClosed(mut v) => match v.values.pop().unwrap().kind.unwrap() {
Kind::StringValue(v) => assert_eq!(v, "100"),
_ => panic!("invalid end kind"),
},
_ => panic!("invalid end key trype"),
}
}
}