summaryrefslogtreecommitdiff
path: root/bs5/universal/native/shared/JsMap.re
blob: abf8cfcc6018db44afcfb6246057ab2809016cf9 (plain)
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
[@platform js]
include {
          type t('k, 'v);

          [@mel.new] external make: unit => t('k, 'v) = "Map";

          [@mel.send] [@mel.return nullable]
          external get: (t('k, 'v), 'k) => option('v) = "get";

          [@mel.send] external set: (t('k, 'v), 'k, 'v) => unit = "set";

          [@mel.send] external delete: (t('k, 'v), 'k) => unit = "delete";

          [@mel.send] external clear: t('k, 'v) => unit = "clear";

          [@mel.send] external size: t('k, 'v) => int = "size";

          [@mel.send] external has: (t('k, 'v), 'k) => bool = "has";

          [@mel.send] external values: t('k, 'v) => array('v) = "values";

          [@mel.send] external keys: t('k, 'v) => array('k) = "keys";

          [@mel.send]
          external entries: t('k, 'v) => array(('k, 'v)) = "entries";

          [@mel.send]
          external forEach: (t('k, 'v), ('k, 'v) => unit) => unit = "forEach";
        };

[@platform native]
include {
          type t('k, 'v) = {mutable entries: list(('k, 'v))};

          let make = () => {entries: []};

          let set = (map, k, v) => {
            let rec update = entries =>
              switch (entries) {
              | [] => [(k, v)]
              | [(k', _), ...rest] when k == k' => [(k, v), ...rest]
              | [pair, ...rest] => [pair, ...update(rest)]
              };
            map.entries = update(map.entries);
            map;
          };

          let get = (map, k) =>
            map.entries
            |> List.find_opt(((k', _)) => k == k')
            |> Option.map(((_, v)) => v);

          let delete = (map, k) => {
            map.entries = List.filter(((k', _)) => k != k', map.entries);
            map;
          };

          let clear = map => {
            map.entries = [];
            map;
          };

          let size = map => List.length(map.entries);

          let has = (map, k) =>
            List.exists(((k', _)) => k == k', map.entries);

          let values = map => List.map(((_, v)) => v, map.entries);

          let keys = map => List.map(((k, _)) => k, map.entries);

          let entries = map => map.entries;

          let forEach = (map, f) =>
            List.iter(((k, v)) => f(v, k, map), map.entries);
        };