1use std::fmt;
5
6use uika_ffi::FNameHandle;
7
8use crate::api::api;
9use crate::error::check_ffi;
10
11#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
16pub struct FName(pub FNameHandle);
17
18impl FName {
19 pub const NONE: FName = FName(FNameHandle(0));
21
22 pub fn new(name: &str) -> Self {
24 let handle = unsafe {
25 ((*api().core).make_fname)(name.as_ptr(), name.len() as u32)
26 };
27 FName(handle)
28 }
29
30 #[inline]
32 pub fn handle(&self) -> FNameHandle {
33 self.0
34 }
35
36 #[inline]
38 pub fn is_none(&self) -> bool {
39 self.0 .0 == 0
40 }
41
42 pub fn to_string_lossy(&self) -> String {
44 let mut buf = [0u8; 256];
46 let mut out_len: u32 = 0;
47 let code = unsafe {
48 ((*api().core).fname_to_string)(
49 self.0,
50 buf.as_mut_ptr(),
51 buf.len() as u32,
52 &mut out_len,
53 )
54 };
55 if check_ffi(code).is_err() {
56 return String::from("<invalid FName>");
57 }
58 std::str::from_utf8(&buf[..out_len as usize])
59 .map(|s| s.to_owned())
60 .unwrap_or_else(|_| String::from("<invalid UTF-8>"))
61 }
62}
63
64impl Default for FName {
65 fn default() -> Self {
66 FName::NONE
67 }
68}
69
70impl fmt::Display for FName {
71 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
72 write!(f, "{}", self.to_string_lossy())
73 }
74}
75
76impl PartialEq<&str> for FName {
77 fn eq(&self, other: &&str) -> bool {
78 self.to_string_lossy() == *other
79 }
80}
81
82impl From<&str> for FName {
83 fn from(s: &str) -> Self {
84 FName::new(s)
85 }
86}
87
88impl From<FName> for FNameHandle {
89 fn from(name: FName) -> FNameHandle {
90 name.0
91 }
92}
93
94impl From<FNameHandle> for FName {
95 fn from(handle: FNameHandle) -> FName {
96 FName(handle)
97 }
98}