use std::sync::Arc;
use uuid::Uuid;
use crate::api_spec::{
ApproveLearnedSimilarityRequest, ApproveLearnedSimilarityResponse, BulkCreateSortsRequest,
BulkCreateSortsResponse, BulkSetSimilaritiesRequest, BulkSetSimilaritiesResponse,
ComputeGlbRequest, ComputeGlbResponse, ComputeLubRequest, ComputeLubResponse,
CreateSortRequest, DecodeGlbResponse, GetEquivalenceClassesResponse, GetPreorderDegreeRequest,
GetPreorderDegreeResponse, GetSortSimilarityRequest, GetSortSimilarityResponse,
IsSubtypeResponse, LearnSortSimilaritiesRequest, LearnSortSimilaritiesResponse,
LearnedSimilarityListResponse, RejectLearnedSimilarityRequest, RejectLearnedSimilarityResponse,
SetSortSimilarityRequest, SetSortSimilarityResponse, SortAncestorsResponse,
SortChildrenResponse, SortCompareOperator, SortCompareRequest, SortCompareResponse,
SortDescendantsResponse, SortDto, SortInfoDto, SortListResponse, SortParentsResponse,
SortResponse, UpdateSortReviewRequest,
};
use crate::error::Error;
use crate::http::HttpClient;
use crate::types::common::RequestOptions;
#[derive(Debug, Clone)]
pub struct SortsClient {
http: HttpClient,
tenant_id: Arc<String>,
}
impl SortsClient {
pub(crate) fn new(http: HttpClient) -> Self {
let tenant_id = Arc::new(http.config.tenant_id.clone());
Self { http, tenant_id }
}
pub(crate) fn http(&self) -> &HttpClient {
&self.http
}
pub async fn create_sort(
&self,
request: CreateSortRequest,
options: Option<&RequestOptions>,
) -> Result<SortDto, Error> {
let response: SortResponse = self.http.post("/sorts", &request, options).await?;
Ok(response.sort)
}
pub async fn get_sort(
&self,
sort_id: &str,
options: Option<&RequestOptions>,
) -> Result<SortDto, Error> {
let path = format!("/sorts/{}", encode(sort_id));
let response: SortResponse = self.http.get(&path, None, options).await?;
Ok(response.sort)
}
pub async fn delete_sort(
&self,
sort_id: &str,
options: Option<&RequestOptions>,
) -> Result<(), Error> {
let path = format!("/sorts/{}", encode(sort_id));
let _: serde_json::Value = self.http.delete(&path, None, options).await?;
Ok(())
}
pub async fn list_sorts(
&self,
options: Option<&RequestOptions>,
) -> Result<Vec<SortDto>, Error> {
let path = format!("/sorts/tenant/{}", encode(self.tenant_id.as_str()));
let response: SortListResponse = self.http.get(&path, None, options).await?;
Ok(response.sorts)
}
pub async fn bulk_create_sorts(
&self,
request: BulkCreateSortsRequest,
options: Option<&RequestOptions>,
) -> Result<BulkCreateSortsResponse, Error> {
self.http.post("/sorts/bulk", &request, options).await
}
pub async fn is_subtype(
&self,
child_id: &str,
parent_id: &str,
options: Option<&RequestOptions>,
) -> Result<bool, Error> {
let path = format!("/sorts/{}/subtype/{}", encode(child_id), encode(parent_id));
let response: IsSubtypeResponse = self.http.get(&path, None, options).await?;
Ok(response.is_subtype)
}
pub async fn compute_glb(
&self,
request: ComputeGlbRequest,
options: Option<&RequestOptions>,
) -> Result<ComputeGlbResponse, Error> {
self.http.post("/sorts/glb", &request, options).await
}
pub async fn compute_lub(
&self,
request: ComputeLubRequest,
options: Option<&RequestOptions>,
) -> Result<ComputeLubResponse, Error> {
self.http.post("/sorts/lub", &request, options).await
}
pub async fn decode_glb(
&self,
request: ComputeGlbRequest,
options: Option<&RequestOptions>,
) -> Result<DecodeGlbResponse, Error> {
self.http.post("/sorts/glb/decode", &request, options).await
}
pub async fn find_common_subtype(
&self,
sort1_id: &str,
sort2_id: &str,
options: Option<&RequestOptions>,
) -> Result<ComputeGlbResponse, Error> {
self.compute_glb(
ComputeGlbRequest {
sort1_id: parse_uuid(sort1_id, "sort1_id")?,
sort2_id: parse_uuid(sort2_id, "sort2_id")?,
},
options,
)
.await
}
pub async fn find_common_supertype(
&self,
sort1_id: &str,
sort2_id: &str,
options: Option<&RequestOptions>,
) -> Result<ComputeLubResponse, Error> {
self.compute_lub(
ComputeLubRequest {
sort1_id: parse_uuid(sort1_id, "sort1_id")?,
sort2_id: parse_uuid(sort2_id, "sort2_id")?,
},
options,
)
.await
}
pub async fn explain_common_subtype(
&self,
sort1_id: &str,
sort2_id: &str,
options: Option<&RequestOptions>,
) -> Result<DecodeGlbResponse, Error> {
self.decode_glb(
ComputeGlbRequest {
sort1_id: parse_uuid(sort1_id, "sort1_id")?,
sort2_id: parse_uuid(sort2_id, "sort2_id")?,
},
options,
)
.await
}
pub async fn get_children(
&self,
sort_id: &str,
options: Option<&RequestOptions>,
) -> Result<Vec<SortInfoDto>, Error> {
let path = format!("/sorts/{}/children", encode(sort_id));
let response: SortChildrenResponse = self.http.get(&path, None, options).await?;
Ok(response.children)
}
pub async fn get_parents(
&self,
sort_id: &str,
options: Option<&RequestOptions>,
) -> Result<Vec<SortInfoDto>, Error> {
let path = format!("/sorts/{}/parents", encode(sort_id));
let response: SortParentsResponse = self.http.get(&path, None, options).await?;
Ok(response.parents)
}
pub async fn get_ancestors(
&self,
sort_id: &str,
options: Option<&RequestOptions>,
) -> Result<Vec<SortInfoDto>, Error> {
let path = format!("/sorts/{}/ancestors", encode(sort_id));
let response: SortAncestorsResponse = self.http.get(&path, None, options).await?;
Ok(response.ancestors)
}
pub async fn get_descendants(
&self,
sort_id: &str,
options: Option<&RequestOptions>,
) -> Result<Vec<SortInfoDto>, Error> {
let path = format!("/sorts/{}/descendants", encode(sort_id));
let response: SortDescendantsResponse = self.http.get(&path, None, options).await?;
Ok(response.descendants)
}
pub async fn get_compatible(
&self,
sort_id: &str,
options: Option<&RequestOptions>,
) -> Result<Vec<SortDto>, Error> {
let path = format!("/sorts/{}/compatible", encode(sort_id));
let response: SortListResponse = self.http.get(&path, None, options).await?;
Ok(response.sorts)
}
pub async fn compare_sorts(
&self,
operator: SortCompareOperator,
sort_a: impl Into<String>,
sort_b: impl Into<String>,
options: Option<&RequestOptions>,
) -> Result<SortCompareResponse, Error> {
let request = SortCompareRequest {
operator,
sort_a: sort_a.into(),
sort_b: sort_b.into(),
tenant_id: parse_uuid(self.tenant_id.as_str(), "tenant_id")?,
};
self.http.post("/sorts/compare", &request, options).await
}
pub async fn index_sorts(&self, options: Option<&RequestOptions>) -> Result<(), Error> {
let _: serde_json::Value = self
.http
.post("/sorts/index", &serde_json::json!({}), options)
.await?;
Ok(())
}
pub async fn update_review_status(
&self,
sort_id: &str,
request: UpdateSortReviewRequest,
options: Option<&RequestOptions>,
) -> Result<(), Error> {
let path = format!("/sorts/{}/review", encode(sort_id));
let _: serde_json::Value = self.http.post(&path, &request, options).await?;
Ok(())
}
pub async fn get_sort_similarity(
&self,
request: GetSortSimilarityRequest,
options: Option<&RequestOptions>,
) -> Result<GetSortSimilarityResponse, Error> {
self.http
.post("/sorts/similarity/get", &request, options)
.await
}
pub async fn set_sort_similarity(
&self,
request: SetSortSimilarityRequest,
options: Option<&RequestOptions>,
) -> Result<SetSortSimilarityResponse, Error> {
self.http.post("/sorts/similarity", &request, options).await
}
pub async fn bulk_set_similarities(
&self,
request: BulkSetSimilaritiesRequest,
options: Option<&RequestOptions>,
) -> Result<BulkSetSimilaritiesResponse, Error> {
self.http
.post("/sorts/similarity/bulk", &request, options)
.await
}
pub async fn get_preorder_degree(
&self,
request: GetPreorderDegreeRequest,
options: Option<&RequestOptions>,
) -> Result<GetPreorderDegreeResponse, Error> {
self.http
.post("/sorts/preorder-degree", &request, options)
.await
}
pub async fn get_equivalence_classes(
&self,
options: Option<&RequestOptions>,
) -> Result<GetEquivalenceClassesResponse, Error> {
self.http
.get("/sorts/equivalence-classes", None, options)
.await
}
pub async fn learn_similarities(
&self,
request: LearnSortSimilaritiesRequest,
options: Option<&RequestOptions>,
) -> Result<LearnSortSimilaritiesResponse, Error> {
self.http
.post("/sorts/learn-similarities", &request, options)
.await
}
pub async fn get_learned_similarities(
&self,
options: Option<&RequestOptions>,
) -> Result<LearnedSimilarityListResponse, Error> {
self.http
.get("/sorts/learned-similarities", None, options)
.await
}
pub async fn approve_similarity(
&self,
request: ApproveLearnedSimilarityRequest,
options: Option<&RequestOptions>,
) -> Result<ApproveLearnedSimilarityResponse, Error> {
self.http
.post("/sorts/learned-similarities/approve", &request, options)
.await
}
pub async fn reject_similarity(
&self,
request: RejectLearnedSimilarityRequest,
options: Option<&RequestOptions>,
) -> Result<RejectLearnedSimilarityResponse, Error> {
self.http
.post("/sorts/learned-similarities/reject", &request, options)
.await
}
pub async fn create_many(
&self,
request: BulkCreateSortsRequest,
options: Option<&RequestOptions>,
) -> Result<BulkCreateSortsResponse, Error> {
self.bulk_create_sorts(request, options).await
}
}
fn encode(segment: &str) -> String {
url::form_urlencoded::byte_serialize(segment.as_bytes()).collect()
}
fn parse_uuid(value: &str, field: &'static str) -> Result<Uuid, Error> {
Uuid::parse_str(value).map_err(|err| Error::Validation {
field: Some(field.to_string()),
message: format!("expected a UUID, got {value:?}: {err}"),
})
}