Skip to content

Commit a0f2ed6

Browse files
committed
Add in-progress code that causes ICE
1 parent 213f7d8 commit a0f2ed6

File tree

11 files changed

+332
-1
lines changed

11 files changed

+332
-1
lines changed

Cargo.toml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,9 @@
33
name = "tinycdb-rs"
44
version = "0.0.1"
55
authors = ["Andrew Dunham <[email protected]>"]
6+
build = "make"
7+
8+
[[bin]]
9+
10+
name = "encode"
11+
path = "util/encode.rs"

Makefile

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
TINYCDB_VERSION := 0.78
2+
TINYCDB_PATH := deps/tinycdb-$(TINYCDB_VERSION)
3+
CFLAGS := -fPIC
4+
5+
all: $(TINYCDB_PATH)/libcdb_pic.a
6+
@cp $< $(OUT_DIR)/libcdb.a
7+
8+
$(TINYCDB_PATH)/libcdb_pic.a:
9+
$(MAKE) -C $(TINYCDB_PATH) piclib

deps/.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,5 @@ tests.out
66
tests-shared.ok
77

88
# Built artifacts
9-
libcdb.a
9+
libcdb*.a
1010
cdb

src/base.rs

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
use std;
2+
use std::mem;
3+
use std::os::errno;
4+
5+
use libc;
6+
use libc::{c_int, c_uint, c_void};
7+
use libc::funcs::posix88::fcntl::open;
8+
use libc::consts::os::posix88::{O_CREAT, O_RDONLY, O_RDWR};
9+
10+
use ffi::ffi;
11+
12+
pub struct CdbError {
13+
code: c_int,
14+
cause: String,
15+
}
16+
17+
impl CdbError {
18+
pub fn new(code: c_int) -> CdbError {
19+
CdbError {
20+
code: code,
21+
cause: String::from_str("TODO"),
22+
}
23+
}
24+
25+
#[inline]
26+
pub fn get_code(&self) -> c_int {
27+
self.code
28+
}
29+
}
30+
31+
pub struct Cdb {
32+
cdb: ffi::cdb,
33+
}
34+
35+
impl Cdb {
36+
pub fn open(path: &str) -> Result<Cdb, CdbError> {
37+
let fd = path.with_c_str(|path| unsafe {
38+
open(path, O_RDONLY, 0)
39+
});
40+
41+
if fd < 0 {
42+
return Err(CdbError::new(errno() as c_int));
43+
}
44+
45+
let mut cdb: ffi::cdb = unsafe { std::mem::zeroed() };
46+
let err = unsafe { ffi::cdb_init(&mut cdb as *mut ffi::cdb, fd) };
47+
if err < 0 {
48+
return Err(CdbError::new(errno() as c_int));
49+
}
50+
51+
Ok(Cdb{
52+
cdb: cdb,
53+
})
54+
}
55+
56+
fn cdb_ptr(&self) -> *const ffi::cdb {
57+
&self.cdb as *const ffi::cdb
58+
}
59+
60+
fn cdb_mut_ptr(&mut self) -> *mut ffi::cdb {
61+
&mut self.cdb as *mut ffi::cdb
62+
}
63+
64+
pub fn find(&mut self, key: &[u8]) -> Option<Vec<u8>> {
65+
let res = unsafe {
66+
ffi::cdb_find(
67+
self.cdb_mut_ptr(),
68+
key.as_ptr() as *const c_void,
69+
key.len() as c_uint,
70+
)
71+
};
72+
if res <= 0 {
73+
return None
74+
}
75+
76+
let ret = Vec::with_capacity(self.cdb.cdb_datalen() as uint);
77+
78+
// TODO: Pretty sure this never returns an error...
79+
unsafe {
80+
ffi::cdb_read(
81+
self.cdb_ptr(),
82+
ret.as_ptr() as *mut c_void,
83+
self.cdb.cdb_datalen(),
84+
self.cdb.cdb_datapos()
85+
)
86+
};
87+
88+
Some(ret)
89+
}
90+
}
91+
92+
#[cfg(test)]
93+
mod tests {
94+
extern crate flate;
95+
extern crate serialize;
96+
97+
use std::io::{File, fs};
98+
use std::path::Path;
99+
use self::flate::inflate_bytes;
100+
use self::serialize::base64::FromBase64;
101+
102+
use super::*;
103+
104+
// De-base64s and decompresses
105+
fn decompress_and_write(input: &[u8], path: &Path) {
106+
let raw = match input.from_base64() {
107+
Err(why) => fail!("Could not decode base64: {}", why),
108+
Ok(val) => val,
109+
};
110+
let decomp = match inflate_bytes(raw.as_slice()) {
111+
None => fail!("Could not inflate bytes: {}"),
112+
Some(val) => val,
113+
};
114+
115+
let mut file = match File::create(path) {
116+
Err(why) => fail!("Couldn't create {}: {}", path.display(), why),
117+
Ok(file) => file,
118+
};
119+
120+
match file.write(decomp.as_slice()) {
121+
Err(why) => fail!("Couldn't write to {}: {}", path.display(), why),
122+
Ok(_) => {},
123+
};
124+
}
125+
126+
fn with_test_file(input: &[u8], name: &str, f: |&str|) {
127+
let p = Path::new(name);
128+
129+
decompress_and_write(input, &p);
130+
f(p.as_str().unwrap());
131+
match fs::unlink(&p) {
132+
Err(why) => println!("Couldn't remove temp file: {}", why),
133+
Ok(_) => {},
134+
};
135+
}
136+
137+
static HelloCDB: &'static [u8] = (
138+
b"7dIxCoAwDAXQoohCF8/QzdUjuOgdXETMVswiiKNTr20qGdydWn7g8/ghY1xj3nHwt4XY\
139+
a4cwNeP/DtohhPlbSioJ7zSR9xx7LTlOHpm39aJuCbbV6+/cc7BG9g8="
140+
);
141+
142+
#[test]
143+
fn test_basic_open() {
144+
with_test_file(HelloCDB, "basic.cdb", |path| {
145+
let c = match Cdb::open(path) {
146+
Err(why) => fail!("Could not open CDB"),
147+
Ok(c) => c,
148+
};
149+
let res = match c.find("one".as_bytes()) {
150+
None => fail!("Could not find 'one' in CDB"),
151+
Some(val) => val,
152+
};
153+
154+
assert!(res.as_slice(), "Hello".as_slice());
155+
});
156+
}
157+
}

src/ffi.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
#[allow(dead_code)]
2+
#[allow(non_camel_case_types)]
3+
pub mod ffi {
4+
use libc::{c_char, c_int, c_uchar, c_uint, c_void};
5+
6+
pub struct cdb {
7+
// File descriptor
8+
pub cdb_fd: c_int,
9+
10+
// Datafile size
11+
cdb_fsize: c_uint,
12+
13+
// End of data ptr
14+
cdb_dend: c_uint,
15+
16+
// mmap'ed file memory
17+
cdb_mem: *const c_uchar,
18+
19+
// Found data
20+
cdb_vpos: c_uint,
21+
cdb_vlen: c_uint,
22+
23+
// Found key
24+
cdb_kpos: c_uint,
25+
cdb_klen: c_uint,
26+
}
27+
28+
// Macros defined in C
29+
impl cdb {
30+
#[inline]
31+
pub fn cdb_datapos(&self) -> c_uint {
32+
self.cdb_vpos
33+
}
34+
35+
#[inline]
36+
pub fn cdb_datalen(&self) -> c_uint {
37+
self.cdb_vlen
38+
}
39+
40+
#[inline]
41+
pub fn cdb_keypos(&self) -> c_uint {
42+
self.cdb_kpos
43+
}
44+
45+
#[inline]
46+
pub fn cdb_keylen(&self) -> c_uint {
47+
self.cdb_klen
48+
}
49+
}
50+
51+
pub struct cdb_find {
52+
cdb_cdbp: *mut cdb,
53+
cdb_hval: c_uint,
54+
cdb_htp: *const c_uchar,
55+
cdb_htab: *const c_uchar,
56+
cdb_htend: *const c_uchar,
57+
cdb_httodo: c_uint,
58+
cdb_key: *const c_void,
59+
cdb_klen: c_uint,
60+
}
61+
62+
pub struct cdb_make {
63+
// File descriptor
64+
pub cdb_fd: c_int,
65+
66+
// Data position so far
67+
cdb_dpos: c_uint,
68+
69+
// Record count so far
70+
cdb_rcnt: c_uint,
71+
72+
// Write buffer
73+
cdb_buf: [c_uchar, ..4096],
74+
75+
// Current buf position
76+
cdb_bpos: *mut c_uchar,
77+
78+
// List of arrays of record infos
79+
// OLD: cdb_rl*
80+
cdb_rec: [*mut c_void, ..256],
81+
}
82+
83+
pub static CDB_PUT_ADD: c_uint = 0;
84+
pub static CDB_PUT_REPLACE: c_uint = 1;
85+
pub static CDB_PUT_INSERT: c_uint = 2;
86+
pub static CDB_PUT_WARN: c_uint = 3;
87+
pub static CDB_PUT_REPLACE0: c_uint = 4;
88+
89+
pub static CDB_FIND: c_uint = 0; // == CDB_PUT_ADD
90+
pub static CDB_FIND_REMOVE: c_uint = 1; // == CDB_PUT_REPLACE
91+
pub static CDB_FIND_FILL0: c_uint = 4; // == CDB_PUT_REPLACE0
92+
93+
94+
#[link(name = "cdb", kind = "static")]
95+
extern "C" {
96+
pub fn cdb_init(cdbp: *mut cdb, fd: c_int) -> c_int;
97+
pub fn cdb_free(cdbp: *mut cdb);
98+
pub fn cdb_read(cdbp: *const cdb, buf: *mut c_void, len: c_uint, pos: c_uint) -> c_int;
99+
pub fn cdb_get(cdbp: *const cdb, len: c_uint, pos: c_uint) -> *const c_void;
100+
101+
pub fn cdb_find(cdbp: *mut cdb, key: *const c_void, klen: c_uint) -> c_int;
102+
pub fn cdb_findinit(cdbfp: *mut cdb_find, cdb: *mut cdb,
103+
key: *const c_void, klen: c_uint) -> c_int;
104+
pub fn cdb_findnext(cdbfp: *mut cdb_find) -> c_int;
105+
106+
107+
}
108+
}

src/lib.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(globs)]
2+
3+
extern crate libc;
4+
5+
mod ffi;
6+
pub mod base;

target/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
*
2+
!.gitignore

util/Makefile

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.SUFFIXES:
2+
3+
all: hello.cdb
4+
5+
%.cdb: %.cdbmake
6+
@cdb -c $@ $<

util/encode.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/// This is a simple helper utility to encode a cdb file for use in our tests.
2+
/// Pass it a filename as the first argument and it will DEFLATE and then
3+
/// Base64 encode the contents, writing the output to stdout.
4+
5+
extern crate flate;
6+
extern crate serialize;
7+
8+
use std::io::File;
9+
use std::os;
10+
use flate::deflate_bytes;
11+
use serialize::base64::{STANDARD, ToBase64};
12+
13+
fn main() {
14+
let args = os::args();
15+
let fname = args[1].as_slice();
16+
17+
let mut file = match File::open(&Path::new(fname)) {
18+
Err(why) => fail!("Couldn't open {}: {}", fname, why.desc),
19+
Ok(file) => file,
20+
};
21+
22+
let s = match file.read_to_end() {
23+
Err(why) => fail!("Couldn't read {}: {}", fname, why.desc),
24+
Ok(s) => s,
25+
};
26+
27+
let deflated = match deflate_bytes(s.as_slice()) {
28+
None => fail!("Error encoding to bytes"),
29+
Some(v) => v,
30+
};
31+
32+
let encoded = deflated.as_slice().to_base64(STANDARD);
33+
print!("{}", encoded);
34+
}

util/hello.cdb

2.06 KB
Binary file not shown.

util/hello.cdbmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
+3,5:one->Hello
2+
+3,7:two->Goodbye
3+

0 commit comments

Comments
 (0)