use std::sync::Arc;
use crate::{Error, Feature, Result, Schema};
pub trait Dataset {
fn layer_names(&self) -> Vec<String>;
fn open_layer<'a>(&'a self, name: &str) -> Result<Box<dyn Layer + 'a>>;
}
pub trait Layer {
fn name(&self) -> &str;
fn schema(&self) -> &Schema;
fn feature_count(&self) -> Option<i64>;
fn read<'a>(&'a self) -> Box<dyn Iterator<Item = Result<Feature>> + 'a>;
}
#[derive(Debug)]
pub struct SingleLayerDataset<L: Layer> {
pub inner: Arc<L>,
pub name: String,
}
impl<L: Layer> SingleLayerDataset<L> {
pub fn new(layer: L) -> Self {
Self {
inner: Arc::new(layer),
name: "default".to_string(),
}
}
pub fn with_name(layer: L, name: impl Into<String>) -> Self {
Self {
inner: Arc::new(layer),
name: name.into(),
}
}
}
impl<L: Layer + 'static> Dataset for SingleLayerDataset<L> {
fn layer_names(&self) -> Vec<String> {
vec![self.name.clone()]
}
fn open_layer<'a>(&'a self, name: &str) -> Result<Box<dyn Layer + 'a>> {
if name == self.name {
Ok(Box::new(LayerRef(self.inner.as_ref())))
} else {
Err(Error::LayerNotFound(name.to_string()))
}
}
}
#[derive(Debug)]
struct LayerRef<'a, L: Layer>(&'a L);
impl<'a, L: Layer> Layer for LayerRef<'a, L> {
fn name(&self) -> &str {
self.0.name()
}
fn schema(&self) -> &Schema {
self.0.schema()
}
fn feature_count(&self) -> Option<i64> {
self.0.feature_count()
}
fn read<'b>(&'b self) -> Box<dyn Iterator<Item = Result<Feature>> + 'b> {
self.0.read()
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::{Crs, FieldDef, GeomField, GeometryType, ValueType};
struct TestLayer {
name: String,
schema: Schema,
features: Vec<Feature>,
}
impl Layer for TestLayer {
fn name(&self) -> &str {
&self.name
}
fn schema(&self) -> &Schema {
&self.schema
}
fn feature_count(&self) -> Option<i64> {
Some(self.features.len() as i64)
}
fn read<'a>(&'a self) -> Box<dyn Iterator<Item = Result<Feature>> + 'a> {
Box::new(self.features.iter().cloned().map(Ok))
}
}
fn make_layer() -> TestLayer {
TestLayer {
name: "roads".into(),
schema: Schema::new(
vec![FieldDef::new("id", ValueType::Int32, false)],
Some(GeomField::new("geom", GeometryType::Point)),
Crs::Unknown,
),
features: vec![
Feature::new(Some(1), None, vec![crate::Value::Int32(1)]),
Feature::new(Some(2), None, vec![crate::Value::Int32(2)]),
],
}
}
#[test]
fn single_layer_dataset_exposes_one_layer() {
let ds = SingleLayerDataset::with_name(make_layer(), "default");
assert_eq!(ds.layer_names(), vec!["default"]);
let layer = ds.open_layer("default").unwrap();
assert_eq!(layer.feature_count(), Some(2));
}
#[test]
fn single_layer_dataset_rejects_wrong_name() {
let ds = SingleLayerDataset::new(make_layer());
assert!(ds.open_layer("nope").is_err());
}
#[test]
fn layer_read_iterator_yields_features() {
let layer = make_layer();
let v: Vec<_> = layer.read().collect::<Result<Vec<_>>>().unwrap();
assert_eq!(v.len(), 2);
}
#[test]
fn dataset_is_object_safe() {
fn _take_dataset(_: Box<dyn Dataset>) {}
let ds: Box<dyn Dataset> = Box::new(SingleLayerDataset::new(make_layer()));
_take_dataset(ds);
}
}