const VERTEX_HOST: &str = "aiplatform.googleapis.com";
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum Hosting {
FirstParty,
Vertex,
}
impl Hosting {
#[must_use]
pub fn of(endpoint: &str) -> Self {
let on_vertex = url::Url::parse(endpoint)
.ok()
.and_then(|url| url.host_str().map(is_vertex_host))
.unwrap_or(false);
if on_vertex {
Self::Vertex
} else {
Self::FirstParty
}
}
#[must_use]
pub const fn as_str(self) -> &'static str {
match self {
Self::FirstParty => "first_party",
Self::Vertex => "vertex",
}
}
}
impl std::fmt::Display for Hosting {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.as_str())
}
}
#[must_use]
pub fn is_vertex_host(host: &str) -> bool {
let host = host.to_ascii_lowercase();
host == VERTEX_HOST || host.ends_with(&format!("-{VERTEX_HOST}"))
}
pub const PROJECT_PLACEHOLDER: &str = "{project}";
pub const REGION_PLACEHOLDER: &str = "{region}";
#[must_use]
pub fn names_a_project_literally(endpoint: &str) -> bool {
let Ok(url) = url::Url::parse(endpoint) else {
return false;
};
if !url.host_str().is_some_and(is_vertex_host) {
return false;
}
let mut segments = url.path_segments().into_iter().flatten();
while let Some(segment) = segments.next() {
if segment == "projects" {
return segments
.next()
.is_some_and(|id| id != "%7Bproject%7D" && id != PROJECT_PLACEHOLDER);
}
}
false
}