pub mod member;
pub use member::*;
use crate::{ConstParameter, Identifier, Indent, Mode, Node, NodeID, ProgramId, TypeKind, TypeNode};
use leo_span::{Span, Symbol};
use itertools::Itertools;
use serde::Serialize;
use std::fmt;
use snarkvm::{
console::program::{RecordType, StructType},
prelude::{
EntryType::{Constant, Private, Public},
Network,
},
};
#[derive(Clone, Debug, Serialize)]
pub struct Composite {
pub is_exported: Option<bool>,
pub identifier: Identifier,
pub const_parameters: Vec<ConstParameter>,
pub members: Vec<Member>,
pub is_record: bool,
pub span: Span,
pub id: NodeID,
}
impl PartialEq for Composite {
fn eq(&self, other: &Self) -> bool {
self.identifier == other.identifier
}
}
impl Eq for Composite {}
impl Composite {
pub fn name(&self) -> Symbol {
self.identifier.name
}
pub fn from_external_record<N: Network>(input: &RecordType<N>, program_id: ProgramId) -> Self {
let mut members = Vec::with_capacity(input.entries().len() + 1);
members.push(Member {
mode: if input.owner().is_public() { Mode::Public } else { Mode::Private },
identifier: Identifier::new(Symbol::intern("owner"), Default::default()),
type_: TypeNode::unchecked(TypeKind::Address, Span::default()),
span: Default::default(),
id: Default::default(),
});
members.extend(input.entries().iter().map(|(id, entry)| {
let (mode, type_) = match entry {
Public(type_) => (Mode::Public, type_),
Private(type_) => (Mode::Private, type_),
Constant(type_) => (Mode::Constant, type_),
};
Member {
mode,
identifier: Identifier::from(id),
type_: TypeNode::unchecked(TypeKind::from_snarkvm(type_, program_id), Span::default()),
span: Default::default(),
id: Default::default(),
}
}));
Self {
is_exported: None,
identifier: Identifier::from(input.name()),
const_parameters: Vec::new(),
members,
is_record: true,
span: Default::default(),
id: Default::default(),
}
}
pub fn from_snarkvm<N: Network>(input: &StructType<N>, program: ProgramId) -> Self {
Self {
is_exported: None,
identifier: Identifier::from(input.name()),
const_parameters: Vec::new(),
members: input
.members()
.iter()
.map(|(id, type_)| Member {
mode: Mode::None,
identifier: Identifier::from(id),
type_: TypeNode::unchecked(TypeKind::from_snarkvm(type_, program), Span::default()),
span: Default::default(),
id: Default::default(),
})
.collect(),
is_record: false,
span: Default::default(),
id: Default::default(),
}
}
}
impl fmt::Display for Composite {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if self.is_exported == Some(true) {
f.write_str("export ")?;
}
f.write_str(if self.is_record { "record" } else { "struct" })?;
write!(f, " {}", self.identifier)?;
if !self.const_parameters.is_empty() {
write!(f, "::[{}]", self.const_parameters.iter().format(", "))?;
}
writeln!(f, " {{")?;
for field in self.members.iter() {
writeln!(f, "{},", Indent(field))?;
}
write!(f, "}}")
}
}
crate::simple_node_impl!(Composite);