pastry_dht/client.rs
1use tonic::transport::Channel;
2
3use crate::{
4 error::*,
5 internal::{
6 dht::service::grpc::{NodeServiceClient, QueryRequest, QueryType},
7 hring::hasher::Sha256Hasher,
8 },
9};
10
11/// A client for Pastry nodes.
12///
13#[derive(Clone)]
14pub struct PastryClient {
15 client: NodeServiceClient<Channel>,
16}
17
18impl PastryClient {
19 /// Connects to a node in the Pastry network.
20 ///
21 /// # Arguments
22 ///
23 /// * `address` - The public address of the node.
24 ///
25 /// # Returns
26 ///
27 /// Returns a `Result` containing the client.
28 ///
29 pub async fn connect(address: &str) -> Result<Self> {
30 Ok(PastryClient {
31 client: NodeServiceClient::connect(address.to_owned()).await?,
32 })
33 }
34
35 /// Retrieves a value associated with the given key stored in the Pastry
36 /// network.
37 ///
38 /// # Arguments
39 ///
40 /// * `key` - A slice of bytes representing the key for which the value is
41 /// requested.
42 ///
43 /// # Returns
44 ///
45 /// Returns a `Result` which is:
46 ///
47 /// - `Ok(Some(Vec<u8>))` if the key exists, containing the associated
48 /// value.
49 /// - `Ok(None)` if the key does not exist.
50 /// - `Err(e)` where `e` encapsulates any error encountered during the
51 /// operation.
52 ///
53 pub async fn get_kv(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>> {
54 let response = self
55 .client
56 .query(QueryRequest {
57 from_id: 0,
58 matched_digits: 0,
59 hops: 0,
60 query_type: QueryType::Get.into(),
61 key: Sha256Hasher::hash_once(key),
62 value: None,
63 })
64 .await?
65 .into_inner();
66
67 Ok(response.value)
68 }
69
70 /// Sets a value for a given key in the Pastry network.
71 ///
72 /// # Arguments
73 ///
74 /// * `key` - A slice of bytes representing the key to which the value is
75 /// to be associated.
76 /// * `value` - A slice of bytes representing the value to be set.
77 ///
78 /// # Returns
79 ///
80 /// Returns a `Result` which is:
81 ///
82 /// - `Ok(Some(Vec<u8>))` if the key existed and the value was replaced,
83 /// containing the old value.
84 /// - `Ok(None)` if the key did not exist and a new entry was created.
85 /// - `Err(e)` where `e` encapsulates any error encountered during the
86 /// operation.
87 ///
88 pub async fn set_kv(&mut self, key: &[u8], value: &[u8]) -> Result<Option<Vec<u8>>> {
89 let response = self
90 .client
91 .query(QueryRequest {
92 from_id: 0,
93 matched_digits: 0,
94 hops: 0,
95 query_type: QueryType::Set.into(),
96 key: Sha256Hasher::hash_once(key),
97 value: Some(value.to_vec()),
98 })
99 .await?
100 .into_inner();
101
102 Ok(response.value)
103 }
104
105 /// Deletes the value associated with the given key in the Pastry network.
106 ///
107 /// # Arguments
108 ///
109 /// * `key` - A slice of bytes representing the key whose associated value
110 /// is to be deleted.
111 ///
112 /// # Returns
113 ///
114 /// Returns a `Result` which is:
115 ///
116 /// - `Ok(Some(Vec<u8>))` if the key existed and the value was successfully deleted, containing the deleted value.
117 /// - `Ok(None)` if the key did not exist.
118 /// - `Err(e)` where `e` encapsulates any error encountered during the operation.
119 ///
120 pub async fn delete_kv(&mut self, key: &[u8]) -> Result<Option<Vec<u8>>> {
121 let response = self
122 .client
123 .query(QueryRequest {
124 from_id: 0,
125 matched_digits: 0,
126 hops: 0,
127 query_type: QueryType::Delete.into(),
128 key: Sha256Hasher::hash_once(key),
129 value: None,
130 })
131 .await?
132 .into_inner();
133
134 Ok(response.value)
135 }
136}