use crate::database::DatabaseAdapter;
#[derive(Clone)]
pub enum Datasource {
Database(DatabaseAdapter),
Api {
base_url: String,
headers: Vec<(String, String)>,
},
}
#[derive(Debug, PartialEq)]
pub enum DsnTarget<'a> {
Collection(&'a str),
Path(&'a str),
Root,
}
pub fn parse_dsn(url: &str) -> Option<(&str, DsnTarget<'_>)> {
let rest = url.strip_prefix("dsn:")?;
if rest.is_empty() {
return None;
}
if let Some(slash_pos) = rest.find('/') {
let name = &rest[..slash_pos];
if name.is_empty() {
return None;
}
let path = &rest[slash_pos..]; return Some((name, DsnTarget::Path(path)));
}
if let Some(dot_pos) = rest.find('.') {
let name = &rest[..dot_pos];
let collection = &rest[dot_pos + 1..];
if name.is_empty() || collection.is_empty() {
return None;
}
return Some((name, DsnTarget::Collection(collection)));
}
Some((rest, DsnTarget::Root))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_dsn_collection() {
let (name, target) = parse_dsn("dsn:users.profiles").unwrap();
assert_eq!(name, "users");
assert_eq!(target, DsnTarget::Collection("profiles"));
}
#[test]
fn test_parse_dsn_path() {
let (name, target) = parse_dsn("dsn:inventory/products").unwrap();
assert_eq!(name, "inventory");
assert_eq!(target, DsnTarget::Path("/products"));
}
#[test]
fn test_parse_dsn_nested_path() {
let (name, target) = parse_dsn("dsn:api/v2/users/active").unwrap();
assert_eq!(name, "api");
assert_eq!(target, DsnTarget::Path("/v2/users/active"));
}
#[test]
fn test_parse_dsn_root() {
let (name, target) = parse_dsn("dsn:mydb").unwrap();
assert_eq!(name, "mydb");
assert_eq!(target, DsnTarget::Root);
}
#[test]
fn test_parse_dsn_not_dsn_prefix() {
assert!(parse_dsn("local:posts").is_none());
assert!(parse_dsn("https://example.com").is_none());
}
#[test]
fn test_parse_dsn_empty_name() {
assert!(parse_dsn("dsn:").is_none());
assert!(parse_dsn("dsn:/path").is_none());
assert!(parse_dsn("dsn:.collection").is_none());
}
#[test]
fn test_parse_dsn_empty_collection() {
assert!(parse_dsn("dsn:name.").is_none());
}
#[test]
fn test_parse_dsn_path_takes_priority_over_dot() {
let (name, target) = parse_dsn("dsn:api/users.json").unwrap();
assert_eq!(name, "api");
assert_eq!(target, DsnTarget::Path("/users.json"));
}
#[test]
fn test_parse_dsn_trailing_slash() {
let (name, target) = parse_dsn("dsn:api/").unwrap();
assert_eq!(name, "api");
assert_eq!(target, DsnTarget::Path("/"));
}
#[test]
fn test_parse_dsn_just_prefix() {
assert!(parse_dsn("dsn:").is_none());
}
#[test]
fn test_parse_dsn_non_dsn_url() {
assert!(parse_dsn("http://example.com").is_none());
assert!(parse_dsn("").is_none());
}
#[test]
fn test_parse_dsn_deep_collection_name() {
let (name, target) = parse_dsn("dsn:db.schema.table").unwrap();
assert_eq!(name, "db");
assert_eq!(target, DsnTarget::Collection("schema.table"));
}
}