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
use std::ffi::CStr;
use std::mem::transmute;
use std::os::raw::{c_char, c_void};
use std::slice;

use crate::string_cache::Atom;
use crate::throne::Context;
use crate::token::Token;

#[repr(C)]
pub struct CRule {
    id: i32,
}

#[no_mangle]
pub extern "C" fn throne_context_create_from_text(string_ptr: *const c_char) -> *mut Context {
    let cstr = unsafe { CStr::from_ptr(string_ptr) };
    unsafe { transmute(Box::new(Context::from_text(cstr.to_str().unwrap()))) }
}

#[no_mangle]
pub extern "C" fn throne_context_destroy(context: *mut Context) {
    let _drop: Box<Context> = unsafe { transmute(context) };
}

#[no_mangle]
pub extern "C" fn throne_update(context: *mut Context) {
    let context = unsafe { &mut *context };
    context.update(|_: &[Token]| None);
}

#[no_mangle]
pub extern "C" fn throne_context_string_to_atom(
    context: *mut Context,
    string_ptr: *const c_char,
) -> Atom {
    let context = unsafe { &mut *context };
    let cstr = unsafe { CStr::from_ptr(string_ptr) };
    context.str_to_atom(cstr.to_str().unwrap())
}

#[no_mangle]
pub extern "C" fn throne_context_find_matching_rules(
    context: *mut Context,
    side_input: extern "C" fn(p: *const Atom, p_len: usize, data: *mut c_void) -> bool,
    side_input_data: *mut c_void,
    result_ptr: *mut CRule,
    result_len: usize,
) -> usize {
    let context = unsafe { &mut *context };
    let result = unsafe { slice::from_raw_parts_mut(result_ptr, result_len) };

    let mut side_input_p = vec![];

    let rules = context.find_matching_rules(|p: &[Token]| {
        side_input_p.clear();
        side_input_p.extend(p.iter().map(|t| t.atom));

        if side_input(side_input_p.as_ptr(), side_input_p.len(), side_input_data) {
            Some(vec![])
        } else {
            None
        }
    });

    let len = rules.len().min(result_len);

    for i in 0..len {
        result[i] = CRule { id: rules[i].id };
    }

    return len;
}

#[no_mangle]
pub extern "C" fn throne_context_find_phrase5(
    context: *mut Context,
    atom_ptr1: *const Atom,
    atom_ptr2: *const Atom,
    atom_ptr3: *const Atom,
    atom_ptr4: *const Atom,
    atom_ptr5: *const Atom,
    result_ptr: *mut Atom,
    result_len: usize,
) -> usize {
    let context = unsafe { &mut *context };
    let result = unsafe { slice::from_raw_parts_mut(result_ptr, result_len) };

    let ptr_to_atom = |atom_ptr: *const Atom| unsafe { atom_ptr.as_ref() };

    if let Some(phrase) = context.find_phrase5(
        ptr_to_atom(atom_ptr1),
        ptr_to_atom(atom_ptr2),
        ptr_to_atom(atom_ptr3),
        ptr_to_atom(atom_ptr4),
        ptr_to_atom(atom_ptr5),
    ) {
        let len = phrase.len().min(result_len);

        for i in 0..len {
            result[i] = phrase[i].atom;
        }

        len
    } else {
        0
    }
}