objc2_foundation/
value.rs1use alloc::ffi::CString;
2use alloc::string::ToString;
3use core::ffi::CStr;
4use core::fmt;
5use core::hash;
6use core::mem::MaybeUninit;
7use core::ptr::NonNull;
8use core::str;
9
10use objc2::encode::Encode;
11use objc2::rc::Retained;
12use objc2::AnyThread;
13
14use crate::NSValue;
15
16impl NSValue {
21 pub fn new<T: 'static + Copy + Encode>(value: T) -> Retained<Self> {
39 let bytes: NonNull<T> = NonNull::from(&value);
40 let encoding = CString::new(T::ENCODING.to_string()).unwrap();
41 unsafe {
42 Self::initWithBytes_objCType(
43 Self::alloc(),
44 bytes.cast(),
45 NonNull::new(encoding.as_ptr() as *mut _).unwrap(),
46 )
47 }
48 }
49}
50
51impl NSValue {
53 pub unsafe fn get<T: 'static + Copy + Encode>(&self) -> T {
85 debug_assert!(
86 self.contains_encoding::<T>(),
87 "wrong encoding. NSValue tried to return something with encoding {}, but the encoding of the given type was {}",
88 self.encoding().unwrap_or("(NULL)"),
89 T::ENCODING,
90 );
91 let mut value = MaybeUninit::<T>::uninit();
92 let ptr: NonNull<T> = NonNull::new(value.as_mut_ptr()).unwrap();
93 #[allow(deprecated)]
94 unsafe {
95 self.getValue(ptr.cast())
96 };
97 unsafe { value.assume_init() }
100 }
101
102 #[cfg(feature = "NSRange")]
103 pub fn get_range(&self) -> Option<crate::NSRange> {
104 if self.contains_encoding::<crate::NSRange>() {
105 Some(unsafe { self.rangeValue() })
107 } else {
108 None
109 }
110 }
111
112 #[cfg(all(feature = "NSGeometry", feature = "objc2-core-foundation"))]
113 pub fn get_point(&self) -> Option<crate::NSPoint> {
114 if self.contains_encoding::<crate::NSPoint>() {
115 Some(unsafe { self.pointValue() })
121 } else {
122 None
123 }
124 }
125
126 #[cfg(all(feature = "NSGeometry", feature = "objc2-core-foundation"))]
127 pub fn get_size(&self) -> Option<crate::NSSize> {
128 if self.contains_encoding::<crate::NSSize>() {
129 Some(unsafe { self.sizeValue() })
131 } else {
132 None
133 }
134 }
135
136 #[cfg(all(feature = "NSGeometry", feature = "objc2-core-foundation"))]
137 pub fn get_rect(&self) -> Option<crate::NSRect> {
138 if self.contains_encoding::<crate::NSRect>() {
139 Some(unsafe { self.rectValue() })
141 } else {
142 None
143 }
144 }
145
146 pub fn encoding(&self) -> Option<&str> {
147 let ptr = self.objCType().as_ptr();
148 Some(unsafe { CStr::from_ptr(ptr) }.to_str().unwrap())
149 }
150
151 pub fn contains_encoding<T: 'static + Copy + Encode>(&self) -> bool {
152 T::ENCODING.equivalent_to_str(self.encoding().unwrap())
153 }
154}
155
156impl hash::Hash for NSValue {
157 #[inline]
158 fn hash<H: hash::Hasher>(&self, state: &mut H) {
159 (**self).hash(state);
160 }
161}
162
163impl PartialEq for NSValue {
164 #[doc(alias = "isEqualToValue:")]
165 fn eq(&self, other: &Self) -> bool {
166 self.isEqualToValue(other)
168 }
169}
170
171impl Eq for NSValue {}
172
173impl fmt::Debug for NSValue {
174 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
175 let enc = self.encoding().unwrap_or("(NULL)");
176 let bytes = &**self; f.debug_struct("NSValue")
178 .field("encoding", &enc)
179 .field("bytes", bytes)
180 .finish()
181 }
182}