<commit_before>use header::*;
use constants::*;
use instructions::Instruction as Instr;
use num::FromPrimitive;
use std::fmt;

#[derive(Debug, Default)]
pub struct Runtime {
    interpreter: Interpreter,
    call_stack: Vec<StackFrame>,
}

impl Runtime {
    pub fn new(mut data: Vec<u8>) -> Runtime {
        let mut r = Runtime {
            interpreter: Interpreter::new(data),
            call_stack: Vec::new(),
        };
        r
    }
    pub fn run(&mut self, options: &::Options) {
        debug!("Running...");

        let debug = options.debug;

        loop {
            let res = self.dispatch_frame(debug);
            match res {
                None => {},
                Some(frm) => {self.call_stack.push(frm);},
            }
        }
    }

    fn dispatch_frame(&mut self, debug: bool) -> Option<StackFrame> {
        let ln = self.call_stack.len();
        let mut last_frame = &mut self.call_stack[ln-1];
        return last_frame.dispatch(&mut self.interpreter, debug);
    }
}

#[derive(Debug, Default)]
pub struct Interpreter {
    // File data
    header: RaptorHeader,
    const_table: ConstTable,

    // Rutime stuff
    op_stack: Vec<i32>,
    memory: Vec<i32>,
}

// Should this be here?

#[derive(Debug, Default, Clone)]
pub struct StackFrame {
    locals: Vec<i32>,
    // The index of the first op in the op_stack that should be kept
    return_addr: usize,
    bytecode: Vec<u8>,
    bc_counter: usize
}

impl Interpreter {
    pub fn new(mut data: Vec<u8>) -> Interpreter {
        debug!("Bytecode length: {} bytes", data.len());
        let header = read_header(&data);
        data.drain(..HEADER_SIZE);
        let const_table: ConstTable = read_const_table(data.as_slice());
        debug!("Constant table length: {} bytes", const_table.bc_counter);
        debug!("Bytecode length: {} bytes", data.len());
        data.drain(..const_table.bc_counter);
        let sf = StackFrame {
            bytecode: data,
            ..Default::default()
        };
        let mut i = Interpreter {
            header: header,
            const_table: const_table,
            op_stack: Vec::new(),
            memory: Vec::new(),
        };
        i.memory.resize(i.header.var_count as usize, 0);
        i
    }
}

impl StackFrame {

    fn get_next_4_bytes(&mut self) -> u32 {
        let val = (self.bytecode[self.bc_counter] as u32) << 24 |
        (self.bytecode[self.bc_counter + 1] as u32) << 16 |
        (self.bytecode[self.bc_counter + 2] as u32) << 8 |
        (self.bytecode[self.bc_counter + 3] as u32);
        self.bc_counter += 4;
        debug!("get_next_4_bytes: 0x{:04X}", val);
        val
    }

    fn dispatch(&mut self, inpr: &mut Interpreter, debug: bool) -> Option<StackFrame> {
        use std::ops::*;
        use std::cmp::*;

        // Main loop
        while self.bc_counter != self.bytecode.len() {
            // info!("PC: {}", bc_counter);

            // Use FromPrimitive trait to convert a value to its enum
            let instr = Instr::from_u8(self.bytecode[self.bc_counter]);
            self.bc_counter += 1;

            if instr.is_none() {
                warn!("Unimplemented instruction: {:04X}", self.bytecode[self.bc_counter]);
                continue;
            }

            let instr = instr.unwrap();   // We're sure it's Some here, so unpack it.

            if debug {
                debug!("{:?}", instr);
            }

            macro_rules! push {
                ( $x:expr ) => {
                    inpr.op_stack.push($x);
                };
            }
            macro_rules! pop {
                () => {
                    inpr.op_stack.pop();
                };
            }
            macro_rules! operation {
                ($op:ident) => ({
                    let final_length: usize = inpr.op_stack.len().saturating_sub(2);
                    let val = inpr.op_stack.drain(final_length..).fold(
                        0, |acc, x| acc.$op(x)
                    );
                    push!(val);
                })
            }
            macro_rules! reljump {
                ($op:ident) => ({
                    let top = pop!().unwrap();
                    if top.$op(&0) {
                        reljump!();
                    } else {
                        self.get_next_4_bytes();
                        if debug {debug!("Jump not taken"); }
                    }
                });
                () => ({
                    let offset = (self.get_next_4_bytes() - 1) as i32;
                    // Need this if because you can't have negative usizes
                    if offset > 0 {
                        if debug {debug!("RELJUMP: {}", offset);}
                        self.bc_counter += offset as usize;
                        if offset == 1 {debug!("RELJUMP 1 is redundant. This is a compiler bug")}
                    } else if offset < 0 {
                        if debug {debug!("RELJUMP: {}", offset);}
                        self.bc_counter -= (-offset) as usize;
                    } else {
                        warn!("Invalid reljump offset: 0");
                    }
                });
            }

            macro_rules! push_frame {
                ($id:expr) => ({
                    let func_const = &inpr.const_table.funcs[$id as usize];
                    let mut sf = StackFrame {
                        locals: Vec::new(),
                        ..Default::default()
                    };
                    for _ in 0..func_const.arg_count {
                        sf.locals.push(pop!().unwrap());
                    }
                    sf.return_addr = inpr.op_stack.len();
                    sf.locals.resize((func_const.arg_count + func_const.local_count) as usize, 0);
                    debug!("Pushed new frame: {}    {:?}", $id, sf);
                    debug!("Op stack: {:?}", inpr.op_stack);
                    return Some(sf);
                });
            }
            // TODO: More macros, less code

            match instr {
                Instr::NOP => {},
                Instr::HALT => {
                    println!("HALT issued, stopped execution.");
                    if debug {
                        debug!("Stack: {:?}", inpr.op_stack);
                        debug!("Memory: {:?}", inpr.memory);
                    }
                },
                Instr::ICONST => {
                    let b = self.get_next_4_bytes() as i32;
                    push!(b);
                },
                Instr::POP => { pop!(); },
                Instr::ADD =>       { operation!(add);    },
                Instr::SUB =>       { operation!(sub);    },
                Instr::MULTIPLY =>  { operation!(mul);    },
                Instr::DIVIDE =>    { operation!(div);    },
                Instr::MODULUS =>   { operation!(rem);    },
                Instr::RSHIFT =>    { operation!(shl);    },
                Instr::LSHIFT =>    { operation!(shr);    },
                Instr::AND =>       { operation!(bitand); },
                Instr::OR =>        { operation!(bitor);  },
                Instr::NOT =>       {
                    let val = pop!().unwrap();
                    push!(val.not());
                },
                Instr::COMP => {
                    let a = pop!(); let b = pop!();
                    push!(if a > b {1} else if a < b {-1} else {0});
                },
                Instr::COMP_LT => {
                    let a = pop!(); let b = pop!();
                    push!(if a < b {1} else {0});
                },
                Instr::COMP_EQ => {
                    let a = pop!(); let b = pop!();
                    push!(if a == b {1} else {0});
                },
                Instr::COMP_GT => {
                    let a = pop!(); let b = pop!();
                    push!(if a > b {1} else {0});
                },
                Instr::RELJUMP => {reljump!();},
                Instr::RELJUMP_GT => {reljump!(gt);},
                Instr::RELJUMP_LT => {reljump!(lt);},
                Instr::RELJUMP_EQ => {reljump!(eq);},
                Instr::STORE => {
                    let index = self.get_next_4_bytes() as usize;
                    self.locals[index] = pop!().unwrap();
                },
                Instr::LOAD => {
                    let index = self.get_next_4_bytes() as usize;
                    push!(self.locals[index]);
                },
                Instr::CALL => {
                    let id: u32 = self.get_next_4_bytes();
                    push_frame!(id);
                },
                Instr::RETURN => {
                    let val = pop!();
                    inpr.op_stack.resize(self.return_addr, 0)
                }
                Instr::PRINT => {
                    println!("PRINT: {}", pop!().unwrap());
                },
                Instr::DUMP_STACK => {
                    println!("{:?}", inpr.op_stack);
                },
                Instr::DUMP_GLOBALS => {
                    println!("{:?}", inpr.memory);},
            }
        }
        return None;    // Pop the current frame
    }
}

// TODO: Add tests
<commit_msg>Don't use function call for dispatch_frame<commit_after>use header::*;
use constants::*;
use instructions::Instruction as Instr;
use num::FromPrimitive;
use std::fmt;

#[derive(Debug, Default)]
pub struct Runtime {
    interpreter: Interpreter,
    call_stack: Vec<StackFrame>,
}

impl Runtime {
    pub fn new(mut data: Vec<u8>) -> Runtime {
        let mut r = Runtime {
            interpreter: Interpreter::new(data),
            call_stack: Vec::new(),
        };
        r
    }
    pub fn run(&mut self, options: &::Options) {
        debug!("Running...");

        let debug = options.debug;

        loop {
            // Need to wrap this here to limit the scope of last_frame borrow
            let dispatch_result = {
                let ln = self.call_stack.len();
                let mut last_frame = &mut self.call_stack[ln-1];
                last_frame.dispatch(&mut self.interpreter, debug)
            };
            // Push the new StackFrame, if CALL was issued
            if let Some(frm) = dispatch_result {
                self.call_stack.push(frm);
            }
        }
    }
}

#[derive(Debug, Default)]
pub struct Interpreter {
    // File data
    header: RaptorHeader,
    const_table: ConstTable,

    // Rutime stuff
    op_stack: Vec<i32>,
    memory: Vec<i32>,
}

// Should this be here?

#[derive(Debug, Default, Clone)]
pub struct StackFrame {
    locals: Vec<i32>,
    // The index of the first op in the op_stack that should be kept
    return_addr: usize,
    bytecode: Vec<u8>,
    bc_counter: usize
}

impl Interpreter {
    pub fn new(mut data: Vec<u8>) -> Interpreter {
        debug!("Bytecode length: {} bytes", data.len());
        let header = read_header(&data);
        data.drain(..HEADER_SIZE);
        let const_table: ConstTable = read_const_table(data.as_slice());
        debug!("Constant table length: {} bytes", const_table.bc_counter);
        debug!("Bytecode length: {} bytes", data.len());
        data.drain(..const_table.bc_counter);
        let sf = StackFrame {
            bytecode: data,
            ..Default::default()
        };
        let mut i = Interpreter {
            header: header,
            const_table: const_table,
            op_stack: Vec::new(),
            memory: Vec::new(),
        };
        i.memory.resize(i.header.var_count as usize, 0);
        i
    }
}

impl StackFrame {

    fn get_next_4_bytes(&mut self) -> u32 {
        let val = (self.bytecode[self.bc_counter] as u32) << 24 |
        (self.bytecode[self.bc_counter + 1] as u32) << 16 |
        (self.bytecode[self.bc_counter + 2] as u32) << 8 |
        (self.bytecode[self.bc_counter + 3] as u32);
        self.bc_counter += 4;
        debug!("get_next_4_bytes: 0x{:04X}", val);
        val
    }

    fn dispatch(&mut self, inpr: &mut Interpreter, debug: bool) -> Option<StackFrame> {
        use std::ops::*;
        use std::cmp::*;

        // Main loop
        while self.bc_counter != self.bytecode.len() {
            // info!("PC: {}", bc_counter);

            // Use FromPrimitive trait to convert a value to its enum
            let instr = Instr::from_u8(self.bytecode[self.bc_counter]);
            self.bc_counter += 1;

            if instr.is_none() {
                warn!("Unimplemented instruction: {:04X}", self.bytecode[self.bc_counter]);
                continue;
            }

            let instr = instr.unwrap();   // We're sure it's Some here, so unpack it.

            if debug {
                debug!("{:?}", instr);
            }

            macro_rules! push {
                ( $x:expr ) => {
                    inpr.op_stack.push($x);
                };
            }
            macro_rules! pop {
                () => {
                    inpr.op_stack.pop();
                };
            }
            macro_rules! operation {
                ($op:ident) => ({
                    let final_length: usize = inpr.op_stack.len().saturating_sub(2);
                    let val = inpr.op_stack.drain(final_length..).fold(
                        0, |acc, x| acc.$op(x)
                    );
                    push!(val);
                })
            }
            macro_rules! reljump {
                ($op:ident) => ({
                    let top = pop!().unwrap();
                    if top.$op(&0) {
                        reljump!();
                    } else {
                        self.get_next_4_bytes();
                        if debug {debug!("Jump not taken"); }
                    }
                });
                () => ({
                    let offset = (self.get_next_4_bytes() - 1) as i32;
                    // Need this if because you can't have negative usizes
                    if offset > 0 {
                        if debug {debug!("RELJUMP: {}", offset);}
                        self.bc_counter += offset as usize;
                        if offset == 1 {debug!("RELJUMP 1 is redundant. This is a compiler bug")}
                    } else if offset < 0 {
                        if debug {debug!("RELJUMP: {}", offset);}
                        self.bc_counter -= (-offset) as usize;
                    } else {
                        warn!("Invalid reljump offset: 0");
                    }
                });
            }

            macro_rules! push_frame {
                ($id:expr) => ({
                    let func_const = &inpr.const_table.funcs[$id as usize];
                    let mut sf = StackFrame {
                        locals: Vec::new(),
                        ..Default::default()
                    };
                    for _ in 0..func_const.arg_count {
                        sf.locals.push(pop!().unwrap());
                    }
                    sf.return_addr = inpr.op_stack.len();
                    sf.locals.resize((func_const.arg_count + func_const.local_count) as usize, 0);
                    debug!("Pushed new frame: {}    {:?}", $id, sf);
                    debug!("Op stack: {:?}", inpr.op_stack);
                    return Some(sf);
                });
            }
            // TODO: More macros, less code

            match instr {
                Instr::NOP => {},
                Instr::HALT => {
                    println!("HALT issued, stopped execution.");
                    if debug {
                        debug!("Stack: {:?}", inpr.op_stack);
                        debug!("Memory: {:?}", inpr.memory);
                    }
                },
                Instr::ICONST => {
                    let b = self.get_next_4_bytes() as i32;
                    push!(b);
                },
                Instr::POP => { pop!(); },
                Instr::ADD =>       { operation!(add);    },
                Instr::SUB =>       { operation!(sub);    },
                Instr::MULTIPLY =>  { operation!(mul);    },
                Instr::DIVIDE =>    { operation!(div);    },
                Instr::MODULUS =>   { operation!(rem);    },
                Instr::RSHIFT =>    { operation!(shl);    },
                Instr::LSHIFT =>    { operation!(shr);    },
                Instr::AND =>       { operation!(bitand); },
                Instr::OR =>        { operation!(bitor);  },
                Instr::NOT =>       {
                    let val = pop!().unwrap();
                    push!(val.not());
                },
                Instr::COMP => {
                    let a = pop!(); let b = pop!();
                    push!(if a > b {1} else if a < b {-1} else {0});
                },
                Instr::COMP_LT => {
                    let a = pop!(); let b = pop!();
                    push!(if a < b {1} else {0});
                },
                Instr::COMP_EQ => {
                    let a = pop!(); let b = pop!();
                    push!(if a == b {1} else {0});
                },
                Instr::COMP_GT => {
                    let a = pop!(); let b = pop!();
                    push!(if a > b {1} else {0});
                },
                Instr::RELJUMP => {reljump!();},
                Instr::RELJUMP_GT => {reljump!(gt);},
                Instr::RELJUMP_LT => {reljump!(lt);},
                Instr::RELJUMP_EQ => {reljump!(eq);},
                Instr::STORE => {
                    let index = self.get_next_4_bytes() as usize;
                    self.locals[index] = pop!().unwrap();
                },
                Instr::LOAD => {
                    let index = self.get_next_4_bytes() as usize;
                    push!(self.locals[index]);
                },
                Instr::CALL => {
                    let id: u32 = self.get_next_4_bytes();
                    push_frame!(id);
                },
                Instr::RETURN => {
                    let val = pop!();
                    inpr.op_stack.resize(self.return_addr, 0)
                }
                Instr::PRINT => {
                    println!("PRINT: {}", pop!().unwrap());
                },
                Instr::DUMP_STACK => {
                    println!("{:?}", inpr.op_stack);
                },
                Instr::DUMP_GLOBALS => {
                    println!("{:?}", inpr.memory);},
            }
        }
        return None;    // Pop the current frame
    }
}

// TODO: Add tests
<|endoftext|>


<commit_before>use buffer::Line;
use std::cmp;

#[deriving(Copy, Show)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl Direction {
    pub fn is_right(&self) -> bool {
        match *self {
            Direction::Right => true,
            _                => false
        }
    }
    pub fn is_left(&self) -> bool {
        match *self {
            Direction::Left => true,
            _               => false
        }
    }
}

pub struct Cursor<'c> {
    /// The number of bytes the cursor is along the line. This must always be on a character
    /// boundary.
    pub offset: uint,
    line: &'c mut Line,
}

impl<'c> Cursor<'c> {
    /// Create a new cursor instance
    pub fn new(line: &'c mut Line, offset: uint) -> Cursor<'c> {
        Cursor {
            offset: offset,
            line: line,
        }
    }

    pub fn get_position(&self) -> (uint, uint) {
        (self.get_offset(), self.get_linenum())
    }

    pub fn get_linenum(&self) -> uint {
        self.line.linenum
    }

    pub fn get_offset(&self) -> uint {
        cmp::min(self.line.len(), self.offset)
    }

    pub fn get_actual_offset(&self) -> uint {
        self.offset
    }

    pub fn get_visible_offset(&self) -> uint {
        ::utils::str_width(self.get_line().data.slice_to(self.get_offset()), false, 4)
    }

    pub fn set_offset(&mut self, offset: uint) {
        self.offset = offset;
    }

    /// Moves the cursor forward one character.
    ///
    /// This can’t simply be `self.offset += 1`, because not all UTF-8 codepoints are exactly one
    /// byte long. This function calculates the width of the current codepoint and increments the
    /// offset by that width, ensuring that the cursor will always be on a character boundary.
    pub fn inc_offset(&mut self) {
        let range = self.get_line().data.char_range_at(self.get_offset());
        self.set_offset(range.next);
    }

    /// Moves the cursor back one character.
    ///
    /// See `inc_offset` for why this method is needed.
    pub fn dec_offset(&mut self) {
        let range = self.get_line().data.char_range_at_reverse(self.get_offset());
        self.set_offset(range.next);
    }

    pub fn get_line(&self) -> &Line {
        &*self.line
    }

    pub fn get_line_mut(&mut self) -> &mut Line {
        self.line
    }

    pub fn get_line_length(&self) -> uint {
        self.get_line().len()
    }

    pub fn delete_backward_char(&mut self) {
        let offset = self.get_offset();
        let range = self.get_line().data.char_range_at_reverse(self.get_offset());
        let back = self.offset - range.next;
        self.dec_offset();
        self.get_line_mut().data.remove(offset-back);
    }

    pub fn delete_forward_char(&mut self) {
        let offset = self.get_offset();
        self.get_line_mut().data.remove(offset);
    }

    pub fn insert_char(&mut self, ch: char) {
        let offset = self.get_offset();
        self.get_line_mut().data.insert(offset, ch);
        self.move_right();
    }

    pub fn move_right(&mut self) {
        let line_len = self.get_line().len();
        let current_offset = self.get_offset();
        if line_len > current_offset {
            self.inc_offset();
        }
    }

    pub fn move_left(&mut self) {
        let current_offset = self.get_offset();
        if current_offset > 0 {
            self.dec_offset();
        }
    }

    pub fn get_status_text(&self) -> String {
        let (offset, line_num) = self.get_position();
        format!("({}, {})", offset + 1, line_num + 1)
    }
}

#[cfg(test)]
mod tests {

    use cursor::Cursor;
    use buffer::Line;
    use utils::data_from_str;

    fn setup_cursor<F>(mut f: F) where F: FnMut(Cursor) {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);
        f(cursor);
    }

    #[test]
    fn test_moving_right() {
        setup_cursor( |mut cursor| {
            assert_eq!(cursor.offset, 0);
            cursor.move_right();
            assert_eq!(cursor.offset, 1);
        });
    }

    #[test]
    fn test_moving_left() {
        setup_cursor( |mut cursor| {
            cursor.set_offset(1);

            assert_eq!(cursor.offset, 1);
            cursor.move_left();
            assert_eq!(cursor.offset, 0);
        });
    }

    #[test]
    fn test_get_position() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);
        assert_eq!(cursor.get_position(), (0, 1));
    }

    #[test]
    fn test_get_linenum() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);

        assert_eq!(cursor.get_linenum(), 1);
    }

    #[test]
    fn test_get_offset() {
        setup_cursor( |cursor| {
            assert_eq!(cursor.get_offset(), 0)
        });
    }

    #[test]
    fn test_set_offset() {
        setup_cursor( |mut cursor| {
            cursor.set_offset(3);

            assert_eq!(cursor.offset, 3);
        });
    }

    #[test]
    fn test_moving_to_end_of_line_when_set() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 10);

        assert_eq!(cursor.offset, 10);
        assert_eq!(cursor.get_offset(), 4);
    }

    #[test]
    fn test_get_line_length() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);

        assert_eq!(cursor.get_line_length(), 4);
    }

    #[test]
    fn test_delete_backward_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 1);
            cursor.delete_backward_char();
        }

        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_delete_forward_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 0);
            cursor.delete_forward_char();
        }

        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_insert_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 0);
            cursor.insert_char('x');
        }

        assert_eq!(line.data, data_from_str("xtest"));
    }

    #[test]
    fn test_get_status_text() {
        setup_cursor( |cursor| {
            assert_eq!(cursor.get_status_text(), "(1, 2)".to_string());
        } );
    }

    #[test]
    fn test_tab_width() {
        let ref mut line = Line::new(data_from_str("a\ttest"), 1);
        let cursor = Cursor::new(line, 2);
        assert_eq!(cursor.get_visible_offset(), 4)
    }

}
<commit_msg>Fix deletion at end of line.<commit_after>use buffer::Line;
use std::cmp;

#[deriving(Copy, Show)]
pub enum Direction {
    Up,
    Down,
    Left,
    Right,
}

impl Direction {
    pub fn is_right(&self) -> bool {
        match *self {
            Direction::Right => true,
            _                => false
        }
    }
    pub fn is_left(&self) -> bool {
        match *self {
            Direction::Left => true,
            _               => false
        }
    }
}

pub struct Cursor<'c> {
    /// The number of bytes the cursor is along the line. This must always be on a character
    /// boundary.
    pub offset: uint,
    line: &'c mut Line,
}

impl<'c> Cursor<'c> {
    /// Create a new cursor instance
    pub fn new(line: &'c mut Line, offset: uint) -> Cursor<'c> {
        Cursor {
            offset: offset,
            line: line,
        }
    }

    pub fn get_position(&self) -> (uint, uint) {
        (self.get_offset(), self.get_linenum())
    }

    pub fn get_linenum(&self) -> uint {
        self.line.linenum
    }

    pub fn get_offset(&self) -> uint {
        cmp::min(self.line.len(), self.offset)
    }

    pub fn get_actual_offset(&self) -> uint {
        self.offset
    }

    pub fn get_visible_offset(&self) -> uint {
        ::utils::str_width(self.get_line().data.slice_to(self.get_offset()), false, 4)
    }

    pub fn set_offset(&mut self, offset: uint) {
        self.offset = offset;
    }

    /// Moves the cursor forward one character.
    ///
    /// This can’t simply be `self.offset += 1`, because not all UTF-8 codepoints are exactly one
    /// byte long. This function calculates the width of the current codepoint and increments the
    /// offset by that width, ensuring that the cursor will always be on a character boundary.
    pub fn inc_offset(&mut self) {
        let range = self.get_line().data.char_range_at(self.get_offset());
        self.set_offset(range.next);
    }

    /// Moves the cursor back one character.
    ///
    /// See `inc_offset` for why this method is needed.
    pub fn dec_offset(&mut self) {
        let range = self.get_line().data.char_range_at_reverse(self.get_offset());
        self.set_offset(range.next);
    }

    pub fn get_line(&self) -> &Line {
        &*self.line
    }

    pub fn get_line_mut(&mut self) -> &mut Line {
        self.line
    }

    pub fn get_line_length(&self) -> uint {
        self.get_line().len()
    }

    pub fn delete_backward_char(&mut self) {
        self.move_left();
        self.delete_forward_char();
    }

    pub fn delete_forward_char(&mut self) {
        let offset = self.get_offset();
        self.get_line_mut().data.remove(offset);
    }

    pub fn insert_char(&mut self, ch: char) {
        let offset = self.get_offset();
        self.get_line_mut().data.insert(offset, ch);
        self.move_right();
    }

    pub fn move_right(&mut self) {
        let line_len = self.get_line().len();
        let current_offset = self.get_offset();
        if line_len > current_offset {
            self.inc_offset();
        }
    }

    pub fn move_left(&mut self) {
        let current_offset = self.get_offset();
        if current_offset > 0 {
            self.dec_offset();
        }
    }

    pub fn get_status_text(&self) -> String {
        let (offset, line_num) = self.get_position();
        format!("({}, {})", offset + 1, line_num + 1)
    }
}

#[cfg(test)]
mod tests {

    use cursor::Cursor;
    use buffer::Line;
    use utils::data_from_str;

    fn setup_cursor<F>(mut f: F) where F: FnMut(Cursor) {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);
        f(cursor);
    }

    #[test]
    fn test_moving_right() {
        setup_cursor( |mut cursor| {
            assert_eq!(cursor.offset, 0);
            cursor.move_right();
            assert_eq!(cursor.offset, 1);
        });
    }

    #[test]
    fn test_moving_left() {
        setup_cursor( |mut cursor| {
            cursor.set_offset(1);

            assert_eq!(cursor.offset, 1);
            cursor.move_left();
            assert_eq!(cursor.offset, 0);
        });
    }

    #[test]
    fn test_get_position() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);
        assert_eq!(cursor.get_position(), (0, 1));
    }

    #[test]
    fn test_get_linenum() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);

        assert_eq!(cursor.get_linenum(), 1);
    }

    #[test]
    fn test_get_offset() {
        setup_cursor( |cursor| {
            assert_eq!(cursor.get_offset(), 0)
        });
    }

    #[test]
    fn test_set_offset() {
        setup_cursor( |mut cursor| {
            cursor.set_offset(3);

            assert_eq!(cursor.offset, 3);
        });
    }

    #[test]
    fn test_moving_to_end_of_line_when_set() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 10);

        assert_eq!(cursor.offset, 10);
        assert_eq!(cursor.get_offset(), 4);
    }

    #[test]
    fn test_get_line_length() {
        let ref mut line = Line::new(data_from_str("test"), 1);
        let cursor = Cursor::new(line, 0);

        assert_eq!(cursor.get_line_length(), 4);
    }

    #[test]
    fn test_delete_backward_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 1);
            cursor.delete_backward_char();
        }

        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_delete_forward_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 0);
            cursor.delete_forward_char();
        }

        assert_eq!(line.data, data_from_str("est"));
    }

    #[test]
    fn test_insert_char() {
        let ref mut line = Line::new(data_from_str("test"), 1);

        {
            let mut cursor = Cursor::new(line, 0);
            cursor.insert_char('x');
        }

        assert_eq!(line.data, data_from_str("xtest"));
    }

    #[test]
    fn test_get_status_text() {
        setup_cursor( |cursor| {
            assert_eq!(cursor.get_status_text(), "(1, 2)".to_string());
        } );
    }

    #[test]
    fn test_tab_width() {
        let ref mut line = Line::new(data_from_str("a\ttest"), 1);
        let cursor = Cursor::new(line, 2);
        assert_eq!(cursor.get_visible_offset(), 4)
    }

}
<|endoftext|>


<commit_before>use {TypedDecider, DeciderImpl, MultiDeciderImpl, Decider, MultiDecider, Decision, Result,
     ErrorKind};

use std::sync::atomic::Ordering::{Relaxed, Release};
use std::time::{Instant, Duration};
use std::cmp;
use std::sync::Arc;

use crossbeam::epoch::{self, Atomic, Owned};

impl Decider for GCRA {}

/// This crate's GCRA implementation also allows checking multiple
/// cells at once, assuming that (counter the traffic-shaping
/// properties of GCRA) if a sufficiently long pause (`n*t`) has
/// occurred between cells, the algorithm can accommodate `n` cells.
///
/// As this assumption does not necessarily hold in all circumstances,
/// users of this trait on GCRA limiters should ensure that this is
/// ok.
impl MultiDecider for GCRA {}

impl TypedDecider for GCRA {
    /// In GCRA, negative decisions come with the time at which the
    /// next cell was expected to arrive; client code of GCRA can use
    /// this to decide what to do with the non-conforming cell.
    type T = Instant;
}

#[derive(Debug, Clone)]
/// Implements the virtual scheduling description of the Generic Cell
/// Rate Algorithm, attributed to ITU-T in recommendation I.371
/// Traffic control and congestion control in B-ISDN; from
/// [Wikipedia](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm).
///
///
/// While algorithms like leaky-bucket rate limiters allow cells to be
/// distributed across time in any way, GCRA is a rate-limiting *and*
/// traffic-shaping algorithm. It mandates that a minimum amount of
/// time passes between cells being measured. For example, if your API
/// mandates that only 20 requests can be made per second, GCRA will
/// ensure that each request is at least 50ms apart from the previous
/// request. This makes GCRA suitable for shaping traffic in
/// networking and telecom equipment (it was initially made for
/// asynchronous transfer mode networks), or for outgoing workloads on
/// *consumers* of attention, e.g. distributing outgoing emails across
/// a day.
///
/// In a blatant side-stepping of the above traffic-shaping criteria,
/// this implementation of GCRA comes with an extension that allows
/// measuring multiple cells at once, assuming that if a pause of
/// `n*(the minimum time between cells)` has passed, we can allow a
/// single big batch of `n` cells through. This assumption may not be
/// correct for your application, but if you depend on GCRA's
/// traffic-shaping properties, it's better to not use the `_n`
/// suffixed check functions.
///
/// # Example
/// In this example, we construct a rate-limiter with the GCR
/// algorithm that can accommodate 20 cells per second. This translates
/// to the GCRA parameters τ=1s, T=50ms (that's 1s / 20 cells).
///
/// ```
/// # use ratelimit_meter::{Decider, GCRA, Decision};
/// # use std::time::{Instant, Duration};
/// let mut limiter = GCRA::for_capacity(20).unwrap().cell_weight(1).unwrap().build();
/// let now = Instant::now();
/// let ms = Duration::from_millis(1);
/// assert_eq!(Decision::Yes, limiter.check_at(now).unwrap()); // the first cell is free
/// for i in 0..20 {
///     // Spam a lot:
///     assert_eq!(Decision::Yes, limiter.check_at(now).unwrap(), "at {}", i);
/// }
/// // We have exceeded the bucket capacity:
/// assert!(!limiter.check_at(now).unwrap().is_compliant());
///
/// // After a sufficient time period, cells are allowed again:
/// assert_eq!(Decision::Yes, limiter.check_at(now + ms*50).unwrap());
pub struct GCRA {
    // The "weight" of a single packet in units of time.
    t: Duration,

    // The "capacity" of the bucket.
    tau: Duration,

    // The theoretical arrival time of the next packet.
    tat: Arc<Atomic<Instant>>,
}

/// A builder object that can be used to construct rate-limiters as
/// meters.
pub struct Builder {
    capacity: u32,
    cell_weight: u32,
    time_unit: Duration,
}

/// Constructs a concrete GCRA instance.
impl Builder {
    /// Sets the "weight" of each cell being checked against the
    /// bucket. Each cell fills the bucket by this much.
    pub fn cell_weight(&mut self, weight: u32) -> Result<&mut Builder> {
        if self.cell_weight > self.capacity {
            return Err(
                ErrorKind::InconsistentCapacity(self.capacity, weight).into(),
            );
        }
        self.cell_weight = weight;
        Ok(self)
    }

    /// Sets the "unit of time" within which the bucket drains.
    ///
    /// The assumption is that in a period of `time_unit` (if no cells
    /// are being checked), the bucket is fully drained.
    pub fn per(&mut self, time_unit: Duration) -> &mut Builder {
        self.time_unit = time_unit;
        self
    }

    /// Builds and returns a lock-free, threadsafe GCRA decider. As
    /// there is no difference between this and the method
    /// [`build`](#method.build), this method is deprecated and will
    /// go away in a future release.
    pub fn build_sync(&self) -> GCRA {
        self.build()
    }

    /// Builds a lock-free, threadsafe GCRA decider.
    pub fn build(&self) -> GCRA {
        GCRA {
            t: (self.time_unit / self.capacity) * self.cell_weight,
            tau: self.time_unit,
            tat: Arc::new(Atomic::null()),
        }
    }
}

impl GCRA {
    /// Constructs a builder object for a GCRA rate-limiter with the
    /// given capacity per second, at cell weight=1. See
    /// [`Builder`](struct.Builder.html) for options.
    pub fn for_capacity(capacity: u32) -> Result<Builder> {
        if capacity == 0 {
            return Err(ErrorKind::InconsistentCapacity(capacity, 0).into());
        }
        Ok(Builder {
            capacity: capacity,
            cell_weight: 1,
            time_unit: Duration::from_secs(1),
        })
    }

    /// Constructs a GCRA rate-limiter with the parameters T (the
    /// minimum amount of time that single cells are spaced apart),
    /// tau (τ, the number of cells that fit into this buffer), and an
    /// optional t_at (the earliest instant that the rate-limiter
    /// would accept another cell).
    pub fn with_parameters(t: Duration, tau: Duration, tat: Option<Instant>) -> GCRA {
        match tat {
            Some(ts) => {
                GCRA {
                    t: t,
                    tau: tau,
                    tat: Arc::new(Atomic::new(ts)),
                }
            }
            None => {
                GCRA {
                    t: t,
                    tau: tau,
                    tat: Arc::new(Atomic::null()),
                }
            }
        }
    }
}

impl DeciderImpl for GCRA {
    /// Tests if a single cell can be accommodated by the
    /// rate-limiter. This is a threadsafe, lock-free implementation
    /// of the method described directly in the GCRA algorithm, and is
    /// the fastest.
    fn test_and_update(&mut self, t0: Instant) -> Result<Decision<Instant>> {
        let guard = epoch::pin();
        loop {
            let tat_there = self.tat.load(Relaxed, &guard);
            let tat = match tat_there {
                Some(sh) => **sh,
                None => t0,
            };

            if t0 < tat - self.tau {
                return Ok(Decision::No(tat));
            }
            if self.tat
                .cas_and_ref(tat_there,
                             Owned::new(cmp::max(tat, t0) + self.t),
                             Release,
                             &guard)
                .is_ok() {
                return Ok(Decision::Yes);
            }
        }
    }
}

impl MultiDeciderImpl for GCRA {
    /// Tests if `n` cells can be accommodated by the rate-limiter
    /// and updates rate limiter state iff they can be.
    ///
    /// As this method is an extension of GCRA (using multiplication),
    /// it is likely not as fast (and not as obviously "right") as the
    /// single-cell variant.
    fn test_n_and_update(&mut self, n: u32, t0: Instant) -> Result<Decision<Instant>> {
        let guard = epoch::pin();
        loop {
            let tat_there = self.tat.load(Relaxed, &guard);
            let tat = match tat_there {
                Some(sh) => **sh,
                None => t0,
            };
            let tat = match n {
                0 => t0,
                1 => tat,
                _ => {
                    let weight = self.t * (n - 1);
                    if (weight + self.t) > self.tau {
                        // The bucket capacity can never accommodate this request
                        return Err(ErrorKind::InsufficientCapacity(n).into());
                    }
                    tat + weight
                }
            };
            if t0 < tat - self.tau {
                return Ok(Decision::No(tat));
            }
            let additional_weight = match n {
                0 => Duration::new(0, 0),
                1 => self.t,
                _ => self.t * n,
            };
            if self.tat
                .cas_and_ref(tat_there,
                             Owned::new(cmp::max(tat, t0) + additional_weight),
                             Release,
                             &guard)
                .is_ok() {
                return Ok(Decision::Yes);
            }
        }
    }
}

/// Allows converting from a GCRA builder directly into a
/// GCRA decider. Same as
/// [the borrowed implementation](#impl-From<&'a Builder>), except for
/// owned `Builder`s.
/// # Example:
/// ```
/// use ratelimit_meter::{GCRA, Decider, Decision};
/// let mut gcra: GCRA = GCRA::for_capacity(50).unwrap().into();
/// assert_eq!(Decision::Yes, gcra.check().unwrap());
/// ```
impl From<Builder> for GCRA {
    fn from(b: Builder) -> Self {
        b.build()
    }
}

/// Allows converting a GCRA builder directly into a GCRA decider.
/// # Example:
/// ```
/// use ratelimit_meter::{GCRA, Decider, Decision};
/// let mut gcra: GCRA = GCRA::for_capacity(50).unwrap().cell_weight(2).unwrap().into();
/// assert_eq!(Decision::Yes, gcra.check().unwrap());
/// ```
impl<'a> From<&'a mut Builder> for GCRA {
    fn from(b: &'a mut Builder) -> Self {
        b.build()
    }
}

/// Allows converting a GCRA into a tuple containing its T (the
/// minimum amount of time that single cells are spaced apart), tau
/// (τ, the number of cells that fit into this buffer), and an
/// optional `t_at` (the earliest instant that the rate-limiter would
/// accept another cell).
///
/// These parameters can be used with
/// [`.with_parameters`](#method.with_parameters) to persist and
/// construct a copy of the GCRA rate-limiter.
impl<'a> Into<(Duration, Duration, Option<Instant>)> for &'a GCRA {
    fn into(self) -> (Duration, Duration, Option<Instant>) {
        let guard = epoch::pin();
        let tat = match self.tat.load(Relaxed, &guard) {
            None => None,
            Some(sh) => Some(**sh),
        };
        (self.t, self.tau, tat)
    }
}

/// Allows converting the parameters returned from
/// [`Into<(Duration, Duration,
/// Option<Instant>)>`](#impl-Into<(Duration, Duration, Option<Instant>)>)
/// back into a GCRA.
impl From<(Duration, Duration, Option<Instant>)> for GCRA {
    fn from(params: (Duration, Duration, Option<Instant>)) -> GCRA {
        let (t, tau, tat) = params;
        GCRA::with_parameters(t, tau, tat)
    }
}
<commit_msg>Rustfmt.<commit_after>use {TypedDecider, DeciderImpl, MultiDeciderImpl, Decider, MultiDecider, Decision, Result,
     ErrorKind};

use std::sync::atomic::Ordering::{Relaxed, Release};
use std::time::{Instant, Duration};
use std::cmp;
use std::sync::Arc;

use crossbeam::epoch::{self, Atomic, Owned};

impl Decider for GCRA {}

/// This crate's GCRA implementation also allows checking multiple
/// cells at once, assuming that (counter the traffic-shaping
/// properties of GCRA) if a sufficiently long pause (`n*t`) has
/// occurred between cells, the algorithm can accommodate `n` cells.
///
/// As this assumption does not necessarily hold in all circumstances,
/// users of this trait on GCRA limiters should ensure that this is
/// ok.
impl MultiDecider for GCRA {}

impl TypedDecider for GCRA {
    /// In GCRA, negative decisions come with the time at which the
    /// next cell was expected to arrive; client code of GCRA can use
    /// this to decide what to do with the non-conforming cell.
    type T = Instant;
}

#[derive(Debug, Clone)]
/// Implements the virtual scheduling description of the Generic Cell
/// Rate Algorithm, attributed to ITU-T in recommendation I.371
/// Traffic control and congestion control in B-ISDN; from
/// [Wikipedia](https://en.wikipedia.org/wiki/Generic_cell_rate_algorithm).
///
///
/// While algorithms like leaky-bucket rate limiters allow cells to be
/// distributed across time in any way, GCRA is a rate-limiting *and*
/// traffic-shaping algorithm. It mandates that a minimum amount of
/// time passes between cells being measured. For example, if your API
/// mandates that only 20 requests can be made per second, GCRA will
/// ensure that each request is at least 50ms apart from the previous
/// request. This makes GCRA suitable for shaping traffic in
/// networking and telecom equipment (it was initially made for
/// asynchronous transfer mode networks), or for outgoing workloads on
/// *consumers* of attention, e.g. distributing outgoing emails across
/// a day.
///
/// In a blatant side-stepping of the above traffic-shaping criteria,
/// this implementation of GCRA comes with an extension that allows
/// measuring multiple cells at once, assuming that if a pause of
/// `n*(the minimum time between cells)` has passed, we can allow a
/// single big batch of `n` cells through. This assumption may not be
/// correct for your application, but if you depend on GCRA's
/// traffic-shaping properties, it's better to not use the `_n`
/// suffixed check functions.
///
/// # Example
/// In this example, we construct a rate-limiter with the GCR
/// algorithm that can accommodate 20 cells per second. This translates
/// to the GCRA parameters τ=1s, T=50ms (that's 1s / 20 cells).
///
/// ```
/// # use ratelimit_meter::{Decider, GCRA, Decision};
/// # use std::time::{Instant, Duration};
/// let mut limiter = GCRA::for_capacity(20).unwrap().cell_weight(1).unwrap().build();
/// let now = Instant::now();
/// let ms = Duration::from_millis(1);
/// assert_eq!(Decision::Yes, limiter.check_at(now).unwrap()); // the first cell is free
/// for i in 0..20 {
///     // Spam a lot:
///     assert_eq!(Decision::Yes, limiter.check_at(now).unwrap(), "at {}", i);
/// }
/// // We have exceeded the bucket capacity:
/// assert!(!limiter.check_at(now).unwrap().is_compliant());
///
/// // After a sufficient time period, cells are allowed again:
/// assert_eq!(Decision::Yes, limiter.check_at(now + ms*50).unwrap());
pub struct GCRA {
    // The "weight" of a single packet in units of time.
    t: Duration,

    // The "capacity" of the bucket.
    tau: Duration,

    // The theoretical arrival time of the next packet.
    tat: Arc<Atomic<Instant>>,
}

/// A builder object that can be used to construct rate-limiters as
/// meters.
pub struct Builder {
    capacity: u32,
    cell_weight: u32,
    time_unit: Duration,
}

/// Constructs a concrete GCRA instance.
impl Builder {
    /// Sets the "weight" of each cell being checked against the
    /// bucket. Each cell fills the bucket by this much.
    pub fn cell_weight(&mut self, weight: u32) -> Result<&mut Builder> {
        if self.cell_weight > self.capacity {
            return Err(
                ErrorKind::InconsistentCapacity(self.capacity, weight).into(),
            );
        }
        self.cell_weight = weight;
        Ok(self)
    }

    /// Sets the "unit of time" within which the bucket drains.
    ///
    /// The assumption is that in a period of `time_unit` (if no cells
    /// are being checked), the bucket is fully drained.
    pub fn per(&mut self, time_unit: Duration) -> &mut Builder {
        self.time_unit = time_unit;
        self
    }

    /// Builds and returns a lock-free, threadsafe GCRA decider. As
    /// there is no difference between this and the method
    /// [`build`](#method.build), this method is deprecated and will
    /// go away in a future release.
    pub fn build_sync(&self) -> GCRA {
        self.build()
    }

    /// Builds a lock-free, threadsafe GCRA decider.
    pub fn build(&self) -> GCRA {
        GCRA {
            t: (self.time_unit / self.capacity) * self.cell_weight,
            tau: self.time_unit,
            tat: Arc::new(Atomic::null()),
        }
    }
}

impl GCRA {
    /// Constructs a builder object for a GCRA rate-limiter with the
    /// given capacity per second, at cell weight=1. See
    /// [`Builder`](struct.Builder.html) for options.
    pub fn for_capacity(capacity: u32) -> Result<Builder> {
        if capacity == 0 {
            return Err(ErrorKind::InconsistentCapacity(capacity, 0).into());
        }
        Ok(Builder {
            capacity: capacity,
            cell_weight: 1,
            time_unit: Duration::from_secs(1),
        })
    }

    /// Constructs a GCRA rate-limiter with the parameters T (the
    /// minimum amount of time that single cells are spaced apart),
    /// tau (τ, the number of cells that fit into this buffer), and an
    /// optional t_at (the earliest instant that the rate-limiter
    /// would accept another cell).
    pub fn with_parameters(t: Duration, tau: Duration, tat: Option<Instant>) -> GCRA {
        match tat {
            Some(ts) => {
                GCRA {
                    t: t,
                    tau: tau,
                    tat: Arc::new(Atomic::new(ts)),
                }
            }
            None => {
                GCRA {
                    t: t,
                    tau: tau,
                    tat: Arc::new(Atomic::null()),
                }
            }
        }
    }
}

impl DeciderImpl for GCRA {
    /// Tests if a single cell can be accommodated by the
    /// rate-limiter. This is a threadsafe, lock-free implementation
    /// of the method described directly in the GCRA algorithm, and is
    /// the fastest.
    fn test_and_update(&mut self, t0: Instant) -> Result<Decision<Instant>> {
        let guard = epoch::pin();
        loop {
            let tat_there = self.tat.load(Relaxed, &guard);
            let tat = match tat_there {
                Some(sh) => **sh,
                None => t0,
            };

            if t0 < tat - self.tau {
                return Ok(Decision::No(tat));
            }
            if self.tat
                .cas_and_ref(
                    tat_there,
                    Owned::new(cmp::max(tat, t0) + self.t),
                    Release,
                    &guard,
                )
                .is_ok()
            {
                return Ok(Decision::Yes);
            }
        }
    }
}

impl MultiDeciderImpl for GCRA {
    /// Tests if `n` cells can be accommodated by the rate-limiter
    /// and updates rate limiter state iff they can be.
    ///
    /// As this method is an extension of GCRA (using multiplication),
    /// it is likely not as fast (and not as obviously "right") as the
    /// single-cell variant.
    fn test_n_and_update(&mut self, n: u32, t0: Instant) -> Result<Decision<Instant>> {
        let guard = epoch::pin();
        loop {
            let tat_there = self.tat.load(Relaxed, &guard);
            let tat = match tat_there {
                Some(sh) => **sh,
                None => t0,
            };
            let tat = match n {
                0 => t0,
                1 => tat,
                _ => {
                    let weight = self.t * (n - 1);
                    if (weight + self.t) > self.tau {
                        // The bucket capacity can never accommodate this request
                        return Err(ErrorKind::InsufficientCapacity(n).into());
                    }
                    tat + weight
                }
            };
            if t0 < tat - self.tau {
                return Ok(Decision::No(tat));
            }
            let additional_weight = match n {
                0 => Duration::new(0, 0),
                1 => self.t,
                _ => self.t * n,
            };
            if self.tat
                .cas_and_ref(
                    tat_there,
                    Owned::new(cmp::max(tat, t0) + additional_weight),
                    Release,
                    &guard,
                )
                .is_ok()
            {
                return Ok(Decision::Yes);
            }
        }
    }
}

/// Allows converting from a GCRA builder directly into a
/// GCRA decider. Same as
/// [the borrowed implementation](#impl-From<&'a Builder>), except for
/// owned `Builder`s.
/// # Example:
/// ```
/// use ratelimit_meter::{GCRA, Decider, Decision};
/// let mut gcra: GCRA = GCRA::for_capacity(50).unwrap().into();
/// assert_eq!(Decision::Yes, gcra.check().unwrap());
/// ```
impl From<Builder> for GCRA {
    fn from(b: Builder) -> Self {
        b.build()
    }
}

/// Allows converting a GCRA builder directly into a GCRA decider.
/// # Example:
/// ```
/// use ratelimit_meter::{GCRA, Decider, Decision};
/// let mut gcra: GCRA = GCRA::for_capacity(50).unwrap().cell_weight(2).unwrap().into();
/// assert_eq!(Decision::Yes, gcra.check().unwrap());
/// ```
impl<'a> From<&'a mut Builder> for GCRA {
    fn from(b: &'a mut Builder) -> Self {
        b.build()
    }
}

/// Allows converting a GCRA into a tuple containing its T (the
/// minimum amount of time that single cells are spaced apart), tau
/// (τ, the number of cells that fit into this buffer), and an
/// optional `t_at` (the earliest instant that the rate-limiter would
/// accept another cell).
///
/// These parameters can be used with
/// [`.with_parameters`](#method.with_parameters) to persist and
/// construct a copy of the GCRA rate-limiter.
impl<'a> Into<(Duration, Duration, Option<Instant>)> for &'a GCRA {
    fn into(self) -> (Duration, Duration, Option<Instant>) {
        let guard = epoch::pin();
        let tat = match self.tat.load(Relaxed, &guard) {
            None => None,
            Some(sh) => Some(**sh),
        };
        (self.t, self.tau, tat)
    }
}

/// Allows converting the parameters returned from
/// [`Into<(Duration, Duration,
/// Option<Instant>)>`](#impl-Into<(Duration, Duration, Option<Instant>)>)
/// back into a GCRA.
impl From<(Duration, Duration, Option<Instant>)> for GCRA {
    fn from(params: (Duration, Duration, Option<Instant>)) -> GCRA {
        let (t, tau, tat) = params;
        GCRA::with_parameters(t, tau, tat)
    }
}
<|endoftext|>


<commit_before>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::{WlcView, WlcOutput, Geometry, Point, ResizeEdge};

pub type TreeErr = TryLockError<MutexGuard<'static, Tree>>;
pub type TreeResult = Result<MutexGuard<'static, Tree>, TreeErr>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

#[derive(Debug)]
pub struct Tree {
    root: Node,
    active_container: *const Node,
}

unsafe impl Send for Tree {}

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null(),
        })
    };
}

impl Tree {

    /// Moves the current active container to a new workspace
    pub fn move_container_to_workspace(&mut self, name: &str) {
        if self.get_active_container().is_none() {
            return;
        }
        if let Some(workspace) = self.get_active_workspace() {
            if workspace.get_children().len() == 1 {
                if workspace.get_children()[0].get_children().len() == 0 {
                    warn!("Tried to move a container not made by the user");
                    return;
                }
            }
            if workspace.get_val().get_name().unwrap() == name {
                warn!("Tried to switch to already current workspace");
                return;
            }
        }
        match self.get_active_container().unwrap().get_val().get_type() {
            //ContainerType::Container => {},
            ContainerType::View => {},
            _ => {
                warn!("Tried to switch workspace on a non-view/container");
                return
            }
        }
        if self.get_workspace_by_name(name).is_none() {
            self.add_workspace(name.to_string());
        }
        info!("Moving container {:?} to workspace {}", self.get_active_container(), name);
        let new_active_container = self.get_active_container().unwrap().get_parent().unwrap()
            as *const Node;
        let moved_container: Node;
        {
            let container = self.get_active_container().unwrap().as_mut();

            // Make view invisible, switch focus
            {
                let parent = container.get_parent().expect("Had no parent");
                // There is another view we can focus on
                if parent.get_children().len() > 1 {
                    trace!("Attempting to focus on a view");
                    let mut children_pool: Vec<&Node>  = parent.get_children().iter()
                        .filter(|child| *child != container).collect();
                    while children_pool.len() > 0 {
                        let child = children_pool.pop().unwrap();
                        if child.get_val().get_type() == ContainerType::View {
                            trace!("Focused on a view");
                            match child.get_val().get_handle().unwrap() {
                                Handle::View(view) => view.focus(),
                                _ => panic!("Expect WlcView, got WlcOutput"),
                            }
                            break;
                        } else {
                            let more_children: Vec<&Node> = child.get_children().iter()
                                .collect();
                            children_pool.extend(more_children);
                        }
                    }
                } else {
                    trace!("Focusing on root, because no other views");
                    WlcView::root().focus();
                }
            }
            moved_container = container.remove_from_parent()
                .expect("Could not remove container, was not part of tree");
            container.set_visibility(false);
            trace!("Removed container {:?}", moved_container);
        }
        if let Some(workspace) = self.get_workspace_by_name(name) {
            let new_parent_container = &mut workspace.as_mut().get_children_mut()[0];
            new_parent_container.new_child(moved_container.get_val().clone())
                .expect("Could not moved container to other a workspace");
            trace!("Added previously removed container to {:?} in workspace {}",
                    new_parent_container,
                    name);
        }
        self.active_container = new_active_container;
    }

    /// Switch to the workspace with the give name
    pub fn switch_workspace(&mut self, name: &str ) {
        if self.active_container.is_null() {
            warn!("No current active container, cannot switch workspace");
            return;
        }
        if let Some(old_workspace) = self.get_active_workspace() {
            trace!("Switching to workspace {}", name);
            old_workspace.as_mut().set_visibility(false);
        } else {
            warn!("Could not find old workspace, could not set invisible");
            return;
        }
        if let Some(_) = self.get_workspace_by_name(name) {
            trace!("Found workspace {}", name);
        } else {
            trace!("Adding workspace {}", name);
            self.add_workspace(name.to_string());
        }
        let new_active_container: *const Node;
        {
            if let Some(_) = self.get_workspace_by_name(name) {
                trace!("Found workspace {}", name);
            } else {
                trace!("Adding workspace {}", name);
                self.add_workspace(name.to_string());
            }
            let new_current_workspace = self.get_workspace_by_name_mut(name)
                .expect(ERR_BAD_TREE).as_mut();
            new_current_workspace.set_visibility(true);
            /* Set the first view to be focused, so the screen refreshes itself */
            if new_current_workspace.get_children()[0].get_children().len() > 0 {
                trace!("Focusing view");
                let view_container = &new_current_workspace.get_children_mut()[0]
                    .get_children_mut()[0];
                match view_container.get_val().get_handle().expect(ERR_BAD_TREE) {
                    Handle::View(view) => view.focus(),
                    _ => {panic!("Expected view, got Wlc Output")},
                }
                new_active_container = view_container as *const Node;
            }
            /* If there is no view in the new workspace, just set the focused container
               to be the workspace */
            else {
                new_active_container = new_current_workspace as *const Node;
                WlcView::root().focus();
            }
        }
        // Update the tree's pointer to the currently focused container
        self.active_container = new_active_container;
    }

    /// Returns the currently viewed container.
    /// If multiple views are selected, the parent container they share is returned
    pub fn get_active_container(&self) -> Option<&Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&*self.active_container)
            }
        }
    }

    /// Get the monitor (output) that the active container is located on
    pub fn get_active_output(&self) -> Option<&Node> {
        if let Some(node) = self.get_active_container() {
            if node.get_val().get_type() == ContainerType::Output {
                Some(node)
            } else {
                node.get_ancestor_of_type(ContainerType::Output)
            }
        } else {
            None
        }
    }

    /// Get the workspace that the active container is located on
    pub fn get_active_workspace(&self) -> Option<&Node> {
        if let Some(node) = self.get_active_container() {
            if node.get_val().get_type() == ContainerType::Workspace {
                return Some(node)
            }
            if let Some(workspace) = node.get_ancestor_of_type(ContainerType::Workspace) {
                return Some(workspace)
            }
        }
        return None
    }

    /// Find the workspace node that has the given name
    pub fn get_workspace_by_name(&mut self, name: &str) -> Option<&Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    /// Find the workspace node that has the given name, with a mutable reference
    pub fn get_workspace_by_name_mut(&mut self, name: &str) -> Option<&Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    /// Make a new output container with the given WlcOutput.
    /// This is done when a new monitor is added
    pub fn add_output(&mut self, wlc_output: WlcOutput) {
        trace!("Adding new output with WlcOutput: {:?}", wlc_output);
        match self.root.new_child(Container::new_output(wlc_output)) {
            Ok(output) => {
                // Need to set active container to this output so that
                // add_workspace know where to put the new workspace
                self.active_container = output as *const Node;
            },
            Err(e) => {
                error!("Could not add output: {:?}", e);
                return;
            }
        }
        // NOTE Should probably not be "1", should be the next unclaimed number
        self.active_container = self.add_workspace("1".to_string()).unwrap() as *const Node;
    }

    /// Make a new workspace container with the given name.
    pub fn add_workspace(&mut self, name: String) -> Option<&Node> {
        let mut new_active_container: *const Node = ptr::null();
        if let Some(output) = self.get_active_output() {
            let size = output.get_val().get_geometry()
                .expect("Output did not have a geometry").size;
            let workspace = Container::new_workspace(name.to_string(),
                                                     size.clone());
            match output.as_mut().new_child(workspace) {
                Ok(workspace) => {
                    trace!("Added workspace {:?}", workspace);
                    let geometry = Geometry {
                        size: size,
                        origin: Point { x: 0, y: 0}
                    };
                    match workspace.new_child(Container::new_container(geometry)) {
                        Err(e) => error!("Could not add container to workspace: {:?}",e ),
                        // New active container should be this container of the new workspace
                        Ok(container) => new_active_container = container as *const Node,
                    };
                    return Some(workspace);
                },
                Err(e) => error!("Could not add workspace: {:?}", e),
            }
        } else {
            warn!("Could not get active output");
        }
        None
    }

    /// Make a new view container with the given WlcView, and adds it to
    /// the active workspace.
    pub fn add_view(&mut self, wlc_view: WlcView) {
        let mut maybe_new_view: *const Node = ptr::null();
        if let Some(current_workspace) = self.get_active_workspace() {
            trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
            if current_workspace.get_children().len() == 0 {
                let output = self.get_active_output()
                    .expect("Could not get active output");
                let output_size = output.get_val().get_geometry()
                    .expect("Could not get geometry from output").size;
                let mut geometry = wlc_view.get_geometry()
                    .expect("Could not get geometry from wlc view").clone();
                // Ensure that it starts within the bounds
                // Width
                if geometry.origin.x > output_size.w as i32 {
                    geometry.origin.x = output_size.w as i32 ;
                } else if geometry.origin.x < 0 {
                    geometry.origin.x = 0;
                }
                // Height
                if geometry.origin.y > output_size.h as i32 {
                    geometry.origin.y = output_size.h as i32;
                } else if geometry.origin.y < 0 {
                    geometry.origin.y = 0;
                }
                wlc_view.set_geometry(ResizeEdge::empty(), &geometry);
                match current_workspace.as_mut().new_child(Container::new_container(geometry)) {
                    Ok(_) => {},
                    Err(e) => {
                        error!("Could not add workspace: {:?}", e);
                        return;
                    }
                }
            }
            let container = &mut current_workspace.as_mut().get_children_mut()[0];
            match container.new_child(Container::new_view(wlc_view)) {
                Ok(view_node) => {
                    maybe_new_view = view_node as *const Node;
                },
                Err(e) => {
                    error!("Could not add view to current workspace: {:?}", e);
                    return;
                }
            }
        };
        if ! maybe_new_view.is_null() {
            self.active_container = maybe_new_view as *const Node;
        }
    }

    /// Remove the view container with the given view
    pub fn remove_view(&self, wlc_view: &WlcView) {
        if let Some(view) = self.root.find_view_by_handle(&wlc_view) {
            let parent = view.get_parent().expect(ERR_BAD_TREE);
            parent.remove_child(view);
        }
    }
}

pub fn try_lock_tree() -> TreeResult {
    trace!("Locking the tree!");
    TREE.try_lock()
}
<commit_msg>Added documentation about the Tree<commit_after>//! Main module to handle the layout.
//! This is where the i3-specific code is.

use std::sync::{Mutex, MutexGuard, TryLockError};
use std::ptr;

use super::container::{Container, Handle, ContainerType};
use super::node::{Node};
use super::super::rustwlc::{WlcView, WlcOutput, Geometry, Point, ResizeEdge};

pub type TreeErr = TryLockError<MutexGuard<'static, Tree>>;
pub type TreeResult = Result<MutexGuard<'static, Tree>, TreeErr>;

const ERR_BAD_TREE: &'static str = "Layout tree was in an invalid configuration";

// NOTE Make an actual image of this, embed in documentation
/* An example Tree:

      Root
        |
    ____|____
   /         \
   |         |
 Output    Output
   |         |
 Workspace   |
   |        / \
   |       /   \
   | Workspace Workspace
   |     |         |
   |  Container Container
 Container
    |
   / \
  /   \
  |    \
  |     \
  |      \
  |       \
 Container \
     |      \
   View    View
 */

/// A Tree of Nodes.
///
/// There are various invariants that the tree upholds:
///
///   + Root
///       - There is only one Root
///       - The root can only have Outputs (monitors) as children
///   + Output
///       - An Output must have at least one Workspace associated with it
///       - An Output must be associated with a WlcOutput (real monitor)
///       - An Output can only have Workspaces as children
///   + Workspace
///       - A Workspace must have at least one Container, even if it doesn't
///         contain any views
///       - A Workspace can only have Containers as children
///   + Container
///       - A Container can only have other Containers or Views as children
///   + View
///       - A View must be associated with a WlcView
///       - A View cannot have any children
#[derive(Debug)]
pub struct Tree {
    root: Node,
    active_container: *const Node,
}

unsafe impl Send for Tree {}

lazy_static! {
    static ref TREE: Mutex<Tree> = {
        Mutex::new(Tree{
            root: Node::new(Container::new_root()),
            active_container: ptr::null(),
        })
    };
}

impl Tree {

    /// Moves the current active container to a new workspace
    pub fn move_container_to_workspace(&mut self, name: &str) {
        if self.get_active_container().is_none() {
            return;
        }
        if let Some(workspace) = self.get_active_workspace() {
            if workspace.get_children().len() == 1 {
                if workspace.get_children()[0].get_children().len() == 0 {
                    warn!("Tried to move a container not made by the user");
                    return;
                }
            }
            if workspace.get_val().get_name().unwrap() == name {
                warn!("Tried to switch to already current workspace");
                return;
            }
        }
        match self.get_active_container().unwrap().get_val().get_type() {
            //ContainerType::Container => {},
            ContainerType::View => {},
            _ => {
                warn!("Tried to switch workspace on a non-view/container");
                return
            }
        }
        if self.get_workspace_by_name(name).is_none() {
            self.add_workspace(name.to_string());
        }
        info!("Moving container {:?} to workspace {}", self.get_active_container(), name);
        let new_active_container = self.get_active_container().unwrap().get_parent().unwrap()
            as *const Node;
        let moved_container: Node;
        {
            let container = self.get_active_container().unwrap().as_mut();

            // Make view invisible, switch focus
            {
                let parent = container.get_parent().expect("Had no parent");
                // There is another view we can focus on
                if parent.get_children().len() > 1 {
                    trace!("Attempting to focus on a view");
                    let mut children_pool: Vec<&Node>  = parent.get_children().iter()
                        .filter(|child| *child != container).collect();
                    while children_pool.len() > 0 {
                        let child = children_pool.pop().unwrap();
                        if child.get_val().get_type() == ContainerType::View {
                            trace!("Focused on a view");
                            match child.get_val().get_handle().unwrap() {
                                Handle::View(view) => view.focus(),
                                _ => panic!("Expect WlcView, got WlcOutput"),
                            }
                            break;
                        } else {
                            let more_children: Vec<&Node> = child.get_children().iter()
                                .collect();
                            children_pool.extend(more_children);
                        }
                    }
                } else {
                    trace!("Focusing on root, because no other views");
                    WlcView::root().focus();
                }
            }
            moved_container = container.remove_from_parent()
                .expect("Could not remove container, was not part of tree");
            container.set_visibility(false);
            trace!("Removed container {:?}", moved_container);
        }
        if let Some(workspace) = self.get_workspace_by_name(name) {
            let new_parent_container = &mut workspace.as_mut().get_children_mut()[0];
            new_parent_container.new_child(moved_container.get_val().clone())
                .expect("Could not moved container to other a workspace");
            trace!("Added previously removed container to {:?} in workspace {}",
                    new_parent_container,
                    name);
        }
        self.active_container = new_active_container;
    }

    /// Switch to the workspace with the give name
    pub fn switch_workspace(&mut self, name: &str ) {
        if self.active_container.is_null() {
            warn!("No current active container, cannot switch workspace");
            return;
        }
        if let Some(old_workspace) = self.get_active_workspace() {
            trace!("Switching to workspace {}", name);
            old_workspace.as_mut().set_visibility(false);
        } else {
            warn!("Could not find old workspace, could not set invisible");
            return;
        }
        if let Some(_) = self.get_workspace_by_name(name) {
            trace!("Found workspace {}", name);
        } else {
            trace!("Adding workspace {}", name);
            self.add_workspace(name.to_string());
        }
        let new_active_container: *const Node;
        {
            if let Some(_) = self.get_workspace_by_name(name) {
                trace!("Found workspace {}", name);
            } else {
                trace!("Adding workspace {}", name);
                self.add_workspace(name.to_string());
            }
            let new_current_workspace = self.get_workspace_by_name_mut(name)
                .expect(ERR_BAD_TREE).as_mut();
            new_current_workspace.set_visibility(true);
            /* Set the first view to be focused, so the screen refreshes itself */
            if new_current_workspace.get_children()[0].get_children().len() > 0 {
                trace!("Focusing view");
                let view_container = &new_current_workspace.get_children_mut()[0]
                    .get_children_mut()[0];
                match view_container.get_val().get_handle().expect(ERR_BAD_TREE) {
                    Handle::View(view) => view.focus(),
                    _ => {panic!("Expected view, got Wlc Output")},
                }
                new_active_container = view_container as *const Node;
            }
            /* If there is no view in the new workspace, just set the focused container
               to be the workspace */
            else {
                new_active_container = new_current_workspace as *const Node;
                WlcView::root().focus();
            }
        }
        // Update the tree's pointer to the currently focused container
        self.active_container = new_active_container;
    }

    /// Returns the currently viewed container.
    /// If multiple views are selected, the parent container they share is returned
    pub fn get_active_container(&self) -> Option<&Node> {
        if self.active_container.is_null() {
            None
        } else {
            unsafe {
                Some(&*self.active_container)
            }
        }
    }

    /// Get the monitor (output) that the active container is located on
    pub fn get_active_output(&self) -> Option<&Node> {
        if let Some(node) = self.get_active_container() {
            if node.get_val().get_type() == ContainerType::Output {
                Some(node)
            } else {
                node.get_ancestor_of_type(ContainerType::Output)
            }
        } else {
            None
        }
    }

    /// Get the workspace that the active container is located on
    pub fn get_active_workspace(&self) -> Option<&Node> {
        if let Some(node) = self.get_active_container() {
            if node.get_val().get_type() == ContainerType::Workspace {
                return Some(node)
            }
            if let Some(workspace) = node.get_ancestor_of_type(ContainerType::Workspace) {
                return Some(workspace)
            }
        }
        return None
    }

    /// Find the workspace node that has the given name
    pub fn get_workspace_by_name(&mut self, name: &str) -> Option<&Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    /// Find the workspace node that has the given name, with a mutable reference
    pub fn get_workspace_by_name_mut(&mut self, name: &str) -> Option<&Node> {
        for child in self.root.get_children_mut()[0].get_children_mut() {
            if child.get_val().get_name().expect(ERR_BAD_TREE) != name {
                continue
            }
            return Some(child);
        }
        return None
    }

    /// Make a new output container with the given WlcOutput.
    /// This is done when a new monitor is added
    pub fn add_output(&mut self, wlc_output: WlcOutput) {
        trace!("Adding new output with WlcOutput: {:?}", wlc_output);
        match self.root.new_child(Container::new_output(wlc_output)) {
            Ok(output) => {
                // Need to set active container to this output so that
                // add_workspace know where to put the new workspace
                self.active_container = output as *const Node;
            },
            Err(e) => {
                error!("Could not add output: {:?}", e);
                return;
            }
        }
        // NOTE Should probably not be "1", should be the next unclaimed number
        self.active_container = self.add_workspace("1".to_string()).unwrap() as *const Node;
    }

    /// Make a new workspace container with the given name.
    pub fn add_workspace(&mut self, name: String) -> Option<&Node> {
        let mut new_active_container: *const Node = ptr::null();
        if let Some(output) = self.get_active_output() {
            let size = output.get_val().get_geometry()
                .expect("Output did not have a geometry").size;
            let workspace = Container::new_workspace(name.to_string(),
                                                     size.clone());
            match output.as_mut().new_child(workspace) {
                Ok(workspace) => {
                    trace!("Added workspace {:?}", workspace);
                    let geometry = Geometry {
                        size: size,
                        origin: Point { x: 0, y: 0}
                    };
                    match workspace.new_child(Container::new_container(geometry)) {
                        Err(e) => error!("Could not add container to workspace: {:?}",e ),
                        // New active container should be this container of the new workspace
                        Ok(container) => new_active_container = container as *const Node,
                    };
                    return Some(workspace);
                },
                Err(e) => error!("Could not add workspace: {:?}", e),
            }
        } else {
            warn!("Could not get active output");
        }
        None
    }

    /// Make a new view container with the given WlcView, and adds it to
    /// the active workspace.
    pub fn add_view(&mut self, wlc_view: WlcView) {
        let mut maybe_new_view: *const Node = ptr::null();
        if let Some(current_workspace) = self.get_active_workspace() {
            trace!("Adding view {:?} to {:?}", wlc_view, current_workspace);
            if current_workspace.get_children().len() == 0 {
                let output = self.get_active_output()
                    .expect("Could not get active output");
                let output_size = output.get_val().get_geometry()
                    .expect("Could not get geometry from output").size;
                let mut geometry = wlc_view.get_geometry()
                    .expect("Could not get geometry from wlc view").clone();
                // Ensure that it starts within the bounds
                // Width
                if geometry.origin.x > output_size.w as i32 {
                    geometry.origin.x = output_size.w as i32 ;
                } else if geometry.origin.x < 0 {
                    geometry.origin.x = 0;
                }
                // Height
                if geometry.origin.y > output_size.h as i32 {
                    geometry.origin.y = output_size.h as i32;
                } else if geometry.origin.y < 0 {
                    geometry.origin.y = 0;
                }
                wlc_view.set_geometry(ResizeEdge::empty(), &geometry);
                match current_workspace.as_mut().new_child(Container::new_container(geometry)) {
                    Ok(_) => {},
                    Err(e) => {
                        error!("Could not add workspace: {:?}", e);
                        return;
                    }
                }
            }
            let container = &mut current_workspace.as_mut().get_children_mut()[0];
            match container.new_child(Container::new_view(wlc_view)) {
                Ok(view_node) => {
                    maybe_new_view = view_node as *const Node;
                },
                Err(e) => {
                    error!("Could not add view to current workspace: {:?}", e);
                    return;
                }
            }
        };
        if ! maybe_new_view.is_null() {
            self.active_container = maybe_new_view as *const Node;
        }
    }

    /// Remove the view container with the given view
    pub fn remove_view(&self, wlc_view: &WlcView) {
        if let Some(view) = self.root.find_view_by_handle(&wlc_view) {
            let parent = view.get_parent().expect(ERR_BAD_TREE);
            parent.remove_child(view);
        }
    }
}

pub fn try_lock_tree() -> TreeResult {
    trace!("Locking the tree!");
    TREE.try_lock()
}
<|endoftext|>


<commit_before>/**
A macro for declaring lazily evaluated statics.
Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.

Forked from https://github.com/rust-lang-nursery/lazy-static.rs

This version uses atomics instead of `std::sync::Once`, so it works also for `#![no_std]` builds.
It requires a nightly Rust version.

# Syntax
```text
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```
Metadata (such as doc comments) is allowed on each ref.
# Semantic
For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)
On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.
Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.
# Example
Using the macro:

```rust
#![feature(const_fn)]

#[macro_use]
extern crate once;
use std::collections::HashMap;
lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}
fn times_two(n: u32) -> u32 { n * 2 }
fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```
# Implementation details
The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access.
**/
#[macro_export]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(MAKE TY, $VIS, $(#[$attr])*, $N);
        impl $crate::__core::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                #[inline(always)]
                fn __static_ref_initialize() -> $T { $e }

                unsafe {
                    use $crate::__core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

                    #[inline(always)]
                    fn require_sync<T: Sync>(_: &T) { }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        use $crate::__core::cell::UnsafeCell;

                        struct SyncCell(UnsafeCell<Option<$T>>);
                        unsafe impl Sync for SyncCell {}

                        static DATA: SyncCell = SyncCell(UnsafeCell::new(None));
                        static INITIALIZED: AtomicUsize = ATOMIC_USIZE_INIT;

                        if INITIALIZED.load(Ordering::Relaxed) != 2 {
                            // not initialized yet

                            // set state to `initializing`
                            match INITIALIZED.compare_and_swap(0, 1, Ordering::Relaxed) {
                                0 => {
                                    // initialize
                                    *DATA.0.get() = Some(__static_ref_initialize());
                                    // set state to `initialized`
                                    INITIALIZED.store(2, Ordering::Relaxed);
                                },
                                1 => {
                                    // currently initializing in another thread, keep spinning
                                    while INITIALIZED.load(Ordering::Relaxed) != 2 {}
                                },
                                2 => {}, // now it's initialized
                                _ => unreachable!(),
                            }
                        }

                        match *DATA.0.get() {
                            Some(ref x) => x,
                            None => unreachable!(),
                        }
                    }

                    let static_ref = __stability();
                    require_sync(static_ref);
                    static_ref
                }
            }
        }
        lazy_static!($($t)*);
    };
    (MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<commit_msg>Ignore warnings from the missing derived debug lint (#2)<commit_after>/**
A macro for declaring lazily evaluated statics.
Using this macro, it is possible to have `static`s that require code to be
executed at runtime in order to be initialized.

Forked from https://github.com/rust-lang-nursery/lazy-static.rs

This version uses atomics instead of `std::sync::Once`, so it works also for `#![no_std]` builds.
It requires a nightly Rust version.

# Syntax
```text
lazy_static! {
    [pub] static ref NAME_1: TYPE_1 = EXPR_1;
    [pub] static ref NAME_2: TYPE_2 = EXPR_2;
    ...
    [pub] static ref NAME_N: TYPE_N = EXPR_N;
}
```
Metadata (such as doc comments) is allowed on each ref.
# Semantic
For a given `static ref NAME: TYPE = EXPR;`, the macro generates a unique type that
implements `Deref<TYPE>` and stores it in a static with name `NAME`. (Metadata ends up
attaching to this type.)
On first deref, `EXPR` gets evaluated and stored internally, such that all further derefs
can return a reference to the same object.
Like regular `static mut`s, this macro only works for types that fulfill the `Sync`
trait.
# Example
Using the macro:

```rust
#![feature(const_fn)]

#[macro_use]
extern crate once;
use std::collections::HashMap;
lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "foo");
        m.insert(1, "bar");
        m.insert(2, "baz");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
    static ref NUMBER: u32 = times_two(21);
}
fn times_two(n: u32) -> u32 { n * 2 }
fn main() {
    println!("The map has {} entries.", *COUNT);
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
    println!("A expensive calculation on a static results in: {}.", *NUMBER);
}
```
# Implementation details
The `Deref` implementation uses a hidden static variable that is guarded by a atomic check on each access.
**/
#[macro_export]
macro_rules! lazy_static {
    ($(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PRIV, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($(#[$attr:meta])* pub static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(PUB, $(#[$attr])* static ref $N : $T = $e; $($t)*);
    };
    ($VIS:ident, $(#[$attr:meta])* static ref $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
        lazy_static!(MAKE TY, $VIS, $(#[$attr])*, $N);
        impl $crate::__core::ops::Deref for $N {
            type Target = $T;
            fn deref<'a>(&'a self) -> &'a $T {
                #[inline(always)]
                fn __static_ref_initialize() -> $T { $e }

                unsafe {
                    use $crate::__core::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};

                    #[inline(always)]
                    fn require_sync<T: Sync>(_: &T) { }

                    #[inline(always)]
                    unsafe fn __stability() -> &'static $T {
                        use $crate::__core::cell::UnsafeCell;

                        struct SyncCell(UnsafeCell<Option<$T>>);
                        unsafe impl Sync for SyncCell {}

                        static DATA: SyncCell = SyncCell(UnsafeCell::new(None));
                        static INITIALIZED: AtomicUsize = ATOMIC_USIZE_INIT;

                        if INITIALIZED.load(Ordering::Relaxed) != 2 {
                            // not initialized yet

                            // set state to `initializing`
                            match INITIALIZED.compare_and_swap(0, 1, Ordering::Relaxed) {
                                0 => {
                                    // initialize
                                    *DATA.0.get() = Some(__static_ref_initialize());
                                    // set state to `initialized`
                                    INITIALIZED.store(2, Ordering::Relaxed);
                                },
                                1 => {
                                    // currently initializing in another thread, keep spinning
                                    while INITIALIZED.load(Ordering::Relaxed) != 2 {}
                                },
                                2 => {}, // now it's initialized
                                _ => unreachable!(),
                            }
                        }

                        match *DATA.0.get() {
                            Some(ref x) => x,
                            None => unreachable!(),
                        }
                    }

                    let static_ref = __stability();
                    require_sync(static_ref);
                    static_ref
                }
            }
        }
        lazy_static!($($t)*);
    };
    (MAKE TY, PUB, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        #[allow(missing_debug_implementations)]
        $(#[$attr])*
        pub struct $N {__private_field: ()}
        #[doc(hidden)]
        pub static $N: $N = $N {__private_field: ()};
    };
    (MAKE TY, PRIV, $(#[$attr:meta])*, $N:ident) => {
        #[allow(missing_copy_implementations)]
        #[allow(non_camel_case_types)]
        #[allow(dead_code)]
        #[allow(missing_debug_implementations)]
        $(#[$attr])*
        struct $N {__private_field: ()}
        #[doc(hidden)]
        static $N: $N = $N {__private_field: ()};
    };
    () => ()
}
<|endoftext|>