1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/// Union `Self` with `Rhs` in place.
pub trait UnionAssign<Rhs = Self> {
	/// Union.
	fn union_assign(&mut self, rhs: Rhs);
}
impl<'a> UnionAssign<&'a u8> for u8 {
	fn union_assign(&mut self, rhs: &'a Self) {
		*self = (*self).max(*rhs);
	}
}
impl<'a> UnionAssign<&'a u16> for u16 {
	fn union_assign(&mut self, rhs: &'a Self) {
		*self = (*self).max(*rhs);
	}
}
impl<'a> UnionAssign<&'a u32> for u32 {
	fn union_assign(&mut self, rhs: &'a Self) {
		*self = (*self).max(*rhs);
	}
}
impl<'a> UnionAssign<&'a u64> for u64 {
	fn union_assign(&mut self, rhs: &'a Self) {
		*self = (*self).max(*rhs);
	}
}
impl UnionAssign for usize {
	fn union_assign(&mut self, rhs: Self) {
		*self = (*self).max(rhs);
	}
}
impl<'a> UnionAssign<&'a usize> for usize {
	fn union_assign(&mut self, rhs: &'a Self) {
		*self = (*self).max(*rhs);
	}
}

/// Intersect zero or more `&Self` to create `Option<Self>`.
pub trait Intersect {
	/// Intersect.
	fn intersect<'a>(iter: impl Iterator<Item = &'a Self>) -> Option<Self>
	where
		Self: Sized + 'a;
}
impl Intersect for u8 {
	fn intersect<'a>(iter: impl Iterator<Item = &'a Self>) -> Option<Self>
	where
		Self: Sized + 'a,
	{
		iter.cloned().min()
	}
}
impl Intersect for u16 {
	fn intersect<'a>(iter: impl Iterator<Item = &'a Self>) -> Option<Self>
	where
		Self: Sized + 'a,
	{
		iter.cloned().min()
	}
}
impl Intersect for u32 {
	fn intersect<'a>(iter: impl Iterator<Item = &'a Self>) -> Option<Self>
	where
		Self: Sized + 'a,
	{
		iter.cloned().min()
	}
}
impl Intersect for u64 {
	fn intersect<'a>(iter: impl Iterator<Item = &'a Self>) -> Option<Self>
	where
		Self: Sized + 'a,
	{
		iter.cloned().min()
	}
}
impl Intersect for usize {
	fn intersect<'a>(iter: impl Iterator<Item = &'a Self>) -> Option<Self>
	where
		Self: Sized + 'a,
	{
		iter.cloned().min()
	}
}

/// New instances are instantiable given a specified input of `<Self as New>::Config`.
pub trait New {
	/// The type of data required to instantiate a new `Self`.
	type Config: Clone;
	/// Instantiate a new `Self` with the given `<Self as New>::Config`.
	fn new(config: &Self::Config) -> Self;
}
impl New for u8 {
	type Config = ();
	fn new(_config: &Self::Config) -> Self {
		0
	}
}
impl New for u16 {
	type Config = ();
	fn new(_config: &Self::Config) -> Self {
		0
	}
}
impl New for u32 {
	type Config = ();
	fn new(_config: &Self::Config) -> Self {
		0
	}
}
impl New for u64 {
	type Config = ();
	fn new(_config: &Self::Config) -> Self {
		0
	}
}
impl New for usize {
	type Config = ();
	fn new(_config: &Self::Config) -> Self {
		0
	}
}

/// An optimisation for cases like putting a HyperLogLog inside a Count–min sketch, where intersecting, adding a val, and then unioning that with counters is the same as simply adding the val to the counters.
pub trait IntersectPlusUnionIsPlus {
	/// Apply optimisation or not
	const VAL: bool;
}

macro_rules! impl_ipuip {
	($($t:ty)*) => ($(
		impl IntersectPlusUnionIsPlus for $t {
			const VAL: bool = false;
		}
	)*)
}

impl_ipuip!(u8 i8 u16 i16 u32 i32 u64 i64 u128 i128 usize isize);