gemini_genai_rs/protocol/
platform.rs

1//! Platform abstraction — Google AI vs Vertex AI URL/version logic.
2
3use crate::protocol::types::GeminiModel;
4
5/// Which platform variant to use for the Gemini API.
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum Platform {
8    /// Google AI (generativelanguage.googleapis.com)
9    GoogleAI,
10    /// Vertex AI (aiplatform.googleapis.com)
11    VertexAI {
12        /// Google Cloud project ID.
13        project: String,
14        /// Regional location (e.g. `"us-central1"` or `"global"`).
15        location: String,
16    },
17}
18
19impl Platform {
20    /// The base hostname for API requests.
21    pub fn base_host(&self) -> String {
22        match self {
23            Platform::GoogleAI => "generativelanguage.googleapis.com".to_string(),
24            Platform::VertexAI { location, .. } => {
25                if location == "global" {
26                    "aiplatform.googleapis.com".to_string()
27                } else {
28                    format!("{location}-aiplatform.googleapis.com")
29                }
30            }
31        }
32    }
33
34    /// The API version string.
35    pub fn api_version(&self) -> &str {
36        match self {
37            Platform::GoogleAI => "v1beta",
38            Platform::VertexAI { .. } => "v1beta1",
39        }
40    }
41
42    /// Build the model URI for the setup message.
43    pub fn model_uri(&self, model: &GeminiModel) -> String {
44        match self {
45            Platform::GoogleAI => model.to_string(), // "models/..."
46            Platform::VertexAI { project, location } => {
47                let model_id = model.to_string().trim_start_matches("models/").to_string();
48                format!(
49                    "projects/{project}/locations/{location}/publishers/google/models/{model_id}"
50                )
51            }
52        }
53    }
54
55    /// The WebSocket service path.
56    pub fn ws_path(&self) -> &str {
57        match self {
58            Platform::GoogleAI => {
59                "google.ai.generativelanguage.v1beta.GenerativeService.BidiGenerateContent"
60            }
61            Platform::VertexAI { .. } => {
62                "google.cloud.aiplatform.v1beta1.LlmBidiService/BidiGenerateContent"
63            }
64        }
65    }
66}
67
68#[cfg(test)]
69mod tests {
70    use super::*;
71    use crate::protocol::types::GeminiModel;
72
73    #[test]
74    fn google_ai_base_host() {
75        assert_eq!(
76            Platform::GoogleAI.base_host(),
77            "generativelanguage.googleapis.com"
78        );
79    }
80
81    #[test]
82    fn google_ai_api_version() {
83        assert_eq!(Platform::GoogleAI.api_version(), "v1beta");
84    }
85
86    #[test]
87    fn vertex_ai_api_version() {
88        let p = Platform::VertexAI {
89            project: "p".into(),
90            location: "us-central1".into(),
91        };
92        assert_eq!(p.api_version(), "v1beta1");
93    }
94
95    #[test]
96    fn vertex_ai_base_host_regional() {
97        let p = Platform::VertexAI {
98            project: "p".into(),
99            location: "us-central1".into(),
100        };
101        assert_eq!(p.base_host(), "us-central1-aiplatform.googleapis.com");
102    }
103
104    #[test]
105    fn vertex_ai_base_host_global() {
106        let p = Platform::VertexAI {
107            project: "p".into(),
108            location: "global".into(),
109        };
110        assert_eq!(p.base_host(), "aiplatform.googleapis.com");
111    }
112
113    #[test]
114    fn google_ai_model_uri() {
115        let uri = Platform::GoogleAI.model_uri(&GeminiModel::Gemini2_0FlashLive);
116        assert_eq!(uri, "models/gemini-2.0-flash-live-001");
117    }
118
119    #[test]
120    fn vertex_ai_model_uri() {
121        let p = Platform::VertexAI {
122            project: "my-proj".into(),
123            location: "us-central1".into(),
124        };
125        let uri = p.model_uri(&GeminiModel::Gemini2_0FlashLive);
126        assert!(uri.contains("projects/my-proj/locations/us-central1/publishers/google/models/gemini-2.0-flash-live-001"));
127    }
128
129    #[test]
130    fn google_ai_ws_path() {
131        assert!(Platform::GoogleAI.ws_path().contains("GenerativeService"));
132    }
133
134    #[test]
135    fn vertex_ai_ws_path() {
136        let p = Platform::VertexAI {
137            project: "p".into(),
138            location: "x".into(),
139        };
140        assert!(p.ws_path().contains("LlmBidiService"));
141    }
142
143    #[test]
144    fn platform_is_clone_and_debug() {
145        let p = Platform::GoogleAI;
146        let _p2 = p.clone();
147        let _s = format!("{:?}", p);
148    }
149}