pub mod model;
pub mod simple_parser;
pub mod validator;
pub use simple_parser::Parser;
pub use model::{Document, Fact, Context, Unit};
pub struct Validator {
inner: validator::XbrlValidator,
#[allow(dead_code)]
strict: bool,
}
impl Validator {
pub fn new() -> Self {
Self {
inner: validator::XbrlValidator::new(),
strict: false,
}
}
pub fn with_config(config: ValidationConfig) -> Self {
let mut inner = validator::XbrlValidator::new();
if config.strict {
inner = inner.strict();
}
Self {
inner,
strict: config.strict,
}
}
pub fn sec_edgar() -> Self {
Self {
inner: validator::XbrlValidator::new().strict(),
strict: true,
}
}
pub fn validate(&self, doc: &Document) -> Result<ValidationResult> {
let start = std::time::Instant::now();
let mut doc_copy = doc.clone();
let is_valid = self.inner.validate(&mut doc_copy).is_ok();
Ok(ValidationResult {
is_valid,
errors: if is_valid {
Vec::new()
} else {
vec!["Validation failed".to_string()]
},
warnings: Vec::new(),
stats: ValidationStats {
facts_validated: doc.facts.len(),
duration_ms: start.elapsed().as_millis() as u64,
},
})
}
}
pub struct ValidationConfig {
pub strict: bool,
}
impl ValidationConfig {
pub fn sec_edgar() -> Self {
Self { strict: true }
}
}
impl Default for ValidationConfig {
fn default() -> Self {
Self { strict: false }
}
}
pub struct ValidationResult {
pub is_valid: bool,
pub errors: Vec<String>,
pub warnings: Vec<String>,
pub stats: ValidationStats,
}
pub struct ValidationStats {
pub facts_validated: usize,
pub duration_ms: u64,
}
pub type Result<T> = std::result::Result<T, Error>;
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("IO error: {0}")]
Io(#[from] std::io::Error),
#[error("Parse error: {0}")]
Parse(String),
#[error("Validation error: {0}")]
Validation(String),
#[error("Not found: {0}")]
NotFound(String),
}