use crate::inventory::{Inventory, TypeId};
use crate::lang::meta::{Docs, Emission, FileEmission, Visibility};
use crate::lang::types::{Type, TypeInfo, TypeKind, TypePattern, WireIO};
use crate::wire::SerializationError;
use crate::{Error, bad_wire};
use std::ffi::CStr;
use std::io::{Read, Write};
use std::marker::PhantomData;
use std::option::Option::None;
use std::os::raw::c_char;
use std::ptr::null;
static EMPTY: &[u8] = b"\0";
#[repr(transparent)]
#[derive(Debug)]
pub struct CStrPtr<'a> {
ptr: *const c_char,
_phantom: PhantomData<&'a ()>,
}
unsafe impl Send for CStrPtr<'_> {}
unsafe impl Sync for CStrPtr<'_> {}
impl Default for CStrPtr<'_> {
fn default() -> Self {
Self { ptr: null(), _phantom: PhantomData }
}
}
impl<'a> CStrPtr<'a> {
#[must_use]
pub fn empty() -> Self {
Self { ptr: EMPTY.as_ptr().cast(), _phantom: PhantomData }
}
pub fn from_slice_with_nul(cstr_with_nul: &'a [u8]) -> Result<Self, Error> {
if !cstr_with_nul.contains(&0) {
return Err(Error::nul_terminated());
}
Ok(Self { ptr: cstr_with_nul.as_ptr().cast(), _phantom: PhantomData })
}
#[must_use]
pub fn from_cstr(cstr: &'a CStr) -> Self {
Self { ptr: cstr.as_ptr(), _phantom: PhantomData }
}
#[must_use]
pub fn as_c_str(&self) -> Option<&'a CStr> {
if self.ptr.is_null() {
None
} else {
unsafe { Some(CStr::from_ptr(self.ptr)) }
}
}
pub fn as_str(&self) -> Result<&'a str, Error> {
Ok(self.as_c_str().ok_or_else(Error::null)?.to_str()?)
}
}
unsafe impl TypeInfo for CStrPtr<'_> {
const WIRE_SAFE: bool = false;
const RAW_SAFE: bool = true;
const ASYNC_SAFE: bool = false;
const SERVICE_SAFE: bool = false;
const SERVICE_CTOR_SAFE: bool = false;
fn id() -> TypeId {
TypeId::new(0xDE450364E9ADDBA5DC9A6C5BBEC7759F)
}
fn kind() -> TypeKind {
TypeKind::TypePattern(TypePattern::CStrPointer)
}
fn ty() -> Type {
Type {
emission: Emission::FileEmission(FileEmission::Common),
docs: Docs::empty(),
visibility: Visibility::Public,
name: "CStrPtr".to_string(),
kind: Self::kind(),
}
}
fn register(inventory: &mut impl Inventory) {
inventory.register_type(Self::id(), Self::ty());
}
}
unsafe impl WireIO for CStrPtr<'_> {
fn write(&self, _: &mut impl Write) -> Result<(), SerializationError> {
bad_wire!()
}
fn read(_: &mut impl Read) -> Result<Self, SerializationError> {
bad_wire!()
}
fn live_size(&self) -> usize {
bad_wire!()
}
}