1use crate::{
8 lldb_addr_t, lldb_user_id_t, sys, Format, SBAddress, SBData, SBError, SBFrame, SBProcess,
9 SBStream, SBTarget, SBThread, SBWatchpoint,
10};
11use std::ffi::{CStr, CString};
12use std::fmt;
13use std::os::raw::c_char;
14
15pub struct SBValue {
17 pub raw: sys::SBValueRef,
19}
20
21impl SBValue {
22 pub(crate) fn wrap(raw: sys::SBValueRef) -> SBValue {
24 SBValue { raw }
25 }
26
27 pub(crate) fn maybe_wrap(raw: sys::SBValueRef) -> Option<SBValue> {
29 if unsafe { sys::SBValueIsValid(raw) } {
30 Some(SBValue { raw })
31 } else {
32 None
33 }
34 }
35
36 pub fn is_valid(&self) -> bool {
38 unsafe { sys::SBValueIsValid(self.raw) }
39 }
40
41 #[allow(missing_docs)]
42 pub fn clear(&self) {
43 unsafe { sys::SBValueClear(self.raw) };
44 }
45
46 #[allow(missing_docs)]
47 pub fn error(&self) -> Option<SBError> {
48 SBError::maybe_wrap(unsafe { sys::SBValueGetError(self.raw) })
49 }
50
51 #[allow(missing_docs)]
52 pub fn id(&self) -> lldb_user_id_t {
53 unsafe { sys::SBValueGetID(self.raw) }
54 }
55
56 #[allow(missing_docs)]
57 pub fn name(&self) -> Option<&str> {
58 unsafe { self.check_null_ptr(sys::SBValueGetName(self.raw)) }
59 }
60
61 #[allow(missing_docs)]
62 pub fn type_name(&self) -> Option<&str> {
63 unsafe { self.check_null_ptr(sys::SBValueGetTypeName(self.raw)) }
64 }
65
66 #[allow(missing_docs)]
67 pub fn display_type_name(&self) -> Option<&str> {
68 unsafe { self.check_null_ptr(sys::SBValueGetDisplayTypeName(self.raw)) }
69 }
70
71 #[allow(missing_docs)]
72 pub fn byte_size(&self) -> usize {
73 unsafe { sys::SBValueGetByteSize(self.raw) }
74 }
75
76 #[allow(missing_docs)]
77 pub fn is_in_scope(&self) -> bool {
78 unsafe { sys::SBValueIsInScope(self.raw) }
79 }
80
81 #[allow(missing_docs)]
82 pub fn format(&self) -> Format {
83 unsafe { sys::SBValueGetFormat(self.raw) }
84 }
85
86 #[allow(missing_docs)]
87 pub fn set_format(&self, format: Format) {
88 unsafe { sys::SBValueSetFormat(self.raw, format) }
89 }
90
91 #[allow(missing_docs)]
92 pub fn value(&self) -> Option<&str> {
93 unsafe { self.check_null_ptr(sys::SBValueGetValue(self.raw)) }
94 }
95
96 #[allow(missing_docs)]
97 pub fn set_value_from_cstring(&self, val: &str) -> Result<(), SBError> {
98 let error = SBError::default();
99 let val = CString::new(val).unwrap();
100
101 if unsafe { sys::SBValueSetValueFromCString2(self.raw, val.as_ptr(), error.raw) } {
102 Ok(())
103 } else {
104 Err(error)
105 }
106 }
107
108 #[allow(missing_docs)]
109 pub fn dereference(&self) -> Option<SBValue> {
110 SBValue::maybe_wrap(unsafe { sys::SBValueDereference(self.raw) })
111 }
112
113 #[allow(missing_docs)]
114 pub fn address_of(&self) -> Option<SBValue> {
115 SBValue::maybe_wrap(unsafe { sys::SBValueAddressOf(self.raw) })
116 }
117
118 #[allow(missing_docs)]
119 pub fn type_is_pointer_type(&self) -> bool {
120 unsafe { sys::SBValueTypeIsPointerType(self.raw) }
121 }
122
123 #[allow(missing_docs)]
124 pub fn target(&self) -> SBTarget {
125 SBTarget::wrap(unsafe { sys::SBValueGetTarget(self.raw) })
126 }
127
128 #[allow(missing_docs)]
129 pub fn process(&self) -> SBProcess {
130 SBProcess::wrap(unsafe { sys::SBValueGetProcess(self.raw) })
131 }
132
133 #[allow(missing_docs)]
134 pub fn thread(&self) -> SBThread {
135 SBThread::wrap(unsafe { sys::SBValueGetThread(self.raw) })
136 }
137
138 #[allow(missing_docs)]
139 pub fn frame(&self) -> SBFrame {
140 SBFrame::wrap(unsafe { sys::SBValueGetFrame(self.raw) })
141 }
142
143 pub fn children(&self) -> SBValueChildIter {
147 SBValueChildIter {
148 value: self,
149 idx: 0,
150 }
151 }
152
153 pub fn watch(
155 &self,
156 resolve_location: bool,
157 read: bool,
158 write: bool,
159 ) -> Result<SBWatchpoint, SBError> {
160 let error = SBError::default();
161 let wp = unsafe { sys::SBValueWatch(self.raw, resolve_location, read, write, error.raw) };
162 if error.is_success() {
163 Ok(SBWatchpoint::wrap(wp))
164 } else {
165 Err(error)
166 }
167 }
168
169 pub fn watch_pointee(
171 &self,
172 resolve_location: bool,
173 read: bool,
174 write: bool,
175 ) -> Result<SBWatchpoint, SBError> {
176 let error = SBError::default();
177 let wp =
178 unsafe { sys::SBValueWatchPointee(self.raw, resolve_location, read, write, error.raw) };
179 if error.is_success() {
180 Ok(SBWatchpoint::wrap(wp))
181 } else {
182 Err(error)
183 }
184 }
185
186 pub fn pointee_data(&self, item_idx: u32, item_count: u32) -> Option<SBData> {
203 SBData::maybe_wrap(unsafe { sys::SBValueGetPointeeData(self.raw, item_idx, item_count) })
204 }
205
206 pub fn data(&self) -> Option<SBData> {
214 SBData::maybe_wrap(unsafe { sys::SBValueGetData(self.raw) })
215 }
216
217 #[allow(missing_docs)]
218 pub fn set_data(&self, data: &SBData) -> Result<(), SBError> {
219 let error = SBError::default();
220 if unsafe { sys::SBValueSetData(self.raw, data.raw, error.raw) } {
221 Ok(())
222 } else {
223 Err(error)
224 }
225 }
226
227 #[allow(missing_docs)]
228 pub fn load_address(&self) -> Option<lldb_addr_t> {
229 let load_address = unsafe { sys::SBValueGetLoadAddress(self.raw) };
230 if load_address != u64::MAX {
231 Some(load_address)
232 } else {
233 None
234 }
235 }
236
237 #[allow(missing_docs)]
238 pub fn address(&self) -> Option<SBAddress> {
239 SBAddress::maybe_wrap(unsafe { sys::SBValueGetAddress(self.raw) })
240 }
241
242 unsafe fn check_null_ptr(&self, ptr: *const c_char) -> Option<&str> {
243 if !ptr.is_null() {
244 match CStr::from_ptr(ptr).to_str() {
245 Ok(s) => Some(s),
246 _ => panic!("Invalid string?"),
247 }
248 } else {
249 None
250 }
251 }
252
253 pub fn get_as_signed(&self) -> Result<i64, SBError> {
255 let error = SBError::default();
256 let result = unsafe { sys::SBValueGetValueAsSigned(self.raw, error.raw, 0) };
257 if error.is_success() {
258 Ok(result)
259 } else {
260 Err(error)
261 }
262 }
263
264 pub fn get_as_unsigned(&self) -> Result<u64, SBError> {
266 let error = SBError::default();
267 let result = unsafe { sys::SBValueGetValueAsUnsigned(self.raw, error.raw, 0) };
268 if error.is_success() {
269 Ok(result)
270 } else {
271 Err(error)
272 }
273 }
274}
275
276impl Clone for SBValue {
277 fn clone(&self) -> SBValue {
278 SBValue {
279 raw: unsafe { sys::CloneSBValue(self.raw) },
280 }
281 }
282}
283
284impl fmt::Debug for SBValue {
285 fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
286 let stream = SBStream::new();
287 unsafe { sys::SBValueGetDescription(self.raw, stream.raw) };
288 write!(fmt, "SBValue {{ {} }}", stream.data())
289 }
290}
291
292impl Drop for SBValue {
293 fn drop(&mut self) {
294 unsafe { sys::DisposeSBValue(self.raw) };
295 }
296}
297
298unsafe impl Send for SBValue {}
299unsafe impl Sync for SBValue {}
300
301pub struct SBValueChildIter<'d> {
306 value: &'d SBValue,
307 idx: u32,
308}
309
310impl Iterator for SBValueChildIter<'_> {
311 type Item = SBValue;
312
313 fn next(&mut self) -> Option<SBValue> {
314 if self.idx < unsafe { sys::SBValueGetNumChildren(self.value.raw) } {
315 let r = Some(SBValue::wrap(unsafe {
316 sys::SBValueGetChildAtIndex(self.value.raw, self.idx)
317 }));
318 self.idx += 1;
319 r
320 } else {
321 None
322 }
323 }
324
325 fn size_hint(&self) -> (usize, Option<usize>) {
326 let sz = unsafe { sys::SBValueGetNumChildren(self.value.raw) } as usize;
327 (sz - self.idx as usize, Some(sz))
328 }
329}
330
331impl ExactSizeIterator for SBValueChildIter<'_> {}
332
333#[cfg(feature = "graphql")]
334#[juniper::graphql_object]
335impl SBValue {
336 fn id() -> i32 {
338 self.id() as i32
339 }
340
341 fn name() -> Option<&str> {
342 self.name()
343 }
344
345 fn type_name() -> Option<&str> {
346 self.type_name()
347 }
348
349 fn display_type_name() -> Option<&str> {
350 self.display_type_name()
351 }
352
353 fn byte_size() -> i32 {
355 self.byte_size() as i32
356 }
357
358 fn is_in_scope() -> bool {
359 self.is_in_scope()
360 }
361}