use serde::{Deserialize, Serialize};
use std::collections::HashMap;
use crate::spec::Schema;
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ErrorResponse {
pub resource_type: Option<String>,
pub resource_name: Option<String>,
pub message: Option<String>,
pub code: Option<i32>,
}
impl ErrorResponse {
pub fn new(
resource_type: Option<String>,
resource_name: Option<String>,
message: Option<String>,
code: Option<i32>,
) -> Self {
Self {
resource_type,
resource_name,
message,
code,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AuditRESTResponse {
pub owner: Option<String>,
pub created_at: Option<i64>,
pub created_by: Option<String>,
pub updated_at: Option<i64>,
pub updated_by: Option<String>,
}
impl AuditRESTResponse {
pub fn new(
owner: Option<String>,
created_at: Option<i64>,
created_by: Option<String>,
updated_at: Option<i64>,
updated_by: Option<String>,
) -> Self {
Self {
owner,
created_at,
created_by,
updated_at,
updated_by,
}
}
pub fn put_audit_options_to(&self, options: &mut HashMap<String, String>) {
if let Some(owner) = &self.owner {
options.insert("owner".to_string(), owner.clone());
}
if let Some(created_by) = &self.created_by {
options.insert("createdBy".to_string(), created_by.clone());
}
if let Some(created_at) = self.created_at {
options.insert("createdAt".to_string(), created_at.to_string());
}
if let Some(updated_by) = &self.updated_by {
options.insert("updatedBy".to_string(), updated_by.clone());
}
if let Some(updated_at) = self.updated_at {
options.insert("updatedAt".to_string(), updated_at.to_string());
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GetTableResponse {
#[serde(flatten)]
pub audit: AuditRESTResponse,
pub id: Option<String>,
pub name: Option<String>,
pub path: Option<String>,
pub is_external: Option<bool>,
pub schema_id: Option<i64>,
pub schema: Option<Schema>,
}
impl GetTableResponse {
#[allow(clippy::too_many_arguments)]
pub fn new(
id: Option<String>,
name: Option<String>,
path: Option<String>,
is_external: Option<bool>,
schema_id: Option<i64>,
schema: Option<Schema>,
audit: AuditRESTResponse,
) -> Self {
Self {
audit,
id,
name,
path,
is_external,
schema_id,
schema,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GetDatabaseResponse {
#[serde(flatten)]
pub audit: AuditRESTResponse,
pub id: Option<String>,
pub name: Option<String>,
pub location: Option<String>,
pub options: HashMap<String, String>,
}
impl GetDatabaseResponse {
pub fn new(
id: Option<String>,
name: Option<String>,
location: Option<String>,
options: HashMap<String, String>,
audit: AuditRESTResponse,
) -> Self {
Self {
audit,
id,
name,
location,
options,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ConfigResponse {
pub defaults: HashMap<String, String>,
}
impl ConfigResponse {
pub fn new(defaults: HashMap<String, String>) -> Self {
Self { defaults }
}
pub fn merge_options(&self, options: &crate::common::Options) -> crate::common::Options {
let mut merged = self.defaults.clone();
merged.extend(options.to_map().clone());
crate::common::Options::from_map(merged)
}
pub fn to_options(&self) -> crate::common::Options {
crate::common::Options::from_map(self.defaults.clone())
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListDatabasesResponse {
pub databases: Vec<String>,
pub next_page_token: Option<String>,
}
impl ListDatabasesResponse {
pub fn new(databases: Vec<String>, next_page_token: Option<String>) -> Self {
Self {
databases,
next_page_token,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct ListTablesResponse {
pub tables: Option<Vec<String>>,
pub next_page_token: Option<String>,
}
impl ListTablesResponse {
pub fn new(tables: Option<Vec<String>>, next_page_token: Option<String>) -> Self {
Self {
tables,
next_page_token,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PagedList<T> {
pub elements: Vec<T>,
pub next_page_token: Option<String>,
}
impl<T> PagedList<T> {
pub fn new(elements: Vec<T>, next_page_token: Option<String>) -> Self {
Self {
elements,
next_page_token,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct GetTableTokenResponse {
pub token: HashMap<String, String>,
pub expires_at_millis: Option<i64>,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_error_response_serialization() {
let resp = ErrorResponse::new(
Some("table".to_string()),
Some("test_table".to_string()),
Some("Table not found".to_string()),
Some(404),
);
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"resourceType\":\"table\""));
assert!(json.contains("\"resourceName\":\"test_table\""));
assert!(json.contains("\"message\":\"Table not found\""));
assert!(json.contains("\"code\":404"));
}
#[test]
fn test_list_databases_response_serialization() {
let resp = ListDatabasesResponse::new(
vec!["db1".to_string(), "db2".to_string()],
Some("token123".to_string()),
);
let json = serde_json::to_string(&resp).unwrap();
assert!(json.contains("\"databases\":[\"db1\",\"db2\"]"));
assert!(json.contains("\"nextPageToken\":\"token123\""));
}
#[test]
fn test_audit_response_options() {
let audit = AuditRESTResponse::new(
Some("owner1".to_string()),
Some(1000),
Some("creator".to_string()),
Some(2000),
Some("updater".to_string()),
);
let mut options = HashMap::new();
audit.put_audit_options_to(&mut options);
assert_eq!(options.get("owner"), Some(&"owner1".to_string()));
assert_eq!(options.get("createdBy"), Some(&"creator".to_string()));
assert_eq!(options.get("createdAt"), Some(&"1000".to_string()));
assert_eq!(options.get("updatedBy"), Some(&"updater".to_string()));
assert_eq!(options.get("updatedAt"), Some(&"2000".to_string()));
}
}