wowlab_engine_domain/rotation/condition/
resolve.rs1#[cfg(test)]
4use wowlab_types::sim::Condition;
5use wowlab_types::{
6 combat::ResourceType,
7 sim::{AuraIdx, AuraOn, FieldRead, SpellIdx},
8};
9
10use super::{
11 super::{
12 buffer::{DescriptorId, DescriptorTable, SlotKind},
13 resolver::SpecResolver,
14 },
15 KeyCategory,
16};
17
18#[derive(Clone, Debug, PartialEq)]
20pub struct ResolvedFieldRead {
21 pub descriptor_id: DescriptorId,
22 pub key: Option<ResolvedKey>,
23 pub on: Option<AuraOn>,
24}
25
26#[derive(Clone, Debug, PartialEq)]
28#[non_exhaustive]
29pub enum ResolvedKey {
30 Spell(SpellIdx),
31 Aura(AuraIdx),
32 Resource(ResourceType),
33 Named(String),
34}
35
36pub(crate) fn resolve_field_read(
37 field: &FieldRead,
38 table: &DescriptorTable,
39 resolver: &SpecResolver,
40) -> super::super::error::Result<ResolvedFieldRead> {
41 let (descriptor_id, descriptor) = table
42 .lookup(&field.domain, &field.name)
43 .ok_or_else(|| super::super::error::Error::unknown_field(&field.domain, &field.name))?;
44
45 match descriptor.slot_kind {
46 SlotKind::Keyed if field.key.is_none() => {
47 return Err(super::super::error::Error::missing_key(
48 &field.domain,
49 &field.name,
50 ));
51 }
52 SlotKind::Singleton if field.key.is_some() => {
53 return Err(super::super::error::Error::unexpected_key(
54 &field.domain,
55 &field.name,
56 ));
57 }
58 _ => {}
59 }
60
61 let key = if let Some(key_str) = &field.key {
62 Some(resolve_key(&field.domain, key_str, resolver)?)
63 } else {
64 None
65 };
66
67 Ok(ResolvedFieldRead {
68 descriptor_id,
69 key,
70 on: field.on,
71 })
72}
73
74fn resolve_key(
75 domain: &str,
76 key: &str,
77 resolver: &SpecResolver,
78) -> super::super::error::Result<ResolvedKey> {
79 match KeyCategory::for_domain(domain) {
80 Some(KeyCategory::Spell) => Ok(ResolvedKey::Spell(resolver.resolve_spell(key)?)),
81 Some(KeyCategory::Aura) => Ok(ResolvedKey::Aura(resolver.resolve_aura(key)?)),
82 Some(KeyCategory::Resource) => {
83 let rt = key
84 .parse()
85 .ok()
86 .ok_or_else(|| super::super::error::Error::unknown_resource(key))?;
87
88 Ok(ResolvedKey::Resource(rt))
89 }
90 Some(KeyCategory::Named) => Ok(ResolvedKey::Named(key.to_string())),
91 None => Err(super::super::error::Error::unknown_domain(domain)),
92 }
93}
94
95#[cfg(test)]
96pub(crate) fn validate_condition(condition: &Condition, table: &DescriptorTable) -> Vec<String> {
97 let mut errors = Vec::new();
98
99 condition.walk(&mut |node| {
100 if let Condition::Read { field } = node {
101 if table.lookup(&field.domain, &field.name).is_none() {
102 errors.push(format!("unknown field: {}.{}", field.domain, field.name));
104 }
105 }
106 });
107
108 errors
109}