1use mlir_sys::{MlirStringRef, mlirStringRefEqual};
2use std::{
3 ffi::CStr,
4 marker::PhantomData,
5 slice,
6 str::{self, Utf8Error},
7};
8
9#[derive(Clone, Copy, Debug)]
11pub struct StringRef<'a> {
12 raw: MlirStringRef,
13 _parent: PhantomData<&'a str>,
14}
15
16impl<'a> StringRef<'a> {
17 pub fn new(string: &'a str) -> Self {
19 let string = MlirStringRef {
20 data: string.as_bytes().as_ptr() as *const _,
21 length: string.len(),
22 };
23
24 unsafe { Self::from_raw(string) }
25 }
26
27 pub fn from_c_str(string: &'a CStr) -> Self {
29 let string = MlirStringRef {
30 data: string.as_ptr(),
31 length: string.to_bytes_with_nul().len() - 1,
32 };
33
34 unsafe { Self::from_raw(string) }
35 }
36
37 pub fn as_str(&self) -> Result<&'a str, Utf8Error> {
39 unsafe {
40 let bytes = slice::from_raw_parts(self.raw.data as *mut u8, self.raw.length);
41
42 str::from_utf8(if bytes[bytes.len() - 1] == 0 {
43 &bytes[..bytes.len() - 1]
44 } else {
45 bytes
46 })
47 }
48 }
49
50 pub const fn to_raw(self) -> MlirStringRef {
52 self.raw
53 }
54
55 pub unsafe fn from_raw(string: MlirStringRef) -> Self {
61 Self {
62 raw: string,
63 _parent: Default::default(),
64 }
65 }
66}
67
68impl PartialEq for StringRef<'_> {
69 fn eq(&self, other: &Self) -> bool {
70 unsafe { mlirStringRefEqual(self.raw, other.raw) }
71 }
72}
73
74impl Eq for StringRef<'_> {}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn equal() {
82 assert_eq!(StringRef::new("foo"), StringRef::new("foo"));
83 }
84
85 #[test]
86 fn equal_str() {
87 assert_eq!(StringRef::new("foo").as_str().unwrap(), "foo");
88 }
89
90 #[test]
91 fn not_equal() {
92 assert_ne!(StringRef::new("foo"), StringRef::new("bar"));
93 }
94}