<commit_before>extern crate libc;

use super::{Wallet, WalletType};

use api::ErrorCode;
use errors::common::CommonError;
use errors::wallet::WalletError;
use utils::json::JsonDecodable;

use self::libc::c_char;

use std::error::Error;
use std::ffi::{CString, CStr, NulError};
use std::ptr;
use std::str::Utf8Error;

#[derive(Debug, Deserialize)]
pub struct PluggedWalletJSONValue {
    pub key: String,
    pub value: String
}

#[derive(Debug, Deserialize)]
pub struct PluggedWalletJSONValues {
    pub values: Vec<PluggedWalletJSONValue>
}

impl<'a> JsonDecodable<'a> for PluggedWalletJSONValues {}

struct PluggedWallet {
    name: String,
    pool_name: String,
    handle: i32,
    set_handler: extern fn(handle: i32,
                           key: *const c_char,
                           value: *const c_char) -> ErrorCode,
    get_handler: extern fn(handle: i32,
                           key: *const c_char,
                           value_ptr: *mut *const c_char) -> ErrorCode,
    get_not_expired_handler: extern fn(handle: i32,
                                       key: *const c_char,
                                       value_ptr: *mut *const c_char) -> ErrorCode,
    list_handler: extern fn(handle: i32,
                            key_prefix: *const c_char,
                            values_json_ptr: *mut *const c_char) -> ErrorCode,
    close_handler: extern fn(handle: i32) -> ErrorCode,
    free_handler: extern fn(handle: i32,
                            value: *const c_char) -> ErrorCode
}

impl PluggedWallet {
    fn new(name: &str,
           pool_name: &str,
           handle: i32,
           set_handler: extern fn(xhandle: i32,
                                  key: *const c_char,
                                  value: *const c_char) -> ErrorCode,
           get_handler: extern fn(xhandle: i32,
                                  key: *const c_char,
                                  value_ptr: *mut *const c_char) -> ErrorCode,
           get_not_expired_handler: extern fn(xhandle: i32,
                                              key: *const c_char,
                                              value_ptr: *mut *const c_char) -> ErrorCode,
           list_handler: extern fn(xhandle: i32,
                                   key_prefix: *const c_char,
                                   values_json_ptr: *mut *const c_char) -> ErrorCode,
           close_handler: extern fn(xhandle: i32) -> ErrorCode,
           free_handler: extern fn(xhandle: i32,
                                   value: *const c_char) -> ErrorCode) -> PluggedWallet {
        PluggedWallet {
            name: name.to_string(),
            pool_name: pool_name.to_string(),
            handle: handle,
            set_handler: set_handler,
            get_handler: get_handler,
            list_handler: list_handler,
            get_not_expired_handler: get_not_expired_handler,
            close_handler: close_handler,
            free_handler: free_handler
        }
    }
}

impl Wallet for PluggedWallet {
    fn set(&self, key: &str, value: &str) -> Result<(), WalletError> {
        let key = CString::new(key)?;
        let value = CString::new(value)?;

        let err = (self.set_handler)(self.handle,
                                     key.as_ptr(),
                                     value.as_ptr());

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }

        Ok(())
    }

    fn get(&self, key: &str) -> Result<String, WalletError> {
        let key = CString::new(key)?;
        let mut value_ptr: *const c_char = ptr::null_mut();

        let err = (self.get_handler)(self.handle,
                                     key.as_ptr(),
                                     &mut value_ptr);

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }

        let result = unsafe {
            CStr::from_ptr(value_ptr).to_str()?.to_string()
        };

        let err = (self.free_handler)(self.handle, value_ptr);

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }

        Ok(result)
    }

    fn list(&self, key_prefix: &str) -> Result<Vec<(String, String)>, WalletError> {
        let key_prefix = CString::new(key_prefix)?;
        let mut values_json_ptr: *const c_char = ptr::null_mut();

        let err = (self.list_handler)(self.handle,
                                      key_prefix.as_ptr(),
                                      &mut values_json_ptr);

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }

        let values_json = unsafe {
            CStr::from_ptr(values_json_ptr).to_str()?.to_string()
        };

        let err = (self.free_handler)(self.handle, values_json_ptr);

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }

        let result = PluggedWalletJSONValues::from_json(values_json.as_str()).map_err(map_err_trace!())?
            .values
            .iter()
            .map(|value| (value.key.clone(), value.value.clone()))
            .collect();

        Ok(result)
    }

    fn get_not_expired(&self, key: &str) -> Result<String, WalletError> {
        let key = CString::new(key)?;
        let mut value_ptr: *const c_char = ptr::null_mut();<commit_msg>fixing extra print<commit_after>extern crate libc;

use super::{Wallet, WalletType};

use api::ErrorCode;
use errors::common::CommonError;
use errors::wallet::WalletError;
use utils::json::JsonDecodable;

use self::libc::c_char;

use std::error::Error;
use std::ffi::{CString, CStr, NulError};
use std::ptr;
use std::str::Utf8Error;

#[derive(Debug, Deserialize)]
pub struct PluggedWalletJSONValue {
    pub key: String,
    pub value: String
}

#[derive(Debug, Deserialize)]
pub struct PluggedWalletJSONValues {
    pub values: Vec<PluggedWalletJSONValue>
}

impl<'a> JsonDecodable<'a> for PluggedWalletJSONValues {}

struct PluggedWallet {
    name: String,
    pool_name: String,
    handle: i32,
    set_handler: extern fn(handle: i32,
                           key: *const c_char,
                           value: *const c_char) -> ErrorCode,
    get_handler: extern fn(handle: i32,
                           key: *const c_char,
                           value_ptr: *mut *const c_char) -> ErrorCode,
    get_not_expired_handler: extern fn(handle: i32,
                                       key: *const c_char,
                                       value_ptr: *mut *const c_char) -> ErrorCode,
    list_handler: extern fn(handle: i32,
                            key_prefix: *const c_char,
                            values_json_ptr: *mut *const c_char) -> ErrorCode,
    close_handler: extern fn(handle: i32) -> ErrorCode,
    free_handler: extern fn(handle: i32,
                            value: *const c_char) -> ErrorCode
}

impl PluggedWallet {
    fn new(name: &str,
           pool_name: &str,
           handle: i32,
           set_handler: extern fn(xhandle: i32,
                                  key: *const c_char,
                                  value: *const c_char) -> ErrorCode,
           get_handler: extern fn(xhandle: i32,
                                  key: *const c_char,
                                  value_ptr: *mut *const c_char) -> ErrorCode,
           get_not_expired_handler: extern fn(xhandle: i32,
                                              key: *const c_char,
                                              value_ptr: *mut *const c_char) -> ErrorCode,
           list_handler: extern fn(xhandle: i32,
                                   key_prefix: *const c_char,
                                   values_json_ptr: *mut *const c_char) -> ErrorCode,
           close_handler: extern fn(xhandle: i32) -> ErrorCode,
           free_handler: extern fn(xhandle: i32,
                                   value: *const c_char) -> ErrorCode) -> PluggedWallet {
        PluggedWallet {
            name: name.to_string(),
            pool_name: pool_name.to_string(),
            handle: handle,
            set_handler: set_handler,
            get_handler: get_handler,
            list_handler: list_handler,
            get_not_expired_handler: get_not_expired_handler,
            close_handler: close_handler,
            free_handler: free_handler
        }
    }
}

impl Wallet for PluggedWallet {
    fn set(&self, key: &str, value: &str) -> Result<(), WalletError> {
        let key = CString::new(key)?;
        let value = CString::new(value)?;

        let err = (self.set_handler)(self.handle,
                                     key.as_ptr(),
                                     value.as_ptr());

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }

        Ok(())
    }

    fn get(&self, key: &str) -> Result<String, WalletError> {
        let key = CString::new(key)?;
        let mut value_ptr: *const c_char = ptr::null_mut();

        let err = (self.get_handler)(self.handle,
                                     key.as_ptr(),
                                     &mut value_ptr);

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }

        let result = unsafe {
            CStr::from_ptr(value_ptr).to_str()?.to_string()
        };

        let err = (self.free_handler)(self.handle, value_ptr);

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }

        Ok(result)
    }

    fn list(&self, key_prefix: &str) -> Result<Vec<(String, String)>, WalletError> {
        let key_prefix = CString::new(key_prefix)?;
        let mut values_json_ptr: *const c_char = ptr::null_mut();

        let err = (self.list_handler)(self.handle,
                                      key_prefix.as_ptr(),
                                      &mut values_json_ptr);

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }

        let values_json = unsafe {
            CStr::from_ptr(values_json_ptr).to_str()?.to_string()
        };

        let err = (self.free_handler)(self.handle, values_json_ptr);

        if err != ErrorCode::Success {
            return Err(WalletError::PluggedWallerError(err));
        }
        
        let result = PluggedWalletJSONValues::from_json(values_json.as_str()).map_err(map_err_trace!())?
            .values
            .iter()
            .map(|value| (value.key.clone(), value.value.clone()))
            .collect();

        Ok(result)
    }

    fn get_not_expired(&self, key: &str) -> Result<String, WalletError> {
        let key = CString::new(key)?;
        let mut value_ptr: *const c_char = ptr::null_mut();
{'fraction_non_alphanumeric': 0.11036635754292536, 'fraction_numerical': 0.005325498117711872, 'mean_word_length': 1.7277736038066616, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 44, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2350540', 'n_tokens_mistral': 3209, 'n_tokens_neox': 3143, 'n_words': 681}