Skip to content

Instantly share code, notes, and snippets.

@dj8yfo
Last active June 26, 2023 10:33
Show Gist options
  • Save dj8yfo/da468206a03feca6d08698cbfc868ea0 to your computer and use it in GitHub Desktop.
Save dj8yfo/da468206a03feca6d08698cbfc868ea0 to your computer and use it in GitHub Desktop.
#![cfg_attr(not(feature = "std"), no_std)]
#[cfg(feature = "std")]
use std::collections::{btree_map::Entry, BTreeMap};
#[cfg(not(feature = "std"))]
extern crate alloc;
#[cfg(not(feature = "std"))]
use alloc::{
boxed::Box,
collections::{btree_map::Entry, BTreeMap},
format,
string::ToString,
vec,
};
use inner::{Declaration, Definition, Fields};
pub mod inner;
pub trait BorshSchema {
fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>);
fn add_definition(
declaration: Declaration,
definition: Definition,
definitions: &mut BTreeMap<Declaration, Definition>,
) {
match definitions.entry(declaration) {
Entry::Occupied(occ) => {
let existing_def = occ.get();
assert_eq!(existing_def, &definition, "Redefining type schema for the same type name. Types with the same names are not supported.");
}
Entry::Vacant(vac) => {
vac.insert(definition);
}
}
}
fn declaration() -> Declaration;
fn schema_container() -> BorshSchemaContainer {
let mut definitions = BTreeMap::new();
Self::add_definitions_recursively(&mut definitions);
BorshSchemaContainer::new(Self::declaration(), definitions)
}
}
// https://github.com/dj8yfo/borsh-rs/blob/tmp_link_container_guarantee/borsh/tests/test_schema_enums.rs#L164
#[cfg(feature = "std")]
pub mod container_serialization_guarantee {
use std::collections::BTreeMap;
use std::io::{Read, Write};
use crate::inner::{Declaration, Definition};
use crate::BorshSchemaContainer;
pub trait BorshSerialize {
fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()>;
}
pub trait BorshDeserialize: Sized {
fn deserialize_reader<R: Read>(reader: &mut R) -> std::io::Result<Self>;
}
impl BorshSerialize for Declaration {
fn serialize<W: Write>(&self, _writer: &mut W) -> std::io::Result<()> {
todo!("done already");
}
}
impl BorshSerialize for Definition {
fn serialize<W: Write>(&self, _writer: &mut W) -> std::io::Result<()> {
todo!("done already");
}
}
impl<K, V> BorshSerialize for BTreeMap<K, V>
where
K: BorshSerialize,
V: BorshSerialize,
{
fn serialize<W: Write>(&self, _writer: &mut W) -> std::io::Result<()> {
todo!("done already");
}
}
impl BorshDeserialize for Declaration {
fn deserialize_reader<R: Read>(_reader: &mut R) -> std::io::Result<Self> {
todo!("done already");
}
}
impl BorshDeserialize for Definition {
fn deserialize_reader<R: Read>(_reader: &mut R) -> std::io::Result<Self> {
todo!("done already");
}
}
impl<K, V> BorshDeserialize for BTreeMap<K, V>
where
K: BorshDeserialize + Ord + core::hash::Hash,
V: BorshDeserialize,
{
fn deserialize_reader<R: Read>(_reader: &mut R) -> std::io::Result<Self> {
todo!("done already");
}
}
impl BorshSerialize for BorshSchemaContainer
where
Declaration: BorshSerialize,
BTreeMap<Declaration, Definition>: BorshSerialize,
{
fn serialize<W: Write>(&self, writer: &mut W) -> std::io::Result<()> {
let declaration = self.declaration();
let definitions: BTreeMap<Declaration, Definition> = self
.definitions()
.map(|(k, v)| (k.clone(), v.clone()))
.collect();
BorshSerialize::serialize(declaration, writer)?;
BorshSerialize::serialize(&definitions, writer)?;
Ok(())
}
}
impl BorshDeserialize for BorshSchemaContainer
where
Declaration: BorshDeserialize,
BTreeMap<Declaration, Definition>: BorshDeserialize,
{
fn deserialize_reader<R: Read>(reader: &mut R) -> std::io::Result<Self> {
let declaration: Declaration = BorshDeserialize::deserialize_reader(reader)?;
let definitions: BTreeMap<Declaration, Definition> =
BorshDeserialize::deserialize_reader(reader)?;
Ok(Self::new(declaration, definitions))
}
}
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct BorshSchemaContainer {
declaration: Declaration,
definitions: BTreeMap<Declaration, Definition>,
}
impl BorshSchemaContainer {
pub fn new(declaration: Declaration, definitions: BTreeMap<Declaration, Definition>) -> Self {
Self {
declaration,
definitions,
}
}
pub fn declaration(&self) -> &Declaration {
&self.declaration
}
pub fn definitions<'_self>(
&'_self self,
) -> impl Iterator<Item = (&'_self Declaration, &'_self Definition)> {
self.definitions.iter()
}
pub fn get_def(&self, declaration: &Declaration) -> Option<&Definition> {
self.definitions.get(declaration)
}
pub fn get_mut_def(&mut self, declaration: &Declaration) -> Option<&mut Definition> {
self.definitions.get_mut(declaration)
}
pub fn insert_def(
&mut self,
declaration: Declaration,
definition: Definition,
) -> Option<Definition> {
self.definitions.insert(declaration, definition)
}
pub fn remove_def(&mut self, declaration: &Declaration) -> Option<Definition> {
self.definitions.remove(declaration)
}
}
impl BorshSchema for Declaration {
fn add_definitions_recursively(_definitions: &mut BTreeMap<Declaration, Definition>) {
todo!("done");
}
fn add_definition(
_declaration: Declaration,
_definition: Definition,
_definitions: &mut BTreeMap<Declaration, Definition>,
) {
todo!("done");
}
fn declaration() -> Declaration {
todo!("done");
}
fn schema_container() -> crate::BorshSchemaContainer {
todo!("done");
}
}
impl BorshSchema for Fields {
fn add_definitions_recursively(_definitions: &mut BTreeMap<Declaration, Definition>) {
todo!("done");
}
fn add_definition(
_declaration: Declaration,
_definition: Definition,
_definitions: &mut BTreeMap<Declaration, Definition>,
) {
todo!("done");
}
fn declaration() -> Declaration {
todo!("done");
}
fn schema_container() -> crate::BorshSchemaContainer {
todo!("done");
}
}
impl BorshSchema for Definition {
fn add_definitions_recursively(_definitions: &mut BTreeMap<Declaration, Definition>) {
todo!("done");
}
fn add_definition(
_declaration: Declaration,
_definition: Definition,
_definitions: &mut BTreeMap<Declaration, Definition>,
) {
todo!("done");
}
fn declaration() -> Declaration {
todo!("done");
}
fn schema_container() -> crate::BorshSchemaContainer {
todo!("done");
}
}
macro_rules! impl_tuple {
($($name:ident),+) => {
impl<$($name),+> BorshSchema for ($($name,)+)
where
$($name: BorshSchema),+
{
fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>) {
let elements = vec![$($name::declaration()),+];
let definition = Definition::Tuple { elements };
Self::add_definition(Self::declaration(), definition, definitions);
$(
$name::add_definitions_recursively(definitions);
)+
}
fn declaration() -> Declaration {
let params = vec![$($name::declaration()),+];
format!(r#"Tuple<{}>"#, params.join(", "))
}
}
};
}
impl_tuple!(T0, T1);
impl<K, V> BorshSchema for BTreeMap<K, V>
where
K: BorshSchema,
V: BorshSchema,
{
fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>) {
let definition = Definition::Sequence {
elements: <(K, V)>::declaration(),
};
Self::add_definition(Self::declaration(), definition, definitions);
<(K, V)>::add_definitions_recursively(definitions);
}
fn declaration() -> Declaration {
format!(r#"BTreeMap<{}, {}>"#, K::declaration(), V::declaration())
}
}
impl BorshSchema for BorshSchemaContainer
where
Declaration: BorshSchema,
BTreeMap<Declaration, Definition>: BorshSchema,
{
fn declaration() -> Declaration {
"BorshSchemaContainer".to_string()
}
fn add_definitions_recursively(definitions: &mut BTreeMap<Declaration, Definition>) {
let fields = Fields::NamedFields(<[_]>::into_vec(Box::new([
(
"declaration".to_string(),
<Declaration as BorshSchema>::declaration(),
),
(
"definitions".to_string(),
<BTreeMap<Declaration, Definition> as BorshSchema>::declaration(),
),
])));
let definition = Definition::Struct { fields };
Self::add_definition(
<Self as BorshSchema>::declaration(),
definition,
definitions,
);
<Declaration as BorshSchema>::add_definitions_recursively(definitions);
<BTreeMap<Declaration, Definition> as BorshSchema>::add_definitions_recursively(
definitions,
);
}
}
@dj8yfo
Copy link
Author

dj8yfo commented Jun 26, 2023

there's slight distinction, <Self as BorshSchema>::declaration() and Self::declaration(&self)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment