Skip to content

Commit 0582bdf

Browse files
committed
feat: Add support for math ops
1 parent f9dd2c9 commit 0582bdf

File tree

5 files changed

+243
-32
lines changed

5 files changed

+243
-32
lines changed

crates/stackable-operator/src/quantity/cpu.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use std::{ops::Deref, str::FromStr};
33
use k8s_openapi::apimachinery::pkg::api::resource::Quantity as K8sQuantity;
44

55
use crate::quantity::{
6-
macros::forward_from_impls, DecimalByteMultiple, ParseQuantityError, Quantity, Suffix,
6+
macros::{forward_from_impls, forward_op_impls},
7+
DecimalByteMultiple, ParseQuantityError, Quantity, Suffix,
78
};
89

910
#[derive(Clone, Debug, PartialEq)]
@@ -27,6 +28,16 @@ impl FromStr for CpuQuantity {
2728
}
2829

2930
forward_from_impls!(Quantity, K8sQuantity, CpuQuantity);
31+
forward_op_impls!(
32+
CpuQuantity(Quantity {
33+
value: 0.0,
34+
suffix: None,
35+
}),
36+
CpuQuantity,
37+
usize,
38+
f32,
39+
f64
40+
);
3041

3142
impl CpuQuantity {
3243
pub fn from_millis(value: u32) -> Self {
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
/// This macro is intended to be used to implement the From and TryFrom traits on specialized
2+
/// quantities.
3+
///
4+
/// Currently two specialized quantities exist: [`MemoryQuantity`][1] and [`CpuQuantity`][2].
5+
/// The traits are implemented by forwarding to the inner [`Quantity`][3] implementation. Both
6+
/// specialized quantities are just newtypes / wrappers around [`Quantity`][3].
7+
///
8+
/// [1]: super::MemoryQuantity
9+
/// [2]: super::CpuQuantity
10+
/// [3]: super::Quantity
11+
macro_rules! forward_from_impls {
12+
($q:ty, $kq:ty, $for:ty) => {
13+
impl From<$q> for $for {
14+
fn from(quantity: $q) -> Self {
15+
Self(quantity)
16+
}
17+
}
18+
19+
impl TryFrom<$kq> for $for {
20+
type Error = ParseQuantityError;
21+
22+
fn try_from(value: $kq) -> Result<Self, Self::Error> {
23+
Ok(Self(Quantity::try_from(value)?))
24+
}
25+
}
26+
27+
impl TryFrom<&$kq> for $for {
28+
type Error = ParseQuantityError;
29+
30+
fn try_from(value: &$kq) -> Result<Self, Self::Error> {
31+
Ok(Self(Quantity::try_from(value)?))
32+
}
33+
}
34+
};
35+
}
36+
37+
macro_rules! forward_op_impls {
38+
($acc:expr, $for:ty, $($on:ty),+) => {
39+
impl ::std::ops::Add for $for {
40+
type Output = $for;
41+
42+
fn add(self, rhs: $for) -> Self::Output {
43+
Self(self.0 + rhs.0)
44+
}
45+
}
46+
47+
impl ::std::ops::AddAssign for $for {
48+
fn add_assign(&mut self, rhs: $for) {
49+
self.0 += rhs.0
50+
}
51+
}
52+
53+
impl ::std::ops::Sub for $for {
54+
type Output = $for;
55+
56+
fn sub(self, rhs: $for) -> Self::Output {
57+
Self(self.0 - rhs.0)
58+
}
59+
}
60+
61+
impl ::std::ops::SubAssign for $for {
62+
fn sub_assign(&mut self, rhs: $for) {
63+
self.0 -= rhs.0
64+
}
65+
}
66+
67+
impl ::std::ops::Div for $for {
68+
type Output = f64;
69+
70+
fn div(self, rhs: $for) -> Self::Output {
71+
self.0 / rhs.0
72+
}
73+
}
74+
75+
impl ::std::iter::Sum for $for {
76+
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
77+
iter.fold(
78+
$acc,
79+
<$for as ::std::ops::Add>::add,
80+
)
81+
}
82+
}
83+
84+
$(
85+
impl ::std::ops::Mul<$on> for $for {
86+
type Output = $for;
87+
88+
fn mul(self, rhs: $on) -> Self::Output {
89+
Self(self.0 * rhs)
90+
}
91+
}
92+
93+
impl ::std::ops::MulAssign<$on> for $for {
94+
fn mul_assign(&mut self, rhs: $on) {
95+
self.0 *= rhs
96+
}
97+
}
98+
)*
99+
};
100+
}
101+
102+
/// HACK: Make the macros only available in this crate.
103+
pub(crate) use forward_from_impls;
104+
pub(crate) use forward_op_impls;

crates/stackable-operator/src/quantity/memory.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ use std::{ops::Deref, str::FromStr};
33
use k8s_openapi::apimachinery::pkg::api::resource::Quantity as K8sQuantity;
44

55
use crate::quantity::{
6-
macros::forward_from_impls, BinaryByteMultiple, ParseQuantityError, Quantity, Suffix,
6+
macros::{forward_from_impls, forward_op_impls},
7+
BinaryByteMultiple, ParseQuantityError, Quantity, Suffix,
78
};
89

910
pub trait JavaHeap {
@@ -35,6 +36,18 @@ impl FromStr for MemoryQuantity {
3536
}
3637

3738
forward_from_impls!(Quantity, K8sQuantity, MemoryQuantity);
39+
forward_op_impls!(
40+
MemoryQuantity(Quantity {
41+
value: 0.0,
42+
// TODO (@Techassi): This needs to be talked about. The previous implementation used Kibi
43+
// here. Code which relies on that fact (for later scaling) will thus break.
44+
suffix: None,
45+
}),
46+
MemoryQuantity,
47+
usize,
48+
f32,
49+
f64
50+
);
3851

3952
impl MemoryQuantity {
4053
pub const fn from_gibi(value: f64) -> Self {

crates/stackable-operator/src/quantity/mod.rs

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ use k8s_openapi::apimachinery::pkg::api::resource::Quantity as K8sQuantity;
99
use snafu::{ensure, ResultExt as _, Snafu};
1010

1111
mod cpu;
12+
mod macros;
1213
mod memory;
14+
mod ops;
1315

1416
pub use cpu::*;
1517
pub use memory::*;
@@ -369,36 +371,6 @@ impl SuffixMultiple for DecimalExponent {
369371
}
370372
}
371373

372-
mod macros {
373-
macro_rules! forward_from_impls {
374-
($q:ty, $kq:ty, $for:ty) => {
375-
impl From<$q> for $for {
376-
fn from(quantity: $q) -> Self {
377-
Self(quantity)
378-
}
379-
}
380-
381-
impl TryFrom<$kq> for $for {
382-
type Error = ParseQuantityError;
383-
384-
fn try_from(value: $kq) -> Result<Self, Self::Error> {
385-
Ok(Self(Quantity::try_from(value)?))
386-
}
387-
}
388-
389-
impl TryFrom<&$kq> for $for {
390-
type Error = ParseQuantityError;
391-
392-
fn try_from(value: &$kq) -> Result<Self, Self::Error> {
393-
Ok(Self(Quantity::try_from(value)?))
394-
}
395-
}
396-
};
397-
}
398-
399-
pub(crate) use forward_from_impls;
400-
}
401-
402374
#[cfg(test)]
403375
mod test {
404376
use super::*;
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use std::{
2+
iter::Sum,
3+
ops::{Add, AddAssign, Div, Mul, MulAssign, Sub, SubAssign},
4+
};
5+
6+
use crate::quantity::Quantity;
7+
8+
impl Add for Quantity {
9+
type Output = Quantity;
10+
11+
fn add(self, rhs: Quantity) -> Self::Output {
12+
Self {
13+
value: self.value + rhs.value,
14+
..self
15+
}
16+
}
17+
}
18+
19+
impl AddAssign for Quantity {
20+
fn add_assign(&mut self, rhs: Quantity) {
21+
self.value += rhs.value
22+
}
23+
}
24+
25+
impl Sub for Quantity {
26+
type Output = Quantity;
27+
28+
fn sub(self, rhs: Quantity) -> Self::Output {
29+
Self {
30+
value: self.value - rhs.value,
31+
..self
32+
}
33+
}
34+
}
35+
36+
impl SubAssign for Quantity {
37+
fn sub_assign(&mut self, rhs: Self) {
38+
self.value -= rhs.value
39+
}
40+
}
41+
42+
impl Mul<usize> for Quantity {
43+
type Output = Quantity;
44+
45+
fn mul(self, rhs: usize) -> Self::Output {
46+
Self {
47+
value: self.value * rhs as f64,
48+
..self
49+
}
50+
}
51+
}
52+
53+
impl MulAssign<usize> for Quantity {
54+
fn mul_assign(&mut self, rhs: usize) {
55+
self.value *= rhs as f64
56+
}
57+
}
58+
59+
impl Mul<f32> for Quantity {
60+
type Output = Quantity;
61+
62+
fn mul(self, rhs: f32) -> Self::Output {
63+
Self {
64+
value: self.value * rhs as f64,
65+
..self
66+
}
67+
}
68+
}
69+
70+
impl MulAssign<f32> for Quantity {
71+
fn mul_assign(&mut self, rhs: f32) {
72+
self.value *= rhs as f64
73+
}
74+
}
75+
76+
impl Mul<f64> for Quantity {
77+
type Output = Quantity;
78+
79+
fn mul(self, rhs: f64) -> Self::Output {
80+
Self {
81+
value: self.value * rhs,
82+
..self
83+
}
84+
}
85+
}
86+
87+
impl MulAssign<f64> for Quantity {
88+
fn mul_assign(&mut self, rhs: f64) {
89+
self.value *= rhs
90+
}
91+
}
92+
93+
impl Div for Quantity {
94+
type Output = f64;
95+
96+
fn div(self, rhs: Self) -> Self::Output {
97+
self.value / rhs.value
98+
}
99+
}
100+
101+
impl Sum for Quantity {
102+
fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
103+
iter.fold(
104+
Quantity {
105+
value: 0.0,
106+
suffix: None,
107+
},
108+
Quantity::add,
109+
)
110+
}
111+
}

0 commit comments

Comments
 (0)