Skip to content

Commit 459a38a

Browse files
committed
Wrap raw::IndexedValue with a C struct to avoid alignment errors on non-x86_64 platforms
1 parent 9ef03c0 commit 459a38a

5 files changed

Lines changed: 33 additions & 13 deletions

File tree

build-wheels.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,9 @@ function clean_project {
4545
# Remove compiled files that might cause conflicts
4646
pushd /io/
4747
rm -rf .cache .eggs rust_fst/_ffi.py build *.egg-info
48-
find ./ -name "__pycache__" -type d -print0 |xargs rm -rf --
49-
find ./ -name "*.pyc" -type f -print0 |xargs rm -rf --
48+
find ./ -name "__pycache__" -type d -print0 |xargs -0 rm -rf
49+
find ./ -name "*.pyc" -type f -print0 |xargs -0 rm -rf
50+
find ./ -name "*.so" -type f -print0 |xargs -0 rm -rf
5051
popd
5152
}
5253

fstwrapper/src/lib.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,10 +79,19 @@ macro_rules! mapop_make_next_fn {
7979
pub extern fn $name(ptr: $t) -> *const MapOpItem {
8080
let stream = mutref_from_ptr!(ptr);
8181
match stream.next() {
82-
Some((k, vs)) => to_raw_ptr(
83-
MapOpItem { key: ::std::ffi::CString::new(k).unwrap().into_raw(),
84-
num_values: vs.len(),
85-
values: vs.as_ptr()}),
82+
Some((k, vs)) => {
83+
let vals: Vec<CIndexedValue> = (0..vs.len()).map(|idx| {
84+
CIndexedValue { index: vs[idx].index,
85+
value: vs[idx].value }
86+
}).collect();
87+
let mut vals_boxed: Box<[CIndexedValue]> = vals.into_boxed_slice();
88+
let vals_ptr: *const CIndexedValue = vals_boxed.as_ptr();
89+
mem::forget(vals_boxed);
90+
to_raw_ptr(MapOpItem {
91+
key: ::std::ffi::CString::new(k).unwrap().into_raw(),
92+
num_values: vs.len(),
93+
values: vals_ptr })
94+
},
8695
None => ::std::ptr::null_mut()
8796
}
8897
}

fstwrapper/src/map.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ extern crate libc;
33
use std::error::Error;
44
use std::fs::File;
55
use std::io;
6+
use std::mem;
67
use std::ptr;
78
use fst::{IntoStreamer, Streamer, Map, MapBuilder};
89
use fst::map;
9-
use fst::raw;
1010
use fst_levenshtein::Levenshtein;
1111
use fst_regex::Regex;
1212

@@ -27,9 +27,16 @@ pub struct MapItem {
2727
pub struct MapOpItem {
2828
key: *const libc::c_char,
2929
num_values: libc::size_t,
30-
values: *const raw::IndexedValue
30+
values: *const CIndexedValue
3131
}
3232

33+
#[repr(C)]
34+
#[derive(Debug)]
35+
#[allow(dead_code)]
36+
pub struct CIndexedValue {
37+
index: libc::size_t,
38+
value: libc::uint64_t,
39+
}
3340

3441
pub type FileMapBuilder = MapBuilder<&'static mut io::BufWriter<File>>;
3542
pub type MemMapBuilder = MapBuilder<Vec<u8>>;

rust_fst/common.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ def __next__(self):
8484
key = ffi.string(itm.key).decode('utf8')
8585
values = []
8686
for n in range(itm.num_values):
87-
v = itm.values[n]
88-
values.append(IndexedValue(int(v.index), v.value))
87+
rust_val = itm.values[n]
88+
values.append(IndexedValue(rust_val.index, rust_val.value))
8989
lib.fst_string_free(itm.key)
9090
lib.fst_map_opitem_free(itm)
9191
return (key, tuple(values))

tests/test_map.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,12 @@ def test_map_union():
9292
b = Map.from_iter({'bar': 32, 'moo': 64})
9393
u = dict(a.union(b))
9494
assert len(u) == 3
95-
assert u['bar'] == ((0, 8), (1, 32))
96-
assert u['baz'] == ((0, 16),)
97-
assert u['moo'] == ((1, 64),)
95+
bar_itms = [(itm.index, itm.value) for itm in u['bar']]
96+
assert bar_itms == [(0, 8), (1, 32)]
97+
baz_itms = [(itm.index, itm.value) for itm in u['baz']]
98+
assert baz_itms == [(0, 16)]
99+
moo_itms = [(itm.index, itm.value) for itm in u['moo']]
100+
assert moo_itms == [(1, 64)]
98101

99102

100103
def test_map_intersection():

0 commit comments

Comments
 (0)