1use ffi;
7
8use std::ffi::CString;
9use std::ptr::null_mut;
10
11use error::{Error, Result};
12use model::Model;
13use parameter::Param;
14use util;
15
16pub struct Env {
18 env: *mut ffi::GRBenv,
19 require_drop: bool
20}
21
22impl Env {
23 pub fn new(logfilename: &str) -> Result<Env> {
25 let mut env = null_mut();
26 let logfilename = try!(CString::new(logfilename));
27 let error = unsafe { ffi::GRBloadenv(&mut env, logfilename.as_ptr()) };
28 if error != 0 {
29 return Err(Error::FromAPI(get_error_msg(env), error));
30 }
31 Ok(Env {
32 env: env,
33 require_drop: true
34 })
35 }
36
37 pub fn new_client(logfilename: &str, computeserver: &str, port: i32, password: &str, priority: i32, timeout: f64)
39 -> Result<Env> {
40 let mut env = null_mut();
41 let logfilename = try!(CString::new(logfilename));
42 let computeserver = try!(CString::new(computeserver));
43 let password = try!(CString::new(password));
44 let error = unsafe {
45 ffi::GRBloadclientenv(&mut env,
46 logfilename.as_ptr(),
47 computeserver.as_ptr(),
48 port,
49 password.as_ptr(),
50 priority,
51 timeout)
52 };
53 if error != 0 {
54 return Err(Error::FromAPI(get_error_msg(env), error));
55 }
56 Ok(Env {
57 env: env,
58 require_drop: true
59 })
60 }
61
62 #[deprecated]
64 pub fn new_model(&self, modelname: &str) -> Result<Model> { Model::new(modelname, self) }
65
66 #[deprecated]
68 pub fn read_model(&self, filename: &str) -> Result<Model> { Model::read_from(filename, self) }
69
70 pub fn get<P: Param>(&self, param: P) -> Result<P::Out> {
72 use util::AsRawPtr;
73 let mut value: P::Buf = util::Init::init();
74 try!(self.check_apicall(unsafe { P::get_param(self.env, param.into().as_ptr(), value.as_rawptr()) }));
75
76 Ok(util::Into::into(value))
77 }
78
79 pub fn set<P: Param>(&mut self, param: P, value: P::Out) -> Result<()> {
81 self.check_apicall(unsafe { P::set_param(self.env, param.into().as_ptr(), util::FromRaw::from(value)) })
82 }
83
84 pub fn read_params(&mut self, filename: &str) -> Result<()> {
86 let filename = try!(CString::new(filename));
87 self.check_apicall(unsafe { ffi::GRBreadparams(self.env, filename.as_ptr()) })
88 }
89
90 pub fn write_params(&self, filename: &str) -> Result<()> {
92 let filename = try!(CString::new(filename));
93 self.check_apicall(unsafe { ffi::GRBwriteparams(self.env, filename.as_ptr()) })
94 }
95
96 #[allow(temporary_cstring_as_ptr)]
100 pub fn message(&self, message: &str) { unsafe { ffi::GRBmsg(self.env, CString::new(message).unwrap().as_ptr()) }; }
101}
102
103pub trait EnvAPI {
104 fn get_ptr(&self) -> *mut ffi::GRBenv;
105 fn check_apicall(&self, error: ffi::c_int) -> Result<()>;
106}
107
108impl EnvAPI for Env {
109 fn get_ptr(&self) -> *mut ffi::GRBenv { self.env }
110
111 fn check_apicall(&self, error: ffi::c_int) -> Result<()> {
112 if error != 0 {
113 return Err(self.error_from_api(error));
114 }
115 Ok(())
116 }
117}
118
119impl Drop for Env {
120 fn drop(&mut self) {
121 if self.require_drop {
122 unsafe { ffi::GRBfreeenv(self.env) };
123 self.env = null_mut();
124 }
125 }
126}
127
128
129pub trait ErrorFromAPI {
130 fn error_from_api(&self, error: ffi::c_int) -> Error;
131}
132
133impl ErrorFromAPI for Env {
134 fn error_from_api(&self, error: ffi::c_int) -> Error { Error::FromAPI(get_error_msg(self.env), error) }
135}
136
137pub trait FromRaw {
138 fn from_raw(env: *mut ffi::GRBenv) -> Self;
139}
140
141impl FromRaw for Env {
142 fn from_raw(env: *mut ffi::GRBenv) -> Env {
143 Env {
144 env: env,
145 require_drop: false
146 }
147 }
148}
149
150
151fn get_error_msg(env: *mut ffi::GRBenv) -> String { unsafe { util::from_c_str(ffi::GRBgeterrormsg(env)) } }
152
153
154#[test]
174fn param_accesors_should_be_valid() {
175 use super::param;
176 let mut env = Env::new("").unwrap();
177 env.set(param::IISMethod, 1).unwrap();
178 let iis_method = env.get(param::IISMethod).unwrap();
179 assert_eq!(iis_method, 1);
180}