Skip to main content

frequenz_microgrid/
bounds.rs

1// License: MIT
2// Copyright © 2026 Frequenz Energy-as-a-Service GmbH
3
4//! A representation of Bounds for any metric.
5
6use crate::proto::common::metrics::Bounds as PbBounds;
7use crate::quantity::{Current, Power, Quantity, ReactivePower};
8
9/// A set of lower and upper bounds for any metric.
10pub struct Bounds<Q: Quantity> {
11    /// The lower bound.
12    /// If None, there is no lower bound.
13    lower: Option<Q>,
14    /// The upper bound.
15    /// If None, there is no upper bound.
16    upper: Option<Q>,
17}
18
19impl<Q: Quantity> Bounds<Q> {
20    /// Creates a new `Bounds` with the given lower and upper bounds.
21    pub fn new(lower: Option<Q>, upper: Option<Q>) -> Self {
22        Self { lower, upper }
23    }
24
25    /// Returns the lower bound.
26    pub fn lower(&self) -> Option<Q> {
27        self.lower
28    }
29
30    /// Returns the upper bound.
31    pub fn upper(&self) -> Option<Q> {
32        self.upper
33    }
34}
35
36impl<Q: Quantity> From<(Option<Q>, Option<Q>)> for Bounds<Q> {
37    fn from(bounds: (Option<Q>, Option<Q>)) -> Self {
38        Self::new(bounds.0, bounds.1)
39    }
40}
41
42impl From<Bounds<Power>> for PbBounds {
43    fn from(bounds: Bounds<Power>) -> Self {
44        PbBounds {
45            lower: bounds.lower.map(|q| q.as_watts()),
46            upper: bounds.upper.map(|q| q.as_watts()),
47        }
48    }
49}
50
51impl From<Bounds<Current>> for PbBounds {
52    fn from(bounds: Bounds<Current>) -> Self {
53        PbBounds {
54            lower: bounds.lower.map(|q| q.as_amperes()),
55            upper: bounds.upper.map(|q| q.as_amperes()),
56        }
57    }
58}
59
60impl From<Bounds<ReactivePower>> for PbBounds {
61    fn from(bounds: Bounds<ReactivePower>) -> Self {
62        PbBounds {
63            lower: bounds.lower.map(|q| q.as_volt_amperes_reactive()),
64            upper: bounds.upper.map(|q| q.as_volt_amperes_reactive()),
65        }
66    }
67}