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
use super::{Error, SassFunction};
use crate::css::Value;
use crate::ordermap::OrderMap;
use crate::value::ListSeparator;
use std::collections::BTreeMap;
pub fn register(f: &mut BTreeMap<&'static str, SassFunction>) {
def!(f, map_get(map, key), |s| Ok(get_map(s.get("map")?)?
.get(&s.get("key")?)
.cloned()
.unwrap_or(Value::Null)));
def!(f, map_merge(map1, map2), |s| {
let mut map1 = get_map(s.get("map1")?)?;
let map2 = get_map(s.get("map2")?)?;
for (key, value) in map2 {
map1.insert(key, value);
}
Ok(Value::Map(map1))
});
def_va!(f, map_remove(map, keys), |s| {
let mut map = get_map(s.get("map")?)?;
match s.get("keys")? {
Value::List(keys, ..) => {
for key in keys {
map.remove(&key);
}
}
key => {
map.remove(&key);
}
}
Ok(Value::Map(map))
});
def!(f, map_keys(map), |s| {
let map = get_map(s.get("map")?)?;
Ok(Value::List(map.keys(), ListSeparator::Comma, false))
});
def!(f, map_values(map), |s| {
let map = get_map(s.get("map")?)?;
Ok(Value::List(map.values(), ListSeparator::Comma, false))
});
def!(f, map_has_key(map, key), |s| {
let map = get_map(s.get("map")?)?;
Ok(Value::bool(map.contains_key(&s.get("key")?)))
});
}
fn get_map(v: Value) -> Result<OrderMap<Value, Value>, Error> {
match v {
Value::Map(m) => Ok(m),
Value::List(ref l, ..) if l.is_empty() => Ok(OrderMap::new()),
v => Err(Error::badarg("map", &v)),
}
}
#[cfg(test)]
mod test {
mod map_get {
use super::check_val;
#[test]
fn a() {
check_val("map-get((\"foo\": 1, \"bar\": 2), \"foo\");", "1")
}
#[test]
fn b() {
check_val("map-get((\"foo\": 1, \"bar\": 2), \"bar\");", "2")
}
#[test]
fn c() {
check_val("map-get((\"foo\": 1, \"bar\": 2), \"baz\");", "")
}
}
mod map_has_key {
use super::check_val;
#[test]
fn a() {
check_val(
"map-has-key((\"foo\": 1, \"bar\": 2), \"foo\");",
"true",
)
}
#[test]
fn b() {
check_val(
"map-has-key((\"foo\": 1, \"bar\": 2), \"baz\");",
"false",
)
}
}
fn check_val(src: &str, correct: &str) {
use crate::variablescope::test::do_evaluate;
assert_eq!(do_evaluate(&[], src.as_bytes()), correct)
}
}