Skip to content

Commit 91b156a

Browse files
authored
feat: Add key/value pair QoL improvements (#711)
* Add TryFrom<[(K, V); N]> implf for labels and annotations * Adjust `try_insert` associated function * Add `parse_insert` functions, revert to old `try_insert` functions * Adjust overide spelling * Fix rustdoc error * Adjust generic type names * Add `parse_insert` tests * Update changelog
1 parent 68b1a17 commit 91b156a

File tree

4 files changed

+203
-80
lines changed

4 files changed

+203
-80
lines changed

CHANGELOG.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file.
44

55
## [Unreleased]
66

7+
### Added
8+
9+
- Add `TryFrom<[(K, V); N]>` implementation for `Annotations` and `Labels` ([#711]).
10+
- Add `parse_insert` associated function for `Annotations` and `Labels` ([#711]).
11+
12+
### Changed
13+
14+
- Adjust `try_insert` for `Annotations` and `Labels` slightly ([#711]).
15+
16+
[#711]: https://github.com/stackabletech/operator-rs/pull/711
17+
718
## [0.60.1] - 2024-01-04
819

920
### Fixed

src/kvp/annotation/mod.rs

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,7 @@ mod value;
2626

2727
pub use value::*;
2828

29-
/// A type alias for errors returned when construction of an annotation fails.
30-
pub type AnnotationsError = KeyValuePairsError<Infallible>;
29+
pub type AnnotationsError = KeyValuePairsError;
3130

3231
/// A type alias for errors returned when construction or manipulation of a set
3332
/// of annotations fails.
@@ -45,13 +44,14 @@ pub type AnnotationError = KeyValuePairError<Infallible>;
4544
#[derive(Debug)]
4645
pub struct Annotation(KeyValuePair<AnnotationValue>);
4746

48-
impl<T> TryFrom<(T, T)> for Annotation
47+
impl<K, V> TryFrom<(K, V)> for Annotation
4948
where
50-
T: AsRef<str>,
49+
K: AsRef<str>,
50+
V: AsRef<str>,
5151
{
5252
type Error = AnnotationError;
5353

54-
fn try_from(value: (T, T)) -> Result<Self, Self::Error> {
54+
fn try_from(value: (K, V)) -> Result<Self, Self::Error> {
5555
let kvp = KeyValuePair::try_from(value)?;
5656
Ok(Self(kvp))
5757
}
@@ -150,6 +150,19 @@ impl TryFrom<BTreeMap<String, String>> for Annotations {
150150
}
151151
}
152152

153+
impl<const N: usize, K, V> TryFrom<[(K, V); N]> for Annotations
154+
where
155+
K: AsRef<str>,
156+
V: AsRef<str>,
157+
{
158+
type Error = AnnotationError;
159+
160+
fn try_from(value: [(K, V); N]) -> Result<Self, Self::Error> {
161+
let kvps = KeyValuePairs::try_from(value)?;
162+
Ok(Self(kvps))
163+
}
164+
}
165+
153166
impl FromIterator<KeyValuePair<AnnotationValue>> for Annotations {
154167
fn from_iter<T: IntoIterator<Item = KeyValuePair<AnnotationValue>>>(iter: T) -> Self {
155168
let kvps = KeyValuePairs::from_iter(iter);
@@ -174,17 +187,19 @@ impl Annotations {
174187
Self(KeyValuePairs::new_with(pairs))
175188
}
176189

177-
/// Tries to insert a new [`Annotation`]. It ensures there are no duplicate
178-
/// entries. Trying to insert duplicated data returns an error. If no such
179-
/// check is required, use the `insert` function instead.
180-
pub fn try_insert(&mut self, annotation: Annotation) -> Result<&mut Self, AnnotationsError> {
181-
self.0.try_insert(annotation.0)?;
182-
Ok(self)
190+
/// Tries to insert a new annotation by first parsing `annotation` as an
191+
/// [`Annotation`] and then inserting it into the list. This function will
192+
/// overwrite any existing annotation already present.
193+
pub fn parse_insert(
194+
&mut self,
195+
annotation: impl TryInto<Annotation, Error = AnnotationError>,
196+
) -> Result<(), AnnotationError> {
197+
self.0.insert(annotation.try_into()?.0);
198+
Ok(())
183199
}
184200

185-
/// Inserts a new [`Annotation`]. This function will overide any existing
186-
/// annotation already present. If this behaviour is not desired, use the
187-
/// `try_insert` function instead.
201+
/// Inserts a new [`Annotation`]. This function will overwrite any existing
202+
/// annotation already present.
188203
pub fn insert(&mut self, annotation: Annotation) -> &mut Self {
189204
self.0.insert(annotation.0);
190205
self
@@ -196,6 +211,11 @@ impl Annotations {
196211
// the need to write boilerplate code.
197212
delegate! {
198213
to self.0 {
214+
/// Tries to insert a new [`Annotation`]. It ensures there are no duplicate
215+
/// entries. Trying to insert duplicated data returns an error. If no such
216+
/// check is required, use [`Annotations::insert`] instead.
217+
pub fn try_insert(&mut self, #[newtype] annotation: Annotation) -> Result<(), AnnotationsError>;
218+
199219
/// Extends `self` with `other`.
200220
pub fn extend(&mut self, #[newtype] other: Self);
201221

@@ -217,3 +237,23 @@ impl Annotations {
217237
}
218238
}
219239
}
240+
241+
#[cfg(test)]
242+
mod test {
243+
use super::*;
244+
245+
#[test]
246+
fn parse_insert() {
247+
let mut annotations = Annotations::new();
248+
249+
annotations
250+
.parse_insert(("stackable.tech/managed-by", "stackablectl"))
251+
.unwrap();
252+
253+
annotations
254+
.parse_insert(("stackable.tech/vendor", "Stäckable"))
255+
.unwrap();
256+
257+
assert_eq!(annotations.len(), 2);
258+
}
259+
}

src/kvp/label/mod.rs

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ mod value;
3434
pub use selector::*;
3535
pub use value::*;
3636

37-
/// A type alias for errors returned when construction of a label fails.
38-
pub type LabelsError = KeyValuePairsError<LabelValueError>;
37+
pub type LabelsError = KeyValuePairsError;
3938

4039
/// A type alias for errors returned when construction or manipulation of a set
4140
/// of labels fails.
@@ -57,13 +56,14 @@ pub type LabelError = KeyValuePairError<LabelValueError>;
5756
#[derive(Clone, Debug)]
5857
pub struct Label(KeyValuePair<LabelValue>);
5958

60-
impl<T> TryFrom<(T, T)> for Label
59+
impl<K, V> TryFrom<(K, V)> for Label
6160
where
62-
T: AsRef<str>,
61+
K: AsRef<str>,
62+
V: AsRef<str>,
6363
{
6464
type Error = LabelError;
6565

66-
fn try_from(value: (T, T)) -> Result<Self, Self::Error> {
66+
fn try_from(value: (K, V)) -> Result<Self, Self::Error> {
6767
let kvp = KeyValuePair::try_from(value)?;
6868
Ok(Self(kvp))
6969
}
@@ -151,6 +151,19 @@ impl TryFrom<BTreeMap<String, String>> for Labels {
151151
}
152152
}
153153

154+
impl<const N: usize, K, V> TryFrom<[(K, V); N]> for Labels
155+
where
156+
K: AsRef<str>,
157+
V: AsRef<str>,
158+
{
159+
type Error = LabelError;
160+
161+
fn try_from(value: [(K, V); N]) -> Result<Self, Self::Error> {
162+
let kvps = KeyValuePairs::try_from(value)?;
163+
Ok(Self(kvps))
164+
}
165+
}
166+
154167
impl FromIterator<KeyValuePair<LabelValue>> for Labels {
155168
fn from_iter<T: IntoIterator<Item = KeyValuePair<LabelValue>>>(iter: T) -> Self {
156169
let kvps = KeyValuePairs::from_iter(iter);
@@ -175,17 +188,19 @@ impl Labels {
175188
Self(KeyValuePairs::new_with(pairs))
176189
}
177190

178-
/// Tries to insert a new [`Label`]. It ensures there are no duplicate
179-
/// entries. Trying to insert duplicated data returns an error. If no such
180-
/// check is required, use the `insert` function instead.
181-
pub fn try_insert(&mut self, label: Label) -> Result<&mut Self, LabelsError> {
182-
self.0.try_insert(label.0)?;
183-
Ok(self)
191+
/// Tries to insert a new label by first parsing `label` as a [`Label`]
192+
/// and then inserting it into the list. This function will overwrite any
193+
/// existing label already present.
194+
pub fn parse_insert(
195+
&mut self,
196+
label: impl TryInto<Label, Error = LabelError>,
197+
) -> Result<(), LabelError> {
198+
self.0.insert(label.try_into()?.0);
199+
Ok(())
184200
}
185201

186-
/// Inserts a new [`Label`]. This function will overide any existing label
187-
/// already present. If this behaviour is not desired, use the `try_insert`
188-
/// function instead.
202+
/// Inserts a new [`Label`]. This function will overwrite any existing label
203+
/// already present.
189204
pub fn insert(&mut self, label: Label) -> &mut Self {
190205
self.0.insert(label.0);
191206
self
@@ -285,6 +300,11 @@ impl Labels {
285300
// need to write boilerplate code.
286301
delegate! {
287302
to self.0 {
303+
/// Tries to insert a new [`Label`]. It ensures there are no duplicate
304+
/// entries. Trying to insert duplicated data returns an error. If no such
305+
/// check is required, use [`Labels::insert`] instead.
306+
pub fn try_insert(&mut self, #[newtype] label: Label) -> Result<(), LabelsError>;
307+
288308
/// Extends `self` with `other`.
289309
pub fn extend(&mut self, #[newtype] other: Self);
290310

@@ -304,3 +324,23 @@ impl Labels {
304324
}
305325
}
306326
}
327+
328+
#[cfg(test)]
329+
mod test {
330+
use super::*;
331+
332+
#[test]
333+
fn parse_insert() {
334+
let mut labels = Labels::new();
335+
336+
labels
337+
.parse_insert(("stackable.tech/managed-by", "stackablectl"))
338+
.unwrap();
339+
340+
labels
341+
.parse_insert(("stackable.tech/vendor", "Stackable"))
342+
.unwrap();
343+
344+
assert_eq!(labels.len(), 2);
345+
}
346+
}

0 commit comments

Comments
 (0)