#![allow(clippy::not_unsafe_ptr_arg_deref, clippy::too_many_arguments)]
#[cfg(any(
simics_version = "6.0.163",
simics_version = "6.0.164",
simics_version = "6.0.165",
simics_version = "6.0.166",
simics_version = "6.0.167",
simics_version = "6.0.168",
simics_version = "6.0.169",
simics_version = "6.0.170",
simics_version = "6.0.171",
simics_version = "6.0.172",
simics_version = "6.0.173",
simics_version = "6.0.174",
simics_version = "6.0.175",
simics_version = "6.0.176",
simics_version = "6.0.177",
simics_version = "6.0.178",
simics_version = "6.0.179",
simics_version = "6.0.180",
simics_version = "6.0.181",
simics_version = "6.0.182",
simics_version = "6.0.183",
simics_version = "6.0.184",
simics_version = "6.0.185",
simics_version = "6.0.186",
simics_version = "6.0.187",
simics_version = "6.0.188",
simics_version = "6.0.189",
simics_version = "6.0.190",
simics_version = "6.0.191",
simics_version = "6.0.192",
simics_version = "6.0.193",
simics_version = "6.0.194",
simics_version = "7.0.0",
simics_version = "7.1.0",
simics_version = "7.2.0",
simics_version = "7.3.0",
simics_version = "7.4.0",
simics_version = "7.5.0",
simics_version = "7.6.0",
simics_version = "7.7.0",
simics_version = "7.8.0",
simics_version = "7.9.0",
))]
use crate::sys::{SIM_object_iterator, SIM_shallow_object_iterator};
#[cfg(not(any(
simics_version = "6.0.163",
simics_version = "6.0.164",
simics_version = "6.0.165",
simics_version = "6.0.166",
simics_version = "6.0.167",
simics_version = "6.0.168",
simics_version = "6.0.169",
simics_version = "6.0.170",
simics_version = "6.0.171",
simics_version = "6.0.172",
simics_version = "6.0.173",
simics_version = "6.0.174",
simics_version = "6.0.175",
simics_version = "6.0.176",
simics_version = "6.0.177",
simics_version = "6.0.178",
simics_version = "6.0.179",
simics_version = "6.0.180",
simics_version = "6.0.181",
simics_version = "6.0.182",
simics_version = "6.0.183",
simics_version = "6.0.184",
simics_version = "6.0.185",
simics_version = "6.0.186",
simics_version = "6.0.187",
simics_version = "6.0.188",
simics_version = "6.0.189",
simics_version = "6.0.190",
simics_version = "6.0.191",
simics_version = "6.0.192",
simics_version = "6.0.193",
simics_version = "6.0.194",
simics_version = "7.0.0",
simics_version = "7.1.0",
simics_version = "7.2.0",
simics_version = "7.3.0",
simics_version = "7.4.0",
simics_version = "7.5.0",
simics_version = "7.6.0",
simics_version = "7.7.0",
simics_version = "7.8.0",
simics_version = "7.9.0",
)))]
use crate::sys::{VT_object_iterator, VT_shallow_object_iterator};
use crate::{
last_error, simics_exception,
sys::{
attr_attr_t, attr_value_t, class_data_t, class_info_t, class_kind_t, conf_class_t,
conf_object_t, get_attr_t, get_class_attr_t, object_iter_t, set_attr_t, set_class_attr_t,
set_error_t, SIM_attribute_error, SIM_copy_class, SIM_create_class, SIM_extend_class,
SIM_extension_data, SIM_get_class_data, SIM_get_class_interface, SIM_get_class_name,
SIM_get_interface, SIM_marked_for_deletion, SIM_object_data, SIM_object_descendant,
SIM_object_id, SIM_object_is_configured, SIM_object_iterator_next, SIM_object_name,
SIM_object_parent, SIM_register_attribute_with_user_data, SIM_register_class_alias,
SIM_register_class_attribute_with_user_data, SIM_register_interface,
SIM_register_typed_attribute, SIM_register_typed_class_attribute, SIM_require_object,
SIM_set_class_data, SIM_set_object_configured,
},
AttrValue, Error, Interface, Result,
};
use raw_cstr::{raw_cstr, AsRawCstr};
use std::{
ffi::{c_void, CStr},
fmt::Display,
ops::Range,
ptr::null_mut,
};
pub type ConfObject = conf_object_t;
pub type ConfClass = conf_class_t;
pub type ClassData = class_data_t;
pub type ClassInfo = class_info_t;
pub type ClassKind = class_kind_t;
pub type AttrAttr = attr_attr_t;
pub type ObjectIter = object_iter_t;
pub type GetAttr = get_attr_t;
pub type SetAttr = set_attr_t;
pub type GetClassAttr = get_class_attr_t;
pub type SetClassAttr = set_class_attr_t;
pub type SetErr = set_error_t;
pub enum TypeStringListType {
Type(Box<TypeStringType>),
Range(Range<usize>, Box<TypeStringType>),
Exact(usize, Box<TypeStringType>),
ZeroOrMore(Box<TypeStringType>),
OneOrMore(Box<TypeStringType>),
}
impl Display for TypeStringListType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TypeStringListType::Type(t) => write!(f, "{}", t),
TypeStringListType::Range(r, t) => {
write!(f, "{}{{{}:{}}}", t, r.start, r.end)
}
TypeStringListType::Exact(c, t) => write!(f, "{}{{{}}}", t, c),
TypeStringListType::ZeroOrMore(t) => write!(f, "{}*", t),
TypeStringListType::OneOrMore(t) => write!(f, "{}+", t),
}
}
}
pub enum TypeStringType {
Integer,
Float,
String,
Boolean,
Object,
Data,
Nil,
Dictionary,
Any,
List(Vec<TypeStringListType>),
Or(Box<TypeStringType>, Box<TypeStringType>),
}
impl Display for TypeStringType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
TypeStringType::Integer => write!(f, "i"),
TypeStringType::Float => write!(f, "f"),
TypeStringType::String => write!(f, "s"),
TypeStringType::Boolean => write!(f, "b"),
TypeStringType::Object => write!(f, "o"),
TypeStringType::Data => write!(f, "d"),
TypeStringType::Nil => write!(f, "n"),
TypeStringType::Dictionary => write!(f, "D"),
TypeStringType::Any => write!(f, "a"),
TypeStringType::List(l) => write!(
f,
"[{}]",
l.iter().map(|li| li.to_string()).collect::<String>()
),
TypeStringType::Or(l, r) => write!(f, "{}|{}", l, r),
}
}
}
#[simics_exception]
pub fn register_class_alias<S>(alias: S, name: S) -> Result<()>
where
S: AsRef<str>,
{
unsafe { SIM_register_class_alias(raw_cstr(alias)?, raw_cstr(name)?) };
Ok(())
}
#[simics_exception]
pub fn create_class<S>(name: S, class_info: ClassInfo) -> Result<*mut ConfClass>
where
S: AsRef<str>,
{
let name_raw = raw_cstr(name.as_ref())?;
let cls = unsafe { SIM_create_class(name_raw, &class_info as *const ClassInfo) };
if cls.is_null() {
Err(Error::CreateClass {
name: name.as_ref().to_string(),
message: last_error(),
})
} else {
Ok(cls)
}
}
#[simics_exception]
pub fn extend_class(cls: *mut ConfClass, ext: *mut ConfClass) {
unsafe { SIM_extend_class(cls, ext) };
}
#[simics_exception]
pub fn copy_class<S>(name: S, src_cls: *mut ConfClass, desc: S) -> Result<*mut ConfClass>
where
S: AsRef<str>,
{
Ok(unsafe { SIM_copy_class(raw_cstr(name)?, src_cls, raw_cstr(desc)?) })
}
#[simics_exception]
pub fn get_class_name(cls: *mut ConfClass) -> Result<String> {
Ok(unsafe { CStr::from_ptr(SIM_get_class_name(cls)) }
.to_str()
.map(|s| s.to_string())?)
}
#[simics_exception]
pub fn set_class_data<T>(cls: *mut ConfClass, data: T) {
unsafe { SIM_set_class_data(cls, Box::into_raw(Box::new(data)) as *mut c_void) }
}
#[simics_exception]
pub fn get_class_data<'a, T>(cls: *mut ConfClass) -> &'a mut T {
unsafe { Box::leak(Box::from_raw(SIM_get_class_data(cls) as *mut T)) }
}
#[simics_exception]
pub fn require_object(obj: *mut ConfObject) {
unsafe { SIM_require_object(obj) };
}
#[simics_exception]
pub fn object_name(obj: *mut ConfObject) -> Result<String> {
Ok(unsafe { CStr::from_ptr(SIM_object_name(obj)) }
.to_str()
.map(|s| s.to_string())?)
}
#[simics_exception]
pub fn object_id(obj: *mut ConfObject) -> Result<String> {
Ok(unsafe { CStr::from_ptr(SIM_object_id(obj)) }
.to_str()
.map(|s| s.to_string())?)
}
#[simics_exception]
pub fn object_is_configured(obj: *mut ConfObject) -> bool {
unsafe { SIM_object_is_configured(obj) }
}
#[simics_exception]
pub fn set_object_configured(obj: *mut ConfObject) {
unsafe { SIM_set_object_configured(obj) }
}
#[simics_exception]
pub fn object_data<'a, T>(obj: *mut ConfObject) -> &'a mut T {
unsafe { Box::leak(Box::from_raw(SIM_object_data(obj) as *mut T)) }
}
#[simics_exception]
pub fn extension_data<'a, T>(obj: *mut ConfObject, cls: *mut ConfClass) -> &'a mut T {
unsafe { Box::leak(Box::from_raw(SIM_extension_data(obj, cls) as *mut T)) }
}
#[simics_exception]
pub fn object_parent(obj: *mut ConfObject) -> Option<*mut ConfObject> {
let ptr = unsafe { SIM_object_parent(obj) };
if ptr.is_null() {
None
} else {
Some(ptr)
}
}
#[simics_exception]
pub fn object_descendant<S>(obj: *mut ConfObject, relname: S) -> Result<Option<*mut ConfObject>>
where
S: AsRef<str>,
{
let ptr = unsafe { SIM_object_descendant(obj, raw_cstr(relname)?) };
if ptr.is_null() {
Ok(None)
} else {
Ok(Some(ptr))
}
}
#[cfg(any(
simics_version = "6.0.163",
simics_version = "6.0.164",
simics_version = "6.0.165",
simics_version = "6.0.166",
simics_version = "6.0.167",
simics_version = "6.0.168",
simics_version = "6.0.169",
simics_version = "6.0.170",
simics_version = "6.0.171",
simics_version = "6.0.172",
simics_version = "6.0.173",
simics_version = "6.0.174",
simics_version = "6.0.175",
simics_version = "6.0.176",
simics_version = "6.0.177",
simics_version = "6.0.178",
simics_version = "6.0.179",
simics_version = "6.0.180",
simics_version = "6.0.181",
simics_version = "6.0.182",
simics_version = "6.0.183",
simics_version = "6.0.184",
simics_version = "6.0.185",
simics_version = "6.0.186",
simics_version = "6.0.187",
simics_version = "6.0.188",
simics_version = "6.0.189",
simics_version = "6.0.190",
simics_version = "6.0.191",
simics_version = "6.0.192",
simics_version = "6.0.193",
simics_version = "6.0.194",
simics_version = "7.0.0",
simics_version = "7.1.0",
simics_version = "7.2.0",
simics_version = "7.3.0",
simics_version = "7.4.0",
simics_version = "7.5.0",
simics_version = "7.6.0",
simics_version = "7.7.0",
simics_version = "7.8.0",
simics_version = "7.9.0",
))]
#[simics_exception]
pub fn object_iterator(obj: *mut ConfObject) -> ObjectIter {
unsafe { SIM_object_iterator(obj) }
}
#[cfg(any(
simics_version = "6.0.163",
simics_version = "6.0.164",
simics_version = "6.0.165",
simics_version = "6.0.166",
simics_version = "6.0.167",
simics_version = "6.0.168",
simics_version = "6.0.169",
simics_version = "6.0.170",
simics_version = "6.0.171",
simics_version = "6.0.172",
simics_version = "6.0.173",
simics_version = "6.0.174",
simics_version = "6.0.175",
simics_version = "6.0.176",
simics_version = "6.0.177",
simics_version = "6.0.178",
simics_version = "6.0.179",
simics_version = "6.0.180",
simics_version = "6.0.181",
simics_version = "6.0.182",
simics_version = "6.0.183",
simics_version = "6.0.184",
simics_version = "6.0.185",
simics_version = "6.0.186",
simics_version = "6.0.187",
simics_version = "6.0.188",
simics_version = "6.0.189",
simics_version = "6.0.190",
simics_version = "6.0.191",
simics_version = "6.0.192",
simics_version = "6.0.193",
simics_version = "6.0.194",
simics_version = "7.0.0",
simics_version = "7.1.0",
simics_version = "7.2.0",
simics_version = "7.3.0",
simics_version = "7.4.0",
simics_version = "7.5.0",
simics_version = "7.6.0",
simics_version = "7.7.0",
simics_version = "7.8.0",
simics_version = "7.9.0",
))]
#[simics_exception]
pub fn shallow_object_iterator(obj: *mut ConfObject) -> ObjectIter {
unsafe { SIM_shallow_object_iterator(obj) }
}
#[cfg(not(any(
simics_version = "6.0.163",
simics_version = "6.0.164",
simics_version = "6.0.165",
simics_version = "6.0.166",
simics_version = "6.0.167",
simics_version = "6.0.168",
simics_version = "6.0.169",
simics_version = "6.0.170",
simics_version = "6.0.171",
simics_version = "6.0.172",
simics_version = "6.0.173",
simics_version = "6.0.174",
simics_version = "6.0.175",
simics_version = "6.0.176",
simics_version = "6.0.177",
simics_version = "6.0.178",
simics_version = "6.0.179",
simics_version = "6.0.180",
simics_version = "6.0.181",
simics_version = "6.0.182",
simics_version = "6.0.183",
simics_version = "6.0.184",
simics_version = "6.0.185",
simics_version = "6.0.186",
simics_version = "6.0.187",
simics_version = "6.0.188",
simics_version = "6.0.189",
simics_version = "6.0.190",
simics_version = "6.0.191",
simics_version = "6.0.192",
simics_version = "6.0.193",
simics_version = "6.0.194",
simics_version = "7.0.0",
simics_version = "7.1.0",
simics_version = "7.2.0",
simics_version = "7.3.0",
simics_version = "7.4.0",
simics_version = "7.5.0",
simics_version = "7.6.0",
simics_version = "7.7.0",
simics_version = "7.8.0",
simics_version = "7.9.0",
)))]
#[simics_exception]
pub fn object_iterator(obj: *mut ConfObject) -> ObjectIter {
unsafe { VT_object_iterator(obj) }
}
#[cfg(not(any(
simics_version = "6.0.163",
simics_version = "6.0.164",
simics_version = "6.0.165",
simics_version = "6.0.166",
simics_version = "6.0.167",
simics_version = "6.0.168",
simics_version = "6.0.169",
simics_version = "6.0.170",
simics_version = "6.0.171",
simics_version = "6.0.172",
simics_version = "6.0.173",
simics_version = "6.0.174",
simics_version = "6.0.175",
simics_version = "6.0.176",
simics_version = "6.0.177",
simics_version = "6.0.178",
simics_version = "6.0.179",
simics_version = "6.0.180",
simics_version = "6.0.181",
simics_version = "6.0.182",
simics_version = "6.0.183",
simics_version = "6.0.184",
simics_version = "6.0.185",
simics_version = "6.0.186",
simics_version = "6.0.187",
simics_version = "6.0.188",
simics_version = "6.0.189",
simics_version = "6.0.190",
simics_version = "6.0.191",
simics_version = "6.0.192",
simics_version = "6.0.193",
simics_version = "6.0.194",
simics_version = "7.0.0",
simics_version = "7.1.0",
simics_version = "7.2.0",
simics_version = "7.3.0",
simics_version = "7.4.0",
simics_version = "7.5.0",
simics_version = "7.6.0",
simics_version = "7.7.0",
simics_version = "7.8.0",
simics_version = "7.9.0",
)))]
#[simics_exception]
pub fn shallow_object_iterator(obj: *mut ConfObject) -> ObjectIter {
unsafe { VT_shallow_object_iterator(obj) }
}
#[simics_exception]
pub fn object_iterator_next(iter: *mut ObjectIter) -> Option<*mut ConfObject> {
let obj = unsafe { SIM_object_iterator_next(iter) };
if obj.is_null() {
None
} else {
Some(obj)
}
}
extern "C" fn get_typed_attr_handler<F>(
cb: *mut c_void,
obj: *mut ConfObject,
idx: *mut attr_value_t,
) -> attr_value_t
where
F: FnMut(*mut ConfObject, AttrValue) -> Result<AttrValue> + 'static,
{
let closure = Box::leak(unsafe { Box::from_raw(cb as *mut Box<F>) });
let idx = unsafe { AttrValue::from_raw(idx) };
closure(obj, idx)
.expect("Error calling get_typed_attr_handler callback")
.into_raw()
}
extern "C" fn set_typed_attr_handler<F>(
cb: *mut c_void,
obj: *mut ConfObject,
val: *mut attr_value_t,
idx: *mut attr_value_t,
) -> SetErr
where
F: FnMut(*mut ConfObject, AttrValue, AttrValue) -> Result<SetErr> + 'static,
{
let closure = Box::leak(unsafe { Box::from_raw(cb as *mut Box<F>) });
let val = unsafe { AttrValue::from_raw(val) };
let idx = unsafe { AttrValue::from_raw(idx) };
closure(obj, val, idx).expect("Error calling set_typed_attr_handler callback")
}
extern "C" fn get_typed_class_attr_handler<F>(
cb: *mut c_void,
cls: *mut ConfClass,
idx: *mut attr_value_t,
) -> attr_value_t
where
F: FnMut(*mut ConfClass, AttrValue) -> Result<AttrValue> + 'static,
{
let closure = Box::leak(unsafe { Box::from_raw(cb as *mut Box<F>) });
let idx = unsafe { AttrValue::from_raw(idx) };
closure(cls, idx)
.expect("Error calling get_typed_class_attr_handler callback")
.into_raw()
}
extern "C" fn set_typed_class_attr_handler<F>(
cb: *mut c_void,
cls: *mut ConfClass,
val: *mut attr_value_t,
idx: *mut attr_value_t,
) -> SetErr
where
F: FnMut(*mut ConfClass, AttrValue, AttrValue) -> Result<SetErr> + 'static,
{
let closure = Box::leak(unsafe { Box::from_raw(cb as *mut Box<F>) });
let val = unsafe { AttrValue::from_raw(val) };
let idx = unsafe { AttrValue::from_raw(idx) };
closure(cls, val, idx).expect("Error calling set_typed_class_attr_handler callback")
}
extern "C" fn get_attr_handler<F>(obj: *mut ConfObject, cb: *mut c_void) -> attr_value_t
where
F: FnMut(*mut ConfObject) -> Result<AttrValue> + 'static,
{
let closure = Box::leak(unsafe { Box::from_raw(cb as *mut Box<F>) });
closure(obj)
.expect("Error calling get_attr_handler callback")
.into_raw()
}
extern "C" fn set_attr_handler<F>(
obj: *mut ConfObject,
val: *mut attr_value_t,
cb: *mut c_void,
) -> SetErr
where
F: FnMut(*mut ConfObject, AttrValue) -> Result<SetErr> + 'static,
{
let closure = Box::leak(unsafe { Box::from_raw(cb as *mut Box<F>) });
let val = unsafe { AttrValue::from_raw(val) };
closure(obj, val).expect("Error calling set_attr_handler callback")
}
extern "C" fn get_class_attr_handler<F>(cls: *mut ConfClass, cb: *mut c_void) -> attr_value_t
where
F: FnMut(*mut ConfClass) -> Result<AttrValue> + 'static,
{
let closure = Box::leak(unsafe { Box::from_raw(cb as *mut Box<F>) });
closure(cls)
.expect("Error calling get_class_attr_handler callback")
.into_raw()
}
extern "C" fn set_class_attr_handler<F>(
cls: *mut ConfClass,
val: *mut attr_value_t,
cb: *mut c_void,
) -> SetErr
where
F: FnMut(*mut ConfClass, AttrValue) -> Result<SetErr> + 'static,
{
let closure = Box::leak(unsafe { Box::from_raw(cb as *mut Box<F>) });
let val = unsafe { AttrValue::from_raw(val) };
closure(cls, val).expect("Error calling set_class_attr_handler callback")
}
#[simics_exception]
pub fn register_typed_attribute<S, GF, SF>(
cls: *mut ConfClass,
name: S,
getter: Option<GF>,
setter: Option<SF>,
attr: AttrAttr,
attr_type: Option<TypeStringType>,
idx_type: Option<TypeStringType>,
desc: S,
) -> Result<()>
where
S: AsRef<str>,
GF: FnMut(*mut ConfObject, AttrValue) -> Result<AttrValue> + 'static,
SF: FnMut(*mut ConfObject, AttrValue, AttrValue) -> Result<SetErr> + 'static,
{
let attr_type = if let Some(attr_type) = attr_type {
raw_cstr(attr_type.to_string())?
} else {
null_mut()
};
let idx_type = if let Some(idx_type) = idx_type {
raw_cstr(idx_type.to_string())?
} else {
null_mut()
};
let (get_attr, getter_cb_raw) = if let Some(getter) = getter {
let getter_cb = Box::new(getter);
let getter_cb_box = Box::new(getter_cb);
(
Some(get_typed_attr_handler::<GF> as _),
Box::into_raw(getter_cb_box),
)
} else {
(None, null_mut())
};
let (set_attr, setter_cb_raw) = if let Some(setter) = setter {
let setter_cb = Box::new(setter);
let setter_cb_box = Box::new(setter_cb);
(
Some(set_typed_attr_handler::<SF> as _),
Box::into_raw(setter_cb_box),
)
} else {
(None, null_mut())
};
unsafe {
SIM_register_typed_attribute(
cls,
raw_cstr(name)?,
get_attr,
getter_cb_raw as *mut c_void,
set_attr,
setter_cb_raw as *mut c_void,
attr,
attr_type,
idx_type,
raw_cstr(desc)?,
)
};
Ok(())
}
#[simics_exception]
pub fn register_typed_class_attribute<S, GF, SF>(
cls: *mut ConfClass,
name: S,
getter: Option<GF>,
setter: Option<SF>,
attr: AttrAttr,
attr_type: Option<TypeStringType>,
idx_type: Option<TypeStringType>,
desc: S,
) -> Result<()>
where
S: AsRef<str>,
GF: FnMut(*mut ConfClass, AttrValue) -> Result<AttrValue> + 'static,
SF: FnMut(*mut ConfClass, AttrValue, AttrValue) -> Result<SetErr> + 'static,
{
let attr_type = if let Some(attr_type) = attr_type {
raw_cstr(attr_type.to_string())?
} else {
null_mut()
};
let idx_type = if let Some(idx_type) = idx_type {
raw_cstr(idx_type.to_string())?
} else {
null_mut()
};
let (get_attr, getter_cb_raw) = if let Some(getter) = getter {
let getter_cb = Box::new(getter);
let getter_cb_box = Box::new(getter_cb);
(
Some(get_typed_class_attr_handler::<GF> as _),
Box::into_raw(getter_cb_box),
)
} else {
(None, null_mut())
};
let (set_attr, setter_cb_raw) = if let Some(setter) = setter {
let setter_cb = Box::new(setter);
let setter_cb_box = Box::new(setter_cb);
(
Some(set_typed_class_attr_handler::<SF> as _),
Box::into_raw(setter_cb_box),
)
} else {
(None, null_mut())
};
unsafe {
SIM_register_typed_class_attribute(
cls,
raw_cstr(name)?,
get_attr,
getter_cb_raw as *mut c_void,
set_attr,
setter_cb_raw as *mut c_void,
attr,
attr_type,
idx_type,
raw_cstr(desc)?,
)
};
Ok(())
}
#[simics_exception]
pub fn register_attribute<S, GF, SF>(
cls: *mut ConfClass,
name: S,
getter: Option<GF>,
setter: Option<SF>,
attr: AttrAttr,
attr_type: Option<TypeStringType>,
desc: S,
) -> Result<()>
where
S: AsRef<str>,
GF: FnMut(*mut ConfObject) -> Result<AttrValue> + 'static,
SF: FnMut(*mut ConfObject, AttrValue) -> Result<SetErr> + 'static,
{
let attr_type = if let Some(attr_type) = attr_type {
raw_cstr(attr_type.to_string())?
} else {
null_mut()
};
let (get_attr, getter_cb_raw) = if let Some(getter) = getter {
let getter_cb = Box::new(getter);
let getter_cb_box = Box::new(getter_cb);
(
Some(get_attr_handler::<GF> as _),
Box::into_raw(getter_cb_box),
)
} else {
(None, null_mut())
};
let (set_attr, setter_cb_raw) = if let Some(setter) = setter {
let setter_cb = Box::new(setter);
let setter_cb_box = Box::new(setter_cb);
(
Some(set_attr_handler::<SF> as _),
Box::into_raw(setter_cb_box),
)
} else {
(None, null_mut())
};
unsafe {
SIM_register_attribute_with_user_data(
cls,
raw_cstr(name)?,
get_attr,
getter_cb_raw as *mut c_void,
set_attr,
setter_cb_raw as *mut c_void,
attr,
attr_type,
raw_cstr(desc)?,
)
};
Ok(())
}
#[simics_exception]
pub fn register_class_attribute<S, GF, SF>(
cls: *mut ConfClass,
name: S,
getter: Option<GF>,
setter: Option<SF>,
attr: AttrAttr,
attr_type: Option<TypeStringType>,
desc: S,
) -> Result<()>
where
S: AsRef<str>,
GF: FnMut(*mut ConfClass) -> Result<AttrValue> + 'static,
SF: FnMut(*mut ConfClass, AttrValue) -> Result<SetErr> + 'static,
{
let attr_type = if let Some(attr_type) = attr_type {
raw_cstr(attr_type.to_string())?
} else {
null_mut()
};
let (get_attr, getter_cb_raw) = if let Some(getter) = getter {
let getter_cb = Box::new(getter);
let getter_cb_box = Box::new(getter_cb);
(
Some(get_class_attr_handler::<GF> as _),
Box::into_raw(getter_cb_box),
)
} else {
(None, null_mut())
};
let (set_attr, setter_cb_raw) = if let Some(setter) = setter {
let setter_cb = Box::new(setter);
let setter_cb_box = Box::new(setter_cb);
(
Some(set_class_attr_handler::<SF> as _),
Box::into_raw(setter_cb_box),
)
} else {
(None, null_mut())
};
unsafe {
SIM_register_class_attribute_with_user_data(
cls,
raw_cstr(name)?,
get_attr,
getter_cb_raw as *mut c_void,
set_attr,
setter_cb_raw as *mut c_void,
attr,
attr_type,
raw_cstr(desc)?,
)
};
Ok(())
}
#[simics_exception]
pub fn attribute_error<S>(msg: S) -> Result<()>
where
S: AsRef<str>,
{
unsafe { SIM_attribute_error(raw_cstr(msg)?) };
Ok(())
}
#[simics_exception]
pub fn register_interface<I>(cls: *mut ConfClass) -> Result<i32>
where
I: Interface,
{
let name_raw = I::NAME.as_raw_cstr()?;
let iface_box = Box::<I::InternalInterface>::default();
let iface_raw = Box::into_raw(iface_box);
debug_assert!(
std::mem::size_of_val(&iface_raw) == std::mem::size_of::<*mut std::ffi::c_void>(),
"Pointer is not convertible to *mut c_void"
);
Ok(unsafe { SIM_register_interface(cls, name_raw, iface_raw as *mut _) })
}
#[simics_exception]
pub fn get_interface<I>(obj: *mut ConfObject) -> Result<I>
where
I: Interface,
{
Ok(I::new(obj, unsafe {
SIM_get_interface(obj as *const ConfObject, I::NAME.as_raw_cstr()?)
as *mut I::InternalInterface
}))
}
#[simics_exception]
pub fn get_class_interface<I>(cls: *mut ConfClass) -> Result<*mut I::InternalInterface>
where
I: Interface,
{
Ok(unsafe {
SIM_get_class_interface(cls as *const ConfClass, I::NAME.as_raw_cstr()?)
as *mut I::InternalInterface
})
}
#[simics_exception]
pub fn marked_for_deletion(obj: *mut ConfObject) -> bool {
unsafe { SIM_marked_for_deletion(obj) }
}