casper-contract-sdk 0.1.2

Casper contract sdk package
Documentation
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],
}

/// All of the entry points generated by proc macro will be registered here.
#[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] = [..];

/// This function is called by the host to collect the schema from the contract.
///
/// This is considered internal implementation detail and should not be used directly.
/// Primary user of this API is `cargo_casper` tool that will use it to extract scheama from the
/// contract.
///
/// # Safety
/// Pointer to json bytes passed to the callback is valid only within the scope of that function.
#[export_name = "__cargo_casper_collect_schema"]
pub unsafe extern "C" fn cargo_casper_collect_schema(size_ptr: *mut u64) -> *mut u8 {
    // Collect definitions
    let definitions = {
        let mut definitions = Definitions::default();

        for abi_collector in ABI_COLLECTORS {
            abi_collector(&mut definitions);
        }

        definitions
    };

    // Collect messages
    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
    };

    // Collect entrypoints
    let entry_points = {
        let mut entry_points = Vec::new();
        for entrypoint in ENTRYPOINTS {
            entry_points.push(entrypoint());
        }
        entry_points
    };

    // Construct a schema object from the extracted information
    let schema = Schema {
        name: "contract".to_string(),
        version: None,
        type_: SchemaType::Contract {
            state: "Contract".to_string(),
        },
        definitions,
        entry_points,
        messages,
    };

    // Write the schema using the provided writer
    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
}