1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
//! C bindings for ergo-lib

// Coding conventions
#![deny(non_upper_case_globals)]
#![deny(non_camel_case_types)]
#![deny(non_snake_case)]
#![deny(unused_mut)]
#![deny(dead_code)]
#![deny(unused_imports)]
#![deny(clippy::unwrap_used)]
#![deny(clippy::expect_used)]
// #![deny(missing_docs)]
#![allow(clippy::missing_safety_doc)]

#[macro_use]
mod macros;
mod address;
mod batchmerkleproof;
mod block_header;
mod box_builder;
mod box_selector;
mod byte_array;
mod constant;
mod context_extension;
mod contract;
mod data_input;
mod ergo_box;
mod ergo_state_ctx;
mod ergo_tree;
mod ext_secret_key;
mod header;
mod input;
mod merkleproof;
mod nipopow;

mod reduced;

#[cfg(feature = "rest")]
mod rest;

mod secret_key;
mod token;
mod transaction;
mod tx_builder;
mod wallet;

pub use crate::address::*;
pub use crate::batchmerkleproof::*;
pub use crate::block_header::*;
pub use crate::box_builder::*;
pub use crate::box_selector::*;
pub use crate::byte_array::*;
pub use crate::context_extension::*;
pub use crate::contract::*;
pub use crate::data_input::*;
pub use crate::ergo_box::*;
pub use crate::ergo_state_ctx::*;
pub use crate::ergo_tree::*;
pub use crate::header::*;
pub use crate::input::*;
pub use crate::merkleproof::*;
pub use crate::nipopow::*;
pub use crate::reduced::*;
pub use crate::secret_key::*;
pub use crate::token::*;
pub use crate::transaction::*;
pub use crate::tx_builder::*;
pub use crate::wallet::*;
pub use ergo_lib_c_core::{
    address::{Address, AddressTypePrefix, NetworkPrefix},
    Error,
};
use std::{ffi::CString, os::raw::c_char};

pub type ErrorPtr = *mut Error;

#[no_mangle]
pub unsafe extern "C" fn ergo_lib_delete_string(ptr: *mut c_char) {
    if !ptr.is_null() {
        let cstring = CString::from_raw(ptr);
        std::mem::drop(cstring)
    }
}

#[no_mangle]
pub unsafe extern "C" fn ergo_lib_delete_error(error: ErrorPtr) {
    if !error.is_null() {
        let boxed = Box::from_raw(error);
        std::mem::drop(boxed);
    }
}

#[no_mangle]
pub unsafe extern "C" fn ergo_lib_error_to_string(error: ErrorPtr) -> *mut c_char {
    #[allow(clippy::unwrap_used)]
    if let Some(error) = error.as_ref() {
        CString::new(error.to_string()).unwrap().into_raw()
    } else {
        CString::new(b"success".to_vec()).unwrap().into_raw()
    }
}

/// Convenience type to allow us to pass Rust enums with `u8` representation through FFI to the C
/// side.
#[repr(C)]
pub struct ReturnNum<T: IntegerType> {
    /// Returned value. Note that it's only valid if the error field is null!
    value: T,
    error: ErrorPtr,
}

/// Convenience type to allow us to pass Rust bools (with possible error) through FFI to the C side.
#[repr(C)]
pub struct ReturnBool {
    /// Returned value. Note that it's only valid if the error field is null!
    value: bool,
    error: ErrorPtr,
}

/// Convenience type to allow us to pass Rust `Option<_>` types through FFI to C side.
#[repr(C)]
pub struct ReturnOption {
    is_some: bool,
    error: ErrorPtr,
}

/// Convenience type to allow us to pass Rust CStrings through FFI to C side (as pointers).
/// Note it is the responsibility of the caller to free the Rust CString.
/// For an example, see MnemonicGenerator in the Swift bindings.
#[repr(C)]
pub struct ReturnString {
    value: *mut c_char,
    error: ErrorPtr,
}

pub unsafe fn delete_ptr<T>(ptr: *mut T) {
    if !ptr.is_null() {
        let boxed = Box::from_raw(ptr);
        std::mem::drop(boxed);
    }
}
pub trait IntegerType {}

impl IntegerType for u8 {}
impl IntegerType for i32 {}
impl IntegerType for u32 {}
impl IntegerType for i64 {}
impl IntegerType for usize {}