@@ -124,7 +124,33 @@ impl From<Alarm> for RpcValue {
124124 }
125125}
126126
127+ trait AlarmGetter {
128+ fn alarm_getter ( f : & impl FieldDescriptionMethods ) -> Option < & str > ;
129+ }
130+
131+ struct CommonAlarm ;
132+ impl AlarmGetter for CommonAlarm {
133+ fn alarm_getter ( f : & impl FieldDescriptionMethods ) -> Option < & str > {
134+ f. alarm ( )
135+ }
136+ }
137+
138+ struct StateAlarm ;
139+ impl AlarmGetter for StateAlarm {
140+ fn alarm_getter ( f : & impl FieldDescriptionMethods ) -> Option < & str > {
141+ f. state_alarm ( )
142+ }
143+ }
144+
127145pub fn collect_alarms ( type_info : & TypeInfo , shv_path : impl AsRef < str > , value : & RpcValue ) -> Vec < Alarm > {
146+ impl_collect_alarms :: < CommonAlarm > ( type_info, shv_path, value)
147+ }
148+
149+ pub fn collect_state_alarms ( type_info : & TypeInfo , shv_path : impl AsRef < str > , value : & RpcValue ) -> Vec < Alarm > {
150+ impl_collect_alarms :: < StateAlarm > ( type_info, shv_path, value)
151+ }
152+
153+ fn impl_collect_alarms < Getter : AlarmGetter > ( type_info : & TypeInfo , shv_path : impl AsRef < str > , value : & RpcValue ) -> Vec < Alarm > {
128154 if value. is_null ( ) {
129155 // value not available, keep previous alarms active
130156 return vec ! [ ] ;
@@ -136,7 +162,7 @@ pub fn collect_alarms(type_info: &TypeInfo, shv_path: impl AsRef<str>, value: &R
136162 return vec ! [ ] ;
137163 }
138164
139- if let Some ( alarm) = property_description . alarm ( ) && !alarm. is_empty ( ) {
165+ if let Some ( alarm) = Getter :: alarm_getter ( & property_description ) && !alarm. is_empty ( ) {
140166 vec ! [
141167 Alarm {
142168 path: shv_path. into( ) ,
@@ -148,11 +174,11 @@ pub fn collect_alarms(type_info: &TypeInfo, shv_path: impl AsRef<str>, value: &R
148174 }
149175 ]
150176 } else {
151- collect_alarms_for_type ( type_info, shv_path, property_description. type_name ( ) . unwrap_or_default ( ) , value)
177+ collect_alarms_for_type :: < Getter > ( type_info, shv_path, property_description. type_name ( ) . unwrap_or_default ( ) , value)
152178 }
153179}
154180
155- fn collect_alarms_for_type ( type_info : & TypeInfo , shv_path : impl AsRef < str > , type_name : impl AsRef < str > , value : & RpcValue ) -> Vec < Alarm > {
181+ fn collect_alarms_for_type < Getter : AlarmGetter > ( type_info : & TypeInfo , shv_path : impl AsRef < str > , type_name : impl AsRef < str > , value : & RpcValue ) -> Vec < Alarm > {
156182 let Some ( type_descr) = type_info. find_type_description ( type_name) . filter ( |descr| descr. is_valid ( ) ) else {
157183 return vec ! [ ]
158184 } ;
@@ -164,7 +190,7 @@ fn collect_alarms_for_type(type_info: &TypeInfo, shv_path: impl AsRef<str>, type
164190 . flat_map ( |fld_descr| {
165191 let sub_path = format ! ( "{shv_path}/{fld_descr_name}" , fld_descr_name = fld_descr. name( ) ) ;
166192 let bitfield_value = fld_descr. bitfield_value ( value. as_u64 ( ) ) ;
167- if let Some ( alarm) = fld_descr . alarm ( ) . filter ( |alarm| !alarm. is_empty ( ) ) {
193+ if let Some ( alarm) = Getter :: alarm_getter ( fld_descr ) . filter ( |alarm| !alarm. is_empty ( ) ) {
168194 vec ! [
169195 Alarm {
170196 path: sub_path,
@@ -176,7 +202,7 @@ fn collect_alarms_for_type(type_info: &TypeInfo, shv_path: impl AsRef<str>, type
176202 }
177203 ]
178204 } else {
179- collect_alarms_for_type (
205+ collect_alarms_for_type :: < Getter > (
180206 type_info,
181207 sub_path,
182208 fld_descr. type_name ( ) . unwrap_or_default ( ) ,
@@ -191,17 +217,16 @@ fn collect_alarms_for_type(type_info: &TypeInfo, shv_path: impl AsRef<str>, type
191217
192218 let has_alarm_definition = fields
193219 . iter ( )
194- . any ( |field| field
195- . alarm ( )
220+ . any ( |field| Getter :: alarm_getter ( field)
196221 . is_some_and ( |f| !f. is_empty ( ) )
197222 ) ;
198223 if !has_alarm_definition {
199224 return vec ! [ ] ;
200225 }
201226
202227 let active_alarm_field = fields
203- . iter ( )
204- . find ( |field| field . alarm ( ) . is_some_and ( |alarm| !alarm. is_empty ( ) )
228+ . into_iter ( )
229+ . find ( |field| Getter :: alarm_getter ( field ) . is_some_and ( |alarm| !alarm. is_empty ( ) )
205230 && field. bit_range ( ) . is_some_and ( |bit_range| bit_range. as_u64 ( ) == value. as_u64 ( ) ) ) ;
206231 match active_alarm_field {
207232 Some ( field) => vec ! [
@@ -211,7 +236,7 @@ fn collect_alarms_for_type(type_info: &TypeInfo, shv_path: impl AsRef<str>, type
211236 description: field. description( ) . unwrap_or_default( ) . into( ) ,
212237 label: field. label( ) . unwrap_or_default( ) . into( ) ,
213238 level: field. alarm_level( ) . unwrap_or_default( ) ,
214- severity: field . alarm ( ) . unwrap_or_default( ) . into( ) ,
239+ severity: Getter :: alarm_getter ( & field ) . unwrap_or_default( ) . into( ) ,
215240 }
216241 ] ,
217242 None => vec ! [
0 commit comments