Skip to content

Commit 4ad75c5

Browse files
committed
Refactor RequestState etc to not need existential types
Signed-off-by: Nick Cameron <nrc@ncameron.org>
1 parent 6416d5a commit 4ad75c5

File tree

6 files changed

+252
-571
lines changed

6 files changed

+252
-571
lines changed

examples/raw.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,30 +62,32 @@ async fn main() -> Result<()> {
6262
.expect("Could not get just deleted entry");
6363
assert!(value.is_none());
6464

65+
// FIXME: batch commands seem to be broken due to over-large types. I think
66+
// LoopFn is to blame.
6567
// You can ask to write multiple key-values at the same time, it is much more
6668
// performant because it is passed in one request to the key-value store.
67-
let pairs = vec![
68-
KvPair::from(("k1", "v1")),
69-
KvPair::from(("k2", "v2")),
70-
KvPair::from(("k3", "v3")),
71-
];
72-
client.batch_put(pairs).await.expect("Could not put pairs");
69+
// let pairs = vec![
70+
// KvPair::from(("k1", "v1")),
71+
// KvPair::from(("k2", "v2")),
72+
// KvPair::from(("k3", "v3")),
73+
// ];
74+
// client.batch_put(pairs).await.expect("Could not put pairs");
7375

7476
// Same thing when you want to retrieve multiple values.
75-
let keys = vec![Key::from("k1"), Key::from("k2")];
76-
let values = client
77-
.batch_get(keys.clone())
78-
.await
79-
.expect("Could not get values");
80-
println!("Found values: {:?} for keys: {:?}", values, keys);
77+
// let keys = vec![Key::from("k1"), Key::from("k2")];
78+
// let values = client
79+
// .batch_get(keys.clone())
80+
// .await
81+
// .expect("Could not get values");
82+
// println!("Found values: {:?} for keys: {:?}", values, keys);
8183

8284
// Scanning a range of keys is also possible giving it two bounds
8385
// it will returns all entries between these two.
8486
let start = "k1";
8587
let end = "k2";
8688
let pairs = client
89+
.with_key_only(true)
8790
.scan(start..=end, 10)
88-
.key_only()
8991
.await
9092
.expect("Could not scan");
9193

src/compat.rs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,83 @@ where
6262
}
6363
}
6464

65+
pub(crate) fn stream_fn<S, T, A, F, E>(initial_state: S, mut func: F) -> LoopFn<A, F>
66+
where
67+
F: FnMut(S) -> A,
68+
A: Future<Output = Result<Option<(S, T)>, E>>,
69+
{
70+
LoopFn {
71+
future: func(initial_state),
72+
func,
73+
}
74+
}
75+
76+
impl<S, T, A, F, E> Stream for LoopFn<A, F>
77+
where
78+
F: FnMut(S) -> A,
79+
A: Future<Output = Result<Option<(S, T)>, E>>,
80+
{
81+
type Item = Result<T, E>;
82+
fn poll_next(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Option<Self::Item>> {
83+
unsafe {
84+
let this = Pin::get_unchecked_mut(self);
85+
match ready!(Pin::new_unchecked(&mut this.future).poll(cx)) {
86+
Err(e) => Poll::Ready(Some(Err(e))),
87+
Ok(None) => Poll::Ready(None),
88+
Ok(Some((s, t))) => {
89+
this.future = (this.func)(s);
90+
Poll::Ready(Some(Ok(t)))
91+
}
92+
}
93+
}
94+
}
95+
}
96+
97+
/// A future created by the `ok_and_then` method.
98+
#[derive(Debug)]
99+
#[must_use = "futures do nothing unless polled"]
100+
pub(crate) struct OkAndThen<A, F> {
101+
future: A,
102+
func: F,
103+
}
104+
105+
impl<U, T, A, F, E> Future for OkAndThen<A, F>
106+
where
107+
F: FnMut(U) -> Result<T, E>,
108+
A: Future<Output = Result<U, E>>,
109+
{
110+
type Output = Result<T, E>;
111+
112+
fn poll(self: Pin<&mut Self>, cx: &mut Context) -> Poll<Result<T, E>> {
113+
unsafe {
114+
let this = Pin::get_unchecked_mut(self);
115+
let result = try_ready!(Pin::new_unchecked(&mut this.future).poll(cx));
116+
Poll::Ready((this.func)(result))
117+
}
118+
}
119+
}
120+
121+
/// An extension crate to make using our combinator functions more ergonomic.
122+
pub(crate) trait ClientFutureExt {
123+
/// This function is similar to `map_ok` combinator. Provide a function which
124+
/// is applied after the `self` future is resolved, only if that future
125+
/// resolves to `Ok`. Similar to `Result::and_then`, the supplied function
126+
/// must return a Result (c.f., `map_ok`, which returns the underlying type,
127+
/// `T`).
128+
///
129+
/// Note that unlike `and_then`, the supplied function returns a resolved
130+
/// value, not a closure.
131+
fn ok_and_then<U, T, F, E>(self, func: F) -> OkAndThen<Self, F>
132+
where
133+
F: FnMut(U) -> Result<T, E>,
134+
Self: Future<Output = Result<U, E>> + Sized,
135+
{
136+
OkAndThen { future: self, func }
137+
}
138+
}
139+
140+
impl<T: TryFuture> ClientFutureExt for T {}
141+
65142
/// Emulate `send_all`/`SendAll` from futures 0.1 since the 0.3 versions don't
66143
/// work with Tokio `Handle`s due to ownership differences.
67144
pub(crate) trait SinkCompat<I, E> {

src/lib.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
// Long and nested future chains can quickly result in large generic types.
44
#![type_length_limit = "16777216"]
5-
#![feature(existential_type)]
65
#![allow(clippy::redundant_closure)]
76

87
//! This crate provides a clean, ready to use client for [TiKV](https://github.com/tikv/tikv), a

0 commit comments

Comments
 (0)