#![allow(non_snake_case)]
extern crate libc;
use std::ffi::CStr;
pub trait ToPointerCString
{
#[inline(always)]
fn to_ptr(&self) -> *const ::libc::c_char;
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct ConstCStr {
pub cValue: &'static str,
pub rustValue: &'static str,
}
impl ToPointerCString for ConstCStr
{
#[inline(always)]
fn to_ptr(&self) -> *const ::libc::c_char
{
self.as_ptr()
}
}
impl ToPointerCString for CStr
{
#[inline(always)]
fn to_ptr(&self) -> *const ::libc::c_char
{
self.as_ptr() as *const ::libc::c_char
}
}
impl ConstCStr {
#[inline(always)]
pub fn to_str(&self) -> &'static str {
self.rustValue
}
#[inline(always)]
pub fn to_bytes(&self) -> &'static [u8] {
self.rustValue.as_bytes()
}
#[inline(always)]
pub fn to_bytes_with_nul(&self) -> &'static [u8] {
self.cValue.as_bytes()
}
#[inline(always)]
pub fn as_ptr(&self) -> *const libc::c_char {
self.cValue.as_ptr() as *const libc::c_char
}
#[inline(always)]
pub fn as_cstr(&self) -> &'static CStr {
unsafe {
CStr::from_ptr(self.cValue.as_ptr() as *const i8)
}
}
}
#[macro_export]
macro_rules! const_cstr {
($strval:expr) => (
$crate::ConstCStr
{
rustValue: $strval,
cValue: concat!($strval, "\0")
}
);
($($strname:ident = $strval:expr);+;) => (
$(
const $strname: $crate::ConstCStr = const_cstr!($strval);
)+
);
($(pub $strname:ident = $strval:expr);+;) => (
$(
pub const $strname: $crate::ConstCStr = const_cstr!($strval);
)+
);
}
#[test]
fn test_creates_valid_str() {
const_cstr! {
HELLO_CSTR = "Hello, world!";
}
let cstr = unsafe { CStr::from_ptr(HELLO_CSTR.as_ptr()) };
assert_eq!(HELLO_CSTR.to_str(), cstr.to_str().unwrap());
}