use alloc::{rc::Rc, string::String, vec::Vec};
use core::{cell::RefCell, convert::From};
use std::hash::{Hash, Hasher};
use grammartec::{
newtypes::NodeID,
rule::RuleIDOrCustom,
tree::{Tree, TreeLike},
};
use serde::{Deserialize, Serialize};
use crate::{bolts::HasLen, generators::nautilus::NautilusContext, inputs::Input};
#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct NautilusInput {
pub tree: Tree,
}
impl Input for NautilusInput {
#[must_use]
fn generate_name(&self, idx: usize) -> String {
format!("id:{idx}")
}
}
impl From<NautilusInput> for Rc<RefCell<NautilusInput>> {
fn from(input: NautilusInput) -> Self {
Rc::new(RefCell::new(input))
}
}
impl HasLen for NautilusInput {
#[inline]
fn len(&self) -> usize {
self.tree.size()
}
}
impl NautilusInput {
#[must_use]
pub fn new(tree: Tree) -> Self {
Self { tree }
}
#[must_use]
pub fn empty() -> Self {
Self {
tree: Tree {
rules: vec![],
sizes: vec![],
paren: vec![],
},
}
}
pub fn unparse(&self, context: &NautilusContext, bytes: &mut Vec<u8>) {
bytes.clear();
self.tree.unparse(NodeID::from(0), &context.ctx, bytes);
}
#[must_use]
pub fn tree(&self) -> &Tree {
&self.tree
}
#[must_use]
pub fn tree_mut(&mut self) -> &mut Tree {
&mut self.tree
}
}
impl Hash for NautilusInput {
fn hash<H: Hasher>(&self, state: &mut H) {
self.tree().paren.hash(state);
for r in &self.tree().rules {
match r {
RuleIDOrCustom::Custom(a, b) => {
a.hash(state);
b.hash(state);
}
RuleIDOrCustom::Rule(a) => a.hash(state),
}
}
self.tree().sizes.hash(state);
}
}