rl_model/model/
resource.rs1use super::*;
2use crate::parser::{Position, RlError};
3use std::collections::HashMap;
4
5#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, Default)]
6pub struct ResourceId(pub usize);
7impl Id for ResourceId {
8 fn index(&self) -> usize {
9 self.0
10 }
11}
12
13#[derive(Debug, Clone)]
14pub struct Resource {
15 id: ResourceId,
16 name: String,
17 states: Vec<State>,
18 initial: Reference<StateId>,
19 transitions: Transitions,
20 position: Option<Position>,
21}
22
23impl Resource {
24 pub fn new<S: Into<String>>(name: S, position: Option<Position>) -> Self {
25 let id = ResourceId::default();
26 let name = name.into();
27 Self {
28 id,
29 name,
30 states: Vec::new(),
31 initial: Reference::Unresolved("?".into(), None),
32 transitions: Transitions::All,
33 position,
34 }
35 }
36
37 pub fn states(&self) -> &Vec<State> {
40 &self.states
41 }
42
43 pub fn add_state(&mut self, mut state: State) -> StateId {
44 let id = StateId(self.id, self.states.len());
45 state.set_id(id);
46 self.states.push(state);
47 id
48 }
49
50 pub fn get_state(&self, id: StateId) -> Option<&State> {
51 let StateId(resource_id, state_id) = id;
52 if self.id != resource_id {
53 None
54 } else {
55 self.states.get(state_id)
56 }
57 }
58
59 pub fn initial(&self) -> StateId {
60 self.initial.resolved()
61 }
62
63 pub fn set_initial(&mut self, state: Reference<StateId>) {
64 self.initial = state;
65 }
66
67 pub fn state_map(&self) -> HashMap<String, StateId> {
68 let mut map = HashMap::new();
69 for x in self.states.iter() {
70 map.insert(x.name().into(), x.id());
71 }
72 map
73 }
74
75 pub fn get_state_from_name(&self, name: &str) -> Option<&State> {
76 for x in self.states.iter() {
77 if x.name() == name {
78 return Some(x);
79 }
80 }
81 None
82 }
83
84 pub fn transitions(&self) -> &Transitions {
87 &self.transitions
88 }
89
90 pub fn set_transitions(&mut self, transitions: Transitions) {
91 self.transitions = transitions;
92 }
93
94 pub fn transitions_list(&self) -> Vec<Transition> {
95 match self.transitions() {
96 Transitions::All => {
97 let mut transitions = vec![];
98 for src in self.states.iter() {
99 let r_src = Reference::Resolved(src.id());
100 for dst in self.states.iter() {
101 let r_dst = Reference::Resolved(dst.id());
102 if src.id() != dst.id() {
103 transitions.push(Transition::new(r_src.clone(), r_dst.clone()));
104 }
105 }
106 }
107 transitions
108 }
109 Transitions::List(transitions) => transitions.clone(),
110 }
111 }
112
113 pub fn names(&self) -> Vec<(String, Option<Position>)> {
116 let mut v = Vec::new();
117 for x in self.states.iter() {
118 v.push((x.name().into(), x.position()))
119 }
120 v
121 }
122
123 pub fn resolve_state(&mut self) -> Result<(), RlError> {
126 let map = self.state_map();
127 self.resolve_initial_state(&map)?;
128 self.transitions.resolve(&map)?;
129 Ok(())
130 }
131
132 fn resolve_initial_state(&mut self, map: &HashMap<String, StateId>) -> Result<(), RlError> {
133 match &self.initial {
134 Reference::Unresolved(name, pos) => match map.get(name) {
135 Some(id) => {
136 self.initial = Reference::Resolved(*id);
137 Ok(())
138 }
139 None => Err(RlError::Resolve {
140 element: format!("state '{}'", name),
141 position: pos.clone(),
142 }),
143 },
144 Reference::Resolved(_) => Ok(()),
145 }
146 }
147}
148
149impl Named<ResourceId> for Resource {
150 fn id(&self) -> ResourceId {
151 self.id
152 }
153
154 fn set_id(&mut self, id: ResourceId) {
155 self.id = id;
156 for state in self.states.iter_mut() {
157 let StateId(_, index) = state.id();
158 state.set_id(StateId(id, index));
159 }
160 }
161
162 fn name(&self) -> &str {
163 &self.name
164 }
165
166 fn position(&self) -> Option<Position> {
167 self.position.clone()
168 }
169}
170
171impl GetFromId<StateId, State> for Resource {
174 fn get(&self, id: StateId) -> Option<&State> {
175 self.get_state(id)
176 }
177}
178
179impl ToLang for Resource {
182 fn to_lang(&self, skillset: &Skillset) -> String {
183 let mut s = String::new();
184 s.push_str(&format!("\t\t{} {{\n", self.name));
185 s.push_str("\t\t\tstate {");
187 for x in self.states.iter() {
188 s.push_str(&format!(" {}", x));
189 }
190 s.push_str(" }\n");
191 s.push_str(&format!(
193 "\t\t\tinitial {}\n",
194 self.initial.to_lang(skillset)
195 ));
196 s.push_str(&self.transitions.to_lang(skillset));
198 s.push_str("\t\t}\n");
200 s
201 }
202}
203
204impl std::fmt::Display for Resource {
207 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
208 write!(f, "{}", self.name())
209 }
210}