1010//! [`Client::list_hash_seq`] can be used to list all tags with a hash_seq format.
1111//!
1212//! [`Client::delete`] can be used to delete a tag.
13+ use std:: ops:: { Bound , RangeBounds } ;
14+
1315use anyhow:: Result ;
1416use futures_lite:: { Stream , StreamExt } ;
1517use quic_rpc:: { client:: BoxedConnector , Connector , RpcClient } ;
@@ -30,6 +32,125 @@ pub struct Client<C = BoxedConnector<RpcService>> {
3032 pub ( super ) rpc : RpcClient < RpcService , C > ,
3133}
3234
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+
33154/// A client that uses the memory connector.
34155pub type MemClient = Client < crate :: rpc:: MemConnector > ;
35156
@@ -42,44 +163,67 @@ where
42163 Self { rpc }
43164 }
44165
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+
45181 /// Get the value of a single tag
46182 pub async fn get ( & self , name : impl AsRef < [ u8 ] > ) -> Result < Option < TagInfo > > {
47183 let mut stream = self
48- . rpc
49- . server_streaming ( ListRequest :: single ( name. as_ref ( ) ) )
184+ . list_with_opts ( ListOptions :: single ( name. as_ref ( ) ) )
50185 . await ?;
51186 Ok ( stream. next ( ) . await . transpose ( ) ?)
52187 }
53188
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+
54198 /// Lists all tags.
55199 pub async fn list_prefix (
56200 & self ,
57201 prefix : impl AsRef < [ u8 ] > ,
58202 ) -> 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
64205 }
65206
66207 /// Lists all tags.
67208 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
70210 }
71211
72212 /// Lists all tags with a hash_seq format.
73213 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
76215 }
77216
78217 /// 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 ??;
81220 Ok ( ( ) )
82221 }
222+
223+ /// Deletes a tag.
224+ pub async fn delete ( & self , name : Tag ) -> Result < ( ) > {
225+ self . delete_with_opts ( DeleteOptions :: single ( name) ) . await
226+ }
83227}
84228
85229/// Information about a tag.
0 commit comments