Sync step3

This commit is contained in:
folex 2019-08-15 15:19:57 +03:00
parent 391e9b1d34
commit b54b030698

View File

@ -4,27 +4,35 @@ use crate::api::AppResult;
use crate::errors::err_msg; use crate::errors::err_msg;
use crate::ffi; use crate::ffi;
// Execute query on SQLite
pub fn query(query: String) -> AppResult<String> { pub fn query(query: String) -> AppResult<String> {
log::debug!("executing query: '{}'", query); log::debug!("executing query: '{}'", query);
unsafe { unsafe {
let bytes = query.as_bytes(); // Convert query string to bytes
let query_ptr = ffi::allocate(bytes.len()); let query_bytes = query.as_bytes();
// Allocate memory for query in SQLite module
let query_ptr = ffi::allocate(query_bytes.len());
for (i, byte) in bytes.iter().enumerate() { // Store query in SQLite's memory
for (i, byte) in query_bytes.iter().enumerate() {
let ptr = query_ptr + i as i32; let ptr = query_ptr + i as i32;
ffi::store(ptr, *byte); ffi::store(ptr, *byte);
} }
let result_ptr = ffi::invoke(query_ptr, bytes.len()); // Execute the query, and get pointer to the result
let result_ptr = ffi::invoke(query_ptr, query_bytes.len());
// First 4 bytes at result_ptr location encode result size, read that first
let mut result_size: usize = 0; let mut result_size: usize = 0;
for i in 0..3 { for i in 0..3 {
let ptr = result_ptr + i as i32; let ptr = result_ptr + i as i32;
let b = ffi::load(ptr) as usize; let b = ffi::load(ptr) as usize;
result_size = result_size + (b << (8 * i)); result_size = result_size + (b << (8 * i));
} }
// Now we know exact size of the query execution result
// Read query execution result byte-by-byte
let mut result_bytes = vec![0; result_size as usize]; let mut result_bytes = vec![0; result_size as usize];
for i in 4..(result_size + 4) { for i in 4..(result_size + 4) {
let ptr = result_ptr + i as i32; let ptr = result_ptr + i as i32;
@ -32,11 +40,17 @@ pub fn query(query: String) -> AppResult<String> {
result_bytes[i as usize - 4] = b; result_bytes[i as usize - 4] = b;
} }
// Deallocate query result
ffi::deallocate(result_ptr, result_size + 4);
// Decode query result to a utf8 string
let result_str = std::str::from_utf8(result_bytes.as_slice()); let result_str = std::str::from_utf8(result_bytes.as_slice());
// Log if there's an error
if result_str.is_err() { if result_str.is_err() {
log::error!("unable to decode result from bytes: {:#x?}", result_bytes); log::error!("unable to decode result from bytes: {:#x?}", result_bytes);
} }
// Wrap error with a better message, and return Result
result_str result_str
.map_err(|e| { .map_err(|e| {
err_msg(&format!( err_msg(&format!(