#![warn(missing_docs)]
mod array;
mod config;
mod dataset;
mod error;
mod meta;
mod schema;
mod store;
pub use config::{Codec, MetaFormat, StoreConfig};
pub use dataset::DatasetView;
pub use error::{Error, Result};
pub use meta::DatasetMeta;
pub use store::Atlas;
pub use array_format::{
ArrayElement, ArrayStats, DType, DeltaCache, FillValue, MergedArrayMeta, StatValue, TimestampNs,
};
pub use schema::{ArraySchema, Attr};
pub(crate) fn validate_name(name: &str) -> Result<()> {
if name.is_empty() || name.starts_with('_') || name.contains('/') || name == ".." || name == "."
{
return Err(Error::InvalidName(name.to_string()));
}
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn create_and_read_dataset() {
let tmp = tempfile::tempdir().unwrap();
{
let mut atlas = Atlas::create_path(tmp.path(), StoreConfig::default())
.await
.unwrap();
{
let mut view = atlas.create_dataset("ds").await.unwrap();
view.define_array::<f32>("temp", vec!["x".into()], vec![4], None, None)
.await
.unwrap();
}
atlas.flush().await.unwrap();
}
let atlas = Atlas::open_path(tmp.path()).await.unwrap();
let view = atlas.open_dataset("ds").await.unwrap();
assert_eq!(view.list_arrays(), vec!["temp".to_string()]);
}
#[test]
fn valid_names_pass() {
for name in ["temperature", "my-array", "x1", "lat.lon", "a"] {
assert!(validate_name(name).is_ok(), "expected '{name}' to be valid");
}
}
#[test]
fn empty_name_rejected() {
assert!(matches!(validate_name(""), Err(Error::InvalidName(_))));
}
#[test]
fn leading_underscore_rejected() {
assert!(matches!(
validate_name("_hidden"),
Err(Error::InvalidName(_))
));
assert!(matches!(validate_name("_"), Err(Error::InvalidName(_))));
}
#[test]
fn slash_in_name_rejected() {
assert!(matches!(validate_name("a/b"), Err(Error::InvalidName(_))));
assert!(matches!(validate_name("/abs"), Err(Error::InvalidName(_))));
}
#[test]
fn dotdot_rejected() {
assert!(matches!(validate_name(".."), Err(Error::InvalidName(_))));
}
#[test]
fn single_dot_rejected() {
assert!(matches!(validate_name("."), Err(Error::InvalidName(_))));
}
}
#[cfg(test)]
mod send_check {
use super::*;
fn _assert_send<T: Send>() {}
fn _assert_sync<T: Sync>() {}
#[test]
fn store_send() {
_assert_send::<Atlas>();
}
#[test]
fn view_send() {
_assert_send::<DatasetView>();
}
#[test]
fn store_sync() {
_assert_sync::<Atlas>();
}
#[test]
fn view_sync() {
_assert_sync::<DatasetView>();
}
}