159 lines
5.0 KiB
Rust
159 lines
5.0 KiB
Rust
mod move_money;
|
|
pub use self::move_money::*;
|
|
use std::ffi::c_char;
|
|
use std::ffi::CStr;
|
|
use std::ffi::CString;
|
|
|
|
mod overhead_allocation;
|
|
pub use self::overhead_allocation::*;
|
|
|
|
mod products;
|
|
pub use self::products::create_products;
|
|
|
|
mod shared_models;
|
|
pub use self::shared_models::*;
|
|
|
|
pub mod link;
|
|
|
|
pub mod filter;
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn move_money_from_text(
|
|
rules: *const c_char,
|
|
lines: *const c_char,
|
|
accounts: *const c_char,
|
|
cost_centres: *const c_char,
|
|
use_numeric_accounts: bool,
|
|
) -> *mut c_char {
|
|
let mut output_writer = csv::Writer::from_writer(vec![]);
|
|
let safe_rules = unwrap_c_char(rules);
|
|
let safe_lines = unwrap_c_char(lines);
|
|
let safe_accounts = unwrap_c_char(accounts);
|
|
let safe_cost_centres = unwrap_c_char(cost_centres);
|
|
move_money(
|
|
&mut csv::Reader::from_reader(safe_rules.to_bytes()),
|
|
&mut csv::Reader::from_reader(safe_lines.to_bytes()),
|
|
&mut csv::Reader::from_reader(safe_accounts.to_bytes()),
|
|
&mut csv::Reader::from_reader(safe_cost_centres.to_bytes()),
|
|
&mut output_writer,
|
|
use_numeric_accounts,
|
|
false,
|
|
)
|
|
.expect("Failed to move money");
|
|
// TODO: Replace all these unwraps with something more elegant
|
|
let inner = output_writer.into_inner().unwrap();
|
|
CString::new(String::from_utf8(inner).unwrap())
|
|
.unwrap()
|
|
.into_raw()
|
|
|
|
// Also some resources I looked at, in case things aren't going right:
|
|
// https://notes.huy.rocks/en/string-ffi-rust.html
|
|
// http://jakegoulding.com/rust-ffi-omnibus/string_return/
|
|
// https://rust-unofficial.github.io/patterns/idioms/ffi/passing-strings.html
|
|
// This looks like exactly what I'm doing too: https://mozilla.github.io/firefox-browser-architecture/experiments/2017-09-06-rust-on-ios.htmlcar
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn move_money_from_text_free(s: *mut c_char) {
|
|
unsafe {
|
|
if s.is_null() {
|
|
return;
|
|
}
|
|
CString::from_raw(s)
|
|
};
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn allocate_overheads_from_text(
|
|
lines: *const c_char,
|
|
accounts: *const c_char,
|
|
allocation_statistics: *const c_char,
|
|
areas: *const c_char,
|
|
cost_centres: *const c_char,
|
|
account_type: *const c_char,
|
|
use_numeric_accounts: bool,
|
|
) -> *mut c_char {
|
|
let lines = unwrap_c_char(lines);
|
|
let accounts = unwrap_c_char(accounts);
|
|
let allocation_statistics = unwrap_c_char(allocation_statistics);
|
|
let areas = unwrap_c_char(areas);
|
|
let cost_centres = unwrap_c_char(cost_centres);
|
|
let account_type = unwrap_c_char(account_type);
|
|
let mut output_writer = csv::Writer::from_writer(vec![]);
|
|
reciprocal_allocation(
|
|
&mut csv::Reader::from_reader(lines.to_bytes()),
|
|
&mut csv::Reader::from_reader(accounts.to_bytes()),
|
|
&mut csv::Reader::from_reader(allocation_statistics.to_bytes()),
|
|
&mut csv::Reader::from_reader(areas.to_bytes()),
|
|
&mut csv::Reader::from_reader(cost_centres.to_bytes()),
|
|
&mut output_writer,
|
|
use_numeric_accounts,
|
|
false,
|
|
true,
|
|
account_type.to_str().unwrap().to_owned(),
|
|
// This needs to be false when we return just a string, as the
|
|
// amount of data produced could easily go out of memory (9000ccs + 1000
|
|
// accounts can reach 2gb)
|
|
false,
|
|
0.1,
|
|
)
|
|
.expect("Failed to allocate overheads");
|
|
let inner = output_writer.into_inner().unwrap();
|
|
CString::new(String::from_utf8(inner).unwrap())
|
|
.unwrap()
|
|
.into_raw()
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn allocate_overheads_from_text_to_file(
|
|
lines: *const c_char,
|
|
accounts: *const c_char,
|
|
allocation_statistics: *const c_char,
|
|
areas: *const c_char,
|
|
cost_centres: *const c_char,
|
|
account_type: *const c_char,
|
|
output_path: *const c_char,
|
|
use_numeric_accounts: bool,
|
|
show_from: bool,
|
|
) {
|
|
let lines = unwrap_c_char(lines);
|
|
let accounts = unwrap_c_char(accounts);
|
|
let allocation_statistics = unwrap_c_char(allocation_statistics);
|
|
let areas = unwrap_c_char(areas);
|
|
let cost_centres = unwrap_c_char(cost_centres);
|
|
let account_type = unwrap_c_char(account_type);
|
|
let output_path = unwrap_c_char(output_path);
|
|
reciprocal_allocation(
|
|
&mut csv::Reader::from_reader(lines.to_bytes()),
|
|
&mut csv::Reader::from_reader(accounts.to_bytes()),
|
|
&mut csv::Reader::from_reader(allocation_statistics.to_bytes()),
|
|
&mut csv::Reader::from_reader(areas.to_bytes()),
|
|
&mut csv::Reader::from_reader(cost_centres.to_bytes()),
|
|
&mut csv::Writer::from_path(output_path.to_str().unwrap()).unwrap(),
|
|
use_numeric_accounts,
|
|
false,
|
|
true,
|
|
account_type.to_str().unwrap().to_owned(),
|
|
show_from,
|
|
0.1,
|
|
)
|
|
.expect("Failed to allocate overheads");
|
|
}
|
|
|
|
fn unwrap_c_char<'a>(s: *const c_char) -> &'a CStr {
|
|
unsafe {
|
|
assert!(!s.is_null());
|
|
CStr::from_ptr(s)
|
|
}
|
|
}
|
|
|
|
#[no_mangle]
|
|
pub extern "C" fn allocate_overheads_from_text_free(s: *mut c_char) {
|
|
unsafe {
|
|
if s.is_null() {
|
|
return;
|
|
}
|
|
CString::from_raw(s)
|
|
};
|
|
}
|