use crate::Engine;
use crate::error::{Result, SconeError};
#[derive(Debug, Clone)]
pub struct ScopedSpace {
id: i64,
name: String,
}
impl ScopedSpace {
pub fn name(&self) -> &str {
&self.name
}
pub(crate) fn id(&self) -> i64 {
self.id
}
}
pub fn resolve(engine: &mut Engine, name: &str, create: bool) -> Result<ScopedSpace> {
if name.is_empty()
|| name.len() > 64
|| !name
.chars()
.all(|c| c.is_ascii_lowercase() || c.is_ascii_digit() || c == '-' || c == '_')
{
return Err(SconeError::InvalidInput(format!(
"space name must be 1..=64 chars of [a-z0-9-_], got {name:?}"
)));
}
let conn = engine.conn_mut();
if create {
conn.execute("INSERT OR IGNORE INTO spaces (name) VALUES (?1)", [name])?;
}
let id = conn
.query_row("SELECT id FROM spaces WHERE name = ?1", [name], |r| {
r.get(0)
})
.map_err(|e| match e {
rusqlite::Error::QueryReturnedNoRows => SconeError::NotFound(format!("space {name:?}")),
other => SconeError::Db(other),
})?;
Ok(ScopedSpace {
id,
name: name.to_owned(),
})
}