probe_rs_debug/language/
value.rs

1use std::str::FromStr;
2
3use crate::{
4    DebugError, Variable, VariableCache, VariableLocation, VariableName, VariableValue,
5    language::parsing::ValueExt,
6};
7
8use probe_rs::MemoryInterface;
9
10/// Traits and Impl's to read from, and write to, memory value based on Variable::typ and Variable::location.
11pub trait Value {
12    /// The MS DAP protocol passes the value as a string, so this trait is here to provide the memory read logic before returning it as a string.
13    fn get_value(
14        variable: &Variable,
15        memory: &mut dyn MemoryInterface,
16        _variable_cache: &VariableCache,
17    ) -> Result<Self, DebugError>
18    where
19        Self: Sized;
20
21    /// This `update_value` will update the target memory with a new value for the [`Variable`], ...
22    /// - Only `base` data types can have their value updated in target memory.
23    /// - The input format of the [Variable.value] is a [String], and the impl of this trait must convert the memory value appropriately before storing.
24    fn update_value(
25        variable: &Variable,
26        memory: &mut dyn MemoryInterface,
27        new_value: &str,
28    ) -> Result<(), DebugError>;
29}
30
31impl<V> From<Result<V, DebugError>> for VariableValue
32where
33    V: Value + ToString,
34{
35    fn from(val: Result<V, DebugError>) -> Self {
36        val.map_or_else(
37            |err| VariableValue::Error(format!("{err:?}")),
38            |value| VariableValue::Valid(value.to_string()),
39        )
40    }
41}
42
43impl Value for bool {
44    fn get_value(
45        variable: &Variable,
46        memory: &mut dyn MemoryInterface,
47        _variable_cache: &VariableCache,
48    ) -> Result<Self, DebugError> {
49        let mem_data = memory.read_word_8(variable.memory_location.memory_address()?)?;
50        let ret_value: bool = mem_data != 0;
51        Ok(ret_value)
52    }
53
54    fn update_value(
55        variable: &Variable,
56        memory: &mut dyn MemoryInterface,
57        new_value: &str,
58    ) -> Result<(), DebugError> {
59        if let VariableLocation::RegisterValue(_) = variable.memory_location {
60            return Err(DebugError::NotImplemented(
61                "Updating a register value is not implemented",
62            ));
63        }
64
65        memory
66            .write_word_8(
67                variable.memory_location.memory_address()?,
68                <bool as FromStr>::from_str(new_value).map_err(|error| {
69                    DebugError::WarnAndContinue {
70                        message: format!(
71                            "Invalid data conversion from value: {new_value:?}. {error:?}"
72                        ),
73                    }
74                })? as u8,
75            )
76            .map_err(|error| DebugError::WarnAndContinue {
77                message: format!("{error:?}"),
78            })
79    }
80}
81impl Value for char {
82    fn get_value(
83        variable: &Variable,
84        memory: &mut dyn MemoryInterface,
85        _variable_cache: &VariableCache,
86    ) -> Result<Self, DebugError> {
87        let mem_data = memory.read_word_32(variable.memory_location.memory_address()?)?;
88        if let Some(return_value) = char::from_u32(mem_data) {
89            Ok(return_value)
90        } else {
91            Ok('?')
92        }
93    }
94
95    fn update_value(
96        variable: &Variable,
97        memory: &mut dyn MemoryInterface,
98        new_value: &str,
99    ) -> Result<(), DebugError> {
100        if let VariableLocation::RegisterValue(_) = variable.memory_location {
101            return Err(DebugError::NotImplemented(
102                "Updating a register value is not implemented",
103            ));
104        }
105
106        memory
107            .write_word_32(
108                variable.memory_location.memory_address()?,
109                <char as FromStr>::from_str(new_value).map_err(|error| {
110                    DebugError::WarnAndContinue {
111                        message: format!(
112                            "Invalid data conversion from value: {new_value:?}. {error:?}"
113                        ),
114                    }
115                })? as u32,
116            )
117            .map_err(|error| DebugError::WarnAndContinue {
118                message: format!("{error:?}"),
119            })
120    }
121}
122impl Value for String {
123    fn get_value(
124        variable: &Variable,
125        memory: &mut dyn MemoryInterface,
126        variable_cache: &VariableCache,
127    ) -> Result<Self, DebugError> {
128        let mut str_value: String = "".to_owned();
129        let children: Vec<_> = variable_cache.get_children(variable.variable_key).collect();
130        if !children.is_empty() {
131            let mut string_length = match children.iter().find(|child_variable| {
132                matches!(child_variable.name, VariableName::Named(ref name) if name == "length")
133            }) {
134                Some(string_length) => {
135                    // TODO: maybe avoid accessing value directly?
136                    if let VariableValue::Valid(length_value) = &string_length.value {
137                        length_value.parse().unwrap_or(0_usize)
138                    } else {
139                        0_usize
140                    }
141                }
142                None => 0_usize,
143            };
144
145            let string_location = match children.iter().find(|child_variable| {
146                matches!(child_variable.name, VariableName::Named(ref name) if name == "data_ptr")
147            }) {
148                Some(location_value) => {
149                    let mut child_variables = variable_cache.get_children(location_value.variable_key);
150                    if let Some(first_child) = child_variables.next() {
151                        first_child.memory_location.memory_address()?
152                    } else {
153                        0_u64
154                    }
155                }
156                None => 0_u64,
157            };
158            if string_location == 0 {
159                str_value = "Error: Failed to determine &str memory location".to_string();
160            } else {
161                // Limit string length to work around buggy information, otherwise the debugger
162                // can hang due to buggy debug information.
163                //
164                // TODO: If implemented, the variable should not be fetched automatically,
165                // but only when requested by the user. This workaround can then be removed.
166                if string_length > 200 {
167                    tracing::warn!(
168                        "Very long string ({} bytes), truncating to 200 bytes.",
169                        string_length
170                    );
171                    string_length = 200;
172                }
173
174                if string_length == 0 {
175                    // A string with length 0 doesn't need to be read from memory.
176                } else {
177                    let mut buff = vec![0u8; string_length];
178                    memory.read(string_location, &mut buff)?;
179                    std::str::from_utf8(&buff)?.clone_into(&mut str_value);
180                }
181            }
182        } else {
183            str_value = "Error: Failed to evaluate &str value".to_string();
184        }
185        Ok(str_value)
186    }
187
188    fn update_value(
189        _variable: &Variable,
190        _memory: &mut dyn MemoryInterface,
191        _new_value: &str,
192    ) -> Result<(), DebugError> {
193        Err(DebugError::WarnAndContinue { message:"Unsupported datatype: \"String\". Please only update variables with a base data type.".to_string()})
194    }
195}
196
197impl Value for i8 {
198    fn get_value(
199        variable: &Variable,
200        memory: &mut dyn MemoryInterface,
201        _variable_cache: &VariableCache,
202    ) -> Result<Self, DebugError> {
203        Self::read_from_location(variable, memory)
204    }
205
206    fn update_value(
207        variable: &Variable,
208        memory: &mut dyn MemoryInterface,
209        new_value: &str,
210    ) -> Result<(), DebugError> {
211        if let VariableLocation::RegisterValue(_) = variable.memory_location {
212            return Err(DebugError::NotImplemented(
213                "Updating a register value is not implemented",
214            ));
215        }
216
217        let buff = i8::parse_to_bytes(new_value)?;
218        memory
219            .write_word_8(variable.memory_location.memory_address()?, buff[0])
220            .map_err(|error| DebugError::WarnAndContinue {
221                message: format!("{error:?}"),
222            })
223    }
224}
225impl Value for i16 {
226    fn get_value(
227        variable: &Variable,
228        memory: &mut dyn MemoryInterface,
229        _variable_cache: &VariableCache,
230    ) -> Result<Self, DebugError> {
231        Self::read_from_location(variable, memory)
232    }
233
234    fn update_value(
235        variable: &Variable,
236        memory: &mut dyn MemoryInterface,
237        new_value: &str,
238    ) -> Result<(), DebugError> {
239        if let VariableLocation::RegisterValue(_) = variable.memory_location {
240            return Err(DebugError::NotImplemented(
241                "Updating a register value is not implemented",
242            ));
243        }
244
245        let buff = i16::parse_to_bytes(new_value)?;
246        memory
247            .write_8(variable.memory_location.memory_address()?, &buff)
248            .map_err(|error| DebugError::WarnAndContinue {
249                message: format!("{error:?}"),
250            })
251    }
252}
253impl Value for i32 {
254    fn get_value(
255        variable: &Variable,
256        memory: &mut dyn MemoryInterface,
257        _variable_cache: &VariableCache,
258    ) -> Result<Self, DebugError> {
259        Self::read_from_location(variable, memory)
260    }
261
262    fn update_value(
263        variable: &Variable,
264        memory: &mut dyn MemoryInterface,
265        new_value: &str,
266    ) -> Result<(), DebugError> {
267        if let VariableLocation::RegisterValue(_) = variable.memory_location {
268            return Err(DebugError::NotImplemented(
269                "Updating a register value is not implemented",
270            ));
271        }
272
273        let buff = i32::parse_to_bytes(new_value)?;
274        memory
275            .write_8(variable.memory_location.memory_address()?, &buff)
276            .map_err(|error| DebugError::WarnAndContinue {
277                message: format!("{error:?}"),
278            })
279    }
280}
281impl Value for i64 {
282    fn get_value(
283        variable: &Variable,
284        memory: &mut dyn MemoryInterface,
285        _variable_cache: &VariableCache,
286    ) -> Result<Self, DebugError> {
287        Self::read_from_location(variable, memory)
288    }
289
290    fn update_value(
291        variable: &Variable,
292        memory: &mut dyn MemoryInterface,
293        new_value: &str,
294    ) -> Result<(), DebugError> {
295        if let VariableLocation::RegisterValue(_) = variable.memory_location {
296            return Err(DebugError::NotImplemented(
297                "Updating a register value is not implemented",
298            ));
299        }
300
301        let buff = i64::parse_to_bytes(new_value)?;
302        memory
303            .write_8(variable.memory_location.memory_address()?, &buff)
304            .map_err(|error| DebugError::WarnAndContinue {
305                message: format!("{error:?}"),
306            })
307    }
308}
309impl Value for i128 {
310    fn get_value(
311        variable: &Variable,
312        memory: &mut dyn MemoryInterface,
313        _variable_cache: &VariableCache,
314    ) -> Result<Self, DebugError> {
315        Self::read_from_location(variable, memory)
316    }
317
318    fn update_value(
319        variable: &Variable,
320        memory: &mut dyn MemoryInterface,
321        new_value: &str,
322    ) -> Result<(), DebugError> {
323        if let VariableLocation::RegisterValue(_) = variable.memory_location {
324            return Err(DebugError::NotImplemented(
325                "Updating a register value is not implemented",
326            ));
327        }
328
329        let buff = i128::parse_to_bytes(new_value)?;
330        memory
331            .write_8(variable.memory_location.memory_address()?, &buff)
332            .map_err(|error| DebugError::WarnAndContinue {
333                message: format!("{error:?}"),
334            })
335    }
336}
337impl Value for u8 {
338    fn get_value(
339        variable: &Variable,
340        memory: &mut dyn MemoryInterface,
341        _variable_cache: &VariableCache,
342    ) -> Result<Self, DebugError> {
343        Self::read_from_location(variable, memory)
344    }
345
346    fn update_value(
347        variable: &Variable,
348        memory: &mut dyn MemoryInterface,
349        new_value: &str,
350    ) -> Result<(), DebugError> {
351        if let VariableLocation::RegisterValue(_) = variable.memory_location {
352            return Err(DebugError::NotImplemented(
353                "Updating a register value is not implemented",
354            ));
355        }
356
357        let buff = u8::parse_to_bytes(new_value)?;
358        memory
359            .write_word_8(variable.memory_location.memory_address()?, buff[0])
360            .map_err(|error| DebugError::WarnAndContinue {
361                message: format!("{error:?}"),
362            })
363    }
364}
365impl Value for u16 {
366    fn get_value(
367        variable: &Variable,
368        memory: &mut dyn MemoryInterface,
369        _variable_cache: &VariableCache,
370    ) -> Result<Self, DebugError> {
371        Self::read_from_location(variable, memory)
372    }
373
374    fn update_value(
375        variable: &Variable,
376        memory: &mut dyn MemoryInterface,
377        new_value: &str,
378    ) -> Result<(), DebugError> {
379        if let VariableLocation::RegisterValue(_) = variable.memory_location {
380            return Err(DebugError::NotImplemented(
381                "Updating a register value is not implemented",
382            ));
383        }
384
385        let buff = u16::parse_to_bytes(new_value)?;
386        memory
387            .write_8(variable.memory_location.memory_address()?, &buff)
388            .map_err(|error| DebugError::WarnAndContinue {
389                message: format!("{error:?}"),
390            })
391    }
392}
393impl Value for u32 {
394    fn get_value(
395        variable: &Variable,
396        memory: &mut dyn MemoryInterface,
397        _variable_cache: &VariableCache,
398    ) -> Result<Self, DebugError> {
399        Self::read_from_location(variable, memory)
400    }
401
402    fn update_value(
403        variable: &Variable,
404        memory: &mut dyn MemoryInterface,
405        new_value: &str,
406    ) -> Result<(), DebugError> {
407        if let VariableLocation::RegisterValue(_) = variable.memory_location {
408            return Err(DebugError::NotImplemented(
409                "Updating a register value is not implemented",
410            ));
411        }
412
413        let buff = u32::parse_to_bytes(new_value)?;
414        memory
415            .write_8(variable.memory_location.memory_address()?, &buff)
416            .map_err(|error| DebugError::WarnAndContinue {
417                message: format!("{error:?}"),
418            })
419    }
420}
421impl Value for u64 {
422    fn get_value(
423        variable: &Variable,
424        memory: &mut dyn MemoryInterface,
425        _variable_cache: &VariableCache,
426    ) -> Result<Self, DebugError> {
427        Self::read_from_location(variable, memory)
428    }
429
430    fn update_value(
431        variable: &Variable,
432        memory: &mut dyn MemoryInterface,
433        new_value: &str,
434    ) -> Result<(), DebugError> {
435        if let VariableLocation::RegisterValue(_) = variable.memory_location {
436            return Err(DebugError::NotImplemented(
437                "Updating a register value is not implemented",
438            ));
439        }
440
441        let buff = u64::parse_to_bytes(new_value)?;
442        memory
443            .write_8(variable.memory_location.memory_address()?, &buff)
444            .map_err(|error| DebugError::WarnAndContinue {
445                message: format!("{error:?}"),
446            })
447    }
448}
449impl Value for u128 {
450    fn get_value(
451        variable: &Variable,
452        memory: &mut dyn MemoryInterface,
453        _variable_cache: &VariableCache,
454    ) -> Result<Self, DebugError> {
455        Self::read_from_location(variable, memory)
456    }
457
458    fn update_value(
459        variable: &Variable,
460        memory: &mut dyn MemoryInterface,
461        new_value: &str,
462    ) -> Result<(), DebugError> {
463        if let VariableLocation::RegisterValue(_) = variable.memory_location {
464            return Err(DebugError::NotImplemented(
465                "Updating a register value is not implemented",
466            ));
467        }
468
469        let buff = u128::parse_to_bytes(new_value)?;
470        memory
471            .write_8(variable.memory_location.memory_address()?, &buff)
472            .map_err(|error| DebugError::WarnAndContinue {
473                message: format!("{error:?}"),
474            })
475    }
476}
477impl Value for f32 {
478    fn get_value(
479        variable: &Variable,
480        memory: &mut dyn MemoryInterface,
481        _variable_cache: &VariableCache,
482    ) -> Result<Self, DebugError> {
483        Self::read_from_location(variable, memory)
484    }
485
486    fn update_value(
487        variable: &Variable,
488        memory: &mut dyn MemoryInterface,
489        new_value: &str,
490    ) -> Result<(), DebugError> {
491        if let VariableLocation::RegisterValue(_) = variable.memory_location {
492            return Err(DebugError::NotImplemented(
493                "Updating a register value is not implemented",
494            ));
495        }
496
497        let buff = f32::parse_to_bytes(new_value)?;
498        memory
499            .write_8(variable.memory_location.memory_address()?, &buff)
500            .map_err(|error| DebugError::WarnAndContinue {
501                message: format!("{error:?}"),
502            })
503    }
504}
505impl Value for f64 {
506    fn get_value(
507        variable: &Variable,
508        memory: &mut dyn MemoryInterface,
509        _variable_cache: &VariableCache,
510    ) -> Result<Self, DebugError> {
511        Self::read_from_location(variable, memory)
512    }
513
514    fn update_value(
515        variable: &Variable,
516        memory: &mut dyn MemoryInterface,
517        new_value: &str,
518    ) -> Result<(), DebugError> {
519        if let VariableLocation::RegisterValue(_) = variable.memory_location {
520            return Err(DebugError::NotImplemented(
521                "Updating a register value is not implemented",
522            ));
523        }
524
525        let buff = f64::parse_to_bytes(new_value)?;
526        memory
527            .write_8(variable.memory_location.memory_address()?, &buff)
528            .map_err(|error| DebugError::WarnAndContinue {
529                message: format!("{error:?}"),
530            })
531    }
532}
533
534/// Format a float value to a string, preserving at least one fractional digit.
535pub fn format_float(value: f64) -> String {
536    let mut s = format!("{value}");
537    if !s.contains('.') {
538        s.push('.');
539    }
540    while s.ends_with('0') {
541        s.pop();
542    }
543    if s.ends_with('.') {
544        s.push('0');
545    }
546
547    s
548}