scaly 0.0.37

Library for the Scaly programming language
Documentation
extern crate libc;
use self::libc::{
    __errno_location, c_int, c_void, close, open, read, unlink, write, O_CREAT, O_RDONLY, O_TRUNC,
    O_WRONLY,
};
use containers::{Ref, String};
use io::{Disposable, IoError, Stream};
use memory::{Page, Region};
use std::ptr::null_mut;

pub struct File {}
impl File {
    pub fn open_read(_pr: &Region, _rp: *mut Page, path: String) -> Result<*mut Stream, IoError> {
        let _r = Region::create(_pr);
        unsafe {
            let file_path = path.to_c_string(_r.page);
            let file_descriptor = open(file_path, O_RDONLY);
            if file_descriptor == -1 {
                return Err(IoError {
                    error_code: (*__errno_location() as i32),
                });
            }
            Ok((*_rp).allocate(FileStream {
                file_descriptor: file_descriptor,
                buffer: null_mut(),
                capacity: 0,
                length: 0,
                position: 0,
            }))
        }
    }

    pub fn open_write(_pr: &Region, _rp: *mut Page, path: String) -> Result<*mut Stream, IoError> {
        let _r = Region::create(_pr);
        unsafe {
            let file_path = path.to_c_string(_r.page);
            let file_descriptor = open(file_path, O_CREAT | O_TRUNC | O_WRONLY, 0o644);
            if file_descriptor == -1 {
                return Err(IoError {
                    error_code: (*__errno_location() as i32),
                });
            }
            Ok((*_rp).allocate(FileStream {
                file_descriptor: file_descriptor,
                buffer: null_mut(),
                capacity: 0,
                length: 0,
                position: 0,
            }))
        }
    }

    pub fn delete(_pr: &Region, path: String) -> Result<(), IoError> {
        let _r = Region::create(_pr);
        unsafe {
            let file_path = path.to_c_string(_r.page);
            let ret = unlink(file_path);
            if ret == -1 {
                return Err(IoError {
                    error_code: (*__errno_location() as i32),
                });
            };
            Ok(())
        }
    }
}

pub struct FileStream {
    file_descriptor: c_int,
    buffer: *mut u8,
    capacity: usize,
    length: usize,
    position: usize,
}

impl Disposable for FileStream {
    fn dispose(&self) {
        unsafe {
            close(self.file_descriptor);
        }
    }
}

impl Stream for FileStream {
    fn read_byte(&mut self) -> Result<i32, IoError> {
        unsafe {
            if self.buffer == null_mut() {
                let exclusive_page =
                    (*Page::own(Ref::from(self as *mut FileStream))).allocate_exclusive_page();
                self.capacity = (*exclusive_page).get_capacity::<u8>();
                self.buffer = (*exclusive_page).allocate_raw(self.capacity, 1) as *mut u8;
                let bytes_read = read(
                    self.file_descriptor,
                    self.buffer as *mut c_void,
                    self.capacity,
                );
                if bytes_read == -1 {
                    return Err(IoError {
                        error_code: (*__errno_location() as i32),
                    });
                }
                if bytes_read == 0 {
                    return Ok(-1);
                }
                self.length = bytes_read as usize;
            }

            if self.position == self.length {
                let bytes_read = read(
                    self.file_descriptor,
                    self.buffer as *mut c_void,
                    self.capacity,
                );
                if bytes_read == -1 {
                    return Err(IoError {
                        error_code: (*__errno_location() as i32),
                    });
                }
                if bytes_read == 0 {
                    return Ok(-1);
                }
                self.length = bytes_read as usize;
                self.position = 0;
            }

            let the_byte = *(self.buffer.offset(self.position as isize));
            self.position += 1;
            Ok(the_byte as i32)
        }
    }

    fn write_byte(&mut self, the_byte: u8) -> Result<(), IoError> {
        unsafe {
            let bytes_written = write(
                self.file_descriptor,
                &the_byte as *const u8 as *const c_void,
                1,
            );

            if bytes_written == 1 {
                Ok(())
            } else {
                Err(IoError {
                    error_code: (*__errno_location() as i32),
                })
            }
        }
    }
}

#[test]
fn test_file() {
    use io::stream::Disposer;
    use memory::Heap;
    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 _r = Region::create_from_page(root_page);
        match File::open_read(
            &_r,
            root_page,
            String::from_string_slice(root_page, "/tmp/0.scaly"),
        ) {
            Ok(file_in) => unsafe {
                let _file_in_disposer = Disposer { stream: file_in };
                match File::open_write(
                    &_r,
                    root_page,
                    String::from_string_slice(root_page, "/tmp/1.scaly"),
                ) {
                    Ok(file_out) => {
                        let _file_out_disposer = Disposer { stream: file_out };
                        loop {
                            match (*file_in).read_byte() {
                                Ok(the_byte) => {
                                    if the_byte == -1 {
                                        break;
                                    }
                                    match (*file_out).write_byte(the_byte as u8) {
                                        Err(_) => break,
                                        Ok(_) => (),
                                    }
                                }
                                Err(_) => break,
                            }
                        }
                    }
                    Err(_) => (),
                }
            },
            Err(_) => (),
        };

        match File::delete(&_r, String::from_string_slice(root_page, "/tmp/1.scaly")) {
            Ok(_) => (),
            Err(_) => (),
        }
    }
}