use crate::{
Authenticated, Client, Result,
path::{validate_endpoint_path, validate_mount_path},
};
#[derive(Clone, Debug)]
pub struct PluginMount<'a> {
client: &'a Client<Authenticated>,
mount: Vec<String>,
}
impl<'a> PluginMount<'a> {
pub fn new(client: &'a Client<Authenticated>, mount: &str) -> Result<Self> {
let mount = validate_mount_path(mount)?;
Ok(Self { client, mount })
}
#[must_use]
pub const fn client(&self) -> &'a Client<Authenticated> {
self.client
}
#[must_use]
pub fn mount_segments(&self) -> &[String] {
&self.mount
}
pub fn path(&self, tail: &[&str]) -> Result<String> {
let mut segments = self.mount.clone();
for segment in tail {
segments.extend(validate_endpoint_path(segment)?);
}
Ok(segments.join("/"))
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::panic)]
use secrecy::SecretString;
use crate::{Client, PluginMount};
#[test]
fn plugin_mount_builds_validated_paths() {
let client = Client::new("https://bao.example.com:8200")
.unwrap_or_else(|error| panic!("{error}"))
.try_with_token(SecretString::from("test-token"))
.unwrap_or_else(|error| panic!("{error}"));
let mount =
PluginMount::new(&client, "custom/plugin").unwrap_or_else(|error| panic!("{error}"));
assert_eq!(
mount
.path(&["creds", "readonly"])
.unwrap_or_else(|error| panic!("{error}")),
"custom/plugin/creds/readonly"
);
assert!(PluginMount::new(&client, "custom//plugin").is_err());
assert!(mount.path(&["creds?role=readonly"]).is_err());
}
}