From c504154595336fe3029bcfdffe0129e127308f68 Mon Sep 17 00:00:00 2001 From: Runxi Yu Date: Sun, 21 Sep 2025 18:40:40 +0800 Subject: [PATCH] Add iter --- ds/map/btree/iter.ha | 110 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ds/map/btree/map.ha | 2 ++ ds/map/hashmap/iter.ha | 63 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ds/map/hashmap/map.ha | 2 ++ ds/map/hashmap_fnv/iter.ha | 11 +++++++++++ ds/map/hashmap_fnv/map.ha | 2 ++ ds/map/hashmap_siphash/iter.ha | 11 +++++++++++ ds/map/hashmap_siphash/map.ha | 2 ++ ds/map/map.ha | 26 ++++++++++++++++++++++++++ ds/map/rbtree/iter.ha | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ds/map/rbtree/map.ha | 2 ++ ds/map/slice_basic/iter.ha | 33 +++++++++++++++++++++++++++++++++ ds/map/slice_basic/map.ha | 2 ++ ds/map/slice_sorted/iter.ha | 33 +++++++++++++++++++++++++++++++++ ds/map/slice_sorted/map.ha | 2 ++ ds/map/swiss/iter.ha | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ ds/map/swiss/map.ha | 2 ++ ds/map/swiss_fnv/iter.ha | 10 ++++++++++ ds/map/swiss_fnv/map.ha | 2 ++ ds/map/swiss_siphash/iter.ha | 10 ++++++++++ ds/map/swiss_siphash/map.ha | 2 ++ diff --git a/ds/map/btree/iter.ha b/ds/map/btree/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..c29058f2b9b47f4c3d2efc3db32864755864e9ec --- /dev/null +++ b/ds/map/btree/iter.ha @@ -0,0 +1,110 @@ +// SPDX-License-Identifier: MPL-2.0 + +use ds::map; + +export type iterator = struct { + vt: map::iterator, + nodes: []*node, + idxs: []size, + visit_key: []bool, +}; + +const _itvt: map::vtable_iterator = map::vtable_iterator { + nexter = &vt_next, +}; + +fn vt_next(it: *map::iterator) (([]u8, *opaque) | done) = next(it: *iterator); + +export fn iter(m: *map) (*map::iterator | nomem) = { + let it = alloc(iterator { + vt = &_itvt, + nodes = [], + idxs = [], + visit_key = [], + })?; + + match (append(it.nodes, m.root)) { + case void => void; + case nomem => return nomem; + }; + match (append(it.idxs, 0z)) { + case void => void; + case nomem => return nomem; + }; + match (append(it.visit_key, false)) { + case void => void; + case nomem => return nomem; + }; + + return (it: *map::iterator); +}; + +export fn next(it: *iterator) (([]u8, *opaque) | done) = { + for (len(it.nodes) != 0) { + let top = len(it.nodes) - 1; + let x = it.nodes[top]; + let i = it.idxs[top]; + let vk = it.visit_key[top]; + + if (x.leaf) { + if (i < len(x.keys)) { + it.idxs[top] = i + 1; + return (x.keys[i], x.vals[i]); + }; + delete(it.nodes[top]); + delete(it.idxs[top]); + delete(it.visit_key[top]); + continue; + }; + + if (vk) { + if (i >= len(x.keys)) { + it.visit_key[top] = false; + continue; + }; + it.visit_key[top] = false; + it.idxs[top] = i + 1; + return (x.keys[i], x.vals[i]); + }; + + if (i < len(x.keys)) { + match (append(it.nodes, x.children[i])) { + case void => void; + case nomem => abort("btree::iter: nomem"); + }; + match (append(it.idxs, 0z)) { + case void => void; + case nomem => abort("btree::iter: nomem"); + }; + match (append(it.visit_key, false)) { + case void => void; + case nomem => abort("btree::iter: nomem"); + }; + it.visit_key[top] = true; + continue; + }; + + if (i == len(x.keys)) { + match (append(it.nodes, x.children[i])) { + case void => void; + case nomem => abort("btree::iter: nomem"); + }; + match (append(it.idxs, 0z)) { + case void => void; + case nomem => abort("btree::iter: nomem"); + }; + match (append(it.visit_key, false)) { + case void => void; + case nomem => abort("btree::iter: nomem"); + }; + it.idxs[top] = i + 1; + continue; + }; + + delete(it.nodes[top]); + delete(it.idxs[top]); + delete(it.visit_key[top]); + }; + + return done; +}; diff --git a/ds/map/btree/map.ha b/ds/map/btree/map.ha index f838b77d77b164b615d0da2d552c4e29a76948d7..008b6ad091f604de75d5f2df8e700c131ee5560e 100644 --- a/ds/map/btree/map.ha +++ b/ds/map/btree/map.ha @@ -17,9 +17,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); diff --git a/ds/map/hashmap/iter.ha b/ds/map/hashmap/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..a06f91c2611f540e4e0caae926964ad01bca1f89 --- /dev/null +++ b/ds/map/hashmap/iter.ha @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: 2024 Drew DeVault +// SPDX-FileCopyrightText: 2025 Runxi Yu + +use ds::map; + +export type iterator = struct { + vt: map::iterator, + m: *map, + bi: size, + cur: nullable *map::iterator, +}; + +const _itvt: map::vtable_iterator = map::vtable_iterator { + nexter = &vt_next, +}; + +fn vt_next(it: *map::iterator) (([]u8, *opaque) | done) = next(it: *iterator); + +export fn iter(m: *map) (*map::iterator | nomem) = { + let it = alloc(iterator { + vt = &_itvt, + m = m, + bi = 0, + cur = null, + })?; + for (it.bi < m.n) { + let b = m.buckets[it.bi]; + it.bi += 1; + match (map::iter(b)) { + case let i: *map::iterator => + it.cur = i; + break; + case nomem => + abort("hashmap::iter: nomem"); + }; + }; + return (it: *map::iterator); +}; + +export fn next(it: *iterator) (([]u8, *opaque) | done) = { + for (true) { + match (it.cur) { + case null => + if (it.bi >= it.m.n) return done; + let b = it.m.buckets[it.bi]; + it.bi += 1; + match (map::iter(b)) { + case let i: *map::iterator => + it.cur = i; + case nomem => + abort("hashmap::iter: nomem"); + }; + case let curi: *map::iterator => + match (map::next(curi)) { + case let kv: ([]u8, *opaque) => + return kv; + case done => + it.cur = null; + }; + }; + }; +}; diff --git a/ds/map/hashmap/map.ha b/ds/map/hashmap/map.ha index 8ae987150b183301740fe63a067f9e2afd7ecee3..ae46b33512bcc6bd1fa83b4a9f76017bba750968 100644 --- a/ds/map/hashmap/map.ha +++ b/ds/map/hashmap/map.ha @@ -21,9 +21,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); diff --git a/ds/map/hashmap_fnv/iter.ha b/ds/map/hashmap_fnv/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..e1a00ffb252a657eeb972f12a67e1ce48c58fb00 --- /dev/null +++ b/ds/map/hashmap_fnv/iter.ha @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: 2024 Drew DeVault +// SPDX-FileCopyrightText: 2025 Runxi Yu + +use ds::map; + +export type iterator = map::iterator; + +export fn iter(m: *map) (*map::iterator | nomem) = { + return map::iter(m.inner); +}; diff --git a/ds/map/hashmap_fnv/map.ha b/ds/map/hashmap_fnv/map.ha index b8f595affaebacaa7895c6170229e2e2c713e3f0..a2a43de78b823bea4ee95fdb1bb61548658b4e52 100644 --- a/ds/map/hashmap_fnv/map.ha +++ b/ds/map/hashmap_fnv/map.ha @@ -18,9 +18,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); diff --git a/ds/map/hashmap_siphash/iter.ha b/ds/map/hashmap_siphash/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..e1a00ffb252a657eeb972f12a67e1ce48c58fb00 --- /dev/null +++ b/ds/map/hashmap_siphash/iter.ha @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: MPL-2.0 +// SPDX-FileCopyrightText: 2024 Drew DeVault +// SPDX-FileCopyrightText: 2025 Runxi Yu + +use ds::map; + +export type iterator = map::iterator; + +export fn iter(m: *map) (*map::iterator | nomem) = { + return map::iter(m.inner); +}; diff --git a/ds/map/hashmap_siphash/map.ha b/ds/map/hashmap_siphash/map.ha index 72ced6b2f5dcfa9b832fceee659b4b0c96abd90b..ea60998637ea3dfb6583750c7f1e4992d1fa5dc0 100644 --- a/ds/map/hashmap_siphash/map.ha +++ b/ds/map/hashmap_siphash/map.ha @@ -19,9 +19,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); diff --git a/ds/map/map.ha b/ds/map/map.ha index 8b6fc22b95bc894131617be51805a0651900c759..b76ad88027f3466c511f96f3cbcda38c1d9e3d1a 100644 --- a/ds/map/map.ha +++ b/ds/map/map.ha @@ -2,12 +2,21 @@ // A map is a pointer to a [[vtable]] which allows for map types to implement // common operations. export type map = *vtable; +// Iterator vtable for map iteration. +export type vtable_iterator = struct { + nexter: *nexter, +}; + +// The outward-facing iterator type (pointer to an iterator vtable). +export type iterator = *vtable_iterator; + // The vtable type defines a set of virtual functions for a [[map]]. export type vtable = struct { getter: *getter, setter: *setter, deleter: *deleter, finisher: *finisher, + iter: *iterer, }; // The interface for a map which could be used to get values. Returns either a @@ -45,3 +54,20 @@ // Frees the map and all of its resources. Do not use the map after calling. export fn finish(m: *map) void = { m.finisher(m); }; + +// Iterator maker function in the main vtable. +export type iterer = fn(m: *map) (*iterator | nomem); + +// Creates an iterator for this map implementation. +export fn iter(m: *map) (*iterator | nomem) = { + return m.iter(m); +}; + +// Iterator "next" method signature. +// Returns the next (key, value) pair, or done when iteration is complete. +export type nexter = fn(it: *iterator) (([]u8, *opaque) | done); + +// Advances the iterator, yielding (key, value) or done when finished. +export fn next(it: *iterator) (([]u8, *opaque) | done) = { + return it.nexter(it); +}; diff --git a/ds/map/rbtree/iter.ha b/ds/map/rbtree/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..0b26b1724124e9e3d8bfa9c926b2d0eacf0bdfbd --- /dev/null +++ b/ds/map/rbtree/iter.ha @@ -0,0 +1,66 @@ +// SPDX-License-Identifier: MPL-2.0 + +use ds::map; + +export type iterator = struct { + vt: map::iterator, + cur: nullable *node, +}; + +const _itvt: map::vtable_iterator = map::vtable_iterator { + nexter = &vt_next, +}; + +fn vt_next(it: *map::iterator) (([]u8, *opaque) | done) = next(it: *iterator); + +export fn iter(m: *map) (*map::iterator | nomem) = { + let start: nullable *node = match (m.root) { + case null => yield null; + case let r: *node => yield subtree_min(r); + }; + let it = alloc(iterator { + vt = &_itvt, + cur = start, + })?; + return (it: *map::iterator); +}; + +fn successor(n0: *node) nullable *node = { + let n = n0; + + match (n.right) { + case let r: *node => + return subtree_min(r); + case null => + void; + }; + + let mut_p: nullable *node = n.parent; + let child: nullable *node = n; + + for (mut_p != null) { + let p = match (mut_p) { + case let pp: *node => yield pp; + case null => break; + }; + if (p.right != child) { + return p; + }; + child = p; + mut_p = p.parent; + }; + + return null; +}; + +export fn next(it: *iterator) (([]u8, *opaque) | done) = { + match (it.cur) { + case null => + return done; + case let n: *node => + let k = n.key; + let v = n.val; + it.cur = successor(n); + return (k, v); + }; +}; diff --git a/ds/map/rbtree/map.ha b/ds/map/rbtree/map.ha index 9f2c65bb871ad44c69d0fc73751f68c1c2be83e7..508723394e7e90b141acf9a0b14dc6eaef7add41 100644 --- a/ds/map/rbtree/map.ha +++ b/ds/map/rbtree/map.ha @@ -13,9 +13,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); diff --git a/ds/map/slice_basic/iter.ha b/ds/map/slice_basic/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..96532975e95510534f7a961f376ccf6ccac5ac07 --- /dev/null +++ b/ds/map/slice_basic/iter.ha @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MPL-2.0 + +use ds::map; + +export type iterator = struct { + vt: map::iterator, + m: *map, + i: size, +}; + +const _itvt: map::vtable_iterator = map::vtable_iterator { + nexter = &vt_next, +}; + +fn vt_next(it: *map::iterator) (([]u8, *opaque) | done) = next(it: *iterator); + +export fn iter(m: *map) (*map::iterator | nomem) = { + let it = alloc(iterator { + vt = &_itvt, + m = m, + i = 0, + })?; + return (it: *map::iterator); +}; + +export fn next(it: *iterator) (([]u8, *opaque) | done) = { + if (it.i >= len(it.m.items)) { + return done; + }; + let kv = it.m.items[it.i]; + it.i += 1; + return (kv.0, kv.1); +}; diff --git a/ds/map/slice_basic/map.ha b/ds/map/slice_basic/map.ha index 0f90fa037687dd0d39b51d491b59aba1699b178a..b356b65c1b60ed7c2f09df559ec6e020dc1a23e0 100644 --- a/ds/map/slice_basic/map.ha +++ b/ds/map/slice_basic/map.ha @@ -15,9 +15,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); diff --git a/ds/map/slice_sorted/iter.ha b/ds/map/slice_sorted/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..96532975e95510534f7a961f376ccf6ccac5ac07 --- /dev/null +++ b/ds/map/slice_sorted/iter.ha @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MPL-2.0 + +use ds::map; + +export type iterator = struct { + vt: map::iterator, + m: *map, + i: size, +}; + +const _itvt: map::vtable_iterator = map::vtable_iterator { + nexter = &vt_next, +}; + +fn vt_next(it: *map::iterator) (([]u8, *opaque) | done) = next(it: *iterator); + +export fn iter(m: *map) (*map::iterator | nomem) = { + let it = alloc(iterator { + vt = &_itvt, + m = m, + i = 0, + })?; + return (it: *map::iterator); +}; + +export fn next(it: *iterator) (([]u8, *opaque) | done) = { + if (it.i >= len(it.m.items)) { + return done; + }; + let kv = it.m.items[it.i]; + it.i += 1; + return (kv.0, kv.1); +}; diff --git a/ds/map/slice_sorted/map.ha b/ds/map/slice_sorted/map.ha index 1f819253f4c88af0ff68f19e70bfc2d82e4609fc..a4b92cb4520a664f1a1c3c5b4290028d98b9edd2 100644 --- a/ds/map/slice_sorted/map.ha +++ b/ds/map/slice_sorted/map.ha @@ -16,9 +16,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); diff --git a/ds/map/swiss/iter.ha b/ds/map/swiss/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..91561ddea4228b8c49449cc79c2e0cd4d3cafadd --- /dev/null +++ b/ds/map/swiss/iter.ha @@ -0,0 +1,54 @@ +// SPDX-License-Identifier: Apache-2.0 AND MPL-2.0 +// SPDX-FileCopyrightText: 2024 The Cockroach Authors +// SPDX-FileCopyrightText: 2025 Runxi Yu + +use ds::map; + +export type iterator = struct { + vt: map::iterator, + m: *map, + gi: size, + si: size, +}; + +const _itvt: map::vtable_iterator = map::vtable_iterator { + nexter = &vt_next, +}; + +fn vt_next(it: *map::iterator) (([]u8, *opaque) | done) = next(it: *iterator); + +export fn iter(m: *map) (*map::iterator | nomem) = { + let it = alloc(iterator { + vt = &_itvt, + m = m, + gi = 0, + si = 0, + })?; + return (it: *map::iterator); +}; + +export fn next(it: *iterator) (([]u8, *opaque) | done) = { + if (len(it.m.groups) == 0) return done; + + for (it.gi <= it.m.group_mask) { + for (let g = &it.m.groups[it.gi]; it.si < GROUP_SIZE; it.si += 1) { + let c = g.ctrl[it.si]; + if (!is_full_ctrl(c)) { + continue; + }; + let k = g.keys[it.si]; + let v = g.vals[it.si]; + it.si += 1; + match (v) { + case null => + abort("map: null internal state escaped"); + case let p: *opaque => + return (k, p); + }; + }; + it.gi += 1; + it.si = 0; + }; + + return done; +}; diff --git a/ds/map/swiss/map.ha b/ds/map/swiss/map.ha index daf694690c3ea8876a429439b952c3c7d9b30b01..530928b6aa33d6a9afa6fa8aaef3460cbbee7f3a 100644 --- a/ds/map/swiss/map.ha +++ b/ds/map/swiss/map.ha @@ -21,9 +21,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); diff --git a/ds/map/swiss_fnv/iter.ha b/ds/map/swiss_fnv/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..01e7a4145dabeef29f6c970752ed1cdc1df93ef7 --- /dev/null +++ b/ds/map/swiss_fnv/iter.ha @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: Apache-2.0 AND MPL-2.0 +// SPDX-FileCopyrightText: 2025 Runxi Yu + +use ds::map; + +export type iterator = map::iterator; + +export fn iter(m: *map) (*map::iterator | nomem) = { + return map::iter(m.inner); +}; diff --git a/ds/map/swiss_fnv/map.ha b/ds/map/swiss_fnv/map.ha index 79b85f7030431200e4352d518c6709db292cd67f..7ff066bbfcaa2604a5b21564794c79b8a2a22622 100644 --- a/ds/map/swiss_fnv/map.ha +++ b/ds/map/swiss_fnv/map.ha @@ -16,9 +16,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); diff --git a/ds/map/swiss_siphash/iter.ha b/ds/map/swiss_siphash/iter.ha new file mode 100644 index 0000000000000000000000000000000000000000..01e7a4145dabeef29f6c970752ed1cdc1df93ef7 --- /dev/null +++ b/ds/map/swiss_siphash/iter.ha @@ -0,0 +1,10 @@ +// SPDX-License-Identifier: Apache-2.0 AND MPL-2.0 +// SPDX-FileCopyrightText: 2025 Runxi Yu + +use ds::map; + +export type iterator = map::iterator; + +export fn iter(m: *map) (*map::iterator | nomem) = { + return map::iter(m.inner); +}; diff --git a/ds/map/swiss_siphash/map.ha b/ds/map/swiss_siphash/map.ha index 15d21ff2abddb7f462d1096c02a25c713d242710..43e9b0264051820a2fcc08f4247111e4f07d58d7 100644 --- a/ds/map/swiss_siphash/map.ha +++ b/ds/map/swiss_siphash/map.ha @@ -17,9 +17,11 @@ getter = &vt_get, setter = &vt_set, deleter = &vt_del, finisher = &vt_finish, + iter = &vt_iter, }; fn vt_get(m: *map::map, key: []u8) (*opaque | void) = get(m: *map, key); fn vt_set(m: *map::map, key: []u8, v: *opaque) (void | nomem) = set(m: *map, key, v); fn vt_del(m: *map::map, key: []u8) (*opaque | void) = del(m: *map, key); fn vt_finish(m: *map::map) void = finish(m: *map); +fn vt_iter(m: *map::map) (*map::iterator | nomem) = iter(m: *map); -- 2.48.1