qcode/value/util/
named.rs1use std::borrow::Cow;
2
3use crate::{
4 context::Context,
5 error::{Error, ErrorTy, Result},
6 value::ValueId,
7};
8
9pub trait Named {
10 fn name(&self) -> Option<&str>;
11}
12
13pub fn update_context_name<'str>(
16 id: ValueId,
17 ctx: &mut Context<'str>,
18 name: Cow<'str, str>,
19 old_name: Option<&str>,
20) -> Result<()> {
21 if let Some(existing_id) = ctx.get_named_in_scope(id, &name) {
22 if existing_id != id {
23 Err(Error::spanless(ErrorTy::DuplicateName(name.to_string())))
24 } else {
25 Ok(())
26 }
27 } else {
28 ctx.update_name(name, id, old_name)
29 }
30}
31
32pub trait Renameable<'str, 'ctx>: Named {
33 fn rename(&mut self, name: Cow<'str, str>) -> Result<()>;
34
35 fn with_name(mut self, name: Cow<'str, str>) -> Result<Self>
36 where
37 Self: Sized,
38 {
39 self.rename(name)?;
40 Ok(self)
41 }
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47 use crate::{
48 context::Context,
49 error::{Error, ErrorTy},
50 value::{Varnode, util::base_ref::WithCtx},
51 };
52
53 #[test]
54 fn test_update_name() {
55 let mut ctx = Context::new();
56 let space_id = ctx.shared.default_space;
57 let mut var = Varnode::make(&mut ctx, 0, 1, space_id);
58
59 assert_eq!(var.ctx().get_named("var"), None);
60
61 var.rename("var".into()).unwrap();
62
63 assert_eq!(var.ctx().get_named("var"), Some(var.id()));
64 assert_eq!(var.name(), Some("var"));
65 }
66
67 #[test]
68 fn test_update_to_same_name() {
69 let mut ctx = Context::new();
70 let space_id = ctx.shared.default_space;
71 let mut var = Varnode::make(&mut ctx, 0, 1, space_id);
72
73 assert_eq!(var.ctx().get_named("var"), None);
74
75 var.rename("var".into()).unwrap();
76
77 assert_eq!(var.ctx().get_named("var"), Some(var.id()));
78 assert_eq!(var.name(), Some("var"));
79
80 var.rename("var".into()).unwrap();
81
82 assert_eq!(var.ctx().get_named("var"), Some(var.id()));
83 assert_eq!(var.name(), Some("var"));
84 }
85
86 #[test]
87 fn test_update_name_conflict() {
88 let mut ctx = Context::new();
89 let space_id = ctx.shared.default_space;
90 let mut var1 = Varnode::make(&mut ctx, 0, 1, space_id);
91 var1.rename("var".into()).unwrap();
92
93 let mut var2 = Varnode::make(&mut ctx, 1, 1, space_id);
94 assert_eq!(
95 var2.rename("var".into()),
96 Err(Error::spanless(ErrorTy::DuplicateName("var".into())))
97 );
98 }
99}