Skip to main content

fre_rs/
validated.rs

1//! 
2//! Validated types for safe interaction with the C API and the Flash Runtime,
3//! ensuring data passed across the FFI boundary is well-formed and valid.
4//! 
5
6use super::*;
7
8
9pub type NonNullFREData = NonNull<c_void>;
10pub type NonNullFREObject = NonNull<c_void>;
11
12
13#[derive(Debug, Clone, Copy, PartialEq, Eq)]
14#[repr(transparent)]
15pub struct NonNegativeInt(i32);
16impl NonNegativeInt {
17    pub const MIN: Self = Self(0);
18    pub const MAX: Self = Self(i32::MAX);
19    pub fn new (value: i32) -> Option<Self> {
20        if value >= 0 {
21            Some(Self(value))
22        } else {
23            None
24        }
25    }
26    pub fn get (self) -> i32 {self.0}
27}
28impl Default for NonNegativeInt {
29    fn default() -> Self {Self::MIN}
30}
31
32
33/// A UTF-8 string stored as a NUL-terminated [`CStr`].
34#[derive(Debug, Clone, PartialEq, Eq)]
35pub struct UCStr(UCStrValue);
36#[derive(Debug, Clone, PartialEq, Eq)]
37enum UCStrValue {
38    Static(&'static CStr),
39    Heap(Arc<CStr>),
40}
41impl UCStr {
42    pub const fn from_literal (literal: &'static CStr) -> Result<Self, Utf8Error> {
43        match literal.to_str() {
44            Ok(_) => Ok(Self(UCStrValue::Static(literal))),
45            Err(e) => Err(e),
46        }
47    }
48    pub const unsafe fn from_literal_unchecked (literal: &'static CStr) -> Self {
49        debug_assert!(literal.to_str().is_ok());
50        Self(UCStrValue::Static(literal))
51    }
52    #[inline]
53    pub fn as_str (&self) -> &str {
54        let s = match self.0 {
55            UCStrValue::Static(s) => s.to_bytes(),
56            UCStrValue::Heap(ref s) => s.to_bytes(),
57        };
58        unsafe {str::from_utf8_unchecked(s)}
59    }
60    pub fn as_c_str (&self) -> &CStr {
61        match self.0 {
62            UCStrValue::Static(s) => s,
63            UCStrValue::Heap(ref s) => s.as_ref(),
64        }
65    }
66    /// # Borrow
67    pub fn as_ptr (&self) -> FREStr {
68        match self.0 {
69            UCStrValue::Static(s) => s.as_ptr() as FREStr,
70            UCStrValue::Heap(ref s) => s.as_ptr() as FREStr,
71        }
72    }
73    pub fn to_c_string (&self) -> CString {
74        match self.0 {
75            UCStrValue::Static(s) => s.to_owned(),
76            UCStrValue::Heap(ref s) => s.as_ref().to_owned(),
77        }
78    }
79}
80impl From<UCStr> for CString {
81    fn from(value: UCStr) -> Self {value.to_c_string()}
82}
83impl From<UCStr> for String {
84    fn from(value: UCStr) -> Self {value.to_string()}
85}
86impl TryFrom<String> for UCStr {
87    type Error = NulError;
88    fn try_from(value: String) -> Result<Self, NulError> {
89        CString::new(value).map(|s|{
90            let s = s.into();
91            Self(UCStrValue::Heap(s))
92        })
93    }
94}
95impl TryFrom<&str> for UCStr {
96    type Error = NulError;
97    fn try_from(value: &str) -> Result<Self, NulError> {
98        CString::new(value).map(|s|{
99            let s = s.into();
100            Self(UCStrValue::Heap(s))
101        })
102    }
103}
104impl TryFrom<CString> for UCStr {
105    type Error = Utf8Error;
106    fn try_from(value: CString) -> Result<Self, Utf8Error> {
107        value.to_str()?;
108        let s = value.into();
109        Ok(Self(UCStrValue::Heap(s)))
110    }
111}
112impl TryFrom<&CStr> for UCStr {
113    type Error = Utf8Error;
114    fn try_from(value: &CStr) -> Result<Self, Utf8Error> {
115        value.to_str().map(|_|{
116            let s = value.to_owned().into();
117            Self(UCStrValue::Heap(s))
118        })
119    }
120}
121impl PartialEq<str> for UCStr {
122    #[inline]
123    fn eq(&self, other: &str) -> bool { self.as_str() == other }
124}
125impl PartialEq<UCStr> for str {
126    #[inline]
127    fn eq(&self, other: &UCStr) -> bool { self == other.as_str() }
128}
129impl PartialOrd for UCStr {
130    #[inline]
131    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> { self.as_str().partial_cmp(other.as_str()) }
132}
133impl Ord for UCStr {
134    #[inline]
135    fn cmp(&self, other: &Self) -> std::cmp::Ordering { self.as_str().cmp(other.as_str()) }
136}
137impl std::hash::Hash for UCStr {
138    #[inline]
139    fn hash<H: std::hash::Hasher>(&self, state: &mut H) { self.as_str().hash(state) }
140}
141impl AsRef<str> for UCStr {
142    fn as_ref(&self) -> &str { self.as_str() }
143}
144impl AsRef<CStr> for UCStr {
145    fn as_ref(&self) -> &CStr { self.as_c_str() }
146}
147impl std::borrow::Borrow<str> for UCStr {
148    #[inline]
149    fn borrow(&self) -> &str { self.as_str() }
150}
151impl Display for UCStr {
152    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { Display::fmt(self.as_str(), f) }
153}