Skip to content

Commit f983394

Browse files
committed
RSCBC-256: Add some idiomatic functionality to collections ds
1 parent 9465b17 commit f983394

2 files changed

Lines changed: 157 additions & 32 deletions

File tree

sdk/couchbase/src/collection_ds.rs

Lines changed: 38 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,9 @@ use tracing::Instrument;
6262
/// ```
6363
#[derive(Clone)]
6464
pub struct CouchbaseList<'a> {
65-
pub collection: &'a Collection,
66-
pub id: String,
67-
pub options: CouchbaseListOptions,
65+
collection: &'a Collection,
66+
id: String,
67+
options: CouchbaseListOptions,
6868
}
6969

7070
impl Collection {
@@ -250,11 +250,11 @@ impl CouchbaseList<'_> {
250250
result
251251
}
252252

253-
/// Returns the index of the first occurrence of the given value, or `-1` if not found.
253+
/// Returns the index of the first occurrence of the given value, or `None` if not found.
254254
pub async fn position<V: PartialEq + DeserializeOwned>(
255255
&self,
256-
value: V,
257-
) -> crate::error::Result<isize> {
256+
value: &V,
257+
) -> crate::error::Result<Option<usize>> {
258258
let ctx = self
259259
.collection
260260
.tracing_client
@@ -267,12 +267,7 @@ impl CouchbaseList<'_> {
267267
let result = async {
268268
let get_res = self.collection.get(&self.id, None).await?;
269269
let list_contents: Vec<V> = get_res.content_as()?;
270-
for (i, item) in list_contents.iter().enumerate() {
271-
if *item == value {
272-
return Ok(i as isize);
273-
}
274-
}
275-
Ok(-1)
270+
Ok(list_contents.iter().position(|item| item == value))
276271
}
277272
.instrument(ctx.span().clone())
278273
.await;
@@ -304,6 +299,11 @@ impl CouchbaseList<'_> {
304299
result
305300
}
306301

302+
/// Returns `true` if the list contains no elements.
303+
pub async fn is_empty(&self) -> crate::error::Result<bool> {
304+
Ok(self.len().await? == 0)
305+
}
306+
307307
/// Removes all elements from the list by deleting the backing document.
308308
pub async fn clear(&self) -> crate::error::Result<()> {
309309
let ctx = self
@@ -331,9 +331,9 @@ impl CouchbaseList<'_> {
331331
/// Supports get, insert, remove, keys, values, exists, size, clear, and iteration.
332332
#[derive(Clone)]
333333
pub struct CouchbaseMap<'a> {
334-
pub collection: &'a Collection,
335-
pub id: String,
336-
pub options: CouchbaseMapOptions,
334+
collection: &'a Collection,
335+
id: String,
336+
options: CouchbaseMapOptions,
337337
}
338338

339339
impl CouchbaseMap<'_> {
@@ -487,6 +487,11 @@ impl CouchbaseMap<'_> {
487487
result
488488
}
489489

490+
/// Returns `true` if the map contains no entries.
491+
pub async fn is_empty(&self) -> crate::error::Result<bool> {
492+
Ok(self.len().await? == 0)
493+
}
494+
490495
/// Returns all keys in the map.
491496
pub async fn keys(&self) -> crate::error::Result<Vec<String>> {
492497
let ctx = self
@@ -559,9 +564,9 @@ impl CouchbaseMap<'_> {
559564
/// Duplicate values are silently ignored.
560565
#[derive(Clone)]
561566
pub struct CouchbaseSet<'a> {
562-
pub collection: &'a Collection,
563-
pub id: String,
564-
pub options: CouchbaseSetOptions,
567+
collection: &'a Collection,
568+
id: String,
569+
options: CouchbaseSetOptions,
565570
}
566571

567572
impl CouchbaseSet<'_> {
@@ -709,7 +714,7 @@ impl CouchbaseSet<'_> {
709714
/// Returns `true` if the set contains the given value.
710715
pub async fn contains<T: PartialEq + DeserializeOwned>(
711716
&self,
712-
value: T,
717+
value: &T,
713718
) -> crate::error::Result<bool> {
714719
let ctx = self
715720
.collection
@@ -723,12 +728,7 @@ impl CouchbaseSet<'_> {
723728
let result = async {
724729
let res = self.collection.get(&self.id, None).await?;
725730
let set_contents: Vec<T> = res.content_as()?;
726-
for item in set_contents {
727-
if item == value {
728-
return Ok(true);
729-
}
730-
}
731-
Ok(false)
731+
Ok(set_contents.iter().any(|item| item == value))
732732
}
733733
.instrument(ctx.span().clone())
734734
.await;
@@ -760,6 +760,11 @@ impl CouchbaseSet<'_> {
760760
result
761761
}
762762

763+
/// Returns `true` if the set contains no elements.
764+
pub async fn is_empty(&self) -> crate::error::Result<bool> {
765+
Ok(self.len().await? == 0)
766+
}
767+
763768
/// Removes all elements from the set by deleting the backing document.
764769
pub async fn clear(&self) -> crate::error::Result<()> {
765770
let ctx = self
@@ -787,9 +792,9 @@ impl CouchbaseSet<'_> {
787792
/// Supports push, pop, size, clear, and iteration.
788793
#[derive(Clone)]
789794
pub struct CouchbaseQueue<'a> {
790-
pub collection: &'a Collection,
791-
pub id: String,
792-
pub options: CouchbaseQueueOptions,
795+
collection: &'a Collection,
796+
id: String,
797+
options: CouchbaseQueueOptions,
793798
}
794799

795800
impl CouchbaseQueue<'_> {
@@ -917,6 +922,11 @@ impl CouchbaseQueue<'_> {
917922
result
918923
}
919924

925+
/// Returns `true` if the queue contains no elements.
926+
pub async fn is_empty(&self) -> crate::error::Result<bool> {
927+
Ok(self.len().await? == 0)
928+
}
929+
920930
/// Removes all elements from the queue by deleting the backing document.
921931
pub async fn clear(&self) -> crate::error::Result<()> {
922932
let ctx = self

sdk/couchbase/tests/data_structures.rs

Lines changed: 119 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ fn test_list() {
3434
list.append("test2").await.unwrap();
3535
list.prepend("test1").await.unwrap();
3636

37-
let index = list.position("test2".to_string()).await.unwrap();
38-
assert_eq!(index, 1);
37+
let index = list.position(&"test2".to_string()).await.unwrap();
38+
assert_eq!(index, Some(1));
3939

4040
let size = list.len().await.unwrap();
4141
assert_eq!(size, 2);
@@ -57,6 +57,49 @@ fn test_list() {
5757
})
5858
}
5959

60+
#[test]
61+
fn test_list_is_empty() {
62+
run_test(async |cluster, bucket| {
63+
let collection = bucket
64+
.scope(cluster.default_scope())
65+
.collection(cluster.default_collection());
66+
let key = new_key();
67+
68+
let list = collection.list(&key, None);
69+
70+
list.append("item").await.unwrap();
71+
72+
let res = list.is_empty().await.unwrap();
73+
assert!(!res);
74+
75+
list.remove(0).await.unwrap();
76+
77+
let res = list.is_empty().await.unwrap();
78+
assert!(res);
79+
80+
list.clear().await.unwrap();
81+
})
82+
}
83+
84+
#[test]
85+
fn test_list_position_not_found() {
86+
run_test(async |cluster, bucket| {
87+
let collection = bucket
88+
.scope(cluster.default_scope())
89+
.collection(cluster.default_collection());
90+
let key = new_key();
91+
92+
let list = collection.list(&key, None);
93+
94+
list.append("a").await.unwrap();
95+
96+
let res = list.position(&"z".to_string()).await.unwrap();
97+
assert_eq!(res, None);
98+
99+
list.clear().await.unwrap();
100+
})
101+
}
102+
60103
#[test]
61104
fn test_map() {
62105
run_test(async |cluster, bucket| {
@@ -111,6 +154,30 @@ fn test_map() {
111154
})
112155
}
113156

157+
#[test]
158+
fn test_map_is_empty() {
159+
run_test(async |cluster, bucket| {
160+
let collection = bucket
161+
.scope(cluster.default_scope())
162+
.collection(cluster.default_collection());
163+
let key = new_key();
164+
165+
let map = collection.map(&key, None);
166+
167+
map.insert("k", "v").await.unwrap();
168+
169+
let res = map.is_empty().await.unwrap();
170+
assert!(!res);
171+
172+
map.remove("k").await.unwrap();
173+
174+
let res = map.is_empty().await.unwrap();
175+
assert!(res);
176+
177+
map.clear().await.unwrap();
178+
})
179+
}
180+
114181
#[test]
115182
fn test_set() {
116183
run_test(async |cluster, bucket| {
@@ -131,7 +198,7 @@ fn test_set() {
131198
let res: Vec<String> = set.values().await.unwrap();
132199
assert_eq!(res, vec!["test1", "test2"]);
133200

134-
let res = set.contains("test1".to_string()).await.unwrap();
201+
let res = set.contains(&"test1".to_string()).await.unwrap();
135202
assert!(res);
136203

137204
let mut iter = set.iter::<String>().await.unwrap();
@@ -141,7 +208,7 @@ fn test_set() {
141208

142209
set.remove("test1".to_string()).await.unwrap();
143210

144-
let res = set.contains("test1".to_string()).await.unwrap();
211+
let res = set.contains(&"test1".to_string()).await.unwrap();
145212
assert!(!res);
146213

147214
set.clear().await.unwrap();
@@ -151,6 +218,30 @@ fn test_set() {
151218
})
152219
}
153220

221+
#[test]
222+
fn test_set_is_empty() {
223+
run_test(async |cluster, bucket| {
224+
let collection = bucket
225+
.scope(cluster.default_scope())
226+
.collection(cluster.default_collection());
227+
let key = new_key();
228+
229+
let set = collection.set(&key, None);
230+
231+
set.insert("only").await.unwrap();
232+
233+
let res = set.is_empty().await.unwrap();
234+
assert!(!res);
235+
236+
set.remove("only".to_string()).await.unwrap();
237+
238+
let res = set.is_empty().await.unwrap();
239+
assert!(res);
240+
241+
set.clear().await.unwrap();
242+
})
243+
}
244+
154245
#[test]
155246
fn test_queue() {
156247
run_test(async |cluster, bucket| {
@@ -181,3 +272,27 @@ fn test_queue() {
181272
assert!(!res.exists());
182273
})
183274
}
275+
276+
#[test]
277+
fn test_queue_is_empty() {
278+
run_test(async |cluster, bucket| {
279+
let collection = bucket
280+
.scope(cluster.default_scope())
281+
.collection(cluster.default_collection());
282+
let key = new_key();
283+
284+
let queue = collection.queue(&key, None);
285+
286+
queue.push("item").await.unwrap();
287+
288+
let res = queue.is_empty().await.unwrap();
289+
assert!(!res);
290+
291+
let _: String = queue.pop().await.unwrap();
292+
293+
let res = queue.is_empty().await.unwrap();
294+
assert!(res);
295+
296+
queue.clear().await.unwrap();
297+
})
298+
}

0 commit comments

Comments
 (0)