1extern crate memmap;
13#[cfg(test)]
14extern crate tempfile;
15
16mod mmap_util;
17use mmap_util::*;
18mod iter;
19use iter::*;
20mod filter;
21use filter::*;
22mod ints;
23pub use ints::*;
24
25#[allow(unused_imports)]
26use std::mem::{size_of, size_of_val};
27use std::fs::{File};
28use std::io::{self, Write};
29use std::str::FromStr;
30
31use memmap::{Mmap, MmapMut};
32
33pub const MAGIC_NUMBER: u64 = 0x4242_0868_7537_8673;
35pub const FILE_FORMAT_VERSION: u16 = 0;
37
38#[derive(Debug)]
39pub struct Storage {
40 header: Header,
41 file: File,
42 mmap: MmapMut,
43}
44
45impl Storage {
46 pub fn create(file: File, schema: &str) -> io::Result<Storage> {
47 let header = Header::new(schema).unwrap();
48 file.set_len(10*1024*1024)?;
50 let mmap = unsafe { MmapMut::map_mut(&file)? };
51
52 let mut s = Storage { header, file, mmap };
53
54 s.persist()?;
55
56 Ok(s)
57 }
58
59 fn calc_required_space(&self) -> u64 {
60 let header = self.header.serialized_size();
61
62 header + self.header.n_tuples * self.header.schema.data_size
63 }
64 fn calc_offset_location(&self, offset: u64) -> u64 {
65 assert!(offset <= self.header.n_tuples, "Storage::calc_offset_location({}) too big - n_tuples: {}", offset, self.header.n_tuples);
66 let header = self.header.serialized_size();
67
68 header + offset * self.header.schema.data_size
69 }
70
71 pub fn persist(&mut self) -> io::Result<()> {
72 let space = self.calc_required_space();
73 self.file.set_len(space)?;
74 self.header.persist(&mut self.mmap);
75 self.mmap.flush()?;
76 Ok( () )
77 }
78
79 pub fn open(file: File) -> io::Result<Storage> {
80 file.set_len(10*1024*1024)?;
82 let mut reader = MmapReader::new(&file)?;
83 let header = Header::open(&mut reader).unwrap();
84
85 let mmap = unsafe { MmapMut::map_mut(&file)? };
86 Ok(Storage { header, file, mmap })
87 }
88
89 pub fn insert(&mut self, tuple: &mut Tuple) -> Result<(), SchemaError> {
92 self.header.schema.matches(&tuple)?;
93
94 if self.iter().any(|t| t.data[0] == tuple.data[0]) {
96 return Err(SchemaError::DuplicateKey)
97 }
98
99 let mut current_offset = self.calc_required_space();
101 let new_size = current_offset + self.header.schema.data_size;
102 assert!(self.file.set_len(new_size).is_ok(), "Storage::insert file.set_len({}) failed", new_size);
103 assert!((new_size as usize) <= self.mmap.len(), "Storage::insert: out of mapped space");
104
105 let start = self.iter().enumerate()
106 .fold(0, |b, (i, t)| {
107 if t.data[0] < tuple.data[0] {
109 i as u64
110 } else {
111 b
112 }
113 });
114 if start < self.header.n_tuples {
116 let mut i = self.header.n_tuples;
118 while i > start {
119 let offset = self.calc_offset_location(i);
121 let mut last = self.get(i - 1).expect("Storage::insert moving out of range");
122 let mut writer = MmapWriter::at_offset(
123 &mut self.mmap,
124 offset as usize);
125 last.persist(&mut writer);
126
127 i -= 1;
128 }
129
130 current_offset = self.calc_offset_location(start);
131 }
132
133 let mut writer = MmapWriter::at_offset(&mut self.mmap, current_offset as usize);
134
135 tuple.persist(&mut writer);
136
137 self.header.n_tuples += 1;
138 Ok( () )
139 }
140
141
142 pub fn append(&mut self, tuple: &mut Tuple) -> Result<(), SchemaError> {
144 self.header.schema.matches(&tuple)?;
145
146 let current_offset = self.calc_required_space();
148 let new_size = current_offset + self.header.schema.data_size;
149 assert!(self.file.set_len(new_size).is_ok(), "Storage::append file.set_len({}) failed", new_size);
150 assert!((new_size as usize) <= self.mmap.len(), "Storage::append: out of mapped space");
151
152 let mut writer = MmapWriter::at_offset(&mut self.mmap, current_offset as usize);
153
154 tuple.persist(&mut writer);
155
156 self.header.n_tuples += 1;
157 Ok( () )
158 }
159
160 pub fn update(&mut self, tuple: &mut Tuple) -> Result<usize, SchemaError> {
164 self.header.schema.matches(tuple)?;
165 let mut count = 0;
166
167 for i in 0..self.header.n_tuples {
168 let t = self.get(i).expect("Tuple must exist in Range");
169 if tuple.data[0] == t.data[0] {
170 let current_offset = self.header.serialized_size()
171 + i as u64 * self.header.schema.data_size;
172 let mut writer = MmapWriter::at_offset(&mut self.mmap, current_offset as usize);
173 tuple.persist(&mut writer);
174 count += 1;
175 }
176 }
177
178 Ok(count)
179 }
180
181 pub fn remove_all(&mut self, filter: &Filter) -> usize {
184 let mut deleted = 0;
186
187 for i in (0..self.header.n_tuples).map(|i| i).rev() {
188 let tuple = self.get(i).expect("in Range access current");
189 if filter.matches(&tuple) {
191 let mut last = self.get(self.header.n_tuples - 1).expect("in Range access last");
192
193 let current_offset = self.calc_offset_location(i);
194 let mut writer = MmapWriter::at_offset(&mut self.mmap, current_offset as usize);
195 last.persist(&mut writer);
196
197 deleted += 1;
198 self.header.n_tuples -= 1;
199 }
200 }
201
202 deleted
203 }
204 pub fn remove(&mut self, filter: &Filter) -> usize {
206 let mut deleted = 0;
208
209 let mut i = 0;
210 while i < self.header.n_tuples {
211 let tuple = self.get(i).expect("in Range access current");
212 if filter.matches(&tuple) {
214 for j in i+1..self.header.n_tuples {
215 let mut current = self.get(j).expect("in Range access moving");
216 let offset = self.calc_offset_location(j-1);
218 let mut writer = MmapWriter::at_offset(&mut self.mmap, offset as usize);
219 current.persist(&mut writer);
220 }
221
222 deleted += 1;
223 self.header.n_tuples -= 1;
224 } else {
225 i += 1;
226 }
227 }
228
229 deleted
230 }
231
232 pub fn iter(&self) -> StorageIterator {
233 StorageIterator::new(self)
234 }
235 pub fn get(&self, offset: u64) -> Option<Tuple> {
240 if offset < self.header.n_tuples {
241 let offset = self.calc_offset_location(offset);
242
243 let mut reader = MmapReader::at_offset(&self.file, offset as usize).unwrap();
244
245 Some(Tuple::from(&mut reader, &self.header.schema))
246 } else {
247 None
248 }
249 }
250
251 pub fn create_filter(&self, filter: &str) -> Result<Filter, SchemaParseError> {
252 Filter::create(&self.header.schema, filter)
253 }
254
255 pub fn schema_to_string(&self) -> String {
256 format!("({})", self.header.schema.schema.join(", "))
257 }
258}
259impl Drop for Storage {
260 fn drop(&mut self) {
261 assert!(self.persist().is_ok());
262 assert!(self.mmap.flush().is_ok());
263 assert!(self.file.flush().is_ok());
264 }
265}
266impl std::cmp::PartialEq for Storage {
267 fn eq(&self, other: &Self) -> bool {
268 self.header == other.header && self.iter().zip(other.iter()).all(|(a, b)| a == b)
269 }
270}
271
272#[derive(Debug, PartialEq)]
273pub struct Header {
274 magic_number: u64,
275 format_version: u16,
276 header_size: u16,
278 n_tuples: u64,
279 schema: Schema,
280}
281
282impl Header {
283 fn new(schema: &str) -> Result<Header, SchemaParseError> {
284 Ok(Header {
285 magic_number: MAGIC_NUMBER,
286 format_version: FILE_FORMAT_VERSION,
287 header_size: Self::base_size(),
288 n_tuples: 0,
289 schema: schema.parse()?,
290 })
291 }
292
293 fn open(reader: &mut MmapReader) -> Result<Header, SchemaParseError> {
294 use SchemaParseError::*;
295
296 if &MAGIC_NUMBER != reader.get() {
297 return Err(InvalidMagicNumber)
298 }
299 if &FILE_FORMAT_VERSION != reader.get() {
300 return Err(InvalidFileFormatVersion)
301 }
302 let header_size = reader.get();
303 if *header_size < Self::base_size() {
304 return Err(HeaderSizeTooSmall(*header_size))
305 }
306 let n_tuples = reader.get();
307
308 let slice = reader.get_str_slice((header_size - Self::base_size()) as usize);
309
310 let schema = slice.parse().unwrap();
312
313
314 Ok(Header {
315 magic_number: MAGIC_NUMBER,
316 format_version: FILE_FORMAT_VERSION,
317 header_size: *header_size,
318 n_tuples: *n_tuples,
319 schema,
320 })
321 }
322
323 fn base_size() -> u16 {
324 let size = size_of::<u64>()
325 + size_of::<u16>()
326 + size_of::<u16>()
327 + size_of::<u64>()
328 ;
330
331 assert!(size <= u16::max_value() as usize, "base_size outgrew data_type {}", size);
332 size as u16
333 }
334
335 fn serialized_size(&self) -> u64 {
336 Self::base_size() as u64 + self.schema.serialized_size()
337 }
338
339 fn persist(&mut self, mmap: &mut MmapMut) {
340 self.header_size = self.serialized_size() as u16;
341
342 let mut writer = MmapWriter::new(mmap);
343
344 writer.append(&self.magic_number);
345 writer.append(&self.format_version);
346 writer.append(&(self.serialized_size() as u16));
347 writer.append(&self.n_tuples);
348
349 self.schema.persist(&mut writer);
350 }
351}
352
353#[derive(Debug, PartialEq)]
354pub struct Schema {
355 schema: Vec<String>,
356 data_size: u64,
358}
359
360impl FromStr for Schema {
361 type Err = SchemaParseError;
362
363 fn from_str(s: &str) -> Result<Self, Self::Err> {
364 let schema = s.trim_matches(|p| p == '(' || p == ')' )
365 .split(",")
366 .map(|s| s.trim())
367 .map(|s| {
368 match s {
369 "u64" | "i64" | "u32" | "i32" | "u16" | "i16" | "u8" | "i8" => Ok(s.into()),
370 t => Err(SchemaParseError::InvalidType(t.into()))
371 }
372 })
373 .collect::<Result<Vec<String>, Self::Err>>()?;
374
375 let data_size = schema.iter()
376 .map(|s: &String| {
377 match &**s {
378 "u64" | "i64" => 8,
379 "u32" | "i32" => 4,
380 "u16" | "i16" => 2,
381 "u8" | "i8" => 1,
382 _ => panic!("unhandled type {:?}", s),
383 }
384 })
385 .sum();
386
387 Ok(Schema { schema, data_size })
388 }
389
390}
391
392impl Schema {
393 fn serialize_schema(&self) -> String {
394 let mut s = "(".to_string();
395
396 s += &self.schema.join(",");
397
398 s += ")";
399 s
400 }
401
402 fn serialized_size(&self) -> u64 {
403 self.serialize_schema().len() as u64
405 }
406
407 fn persist(&mut self, writer: &mut MmapWriter) {
408 let schema = self.serialize_schema();
409 writer.append_slice(&schema.as_bytes());
410 }
411
412 fn matches(&self, tuple: &Tuple) -> Result<(), SchemaError> {
413 use SchemaError::*;
414 if self.schema.len() != tuple.data.len() {
415 return Err(MismatchedLength)
416 }
417 for (s, t) in self.schema.iter().zip(tuple.data.iter()) {
418 let t_s = t.str_repr();
419 if s != t_s {
420 return Err(InvalidType(t_s.into()))
421 }
422 }
423 Ok( () )
424 }
425}
426
427#[derive(Debug, PartialEq)]
428pub enum SchemaParseError {
429 InvalidType(String),
430 InvalidMagicNumber,
431 InvalidFileFormatVersion,
432 HeaderSizeTooSmall(u16),
433 FilterInvalidOperand(String),
434}
435
436#[derive(Debug, PartialEq)]
437pub enum SchemaError {
438 MismatchedLength,
439 InvalidType(String),
440 DuplicateKey,
441}
442
443#[derive(Debug, PartialEq)]
444pub struct Tuple {
445 data: Vec<Ints>,
446}
447
448impl Tuple {
449 pub fn new(data: Vec<Ints>) -> Tuple {
450 Tuple { data }
451 }
452
453 pub fn from(reader: &mut MmapReader, schema: &Schema) -> Tuple {
454 let mut data = vec![];
456
457 for t in &schema.schema {
458 let x = match &t[..] {
459 "u64" => U64(*reader.get()),
460 "i64" => I64(*reader.get()),
461 "u32" => U32(*reader.get()),
462 "i32" => I32(*reader.get()),
463 "u16" => U16(*reader.get()),
464 "i16" => I16(*reader.get()),
465 "u8" => U8(*reader.get()),
466 "i8" => I8(*reader.get()),
467 _ => unimplemented!("Tuple::from({:?}) missing type {:?}", schema, t),
468 };
469 data.push(x);
470 }
471
472 Tuple { data }
473 }
474
475 pub fn from_str(storage: &Storage, input: &str) -> Tuple {
476 let ref schema = storage.header.schema;
477 Self::from_schema_and_str(schema, input)
478 }
479
480 fn from_schema_and_str(schema: &Schema, input: &str) -> Tuple {
481 let input = input.trim_matches(|p| p == '(' || p == ')' )
482 .split(",")
483 .map(|s| s.trim())
484 .collect::<Vec<_>>();
485 assert_eq!(schema.schema.len(), input.len(), "Tuple::from_str() input len does not match");
486
487 let mut data = vec![];
488
489 for (t, i) in schema.schema.iter().zip(input.iter()) {
490 let x = match &t[..] {
491 "u64" => U64(i.parse().unwrap()),
492 "i64" => I64(i.parse().unwrap()),
493 "u32" => U32(i.parse().unwrap()),
494 "i32" => I32(i.parse().unwrap()),
495 "u16" => U16(i.parse().unwrap()),
496 "i16" => I16(i.parse().unwrap()),
497 "u8" => U8 (i.parse().unwrap()),
498 "i8" => I8 (i.parse().unwrap()),
499 _ => unimplemented!("Tuple::from({:?}) missing type {:?}", schema, t),
500 };
501 data.push(x);
502 }
503
504 Tuple { data }
505 }
506
507 fn persist(&mut self, writer: &mut MmapWriter) {
508 for val in &self.data {
510 match val {
511 U64(value) => writer.append(value),
512 I64(value) => writer.append(value),
513 U32(value) => writer.append(value),
514 I32(value) => writer.append(value),
515 U16(value) => writer.append(value),
516 I16(value) => writer.append(value),
517 U8(value) => writer.append(value),
518 I8(value) => writer.append(value),
519 }
520 }
521 }
522
523 pub fn to_string(&self) -> String {
524 let mut parts = vec![];
525
526 for val in &self.data {
527 parts.push(match val {
528 U64(value) => format!("{}", value),
529 I64(value) => format!("{}", value),
530 U32(value) => format!("{}", value),
531 I32(value) => format!("{}", value),
532 U16(value) => format!("{}", value),
533 I16(value) => format!("{}", value),
534 U8(value) => format!("{}", value),
535 I8(value) => format!("{}", value),
536 });
537 }
538
539 format!("({})", parts.join(", "))
540 }
541}
542
543
544
545
546#[cfg(test)]
547mod test {
548 use super::*;
549 use tempfile::{TempDir};
550
551
552 fn random_file() -> io::Result<(TempDir, File)> {
553 let dir = tempfile::tempdir()?;
554 println!("{:?}", dir);
555 let path = dir.path().join("demo.ts");
556 let file = std::fs::OpenOptions::new()
557 .read(true).write(true).create(true)
558 .open(&path)?;
559
560 Ok((dir, file))
561 }
562
563 #[test]
572 fn serialize_empty() {
573 let expected = [
574 0x73, 0x86, 0x37, 0x75, 0x68, 0x08, 0x42, 0x42,
575 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00,
576 0x00, 0x00, 0x00, 0x00, 0x28, 0x75, 0x36, 0x34,
577 0x2c, 0x69, 0x36, 0x34, 0x29,
578 ];
579 let (dir, file) = random_file().unwrap();
580 {
581 let mut s = Storage::create(file, "(u64, i64)").unwrap();
582 assert!(s.persist().is_ok());
583 println!("{:?}", s);
584 }
585
586 let r = std::fs::read(dir.path().join("demo.ts")).unwrap();
587
588 assert_eq!(expected, *r);
589
590 }
591
592 #[test]
593 fn deserialize_empty() {
594 let blob = [
595 0x73, 0x86, 0x37, 0x75, 0x68, 0x08, 0x42, 0x42,
596 0x00, 0x00, 0x1d, 0x00, 0x00, 0x00, 0x00, 0x00,
597 0x00, 0x00, 0x00, 0x00, 0x28, 0x75, 0x36, 0x34,
598 0x2c, 0x69, 0x36, 0x34, 0x29,
599 ];
600 let (dir, file) = random_file().unwrap();
601 std::fs::write(dir.path().join("demo.ts"), &blob).is_ok();
602
603 let r = Storage::open(file).unwrap();
604 println!("{:?}", r);
605
606 let (_dir, file) = random_file().unwrap();
607 let expected = Storage::create(file, "(u64, i64)").unwrap();
608
609 assert_eq!(expected, r);
610
611 }
612
613
614
615 #[test]
616 fn serialize_one() {
617 let expected = vec![
618 0x73, 0x86, 0x37, 0x75, 0x68, 0x08, 0x42, 0x42,
619 0x00, 0x00, 0x1d, 0x00, 0x01, 0x00, 0x00, 0x00,
620 0x00, 0x00, 0x00, 0x00, 0x28, 0x75, 0x36, 0x34,
621 0x2c, 0x69, 0x36, 0x34, 0x29,
622 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
624 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
625 ];
626 let (dir, file) = random_file().unwrap();
627 {
628 let mut s = Storage::create(file, "(u64, i64)").unwrap();
629 assert!(s.append(&mut Tuple{ data: vec![U64(12), I64(-64)]}).is_ok());
630 assert!(s.persist().is_ok());
631 println!("{:?}", s);
632 }
633
634 let r = std::fs::read(dir.path().join("demo.ts")).unwrap();
635
636 assert_eq!(expected, r, "\n expected: `{:x?}`\n read: `{:x?}`", expected, r);
637 }
638
639 #[test]
640 fn deserialize_one() {
641 let blob = vec![
642 0x73, 0x86, 0x37, 0x75, 0x68, 0x08, 0x42, 0x42,
643 0x00, 0x00,
645 0x1d, 0x00,
647 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
649 0x28, 0x75, 0x36, 0x34, 0x2c, 0x69, 0x36, 0x34,
651 0x29,
652 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
654 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
655 ];
656 let (dir, file) = random_file().unwrap();
657 std::fs::write(dir.path().join("demo.ts"), &blob).is_ok();
658
659 let r = Storage::open(file).unwrap();
660 println!("{:?}", r);
661
662 let (_dir, file) = random_file().unwrap();
663 let mut expected = Storage::create(file, "(u64, i64)").unwrap();
664 assert!(expected.append(&mut Tuple{ data: vec![U64(12), I64(-64)]}).is_ok());
665 assert!(expected.persist().is_ok());
666
667 assert_eq!(expected, r);
668
669 let mut it = expected.iter();
670 let expected = Tuple { data: vec![ U64(12), I64(-64) ]};
671 assert_eq!(Some(expected), it.next());
672 assert_eq!(None, it.next());
673 }
674
675 #[test]
676 fn update_one() {
677 let blob = vec![
678 0x73, 0x86, 0x37, 0x75, 0x68, 0x08, 0x42, 0x42,
679 0x00, 0x00,
681 0x1d, 0x00,
683 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x28, 0x75, 0x36, 0x34, 0x2c, 0x69, 0x36, 0x34,
687 0x29,
688 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
691 ];
692 let expected = vec![
693 0x73, 0x86, 0x37, 0x75, 0x68, 0x08, 0x42, 0x42,
694 0x00, 0x00,
696 0x1d, 0x00,
698 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700 0x28, 0x75, 0x36, 0x34, 0x2c, 0x69, 0x36, 0x34,
702 0x29,
703 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
705 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
706 ];
707 let (dir, file) = random_file().unwrap();
708 std::fs::write(dir.path().join("demo.ts"), &blob).is_ok();
709
710 let mut s = Storage::open(file).unwrap();
711 println!("{:?}", s);
712
713 let mut t = Tuple { data: vec![ U64(12), I64(64) ]};
714 assert_eq!(Ok(1), s.update(&mut t));
715 s.persist().unwrap();
716
717 let r = std::fs::read(dir.path().join("demo.ts")).unwrap();
718 assert_eq!(expected, r, "\n expected: `{:x?}`\n read: `{:x?}`", expected, r);
719
720 let mut it = s.iter();
721 assert_eq!(Some(t), it.next());
722 assert_eq!(None, it.next());
723 }
724
725 #[test]
726 fn insert_duplicate() {
727 let schema = "(u8, i8)";
728 let (_dir, file) = random_file().unwrap();
729 let mut s = Storage::create(file, schema).unwrap();
730
731 let mut t = Tuple { data: vec![ U8(12), I8(64) ]};
732
733 assert_eq!(Ok(()), s.insert(&mut t));
734 assert_eq!(1, s.header.n_tuples);
735
736 assert_eq!(Err(SchemaError::DuplicateKey), s.insert(&mut t));
737 assert_eq!(1, s.header.n_tuples);
738 }
739
740 #[test]
741 fn insert_sorted() {
742 let schema = "(u8, i8)";
743 let (_dir, file) = random_file().unwrap();
744 let mut s = Storage::create(file, schema).unwrap();
745
746 let mut t0 = Tuple { data: vec![ U8(12), I8(64) ]};
747 assert_eq!(Ok(()), s.insert(&mut t0));
748 assert_eq!(1, s.header.n_tuples);
749
750 let mut t1 = Tuple { data: vec![ U8(8), I8(64) ]};
751 assert_eq!(Ok(()), s.insert(&mut t1));
752 assert_eq!(2, s.header.n_tuples);
753
754 let mut t2 = Tuple { data: vec![ U8(6), I8(64) ]};
755 assert_eq!(Ok(()), s.insert(&mut t2));
756 assert_eq!(3, s.header.n_tuples);
757
758 let mut iter = s.iter();
759 assert_eq!(Some(t2), iter.next(), "t2");
760 assert_eq!(Some(t1), iter.next(), "t1");
761 assert_eq!(Some(t0), iter.next(), "t0");
762 }
763
764 #[test]
765 fn remove_all() {
766 let schema = "(u8, i8)";
767 let (_dir, file) = random_file().unwrap();
768 let mut s = Storage::create(file, schema).unwrap();
769
770 let mut t0 = Tuple { data: vec![ U8(12), I8(64) ]};
771 assert_eq!(Ok(()), s.insert(&mut t0));
772
773 let mut t1 = Tuple { data: vec![ U8(8), I8(64) ]};
774 assert_eq!(Ok(()), s.insert(&mut t1));
775
776 let filter = Filter::Equal(U8(12));
777 assert_eq!(1, s.remove_all(&filter));
778 assert_eq!(1, s.header.n_tuples);
779
780 let mut iter = s.iter();
781 assert_eq!(Some(t1), iter.next(), "t1");
782 assert_eq!(None, iter.next(), "should be empty");
783 }
784
785 #[test]
786 fn remove_mid() {
787 let schema = "(u8, i8)";
788 let (_dir, file) = random_file().unwrap();
789 let mut s = Storage::create(file, schema).unwrap();
790
791 let mut t0 = Tuple { data: vec![ U8(12), I8(64) ]};
792 assert_eq!(Ok(()), s.insert(&mut t0));
793
794 let mut t1 = Tuple { data: vec![ U8(8), I8(64) ]};
795 assert_eq!(Ok(()), s.insert(&mut t1));
796
797 let mut t2 = Tuple { data: vec![ U8(6), I8(64) ]};
798 assert_eq!(Ok(()), s.insert(&mut t2));
799
800 let filter = Filter::Equal(U8(8));
801 assert_eq!(1, s.remove(&filter));
802 assert_eq!(2, s.header.n_tuples);
803
804 let mut iter = s.iter();
805 assert_eq!(Some(t2), iter.next(), "t2");
806 assert_eq!(Some(t0), iter.next(), "t0");
807 assert_eq!(None, iter.next(), "should be empty");
808 }
809
810 #[test]
811 fn remove_first() {
812 let schema = "(u8, i8)";
813 let (_dir, file) = random_file().unwrap();
814 let mut s = Storage::create(file, schema).unwrap();
815
816 let mut t0 = Tuple { data: vec![ U8(12), I8(0) ]};
817 assert_eq!(Ok(()), s.insert(&mut t0));
818
819 let mut t1 = Tuple { data: vec![ U8(8), I8(1) ]};
820 assert_eq!(Ok(()), s.insert(&mut t1));
821
822 let mut t2 = Tuple { data: vec![ U8(6), I8(2) ]};
823 assert_eq!(Ok(()), s.insert(&mut t2));
824
825 let filter = Filter::Less(U8(8));
826 assert_eq!(1, s.remove(&filter));
827 assert_eq!(2, s.header.n_tuples);
828
829 let mut iter = s.iter();
830 assert_eq!(Some(t1), iter.next(), "t1");
831 assert_eq!(Some(t0), iter.next(), "t0");
832 assert_eq!(None, iter.next(), "should be empty");
833 }
834
835 #[test]
836 fn remove_sorted_all() {
837 let schema = "(i8, i8)";
838 let (_dir, file) = random_file().unwrap();
839 let mut s = Storage::create(file, schema).unwrap();
840
841 let mut t0 = Tuple { data: vec![ I8(2), I8(0) ]};
842 assert_eq!(Ok(()), s.insert(&mut t0));
843
844 let mut t1 = Tuple { data: vec![ I8(0), I8(1) ]};
845 assert_eq!(Ok(()), s.insert(&mut t1));
846
847 let mut t2 = Tuple { data: vec![ I8(-1), I8(2) ]};
848 assert_eq!(Ok(()), s.insert(&mut t2));
849
850 let filter = Filter::Greater(I8(-10));
851 assert_eq!(3, s.remove(&filter));
852 assert_eq!(0, s.header.n_tuples);
853
854 let mut iter = s.iter();
855 assert_eq!(None, iter.next(), "should be empty");
856 }
857
858
859
860 #[test]
861 fn schema_to_string() {
862 let schema = "(i8, i8)";
863 let (_dir, file) = random_file().unwrap();
864 let s = Storage::create(file, schema).unwrap();
865
866 assert_eq!(schema, s.schema_to_string());
867 }
868
869 #[test]
870 fn tuple_to_string() {
871 let expected = "(-666, 747)";
872 let t = Tuple { data: vec![ I32(-666), U16(747) ] };
873
874 assert_eq!(expected, t.to_string())
875 }
876}