1use serde::{Deserialize, Serialize};
4use serde_json::Value;
5use std::collections::HashMap;
6
7#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
9#[serde(rename_all = "lowercase")]
10pub enum ResolveTargetType {
11 Entity,
13 Organization,
15}
16
17#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
19pub struct ResolveInput {
20 pub name: String,
22 pub target_type: ResolveTargetType,
24 #[serde(default, skip_serializing_if = "Option::is_none")]
26 pub state: Option<String>,
27 #[serde(default, skip_serializing_if = "Option::is_none")]
29 pub city: Option<String>,
30 #[serde(default, skip_serializing_if = "Option::is_none")]
32 pub context: Option<String>,
33}
34
35#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
37pub struct ResolveCandidate {
38 #[serde(default, skip_serializing_if = "Option::is_none")]
40 pub identifier: Option<String>,
41 #[serde(default, skip_serializing_if = "Option::is_none")]
43 pub display_name: Option<String>,
44 #[serde(default, skip_serializing_if = "Option::is_none")]
46 pub match_tier: Option<String>,
47 #[serde(flatten)]
49 pub extra: HashMap<String, Value>,
50}
51
52#[derive(Debug, Clone, Default, Serialize, Deserialize, PartialEq)]
54pub struct ResolveResult {
55 #[serde(default)]
57 pub count: u32,
58 #[serde(default)]
60 pub candidates: Vec<ResolveCandidate>,
61 #[serde(flatten)]
63 pub extra: HashMap<String, Value>,
64}
65
66#[cfg(test)]
67mod tests {
68 use super::*;
69 use serde_json::json;
70
71 #[test]
72 fn resolve_result_captures_unknown_fields_via_extra() {
73 let body = json!({
74 "count": 1,
75 "candidates": [{
76 "identifier": "ABC",
77 "display_name": "ACME",
78 "match_tier": "high",
79 "future_score": 0.92
80 }],
81 "future_meta": {"version": 2}
82 });
83 let r: ResolveResult = serde_json::from_value(body).expect("decode");
84 assert_eq!(r.count, 1);
85 assert!(r.extra.contains_key("future_meta"));
86 let candidate = &r.candidates[0];
87 assert_eq!(candidate.identifier.as_deref(), Some("ABC"));
88 assert!(candidate.extra.contains_key("future_score"));
89 }
90
91 #[test]
92 fn resolve_target_type_round_trips() {
93 let v = serde_json::to_value(ResolveTargetType::Entity).unwrap();
94 assert_eq!(v, json!("entity"));
95 let back: ResolveTargetType = serde_json::from_value(json!("organization")).unwrap();
96 assert_eq!(back, ResolveTargetType::Organization);
97 }
98}