use crypto::hash::{HashTrait, HashType};
use std::collections::HashMap;
pub use tezos_data_encoding_derive::HasEncoding;
#[derive(Debug, Clone)]
pub struct Field {
name: String,
encoding: Encoding,
}
impl Field {
pub fn new(name: &str, encoding: Encoding) -> Field {
Field {
name: String::from(name),
encoding,
}
}
pub fn get_name(&self) -> &String {
&self.name
}
pub fn get_encoding(&self) -> &Encoding {
&self.encoding
}
}
pub type Schema = Vec<Field>;
#[derive(Debug, Clone)]
pub struct Tag {
id: u16,
variant: String,
encoding: Encoding,
}
impl Tag {
pub fn new(id: u16, variant: &str, encoding: Encoding) -> Tag {
Tag {
id,
variant: String::from(variant),
encoding,
}
}
pub fn get_id(&self) -> u16 {
self.id
}
pub fn get_encoding(&self) -> &Encoding {
&self.encoding
}
pub fn get_variant(&self) -> &String {
&self.variant
}
}
#[derive(Debug, Clone)]
pub struct TagMap {
id_to_tag: HashMap<u16, Tag>,
variant_to_id: HashMap<String, u16>,
}
impl TagMap {
pub fn new(tags: Vec<Tag>) -> TagMap {
let mut id_to_tag = HashMap::new();
let mut variant_to_id = HashMap::new();
for tag in tags {
let tag_id = tag.get_id();
let variant = tag.get_variant().to_string();
let prev_item = id_to_tag.insert(tag_id, tag);
debug_assert!(
prev_item.is_none(),
"Tag id: 0x{:X} is already present in TagMap",
tag_id
);
variant_to_id.insert(variant, tag_id);
}
TagMap {
id_to_tag,
variant_to_id,
}
}
pub fn find_by_id(&self, id: u16) -> Option<&Tag> {
self.id_to_tag.get(&id)
}
pub fn find_by_variant(&self, variant: &str) -> Option<&Tag> {
self.variant_to_id
.get(variant)
.and_then(|tag_id| self.id_to_tag.get(tag_id))
}
pub fn tags(&self) -> impl Iterator<Item = &Tag> {
self.id_to_tag.values()
}
}
#[derive(Debug, Clone)]
pub enum Encoding {
Unit,
Int8,
Uint8,
Int16,
Uint16,
Int31,
Int32,
Uint32,
Int64,
RangedInt,
Z,
Mutez,
Float,
RangedFloat,
Bool,
String,
BoundedString(usize),
Bytes,
Tags(usize, TagMap),
List(Box<Encoding>),
BoundedList(usize, Box<Encoding>),
Enum,
Option(Box<Encoding>),
OptionalField(Box<Encoding>),
Obj(&'static str, Schema),
Tup(Vec<Encoding>),
ShortDynamic(Box<Encoding>),
Dynamic(Box<Encoding>),
BoundedDynamic(usize, Box<Encoding>),
Sized(usize, Box<Encoding>),
Bounded(usize, Box<Encoding>),
Greedy(Box<Encoding>),
Hash(HashType),
Timestamp,
Custom,
}
impl Encoding {
#[inline]
pub fn list(encoding: Encoding) -> Encoding {
Encoding::List(Box::new(encoding))
}
#[inline]
pub fn bounded_list(max: usize, encoding: Encoding) -> Encoding {
Encoding::BoundedList(max, Box::new(encoding))
}
#[inline]
pub fn sized(bytes_sz: usize, encoding: Encoding) -> Encoding {
Encoding::Sized(bytes_sz, Box::new(encoding))
}
#[inline]
pub fn bounded(max: usize, encoding: Encoding) -> Encoding {
Encoding::Bounded(max, Box::new(encoding))
}
#[inline]
pub fn greedy(encoding: Encoding) -> Encoding {
Encoding::Greedy(Box::new(encoding))
}
#[inline]
pub fn short_dynamic(encoding: Encoding) -> Encoding {
Encoding::Dynamic(Box::new(encoding))
}
#[inline]
pub fn dynamic(encoding: Encoding) -> Encoding {
Encoding::Dynamic(Box::new(encoding))
}
#[inline]
pub fn bounded_dynamic(max: usize, encoding: Encoding) -> Encoding {
Encoding::BoundedDynamic(max, Box::new(encoding))
}
#[inline]
pub fn option(encoding: Encoding) -> Encoding {
Encoding::Option(Box::new(encoding))
}
#[inline]
pub fn option_field(encoding: Encoding) -> Encoding {
Encoding::OptionalField(Box::new(encoding))
}
}
pub trait HasEncoding {
fn encoding() -> Encoding;
}
macro_rules! hash_has_encoding {
($hash_name:ident, $enc_ref_name:ident) => {
impl HasEncoding for crypto::hash::$hash_name {
fn encoding() -> Encoding {
Encoding::Hash(crypto::hash::$hash_name::hash_type())
}
}
};
}
hash_has_encoding!(ChainId, CHAIN_ID);
hash_has_encoding!(BlockHash, BLOCK_HASH);
hash_has_encoding!(BlockMetadataHash, BLOCK_METADATA_HASH);
hash_has_encoding!(BlockPayloadHash, BLOCK_PAYLOAD_HASH);
hash_has_encoding!(OperationHash, OPERATION_HASH);
hash_has_encoding!(OperationListListHash, OPERATION_LIST_LIST_HASH);
hash_has_encoding!(OperationMetadataHash, OPERATION_METADATA_HASH);
hash_has_encoding!(
OperationMetadataListListHash,
OPERATION_METADATA_LIST_LIST_HASH
);
hash_has_encoding!(ContextHash, CONTEXT_HASH);
hash_has_encoding!(ProtocolHash, PROTOCOL_HASH);
hash_has_encoding!(ContractKt1Hash, CONTRACT_KT1HASH);
hash_has_encoding!(ContractTz1Hash, CONTRACT_TZ1HASH);
hash_has_encoding!(ContractTz2Hash, CONTRACT_TZ2HASH);
hash_has_encoding!(ContractTz3Hash, CONTRACT_TZ3HASH);
hash_has_encoding!(ContractTz4Hash, CONTRACT_TZ4HASH);
hash_has_encoding!(CryptoboxPublicKeyHash, CRYPTOBOX_PUBLIC_KEY_HASH);
hash_has_encoding!(PublicKeyEd25519, PUBLIC_KEY_ED25519);
hash_has_encoding!(PublicKeySecp256k1, PUBLIC_KEY_SECP256K1);
hash_has_encoding!(PublicKeyP256, PUBLIC_KEY_P256);
hash_has_encoding!(PublicKeyBls, PUBLIC_KEY_BLS);
hash_has_encoding!(SecretKeyEd25519, SECRET_KEY_ED25519);
hash_has_encoding!(SecretKeyBls, SECRET_KEY_BLS);
hash_has_encoding!(Signature, SIGNATURE);
hash_has_encoding!(BlsSignature, BLS_SIGNATURE_HASH);
hash_has_encoding!(NonceHash, NONCE_HASH);
hash_has_encoding!(SmartRollupHash, SMART_ROLLUP_HASH);
#[macro_export]
macro_rules! has_encoding {
($struct_name:ident, $enc_ref_name:ident, $code:block) => {
impl HasEncoding for $struct_name {
fn encoding() -> Encoding {
$code
}
}
};
}