1+ use super :: error:: AccumulatorError ;
12use crate :: data_model:: {
23 AggregateCore , AggregationType , MergeableAccumulator , SerializableToSink ,
34 SingleSubpopulationAggregate , SingleSubpopulationAggregateFactory ,
@@ -29,19 +30,19 @@ impl MinMaxAccumulator {
2930 }
3031 }
3132
32- pub fn new ( sub_type : String ) -> Self {
33+ pub fn new ( sub_type : String ) -> Result < Self , AccumulatorError > {
3334 match sub_type. as_str ( ) {
34- "min" => Self :: new_min ( ) ,
35- "max" => Self :: new_max ( ) ,
36- _ => panic ! ( " sub_type must be 'min' or 'max'" ) ,
35+ "min" => Ok ( Self :: new_min ( ) ) ,
36+ "max" => Ok ( Self :: new_max ( ) ) ,
37+ _ => Err ( AccumulatorError :: InvalidSubType ( sub_type) ) ,
3738 }
3839 }
3940
40- pub fn with_value ( value : f64 , sub_type : String ) -> Self {
41+ pub fn with_value ( value : f64 , sub_type : String ) -> Result < Self , AccumulatorError > {
4142 if sub_type != "min" && sub_type != "max" {
42- panic ! ( " sub_type must be 'min' or 'max'" ) ;
43+ return Err ( AccumulatorError :: InvalidSubType ( sub_type) ) ;
4344 }
44- Self { value, sub_type }
45+ Ok ( Self { value, sub_type } )
4546 }
4647
4748 pub fn update ( & mut self , value : f64 ) {
@@ -56,7 +57,7 @@ impl MinMaxAccumulator {
5657 self . value = value;
5758 }
5859 }
59- _ => panic ! ( "Invalid sub_type" ) ,
60+ _ => unreachable ! ( "MinMaxAccumulator sub_type is always 'min' or 'max' " ) ,
6061 }
6162 }
6263
@@ -73,7 +74,7 @@ impl MinMaxAccumulator {
7374 return Err ( "sub_type must be 'min' or 'max'" . into ( ) ) ;
7475 }
7576
76- Ok ( Self :: with_value ( value, sub_type) )
77+ Ok ( Self :: with_value ( value, sub_type) ? )
7778 }
7879
7980 pub fn deserialize_from_bytes ( buffer : & [ u8 ] ) -> Result < Self , Box < dyn std:: error:: Error > > {
@@ -91,7 +92,7 @@ impl MinMaxAccumulator {
9192 _ => return Err ( "Invalid sub_type byte" . into ( ) ) ,
9293 } ;
9394
94- Ok ( Self :: with_value ( value, sub_type) )
95+ Ok ( Self :: with_value ( value, sub_type) ? )
9596 }
9697}
9798
@@ -108,7 +109,7 @@ impl SerializableToSink for MinMaxAccumulator {
108109 let sub_type_byte = match self . sub_type . as_str ( ) {
109110 "min" => 0u8 ,
110111 "max" => 1u8 ,
111- _ => panic ! ( "Invalid sub_type" ) ,
112+ _ => unreachable ! ( "MinMaxAccumulator sub_type is always 'min' or 'max' " ) ,
112113 } ;
113114 bytes. push ( sub_type_byte) ;
114115 bytes
@@ -120,19 +121,23 @@ impl MergeableAccumulator<MinMaxAccumulator> for MinMaxAccumulator {
120121 accumulators : Vec < MinMaxAccumulator > ,
121122 ) -> Result < MinMaxAccumulator , Box < dyn std:: error:: Error + Send + Sync > > {
122123 if accumulators. is_empty ( ) {
123- return Err ( "No accumulators to merge" . into ( ) ) ;
124+ return Err ( AccumulatorError :: EmptySlice . into ( ) ) ;
124125 }
125126
126127 let sub_type = & accumulators[ 0 ] . sub_type ;
127128
128129 // Verify all accumulators have the same sub_type
129130 for acc in & accumulators {
130131 if acc. sub_type != * sub_type {
131- return Err ( "Cannot merge accumulators with different sub_types" . into ( ) ) ;
132+ return Err ( AccumulatorError :: MergeTypeMismatch {
133+ expected : sub_type. clone ( ) ,
134+ got : acc. sub_type . clone ( ) ,
135+ }
136+ . into ( ) ) ;
132137 }
133138 }
134139
135- let mut result = MinMaxAccumulator :: new ( sub_type. clone ( ) ) ;
140+ let mut result = MinMaxAccumulator :: new ( sub_type. clone ( ) ) ? ;
136141
137142 for acc in accumulators {
138143 result. update ( acc. value ) ;
@@ -282,7 +287,7 @@ impl SingleSubpopulationAggregateFactory for MinMaxAccumulatorFactory {
282287 Ok ( Box :: new ( MinMaxAccumulator :: with_value (
283288 result_value,
284289 self . sub_type . clone ( ) ,
285- ) ) )
290+ ) ? ) )
286291 }
287292
288293 fn create_default ( & self ) -> Box < dyn SingleSubpopulationAggregate > {
@@ -330,9 +335,9 @@ mod tests {
330335
331336 #[ test]
332337 fn test_merge_min_accumulators ( ) {
333- let acc1 = MinMaxAccumulator :: with_value ( 10.0 , "min" . to_string ( ) ) ;
334- let acc2 = MinMaxAccumulator :: with_value ( 5.0 , "min" . to_string ( ) ) ;
335- let acc3 = MinMaxAccumulator :: with_value ( 15.0 , "min" . to_string ( ) ) ;
338+ let acc1 = MinMaxAccumulator :: with_value ( 10.0 , "min" . to_string ( ) ) . unwrap ( ) ;
339+ let acc2 = MinMaxAccumulator :: with_value ( 5.0 , "min" . to_string ( ) ) . unwrap ( ) ;
340+ let acc3 = MinMaxAccumulator :: with_value ( 15.0 , "min" . to_string ( ) ) . unwrap ( ) ;
336341
337342 let merged =
338343 <MinMaxAccumulator as MergeableAccumulator < MinMaxAccumulator > >:: merge_accumulators (
@@ -345,9 +350,9 @@ mod tests {
345350
346351 #[ test]
347352 fn test_merge_max_accumulators ( ) {
348- let acc1 = MinMaxAccumulator :: with_value ( 10.0 , "max" . to_string ( ) ) ;
349- let acc2 = MinMaxAccumulator :: with_value ( 5.0 , "max" . to_string ( ) ) ;
350- let acc3 = MinMaxAccumulator :: with_value ( 15.0 , "max" . to_string ( ) ) ;
353+ let acc1 = MinMaxAccumulator :: with_value ( 10.0 , "max" . to_string ( ) ) . unwrap ( ) ;
354+ let acc2 = MinMaxAccumulator :: with_value ( 5.0 , "max" . to_string ( ) ) . unwrap ( ) ;
355+ let acc3 = MinMaxAccumulator :: with_value ( 15.0 , "max" . to_string ( ) ) . unwrap ( ) ;
351356
352357 let merged =
353358 <MinMaxAccumulator as MergeableAccumulator < MinMaxAccumulator > >:: merge_accumulators (
@@ -360,8 +365,8 @@ mod tests {
360365
361366 #[ test]
362367 fn test_merge_different_types_error ( ) {
363- let acc1 = MinMaxAccumulator :: with_value ( 10.0 , "min" . to_string ( ) ) ;
364- let acc2 = MinMaxAccumulator :: with_value ( 5.0 , "max" . to_string ( ) ) ;
368+ let acc1 = MinMaxAccumulator :: with_value ( 10.0 , "min" . to_string ( ) ) . unwrap ( ) ;
369+ let acc2 = MinMaxAccumulator :: with_value ( 5.0 , "max" . to_string ( ) ) . unwrap ( ) ;
365370
366371 assert ! (
367372 <MinMaxAccumulator as MergeableAccumulator <MinMaxAccumulator >>:: merge_accumulators(
@@ -373,7 +378,7 @@ mod tests {
373378
374379 #[ test]
375380 fn test_serialization ( ) {
376- let acc = MinMaxAccumulator :: with_value ( 42.5 , "min" . to_string ( ) ) ;
381+ let acc = MinMaxAccumulator :: with_value ( 42.5 , "min" . to_string ( ) ) . unwrap ( ) ;
377382
378383 // Test JSON serialization
379384 let json = acc. serialize_to_json ( ) ;
@@ -391,10 +396,22 @@ mod tests {
391396 #[ test]
392397 fn test_single_subpopulation_aggregate_trait ( ) {
393398 let acc: Box < dyn SingleSubpopulationAggregate > =
394- Box :: new ( MinMaxAccumulator :: with_value ( 42.0 , "max" . to_string ( ) ) ) ;
399+ Box :: new ( MinMaxAccumulator :: with_value ( 42.0 , "max" . to_string ( ) ) . unwrap ( ) ) ;
395400
396401 assert_eq ! ( acc. query( Statistic :: Max , None ) . unwrap( ) , 42.0 ) ;
397402 assert ! ( acc. query( Statistic :: Min , None ) . is_err( ) ) ;
398403 assert_eq ! ( acc. type_name( ) , "MinMaxAccumulator" ) ;
399404 }
405+
406+ #[ test]
407+ fn test_new_invalid_sub_type ( ) {
408+ let err = MinMaxAccumulator :: new ( "mean" . to_string ( ) ) . unwrap_err ( ) ;
409+ assert ! ( matches!( err, AccumulatorError :: InvalidSubType ( s) if s == "mean" ) ) ;
410+ }
411+
412+ #[ test]
413+ fn test_with_value_invalid_sub_type ( ) {
414+ let err = MinMaxAccumulator :: with_value ( 1.0 , "sum" . to_string ( ) ) . unwrap_err ( ) ;
415+ assert ! ( matches!( err, AccumulatorError :: InvalidSubType ( s) if s == "sum" ) ) ;
416+ }
400417}
0 commit comments