model.rs 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531
  1. use std::{
  2. collections::{HashMap, HashSet, LinkedList},
  3. hash::Hash,
  4. rc::Rc,
  5. };
  6. use btrun::model::End;
  7. use proc_macro2::{Ident, Span, TokenStream};
  8. use quote::{format_ident, quote, quote_spanned};
  9. use crate::{
  10. case_convert::CaseConvert,
  11. error,
  12. parsing::{ActorDef, Dest, GetSpan, Message, Protocol, State, Transition},
  13. parsing::{DestinationState, MessageReplyPart},
  14. };
  15. pub(crate) struct ProtocolModel {
  16. def: Protocol,
  17. msg_lookup: MsgLookup,
  18. actor_lookup: ActorLookup,
  19. use_statements: TokenStream,
  20. actors: HashMap<Rc<Ident>, ActorModel>,
  21. msg_enum_name: Ident,
  22. msg_enum_kinds_name: Ident,
  23. end_ident: Ident,
  24. end_struct: TokenStream,
  25. actor_id_param: Ident,
  26. runtime_param: Ident,
  27. msg_ident: Ident,
  28. reply_ident: Ident,
  29. from_ident: Ident,
  30. actor_name_ident: Ident,
  31. init_state_var: Ident,
  32. init_state_type_param: Ident,
  33. state_type_param: Ident,
  34. new_state_type_param: Ident,
  35. new_state_method: Ident,
  36. state_var: Ident,
  37. }
  38. impl ProtocolModel {
  39. pub(crate) fn new(def: Protocol) -> syn::Result<Self> {
  40. let get_transitions = || def.transitions.iter().map(|x| x.as_ref());
  41. let actor_lookup =
  42. ActorLookup::new(def.actor_defs.iter().map(|x| x.as_ref()), get_transitions())?;
  43. let mut is_client = HashMap::<Rc<Ident>, bool>::new();
  44. // First mark all actors as not clients.
  45. for actor_def in def.actor_defs.iter() {
  46. is_client.insert(actor_def.actor.clone(), false);
  47. }
  48. // For every actor which is not spawned by another actor, mark it as a client if its
  49. // initial state receives no messages, then mark all of the actors it spawns as clients.
  50. for actor_def in def.actor_defs.iter() {
  51. if !actor_lookup.parents(actor_def.actor.as_ref()).is_empty() {
  52. continue;
  53. }
  54. let init_state = actor_def.states.as_ref().first().unwrap();
  55. let init_state_receives_no_msgs = def
  56. .transitions
  57. .iter()
  58. .filter(|transition| {
  59. transition.in_state.state_trait.as_ref() == init_state.as_ref()
  60. })
  61. .all(|transition| transition.in_msg().is_none());
  62. if init_state_receives_no_msgs {
  63. mark_all_progeny(&actor_lookup, &mut is_client, actor_def.actor.as_ref());
  64. }
  65. }
  66. fn mark_all_progeny(
  67. actor_lookup: &ActorLookup,
  68. is_client: &mut HashMap<Rc<Ident>, bool>,
  69. actor_name: &Ident,
  70. ) {
  71. *is_client.get_mut(actor_name).unwrap() = true;
  72. let children = actor_lookup.children(actor_name);
  73. for child in children {
  74. *is_client.get_mut(child).unwrap() = true;
  75. mark_all_progeny(actor_lookup, is_client, child.as_ref());
  76. }
  77. }
  78. let msg_lookup = MsgLookup::new(get_transitions());
  79. let mut actors = HashMap::new();
  80. for actor_def in def.actor_defs.iter() {
  81. let actor_name = &actor_def.actor;
  82. let actor_states = actor_lookup.actor_states(actor_name.as_ref());
  83. let transitions_by_state = actor_states.iter().map(|state_name| {
  84. let transitions = def
  85. .transitions
  86. .iter()
  87. .filter(|transition| {
  88. state_name.as_ref() == transition.in_state.state_trait.as_ref()
  89. })
  90. .cloned();
  91. (state_name.clone(), transitions)
  92. });
  93. let is_client = *is_client.get(&actor_def.actor).unwrap();
  94. let is_service = actor_lookup.service_providers.contains(&actor_def.actor);
  95. let kind = ActorKind::new(is_client, is_service).ok_or_else(|| {
  96. syn::Error::new(actor_def.actor.span(), error::msgs::CLIENT_USED_IN_SERVICE)
  97. })?;
  98. let actor =
  99. ActorModel::new(actor_def.clone(), &msg_lookup, kind, transitions_by_state)?;
  100. actors.insert(actor_name.clone(), actor);
  101. }
  102. let end_ident = format_ident!("{}", End::ident());
  103. Ok(Self {
  104. msg_enum_name: Self::make_msg_enum_name(&def),
  105. msg_enum_kinds_name: Self::make_msg_enum_kinds_name(&def),
  106. use_statements: Self::make_use_statements(),
  107. def,
  108. msg_lookup,
  109. actor_lookup,
  110. actors,
  111. end_struct: quote! { ::btrun::model::#end_ident },
  112. end_ident,
  113. actor_id_param: format_ident!("actor_id"),
  114. runtime_param: format_ident!("runtime"),
  115. msg_ident: format_ident!("msg"),
  116. reply_ident: format_ident!("reply"),
  117. from_ident: format_ident!("from"),
  118. actor_name_ident: format_ident!("actor_name"),
  119. init_state_var: format_ident!("init"),
  120. init_state_type_param: format_ident!("Init"),
  121. state_type_param: format_ident!("State"),
  122. new_state_type_param: format_ident!("NewState"),
  123. new_state_method: format_ident!("new_state"),
  124. state_var: format_ident!("state"),
  125. })
  126. }
  127. fn make_msg_enum_name(def: &Protocol) -> Ident {
  128. format_ident!("{}Msgs", def.name_def.name)
  129. }
  130. fn make_msg_enum_kinds_name(def: &Protocol) -> Ident {
  131. format_ident!("{}MsgKinds", def.name_def.name)
  132. }
  133. fn make_use_statements() -> TokenStream {
  134. quote! {
  135. use ::btlib::bterr;
  136. use ::btrun::{
  137. log, Mailbox,
  138. model::{
  139. Envelope, ControlMsg, Named, TransResult, ActorError, ActorErrorPayload,
  140. TransKind, Mutex,
  141. }
  142. };
  143. use ::std::sync::Arc;
  144. }
  145. }
  146. pub(crate) fn def(&self) -> &Protocol {
  147. &self.def
  148. }
  149. pub(crate) fn msg_lookup(&self) -> &MsgLookup {
  150. &self.msg_lookup
  151. }
  152. pub(crate) fn actor_lookup(&self) -> &ActorLookup {
  153. &self.actor_lookup
  154. }
  155. pub(crate) fn actors(&self) -> &HashMap<Rc<Ident>, ActorModel> {
  156. &self.actors
  157. }
  158. pub(crate) fn actors_iter(&self) -> impl Iterator<Item = &ActorModel> {
  159. self.actors.values()
  160. }
  161. pub(crate) fn states_iter(&self) -> impl Iterator<Item = &StateModel> {
  162. self.actors_iter().flat_map(|actor| actor.states().values())
  163. }
  164. #[cfg(test)]
  165. pub(crate) fn methods_iter(&self) -> impl Iterator<Item = &MethodModel> {
  166. self.states_iter()
  167. .flat_map(|state| state.methods().values())
  168. }
  169. #[cfg(test)]
  170. pub(crate) fn outputs_iter(&self) -> impl Iterator<Item = &ValueModel> {
  171. self.methods_iter()
  172. .flat_map(|method| method.output_values().iter())
  173. }
  174. /// Returns the tokens for the use statements which bring the types used inside spawn functions
  175. /// into scope.
  176. pub(crate) fn use_statements(&self) -> &TokenStream {
  177. &self.use_statements
  178. }
  179. /// The name of the message enum used by this protocol.
  180. pub(crate) fn msg_enum_ident(&self) -> &Ident {
  181. &self.msg_enum_name
  182. }
  183. /// The name of the message kinds enum used by this protocol.
  184. pub(crate) fn msg_enum_kinds_ident(&self) -> &Ident {
  185. &self.msg_enum_kinds_name
  186. }
  187. /// The [Ident] containing [End::ident].
  188. pub(crate) fn end_ident(&self) -> &Ident {
  189. &self.end_ident
  190. }
  191. /// Returns a token stream which references the [End] struct using a fully qualified path.
  192. #[allow(dead_code)]
  193. pub(crate) fn end_struct(&self) -> &TokenStream {
  194. &self.end_struct
  195. }
  196. /// The name of the [btrun::ActorId] parameter in an actor closure.
  197. pub(crate) fn actor_id_param(&self) -> &Ident {
  198. &self.actor_id_param
  199. }
  200. /// The name of the `&'static `[Runtime] parameter in an actor closure.
  201. pub(crate) fn runtime_param(&self) -> &Ident {
  202. &self.runtime_param
  203. }
  204. /// The name of the variable used to hold the `from` field of a [btrun::Envelope].
  205. #[allow(clippy::wrong_self_convention)]
  206. pub(crate) fn from_ident(&self) -> &Ident {
  207. &self.from_ident
  208. }
  209. /// The name of the variable used to hold the `reply` field from a [btrun::Envelope].
  210. pub(crate) fn reply_ident(&self) -> &Ident {
  211. &self.reply_ident
  212. }
  213. /// The name of the variable used to hold the `msg` field from a [btrun::Envelope].
  214. pub(crate) fn msg_ident(&self) -> &Ident {
  215. &self.msg_ident
  216. }
  217. /// The name of the local variable in an actor closure used to hold the actor's name.
  218. pub(crate) fn actor_name_ident(&self) -> &Ident {
  219. &self.actor_name_ident
  220. }
  221. /// The identifier for the variable holding the initial state of an actor.
  222. pub(crate) fn init_state_var(&self) -> &Ident {
  223. &self.init_state_var
  224. }
  225. /// The identifier for the `Init` type parameter used in client enums, handles, and spawn
  226. /// functions.
  227. pub(crate) fn init_type_param(&self) -> &Ident {
  228. &self.init_state_type_param
  229. }
  230. /// The type parameter for client handles which indicates the handle's current state.
  231. pub(crate) fn state_type_param(&self) -> &Ident {
  232. &self.state_type_param
  233. }
  234. /// The type parameter for client handles which indicates the new state the handle is
  235. /// transitioning to.
  236. pub(crate) fn new_state_type_param(&self) -> &Ident {
  237. &self.new_state_type_param
  238. }
  239. /// The name of the method used to transition client handles to a new type state.
  240. pub(crate) fn new_state_method(&self) -> &Ident {
  241. &self.new_state_method
  242. }
  243. /// The identifier of variable used to hold the current state of an actor, and the field of
  244. /// a client handle which holds the current state.
  245. pub(crate) fn state_var(&self) -> &Ident {
  246. &self.state_var
  247. }
  248. /// Returns the name of the field used to hold the shared state in a client handle.
  249. pub(crate) fn state_field(&self) -> &Ident {
  250. &self.state_var
  251. }
  252. /// Returns an iterator over the [Ident]s for each of the states in [actor].
  253. pub(crate) fn state_idents<'a>(
  254. &'a self,
  255. actor: &'a ActorModel,
  256. ) -> impl Iterator<Item = &'a Ident> {
  257. actor
  258. .states()
  259. .values()
  260. .map(|state| state.name())
  261. .chain(std::iter::once(&self.end_ident))
  262. }
  263. fn get_actor<'a>(&'a self, actor_name: &Ident) -> &'a ActorModel {
  264. self.actors
  265. .get(actor_name)
  266. .unwrap_or_else(|| panic!("Invalid actor name: '{actor_name}'"))
  267. }
  268. pub(crate) fn get_state<'a>(&'a self, state_name: &Ident) -> &'a StateModel {
  269. let actor_name = self.actor_lookup().actor_with_state(state_name);
  270. let actor = self.get_actor(actor_name);
  271. actor
  272. .states()
  273. .get(state_name)
  274. .unwrap_or_else(|| panic!("Actor {actor_name} doesn't contain state {state_name}."))
  275. }
  276. /// Returns a struct with the type params and their associated constraints for the given actor's
  277. /// spawn function.
  278. pub(crate) fn type_param_info_for<'a>(&'a self, actor_name: &Ident) -> TypeParamInfo<'a> {
  279. let mut type_params = Vec::<&Ident>::new();
  280. let mut constraints = Vec::<TokenStream>::new();
  281. // We do a breadth-first traversal over the associated types referenced by this actor,
  282. // starting with it's initial state.
  283. let mut visited = HashSet::<&Ident>::new();
  284. let mut queue = LinkedList::<&Ident>::new();
  285. queue.push_front(self.get_actor(actor_name).init_state().name());
  286. while !queue.is_empty() {
  287. let state_name = queue.pop_back().unwrap();
  288. visited.insert(state_name);
  289. let state = self.get_state(state_name);
  290. let mut any = false;
  291. let eqs = state
  292. .out_states_and_assoc_types()
  293. .map(|(out_state, assoc_type)| {
  294. any = true;
  295. if !visited.contains(out_state) {
  296. queue.push_front(out_state);
  297. }
  298. let type_param = self.get_state(out_state).type_param();
  299. quote! { #assoc_type = #type_param }
  300. });
  301. let constraint_list = quote! { #( #eqs ),* };
  302. let constraint = if any {
  303. quote! { < #constraint_list > }
  304. } else {
  305. constraint_list
  306. };
  307. let type_param = state.type_param();
  308. type_params.push(type_param);
  309. let state_name = state.name();
  310. let constraint = quote! { #type_param: 'static + #state_name #constraint };
  311. constraints.push(constraint);
  312. }
  313. TypeParamInfo {
  314. constraints,
  315. type_params,
  316. }
  317. }
  318. /// Returns an iterator of the names of the states which the given state transitions to.
  319. pub(crate) fn next_states<'a>(
  320. &'a self,
  321. state: &'a StateModel,
  322. ) -> impl Iterator<Item = &'a ValueModel> {
  323. state
  324. .methods()
  325. .values()
  326. // The first output of a method is the state this state transitions to.
  327. .flat_map(|method| method.output_values().first().zip(Some(method.name())))
  328. .filter(|(output, method_name)| {
  329. let state_trait = output.kind().state_trait()
  330. .unwrap_or_else(|| panic!("The first output of method {method_name} in state {} was not the correct kind.", state.name()));
  331. state_trait.as_ref() != End::ident()
  332. })
  333. .map(|(output, _)| output)
  334. }
  335. }
  336. pub(crate) struct TypeParamInfo<'a> {
  337. pub(crate) type_params: Vec<&'a Ident>,
  338. pub(crate) constraints: Vec<TokenStream>,
  339. }
  340. #[derive(Clone, Debug)]
  341. /// A categorization of different actor types based on their messaging behavior.
  342. pub(crate) enum ActorKind {
  343. /// A client is an actor which is not spawned by another actor (i.e. has no parents) and
  344. /// whose initial state has no transition which receives a message, or which is spawned by a
  345. /// client.
  346. Client,
  347. /// Any actor with a state that appears wrapped in `service()` is in this category.
  348. Service,
  349. /// Any actor not in either of the other two categories falls into this one.
  350. Worker,
  351. }
  352. impl ActorKind {
  353. fn new(is_client: bool, is_service: bool) -> Option<Self> {
  354. match (is_client, is_service) {
  355. (true, false) => Some(Self::Client),
  356. (false, true) => Some(Self::Service),
  357. (false, false) => Some(Self::Worker),
  358. (true, true) => None,
  359. }
  360. }
  361. pub(crate) fn is_client(&self) -> bool {
  362. matches!(self, Self::Client)
  363. }
  364. }
  365. impl Copy for ActorKind {}
  366. pub(crate) struct ActorModel {
  367. #[allow(dead_code)]
  368. def: Rc<ActorDef>,
  369. kind: ActorKind,
  370. state_enum_ident: Ident,
  371. states: HashMap<Rc<Ident>, StateModel>,
  372. spawn_function_ident: Option<Ident>,
  373. handle_struct_ident: Option<Ident>,
  374. }
  375. impl ActorModel {
  376. fn new<S, T>(
  377. def: Rc<ActorDef>,
  378. messages: &MsgLookup,
  379. kind: ActorKind,
  380. state_iter: S,
  381. ) -> syn::Result<Self>
  382. where
  383. S: IntoIterator<Item = (Rc<Ident>, T)>,
  384. T: IntoIterator<Item = Rc<Transition>>,
  385. {
  386. let transitions: HashMap<_, Vec<_>> = state_iter
  387. .into_iter()
  388. .map(|(name, transitions)| (name, transitions.into_iter().collect()))
  389. .collect();
  390. let mut states = HashMap::new();
  391. let is_client = matches!(kind, ActorKind::Client);
  392. for (name, transitions) in transitions.into_iter() {
  393. let state = StateModel::new(name.clone(), messages, transitions, is_client)?;
  394. if let Some(prev) = states.insert(name, state) {
  395. panic!(
  396. "States are not being grouped by actor correctly. Duplicate state name: '{}'",
  397. prev.name
  398. );
  399. }
  400. }
  401. let actor_name = def.actor.as_ref();
  402. Ok(Self {
  403. state_enum_ident: Self::make_state_enum_ident(actor_name),
  404. spawn_function_ident: Self::make_spawn_function_ident(kind, actor_name),
  405. handle_struct_ident: Self::make_handle_struct_ident(kind, actor_name),
  406. def,
  407. kind,
  408. states,
  409. })
  410. }
  411. fn make_state_enum_ident(actor_name: &Ident) -> Ident {
  412. format_ident!("{}State", actor_name.to_string().snake_to_pascal())
  413. }
  414. fn make_spawn_function_ident(kind: ActorKind, actor_name: &Ident) -> Option<Ident> {
  415. // Services are registered, not spawned, so they have no spawn function.
  416. if let ActorKind::Service = kind {
  417. None
  418. } else {
  419. Some(format_ident!("spawn_{actor_name}"))
  420. }
  421. }
  422. fn make_handle_struct_ident(kind: ActorKind, actor_name: &Ident) -> Option<Ident> {
  423. if let ActorKind::Client = kind {
  424. Some(format_ident!("{}Handle", actor_name.snake_to_pascal()))
  425. } else {
  426. None
  427. }
  428. }
  429. pub(crate) fn def(&self) -> &ActorDef {
  430. &self.def
  431. }
  432. pub(crate) fn name(&self) -> &Ident {
  433. &self.def.actor
  434. }
  435. pub(crate) fn kind(&self) -> ActorKind {
  436. self.kind
  437. }
  438. pub(crate) fn states(&self) -> &HashMap<Rc<Ident>, StateModel> {
  439. &self.states
  440. }
  441. pub(crate) fn init_state(&self) -> &StateModel {
  442. // It's a syntax error to have an IdentArray with no states in it, so this unwrap
  443. // shouldn't panic.
  444. let init = self.def.states.as_ref().first().unwrap();
  445. self.states.get(init).unwrap()
  446. }
  447. pub(crate) fn state_enum_ident(&self) -> &Ident {
  448. &self.state_enum_ident
  449. }
  450. pub(crate) fn spawn_function_ident(&self) -> Option<&Ident> {
  451. self.spawn_function_ident.as_ref()
  452. }
  453. pub(crate) fn handle_struct_ident(&self) -> Option<&Ident> {
  454. self.handle_struct_ident.as_ref()
  455. }
  456. }
  457. pub(crate) struct StateModel {
  458. name: Rc<Ident>,
  459. methods: HashMap<Rc<Ident>, MethodModel>,
  460. type_param: Ident,
  461. }
  462. impl StateModel {
  463. fn new<T>(
  464. name: Rc<Ident>,
  465. messages: &MsgLookup,
  466. transitions: T,
  467. part_of_client: bool,
  468. ) -> syn::Result<Self>
  469. where
  470. T: IntoIterator<Item = Rc<Transition>>,
  471. {
  472. let mut methods = HashMap::new();
  473. for transition in transitions.into_iter() {
  474. let transition_span = transition.span();
  475. let method = MethodModel::new(transition, messages, part_of_client)?;
  476. if methods.insert(method.name.clone(), method).is_some() {
  477. return Err(syn::Error::new(
  478. transition_span,
  479. error::msgs::DUPLICATE_TRANSITION,
  480. ));
  481. }
  482. }
  483. Ok(Self {
  484. type_param: Self::make_generic_type_param(name.as_ref()),
  485. name,
  486. methods,
  487. })
  488. }
  489. fn make_generic_type_param(name: &Ident) -> Ident {
  490. format_ident!("T{name}")
  491. }
  492. pub(crate) fn name(&self) -> &Ident {
  493. self.name.as_ref()
  494. }
  495. pub(crate) fn methods(&self) -> &HashMap<Rc<Ident>, MethodModel> {
  496. &self.methods
  497. }
  498. pub(crate) fn type_param(&self) -> &Ident {
  499. &self.type_param
  500. }
  501. fn out_states_and_assoc_types(&self) -> impl Iterator<Item = (&Ident, &Ident)> {
  502. self.methods().values().flat_map(|method| {
  503. method.output_values().iter().flat_map(|output| {
  504. output
  505. .kind()
  506. .state_trait()
  507. .map(|ptr| ptr.as_ref())
  508. .zip(output.assoc_type())
  509. })
  510. })
  511. }
  512. }
  513. impl GetSpan for StateModel {
  514. fn span(&self) -> Span {
  515. self.name.span()
  516. }
  517. }
  518. #[cfg_attr(test, derive(Debug))]
  519. pub(crate) struct MethodModel {
  520. def: Rc<Transition>,
  521. name: Rc<Ident>,
  522. handle_name: Option<Ident>,
  523. inputs: Vec<ValueModel>,
  524. outputs: Vec<ValueModel>,
  525. future: Ident,
  526. }
  527. impl MethodModel {
  528. fn new(def: Rc<Transition>, messages: &MsgLookup, part_of_client: bool) -> syn::Result<Self> {
  529. let (name, client_handle_name) = Self::new_name(def.as_ref())?;
  530. let name = Rc::new(name);
  531. let type_prefix = name.snake_to_pascal();
  532. Ok(Self {
  533. name,
  534. handle_name: client_handle_name,
  535. inputs: Self::make_inputs(def.as_ref(), &type_prefix, messages, part_of_client),
  536. outputs: Self::make_outputs(def.as_ref(), &type_prefix, messages, part_of_client),
  537. future: format_ident!("{type_prefix}Fut"),
  538. def,
  539. })
  540. }
  541. fn new_name(def: &Transition) -> syn::Result<(Ident, Option<Ident>)> {
  542. let pair = if let Some(msg) = def.in_msg() {
  543. let name = format_ident!("handle_{}", msg.variant().pascal_to_snake());
  544. (name, None)
  545. } else {
  546. let mut dests = def.out_msgs.as_ref().iter();
  547. let mut msg_names = String::new();
  548. if let Some(dest) = dests.next() {
  549. msg_names.push_str(dest.msg.variant().pascal_to_snake().as_str());
  550. } else {
  551. return Err(syn::Error::new(
  552. def.span(),
  553. error::msgs::NO_MSG_SENT_OR_RECEIVED,
  554. ));
  555. }
  556. for dest in dests {
  557. msg_names.push('_');
  558. msg_names.push_str(dest.msg.variant().pascal_to_snake().as_str());
  559. }
  560. let name = format_ident!("on_send_{msg_names}");
  561. let handle_name = format_ident!("send_{msg_names}");
  562. (name, Some(handle_name))
  563. };
  564. Ok(pair)
  565. }
  566. fn make_inputs(
  567. def: &Transition,
  568. type_prefix: &str,
  569. messages: &MsgLookup,
  570. part_of_client: bool,
  571. ) -> Vec<ValueModel> {
  572. let mut inputs = Vec::new();
  573. if let Some(in_msg) = def.in_msg() {
  574. let kind = ValueKind::Msg {
  575. def: in_msg.clone(),
  576. };
  577. inputs.push(ValueModel::new(kind, type_prefix));
  578. }
  579. if part_of_client {
  580. for dest in def.out_msgs.as_ref().iter() {
  581. let kind = ValueKind::new_dest(dest.clone(), messages, part_of_client);
  582. inputs.push(ValueModel::new(kind, type_prefix));
  583. }
  584. }
  585. inputs
  586. }
  587. fn make_outputs(
  588. def: &Transition,
  589. type_prefix: &str,
  590. messages: &MsgLookup,
  591. part_of_client: bool,
  592. ) -> Vec<ValueModel> {
  593. let mut outputs = Vec::new();
  594. for state in def.out_states.as_ref().iter() {
  595. let kind = ValueKind::State { def: state.clone() };
  596. outputs.push(ValueModel::new(kind, type_prefix));
  597. }
  598. if part_of_client {
  599. if def.in_msg().is_none() {
  600. outputs.push(ValueModel::new(ValueKind::Return, type_prefix));
  601. }
  602. } else {
  603. for dest in def.out_msgs.as_ref().iter() {
  604. let kind = ValueKind::new_dest(dest.clone(), messages, part_of_client);
  605. outputs.push(ValueModel::new(kind, type_prefix));
  606. }
  607. }
  608. outputs
  609. }
  610. /// Returns the input associated with the message this method is handling, or [None] if this
  611. /// method is not handling a message.
  612. pub(crate) fn msg_received_input(&self) -> Option<&Message> {
  613. self.def.in_msg().map(|rc| rc.as_ref())
  614. }
  615. pub(crate) fn def(&self) -> &Transition {
  616. self.def.as_ref()
  617. }
  618. pub(crate) fn name(&self) -> &Rc<Ident> {
  619. &self.name
  620. }
  621. pub(crate) fn inputs(&self) -> &Vec<ValueModel> {
  622. &self.inputs
  623. }
  624. pub(crate) fn output_values(&self) -> &Vec<ValueModel> {
  625. &self.outputs
  626. }
  627. pub(crate) fn future(&self) -> &Ident {
  628. &self.future
  629. }
  630. /// The name of this method in a client handle, if this method is part of a client actor.
  631. pub(crate) fn handle_name(&self) -> Option<&Ident> {
  632. self.handle_name.as_ref()
  633. }
  634. /// Returns the output for the state this method transitions into.
  635. pub(crate) fn next_state(&self) -> &ValueModel {
  636. self.output_values().get(0).unwrap()
  637. }
  638. /// Returns an iterator over the output variables returned by this method.
  639. pub(crate) fn output_vars(&self) -> impl Iterator<Item = &'_ Ident> {
  640. self.output_values()
  641. .iter()
  642. .flat_map(|output| output.output_var_name())
  643. }
  644. }
  645. impl GetSpan for MethodModel {
  646. fn span(&self) -> Span {
  647. self.def.span()
  648. }
  649. }
  650. #[cfg_attr(test, derive(Debug))]
  651. pub(crate) struct ValueModel {
  652. kind: ValueKind,
  653. type_name: Option<TokenStream>,
  654. assoc_type: Option<Ident>,
  655. decl: Option<TokenStream>,
  656. var_name: Ident,
  657. }
  658. impl ValueModel {
  659. fn new(kind: ValueKind, type_prefix: &str) -> Self {
  660. let (decl, type_name, assoc_type) = match &kind {
  661. ValueKind::Msg { def, .. } => {
  662. let decl = None;
  663. let msg_type = def.msg_type.as_ref();
  664. let type_name = Some(quote! { #msg_type });
  665. let assoc_type = None;
  666. (decl, type_name, assoc_type)
  667. }
  668. ValueKind::State { def, .. } => {
  669. let state_trait = def.state_trait.as_ref();
  670. if state_trait == End::ident() {
  671. let decl = None;
  672. let end_ident = format_ident!("{}", End::ident());
  673. let type_name = Some(quote! { ::btrun::model::#end_ident });
  674. let assoc_type = None;
  675. (decl, type_name, assoc_type)
  676. } else {
  677. let assoc_type_ident = format_ident!("{type_prefix}{}", state_trait);
  678. let decl = Some(quote! { type #assoc_type_ident: #state_trait; });
  679. let type_name = Some(quote! { Self::#assoc_type_ident });
  680. let assoc_type = Some(assoc_type_ident);
  681. (decl, type_name, assoc_type)
  682. }
  683. }
  684. ValueKind::Dest {
  685. msg_type,
  686. reply_type,
  687. part_of_client,
  688. ..
  689. } => {
  690. let decl = None;
  691. let type_name = if *part_of_client {
  692. if reply_type.is_some() {
  693. Some(quote! {
  694. <#msg_type as ::btrun::model::CallMsg>::Reply
  695. })
  696. } else {
  697. None
  698. }
  699. } else {
  700. Some(quote! { #msg_type })
  701. };
  702. let assoc_type = None;
  703. (decl, type_name, assoc_type)
  704. }
  705. ValueKind::Return { .. } => {
  706. let assoc_type_ident = format_ident!("{type_prefix}Return");
  707. let decl = Some(quote! { type #assoc_type_ident; });
  708. let type_name = Some(quote! { Self::#assoc_type_ident });
  709. let assoc_type = Some(assoc_type_ident);
  710. (decl, type_name, assoc_type)
  711. }
  712. };
  713. Self {
  714. var_name: kind.var_name(),
  715. type_name,
  716. decl,
  717. kind,
  718. assoc_type,
  719. }
  720. }
  721. fn span(&self) -> Span {
  722. self.kind.span()
  723. }
  724. /// The code for specifying the type of this input.
  725. pub(crate) fn type_name(&self) -> Option<&TokenStream> {
  726. self.type_name.as_ref()
  727. }
  728. pub(crate) fn decl(&self) -> Option<&TokenStream> {
  729. self.decl.as_ref()
  730. }
  731. pub(crate) fn kind(&self) -> &ValueKind {
  732. &self.kind
  733. }
  734. /// Returns the associated type for this output. If this output not a state, or is the end
  735. /// state, then `None` is returned.
  736. pub(crate) fn assoc_type(&self) -> Option<&Ident> {
  737. self.assoc_type.as_ref()
  738. }
  739. pub(crate) fn var_name(&self) -> &Ident {
  740. &self.var_name
  741. }
  742. /// If this output actually appears in the tuple returned by its method, then its variable name
  743. /// is returned. Otherwise, `None` is returned.
  744. ///
  745. /// An output of a transition is not actually be an output of the corresponding trait method in
  746. /// the case of a method in a client actor.
  747. pub(crate) fn output_var_name(&self) -> Option<&Ident> {
  748. if self.type_name.is_some() {
  749. Some(&self.var_name)
  750. } else {
  751. None
  752. }
  753. }
  754. /// Returns the token for this input when it appears in a client handle method.
  755. pub(crate) fn as_handle_param(&self) -> TokenStream {
  756. let name = &self.var_name;
  757. if let ValueKind::Dest { msg_type, .. } = &self.kind {
  758. quote_spanned! {self.span()=> mut #name: #msg_type }
  759. } else {
  760. quote_spanned! {self.span() => }
  761. }
  762. }
  763. #[allow(dead_code)]
  764. pub(crate) fn as_method_call(&self) -> TokenStream {
  765. if let ValueKind::Msg { .. } | ValueKind::Dest { .. } = &self.kind {
  766. let var_name = &self.var_name;
  767. quote_spanned! {self.span()=> #var_name }
  768. } else {
  769. quote_spanned! {self.span()=> }
  770. }
  771. }
  772. pub(crate) fn in_method_decl(&self) -> TokenStream {
  773. let var_name = &self.var_name;
  774. match &self.kind {
  775. ValueKind::Msg { def, .. } => {
  776. let msg_type = def.msg_type.as_ref();
  777. quote! { #var_name: #msg_type }
  778. }
  779. ValueKind::State { .. } => quote_spanned! {self.span()=> },
  780. // Dest values only ever occur in the inputs of clients. In client handles, only call
  781. // replies are passed in.
  782. ValueKind::Dest { reply_type, .. } => {
  783. if let Some(reply_type) = reply_type {
  784. quote! { #var_name: #reply_type }
  785. } else {
  786. quote! {}
  787. }
  788. }
  789. ValueKind::Return => quote! {},
  790. }
  791. }
  792. }
  793. #[cfg_attr(test, derive(Debug))]
  794. pub(crate) enum ValueKind {
  795. /// Represents a value which is passing in a message, and so always occurs in an input position.
  796. Msg { def: Rc<Message> },
  797. /// Represents a value which is passing out a state, and so always occurs in an output position.
  798. State { def: Rc<State> },
  799. /// Represents a value which is sending a message to another actor, and so is in the input
  800. /// position for client actors, but in the output position for server actors.
  801. Dest {
  802. def: Rc<Dest>,
  803. msg_type: Rc<TokenStream>,
  804. reply_type: Option<Rc<TokenStream>>,
  805. part_of_client: bool,
  806. },
  807. /// Represents the return value of a client handle.
  808. Return,
  809. }
  810. impl ValueKind {
  811. fn var_name(&self) -> Ident {
  812. let ident = match self {
  813. Self::Msg { def, .. } => def.msg_type.as_ref(),
  814. Self::State { def, .. } => def.state_trait.as_ref(),
  815. Self::Dest { def, .. } => def.state.state_ref().state_trait.as_ref(),
  816. Self::Return { .. } => return format_ident!("return_var"),
  817. };
  818. format_ident!("{}_var", ident.pascal_to_snake())
  819. }
  820. fn new_dest(def: Rc<Dest>, msg_lookup: &MsgLookup, part_of_client: bool) -> Self {
  821. let msg_info = msg_lookup.lookup(&def.msg);
  822. let msg_type = msg_info.msg_type().clone();
  823. let reply_type = msg_info.reply().map(|reply| reply.msg_type().clone());
  824. Self::Dest {
  825. def,
  826. msg_type,
  827. reply_type,
  828. part_of_client,
  829. }
  830. }
  831. fn span(&self) -> Span {
  832. match self {
  833. Self::Msg { def, .. } => def.span(),
  834. Self::State { def, .. } => def.span(),
  835. Self::Dest { def, .. } => def.span(),
  836. Self::Return { .. } => Span::call_site(),
  837. }
  838. }
  839. pub(crate) fn state_trait(&self) -> Option<&Rc<Ident>> {
  840. if let Self::State { def, .. } = self {
  841. Some(&def.state_trait)
  842. } else {
  843. None
  844. }
  845. }
  846. }
  847. /// A type used to query information about actors, states, and their relationships.
  848. pub(crate) struct ActorLookup {
  849. /// A map from an actor name to the set of states which are part of that actor.
  850. actor_states: HashMap<Rc<Ident>, HashSet<Rc<Ident>>>,
  851. #[allow(dead_code)]
  852. /// A map from a state name to the actor name which that state is a part of.
  853. actors_by_state: HashMap<Rc<Ident>, Rc<Ident>>,
  854. /// A map from an actor name to the set of actor names which spawn it.
  855. parents: HashMap<Rc<Ident>, HashSet<Rc<Ident>>>,
  856. /// A map from an actor name to the set of actors names which it spawns.
  857. children: HashMap<Rc<Ident>, HashSet<Rc<Ident>>>,
  858. /// A map from the initial state of an actor to the actor.
  859. actors_by_init_state: HashMap<Rc<Ident>, Rc<Ident>>,
  860. /// The set of actors which are service providers in this protocol.
  861. service_providers: HashSet<Rc<Ident>>,
  862. }
  863. impl ActorLookup {
  864. fn new<'a, A, T>(actor_defs: A, transitions: T) -> syn::Result<Self>
  865. where
  866. A: IntoIterator<Item = &'a ActorDef>,
  867. T: IntoIterator<Item = &'a Transition>,
  868. {
  869. // First we gather all the information we can by iterating over the actor definitions.
  870. let mut actor_states = HashMap::new();
  871. let mut actors_by_state = HashMap::new();
  872. let mut parents = HashMap::new();
  873. let mut children = HashMap::new();
  874. let mut actors_by_init_state = HashMap::new();
  875. for actor_def in actor_defs {
  876. let mut states = HashSet::new();
  877. let actor_name = &actor_def.actor;
  878. let mut first = true;
  879. for state in actor_def.states.as_ref().iter() {
  880. if first {
  881. actors_by_init_state.insert(state.clone(), actor_name.clone());
  882. first = false;
  883. }
  884. states.insert(state.clone());
  885. actors_by_state.insert(state.clone(), actor_def.actor.clone());
  886. }
  887. actor_states.insert(actor_name.clone(), states);
  888. parents.insert(actor_name.clone(), HashSet::new());
  889. children.insert(actor_name.clone(), HashSet::new());
  890. }
  891. // Then, we gather information by iterating over the transitions.
  892. let mut transitions_to = HashMap::new();
  893. let mut service_providers = HashSet::new();
  894. for transition in transitions {
  895. let in_state = &transition.in_state.state_trait;
  896. let parent = actors_by_state
  897. .get(in_state)
  898. .ok_or_else(|| syn::Error::new(in_state.span(), error::msgs::UNDECLARED_STATE))?;
  899. for (index, out_state) in transition.out_states.as_ref().iter().enumerate() {
  900. let out_state = &out_state.state_trait;
  901. transitions_to
  902. .entry(in_state.clone())
  903. .or_insert_with(HashSet::new)
  904. .insert(out_state.clone());
  905. // The first output state is skipped because the current actor is transitioning to
  906. // it, its not creating a new actor.
  907. if 0 == index {
  908. continue;
  909. }
  910. let child = actors_by_state.get(out_state).ok_or_else(|| {
  911. syn::Error::new(out_state.span(), error::msgs::UNDECLARED_STATE)
  912. })?;
  913. parents
  914. .entry(child.clone())
  915. .or_insert_with(HashSet::new)
  916. .insert(parent.clone());
  917. children
  918. .entry(parent.clone())
  919. .or_insert_with(HashSet::new)
  920. .insert(child.clone());
  921. }
  922. for dest in transition.out_msgs.as_ref().iter() {
  923. if let DestinationState::Service(service) = &dest.state {
  924. let dest_state = &service.state_trait;
  925. let actor_name = actors_by_state.get(dest_state).ok_or_else(|| {
  926. syn::Error::new(dest_state.span(), error::msgs::UNDECLARED_STATE)
  927. })?;
  928. service_providers.insert(actor_name.clone());
  929. }
  930. }
  931. }
  932. Ok(Self {
  933. actor_states,
  934. actors_by_state,
  935. parents,
  936. children,
  937. actors_by_init_state,
  938. service_providers,
  939. })
  940. }
  941. const UNKNOWN_ACTOR_ERR: &str =
  942. "Unknown actor. This indicates there is a bug in the btproto crate.";
  943. /// Returns the set of states associated with the given actor.
  944. ///
  945. /// This method **panics** if you call it with a non-existent actor name.
  946. pub(crate) fn actor_states(&self, actor_name: &Ident) -> &HashSet<Rc<Ident>> {
  947. self.actor_states
  948. .get(actor_name)
  949. .unwrap_or_else(|| panic!("actor_states: {}", Self::UNKNOWN_ACTOR_ERR))
  950. }
  951. /// Returns the name of the actor containing the given state.
  952. ///
  953. /// **Panics**, if called with an unknown state name.
  954. pub(crate) fn actor_with_state(&self, state_name: &Ident) -> &Rc<Ident> {
  955. self.actors_by_state
  956. .get(state_name)
  957. .unwrap_or_else(|| panic!("can't find state {state_name}"))
  958. }
  959. pub(crate) fn parents(&self, actor_name: &Ident) -> &HashSet<Rc<Ident>> {
  960. self.parents
  961. .get(actor_name)
  962. .unwrap_or_else(|| panic!("parents: {}", Self::UNKNOWN_ACTOR_ERR))
  963. }
  964. pub(crate) fn children(&self, actor_name: &Ident) -> &HashSet<Rc<Ident>> {
  965. self.children
  966. .get(actor_name)
  967. .unwrap_or_else(|| panic!("children: {}", Self::UNKNOWN_ACTOR_ERR))
  968. }
  969. /// Returns the name of the actor for which the given state name is the initial state. If the
  970. /// given name is not the initial state of any actor, [None] is returned.
  971. pub(crate) fn actor_with_init_state(&self, init_state: &Ident) -> Option<&Rc<Ident>> {
  972. self.actors_by_init_state.get(init_state)
  973. }
  974. }
  975. pub(crate) struct MsgLookup {
  976. messages: HashMap<Rc<Ident>, MsgInfo>,
  977. }
  978. impl MsgLookup {
  979. fn new<'a>(transitions: impl IntoIterator<Item = &'a Transition>) -> Self {
  980. let mut messages = HashMap::new();
  981. for transition in transitions.into_iter() {
  982. let in_state = &transition.in_state.state_trait;
  983. if let Some(in_msg) = transition.in_msg() {
  984. let msg_name = &in_msg.msg_type;
  985. let msg_info = messages
  986. .entry(msg_name.clone())
  987. .or_insert_with(|| MsgInfo::empty(in_msg.clone()));
  988. msg_info.record_receiver(in_msg, in_state.clone());
  989. }
  990. for dest in transition.out_msgs.as_ref().iter() {
  991. let msg = &dest.msg;
  992. let msg_info = messages
  993. .entry(msg.msg_type.clone())
  994. .or_insert_with(|| MsgInfo::empty(msg.clone()));
  995. msg_info.record_sender(&dest.msg, in_state.clone());
  996. }
  997. }
  998. Self { messages }
  999. }
  1000. pub(crate) fn lookup(&self, msg: &Message) -> &MsgInfo {
  1001. self.messages
  1002. .get(msg.msg_type.as_ref())
  1003. // Since a message is either sent or received, and we've added all such messages in
  1004. // the new method, this unwrap should not panic.
  1005. .unwrap_or_else(|| {
  1006. panic!("Failed to find message info. There is a bug in MessageLookup::new.")
  1007. })
  1008. .info_for(msg)
  1009. }
  1010. pub(crate) fn msg_iter(&self) -> impl Iterator<Item = &MsgInfo> {
  1011. self.messages
  1012. .values()
  1013. .flat_map(|msg_info| [Some(msg_info), msg_info.reply()])
  1014. .flatten()
  1015. }
  1016. }
  1017. impl AsRef<HashMap<Rc<Ident>, MsgInfo>> for MsgLookup {
  1018. fn as_ref(&self) -> &HashMap<Rc<Ident>, MsgInfo> {
  1019. &self.messages
  1020. }
  1021. }
  1022. #[cfg_attr(test, derive(Debug))]
  1023. pub(crate) struct MsgInfo {
  1024. def: Rc<Message>,
  1025. msg_name: Rc<Ident>,
  1026. msg_type: Rc<TokenStream>,
  1027. is_reply: bool,
  1028. senders: HashSet<Rc<Ident>>,
  1029. receivers: HashSet<Rc<Ident>>,
  1030. reply: Option<Box<MsgInfo>>,
  1031. }
  1032. impl MsgInfo {
  1033. fn empty(def: Rc<Message>) -> Self {
  1034. let msg_name = def.msg_type.as_ref();
  1035. Self {
  1036. msg_name: def.msg_type.clone(),
  1037. msg_type: Rc::new(quote! { #msg_name }),
  1038. is_reply: false,
  1039. senders: HashSet::new(),
  1040. receivers: HashSet::new(),
  1041. reply: None,
  1042. def,
  1043. }
  1044. }
  1045. fn info_for(&self, msg: &Message) -> &Self {
  1046. if msg.is_reply() {
  1047. // If this message is a reply, then we should have seen it in MsgLookup::new and
  1048. // initialized its reply pointer. So this unwrap shouldn't panic.
  1049. self.reply.as_ref().unwrap_or_else(|| {
  1050. panic!(
  1051. "A reply message was not properly recorded. There is a bug in MessageLookup::new."
  1052. )
  1053. })
  1054. } else {
  1055. self
  1056. }
  1057. }
  1058. fn info_for_mut(&mut self, msg: &Rc<Message>) -> &mut Self {
  1059. if msg.is_reply() {
  1060. self.reply.get_or_insert_with(|| {
  1061. let mut reply = MsgInfo::empty(msg.clone());
  1062. reply.is_reply = true;
  1063. reply.msg_name = Rc::new(format_ident!(
  1064. "{}{}",
  1065. msg.msg_type.as_ref(),
  1066. MessageReplyPart::REPLY_IDENT
  1067. ));
  1068. let parent = self.msg_name.as_ref();
  1069. reply.msg_type = Rc::new(quote! { <#parent as ::btrun::model::CallMsg>::Reply });
  1070. Box::new(reply)
  1071. })
  1072. } else {
  1073. self
  1074. }
  1075. }
  1076. fn record_receiver(&mut self, msg: &Rc<Message>, receiver: Rc<Ident>) {
  1077. let target = self.info_for_mut(msg);
  1078. target.receivers.insert(receiver);
  1079. }
  1080. fn record_sender(&mut self, msg: &Rc<Message>, sender: Rc<Ident>) {
  1081. let target = self.info_for_mut(msg);
  1082. target.senders.insert(sender);
  1083. }
  1084. pub(crate) fn def(&self) -> &Rc<Message> {
  1085. &self.def
  1086. }
  1087. /// The unique name of this message. If it is a reply, it will end in
  1088. /// `MessageReplyPart::REPLY_IDENT`.
  1089. pub(crate) fn msg_name(&self) -> &Rc<Ident> {
  1090. &self.msg_name
  1091. }
  1092. /// The type of this message. If this message is not a reply, this is just `msg_name`. If it is
  1093. /// a reply, it is `<#msg_name as ::btrun::model::CallMsg>::Reply`.
  1094. pub(crate) fn msg_type(&self) -> &Rc<TokenStream> {
  1095. &self.msg_type
  1096. }
  1097. pub(crate) fn reply(&self) -> Option<&MsgInfo> {
  1098. self.reply.as_ref().map(|ptr| ptr.as_ref())
  1099. }
  1100. pub(crate) fn is_reply(&self) -> bool {
  1101. self.is_reply
  1102. }
  1103. /// Returns true iff this message is a call.
  1104. pub(crate) fn is_call(&self) -> bool {
  1105. self.reply.is_some()
  1106. }
  1107. }
  1108. impl PartialEq for MsgInfo {
  1109. fn eq(&self, other: &Self) -> bool {
  1110. self.msg_name.as_ref() == other.msg_name.as_ref()
  1111. }
  1112. }
  1113. impl Eq for MsgInfo {}
  1114. impl Hash for MsgInfo {
  1115. fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
  1116. self.msg_name.hash(state)
  1117. }
  1118. }
  1119. #[cfg(test)]
  1120. mod tests {
  1121. use crate::{
  1122. error::{assert_err, assert_ok},
  1123. parsing::{DestinationState, NameDef},
  1124. };
  1125. use super::*;
  1126. #[test]
  1127. fn protocol_model_new_minimal_ok() {
  1128. let input = Protocol::minimal();
  1129. let result = ProtocolModel::new(input);
  1130. assert_ok(result);
  1131. }
  1132. #[test]
  1133. fn protocol_model_new_dup_recv_transition_err() {
  1134. let input = Protocol::new(
  1135. NameDef::new("Undeclared"),
  1136. [ActorDef::new("actor", ["Init", "Next"])],
  1137. [
  1138. Transition::new(
  1139. State::new("Init", []),
  1140. Some(Message::new("Query", false, [])),
  1141. [State::new("Next", [])],
  1142. [],
  1143. ),
  1144. Transition::new(
  1145. State::new("Init", []),
  1146. Some(Message::new("Query", false, [])),
  1147. [State::new("Init", [])],
  1148. [],
  1149. ),
  1150. ],
  1151. );
  1152. let result = ProtocolModel::new(input);
  1153. assert_err(result, error::msgs::DUPLICATE_TRANSITION);
  1154. }
  1155. #[test]
  1156. fn protocol_model_new_dup_send_transition_err() {
  1157. let input = Protocol::new(
  1158. NameDef::new("Undeclared"),
  1159. [
  1160. ActorDef::new("server", ["Init", "Next"]),
  1161. ActorDef::new("client", ["Client"]),
  1162. ],
  1163. [
  1164. Transition::new(
  1165. State::new("Client", []),
  1166. None,
  1167. [State::new("Client", [])],
  1168. [Dest::new(
  1169. DestinationState::Individual(State::new("Init", [])),
  1170. Message::new("Query", false, []),
  1171. )],
  1172. ),
  1173. Transition::new(
  1174. State::new("Client", []),
  1175. None,
  1176. [State::new("Client", [])],
  1177. [Dest::new(
  1178. DestinationState::Individual(State::new("Next", [])),
  1179. Message::new("Query", false, []),
  1180. )],
  1181. ),
  1182. ],
  1183. );
  1184. let result = ProtocolModel::new(input);
  1185. assert_err(result, error::msgs::DUPLICATE_TRANSITION);
  1186. }
  1187. #[test]
  1188. fn msg_sent_or_received_msg_received_ok() {
  1189. let input = Protocol::new(
  1190. NameDef::new("Test"),
  1191. [ActorDef::new("actor", ["Init"])],
  1192. [Transition::new(
  1193. State::new("Init", []),
  1194. Some(Message::new("Activate", false, [])),
  1195. [State::new("End", [])],
  1196. [],
  1197. )],
  1198. );
  1199. let result = ProtocolModel::new(input);
  1200. assert_ok(result);
  1201. }
  1202. #[test]
  1203. fn msg_sent_or_received_msg_sent_ok() {
  1204. let input = Protocol::new(
  1205. NameDef::new("Test"),
  1206. [ActorDef::new("actor", ["First", "Second"])],
  1207. [Transition::new(
  1208. State::new("First", []),
  1209. None,
  1210. [State::new("First", [])],
  1211. [Dest::new(
  1212. DestinationState::Individual(State::new("Second", [])),
  1213. Message::new("Msg", false, []),
  1214. )],
  1215. )],
  1216. );
  1217. let result = ProtocolModel::new(input);
  1218. assert_ok(result);
  1219. }
  1220. #[test]
  1221. fn msg_sent_or_received_neither_err() {
  1222. let input = Protocol::new(
  1223. NameDef::new("Test"),
  1224. [ActorDef::new("actor", ["First"])],
  1225. [Transition::new(
  1226. State::new("First", []),
  1227. None,
  1228. [State::new("First", [])],
  1229. [],
  1230. )],
  1231. );
  1232. let result = ProtocolModel::new(input);
  1233. assert_err(result, error::msgs::NO_MSG_SENT_OR_RECEIVED);
  1234. }
  1235. #[test]
  1236. fn reply_is_marked_in_output() {
  1237. const MSG: &str = "Ping";
  1238. let msg_ident = format_ident!("{MSG}");
  1239. let expected = quote! { < #msg_ident as :: btrun :: model :: CallMsg > :: Reply };
  1240. let input = Protocol::new(
  1241. NameDef::new("ReplyTest"),
  1242. [
  1243. ActorDef::new("server", ["Listening"]),
  1244. ActorDef::new("client", ["Client", "Waiting"]),
  1245. ],
  1246. [
  1247. Transition::new(
  1248. State::new("Client", []),
  1249. None,
  1250. [State::new("Waiting", [])],
  1251. [Dest::new(
  1252. DestinationState::Service(State::new("Listening", [])),
  1253. Message::new(MSG, false, []),
  1254. )],
  1255. ),
  1256. Transition::new(
  1257. State::new("Listening", []),
  1258. Some(Message::new(MSG, false, [])),
  1259. [State::new("Listening", [])],
  1260. [Dest::new(
  1261. DestinationState::Individual(State::new("Client", [])),
  1262. Message::new(MSG, true, []),
  1263. )],
  1264. ),
  1265. ],
  1266. );
  1267. let actual = ProtocolModel::new(input).unwrap();
  1268. let mut msg_types = actual.outputs_iter().flat_map(|output| {
  1269. if let ValueKind::Dest { msg_type, .. } = &output.kind {
  1270. Some(msg_type)
  1271. } else {
  1272. None
  1273. }
  1274. });
  1275. let msg_type = msg_types.next().unwrap();
  1276. assert!(msg_types.next().is_none());
  1277. assert_eq!(expected.to_string(), msg_type.to_string());
  1278. }
  1279. fn simple_client_server_proto() -> Protocol {
  1280. Protocol::new(
  1281. NameDef::new("IsClientTest"),
  1282. [
  1283. ActorDef::new("server", ["Server"]),
  1284. ActorDef::new("client", ["Client"]),
  1285. ],
  1286. [
  1287. Transition::new(
  1288. State::new("Client", []),
  1289. None,
  1290. [State::new("End", [])],
  1291. [Dest::new(
  1292. DestinationState::Service(State::new("Server", [])),
  1293. Message::new("Msg", false, []),
  1294. )],
  1295. ),
  1296. Transition::new(
  1297. State::new("Server", []),
  1298. Some(Message::new("Msg", false, [])),
  1299. [State::new("End", [])],
  1300. [],
  1301. ),
  1302. ],
  1303. )
  1304. }
  1305. #[test]
  1306. fn is_client_false_for_server() {
  1307. let input = simple_client_server_proto();
  1308. let actual = ProtocolModel::new(input).unwrap();
  1309. let server = actual.actors.get(&format_ident!("server")).unwrap();
  1310. assert!(!server.kind().is_client());
  1311. }
  1312. #[test]
  1313. fn is_client_true_for_client() {
  1314. let input = simple_client_server_proto();
  1315. let actual = ProtocolModel::new(input).unwrap();
  1316. let client = actual.actors.get(&format_ident!("client")).unwrap();
  1317. assert!(client.kind().is_client());
  1318. }
  1319. #[test]
  1320. fn is_client_false_for_worker() {
  1321. let input = Protocol::new(
  1322. NameDef::new("IsClientTest"),
  1323. [
  1324. ActorDef::new("server", ["Listening"]),
  1325. ActorDef::new("worker", ["Working"]),
  1326. ActorDef::new("client", ["Unregistered", "Registered"]),
  1327. ],
  1328. [
  1329. Transition::new(
  1330. State::new("Unregistered", []),
  1331. None,
  1332. [State::new("Registered", [])],
  1333. [Dest::new(
  1334. DestinationState::Service(State::new("Listening", [])),
  1335. Message::new("Register", false, ["Registered"]),
  1336. )],
  1337. ),
  1338. Transition::new(
  1339. State::new("Listening", []),
  1340. Some(Message::new("Register", false, ["Registered"])),
  1341. [
  1342. State::new("Listening", []),
  1343. State::new("Working", ["Registered"]),
  1344. ],
  1345. [],
  1346. ),
  1347. Transition::new(
  1348. State::new("Working", ["Registered"]),
  1349. None,
  1350. [State::new("End", [])],
  1351. [Dest::new(
  1352. DestinationState::Individual(State::new("Registered", [])),
  1353. Message::new("Completed", false, []),
  1354. )],
  1355. ),
  1356. Transition::new(
  1357. State::new("Registered", []),
  1358. Some(Message::new("Completed", false, [])),
  1359. [State::new("End", [])],
  1360. [],
  1361. ),
  1362. ],
  1363. );
  1364. let actual = ProtocolModel::new(input).unwrap();
  1365. let worker = actual.actors.get(&format_ident!("worker")).unwrap();
  1366. assert!(!worker.kind().is_client());
  1367. }
  1368. }