Skip to content

Commit 480dfd9

Browse files
committed
Make path parameters generic
We deal with the type inference problem for empty paths (&[]) by providing a small convenience macro (root![]) that expresses the root path. Closes #15
1 parent 754a382 commit 480dfd9

File tree

3 files changed

+31
-26
lines changed

3 files changed

+31
-26
lines changed

lighthouse-client/examples/admin_list_root.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
use clap::Parser;
2-
use lighthouse_client::{protocol::Authentication, Lighthouse, Result, TokioWebSocket, LIGHTHOUSE_URL};
2+
use lighthouse_client::{protocol::Authentication, root, Lighthouse, Result, TokioWebSocket, LIGHTHOUSE_URL};
33
use tracing::info;
44

55
async fn run(lh: Lighthouse<TokioWebSocket>) -> Result<()> {
66
info!("Connected to the Lighthouse server");
77

8-
let tree = lh.list(&[]).await?.payload;
8+
let tree = lh.list(root![]).await?.payload;
99
info!("Got {}", tree);
1010

1111
Ok(())

lighthouse-client/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,11 @@ pub use lighthouse::*;
1313
pub use spawn::*;
1414

1515
pub use lighthouse_protocol as protocol;
16+
17+
/// Small convenience macro that expresses the root path.
18+
#[macro_export]
19+
macro_rules! root {
20+
() => {
21+
&[] as &[&str]
22+
};
23+
}

lighthouse-client/src/lighthouse.rs

Lines changed: 21 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,13 @@ impl<S> Lighthouse<S>
121121
/// Replaces the user's lighthouse model with the given frame.
122122
pub async fn put_model(&self, frame: Frame) -> Result<ServerMessage<()>> {
123123
let username = self.authentication.username.clone();
124-
self.put(&["user", username.as_str(), "model"], Model::Frame(frame)).await
124+
self.put(&["user".into(), username, "model".into()], Model::Frame(frame)).await
125125
}
126126

127127
/// Requests a stream of events (including key/controller events) for the user's lighthouse model.
128128
pub async fn stream_model(&self) -> Result<impl Stream<Item = Result<ServerMessage<Model>>>> {
129129
let username = self.authentication.username.clone();
130-
self.stream(&["user", username.as_str(), "model"], ()).await
130+
self.stream(&["user".into(), username, "model".into()], ()).await
131131
}
132132

133133
/// Fetches lamp server metrics.
@@ -136,65 +136,65 @@ impl<S> Lighthouse<S>
136136
}
137137

138138
/// Combines PUT and CREATE. Requires CREATE and WRITE permission.
139-
pub async fn post<P>(&self, path: &[&str], payload: P) -> Result<ServerMessage<()>>
139+
pub async fn post<P>(&self, path: &[impl AsRef<str> + Debug], payload: P) -> Result<ServerMessage<()>>
140140
where
141141
P: Serialize {
142142
self.perform(&Verb::Post, path, payload).await
143143
}
144144

145145
/// Updates the resource at the given path with the given payload. Requires WRITE permission.
146-
pub async fn put<P>(&self, path: &[&str], payload: P) -> Result<ServerMessage<()>>
146+
pub async fn put<P>(&self, path: &[impl AsRef<str> + Debug], payload: P) -> Result<ServerMessage<()>>
147147
where
148148
P: Serialize {
149149
self.perform(&Verb::Put, path, payload).await
150150
}
151151

152152
/// Creates a resource at the given path. Requires CREATE permission.
153-
pub async fn create(&self, path: &[&str]) -> Result<ServerMessage<()>> {
153+
pub async fn create(&self, path: &[impl AsRef<str> + Debug]) -> Result<ServerMessage<()>> {
154154
self.perform(&Verb::Create, path, ()).await
155155
}
156156

157157
/// Deletes a resource at the given path. Requires DELETE permission.
158-
pub async fn delete(&self, path: &[&str]) -> Result<ServerMessage<()>> {
158+
pub async fn delete(&self, path: &[impl AsRef<str> + Debug]) -> Result<ServerMessage<()>> {
159159
self.perform(&Verb::Delete, path, ()).await
160160
}
161161

162162
/// Creates a directory at the given path. Requires CREATE permission.
163-
pub async fn mkdir(&self, path: &[&str]) -> Result<ServerMessage<()>> {
163+
pub async fn mkdir(&self, path: &[impl AsRef<str> + Debug]) -> Result<ServerMessage<()>> {
164164
self.perform(&Verb::Mkdir, path, ()).await
165165
}
166166

167167
/// Lists the directory tree at the given path. Requires READ permission.
168-
pub async fn list(&self, path: &[&str]) -> Result<ServerMessage<DirectoryTree>> {
168+
pub async fn list(&self, path: &[impl AsRef<str> + Debug]) -> Result<ServerMessage<DirectoryTree>> {
169169
self.perform(&Verb::List, path, ()).await
170170
}
171171

172172
/// Gets the resource at the given path. Requires READ permission.
173-
pub async fn get<R>(&self, path: &[&str]) -> Result<ServerMessage<R>>
173+
pub async fn get<R>(&self, path: &[impl AsRef<str> + Debug]) -> Result<ServerMessage<R>>
174174
where
175175
R: for<'de> Deserialize<'de> {
176176
self.perform(&Verb::Get, path, ()).await
177177
}
178178

179179
/// Links the given source to the given destination path.
180-
pub async fn link(&self, src_path: &[&str], dest_path: &[&str]) -> Result<ServerMessage<()>> {
181-
self.perform(&Verb::Link, dest_path, src_path).await
180+
pub async fn link(&self, src_path: &[impl AsRef<str> + Debug], dest_path: &[impl AsRef<str> + Debug]) -> Result<ServerMessage<()>> {
181+
self.perform(&Verb::Link, dest_path, src_path.iter().map(|s| s.as_ref().to_owned()).collect::<Vec<_>>()).await
182182
}
183183

184184
/// Unlinks the given source from the given destination path.
185-
pub async fn unlink(&self, src_path: &[&str], dest_path: &[&str]) -> Result<ServerMessage<()>> {
186-
self.perform(&Verb::Unlink, dest_path, src_path).await
185+
pub async fn unlink(&self, src_path: &[impl AsRef<str> + Debug], dest_path: &[impl AsRef<str> + Debug]) -> Result<ServerMessage<()>> {
186+
self.perform(&Verb::Unlink, dest_path, src_path.iter().map(|s| s.as_ref().to_owned()).collect::<Vec<_>>()).await
187187
}
188188

189189
/// Stops the given stream. **Should generally not be called manually**,
190190
/// since streams will automatically be stopped once dropped.
191-
pub async fn stop(&self, request_id: i32, path: &[&str]) -> Result<ServerMessage<()>> {
191+
pub async fn stop(&self, request_id: i32, path: &[impl AsRef<str> + Debug]) -> Result<ServerMessage<()>> {
192192
self.perform_with_id(request_id, &Verb::Stop, path, ()).await
193193
}
194194

195195
/// Performs a single request to the given path with the given payload.
196196
#[tracing::instrument(skip(self, payload))]
197-
pub async fn perform<P, R>(&self, verb: &Verb, path: &[&str], payload: P) -> Result<ServerMessage<R>>
197+
pub async fn perform<P, R>(&self, verb: &Verb, path: &[impl AsRef<str> + Debug], payload: P) -> Result<ServerMessage<R>>
198198
where
199199
P: Serialize,
200200
R: for<'de> Deserialize<'de> {
@@ -204,7 +204,7 @@ impl<S> Lighthouse<S>
204204

205205
/// Performs a single request to the given path with the given request id.
206206
#[tracing::instrument(skip(self, payload))]
207-
async fn perform_with_id<P, R>(&self, request_id: i32, verb: &Verb, path: &[&str], payload: P) -> Result<ServerMessage<R>>
207+
async fn perform_with_id<P, R>(&self, request_id: i32, verb: &Verb, path: &[impl AsRef<str> + Debug], payload: P) -> Result<ServerMessage<R>>
208208
where
209209
P: Serialize,
210210
R: for<'de> Deserialize<'de> {
@@ -217,22 +217,19 @@ impl<S> Lighthouse<S>
217217
/// Performs a STREAM request to the given path with the given payload.
218218
/// Automatically sends a STOP once dropped.
219219
#[tracing::instrument(skip(self, payload))]
220-
pub async fn stream<P, R>(&self, path: &[&str], payload: P) -> Result<impl Stream<Item = Result<ServerMessage<R>>>>
220+
pub async fn stream<P, R>(&self, path: &[impl AsRef<str> + Debug], payload: P) -> Result<impl Stream<Item = Result<ServerMessage<R>>>>
221221
where
222222
P: Serialize,
223223
R: for<'de> Deserialize<'de> {
224224
let request_id = self.next_request_id();
225-
self.send_request(request_id, &Verb::Stream, path, payload).await?;
225+
let path: Vec<String> = path.into_iter().map(|s| s.as_ref().to_string()).collect();
226+
self.send_request(request_id, &Verb::Stream, &path, payload).await?;
226227
let stream = self.receive_streaming(request_id).await?;
227228
Ok(stream.guard({
228229
// Stop the stream on drop
229230
let this = (*self).clone();
230-
let path: Vec<_> = path.into_iter().map(|s| s.to_string()).collect();
231231
move || {
232232
tokio::spawn(async move {
233-
// TODO: Find a more elegant way to pass the path, ideally without
234-
// converting back and forth between Vec<String>, Vec<&str> and &[&str]
235-
let path: Vec<_> = path.iter().map(|s| &**s).collect();
236233
if let Err(error) = this.stop(request_id, &path).await {
237234
error! { ?path, %error, "Could not STOP stream" };
238235
}
@@ -242,10 +239,10 @@ impl<S> Lighthouse<S>
242239
}
243240

244241
/// Sends a request to the given path with the given payload.
245-
async fn send_request<P>(&self, request_id: i32, verb: &Verb, path: &[&str], payload: P) -> Result<i32>
242+
async fn send_request<P>(&self, request_id: i32, verb: &Verb, path: &[impl AsRef<str> + Debug], payload: P) -> Result<i32>
246243
where
247244
P: Serialize {
248-
let path = path.into_iter().map(|s| s.to_string()).collect();
245+
let path = path.into_iter().map(|s| s.as_ref().to_string()).collect();
249246
debug! { %request_id, "Sending request" };
250247
self.send_message(&ClientMessage {
251248
request_id,

0 commit comments

Comments
 (0)