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
use crate::rubysys::{
libc::uintptr_t,
types::{c_int, size_t},
};
// `struct st_table`, Ruby's hash table (`ruby/st.h`); only used through
// pointers.
#[repr(C)]
pub struct StTable {
_private: [u8; 0],
}
// st_data_t: an `unsigned long`, or `unsigned long long` where that is the
// size of a pointer (64-bit Windows).
pub type StData = uintptr_t;
#[cfg_attr(rutie_dllimport, link(name = "rutie_ruby"))]
extern "C" {
// st_table *
// rb_st_init_numtable(void)
//
// An empty table keyed by integers (or pointers); free it with
// `rb_st_free_table`.
pub fn rb_st_init_numtable() -> *mut StTable;
// int
// rb_st_insert(st_table *, st_data_t, st_data_t)
//
// Returns 1 when the key already existed (its value is replaced), else 0.
pub fn rb_st_insert(table: *mut StTable, key: StData, value: StData) -> c_int;
// void
// rb_st_free_table(st_table *)
pub fn rb_st_free_table(table: *mut StTable);
// size_t
// rb_st_table_size(const struct st_table *tbl)
//
// The number of entries in `tbl` (`st_table_size`).
#[cfg(ruby_gte_3_2)]
pub fn rb_st_table_size(table: *const StTable) -> size_t;
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_st_numtable() {
crate::on_ruby_thread(|| unsafe {
let table = rb_st_init_numtable();
assert_eq!(rb_st_insert(table, 1, 10), 0);
assert_eq!(rb_st_insert(table, 2, 20), 0);
assert_eq!(rb_st_insert(table, 1, 11), 1);
#[cfg(ruby_gte_3_2)]
assert_eq!(rb_st_table_size(table), 2);
rb_st_free_table(table);
});
}
}