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
mod api;

const MAX_OUTPUT_LEN: usize = 256*3*2; // output if Fp = 1023 bits, Fp3 extension, affine point

pub fn run(bytes: &[u8]) -> Result<Vec<u8>, String> {
    let mut result = vec![0u8; MAX_OUTPUT_LEN];
    let mut error_description_buffer = vec![0u8; MAX_OUTPUT_LEN];
    let input = bytes.as_ptr() as *const std::os::raw::c_char;
    let output = result.as_mut_ptr() as *mut std::os::raw::c_char;
    let error_buffer = error_description_buffer.as_mut_ptr() as *mut std::os::raw::c_char;
    let input_len = bytes.len() as u32;
    let mut output_len = 0u32;
    let mut error_description_len = 0u32;

    let success = unsafe { self::api::run(
        input, 
        input_len, 
        output, 
        &mut output_len as *mut u32,
        error_buffer,
        &mut error_description_len as *mut u32
    ) };
    if success == 0 {
        if error_description_len == 0 {
            return Err("C++ api returned empty error description".to_string());
        }
        error_description_buffer.truncate(error_description_len as usize);
        let error_description_string = std::ffi::CString::new(error_description_buffer);
        match error_description_string {
            Ok(c_string) => {
                let string = c_string.into_string();
                match string {
                    Ok(string) => {
                        return Err(string);
                    },
                    Err(err) => {
                        return Err(format!("Error on conversion of string description, {:?}", err));
                    }
                }
            },
            Err(n_error) => {
                return Err(format!("CString containts empty bytes in a middle, {:?}", n_error));
            }
        }
    }

    result.truncate(output_len as usize);

    Ok(result)
}

pub fn meter(bytes: &[u8]) -> Result<u64, String> {
    let input = bytes.as_ptr() as *const std::os::raw::c_char;
    let input_len = bytes.len() as u32;
    let mut gas = 0u64;

    let success = unsafe { self::api::meter_gas(
        input, 
        input_len, 
        &mut gas as *mut u64
    ) };
    if success == 0 {
        return Err("Failed to meter gas".to_string());
    }

    Ok(gas)
}