use std::collections::{BTreeMap, VecDeque};
use serde_json::Value;
use zksync_basic_types::H256;
use crate::eip712_signature::typed_structure::{EncodedStructureMember, StructMember};
pub trait StructBuilder {
fn new() -> Self;
fn add_member<MEMBER: StructMember>(&mut self, name: &str, member: &MEMBER);
}
pub(crate) struct TypeBuilder {
members: Vec<EncodedStructureMember>,
}
impl TypeBuilder {
pub fn get_inner_members(&self) -> Vec<EncodedStructureMember> {
self.members.clone()
}
}
impl StructBuilder for TypeBuilder {
fn new() -> Self {
Self {
members: Vec::new(),
}
}
fn add_member<MEMBER: StructMember>(&mut self, name: &str, member: &MEMBER) {
self.members
.push(EncodedStructureMember::encode(name, member));
}
}
struct OuterTypeBuilder {
inner_members_queue: VecDeque<EncodedStructureMember>,
}
impl OuterTypeBuilder {
fn new() -> Self {
Self {
inner_members_queue: VecDeque::new(),
}
}
fn add_member(&mut self, encoded_member: EncodedStructureMember) {
if encoded_member.is_reference_type {
self.inner_members_queue.push_back(encoded_member);
}
}
fn build(mut self) -> BTreeMap<String, EncodedStructureMember> {
let mut result = BTreeMap::new();
while let Some(front_element) = self.inner_members_queue.pop_front() {
if result.contains_key(&front_element.member_type) {
continue;
}
result.insert(front_element.member_type.clone(), front_element.clone());
for inner_member in front_element.inner_members {
if inner_member.is_reference_type && !result.contains_key(&inner_member.member_type)
{
self.inner_members_queue.push_back(inner_member);
}
}
}
result
}
}
pub(crate) struct EncodeBuilder {
members: Vec<(EncodedStructureMember, H256)>,
}
impl EncodeBuilder {
pub fn encode_data(&self) -> Vec<H256> {
self.members.iter().map(|(_, data)| *data).collect()
}
pub fn encode_type(&self, type_name: &str) -> String {
let mut result = String::new();
let mut outer_members_builder = OuterTypeBuilder::new();
for (member, _) in self.members.iter() {
outer_members_builder.add_member(member.clone());
}
let outer_members = outer_members_builder.build();
let inner_member = {
let member_type = type_name.to_string();
let inner_members = self
.members
.iter()
.cloned()
.map(|(encoded_struct, _)| encoded_struct)
.collect::<Vec<_>>();
EncodedStructureMember {
member_type,
name: String::default(),
is_reference_type: true,
inner_members,
}
};
result.push_str(&inner_member.get_encoded_type());
for (_, outer_member) in outer_members {
result.push_str(&outer_member.get_encoded_type());
}
result
}
pub fn get_json_types(&self, type_name: &str) -> Vec<Value> {
let mut result = Vec::new();
let mut outer_members_builder = OuterTypeBuilder::new();
for (member, _) in self.members.iter() {
outer_members_builder.add_member(member.clone());
}
let outer_members = outer_members_builder.build();
let inner_member = {
let member_type = type_name.to_string();
let inner_members = self
.members
.iter()
.cloned()
.map(|(encoded_struct, _)| encoded_struct)
.collect::<Vec<_>>();
EncodedStructureMember {
member_type,
name: String::default(),
is_reference_type: true,
inner_members,
}
};
result.push(inner_member.get_json_types());
for (_, outer_member) in outer_members {
result.push(outer_member.get_json_types());
}
result
}
}
impl StructBuilder for EncodeBuilder {
fn new() -> Self {
Self {
members: Vec::new(),
}
}
fn add_member<MEMBER: StructMember>(&mut self, name: &str, member: &MEMBER) {
let encoded_data = member.encode_member_data();
self.members
.push((EncodedStructureMember::encode(name, member), encoded_data));
}
}