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