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 struct Serialize<'a> {
70 value: &'a Value,
72 }
73
74 impl serde::Serialize for Serialize<'_> {
75 fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
76 where
77 S: serde::Serializer,
78 {
79 self.value.serialize(serializer)
80 }
81 }
82
83 let mut s = serializer.serialize_map(Some(self.values.len()))?;
84 for (k, v) in &self.values {
85 match &self.name {
86 Some(prefix) => {
87 s.serialize_entry(&format!("{prefix}.{k}"), &Serialize { value: v })?
88 }
89 None => s.serialize_entry(k, &Serialize { value: v })?,
90 }
91 }
92
93 s.end()
94 }
95}
96
97impl From<Scope> for Outputs {
98 fn from(scope: Scope) -> Self {
99 Self {
100 name: None,
101 values: scope.into(),
102 }
103 }
104}
105
106impl FromIterator<(String, Value)> for Outputs {
107 fn from_iter<T: IntoIterator<Item = (String, Value)>>(iter: T) -> Self {
108 Self {
109 name: None,
110 values: iter.into_iter().collect(),
111 }
112 }
113}