use crate::common::{CatalogOptions, Options};
use super::rest_util::RESTUtil;
#[derive(Clone)]
pub struct ResourcePaths {
base_path: String,
}
impl ResourcePaths {
const V1: &'static str = "v1";
const DATABASES: &'static str = "databases";
const TABLES: &'static str = "tables";
const TABLE_DETAILS: &'static str = "table-details";
pub fn new(prefix: &str) -> Self {
let base_path = if prefix.is_empty() {
format!("/{}", Self::V1)
} else {
format!("/{}/{}", Self::V1, prefix.trim_matches('/'))
};
ResourcePaths { base_path }
}
pub fn for_catalog_properties(options: &Options) -> Self {
let prefix = options
.get(CatalogOptions::PREFIX)
.map(|s| s.as_str())
.unwrap_or("");
Self::new(prefix)
}
pub fn base_path(&self) -> &str {
&self.base_path
}
pub fn config() -> String {
format!("/{}/config", Self::V1)
}
pub fn databases(&self) -> String {
format!("{}/{}", self.base_path, Self::DATABASES)
}
pub fn database(&self, name: &str) -> String {
format!(
"{}/{}/{}",
self.base_path,
Self::DATABASES,
RESTUtil::encode_string(name)
)
}
pub fn tables(&self, database_name: Option<&str>) -> String {
if let Some(db_name) = database_name {
format!(
"{}/{}/{}/{}",
self.base_path,
Self::DATABASES,
RESTUtil::encode_string(db_name),
Self::TABLES
)
} else {
format!("{}/{}", self.base_path, Self::TABLES)
}
}
pub fn table(&self, database_name: &str, table_name: &str) -> String {
format!(
"{}/{}/{}/{}/{}",
self.base_path,
Self::DATABASES,
RESTUtil::encode_string(database_name),
Self::TABLES,
RESTUtil::encode_string(table_name)
)
}
pub fn table_details(&self, database_name: &str) -> String {
format!(
"{}/{}/{}/{}",
self.base_path,
Self::DATABASES,
RESTUtil::encode_string(database_name),
Self::TABLE_DETAILS
)
}
pub fn table_token(&self, database_name: &str, table_name: &str) -> String {
format!(
"{}/{}/{}/{}/{}/token",
self.base_path,
Self::DATABASES,
RESTUtil::encode_string(database_name),
Self::TABLES,
RESTUtil::encode_string(table_name)
)
}
pub fn rename_table(&self) -> String {
format!("{}/{}/rename", self.base_path, Self::TABLES)
}
pub fn commit_table(&self, database_name: &str, table_name: &str) -> String {
format!(
"{}/{}/{}/{}/{}/commit",
self.base_path,
Self::DATABASES,
RESTUtil::encode_string(database_name),
Self::TABLES,
RESTUtil::encode_string(table_name)
)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_resource_paths_basic() {
let paths = ResourcePaths::new("");
assert_eq!(paths.databases(), "/v1/databases");
assert_eq!(paths.tables(None), "/v1/tables");
}
#[test]
fn test_resource_paths_with_prefix() {
let paths = ResourcePaths::new("my-catalog");
assert_eq!(paths.databases(), "/v1/my-catalog/databases");
assert_eq!(
paths.database("test-db"),
"/v1/my-catalog/databases/test-db"
);
}
#[test]
fn test_resource_paths_table() {
let paths = ResourcePaths::new("");
let table_path = paths.table("my-db", "my-table");
assert!(table_path.contains("my-db"));
assert!(table_path.contains("my-table"));
}
#[test]
fn test_config_path() {
assert_eq!(ResourcePaths::config(), "/v1/config");
}
}