use std::ffi::{CStr, CString};
use crate::MlxCError;
use crate::error::check_status;
use crate::raw;
#[derive(Debug)]
pub struct MlxString(raw::mlx_string);
impl MlxString {
pub fn empty() -> Self {
let raw_string = unsafe { raw::mlx_string_new() };
Self(raw_string)
}
pub fn set(&mut self, source: &Self) -> Result<(), MlxCError> {
let status = unsafe { raw::mlx_string_set(&mut self.0, source.0) };
check_status(status, "copy an MLX string")
}
#[must_use]
pub fn to_string_lossy(&self) -> String {
let data_pointer = unsafe { raw::mlx_string_data(self.0) };
if data_pointer.is_null() {
return String::new();
}
unsafe { CStr::from_ptr(data_pointer) }
.to_string_lossy()
.into_owned()
}
pub(crate) fn raw_mut(&mut self) -> *mut raw::mlx_string {
&mut self.0
}
pub(crate) fn require_populated(&self, operation: &'static str) -> Result<(), MlxCError> {
if self.0.ctx.is_null() {
return Err(MlxCError {
operation,
description: "MLX returned an empty string handle".to_owned(),
});
}
Ok(())
}
}
impl Drop for MlxString {
fn drop(&mut self) {
unsafe {
raw::mlx_string_free(self.0);
}
}
}
impl std::str::FromStr for MlxString {
type Err = MlxCError;
fn from_str(value: &str) -> Result<Self, Self::Err> {
let value_argument = CString::new(value).map_err(|_| MlxCError {
operation: "create an MLX string",
description: "string contains an interior null byte".to_owned(),
})?;
let raw_string = unsafe { raw::mlx_string_new_data(value_argument.as_ptr()) };
let string = Self(raw_string);
string.require_populated("create an MLX string")?;
Ok(string)
}
}