use std::fmt::Display;
use std::fmt::Formatter;
use std::fmt::Result as FmtResult;
use std::ops::Deref;
use std::ops::DerefMut;
use fastobo_derive_internal::FromStr;
use crate::ast::*;
use crate::error::SyntaxError;
use crate::parser::Cache;
use crate::parser::FromPair;
use crate::semantics::Identified;
use crate::semantics::OboFrame;
use crate::semantics::Orderable;
use crate::syntax::pest::iterators::Pair;
use crate::syntax::Rule;
#[derive(Clone, Debug, Eq, FromStr, Hash, PartialEq)]
pub struct InstanceFrame {
id: Line<InstanceIdent>,
clauses: Vec<Line<InstanceClause>>,
}
impl InstanceFrame {
pub fn new<I>(id: I) -> Self
where
I: Into<Line<InstanceIdent>>,
{
Self::with_clauses(id, Vec::new())
}
pub fn with_clauses<I>(id: I, clauses: Vec<Line<InstanceClause>>) -> Self
where
I: Into<Line<InstanceIdent>>,
{
Self {
id: id.into(),
clauses,
}
}
pub fn id(&self) -> &Line<InstanceIdent> {
&self.id
}
pub fn id_mut(&mut self) -> &mut Line<InstanceIdent> {
&mut self.id
}
pub fn clauses(&self) -> &Vec<Line<InstanceClause>> {
&self.clauses
}
pub fn clauses_mut(&mut self) -> &mut Vec<Line<InstanceClause>> {
&mut self.clauses
}
pub fn name(&self) -> Result<&UnquotedString, CardinalityError> {
let mut name: Option<&UnquotedString> = None;
for clause in &self.clauses {
if let InstanceClause::Name(n) = clause.as_inner() {
match name {
Some(_) => return Err(CardinalityError::duplicate("name")),
None => name = Some(n),
}
}
}
name.ok_or_else(|| CardinalityError::missing("name"))
}
pub fn definition(&self) -> Result<&Definition, CardinalityError> {
let mut def: Option<&Definition> = None;
for clause in &self.clauses {
if let InstanceClause::Def(n) = clause.as_inner() {
match def {
Some(_) => return Err(CardinalityError::duplicate("def")),
None => def = Some(n),
}
}
}
def.ok_or_else(|| CardinalityError::missing("def"))
}
}
impl AsRef<Vec<Line<InstanceClause>>> for InstanceFrame {
fn as_ref(&self) -> &Vec<Line<InstanceClause>> {
&self.clauses
}
}
impl AsRef<[Line<InstanceClause>]> for InstanceFrame {
fn as_ref(&self) -> &[Line<InstanceClause>] {
&self.clauses
}
}
impl Deref for InstanceFrame {
type Target = Vec<Line<InstanceClause>>;
fn deref(&self) -> &Self::Target {
&self.clauses
}
}
impl DerefMut for InstanceFrame {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.clauses
}
}
impl Display for InstanceFrame {
fn fmt(&self, f: &mut Formatter) -> FmtResult {
f.write_str("[Instance]\nid: ").and(self.id.fmt(f))?;
self.clauses.iter().try_for_each(|clause| clause.fmt(f))
}
}
impl Identified for InstanceFrame {
fn as_id(&self) -> &Ident {
self.id.as_inner().as_ref()
}
fn as_id_mut(&mut self) -> &mut Ident {
self.id.as_mut().as_mut()
}
}
impl<'i> FromPair<'i> for InstanceFrame {
const RULE: Rule = Rule::InstanceFrame;
unsafe fn from_pair_unchecked(
pair: Pair<'i, Rule>,
cache: &Cache,
) -> Result<Self, SyntaxError> {
let mut inner = pair.into_inner();
let iid = InstanceIdent::from_pair_unchecked(inner.next().unwrap(), cache)?;
let id = Eol::from_pair_unchecked(inner.next().unwrap(), cache)?.and_inner(iid);
let mut clauses = Vec::new();
for pair in inner {
clauses.push(Line::<InstanceClause>::from_pair_unchecked(pair, cache)?);
}
Ok(InstanceFrame { id, clauses })
}
}
impl IntoIterator for InstanceFrame {
type Item = Line<InstanceClause>;
type IntoIter = <Vec<Line<InstanceClause>> as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.clauses.into_iter()
}
}
impl<'a> IntoIterator for &'a InstanceFrame {
type Item = &'a Line<InstanceClause>;
type IntoIter = <&'a [Line<InstanceClause>] as IntoIterator>::IntoIter;
fn into_iter(self) -> Self::IntoIter {
self.clauses.as_slice().iter()
}
}
impl Orderable for InstanceFrame {
fn sort(&mut self) {
self.clauses.sort_unstable();
}
fn is_sorted(&self) -> bool {
for i in 1..self.clauses.len() {
if self.clauses[i - 1] > self.clauses[i] {
return false;
}
}
true
}
}
impl OboFrame for InstanceFrame {
type Clause = InstanceClause;
fn clauses_ref(&self) -> Vec<&Self::Clause> {
self.clauses.iter().map(Line::as_inner).collect()
}
}