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
138
139
140
141
142
143
144
145
// Copyright 2018-2022 argmin developers
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
// http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

use std::fmt;
use std::fmt::{Debug, Display};
use std::rc::Rc;

/// A simple key-value storage
///
/// Keeps pairs of `(&'static str, Rc<dyn Display>)` and is used to pass key-value pairs to
/// [`Observers`](`crate::core::observers`) in each iteration of an optimization algorithm.
/// Typically constructed using the [`make_kv!`](`crate::make_kv`) macro.
///
/// # Example
///
/// ```
/// use argmin::make_kv;
///
/// let kv = make_kv!(
///     "key1" => "value1";
///     "key2" => "value2";
///     "key3" => 1234;
/// );
/// # assert_eq!(kv.kv.len(), 3);
/// # assert_eq!(kv.kv[0].0, "key1");
/// # assert_eq!(format!("{}", kv.kv[0].1), "value1");
/// # assert_eq!(kv.kv[1].0, "key2");
/// # assert_eq!(format!("{}", kv.kv[1].1), "value2");
/// # assert_eq!(kv.kv[2].0, "key3");
/// # assert_eq!(format!("{}", kv.kv[2].1), "1234");
/// ```
#[derive(Clone, Default)]
pub struct KV {
    /// The actual key value storage
    pub kv: Vec<(&'static str, Rc<dyn Display>)>,
}

impl Debug for KV {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "{}", self)?;
        Ok(())
    }
}
impl Display for KV {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        writeln!(f, "KV")?;
        for (key, val) in self.kv.iter() {
            writeln!(f, "   {}: {}", key, val)?;
        }
        Ok(())
    }
}

impl KV {
    /// Constructor a new empty `KV`
    ///
    /// # Example
    ///
    /// ```
    /// # use argmin::core::KV;
    /// #
    /// let kv = KV::new();
    /// # assert_eq!(kv.kv.len(), 0);
    /// ```
    pub fn new() -> Self {
        KV { kv: vec![] }
    }

    /// Push a key-value pair
    ///
    /// # Example
    ///
    /// ```
    /// # use argmin::core::KV;
    /// # use std::rc::Rc;
    ///
    /// let mut kv = KV::new();
    /// kv.push("key", Rc::new("value"));
    /// kv.push("key", Rc::new(1234));
    /// # assert_eq!(kv.kv.len(), 2);
    /// # assert_eq!(kv.kv[0].0, "key");
    /// # assert_eq!(format!("{}", kv.kv[0].1), "value");
    /// # assert_eq!(kv.kv[1].0, "key");
    /// # assert_eq!(format!("{}", kv.kv[1].1), "1234");
    /// ```
    pub fn push(&mut self, key: &'static str, val: Rc<dyn Display>) -> &mut Self {
        self.kv.push((key, val));
        self
    }

    /// Merge with another `KV`
    ///
    /// # Example
    ///
    /// ```
    /// # use argmin::core::KV;
    /// # use std::rc::Rc;
    ///
    /// let mut kv1 = KV::new();
    /// kv1.push("key1", Rc::new("value1"));
    /// # assert_eq!(kv1.kv.len(), 1);
    /// # assert_eq!(kv1.kv[0].0, "key1");
    /// # assert_eq!(format!("{}", kv1.kv[0].1), "value1");
    ///
    /// let mut kv2 = KV::new();
    /// kv2.push("key2", Rc::new("value2"));
    /// # assert_eq!(kv2.kv.len(), 1);
    /// # assert_eq!(kv2.kv[0].0, "key2");
    /// # assert_eq!(format!("{}", kv2.kv[0].1), "value2");
    ///
    /// let kv1 = kv1.merge(kv2);
    /// # assert_eq!(kv1.kv.len(), 2);
    /// # assert_eq!(kv1.kv[0].0, "key1");
    /// # assert_eq!(format!("{}", kv1.kv[0].1), "value1");
    /// # assert_eq!(kv1.kv[1].0, "key2");
    /// # assert_eq!(format!("{}", kv1.kv[1].1), "value2");
    /// ```
    #[must_use]
    pub fn merge(mut self, mut other: KV) -> Self {
        self.kv.append(&mut other.kv);
        self
    }
}

impl std::iter::FromIterator<(&'static str, Rc<dyn Display>)> for KV {
    fn from_iter<I: IntoIterator<Item = (&'static str, Rc<dyn Display>)>>(iter: I) -> Self {
        let mut c = KV::new();
        for i in iter {
            c.push(i.0, i.1);
        }
        c
    }
}

impl std::iter::Extend<(&'static str, Rc<dyn Display>)> for KV {
    fn extend<I: IntoIterator<Item = (&'static str, Rc<dyn Display>)>>(&mut self, iter: I) {
        for i in iter {
            self.push(i.0, i.1);
        }
    }
}