use crate::tm_std::*;
use crate::{
form::{CompactForm, Form},
interner::{Interner, UntrackedSymbol},
meta_type::MetaType,
Type,
};
use scale::{Decode, Encode};
use serde::{Deserialize, Serialize};
pub trait IntoCompact {
type Output;
fn into_compact(self, registry: &mut Registry) -> Self::Output;
}
impl IntoCompact for &'static str {
type Output = <CompactForm as Form>::String;
fn into_compact(self, _registry: &mut Registry) -> Self::Output {
self.to_string()
}
}
#[derive(Debug, PartialEq, Eq, Serialize)]
pub struct Registry {
#[serde(skip)]
type_table: Interner<TypeId>,
#[serde(serialize_with = "serialize_registry_types")]
types: BTreeMap<UntrackedSymbol<core::any::TypeId>, Type<CompactForm>>,
}
fn serialize_registry_types<S>(
types: &BTreeMap<UntrackedSymbol<core::any::TypeId>, Type<CompactForm>>,
serializer: S,
) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
let types = types.values().collect::<Vec<_>>();
types.serialize(serializer)
}
impl Default for Registry {
fn default() -> Self {
Self::new()
}
}
impl Encode for Registry {
fn size_hint(&self) -> usize {
mem::size_of::<u32>() + mem::size_of::<Type<CompactForm>>() * self.types.len()
}
fn encode_to<W: scale::Output>(&self, dest: &mut W) {
if self.types.len() > u32::max_value() as usize {
panic!("Attempted to encode too many elements.");
}
scale::Compact(self.types.len() as u32).encode_to(dest);
for ty in self.types.values() {
ty.encode_to(dest);
}
}
}
impl Registry {
pub fn new() -> Self {
Self {
type_table: Interner::new(),
types: BTreeMap::new(),
}
}
fn intern_type_id(&mut self, type_id: TypeId) -> (bool, UntrackedSymbol<TypeId>) {
let (inserted, symbol) = self.type_table.intern_or_get(type_id);
(inserted, symbol.into_untracked())
}
pub fn register_type(&mut self, ty: &MetaType) -> UntrackedSymbol<TypeId> {
let (inserted, symbol) = self.intern_type_id(ty.type_id());
if inserted {
let compact_id = ty.type_info().into_compact(self);
self.types.insert(symbol, compact_id);
}
symbol
}
pub fn register_types<I>(&mut self, iter: I) -> Vec<UntrackedSymbol<TypeId>>
where
I: IntoIterator<Item = MetaType>,
{
iter.into_iter().map(|i| self.register_type(&i)).collect::<Vec<_>>()
}
pub fn map_into_compact<I, T>(&mut self, iter: I) -> Vec<T::Output>
where
I: IntoIterator<Item = T>,
T: IntoCompact,
{
iter.into_iter().map(|i| i.into_compact(self)).collect::<Vec<_>>()
}
}
#[derive(Debug, PartialEq, Eq, Serialize, Deserialize, Decode)]
pub struct RegistryReadOnly {
types: Vec<Type<CompactForm>>,
}
impl From<Registry> for RegistryReadOnly {
fn from(registry: Registry) -> Self {
RegistryReadOnly {
types: registry.types.values().cloned().collect::<Vec<_>>(),
}
}
}
impl RegistryReadOnly {
pub fn resolve(&self, id: NonZeroU32) -> Option<&Type<CompactForm>> {
self.types.get((id.get() - 1) as usize)
}
}