use super::*;
use std::fmt;
use std::rc::Rc;
pub fn receive_str<'a>(s: *const c_char) -> Result<&'a str> {
if s.is_null() {
inv_arg("unexpected NULL string")
} else {
Ok(unsafe { CStr::from_ptr(s) }.to_str()?)
}
}
pub fn receive_optional_str<'a>(s: *const c_char) -> Result<Option<&'a str>> {
if s.is_null() {
Ok(None)
} else {
Ok(Some(unsafe { CStr::from_ptr(s) }.to_str()?))
}
}
pub fn receive_raw<'a>(obj: *const c_void, obj_size: usize) -> Result<&'a [u8]> {
if obj_size == 0 {
Ok(&[])
} else if obj.is_null() {
inv_arg("unexpected NULL data")
} else {
Ok(unsafe { std::slice::from_raw_parts(obj as *const u8, obj_size) })
}
}
pub fn return_raw(obj_in: &[u8], obj_out: *mut c_void, obj_size: usize) -> Result<ssize_t> {
if obj_size > 0 && obj_out.is_null() {
inv_arg("unexpected NULL buffer")
} else {
let actual_size = obj_in.len();
let copy_size = std::cmp::min(actual_size, obj_size);
if copy_size > 0 {
unsafe {
memcpy(obj_out, obj_in.as_ptr() as *const c_void, copy_size);
}
}
Ok(actual_size as ssize_t)
}
}
pub fn receive_index(len: size_t, index: ssize_t, insert: bool) -> Result<size_t> {
let converted_index = if index < 0 {
if insert {
index + (len as ssize_t) + 1
} else {
index + (len as ssize_t)
}
} else {
index
};
let mut ok = true;
if converted_index < 0 || converted_index as size_t > len {
ok = false;
} else if converted_index as size_t == len {
ok = insert;
}
if ok {
Ok(converted_index as size_t)
} else {
inv_arg(format!("index out of range: {}", index))
}
}
#[derive(Debug)]
pub struct UserData {
user_free: Option<extern "C" fn(*mut c_void)>,
data: *mut c_void,
}
unsafe impl Send for UserData {}
impl Drop for UserData {
fn drop(&mut self) {
if let Some(user_free) = self.user_free {
user_free(self.data);
}
}
}
impl UserData {
pub fn new(user_free: Option<extern "C" fn(*mut c_void)>, data: *mut c_void) -> UserData {
UserData { user_free, data }
}
pub fn data(&self) -> *mut c_void {
self.data
}
}
#[derive(Clone, Debug)]
pub enum UserKeyData {
Owned(Rc<UserData>),
Borrowed(*const c_void),
}
impl UserKeyData {
pub fn new(key_free: Option<extern "C" fn(*mut c_void)>, key_data: *mut c_void) -> UserKeyData {
UserKeyData::Owned(Rc::new(UserData::new(key_free, key_data)))
}
pub fn new_borrowed(key_data: *const c_void) -> UserKeyData {
UserKeyData::Borrowed(key_data)
}
pub fn raw(&self) -> *const c_void {
match self {
UserKeyData::Owned(data) => data.data,
UserKeyData::Borrowed(data) => *data,
}
}
}
#[derive(Clone, Debug)]
pub struct UserKey {
data: UserKeyData,
cmp: Option<extern "C" fn(*const c_void, *const c_void) -> bool>,
hash: Option<extern "C" fn(*const c_void) -> u64>,
}
impl PartialEq for UserKey {
fn eq(&self, other: &Self) -> bool {
assert_eq!(self.cmp, other.cmp);
assert_eq!(self.hash, other.hash);
if let Some(cmp) = self.cmp {
cmp(self.data.raw(), other.data.raw())
} else {
self.data.raw() == other.data.raw()
}
}
}
impl Eq for UserKey {}
impl std::hash::Hash for UserKey {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
if let Some(hash) = self.hash {
hash(self.data.raw()).hash(state)
} else if self.cmp.is_none() {
self.data.raw().hash(state)
}
}
}
impl UserKey {
pub fn new(
data: UserKeyData,
cmp: Option<extern "C" fn(*const c_void, *const c_void) -> bool>,
hash: Option<extern "C" fn(*const c_void) -> u64>,
) -> UserKey {
UserKey { data, cmp, hash }
}
pub fn raw(&self) -> *const c_void {
self.data.raw()
}
}
pub struct GateMap {
pub map: ConverterMap<'static, UserKey, Gate, (Vec<QubitRef>, ArbData)>,
pub key_cmp: Option<extern "C" fn(*const c_void, *const c_void) -> bool>,
pub key_hash: Option<extern "C" fn(*const c_void) -> u64>,
}
impl GateMap {
pub fn make_key(&self, key: UserKeyData) -> UserKey {
UserKey::new(key, self.key_cmp, self.key_hash)
}
}
impl fmt::Debug for GateMap {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "GateMap")
}
}