1pub mod member;
18pub use member::*;
19
20use crate::{ConstParameter, Identifier, Indent, Mode, Node, NodeID, ProgramId, TypeKind, TypeNode};
21use leo_span::{Span, Symbol};
22
23use itertools::Itertools;
24use serde::Serialize;
25use std::fmt;
26
27use snarkvm::{
28 console::program::{RecordType, StructType},
29 prelude::{
30 EntryType::{Constant, Private, Public},
31 Network,
32 },
33};
34
35#[derive(Clone, Debug, Serialize)]
41pub struct Composite {
42 pub is_exported: Option<bool>,
46 pub identifier: Identifier,
48 pub const_parameters: Vec<ConstParameter>,
50 pub members: Vec<Member>,
52 pub is_record: bool,
55 pub span: Span,
57 pub id: NodeID,
59}
60
61impl PartialEq for Composite {
62 fn eq(&self, other: &Self) -> bool {
63 self.identifier == other.identifier
64 }
65}
66
67impl Eq for Composite {}
68
69impl Composite {
70 pub fn name(&self) -> Symbol {
72 self.identifier.name
73 }
74
75 pub fn from_external_record<N: Network>(input: &RecordType<N>, program_id: ProgramId) -> Self {
78 let mut members = Vec::with_capacity(input.entries().len() + 1);
79 members.push(Member {
80 mode: if input.owner().is_public() { Mode::Public } else { Mode::Private },
81 identifier: Identifier::new(Symbol::intern("owner"), Default::default()),
82 type_: TypeNode::unchecked(TypeKind::Address, Span::default()),
83 span: Default::default(),
84 id: Default::default(),
85 });
86 members.extend(input.entries().iter().map(|(id, entry)| {
87 let (mode, type_) = match entry {
88 Public(type_) => (Mode::Public, type_),
89 Private(type_) => (Mode::Private, type_),
90 Constant(type_) => (Mode::Constant, type_),
91 };
92 Member {
93 mode,
94 identifier: Identifier::from(id),
95 type_: TypeNode::unchecked(TypeKind::from_snarkvm(type_, program_id), Span::default()),
96 span: Default::default(),
97 id: Default::default(),
98 }
99 }));
100 Self {
101 is_exported: None,
102 identifier: Identifier::from(input.name()),
103 const_parameters: Vec::new(),
104 members,
105 is_record: true,
106 span: Default::default(),
107 id: Default::default(),
108 }
109 }
110
111 pub fn from_snarkvm<N: Network>(input: &StructType<N>, program: ProgramId) -> Self {
113 Self {
114 is_exported: None,
115 identifier: Identifier::from(input.name()),
116 const_parameters: Vec::new(),
117 members: input
118 .members()
119 .iter()
120 .map(|(id, type_)| Member {
121 mode: Mode::None,
122 identifier: Identifier::from(id),
123 type_: TypeNode::unchecked(TypeKind::from_snarkvm(type_, program), Span::default()),
124 span: Default::default(),
125 id: Default::default(),
126 })
127 .collect(),
128 is_record: false,
129 span: Default::default(),
130 id: Default::default(),
131 }
132 }
133}
134
135impl fmt::Display for Composite {
136 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137 if self.is_exported == Some(true) {
138 f.write_str("export ")?;
139 }
140 f.write_str(if self.is_record { "record" } else { "struct" })?;
141 write!(f, " {}", self.identifier)?;
142 if !self.const_parameters.is_empty() {
143 write!(f, "::[{}]", self.const_parameters.iter().format(", "))?;
144 }
145 writeln!(f, " {{")?;
146
147 for field in self.members.iter() {
148 writeln!(f, "{},", Indent(field))?;
149 }
150 write!(f, "}}")
151 }
152}
153
154crate::simple_node_impl!(Composite);