use serde::{Deserialize, Serialize};
#[derive(Debug, Deserialize, Serialize)]
pub struct SearchResponse {
pub facets: Option<Facets>,
pub hits: Hits,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Hits {
#[serde(default)]
pub hits: Vec<Hit>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Facets {
pub lang: Option<FacetBucket>,
pub repo: Option<FacetBucket>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct FacetBucket {
pub buckets: Vec<Bucket>,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Bucket {
pub key: String,
#[serde(rename = "doc_count")]
pub doc_count: u64,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct Hit {
#[serde(rename = "_source")]
pub source: HitSource,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct HitSource {
pub repo: RepoField,
pub path: PathField,
pub branch: BranchField,
pub content: ContentField,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct RepoField {
pub raw: String,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct PathField {
pub raw: String,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct BranchField {
pub raw: String,
}
#[derive(Debug, Deserialize, Serialize)]
pub struct ContentField {
pub snippet: String,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_deserialize_search_response() {
let json = r#"{
"facets": {
"lang": {
"buckets": [
{"key": "Rust", "doc_count": 42}
]
},
"repo": {
"buckets": [
{"key": "terraphim/terraphim-ai", "doc_count": 10}
]
}
},
"hits": {
"hits": [
{
"_source": {
"repo": {"raw": "terraphim/terraphim-ai"},
"path": {"raw": "src/main.rs"},
"branch": {"raw": "main"},
"content": {"snippet": "async fn <mark>search</mark>()"}
}
}
]
}
}"#;
let response: SearchResponse = serde_json::from_str(json).unwrap();
assert_eq!(response.hits.hits.len(), 1);
assert_eq!(
response.hits.hits[0].source.repo.raw,
"terraphim/terraphim-ai"
);
let facets = response.facets.unwrap();
assert!(facets.lang.is_some());
assert_eq!(facets.lang.unwrap().buckets[0].key, "Rust");
}
}