use powerio_core::{Error, PioModule, Source};
use super::source_text;
use crate::diagnostics::codes;
use crate::instance::AcScucInstance;
use crate::scopf::{ScopfError, parse_scopf_str};
pub fn parse_goc3_instance(source: Source) -> Result<PioModule<AcScucInstance>, Error> {
let source = match source.format() {
Some(_) => source,
None => source.with_format(powerio_core::FormatId::new("goc3-json")?),
};
match parse_goc3_text(&source) {
Ok((instance, diagnostics)) => PioModule::parsed(instance, source, diagnostics),
Err(error) => Err(error.with_source(source)),
}
}
fn parse_goc3_text(
source: &Source,
) -> Result<(AcScucInstance, Vec<powerio_core::Diagnostic>), Error> {
let name = source.name().to_owned();
let buffer = source.primary_buffer()?;
let content = source_text(&buffer)?;
let (network, diagnostics, _document) = powerio_tx::parse_goc3_json(content)
.map_err(|error| Error::new(error.code(), format!("{name}: {error}")))?;
let inputs = parse_scopf_str(content, "goc3-json").map_err(|error| scopf_error(&error))?;
let stated = inputs.static_data.bus.len();
if stated != network.buses().len() {
return Err(Error::new(
&codes::BUILD_INSTANCE_SHAPE_MISMATCH,
format!(
"{name}: the typed categories state {stated} buses; the network states {}",
network.buses().len()
),
));
}
for (row, bus) in inputs.static_data.bus.iter().zip(network.buses()) {
if row.i != bus.id {
return Err(Error::new(
&codes::BUILD_INSTANCE_SHAPE_MISMATCH,
format!(
"{name}: bus \"{}\" resolved to id {} in the categories and {} in the network",
row.uid, row.i.0, bus.id.0
),
));
}
}
let instance = AcScucInstance::new(network, inputs)?;
Ok((instance, diagnostics))
}
fn scopf_error(error: &ScopfError) -> Error {
Error::new(error.code(), error.to_string())
}