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
use crate::errors::*;

use crate::{proto, base};

use crate::components::{Expandable};
use crate::base::{ValueProperties, IndexKey, Value, ReleaseNode};
use crate::utilities::{get_literal};
use crate::utilities::inference::infer_property;
use indexmap::set::IndexSet;
use indexmap::map::IndexMap;


impl Expandable for proto::Map {
    fn expand_component(
        &self,
        _privacy_definition: &Option<proto::PrivacyDefinition>,
        component: &proto::Component,
        public_arguments: &IndexMap<IndexKey, &Value>,
        properties: &base::NodeProperties,
        component_id: u32,
        mut maximum_id: u32
    ) -> Result<base::ComponentExpansion> {
        let mut expansion = base::ComponentExpansion::default();

        let mapped_component = self.component.as_ref()
            .ok_or_else(|| "component must be defined")?;

        let (props_partitioned, props_singular): (
            IndexMap<IndexKey, ValueProperties>,
            IndexMap<IndexKey, ValueProperties>
        ) = properties.clone().into_iter()
            .partition(|(_, props)| props.partitions().is_ok());

        let indexes = props_partitioned.values()
            .map(|v| Ok(v.partitions()?.children.keys().collect()))
            .collect::<Result<Vec<Vec<&IndexKey>>>>()?.into_iter().flatten()
            .collect::<IndexSet<&IndexKey>>();

        let arguments = component.arguments();

        // for each partition
        let union_arguments = indexes.into_iter()
            // for each argument
            .map(|partition_idx| Ok((
                partition_idx.clone(),
                props_partitioned.iter()
                    .map(|(name, _)| {
                        maximum_id += 1;
                        let id_index_name = maximum_id;
                        let (patch_node, release) = get_literal(Value::from_index_key(partition_idx.clone())?, component.submission)?;
                        expansion.computation_graph.insert(id_index_name, patch_node);
                        expansion.properties.insert(id_index_name, infer_property(&release.value, None, id_index_name)?);
                        expansion.releases.insert(id_index_name, release);

                        maximum_id += 1;
                        let id_index = maximum_id;
                        let id_data = *arguments.get(name)
                            .ok_or_else(|| Error::from(format!("{:?}: missing from component arguments", name)))?;
                        expansion.computation_graph.insert(id_index, proto::Component {
                            arguments: Some(proto::ArgumentNodeIds::new(indexmap!["data".into() => id_data, "names".into() => id_index_name])),
                            omit: true,
                            submission: component.submission,
                            variant: Some(proto::component::Variant::Index(proto::Index {})),
                        });

                        match (public_arguments.get(name), properties.get(name)) {
                            (Some(release_node), Some(properties)) => match (
                                release_node.ref_partitions()?.get(partition_idx),
                                properties.partitions()?.children.get(partition_idx)
                            ) {
                                (Some(partition_value), Some(partition_properties)) => {
                                    expansion.releases.insert(id_index, ReleaseNode {
                                        value: partition_value.clone(),
                                        privacy_usages: None,
                                        public: partition_properties.is_public()
                                    });
                                    expansion.properties.insert(id_index, partition_properties.clone());
                                },
                                _ => expansion.traversal.push(id_index)
                            },
                            _ => expansion.traversal.push(id_index)
                        }

                        Ok((name.clone(), id_index))
                    })
                    .chain(props_singular.clone().into_iter().map(|(name, _)| {
                        let id_arg = arguments.get(&name).ok_or_else(||
                            format!("{:?}: missing from component arguments", name))?;
                        Ok((name, *id_arg))
                    }))
                    .collect::<Result<IndexMap<IndexKey, u32>>>()?
            )))
            .collect::<Result<IndexMap<IndexKey, IndexMap<IndexKey, u32>>>>()?.into_iter()
            .map(|(partition_idx, arguments)| {

                maximum_id += 1;
                let id_inner_component = maximum_id;
                let mut inner_component = *mapped_component.clone();

                inner_component.arguments = Some(proto::ArgumentNodeIds::new(arguments));
                inner_component.omit = true;

                expansion.computation_graph.insert(id_inner_component, inner_component);
                expansion.traversal.push(id_inner_component);

                Ok((partition_idx, id_inner_component))
            })
            .collect::<Result<IndexMap<IndexKey, u32>>>()?;

        expansion.computation_graph.insert(component_id, proto::Component {
            arguments: Some(proto::ArgumentNodeIds::new(union_arguments)),
            omit: component.omit,
            submission: component.submission,
            variant: Some(proto::component::Variant::Union(proto::Union {
                flatten: false
            }))
        });
        expansion.traversal.push(component_id);

        Ok(expansion)
    }
}