1use std::cmp::Ordering;
4
5use indexmap::IndexMap;
6use serde::Serialize;
7
8use crate::Scope;
9use crate::Value;
10
11#[derive(Default, Debug)]
13pub struct Outputs {
14 name: Option<String>,
19 values: IndexMap<String, Value>,
21}
22
23impl Outputs {
24 pub fn new() -> Self {
26 Self::default()
27 }
28
29 pub fn with_name(mut self, name: impl Into<String>) -> Self {
33 self.name = Some(name.into());
34 self
35 }
36
37 pub fn iter(&self) -> impl Iterator<Item = (&str, &Value)> + use<'_> {
39 self.values.iter().map(|(k, v)| (k.as_str(), v))
40 }
41
42 pub fn get(&self, name: &str) -> Option<&Value> {
46 self.values.get(name)
47 }
48
49 pub(crate) fn sort_by(&mut self, mut cmp: impl FnMut(&str, &str) -> Ordering) {
51 self.values.sort_unstable_by(move |a, _, b, _| {
54 let ordering = cmp(a, b);
55 assert!(ordering != Ordering::Equal);
56 ordering
57 });
58 }
59}
60
61impl Serialize for Outputs {
62 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
63 where
64 S: serde::Serializer,
65 {
66 use serde::ser::SerializeMap;
67
68 let mut s = serializer.serialize_map(Some(self.values.len()))?;
69 for (k, v) in &self.values {
70 let v = crate::ValueSerializer::new(v, true);
71 match &self.name {
72 Some(prefix) => s.serialize_entry(&format!("{prefix}.{k}"), &v)?,
73 None => s.serialize_entry(k, &v)?,
74 }
75 }
76
77 s.end()
78 }
79}
80
81impl From<Scope> for Outputs {
82 fn from(scope: Scope) -> Self {
83 Self {
84 name: None,
85 values: scope.into(),
86 }
87 }
88}
89
90impl FromIterator<(String, Value)> for Outputs {
91 fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> Self {
92 Self {
93 name: None,
94 values: iter.into_iter().collect(),
95 }
96 }
97}