use ffi;
use std::ffi::CString;
use std::ptr::null_mut;
use error::{Error, Result};
use model::Model;
use parameter::Param;
use util;
pub struct Env {
env: *mut ffi::GRBenv,
require_drop: bool
}
impl Env {
pub fn new(logfilename: &str) -> Result<Env> {
let mut env = null_mut();
let logfilename = try!(CString::new(logfilename));
let error = unsafe { ffi::GRBloadenv(&mut env, logfilename.as_ptr()) };
if error != 0 {
return Err(Error::FromAPI(get_error_msg(env), error));
}
Ok(Env {
env: env,
require_drop: true
})
}
pub fn new_client(logfilename: &str, computeserver: &str, port: i32, password: &str, priority: i32, timeout: f64)
-> Result<Env> {
let mut env = null_mut();
let logfilename = try!(CString::new(logfilename));
let computeserver = try!(CString::new(computeserver));
let password = try!(CString::new(password));
let error = unsafe {
ffi::GRBloadclientenv(&mut env,
logfilename.as_ptr(),
computeserver.as_ptr(),
port,
password.as_ptr(),
priority,
timeout)
};
if error != 0 {
return Err(Error::FromAPI(get_error_msg(env), error));
}
Ok(Env {
env: env,
require_drop: true
})
}
#[deprecated]
pub fn new_model(&self, modelname: &str) -> Result<Model> { Model::new(modelname, self) }
#[deprecated]
pub fn read_model(&self, filename: &str) -> Result<Model> { Model::read_from(filename, self) }
pub fn get<P: Param>(&self, param: P) -> Result<P::Out> {
use util::AsRawPtr;
let mut value: P::Buf = util::Init::init();
try!(self.check_apicall(unsafe { P::get_param(self.env, param.into().as_ptr(), value.as_rawptr()) }));
Ok(util::Into::into(value))
}
pub fn set<P: Param>(&mut self, param: P, value: P::Out) -> Result<()> {
self.check_apicall(unsafe { P::set_param(self.env, param.into().as_ptr(), util::FromRaw::from(value)) })
}
pub fn read_params(&mut self, filename: &str) -> Result<()> {
let filename = try!(CString::new(filename));
self.check_apicall(unsafe { ffi::GRBreadparams(self.env, filename.as_ptr()) })
}
pub fn write_params(&self, filename: &str) -> Result<()> {
let filename = try!(CString::new(filename));
self.check_apicall(unsafe { ffi::GRBwriteparams(self.env, filename.as_ptr()) })
}
#[allow(temporary_cstring_as_ptr)]
pub fn message(&self, message: &str) { unsafe { ffi::GRBmsg(self.env, CString::new(message).unwrap().as_ptr()) }; }
}
pub trait EnvAPI {
fn get_ptr(&self) -> *mut ffi::GRBenv;
fn check_apicall(&self, error: ffi::c_int) -> Result<()>;
}
impl EnvAPI for Env {
fn get_ptr(&self) -> *mut ffi::GRBenv { self.env }
fn check_apicall(&self, error: ffi::c_int) -> Result<()> {
if error != 0 {
return Err(self.error_from_api(error));
}
Ok(())
}
}
impl Drop for Env {
fn drop(&mut self) {
if self.require_drop {
unsafe { ffi::GRBfreeenv(self.env) };
self.env = null_mut();
}
}
}
pub trait ErrorFromAPI {
fn error_from_api(&self, error: ffi::c_int) -> Error;
}
impl ErrorFromAPI for Env {
fn error_from_api(&self, error: ffi::c_int) -> Error { Error::FromAPI(get_error_msg(self.env), error) }
}
pub trait FromRaw {
fn from_raw(env: *mut ffi::GRBenv) -> Self;
}
impl FromRaw for Env {
fn from_raw(env: *mut ffi::GRBenv) -> Env {
Env {
env: env,
require_drop: false
}
}
}
fn get_error_msg(env: *mut ffi::GRBenv) -> String { unsafe { util::from_c_str(ffi::GRBgeterrormsg(env)) } }
#[test]
fn param_accesors_should_be_valid() {
use super::param;
let mut env = Env::new("").unwrap();
env.set(param::IISMethod, 1).unwrap();
let iis_method = env.get(param::IISMethod).unwrap();
assert_eq!(iis_method, 1);
}