use std::ptr;
use std::ffi::CString;
use logic::utils::{parse_error_code, parse_multi_cstring};
use logic::reader::Reader;
use parameters::context_scope::ContextScope;
use errors::*;
use pcsc_sys::*;
#[derive(Debug)]
pub struct Context {
handle: SCARDCONTEXT
}
impl Context {
pub fn establish_context(scope: ContextScope) -> Result<Context> {
let mut h_context: SCARDCONTEXT = SCARDCONTEXT::default();
try!( parse_error_code( unsafe { SCardEstablishContext(scope.to_value(), ptr::null(), ptr::null(), &mut h_context) }));
debug!("Context created with scope {:?}.", scope);
Ok(Context { handle: h_context })
}
pub fn establish_context_auto() -> Result<Context> {
Context::establish_context(ContextScope::Auto)
}
pub fn get_handle(&self) -> SCARDCONTEXT {
self.handle
}
pub fn is_valid(&self) -> Result<bool> {
let r_code = unsafe { SCardIsValidContext(self.handle) };
match r_code {
SCARD_E_INVALID_HANDLE => Ok(false),
rc => parse_error_code(rc).and(Ok(true))
}
}
pub fn list_readers(&self) -> Result<Vec<Reader>> {
let readers_names = unsafe {
let mut buf_size = 0u64;
try!(
parse_error_code(
SCardListReaders(self.handle, ptr::null(), ptr::null_mut(), &mut buf_size)));
let empty_buf = vec![0u8;buf_size as usize];
let mut readers_ptr = CString::from_vec_unchecked(empty_buf);
let str_ptr = readers_ptr.into_raw();
try!(
parse_error_code(
SCardListReaders(self.handle, ptr::null(), str_ptr, &mut buf_size)));
readers_ptr = CString::from_raw(str_ptr);
parse_multi_cstring(readers_ptr, buf_size)
};
let readers: Vec<Reader> = readers_names.into_iter().map(|name|Reader::new(name.to_string())).collect();
info!("Available readers:");
for r in readers.iter() {
info!("- {}", r.get_name());
}
Ok(readers)
}
}
impl Drop for Context {
fn drop(&mut self) {
unsafe { SCardReleaseContext(self.handle) };
}
}
#[test]
fn test_context_creation() {
let context = Context::establish_context_auto();
assert!(context.is_ok());
assert!(context.unwrap().is_valid().unwrap());
}
#[test]
fn test_list_readers() {
let context = Context::establish_context_auto().unwrap();
let _ = context.list_readers().unwrap();
}