gitql_core/values/
composite.rs

1use std::any::Any;
2use std::cmp::Ordering;
3use std::collections::HashMap;
4
5use gitql_ast::types::composite::CompositeType;
6use gitql_ast::types::DataType;
7
8use indexmap::IndexMap;
9
10use super::base::Value;
11
12#[derive(Clone)]
13pub struct CompositeValue {
14    pub name: String,
15    pub members: IndexMap<String, Box<dyn Value>>,
16}
17
18impl CompositeValue {
19    pub fn new(name: String, members: IndexMap<String, Box<dyn Value>>) -> Self {
20        CompositeValue { name, members }
21    }
22
23    pub fn empty(name: String) -> Self {
24        CompositeValue {
25            name,
26            members: IndexMap::default(),
27        }
28    }
29
30    pub fn add_member(mut self, name: String, value: Box<dyn Value>) -> Self {
31        self.members.insert(name, value);
32        self
33    }
34}
35
36impl Value for CompositeValue {
37    fn literal(&self) -> String {
38        let mut str = String::new();
39        let last_position = self.members.len() - 1;
40        str += "(";
41        for (pos, member) in self.members.iter().enumerate() {
42            str += &member.1.literal();
43            if pos != last_position {
44                str += ", ";
45            }
46        }
47        str += ")";
48        str
49    }
50
51    fn equals(&self, other: &Box<dyn Value>) -> bool {
52        if let Some(other_composite) = other.as_any().downcast_ref::<CompositeValue>() {
53            return self.name.eq(&other_composite.name)
54                && self.members.eq(&other_composite.members);
55        }
56        false
57    }
58
59    fn compare(&self, _other: &Box<dyn Value>) -> Option<Ordering> {
60        None
61    }
62
63    fn data_type(&self) -> Box<dyn DataType> {
64        let name = self.name.to_string();
65        let mut members: HashMap<String, Box<dyn DataType>> = HashMap::new();
66        for member in self.members.iter() {
67            members.insert(member.0.to_string(), member.1.data_type().clone());
68        }
69        Box::new(CompositeType::new(name, members))
70    }
71
72    fn as_any(&self) -> &dyn Any {
73        self
74    }
75}