10
10
//! [`Client::list_hash_seq`] can be used to list all tags with a hash_seq format.
11
11
//!
12
12
//! [`Client::delete`] can be used to delete a tag.
13
+ use std:: ops:: { Bound , RangeBounds } ;
14
+
13
15
use anyhow:: Result ;
14
16
use futures_lite:: { Stream , StreamExt } ;
15
17
use quic_rpc:: { client:: BoxedConnector , Connector , RpcClient } ;
@@ -30,6 +32,125 @@ pub struct Client<C = BoxedConnector<RpcService>> {
30
32
pub ( super ) rpc : RpcClient < RpcService , C > ,
31
33
}
32
34
35
+ /// Options for a list operation.
36
+ #[ derive( Debug , Clone ) ]
37
+ pub struct ListOptions {
38
+ /// List tags to hash seqs
39
+ pub hash_seq : bool ,
40
+ /// List tags to raw blobs
41
+ pub raw : bool ,
42
+ /// Optional from tag (inclusive)
43
+ pub from : Option < Tag > ,
44
+ /// Optional to tag (exclusive)
45
+ pub to : Option < Tag > ,
46
+ }
47
+
48
+ fn tags_from_range < R , E > ( range : R ) -> ( Option < Tag > , Option < Tag > )
49
+ where
50
+ R : RangeBounds < E > ,
51
+ E : AsRef < [ u8 ] > ,
52
+ {
53
+ let from = match range. start_bound ( ) {
54
+ Bound :: Included ( start) => Some ( Tag :: from ( start. as_ref ( ) ) ) ,
55
+ Bound :: Excluded ( start) => Some ( Tag :: from ( start. as_ref ( ) ) . successor ( ) ) ,
56
+ Bound :: Unbounded => None ,
57
+ } ;
58
+ let to = match range. end_bound ( ) {
59
+ Bound :: Included ( end) => Some ( Tag :: from ( end. as_ref ( ) ) . successor ( ) ) ,
60
+ Bound :: Excluded ( end) => Some ( Tag :: from ( end. as_ref ( ) ) ) ,
61
+ Bound :: Unbounded => None ,
62
+ } ;
63
+ ( from, to)
64
+ }
65
+
66
+ impl ListOptions {
67
+ /// List a range of tags
68
+ pub fn range < R , E > ( range : R ) -> Self
69
+ where
70
+ R : RangeBounds < E > ,
71
+ E : AsRef < [ u8 ] > ,
72
+ {
73
+ let ( from, to) = tags_from_range ( range) ;
74
+ Self {
75
+ from,
76
+ to,
77
+ raw : true ,
78
+ hash_seq : true ,
79
+ }
80
+ }
81
+
82
+ /// List tags with a prefix
83
+ pub fn prefix ( prefix : & [ u8 ] ) -> Self {
84
+ let from = Tag :: from ( prefix) ;
85
+ let to = from. next_prefix ( ) ;
86
+ Self {
87
+ raw : true ,
88
+ hash_seq : true ,
89
+ from : Some ( from) ,
90
+ to,
91
+ }
92
+ }
93
+
94
+ /// List a single tag
95
+ pub fn single ( name : & [ u8 ] ) -> Self {
96
+ let from = Tag :: from ( name) ;
97
+ Self {
98
+ to : Some ( from. successor ( ) ) ,
99
+ from : Some ( from) ,
100
+ raw : true ,
101
+ hash_seq : true ,
102
+ }
103
+ }
104
+
105
+ /// List all tags
106
+ pub fn all ( ) -> Self {
107
+ Self {
108
+ raw : true ,
109
+ hash_seq : true ,
110
+ from : None ,
111
+ to : None ,
112
+ }
113
+ }
114
+
115
+ /// List raw tags
116
+ pub fn raw ( ) -> Self {
117
+ Self {
118
+ raw : true ,
119
+ hash_seq : false ,
120
+ from : None ,
121
+ to : None ,
122
+ }
123
+ }
124
+
125
+ /// List hash seq tags
126
+ pub fn hash_seq ( ) -> Self {
127
+ Self {
128
+ raw : false ,
129
+ hash_seq : true ,
130
+ from : None ,
131
+ to : None ,
132
+ }
133
+ }
134
+ }
135
+
136
+ /// Options for a delete operation.
137
+ #[ derive( Debug , Clone ) ]
138
+ pub struct DeleteOptions {
139
+ /// Optional from tag (inclusive)
140
+ pub from : Option < Tag > ,
141
+ /// Optional to tag (exclusive)
142
+ pub to : Option < Tag > ,
143
+ }
144
+
145
+ impl DeleteOptions {
146
+ pub fn single ( name : Tag ) -> Self {
147
+ Self {
148
+ to : Some ( name. successor ( ) ) ,
149
+ from : Some ( name) ,
150
+ }
151
+ }
152
+ }
153
+
33
154
/// A client that uses the memory connector.
34
155
pub type MemClient = Client < crate :: rpc:: MemConnector > ;
35
156
@@ -42,44 +163,67 @@ where
42
163
Self { rpc }
43
164
}
44
165
166
+ /// List all tags with options.
167
+ ///
168
+ /// This is the most flexible way to list tags. All the other list methods are just convenience
169
+ /// methods that call this one with the appropriate options.
170
+ pub async fn list_with_opts (
171
+ & self ,
172
+ options : ListOptions ,
173
+ ) -> Result < impl Stream < Item = Result < TagInfo > > > {
174
+ let stream = self
175
+ . rpc
176
+ . server_streaming ( ListRequest :: from ( options) )
177
+ . await ?;
178
+ Ok ( stream. map ( |res| res. map_err ( anyhow:: Error :: from) ) )
179
+ }
180
+
45
181
/// Get the value of a single tag
46
182
pub async fn get ( & self , name : impl AsRef < [ u8 ] > ) -> Result < Option < TagInfo > > {
47
183
let mut stream = self
48
- . rpc
49
- . server_streaming ( ListRequest :: single ( name. as_ref ( ) ) )
184
+ . list_with_opts ( ListOptions :: single ( name. as_ref ( ) ) )
50
185
. await ?;
51
186
Ok ( stream. next ( ) . await . transpose ( ) ?)
52
187
}
53
188
189
+ /// List a range of tags
190
+ pub async fn list_range < R , E > ( & self , range : R ) -> Result < impl Stream < Item = Result < TagInfo > > >
191
+ where
192
+ R : RangeBounds < E > ,
193
+ E : AsRef < [ u8 ] > ,
194
+ {
195
+ self . list_with_opts ( ListOptions :: range ( range) ) . await
196
+ }
197
+
54
198
/// Lists all tags.
55
199
pub async fn list_prefix (
56
200
& self ,
57
201
prefix : impl AsRef < [ u8 ] > ,
58
202
) -> Result < impl Stream < Item = Result < TagInfo > > > {
59
- let stream = self
60
- . rpc
61
- . server_streaming ( ListRequest :: prefix ( prefix. as_ref ( ) ) )
62
- . await ?;
63
- Ok ( stream. map ( |res| res. map_err ( anyhow:: Error :: from) ) )
203
+ self . list_with_opts ( ListOptions :: prefix ( prefix. as_ref ( ) ) )
204
+ . await
64
205
}
65
206
66
207
/// Lists all tags.
67
208
pub async fn list ( & self ) -> Result < impl Stream < Item = Result < TagInfo > > > {
68
- let stream = self . rpc . server_streaming ( ListRequest :: all ( ) ) . await ?;
69
- Ok ( stream. map ( |res| res. map_err ( anyhow:: Error :: from) ) )
209
+ self . list_with_opts ( ListOptions :: all ( ) ) . await
70
210
}
71
211
72
212
/// Lists all tags with a hash_seq format.
73
213
pub async fn list_hash_seq ( & self ) -> Result < impl Stream < Item = Result < TagInfo > > > {
74
- let stream = self . rpc . server_streaming ( ListRequest :: hash_seq ( ) ) . await ?;
75
- Ok ( stream. map ( |res| res. map_err ( anyhow:: Error :: from) ) )
214
+ self . list_with_opts ( ListOptions :: hash_seq ( ) ) . await
76
215
}
77
216
78
217
/// Deletes a tag.
79
- pub async fn delete ( & self , name : Tag ) -> Result < ( ) > {
80
- self . rpc . rpc ( DeleteRequest { name } ) . await ??;
218
+ pub async fn delete_with_opts ( & self , options : DeleteOptions ) -> Result < ( ) > {
219
+ self . rpc . rpc ( DeleteRequest :: from ( options ) ) . await ??;
81
220
Ok ( ( ) )
82
221
}
222
+
223
+ /// Deletes a tag.
224
+ pub async fn delete ( & self , name : Tag ) -> Result < ( ) > {
225
+ self . delete_with_opts ( DeleteOptions :: single ( name) ) . await
226
+ }
83
227
}
84
228
85
229
/// Information about a tag.
0 commit comments