use super::funejson::Value; /// Units a meter advanced between two reads. A closing read lower than the /// opening read means the register rolled over past all nines, once. /// /// # Panics /// Panics if `digits` is outside 1 to 15, or a read does not fit the register. pub fn meter_advance(opening_read: i64, closing_read: i64, digits: i64) -> i64 { if !(1..=15).contains(&digits) { panic!("digits must be a whole number from 1 to 15, received {}", digits); } let span = 10_i64.pow(digits as u32); for read in [opening_read, closing_read] { if read < 0 || read >= span { panic!( "reads must be whole numbers from 0 to {} for a {}-digit meter, received {}", span - 1, digits, read ); } } if closing_read >= opening_read { closing_read - opening_read } else { closing_read + span - opening_read } } pub fn fune_vector(args: &[Value]) -> Value { for arg in &args[0..2] { if let Value::Float(f) = arg { panic!("reads must be whole numbers, received {}", f); } } Value::Int(meter_advance(args[0].as_i64(), args[1].as_i64(), args[2].as_i64())) }