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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
extern crate libc;

use self::libc::c_char;
use self::libc::strlen;
use memory::Page;
use std::mem::size_of;
use std::ptr;

pub struct String {
    pub data: *const u8,
}

const PACKED_SIZE: usize = size_of::<usize>() * 8 / 7;

impl String {
    pub fn create(page: *mut Page, data: *const u8, length: usize) -> String {
        let mut length_array: [u8; PACKED_SIZE] = [0; PACKED_SIZE];
        let mut rest = length;
        let mut counter: usize = 0;
        while rest >= 0x80 {
            length_array[counter] = rest as u8 | 0x80;
            rest >>= 7;
            counter += 1;
        }
        length_array[counter] = rest as u8;
        let overall_length = counter + 1 + length;
        unsafe {
            let pointer = (*page).allocate_raw(overall_length, 1);
            ptr::copy_nonoverlapping(length_array.as_ptr(), pointer, counter + 1);
            ptr::copy_nonoverlapping(data, pointer.offset((counter + 1) as isize), length);
            String { data: pointer }
        }
    }

    pub fn new(page: *mut Page, string: &str) -> String {
        let length = string.len();
        String::create(page, string.as_ptr(), length)
    }

    pub fn from_c_string(page: *mut Page, c_string: *const c_char) -> String {
        unsafe {
            let length = strlen(c_string);
            String::create(page, c_string as *const u8, length)
        }
    }

    pub fn get_length(&self) -> usize {
        let mut result: usize = 0;
        let mut bit_count = 0;
        let mut index = 0;
        loop {
            if bit_count == PACKED_SIZE * 7 {
                panic!("Bad string length.");
            }

            let byte: u8 = unsafe { *(self.data.offset(index)) };
            result |= ((byte & 0x7F) as usize) << bit_count;
            if (byte & 0x80) == 0 {
                break;
            }
            bit_count += 7;
            index += 1;
        }
        result
    }
}

#[test]
fn test_string() {
    use memory::Heap;
    use memory::Page;
    use memory::StackBucket;
    let mut heap = Heap::create();
    let root_stack_bucket = StackBucket::create(&mut heap);
    {
        let root_page = Page::get(root_stack_bucket as usize);
        let string = String::new(root_page, "Hello world!");
        let length = string.get_length();
        assert_eq!(length, 12);
        let long_string = String::new(root_page, "1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
        assert_eq!(long_string.get_length(), 130);
    }
}