use core::{mem, ptr::NonNull};
use crate::{
abi::{Declaration, Definitions},
linkme::distributed_slice,
schema::{Schema, SchemaMessage, SchemaType},
};
#[derive(Debug)]
pub struct Param {
pub name: &'static str,
pub decl: Declaration,
}
#[derive(Debug)]
pub struct EntryPoint {
pub name: &'static str,
pub params: &'static [&'static Param],
pub result_decl: Declaration,
}
#[derive(Debug, Clone)]
pub struct Message {
pub name: &'static str,
pub decl: &'static str,
}
pub struct Manifest {
pub name: &'static str,
pub entry_points: &'static [EntryPoint],
}
#[distributed_slice]
#[linkme(crate = crate::linkme)]
pub static ENTRYPOINTS: [fn() -> crate::schema::SchemaEntryPoint] = [..];
#[distributed_slice]
#[linkme(crate = crate::linkme)]
pub static ABI_COLLECTORS: [fn(&mut crate::abi::Definitions)] = [..];
#[distributed_slice]
#[linkme(crate = crate::linkme)]
pub static MESSAGES: [Message] = [..];
#[export_name = "__cargo_casper_collect_schema"]
pub unsafe extern "C" fn cargo_casper_collect_schema(size_ptr: *mut u64) -> *mut u8 {
let definitions = {
let mut definitions = Definitions::default();
for abi_collector in ABI_COLLECTORS {
abi_collector(&mut definitions);
}
definitions
};
let messages = {
let mut messages = Vec::new();
for message in MESSAGES {
messages.push(SchemaMessage {
name: message.name.to_owned(),
decl: message.decl.to_owned(),
});
}
messages
};
let entry_points = {
let mut entry_points = Vec::new();
for entrypoint in ENTRYPOINTS {
entry_points.push(entrypoint());
}
entry_points
};
let schema = Schema {
name: "contract".to_string(),
version: None,
type_: SchemaType::Contract {
state: "Contract".to_string(),
},
definitions,
entry_points,
messages,
};
let mut json_bytes = serde_json::to_vec(&schema).expect("Serialized schema");
NonNull::new(size_ptr)
.expect("expected non-null ptr")
.write(json_bytes.len().try_into().expect("usize to u64"));
let ptr = json_bytes.as_mut_ptr();
mem::forget(json_bytes);
ptr
}