use crate::error::{RayforceError, Result};
use crate::ffi::{self, RayObj};
use crate::types::RayString;
use crate::*;
pub struct Connection {
handle: RayObj,
closed: bool,
}
impl Connection {
fn new(handle: RayObj) -> Self {
Self {
handle,
closed: false,
}
}
pub fn execute(&self, query: &str) -> Result<RayObj> {
if self.closed {
return Err(RayforceError::ConnectionError("Connection is closed".into()));
}
let query_str = RayString::new(query);
unsafe {
let result = ray_write(self.handle.as_ptr(), query_str.ptr().as_ptr());
if result.is_null() {
return Err(RayforceError::IoError("Write failed".into()));
}
if (*result).type_ == TYPE_ERR as i8 {
let msg = ffi::get_error_message(result);
drop_obj(result);
return Err(RayforceError::IoError(msg));
}
Ok(RayObj::from_raw(result))
}
}
pub fn execute_obj(&self, obj: &RayObj) -> Result<RayObj> {
if self.closed {
return Err(RayforceError::ConnectionError("Connection is closed".into()));
}
unsafe {
let result = ray_write(self.handle.as_ptr(), obj.as_ptr());
if result.is_null() {
return Err(RayforceError::IoError("Write failed".into()));
}
if (*result).type_ == TYPE_ERR as i8 {
let msg = ffi::get_error_message(result);
drop_obj(result);
return Err(RayforceError::IoError(msg));
}
Ok(RayObj::from_raw(result))
}
}
pub fn close(&mut self) -> Result<()> {
if self.closed {
return Ok(());
}
unsafe {
let result = ray_hclose(self.handle.as_ptr());
if !result.is_null() && (*result).type_ == TYPE_ERR as i8 {
let msg = ffi::get_error_message(result);
drop_obj(result);
return Err(RayforceError::IoError(msg));
}
if !result.is_null() {
drop_obj(result);
}
}
self.closed = true;
Ok(())
}
pub fn is_closed(&self) -> bool {
self.closed
}
}
impl Drop for Connection {
fn drop(&mut self) {
if !self.closed {
let _ = self.close();
}
}
}
pub fn hopen(host: &str, port: u16) -> Result<Connection> {
let path = format!("{}:{}", host, port);
let path_str = RayString::new(&path);
unsafe {
let args = [path_str.ptr().as_ptr()];
let handle = ray_hopen(args.as_ptr() as *mut *mut obj_t, 1);
if handle.is_null() {
return Err(RayforceError::ConnectionError(
format!("Failed to connect to {}:{}", host, port)
));
}
if (*handle).type_ == TYPE_ERR as i8 {
let msg = ffi::get_error_message(handle);
drop_obj(handle);
return Err(RayforceError::ConnectionError(msg));
}
Ok(Connection::new(RayObj::from_raw(handle)))
}
}
pub fn hopen_timeout(host: &str, port: u16, timeout_ms: i64) -> Result<Connection> {
let path = format!("{}:{}", host, port);
let path_str = RayString::new(&path);
let timeout = RayObj::from(timeout_ms);
unsafe {
let args = [path_str.ptr().as_ptr(), timeout.as_ptr()];
let handle = ray_hopen(args.as_ptr() as *mut *mut obj_t, 2);
if handle.is_null() {
return Err(RayforceError::ConnectionError(
format!("Failed to connect to {}:{}", host, port)
));
}
if (*handle).type_ == TYPE_ERR as i8 {
let msg = ffi::get_error_message(handle);
drop_obj(handle);
return Err(RayforceError::ConnectionError(msg));
}
Ok(Connection::new(RayObj::from_raw(handle)))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
#[ignore]
fn test_connection() {
let _rf = crate::Rayforce::new().unwrap();
let conn = hopen("localhost", 5000).unwrap();
assert!(!conn.is_closed());
}
}