shex_ast 0.0.4

Rust implementation of ShEx
Documentation
use crate::schema::Schema;
use iri_s::IriS;
use prefix_map::PrefixMap;
use std::{error::Error, fmt};

pub struct SchemaBuilder {
    inner: Result<SchemaParts, ErrorBuildingSchema>,
}

#[derive(Debug)]
pub enum ErrorBuildingSchema {
    NotImplemented,
}
impl fmt::Display for ErrorBuildingSchema {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match &self {
            ErrorBuildingSchema::NotImplemented => write!(f, "Not implemented!"),
        }
    }
}
impl Error for ErrorBuildingSchema {}

// type Result<T> = Result<T,ErrorBuildingSchema>

struct SchemaParts {
    id: Option<IriS>,
    base: Option<IriS>,
    prefixes: PrefixMap,
    shapes_counter: u32,
}

impl SchemaBuilder {
    pub fn new() -> SchemaBuilder {
        SchemaBuilder::default()
    }

    pub fn add_prefix(self, alias: &str, iri: IriS) -> SchemaBuilder {
        self.and_then(move |mut schema_parts| {
            schema_parts.prefixes.insert(alias, iri);
            Ok(schema_parts)
        })
    }

    pub fn set_base(self, base: IriS) -> SchemaBuilder {
        self.and_then(move |mut schema_parts| {
            schema_parts.base = Some(base);
            Ok(schema_parts)
        })
    }

    pub fn add_shape(self) -> SchemaBuilder {
        self.and_then(move |mut schema_parts| {
            schema_parts.shapes_counter += 1;
            Ok(schema_parts)
        })
    }

    pub fn build(self) -> Result<Schema, ErrorBuildingSchema> {
        self.inner.and_then(|schema_parts| {
            Ok(Schema {
                id: schema_parts.id,
                base: schema_parts.base,
                prefixes: Some(schema_parts.prefixes),
            })
        })
    }

    // private
    fn and_then<F>(self, func: F) -> Self
    where
        F: FnOnce(SchemaParts) -> Result<SchemaParts, ErrorBuildingSchema>,
    {
        SchemaBuilder {
            inner: self.inner.and_then(func),
        }
    }
}

impl<'a> Default for SchemaBuilder {
    fn default() -> SchemaBuilder {
        SchemaBuilder {
            inner: Ok(SchemaParts {
                id: None,
                base: None,
                prefixes: PrefixMap::default(),
                shapes_counter: 0,
            }),
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::str::FromStr;

    fn update_base(sb: SchemaBuilder, iri: IriS) -> Result<SchemaBuilder, ErrorBuildingSchema> {
        Ok(sb.set_base(iri))
    }

    fn update_prefix_map(
        sb: SchemaBuilder,
        alias: &str,
        iri: &IriS,
    ) -> Result<SchemaBuilder, ErrorBuildingSchema> {
        Ok(sb.add_prefix(alias, iri.to_owned()))
    }

    #[test]
    fn test_update_base() {
        let sb = SchemaBuilder::new();
        let iri = IriS::from_str("http://example.org/").unwrap();
        let schema = update_base(sb, iri).unwrap().build().unwrap();
        assert_eq!(
            schema.base(),
            Some(IriS::from_str("http://example.org/").unwrap())
        );
    }

    #[test]
    fn test_update_prefix_map() {
        let sb = SchemaBuilder::new();
        let iri = IriS::from_str("http://example.org/").unwrap();
        let schema = update_prefix_map(sb, &"ss", &iri).unwrap().build().unwrap();
        assert_eq!(
            schema.resolve(&"ss:foo").unwrap(),
            Some(IriS::from_str("http://example.org/foo").unwrap())
        );
    }
}