use proc_macro2::TokenStream;
use quote::quote;
use std::str::FromStr;
pub enum HsType {
CString,
Empty,
IO(Box<HsType>),
}
impl std::fmt::Display for HsType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(
f,
"{}",
match self {
HsType::CString => "CString".to_string(),
HsType::Empty => "()".to_string(),
HsType::IO(x) => format!("IO {}", x),
}
)
}
}
impl FromStr for HsType {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.trim() {
"CString" => Ok(HsType::CString),
"()" => Ok(HsType::Empty),
"IO()" => Ok(HsType::IO(Box::new(HsType::Empty))),
x => Err(format!(
"type `{x}` isn't in the list of supported Haskell types
consider opening an issue https://github.com/yvan-sraka/hs-bindgen-traits"
)),
}
}
}
impl HsType {
pub fn quote(&self) -> TokenStream {
match self {
HsType::CString => quote! { *const std::os::raw::c_char },
HsType::Empty => quote! { () },
HsType::IO(x) => x.quote(),
}
}
}
pub trait ReprHs {
fn into() -> HsType;
}
impl ReprHs for String {
fn into() -> HsType {
HsType::CString
}
}
impl ReprHs for &str {
fn into() -> HsType {
HsType::CString
}
}
impl ReprHs for () {
fn into() -> HsType {
HsType::Empty
}
}
pub trait ReprC<T> {
fn from(_: T) -> Self;
}
impl ReprC<*const std::os::raw::c_char> for &str {
#[allow(clippy::not_unsafe_ptr_arg_deref)]
fn from(x: *const std::os::raw::c_char) -> Self {
unsafe { std::ffi::CStr::from_ptr(x) }.to_str().unwrap()
}
}
impl ReprC<*const std::os::raw::c_char> for String {
fn from(x: *const std::os::raw::c_char) -> Self {
let r: &str = ReprC::from(x);
r.to_string()
}
}