use std::borrow::Borrow;
use std::marker::PhantomData;
use std::cmp::Ordering;
use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::ops::Deref;
use mcrl2_sys::atermpp::ffi::{self};
#[derive(Hash, PartialEq, Eq, PartialOrd, Ord)]
pub struct SymbolRef<'a> {
symbol: *const ffi::_function_symbol,
marker: PhantomData<&'a ()>,
}
impl<'a> SymbolRef<'a> {
fn new(symbol: *const ffi::_function_symbol) -> SymbolRef<'a> {
SymbolRef {
symbol,
marker: PhantomData,
}
}
pub fn protect(&self) -> Symbol {
Symbol::new(self.symbol)
}
pub fn copy(&self) -> SymbolRef<'_> {
SymbolRef::new(self.symbol)
}
}
impl SymbolRef<'_> {
pub fn name(&self) -> &str {
unsafe { ffi::get_function_symbol_name(self.symbol) }
}
pub fn arity(&self) -> usize {
unsafe { ffi::get_function_symbol_arity(self.symbol) }
}
pub fn address(&self) -> *const ffi::_function_symbol {
self.symbol
}
}
impl fmt::Display for SymbolRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}
impl fmt::Debug for SymbolRef<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}:{} [{}]", self.name(), self.arity(), self.address() as usize,)
}
}
impl From<*const ffi::_function_symbol> for SymbolRef<'_> {
fn from(symbol: *const ffi::_function_symbol) -> Self {
SymbolRef {
symbol,
marker: PhantomData,
}
}
}
pub struct Symbol {
symbol: SymbolRef<'static>,
}
impl Symbol {
pub(crate) fn take(symbol: *const ffi::_function_symbol) -> Symbol {
Symbol {
symbol: SymbolRef::new(symbol),
}
}
pub(crate) fn new(symbol: *const ffi::_function_symbol) -> Symbol {
unsafe { ffi::protect_function_symbol(symbol) };
Symbol {
symbol: SymbolRef::new(symbol),
}
}
}
impl Drop for Symbol {
fn drop(&mut self) {
unsafe { ffi::drop_function_symbol(self.symbol.symbol) };
}
}
impl Symbol {
pub fn copy(&self) -> SymbolRef<'_> {
self.symbol.copy()
}
}
impl From<&SymbolRef<'_>> for Symbol {
fn from(value: &SymbolRef) -> Self {
value.protect()
}
}
impl Clone for Symbol {
fn clone(&self) -> Self {
self.copy().protect()
}
}
impl Deref for Symbol {
type Target = SymbolRef<'static>;
fn deref(&self) -> &Self::Target {
&self.symbol
}
}
impl fmt::Display for Symbol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}
impl fmt::Debug for Symbol {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.name())
}
}
impl Hash for Symbol {
fn hash<H: Hasher>(&self, state: &mut H) {
self.copy().hash(state)
}
}
impl PartialEq for Symbol {
fn eq(&self, other: &Self) -> bool {
self.copy().eq(&other.copy())
}
}
impl PartialOrd for Symbol {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.copy().cmp(&other.copy()))
}
}
impl Ord for Symbol {
fn cmp(&self, other: &Self) -> Ordering {
self.copy().cmp(&other.copy())
}
}
impl Borrow<SymbolRef<'static>> for Symbol {
fn borrow(&self) -> &SymbolRef<'static> {
&self.symbol
}
}
impl Eq for Symbol {}