<commit_before>/* kernel::sgash.rs */
#[allow(unused_imports)];
use core::*;
use core::str::*;
use core::option::{Some, Option, None};
use core::iter::Iterator;
use kernel::*;
use super::super::platform::*;
use kernel::memory::Allocator;

// Used to store character into QEMU
pub fn putchar(key: char) {
    unsafe {
        /*
        * We need to include a blank asm call to prevent rustc
        * from optimizing this part out
        */
        asm!("");
        io::write_char(key, io::UART0);
    }
}

fn putstr(msg: &str) {
    for c in slice::iter(as_bytes(msg)) {
        putchar(*c as char);
    }
}

pub unsafe fn drawstr(msg: &str) {
    // See starting code to change color of print out
    for c in slice::iter(as_bytes(msg)) {
        drawchar(*c as char);
    }
}

// Draws character onto QEMU screen
unsafe fn drawchar(x: char)
{
    io::restore();
    if x == '\n' {
    io::CURSOR_Y += io::CURSOR_HEIGHT;
        io::CURSOR_X = 0u32;
        return;
    } else {
io::draw_char(x);
io::CURSOR_X += io::CURSOR_WIDTH;
    }
    io::backup();
    io::draw_cursor();
}

unsafe fn backspace()
{
    io::restore();
    if (io::CURSOR_X >= io::CURSOR_WIDTH) {
io::CURSOR_X -= io::CURSOR_WIDTH;
io::draw_char(' ');
    }
    io::backup();
    io::draw_cursor();
}

// Used to get keystroke and print onscreen
pub unsafe fn parsekey(x: char) {
    let x = x as u8;
    match x {
        13  =>  {
            parse();
            prompt(false);
        }
        127 =>  {
            if(buffer.delete_char()) {
                putchar('');
                putchar(' ');
                putchar('');
                backspace();
            }
        }
        _   =>  {
            if (buffer.add_char(x)) {
                putchar(x as char);
                drawchar(x as char);
            }
        }
    }
}

pub unsafe fn init() {
    buffer = cstr::new(256);
    screen();
    // First prompt does draw, but out of bounds?
    prompt(true);
}

/****************** Added Code ***************/
pub static mut buffer: cstr = cstr {
    pointer: 0 as *mut u8,
    index_pointer: 0,
    max: 0
};

// Problem 1: Prompt on each line
unsafe fn prompt(startup: bool) {
    putstr(&"\nsgash > ");
    if !startup {
        drawstr(&"\nsgash > ");
    } else {
        // Technically it's there, but it's not visible
        // Unlikely color issue, maybe something with CRUSOR?
        drawstr(&"\nstart >");
    }
    buffer.reset();
}

// Problem 4: echo input on second line
unsafe fn echo() {
    putstr(&"\n");
    drawstr(&"\n");
    let mut i: uint = 0;
    while i < buffer.len(){
        let current_char: char = buffer.get_char(i);

        // Occassionally gets wrong char, probably something to do with the cstr implementation
        putchar(current_char);
        drawchar(current_char);       // Hangs without the first sgash> prompt
        i += 1;
    }
    buffer.reset();
}

// Problem 5: Recognize shell commands
unsafe fn parse() {
    if (buffer.streq(&"ls")) {
        putstr( &"\na\tb") ;
        drawstr( &"\na    b") ;
        buffer.reset();
    }
    else {
        putstr(&"\nparsing command...");
        match buffer.getarg(' ', 0){
            // Hangs here
            Some(cmd)   => {
                putstr(&"\nmatching...");
                drawstr(&"\nmatching...");
            },
            None        => {
                putstr(&"\nDidn't recognize command...");
                drawstr(&"\nDidn't recognize command...");
            }
        }

        buffer.reset();
    }

    /*
    if (buffer.streq(&"echo")) {
        putstr( &"\necho");
        drawstr( &"\necho");
        buffer.reset();
    };
    // Separates what's in buffer by spliting spaces
    match buffer.getarg(' ', 0) {
        Some(cmd)        => {
            if(cmd.streq(&"cat")) {
                match buffer.getarg(' ', 1) {
                Some(x)        => {
                    if(x.streq(&"a")) {
                    putstr( &"\nHowdy!");
                    drawstr( &"\nHowdy!");
                    }
                    if(x.streq(&"b")) {
                    putstr( &"\nworld!");
                    drawstr( &"\nworld!");
                    }
                }
                None        => { }
                };
            }

            if cmd.streq(&"echo") {
                putstr(&"\necho");
                drawstr(&"\necho");
            }
        }
        None        => {}
    };
    */

}

/* CString */
struct cstr {
    pointer: *mut u8,       // Starting address
    index_pointer: uint,    // Address of i
    max: uint               // Maximum end address
}

impl cstr {
    pub unsafe fn new(size: uint) -> cstr {
        // Sometimes this doesn't allocate enough memory and gets stuck...
        let (addr_offset,mem_size) = heap.alloc(size);
        let this = cstr {
            pointer:            addr_offset,
            index_pointer:      0,
            max:                mem_size
        };
        // String requires null terminator
        *(((this.pointer as uint)+this.index_pointer) as *mut char) = '\0';
        this
    }

#[allow(dead_code)]
    unsafe fn from_str(s: &str) -> cstr {
        let mut this = cstr::new(256);
        for c in slice::iter(as_bytes(s)) {
            this.add_char(*c);
        };
        this
    }

#[allow(dead_code)]
    fn len(&self) -> uint { self.index_pointer }

    // HELP THIS DOESN'T WORK THERE IS NO GARBAGE COLLECTION!!!
    // -- TODO: exchange_malloc, exchange_free
#[allow(dead_code)]
    unsafe fn destroy(&self) { heap.free(self.pointer); }

    unsafe fn add_char(&mut self, x: u8) -> bool{
        if (self.index_pointer == self.max) { return false; }
        *(((self.pointer as uint)+self.index_pointer) as *mut u8) = x;
        self.index_pointer += 1;
        *(((self.pointer as uint)+self.index_pointer) as *mut char) = '\0';
        true
    }

    // Used for echo function
    unsafe fn get_char(&mut self, index: uint) -> char {
        if self.index_pointer == 0 {
            return (0 as u8) as char;
        }
        return *(((self.pointer as uint)+index) as *mut char);
    }

    unsafe fn delete_char(&mut self) -> bool {
        if (self.index_pointer == 0) { return false; }
        self.index_pointer -= 1;
        *(((self.pointer as uint)+self.index_pointer) as *mut char) = '\0';
        true
    }

    unsafe fn reset(&mut self) {
        let length = self.len();
        let mut i = length-1;
        while i < length {
            self.delete_char();
            i -= 1;
        }
        self.index_pointer = 0;
        *(self.pointer as *mut char) = '\0';
    }

#[allow(dead_code)]
    unsafe fn eq(&self, other: &cstr) -> bool {
        if (self.len() != other.len()) { return false; }
        else {
            let mut x = 0;
            let mut selfp: uint = self.pointer as uint;
            let mut otherp: uint = other.pointer as uint;
            while x < self.len() {
                if (*(selfp as *char) != *(otherp as *char)) { return false; }
                selfp += 1;
                otherp += 1;
                x += 1;
            }
            true
        }
    }

    unsafe fn streq(&self, other: &str) -> bool {
        let mut selfp: uint = self.pointer as uint;
        for c in slice::iter(as_bytes(other)) {
            if( *c != *(selfp as *u8) ) { return false; }
            selfp += 1;
        };
        *(selfp as *char) == '\0'
    }

    unsafe fn getarg(&self, delim: char, mut k: uint) -> Option<cstr> {
        let mut ind: uint = 0;
        let mut found = k == 0;
        let mut selfp: uint = self.pointer as uint;
        let mut s = cstr::new(256);
        loop {
            if (*(selfp as *char) == '\0') {
                // End of string
                if (found) { return Some(s); }
                else { return None; }
            };
            if (*(selfp as *u8) == delim as u8) {
                if (found) { return Some(s); }
                k -= 1;
            };
            if (found) {
                s.add_char(*(selfp as *u8));
            };
            found = k == 0;
            selfp += 1;
            ind += 1;
            if (ind == self.max) {
                putstr(&"\nSomething broke!");
                return None;
            }
        }
    }

#[allow(dead_code)]
    unsafe fn split(&self, delim: char) -> (cstr, cstr) {
        let mut selfp: uint = self.pointer as uint;
        let mut beg = cstr::new(256);
        let mut end = cstr::new(256);
        let mut found = false;
        loop {
            if (*(selfp as *char) == '\0') {
                return (beg, end);
            }
            else if (*(selfp as *u8) == delim as u8) {
                found = true;
            }
            else if (!found) {
                beg.add_char(*(selfp as *u8));
            }
            else if (found) {
                end.add_char(*(selfp as *u8));
            };
            selfp += 1;
        }
    }

    unsafe fn get_cmd(&self, delim: char, mut k: uint) -> cstr {
        let mut ind: uint = 0;
        let mut found = k == 0;
        let mut selfp: uint = self.pointer as uint;
        let mut s = cstr::new(256);
        loop {
            if (*(selfp as *char) == '\0') {
                // End of string
                if (found) { return s; }
                else { s.reset(); return s;  }
            };
            if (*(selfp as *u8) == delim as u8) {
                if (found) { return s; }
                k -= 1;
            };
            if (found) {
                s.add_char(*(selfp as *u8));
            };
            found = k == 0;
            selfp += 1;
            ind += 1;
            if (ind == self.max) {
                putstr(&"\nSomething broke!");
                s.reset();
                return s;
            }
        }
    }

}

// No real purpose beside printing on bash
fn screen() {
    putstr(&"\n ");
    putstr(&"\n ");
    putstr(&"\n 7=..~$=..:7 ");
    putstr(&"\n +$: =$$$+$$$?$$$+ ,7? ");
    putstr(&"\n $$$$$$$$$$$$$$$$$$Z$$ ");
    putstr(&"\n 7$$$$$$$$$$$$. .Z$$$$$Z$$$$$$ ");
    putstr(&"\n ~..7$$Z$$$$$7+7$+.?Z7=7$$Z$$Z$$$..: ");
    putstr(&"\n ~$$$$$$$$7: :ZZZ, :7ZZZZ$$$$= ");
    putstr(&"\n Z$$$$$? .+ZZZZ$$ ");
    putstr(&"\n +$ZZ$$$Z7 7ZZZ$Z$$I. ");
    putstr(&"\n $$$$ZZZZZZZZZZZZZZZZZZZZZZZZI, ,ZZZ$$Z ");
    putstr(&"\n :+$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZ= $ZZ$$+~, ");
    putstr(&"\n ?$Z$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZZI 7ZZZ$ZZI ");
    putstr(&"\n =Z$$+7Z$$7ZZZZZZZZ$$$$$$$ZZZZZZZZZZ ~Z$?$ZZ? ");
    putstr(&"\n :$Z$Z...$Z $ZZZZZZZ~ ~ZZZZZZZZ,.ZZ...Z$Z$~ ");
    putstr(&"\n 7ZZZZZI$ZZ $ZZZZZZZ~ =ZZZZZZZ7..ZZ$?$ZZZZ$ ");
    putstr(&"\n ZZZZ$: $ZZZZZZZZZZZZZZZZZZZZZZ= ~$ZZZ$: ");
    putstr(&"\n 7Z$ZZ$, $ZZZZZZZZZZZZZZZZZZZZ7 ZZZ$Z$ ");
    putstr(&"\n =ZZZZZZ, $ZZZZZZZZZZZZZZZZZZZZZZ, ZZZ$ZZ+ ");
    putstr(&"\n ,ZZZZ, $ZZZZZZZ: =ZZZZZZZZZ ZZZZZ$: ");
    putstr(&"\n =$ZZZZ+ ZZZZZZZZ~ ZZZZZZZZ~ =ZZZZZZZI ");
    putstr(&"\n $ZZ$ZZZ$$Z$$ZZZZZZZZZ$$$$ IZZZZZZZZZ$ZZZZZZZZZ$ ");
    putstr(&"\n :ZZZZZZZZZZZZZZZZZZZZZZ ~ZZZZZZZZZZZZZZZZZ~ ");
    putstr(&"\n ,Z$$ZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZ~ ");
    putstr(&"\n =$ZZZZZZZZZZZZZZZZZZZZZZ $ZZZZZZZZZZZZZZZ$+ ");
    putstr(&"\n IZZZZZ:. . ,ZZZZZ$ ");
    putstr(&"\n ~$ZZZZZZZZZZZ ZZZZ$ZZZZZZZ+ ");
    putstr(&"\n Z$ZZZ. ,Z~ =Z:.,ZZZ$Z ");
    putstr(&"\n ,ZZZZZ..~Z$. .7Z:..ZZZZZ: ");
    putstr(&"\n ~7+:$ZZZZZZZZI=:. .,=IZZZZZZZ$Z:=7= ");
    putstr(&"\n $$ZZZZZZZZZZZZZZZZZZZZZZ$ZZZZ ");
    putstr(&"\n ==..$ZZZ$ZZZZZZZZZZZ$ZZZZ .~+ ");
    putstr(&"\n I$?.?ZZZ$ZZZ$ZZZI =$7 ");
    putstr(&"\n $7..I$7..I$, ");
    putstr(&"\n");
    putstr(&"\n _ _ _ _ ");
    putstr(&"\n| | (_) | | | | ");
    putstr(&"\n| | ____ ___ ____ _____| |_____ ____ ____ _____| | ");
    putstr(&"\n| |/ ___) _ \\| _ \\ | _ _) ___ |/ ___) _ \\| ___ | | ");
    putstr(&"\n| | | | |_| | | | | | | \\ \\| ____| | | | | | ____| | ");
    putstr(&"\n|_|_| \\____/|_| |_| |_| \\_\\_____)_| |_| |_|_____)__)\n\n");
}<commit_msg>Still debugging command recognition<commit_after>/* kernel::sgash.rs */
#[allow(unused_imports)];
use core::*;
use core::str::*;
use core::option::{Some, Option, None};
use core::iter::Iterator;
use kernel::*;
use super::super::platform::*;
use kernel::memory::Allocator;

// Used to store character into QEMU
pub fn putchar(key: char) {
    unsafe {
        /*
        * We need to include a blank asm call to prevent rustc
        * from optimizing this part out
        */
        asm!("");
        io::write_char(key, io::UART0);
    }
}

fn putstr(msg: &str) {
    for c in slice::iter(as_bytes(msg)) {
        putchar(*c as char);
    }
}

pub unsafe fn drawstr(msg: &str) {
    // See starting code to change color of print out
    for c in slice::iter(as_bytes(msg)) {
        drawchar(*c as char);
    }
}

// Draws character onto QEMU screen
unsafe fn drawchar(x: char)
{
    io::restore();
    if x == '\n' {
    io::CURSOR_Y += io::CURSOR_HEIGHT;
        io::CURSOR_X = 0u32;
        return;
    } else {
io::draw_char(x);
io::CURSOR_X += io::CURSOR_WIDTH;
    }
    io::backup();
    io::draw_cursor();
}

unsafe fn backspace()
{
    io::restore();
    if (io::CURSOR_X >= io::CURSOR_WIDTH) {
io::CURSOR_X -= io::CURSOR_WIDTH;
io::draw_char(' ');
    }
    io::backup();
    io::draw_cursor();
}

// Used to get keystroke and print onscreen
pub unsafe fn parsekey(x: char) {
    let x = x as u8;
    match x {
        13  =>  {
            //echo();
            parse();
            prompt(false);
        }
        127 =>  {
            if(buffer.delete_char()) {
                putchar('');
                putchar(' ');
                putchar('');
                backspace();
            }
        }
        _   =>  {
            if (buffer.add_char(x)) {
                putchar(x as char);
                drawchar(x as char);
            }
        }
    }
}

pub unsafe fn init() {
    buffer = cstr::new(256);
    screen();
    // First prompt does draw, but out of bounds?
    prompt(true);
}

/****************** Added Code ***************/
pub static mut buffer: cstr = cstr {
    addr_pointer: 0 as *mut u8,
    end_pointer: 0,
    max_size: 0
};

// Problem 1: Prompt on each line
unsafe fn prompt(startup: bool) {
    putstr(&"\nsgash > ");
    if !startup {
        drawstr(&"\nsgash > ");
    } else {
        // Technically it's there, but it's not visible
        // Unlikely color issue, maybe something with CRUSOR?
        drawstr(&"\nstart >");
    }
    buffer.reset();
}

// Problem 4: echo input on second line
unsafe fn echo() {
    putstr(&"\n");
    drawstr(&"\n");
    let mut i: uint = 0;
    while i < buffer.len(){
        let current_char: char = buffer.get_char(i);

        // Occassionally gets wrong char, probably something to do with the cstr implementation
        putchar(current_char);
        drawchar(current_char);       // Hangs without the first sgash> prompt
        i += 1;
    }
    buffer.reset();
}

// Problem 5: Recognize shell commands
/*unsafe fn parse() {
    if buffer.streq(&"ls") {
        putstr(&"\nListing folder children...");
        drawstr(&"\nListing folder children...");
        buffer.reset();
    }
    else {
        putstr(&"\nparsing command...");
        let cmd = buffer.frontslice(' ');       // Problem is here...
        putstr(&"\nsliced!");
        if cmd.streq(&"echo"){
            putstr(&"\ncan you hear me?");
            echo();
        }
        else {
            putstr(&"\nit's all good.jpg");
            buffer.reset();
        }

    }
}*/

unsafe fn parse() {
    if (buffer.streq(&"ls")) {
        putstr( &"\na\tb") ;
        drawstr( &"\na    b") ;
        buffer.reset();
    }
    else {
        putstr(&"\nparsing command...");
        match buffer.getarg(' ', 0){        // Hangs here
            Some(cmd)   => {
                if cmd.streq(&"echo"){
                    putstr(&"echo");
                    drawstr(&"echo");
                }
            },
            None        => {
                putstr(&"\nDidn't recognize command...");
                drawstr(&"\nDidn't recognize command...");
            }
        }
        buffer.reset();
    }

    /*
    if (buffer.streq(&"echo")) {
        putstr( &"\necho");
        drawstr( &"\necho");
        buffer.reset();
    };
    // Separates what's in buffer by spliting spaces
    match buffer.getarg(' ', 0) {
        Some(cmd)        => {
            if(cmd.streq(&"cat")) {
                match buffer.getarg(' ', 1) {
                Some(x)        => {
                    if(x.streq(&"a")) {
                    putstr( &"\nHowdy!");
                    drawstr( &"\nHowdy!");
                    }
                    if(x.streq(&"b")) {
                    putstr( &"\nworld!");
                    drawstr( &"\nworld!");
                    }
                }
                None        => { }
                };
            }

            if cmd.streq(&"echo") {
                putstr(&"\necho");
                drawstr(&"\necho");
            }
        }
        None        => {}
    };
    */

}

/* CString */
struct cstr {
    addr_pointer: *mut u8,       // Starting address
    end_pointer: uint,    // Address of i
    max_size: uint               // Maximum end address
}

impl cstr {
    pub unsafe fn new(size: uint) -> cstr {
        // Sometimes this doesn't allocate enough memory and gets stuck...
        let (addr_offset,mem_size) = heap.alloc(size);
        let this = cstr {
            addr_pointer:       addr_offset,
            end_pointer:        0,
            max_size:                mem_size
        };

        // String requires null terminator
        // This is also the standard way to access character bytes
        *(((this.addr_pointer as uint)+this.end_pointer) as *mut char) = '\0';
        this
    }

#[allow(dead_code)]
    unsafe fn from_str(s: &str) -> cstr {
        let mut this = cstr::new(256);
        for c in slice::iter(as_bytes(s)) {
            this.add_char(*c);
        };
        this
    }

#[allow(dead_code)]
    fn len(&self) -> uint { self.end_pointer }

    // HELP THIS DOESN'T WORK THERE IS NO GARBAGE COLLECTION!!!
    // -- TODO: exchange_malloc, exchange_free
#[allow(dead_code)]
    unsafe fn destroy(&self) { heap.free(self.addr_pointer); }

    unsafe fn add_char(&mut self, character: u8) -> bool{
        if (self.end_pointer == self.max_size) { return false; }
        *(((self.addr_pointer as uint)+self.end_pointer) as *mut u8) = character;
        self.end_pointer += 1;
        *(((self.addr_pointer as uint)+self.end_pointer) as *mut char) = '\0';
        true
    }

    // Used for echo function (Works fine)
    unsafe fn get_char(&mut self, index: uint) -> char {
        if self.end_pointer == 0 {
            return *(((self.addr_pointer as uint)) as *mut char);   // Should return '\0'
        }
        return *(((self.addr_pointer as uint)+index) as *mut char);
    }

    unsafe fn delete_char(&mut self) -> bool {
        if (self.end_pointer == 0) { return false; }
        self.end_pointer -= 1;
        *(((self.addr_pointer as uint)+self.end_pointer) as *mut char) = '\0';
        true
    }

    unsafe fn reset(&mut self) {
        let length = self.len();
        let mut i = length-1;
        while i < length {
            self.delete_char();
            i -= 1;
        }
        self.end_pointer = 0;
        *(self.addr_pointer as *mut char) = '\0';
    }

#[allow(dead_code)]
    unsafe fn eq(&self, other: &cstr) -> bool {
        if (self.len() != other.len()) { return false; }
        else {
            let mut x = 0;
            let mut selfp: uint = self.addr_pointer as uint;
            let mut otherp: uint = other.addr_pointer as uint;
            while x < self.len() {
                if (*(selfp as *char) != *(otherp as *char)) { return false; }
                selfp += 1;
                otherp += 1;
                x += 1;
            }
            true
        }
    }

    unsafe fn streq(&self, other: &str) -> bool {
        let mut selfp: uint = self.addr_pointer as uint;
        for c in slice::iter(as_bytes(other)) {
            if( *c != *(selfp as *u8) ) { return false; }
            selfp += 1;
        };
        *(selfp as *char) == '\0'
    }

    unsafe fn getarg(&self, delim: char, mut k: uint) -> Option<cstr> {
        let mut index: uint = 0;
        let mut pointer: uint = self.addr_pointer as uint;
        let mut string = cstr::new(256);
        loop {
            if (*(pointer as *char) == '\0') {
                return None;
            };
            if (*(pointer as *char) == delim) {
                return Some(string);
            };
            string.add_char(*(pointer as *u8));
            pointer += 1;
            index += 1;
            if (index == self.max_size) {
                putstr(&"\nSomething broke!");
                return None;
            }
        }
    }

#[allow(dead_code)]
    unsafe fn split(&self, delim: char) -> (cstr, cstr) {
        let mut selfp: uint = self.addr_pointer as uint;
        let mut beg = cstr::new(256);
        let mut end = cstr::new(256);
        let mut found = false;
        loop {
            if (*(selfp as *char) == '\0') {
                return (beg, end);
            }
            else if (*(selfp as *u8) == delim as u8) {
                found = true;
            }
            else if (!found) {
                beg.add_char(*(selfp as *u8));
            }
            else if (found) {
                end.add_char(*(selfp as *u8));
            };
            selfp += 1;
        }
    }

    unsafe fn frontslice(&self, delimiter: char) -> cstr {
        let mut index: uint = self.addr_pointer as uint;
        let length: uint = self.max_size as uint;
        let mut return_str = cstr::new(256);
        let mut i: uint = 0;
        loop {
            if (*(index as *char) == '\0') {
                return return_str;
            }
            else if (*(index as *u8) == delimiter as u8) {
                return return_str;
            }
            else {
                return_str.add_char(*(index as *u8));
                index += 1;
            }
        }
    }

    unsafe fn get_cmd(&self, delim: char) -> cstr {
        let mut index: uint = 0;
        let mut pointer: uint = self.addr_pointer as uint;
        let mut string = cstr::new(256);
        loop {
            if (*(pointer as *char) == '\0') {
                return string;
            };
            if (*(pointer as *char) == delim) {
                return string;
            };
            string.add_char(*(pointer as *u8));
            pointer += 1;
            index += 1;
            if (index == self.max_size) {
                putstr(&"\nSomething broke!");
                return string;
            }
        }
    }

}

/********* File System ****************/
struct inode {
    uid:    uint,
    address: *mut u8
    left_child: *mut u8,
    right_child: *mut u8,
    filename: cstr,
    data: cstr
}
impl inode {
    pub unsafe fn new(id: uint, filename: cstr) -> inode {
        let (addr_offset,mem_size) = heap.alloc(size);
        uid: id,
        address: addr_offset,
        left_child: 0 as *mut u8,
        right_child: 0 as *mut u8,
        filename: filename,
        data: cstr::new(256);
    }
}

// No real purpose beside printing on bash
fn screen() {
    putstr(&"\n ");
    putstr(&"\n ");
    putstr(&"\n 7=..~$=..:7 ");
    putstr(&"\n +$: =$$$+$$$?$$$+ ,7? ");
    putstr(&"\n $$$$$$$$$$$$$$$$$$Z$$ ");
    putstr(&"\n 7$$$$$$$$$$$$. .Z$$$$$Z$$$$$$ ");
    putstr(&"\n ~..7$$Z$$$$$7+7$+.?Z7=7$$Z$$Z$$$..: ");
    putstr(&"\n ~$$$$$$$$7: :ZZZ, :7ZZZZ$$$$= ");
    putstr(&"\n Z$$$$$? .+ZZZZ$$ ");
    putstr(&"\n +$ZZ$$$Z7 7ZZZ$Z$$I. ");
    putstr(&"\n $$$$ZZZZZZZZZZZZZZZZZZZZZZZZI, ,ZZZ$$Z ");
    putstr(&"\n :+$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZ= $ZZ$$+~, ");
    putstr(&"\n ?$Z$$$$ZZZZZZZZZZZZZZZZZZZZZZZZZZZZI 7ZZZ$ZZI ");
    putstr(&"\n =Z$$+7Z$$7ZZZZZZZZ$$$$$$$ZZZZZZZZZZ ~Z$?$ZZ? ");
    putstr(&"\n :$Z$Z...$Z $ZZZZZZZ~ ~ZZZZZZZZ,.ZZ...Z$Z$~ ");
    putstr(&"\n 7ZZZZZI$ZZ $ZZZZZZZ~ =ZZZZZZZ7..ZZ$?$ZZZZ$ ");
    putstr(&"\n ZZZZ$: $ZZZZZZZZZZZZZZZZZZZZZZ= ~$ZZZ$: ");
    putstr(&"\n 7Z$ZZ$, $ZZZZZZZZZZZZZZZZZZZZ7 ZZZ$Z$ ");
    putstr(&"\n =ZZZZZZ, $ZZZZZZZZZZZZZZZZZZZZZZ, ZZZ$ZZ+ ");
    putstr(&"\n ,ZZZZ, $ZZZZZZZ: =ZZZZZZZZZ ZZZZZ$: ");
    putstr(&"\n =$ZZZZ+ ZZZZZZZZ~ ZZZZZZZZ~ =ZZZZZZZI ");
    putstr(&"\n $ZZ$ZZZ$$Z$$ZZZZZZZZZ$$$$ IZZZZZZZZZ$ZZZZZZZZZ$ ");
    putstr(&"\n :ZZZZZZZZZZZZZZZZZZZZZZ ~ZZZZZZZZZZZZZZZZZ~ ");
    putstr(&"\n ,Z$$ZZZZZZZZZZZZZZZZZZZZ ZZZZZZZZZZZZZZZZZZ~ ");
    putstr(&"\n =$ZZZZZZZZZZZZZZZZZZZZZZ $ZZZZZZZZZZZZZZZ$+ ");
    putstr(&"\n IZZZZZ:. . ,ZZZZZ$ ");
    putstr(&"\n ~$ZZZZZZZZZZZ ZZZZ$ZZZZZZZ+ ");
    putstr(&"\n Z$ZZZ. ,Z~ =Z:.,ZZZ$Z ");
    putstr(&"\n ,ZZZZZ..~Z$. .7Z:..ZZZZZ: ");
    putstr(&"\n ~7+:$ZZZZZZZZI=:. .,=IZZZZZZZ$Z:=7= ");
    putstr(&"\n $$ZZZZZZZZZZZZZZZZZZZZZZ$ZZZZ ");
    putstr(&"\n ==..$ZZZ$ZZZZZZZZZZZ$ZZZZ .~+ ");
    putstr(&"\n I$?.?ZZZ$ZZZ$ZZZI =$7 ");
    putstr(&"\n $7..I$7..I$, ");
    putstr(&"\n");
    putstr(&"\n _ _ _ _ ");
    putstr(&"\n| | (_) | | | | ");
    putstr(&"\n| | ____ ___ ____ _____| |_____ ____ ____ _____| | ");
    putstr(&"\n| |/ ___) _ \\| _ \\ | _ _) ___ |/ ___) _ \\| ___ | | ");
    putstr(&"\n| | | | |_| | | | | | | \\ \\| ____| | | | | | ____| | ");
    putstr(&"\n|_|_| \\____/|_| |_| |_| \\_\\_____)_| |_| |_|_____)__)\n\n");
}<|endoftext|>


<commit_before>//! [GET /_matrix/media/r0/thumbnail/{serverName}/{mediaId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-media-r0-thumbnail-servername-mediaid)

use js_int::UInt;
use ruma_api::ruma_api;
use serde::{Deserialize, Serialize};

/// The desired resizing method.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Method {
    /// Crop the original to produce the requested image dimensions.
    Crop,

    /// Maintain the original aspect ratio of the source image.
    Scale,
}

ruma_api! {
    metadata {
        description: "Get a thumbnail of content from the media store.",
        method: GET,
        name: "get_content_thumbnail",
        path: "/_matrix/media/r0/thumbnail/:server_name/:media_id",
        rate_limited: true,
        requires_authentication: false,
    }

    request {
        /// Whether to fetch media deemed remote.
        ///
        /// Used to prevent routing loops. Defaults to `true`.
        #[ruma_api(query)]
        #[serde(skip_serializing_if = "Option::is_none")]
        pub allow_remote: Option<bool>,

        /// The media ID from the mxc:// URI (the path component).
        #[ruma_api(path)]
        pub media_id: String,

        /// The server name from the mxc:// URI (the authoritory component).
        #[ruma_api(path)]
        pub server_name: String,

        /// The *desired* height of the thumbnail. The actual thumbnail may not match the size
        /// specified.
        #[ruma_api(query)]
        pub height: UInt,

        /// The desired resizing method.
        #[ruma_api(query)]
        #[serde(skip_serializing_if = "Option::is_none")]
        pub method: Option<Method>,

        /// The *desired* width of the thumbnail. The actual thumbnail may not match the size
        /// specified.
        #[ruma_api(query)]
        pub width: UInt,
    }

    response {
        /// The content type of the thumbnail.
        #[ruma_api(header = CONTENT_TYPE)]
        pub content_type: String,

        /// A thumbnail of the requested content.
        #[ruma_api(body)]
        pub file: Vec<u8>,
    }

    error: crate::Error
}
<commit_msg>Fix get_content_thumbnail response<commit_after>//! [GET /_matrix/media/r0/thumbnail/{serverName}/{mediaId}](https://matrix.org/docs/spec/client_server/r0.6.0#get-matrix-media-r0-thumbnail-servername-mediaid)

use js_int::UInt;
use ruma_api::ruma_api;
use serde::{Deserialize, Serialize};

/// The desired resizing method.
#[derive(Clone, Copy, Debug, Deserialize, Serialize)]
#[serde(rename_all = "snake_case")]
pub enum Method {
    /// Crop the original to produce the requested image dimensions.
    Crop,

    /// Maintain the original aspect ratio of the source image.
    Scale,
}

ruma_api! {
    metadata {
        description: "Get a thumbnail of content from the media store.",
        method: GET,
        name: "get_content_thumbnail",
        path: "/_matrix/media/r0/thumbnail/:server_name/:media_id",
        rate_limited: true,
        requires_authentication: false,
    }

    request {
        /// Whether to fetch media deemed remote.
        ///
        /// Used to prevent routing loops. Defaults to `true`.
        #[ruma_api(query)]
        #[serde(skip_serializing_if = "Option::is_none")]
        pub allow_remote: Option<bool>,

        /// The media ID from the mxc:// URI (the path component).
        #[ruma_api(path)]
        pub media_id: String,

        /// The server name from the mxc:// URI (the authoritory component).
        #[ruma_api(path)]
        pub server_name: String,

        /// The *desired* height of the thumbnail. The actual thumbnail may not match the size
        /// specified.
        #[ruma_api(query)]
        pub height: UInt,

        /// The desired resizing method.
        #[ruma_api(query)]
        #[serde(skip_serializing_if = "Option::is_none")]
        pub method: Option<Method>,

        /// The *desired* width of the thumbnail. The actual thumbnail may not match the size
        /// specified.
        #[ruma_api(query)]
        pub width: UInt,
    }

    response {
        /// The content type of the thumbnail.
        #[ruma_api(header = CONTENT_TYPE)]
        pub content_type: String,

        /// A thumbnail of the requested content.
        #[ruma_api(raw_body)]
        pub file: Vec<u8>,
    }

    error: crate::Error
}
<|endoftext|>


<commit_before>//! Cretonne compilation context and main entry point.
//!
//! When compiling many small functions, it is important to avoid repeatedly allocating and
//! deallocating the data structures needed for compilation. The `Context` struct is used to hold
//! on to memory allocations between function compilations.
//!
//! The context does not hold a `TargetIsa` instance which has to be provided as an argument
//! instead. This is because an ISA instance is immutable and can be used by multiple compilation
//! contexts concurrently. Typically, you would have one context per compilation thread and only a
//! single ISA instance.

use binemit::{CodeOffset, relax_branches, MemoryCodeSink, RelocSink};
use dominator_tree::DominatorTree;
use flowgraph::ControlFlowGraph;
use ir::Function;
use loop_analysis::LoopAnalysis;
use isa::TargetIsa;
use legalize_function;
use regalloc;
use result::{CtonError, CtonResult};
use settings::{FlagsOrIsa, OptLevel};
use unreachable_code::eliminate_unreachable_code;
use verifier;
use simple_gvn::do_simple_gvn;
use licm::do_licm;

/// Persistent data structures and compilation pipeline.
pub struct Context {
    /// The function we're compiling.
    pub func: Function,

    /// The control flow graph of `func`.
    pub cfg: ControlFlowGraph,

    /// Dominator tree for `func`.
    pub domtree: DominatorTree,

    /// Register allocation context.
    pub regalloc: regalloc::Context,

    /// Loop analysis of `func`.
    pub loop_analysis: LoopAnalysis,
}

impl Context {
    /// Allocate a new compilation context.
    ///
    /// The returned instance should be reused for compiling multiple functions in order to avoid
    /// needless allocator thrashing.
    pub fn new() -> Context {
        Context {
            func: Function::new(),
            cfg: ControlFlowGraph::new(),
            domtree: DominatorTree::new(),
            regalloc: regalloc::Context::new(),
            loop_analysis: LoopAnalysis::new(),
        }
    }

    /// Compile the function.
    ///
    /// Run the function through all the passes necessary to generate code for the target ISA
    /// represented by `isa`. This does not include the final step of emitting machine code into a
    /// code sink.
    ///
    /// Returns the size of the function's code.
    pub fn compile(&mut self, isa: &TargetIsa) -> Result<CodeOffset, CtonError> {
        self.verify_if(isa)?;

        self.compute_cfg();
        self.legalize(isa)?;
        if isa.flags().opt_level() == OptLevel::Best {
            self.compute_domtree();
            self.compute_loop_analysis();
            self.licm(isa)?;
            self.simple_gvn(isa)?;
        }
        self.compute_domtree();
        self.eliminate_unreachable_code(isa)?;
        self.regalloc(isa)?;
        self.prologue_epilogue(isa)?;
        self.relax_branches(isa)
    }

    /// Emit machine code directly into raw memory.
    ///
    /// Write all of the function's machine code to the memory at `mem`. The size of the machine
    /// code is returned by `compile` above.
    ///
    /// The machine code is not relocated. Instead, any relocations are emitted into `relocs`.
    pub fn emit_to_memory(&self, mem: *mut u8, relocs: &mut RelocSink, isa: &TargetIsa) {
        isa.emit_function(&self.func, &mut MemoryCodeSink::new(mem, relocs));
    }

    /// Run the verifier on the function.
    ///
    /// Also check that the dominator tree and control flow graph are consistent with the function.
    pub fn verify<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> verifier::Result {
        verifier::verify_context(&self.func, &self.cfg, &self.domtree, fisa)
    }

    /// Run the verifier only if the `enable_verifier` setting is true.
    pub fn verify_if<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> CtonResult {
        let fisa = fisa.into();
        if fisa.flags.enable_verifier() {
            self.verify(fisa).map_err(Into::into)
        } else {
            Ok(())
        }
    }

    /// Run the legalizer for `isa` on the function.
    pub fn legalize(&mut self, isa: &TargetIsa) -> CtonResult {
        // Legalization invalidates the domtree and loop_analysis by mutating the CFG.
        // TODO: Avoid doing this when legalization doesn't actually mutate the CFG.
        self.domtree.clear();
        self.loop_analysis.clear();
        legalize_function(&mut self.func, &mut self.cfg, isa);
        self.verify_if(isa)
    }

    /// Compute the control flow graph.
    pub fn compute_cfg(&mut self) {
        self.cfg.compute(&self.func)
    }

    /// Compute dominator tree.
    pub fn compute_domtree(&mut self) {
        self.domtree.compute(&self.func, &self.cfg)
    }

    /// Compute the loop analysis.
    pub fn compute_loop_analysis(&mut self) {
        self.loop_analysis.compute(
            &self.func,
            &self.cfg,
            &self.domtree,
        )
    }

    /// Compute the control flow graph and dominator tree.
    pub fn flowgraph(&mut self) {
        self.compute_cfg();
        self.compute_domtree()
    }

    /// Perform simple GVN on the function.
    pub fn simple_gvn<'a, FOI: Into<FlagsOrIsa<'a>>>(&mut self, fisa: FOI) -> CtonResult {
        do_simple_gvn(&mut self.func, &mut self.cfg, &mut self.domtree);
        self.verify_if(fisa)
    }

    /// Perform LICM on the function.
    pub fn licm<'a, FOI: Into<FlagsOrIsa<'a>>>(&mut self, fisa: FOI) -> CtonResult {
        do_licm(
            &mut self.func,
            &mut self.cfg,
            &mut self.domtree,
            &mut self.loop_analysis,
        );
        self.verify_if(fisa)
    }

    /// Perform unreachable code elimination.
    pub fn eliminate_unreachable_code<'a, FOI>(&mut self, fisa: FOI) -> CtonResult
    where
        FOI: Into<FlagsOrIsa<'a>>,
    {
        eliminate_unreachable_code(&mut self.func, &mut self.cfg, &self.domtree);
        self.verify_if(fisa)
    }

    /// Run the register allocator.
    pub fn regalloc(&mut self, isa: &TargetIsa) -> CtonResult {
        self.regalloc.run(
            isa,
            &mut self.func,
            &self.cfg,
            &mut self.domtree,
        )
    }

    /// Insert prologue and epilogues after computing the stack frame layout.
    pub fn prologue_epilogue(&mut self, isa: &TargetIsa) -> CtonResult {
        isa.prologue_epilogue(&mut self.func)?;
        self.verify_if(isa)
    }

    /// Run the branch relaxation pass and return the final code size.
    pub fn relax_branches(&mut self, isa: &TargetIsa) -> Result<CodeOffset, CtonError> {
        let code_size = relax_branches(&mut self.func, isa)?;
        self.verify_if(isa)?;

        Ok(code_size)
    }
}
<commit_msg>Actually disable simple_gvn and licm by default.<commit_after>//! Cretonne compilation context and main entry point.
//!
//! When compiling many small functions, it is important to avoid repeatedly allocating and
//! deallocating the data structures needed for compilation. The `Context` struct is used to hold
//! on to memory allocations between function compilations.
//!
//! The context does not hold a `TargetIsa` instance which has to be provided as an argument
//! instead. This is because an ISA instance is immutable and can be used by multiple compilation
//! contexts concurrently. Typically, you would have one context per compilation thread and only a
//! single ISA instance.

use binemit::{CodeOffset, relax_branches, MemoryCodeSink, RelocSink};
use dominator_tree::DominatorTree;
use flowgraph::ControlFlowGraph;
use ir::Function;
use loop_analysis::LoopAnalysis;
use isa::TargetIsa;
use legalize_function;
use regalloc;
use result::{CtonError, CtonResult};
use settings::{FlagsOrIsa, OptLevel};
use unreachable_code::eliminate_unreachable_code;
use verifier;
use simple_gvn::do_simple_gvn;
use licm::do_licm;

/// Persistent data structures and compilation pipeline.
pub struct Context {
    /// The function we're compiling.
    pub func: Function,

    /// The control flow graph of `func`.
    pub cfg: ControlFlowGraph,

    /// Dominator tree for `func`.
    pub domtree: DominatorTree,

    /// Register allocation context.
    pub regalloc: regalloc::Context,

    /// Loop analysis of `func`.
    pub loop_analysis: LoopAnalysis,
}

impl Context {
    /// Allocate a new compilation context.
    ///
    /// The returned instance should be reused for compiling multiple functions in order to avoid
    /// needless allocator thrashing.
    pub fn new() -> Context {
        Context {
            func: Function::new(),
            cfg: ControlFlowGraph::new(),
            domtree: DominatorTree::new(),
            regalloc: regalloc::Context::new(),
            loop_analysis: LoopAnalysis::new(),
        }
    }

    /// Compile the function.
    ///
    /// Run the function through all the passes necessary to generate code for the target ISA
    /// represented by `isa`. This does not include the final step of emitting machine code into a
    /// code sink.
    ///
    /// Returns the size of the function's code.
    pub fn compile(&mut self, isa: &TargetIsa) -> Result<CodeOffset, CtonError> {
        self.verify_if(isa)?;

        self.compute_cfg();
        self.legalize(isa)?;
        /* TODO: Enable additional optimization passes.
        if isa.flags().opt_level() == OptLevel::Best {
            self.compute_domtree();
            self.compute_loop_analysis();
            self.licm(isa)?;
            self.simple_gvn(isa)?;
        }
        */
        self.compute_domtree();
        self.eliminate_unreachable_code(isa)?;
        self.regalloc(isa)?;
        self.prologue_epilogue(isa)?;
        self.relax_branches(isa)
    }

    /// Emit machine code directly into raw memory.
    ///
    /// Write all of the function's machine code to the memory at `mem`. The size of the machine
    /// code is returned by `compile` above.
    ///
    /// The machine code is not relocated. Instead, any relocations are emitted into `relocs`.
    pub fn emit_to_memory(&self, mem: *mut u8, relocs: &mut RelocSink, isa: &TargetIsa) {
        isa.emit_function(&self.func, &mut MemoryCodeSink::new(mem, relocs));
    }

    /// Run the verifier on the function.
    ///
    /// Also check that the dominator tree and control flow graph are consistent with the function.
    pub fn verify<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> verifier::Result {
        verifier::verify_context(&self.func, &self.cfg, &self.domtree, fisa)
    }

    /// Run the verifier only if the `enable_verifier` setting is true.
    pub fn verify_if<'a, FOI: Into<FlagsOrIsa<'a>>>(&self, fisa: FOI) -> CtonResult {
        let fisa = fisa.into();
        if fisa.flags.enable_verifier() {
            self.verify(fisa).map_err(Into::into)
        } else {
            Ok(())
        }
    }

    /// Run the legalizer for `isa` on the function.
    pub fn legalize(&mut self, isa: &TargetIsa) -> CtonResult {
        // Legalization invalidates the domtree and loop_analysis by mutating the CFG.
        // TODO: Avoid doing this when legalization doesn't actually mutate the CFG.
        self.domtree.clear();
        self.loop_analysis.clear();
        legalize_function(&mut self.func, &mut self.cfg, isa);
        self.verify_if(isa)
    }

    /// Compute the control flow graph.
    pub fn compute_cfg(&mut self) {
        self.cfg.compute(&self.func)
    }

    /// Compute dominator tree.
    pub fn compute_domtree(&mut self) {
        self.domtree.compute(&self.func, &self.cfg)
    }

    /// Compute the loop analysis.
    pub fn compute_loop_analysis(&mut self) {
        self.loop_analysis.compute(
            &self.func,
            &self.cfg,
            &self.domtree,
        )
    }

    /// Compute the control flow graph and dominator tree.
    pub fn flowgraph(&mut self) {
        self.compute_cfg();
        self.compute_domtree()
    }

    /// Perform simple GVN on the function.
    pub fn simple_gvn<'a, FOI: Into<FlagsOrIsa<'a>>>(&mut self, fisa: FOI) -> CtonResult {
        do_simple_gvn(&mut self.func, &mut self.cfg, &mut self.domtree);
        self.verify_if(fisa)
    }

    /// Perform LICM on the function.
    pub fn licm<'a, FOI: Into<FlagsOrIsa<'a>>>(&mut self, fisa: FOI) -> CtonResult {
        do_licm(
            &mut self.func,
            &mut self.cfg,
            &mut self.domtree,
            &mut self.loop_analysis,
        );
        self.verify_if(fisa)
    }

    /// Perform unreachable code elimination.
    pub fn eliminate_unreachable_code<'a, FOI>(&mut self, fisa: FOI) -> CtonResult
    where
        FOI: Into<FlagsOrIsa<'a>>,
    {
        eliminate_unreachable_code(&mut self.func, &mut self.cfg, &self.domtree);
        self.verify_if(fisa)
    }

    /// Run the register allocator.
    pub fn regalloc(&mut self, isa: &TargetIsa) -> CtonResult {
        self.regalloc.run(
            isa,
            &mut self.func,
            &self.cfg,
            &mut self.domtree,
        )
    }

    /// Insert prologue and epilogues after computing the stack frame layout.
    pub fn prologue_epilogue(&mut self, isa: &TargetIsa) -> CtonResult {
        isa.prologue_epilogue(&mut self.func)?;
        self.verify_if(isa)
    }

    /// Run the branch relaxation pass and return the final code size.
    pub fn relax_branches(&mut self, isa: &TargetIsa) -> Result<CodeOffset, CtonError> {
        let code_size = relax_branches(&mut self.func, isa)?;
        self.verify_if(isa)?;

        Ok(code_size)
    }
}
<|endoftext|>


<commit_before>// Make sure that we can detect when one end of the pipe is closed.

// xfail-pretty

use std;
import std::timer::sleep;
import std::uv;

import pipes::{try_recv, recv};

proto! oneshot {
    waiting:send {
        signal -> signaled
    }

    signaled:send { }
}

fn main() {
    let iotask = uv::global_loop::get();

    let c = pipes::spawn_service(oneshot::init, |p| {
        alt try_recv(p) {
          some(*) { fail }
          none { }
        }
    });

    sleep(iotask, 100);

    let b = task::builder();
    task::unsupervise(b);
    task::run(b, failtest);
}

// Make sure the right thing happens during failure.
fn failtest() {
    let iotask = uv::global_loop::get();

    let (c, p) = oneshot::init();

    do task::spawn_with(c) |_c| {
        fail;
    }

    #error("%?", recv(p));
    // make sure we get killed if we missed it in the receive.
    loop { task::yield() }
}
<commit_msg>xfailing pipe-detect-term on Windows, because it requires failure.<commit_after>// Make sure that we can detect when one end of the pipe is closed.

// xfail-pretty
// xfail-win32

use std;
import std::timer::sleep;
import std::uv;

import pipes::{try_recv, recv};

proto! oneshot {
    waiting:send {
        signal -> signaled
    }

    signaled:send { }
}

fn main() {
    let iotask = uv::global_loop::get();

    let c = pipes::spawn_service(oneshot::init, |p| {
        alt try_recv(p) {
          some(*) { fail }
          none { }
        }
    });

    sleep(iotask, 100);

    let b = task::builder();
    task::unsupervise(b);
    task::run(b, failtest);
}

// Make sure the right thing happens during failure.
fn failtest() {
    let iotask = uv::global_loop::get();

    let (c, p) = oneshot::init();

    do task::spawn_with(c) |_c| {
        fail;
    }

    #error("%?", recv(p));
    // make sure we get killed if we missed it in the receive.
    loop { task::yield() }
}
<|endoftext|>


<commit_before>//! Layout handling

// remove
#![allow(unused)]

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::VIEW_MAXIMIZED;
use std::rc::{Rc, Weak};
use std::fmt;

pub type Container = Box<Containable>;
pub type Node = Rc<Container>;

#[derive(Debug, Clone, Copy, PartialEq)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
pub enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<Node>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Node>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str>;

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u32, u32);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Returns true if this container is a parent of the child
    fn is_parent_of(&self, child: Node) -> bool {
        unimplemented!();
    }

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of(&self, parent: Node) -> bool {
        unimplemented!();
    }

    fn is_root(&self) -> bool {
        self.get_type() == ContainerType::Root
    }

    fn add_child(&mut self, container: Node);

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, container_type: ContainerType) -> Option<Node> {
        let mut container = self.get_parent();
        loop {
            if let Some(parent) = container {
                if parent.get_type() == container_type {
                    return Some(parent);
                }
                container = parent.get_parent();
            } else {
                return None;
            }
        }
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace(&self) -> Node;
}

pub struct Workspace {
    handle: Option<WlcOutput>,

    parent: Weak<Container>,
    children: Vec<Node>,
    container_type: ContainerType,
    layout: Layout,

    width: u32,
    height: u32,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Workspace {
    /// Makes a new workspace container. This should only be called by root
    /// since it will properly initialize the right number and properly put
    /// them in the main tree.
    pub fn new_workspace(root: Node) -> Node {
        let workspace: Node =
            Rc::new(Box::new(
                Workspace {
                    handle: None,
                    parent: Rc::downgrade(&root),
                    children: vec!(),
                    container_type: ContainerType::Root,
                    // NOTE Change this to some other default
                    layout: Layout::None,
                    // NOTE Figure out how to initialize these properly
                    width: 0,
                    height: 0,
                    x: 0,
                    y: 0,
                    visible: false,
                    is_focused: false,
                    is_floating: false,
                }));
        if let Some(root) = Rc::get_mut(&mut root.clone()) {
            root.add_child(workspace.clone());
            workspace
        } else {
            panic!("There was a weak reference to root, couldn't get mut");
        }
    }
}

pub struct Root {
    children: Vec<Node>,
}

impl fmt::Debug for Root {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let children = self.children.iter().map(|child|
                                                format!("{:?}", child.get_type()));
        let children_string = children.collect::<Vec<_>>().join(",");
        write!(f, "Root window. Children:\n{}", children_string)
    }
}

impl Containable for Root {
    fn get_parent(&self) -> Option<Node> {
        None
    }

    fn get_children(&self) -> Option<Vec<Node>> {
        if self.children.len() == 0 {
            None
        } else {
            Some(self.children.clone())
        }
    }

    fn get_type(&self) -> ContainerType {
        ContainerType::Root
    }

    fn add_child(&mut self, container: Node) {
        // NOTE check to make sure we are not adding a duplicate
        self.children.push(container);
    }

    fn is_focused(&self) -> bool {
        false
    }

    fn remove_container(&self) -> Result<(), &'static str> {
        panic!("Cannot remove the root of the tree");
    }

    fn set_visibility(&mut self, visibility: bool) {
        trace!("Setting visibility of root");
    }

    fn get_dimensions(&self) -> (u32, u32) {
        panic!("Root has no dimensions");
    }

    fn get_position(&self) -> (i64, i64) {
        panic!("Root has no position");
    }

    fn is_parent_of(&self, child: Node) -> bool {
        true
    }

    fn is_child_of(&self, parent: Node) -> bool {
        false
    }

    fn is_root(&self) -> bool {
        true
    }
}

impl Root {
    /// Makes the root container. There should be only one of these
    /// Does not ensure that this is the only root container
    /* NOTE Need to find a way to ensure there is only one of these things
     * Perhaps set a static global variable
     */
    pub fn new_root() -> Node {
        trace!("Root created");
        Rc::new(Box::new(Root { children: vec!() }))
    }
}

impl Containable for Workspace {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<Node> {
        match self.container_type {
            ContainerType::Root => None,
            _ => self.parent.upgrade()
        }
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Node>> {
        if self.children.len() == 0 {
            None
        } else {
            Some(self.children.clone())
        }
    }

    fn add_child(&mut self, container: Node) {
        // NOTE check to make sure we are not adding a duplicate
        self.children.push(container);
    }

    fn get_type(&self) -> ContainerType {
        self.container_type
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        if let Some(children) = self.get_children() {
            for child in children {
                child.remove_container().ok();
                drop(child);
            }
        }
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

pub struct View {
    handle: Option<Box<WlcView>>,
    parent: Weak<Container>,

    width: u32,
    height: u32,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<Node> {
        self.parent.upgrade()
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Node>> {
        None
    }

    fn add_child(&mut self, container: Node) {
        panic!("Views can not have children");
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        if let Some(ref handle) = self.handle {
            handle.close();
        }
        drop(self);
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }
}

impl Viewable for View {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool {
        if let Some(ref handle) = self.handle {
            match handle.get_state() {
                VIEW_MAXIMIZED => true,
                _ => false,
            }
        } else {
            false
        }
    }

    /// Figures out if the view is focused
    fn is_active(&self) -> bool {
        self.is_focused
    }

    /// Gets the active workspace of the view
    fn active_workspace(&self) -> Node {
        let mut workspace = self.get_parent();
        loop {
            if let Some(parent) = workspace {
                if parent.get_type() == ContainerType::Workspace {
                    return parent
                }
                workspace = parent.get_parent();
            } else {
                // Should never happen under our current setup
                panic!("View not attached to a workspace!")
            }
        }
    }

}
<commit_msg>Add proper Debug implementation for Root<commit_after>//! Layout handling

// remove
#![allow(unused)]

use rustwlc::handle::{WlcView, WlcOutput};
use rustwlc::types::VIEW_MAXIMIZED;
use std::rc::{Rc, Weak};
use std::fmt::{Debug, Formatter};
use std::fmt::Result as FmtResult;

pub type Container = Box<Containable>;
pub type Node = Rc<Container>;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ContainerType {
    /// Root container, only one exists
    Root,
    /// WlcOutput/Monitor
    Output,
    /// A workspace
    Workspace,
    /// A view (window)
    View
}

/// Layout mode for a container
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Layout {
    None,
    Horizontal,
    Vertical,
    Stacked,
    Tabbed,
    Floating
}

/// Like i3, everything (workspaces, containers, views) are containable.
pub trait Containable {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<Node>;

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Node>>;

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType;

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool;

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str>;

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool);

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u32, u32);

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64);

    /// Returns true if this container is a parent of the child
    fn is_parent_of(&self, child: Node) -> bool {
        unimplemented!();
    }

    /// Returns true if this view is a child is an decedent of the parent
    fn is_child_of(&self, parent: Node) -> bool {
        unimplemented!();
    }

    fn is_root(&self) -> bool {
        self.get_type() == ContainerType::Root
    }

    fn add_child(&mut self, container: Node);

    /// Finds a parent container with the given type, if there is any
    fn get_parent_by_type(&self, container_type: ContainerType) -> Option<Node> {
        let mut container = self.get_parent();
        loop {
            if let Some(parent) = container {
                if parent.get_type() == container_type {
                    return Some(parent);
                }
                container = parent.get_parent();
            } else {
                return None;
            }
        }
    }
}

/// View specific functions
pub trait Viewable {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool;

    /// Figures out if the view is focused
    fn is_active(&self) -> bool;

    /// Gets the active workspace of the view
    fn active_workspace(&self) -> Node;
}

pub struct Workspace {
    handle: Option<WlcOutput>,

    parent: Weak<Container>,
    children: Vec<Node>,
    container_type: ContainerType,
    layout: Layout,

    width: u32,
    height: u32,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Workspace {
    /// Makes a new workspace container. This should only be called by root
    /// since it will properly initialize the right number and properly put
    /// them in the main tree.
    pub fn new_workspace(root: Node) -> Node {
        let workspace: Node =
            Rc::new(Box::new(
                Workspace {
                    handle: None,
                    parent: Rc::downgrade(&root),
                    children: vec!(),
                    container_type: ContainerType::Root,
                    // NOTE Change this to some other default
                    layout: Layout::None,
                    // NOTE Figure out how to initialize these properly
                    width: 0,
                    height: 0,
                    x: 0,
                    y: 0,
                    visible: false,
                    is_focused: false,
                    is_floating: false,
                }));
        if let Some(root) = Rc::get_mut(&mut root.clone()) {
            root.add_child(workspace.clone());
            workspace
        } else {
            panic!("There was a weak reference to root, couldn't get mut");
        }
    }
}

pub struct Root {
    children: Vec<Node>,
}

impl Debug for Root {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        write!(f, "Root: ");
            f.debug_list()
            .entries(self.children.iter().map(|child: &Node| child.get_type()))
            .finish()
    }
}

impl Containable for Root {
    fn get_parent(&self) -> Option<Node> {
        None
    }

    fn get_children(&self) -> Option<Vec<Node>> {
        if self.children.len() == 0 {
            None
        } else {
            Some(self.children.clone())
        }
    }

    fn get_type(&self) -> ContainerType {
        ContainerType::Root
    }

    fn add_child(&mut self, container: Node) {
        // NOTE check to make sure we are not adding a duplicate
        self.children.push(container);
    }

    fn is_focused(&self) -> bool {
        false
    }

    fn remove_container(&self) -> Result<(), &'static str> {
        panic!("Cannot remove the root of the tree");
    }

    fn set_visibility(&mut self, visibility: bool) {
        trace!("Setting visibility of root");
    }

    fn get_dimensions(&self) -> (u32, u32) {
        panic!("Root has no dimensions");
    }

    fn get_position(&self) -> (i64, i64) {
        panic!("Root has no position");
    }

    fn is_parent_of(&self, child: Node) -> bool {
        true
    }

    fn is_child_of(&self, parent: Node) -> bool {
        false
    }

    fn is_root(&self) -> bool {
        true
    }
}

impl Root {
    /// Makes the root container. There should be only one of these
    /// Does not ensure that this is the only root container
    /* NOTE Need to find a way to ensure there is only one of these things
     * Perhaps set a static global variable
     */
    pub fn new_root() -> Node {
        trace!("Root created");
        Rc::new(Box::new(Root { children: vec!() }))
    }
}

impl Containable for Workspace {

    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<Node> {
        match self.container_type {
            ContainerType::Root => None,
            _ => self.parent.upgrade()
        }
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Node>> {
        if self.children.len() == 0 {
            None
        } else {
            Some(self.children.clone())
        }
    }

    fn add_child(&mut self, container: Node) {
        // NOTE check to make sure we are not adding a duplicate
        self.children.push(container);
    }

    fn get_type(&self) -> ContainerType {
        self.container_type
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        if let Some(children) = self.get_children() {
            for child in children {
                child.remove_container().ok();
                drop(child);
            }
        }
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X (width) and Y (height) dimensions of the container
    fn get_dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }

}

pub struct View {
    handle: Option<Box<WlcView>>,
    parent: Weak<Container>,

    width: u32,
    height: u32,

    x: i64,
    y: i64,

    visible: bool,
    is_focused: bool,
    is_floating: bool,
}

impl Containable for View {
    /// Gets the parent that this container sits in.
    ///
    /// If the container is the root, it returns None
    fn get_parent(&self) -> Option<Node> {
        self.parent.upgrade()
    }

    /// Gets the children of this container.
    ///
    /// Views never have children
    fn get_children(&self) -> Option<Vec<Node>> {
        None
    }

    fn add_child(&mut self, container: Node) {
        panic!("Views can not have children");
    }

    /// Gets the type of the container
    fn get_type(&self) -> ContainerType {
        ContainerType::View
    }

    /// Returns true if this container is focused.
    fn is_focused(&self) -> bool {
        self.is_focused
    }

    /// Removes this container and all of its children
    fn remove_container(&self) -> Result<(), &'static str> {
        if let Some(ref handle) = self.handle {
            handle.close();
        }
        drop(self);
        Ok(())
    }

    /// Sets this container (and everything in it) to given visibility
    fn set_visibility(&mut self, visibility: bool) {
        self.visible = visibility
    }

    /// Gets the X and Y dimensions of the container
    fn get_dimensions(&self) -> (u32, u32) {
        (self.width, self.height)
    }

    /// Gets the position of this container on the screen
    fn get_position(&self) -> (i64, i64) {
        (self.x, self.y)
    }
}

impl Viewable for View {
    /// Determines if the view is full screen
    fn is_fullscreen(&self) -> bool {
        if let Some(ref handle) = self.handle {
            match handle.get_state() {
                VIEW_MAXIMIZED => true,
                _ => false,
            }
        } else {
            false
        }
    }

    /// Figures out if the view is focused
    fn is_active(&self) -> bool {
        self.is_focused
    }

    /// Gets the active workspace of the view
    fn active_workspace(&self) -> Node {
        let mut workspace = self.get_parent();
        loop {
            if let Some(parent) = workspace {
                if parent.get_type() == ContainerType::Workspace {
                    return parent
                }
                workspace = parent.get_parent();
            } else {
                // Should never happen under our current setup
                panic!("View not attached to a workspace!")
            }
        }
    }
}
<|endoftext|>


<commit_before>use crate::io::util::lines::{lines, Lines};
use crate::io::util::read_line::{read_line, ReadLine};
use crate::io::util::read_until::{read_until, ReadUntil};
use crate::io::util::split::{split, Split};
use crate::io::AsyncBufRead;

cfg_io_util! {
    /// An extension trait which adds utility methods to `AsyncBufRead` types.
    pub trait AsyncBufReadExt: AsyncBufRead {
        /// Creates a future which will read all the bytes associated with this I/O
        /// object into `buf` until the delimiter `byte` or EOF is reached.
        /// This method is the async equivalent to [`BufRead::read_until`](std::io::BufRead::read_until).
        ///
        /// This function will read bytes from the underlying stream until the
        /// delimiter or EOF is found. Once found, all bytes up to, and including,
        /// the delimiter (if found) will be appended to `buf`.
        ///
        /// The returned future will resolve to the number of bytes read once the read
        /// operation is completed.
        ///
        /// In the case of an error the buffer and the object will be discarded, with
        /// the error yielded.
        fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
        where
            Self: Unpin,
        {
            read_until(self, byte, buf)
        }

        /// Creates a future which will read all the bytes associated with this I/O
        /// object into `buf` until a newline (the 0xA byte) or EOF is reached,
        /// This method is the async equivalent to [`BufRead::read_line`](std::io::BufRead::read_line).
        ///
        /// This function will read bytes from the underlying stream until the
        /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes
        /// up to, and including, the delimiter (if found) will be appended to
        /// `buf`.
        ///
        /// The returned future will resolve to the number of bytes read once the read
        /// operation is completed.
        ///
        /// In the case of an error the buffer and the object will be discarded, with
        /// the error yielded.
        ///
        /// # Errors
        ///
        /// This function has the same error semantics as [`read_until`] and will
        /// also return an error if the read bytes are not valid UTF-8. If an I/O
        /// error is encountered then `buf` may contain some bytes already read in
        /// the event that all data read so far was valid UTF-8.
        ///
        /// [`read_until`]: AsyncBufReadExt::read_until
        fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
        where
            Self: Unpin,
        {
            read_line(self, buf)
        }

        /// Returns a stream of the contents of this reader split on the byte
        /// `byte`.
        ///
        /// This method is the asynchronous equivalent to
        /// [`BufRead::split`](std::io::BufRead::split).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
        /// the delimiter byte at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`Vec<u8>`]: std::vec::Vec
        ///
        /// # Errors
        ///
        /// Each item of the stream has the same error semantics as
        /// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until).
        ///
        /// # Examples
        ///
        /// ```
        /// # use tokio::io::AsyncBufRead;
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> {
        /// let mut segments = my_buf_read.split(b'f');
        ///
        /// while let Some(segment) = segments.next_segment().await? {
        ///     println!("length = {}", segment.len())
        /// }
        /// # Ok(())
        /// # }
        /// ```
        fn split(self, byte: u8) -> Split<Self>
        where
            Self: Sized + Unpin,
        {
            split(self, byte)
        }

        /// Returns a stream over the lines of this reader.
        /// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
        /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`String`]: String
        ///
        /// # Errors
        ///
        /// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`].
        ///
        /// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
        fn lines(self) -> Lines<Self>
        where
            Self: Sized,
        {
            lines(self)
        }
    }
}

impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}
<commit_msg>doc: add API docs for AsyncBufReadExt::read_line (#1866)<commit_after>use crate::io::util::lines::{lines, Lines};
use crate::io::util::read_line::{read_line, ReadLine};
use crate::io::util::read_until::{read_until, ReadUntil};
use crate::io::util::split::{split, Split};
use crate::io::AsyncBufRead;

cfg_io_util! {
    /// An extension trait which adds utility methods to `AsyncBufRead` types.
    pub trait AsyncBufReadExt: AsyncBufRead {
        /// Creates a future which will read all the bytes associated with this I/O
        /// object into `buf` until the delimiter `byte` or EOF is reached.
        /// This method is the async equivalent to [`BufRead::read_until`](std::io::BufRead::read_until).
        ///
        /// This function will read bytes from the underlying stream until the
        /// delimiter or EOF is found. Once found, all bytes up to, and including,
        /// the delimiter (if found) will be appended to `buf`.
        ///
        /// The returned future will resolve to the number of bytes read once the read
        /// operation is completed.
        ///
        /// In the case of an error the buffer and the object will be discarded, with
        /// the error yielded.
        fn read_until<'a>(&'a mut self, byte: u8, buf: &'a mut Vec<u8>) -> ReadUntil<'a, Self>
        where
            Self: Unpin,
        {
            read_until(self, byte, buf)
        }

        /// Creates a future which will read all the bytes associated with this I/O
        /// object into `buf` until a newline (the 0xA byte) or EOF is reached,
        /// This method is the async equivalent to [`BufRead::read_line`](std::io::BufRead::read_line).
        ///
        /// This function will read bytes from the underlying stream until the
        /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes
        /// up to, and including, the delimiter (if found) will be appended to
        /// `buf`.
        ///
        /// The returned future will resolve to the number of bytes read once the read
        /// operation is completed.
        ///
        /// In the case of an error the buffer and the object will be discarded, with
        /// the error yielded.
        ///
        /// # Errors
        ///
        /// This function has the same error semantics as [`read_until`] and will
        /// also return an error if the read bytes are not valid UTF-8. If an I/O
        /// error is encountered then `buf` may contain some bytes already read in
        /// the event that all data read so far was valid UTF-8.
        ///
        /// [`read_until`]: AsyncBufReadExt::read_until
        /// ------------
        /// Read all bytes until a newline (the 0xA byte) is reached, and append
        /// them to the provided buffer.
        ///
        /// This function will read bytes from the underlying stream until the
        /// newline delimiter (the 0xA byte) or EOF is found. Once found, all bytes
        /// up to, and including, the delimiter (if found) will be appended to
        /// `buf`.
        ///
        /// If successful, this function will return the total number of bytes read.
        ///
        /// If this function returns `Ok(0)`, the stream has reached EOF.
        ///
        /// # Errors
        ///
        /// This function has the same error semantics as [`read_until`] and will
        /// also return an error if the read bytes are not valid UTF-8. If an I/O
        /// error is encountered then `buf` may contain some bytes already read in
        /// the event that all data read so far was valid UTF-8.
        ///
        /// [`read_until`]: AsyncBufReadExt::read_until
        ///
        /// # Examples
        ///
        /// [`std::io::Cursor`][`Cursor`] is a type that implements
        /// `AsyncBufRead`. In this example, we use [`Cursor`] to read all the
        /// lines in a byte slice:
        ///
        /// [`Cursor`]: std::io::Cursor
        ///
        /// ```
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// use std::io::Cursor;
        ///
        /// #[tokio::main]
        /// async fn main() {
        ///     let mut cursor = Cursor::new(b"foo\nbar");
        ///     let mut buf = String::new();
        ///
        ///     // cursor is at 'f'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 4);
        ///     assert_eq!(buf, "foo\n");
        ///     buf.clear();
        ///
        ///     // cursor is at 'b'
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 3);
        ///     assert_eq!(buf, "bar");
        ///     buf.clear();
        ///
        ///     // cursor is at EOF
        ///     let num_bytes = cursor.read_line(&mut buf)
        ///         .await
        ///         .expect("reading from cursor won't fail");
        ///
        ///     assert_eq!(num_bytes, 0);
        ///     assert_eq!(buf, "");
        /// }
        /// ```
        fn read_line<'a>(&'a mut self, buf: &'a mut String) -> ReadLine<'a, Self>
        where
            Self: Unpin,
        {
            read_line(self, buf)
        }

        /// Returns a stream of the contents of this reader split on the byte
        /// `byte`.
        ///
        /// This method is the asynchronous equivalent to
        /// [`BufRead::split`](std::io::BufRead::split).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`Vec<u8>`]`>`. Each vector returned will *not* have
        /// the delimiter byte at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`Vec<u8>`]: std::vec::Vec
        ///
        /// # Errors
        ///
        /// Each item of the stream has the same error semantics as
        /// [`AsyncBufReadExt::read_until`](AsyncBufReadExt::read_until).
        ///
        /// # Examples
        ///
        /// ```
        /// # use tokio::io::AsyncBufRead;
        /// use tokio::io::AsyncBufReadExt;
        ///
        /// # async fn dox(my_buf_read: impl AsyncBufRead + Unpin) -> std::io::Result<()> {
        /// let mut segments = my_buf_read.split(b'f');
        ///
        /// while let Some(segment) = segments.next_segment().await? {
        ///     println!("length = {}", segment.len())
        /// }
        /// # Ok(())
        /// # }
        /// ```
        fn split(self, byte: u8) -> Split<Self>
        where
            Self: Sized + Unpin,
        {
            split(self, byte)
        }

        /// Returns a stream over the lines of this reader.
        /// This method is the async equivalent to [`BufRead::lines`](std::io::BufRead::lines).
        ///
        /// The stream returned from this function will yield instances of
        /// [`io::Result`]`<`[`String`]`>`. Each string returned will *not* have a newline
        /// byte (the 0xA byte) or CRLF (0xD, 0xA bytes) at the end.
        ///
        /// [`io::Result`]: std::io::Result
        /// [`String`]: String
        ///
        /// # Errors
        ///
        /// Each line of the stream has the same error semantics as [`AsyncBufReadExt::read_line`].
        ///
        /// [`AsyncBufReadExt::read_line`]: AsyncBufReadExt::read_line
        fn lines(self) -> Lines<Self>
        where
            Self: Sized,
        {
            lines(self)
        }
    }
}

impl<R: AsyncBufRead + ?Sized> AsyncBufReadExt for R {}
<|endoftext|>


<commit_before>#![warn(clippy::while_let_loop, clippy::empty_loop, clippy::while_let_on_iterator)]
#![allow(dead_code, clippy::never_loop, unused, clippy::cognitive_complexity)]

fn main() {
    let y = Some(true);
    loop {
        if let Some(_x) = y {
            let _v = 1;
        } else {
            break;
        }
    }
    loop {
        // no error, break is not in else clause
        if let Some(_x) = y {
            let _v = 1;
        }
        break;
    }
    loop {
        match y {
            Some(_x) => true,
            None => break,
        };
    }
    loop {
        let x = match y {
            Some(x) => x,
            None => break,
        };
        let _x = x;
        let _str = "foo";
    }
    loop {
        let x = match y {
            Some(x) => x,
            None => break,
        };
        {
            let _a = "bar";
        };
        {
            let _b = "foobar";
        }
    }
    loop {
        // no error, else branch does something other than break
        match y {
            Some(_x) => true,
            _ => {
                let _z = 1;
                break;
            },
        };
    }
    while let Some(x) = y {
        // no error, obviously
        println!("{}", x);
    }

    // #675, this used to have a wrong suggestion
    loop {
        let (e, l) = match "".split_whitespace().next() {
            Some(word) => (word.is_empty(), word.len()),
            None => break,
        };

        let _ = (e, l);
    }

    let mut iter = 1..20;
    while let Option::Some(x) = iter.next() {
        println!("{}", x);
    }

    let mut iter = 1..20;
    while let Some(x) = iter.next() {
        println!("{}", x);
    }

    let mut iter = 1..20;
    while let Some(_) = iter.next() {}

    let mut iter = 1..20;
    while let None = iter.next() {} // this is fine (if nonsensical)

    let mut iter = 1..20;
    if let Some(x) = iter.next() {
        // also fine
        println!("{}", x)
    }

    // the following shouldn't warn because it can't be written with a for loop
    let mut iter = 1u32..20;
    while let Some(x) = iter.next() {
        println!("next: {:?}", iter.next())
    }

    // neither can this
    let mut iter = 1u32..20;
    while let Some(x) = iter.next() {
        println!("next: {:?}", iter.next());
    }

    // or this
    let mut iter = 1u32..20;
    while let Some(x) = iter.next() {
        break;
    }
    println!("Remaining iter {:?}", iter);

    // or this
    let mut iter = 1u32..20;
    while let Some(x) = iter.next() {
        iter = 1..20;
    }
}

// regression test (#360)
// this should not panic
// it's ok if further iterations of the lint
// cause this function to trigger it
fn no_panic<T>(slice: &[T]) {
    let mut iter = slice.iter();
    loop {
        let _ = match iter.next() {
            Some(ele) => ele,
            None => break,
        };
        loop {}
    }
}

fn issue1017() {
    let r: Result<u32, u32> = Ok(42);
    let mut len = 1337;

    loop {
        match r {
            Err(_) => len = 0,
            Ok(length) => {
                len = length;
                break;
            },
        }
    }
}

// Issue #1188
fn refutable() {
    let a = [42, 1337];
    let mut b = a.iter();

    // consume all the 42s
    while let Some(&42) = b.next() {}

    let a = [(1, 2, 3)];
    let mut b = a.iter();

    while let Some(&(1, 2, 3)) = b.next() {}

    let a = [Some(42)];
    let mut b = a.iter();

    while let Some(&None) = b.next() {}

    /* This gives “refutable pattern in `for` loop binding: `&_` not covered”
    for &42 in b {}
    for &(1, 2, 3) in b {}
    for &Option::None in b.next() {}
    // */
}

fn nested_loops() {
    let a = [42, 1337];
    let mut y = a.iter();
    loop {
        // x is reused, so don't lint here
        while let Some(v) = y.next() {}
    }

    let mut y = a.iter();
    for _ in 0..2 {
        while let Some(v) = y.next() {
            // y is reused, don't lint
        }
    }

    loop {
        let mut y = a.iter();
        while let Some(v) = y.next() {
            // use a for loop here
        }
    }
}

fn issue1948() {
    // should not trigger clippy::while_let_loop lint because break passes an expression
    let a = Some(10);
    let b = loop {
        if let Some(c) = a {
            break Some(c);
        } else {
            break None;
        }
    };
}

fn issue1121() {
    use std::collections::HashSet;
    let mut values = HashSet::new();
    values.insert(1);

    while let Some(&value) = values.iter().next() {
        values.remove(&value);
    }
}

fn issue2965() {
    // This should not cause an ICE and suggest:
    //
    // for _ in values.iter() {}
    //
    use std::collections::HashSet;
    let mut values = HashSet::new();
    values.insert(1);

    while let Some(..) = values.iter().next() {
        values.remove(&1);
    }
}

fn issue3670() {
    let array = [Some(0), None, Some(1)];
    let mut iter = array.iter();

    while let Some(elem) = iter.next() {
        let _ = elem.or_else(|| *iter.next()?);
    }
}
<commit_msg>Auto merge of #4064 - mikerite:fix-771, r=matthiaskrgr<commit_after>#![warn(clippy::while_let_loop, clippy::empty_loop, clippy::while_let_on_iterator)]
#![allow(dead_code, clippy::never_loop, unused, clippy::cognitive_complexity)]

fn main() {
    let y = Some(true);
    loop {
        if let Some(_x) = y {
            let _v = 1;
        } else {
            break;
        }
    }
    loop {
        // no error, break is not in else clause
        if let Some(_x) = y {
            let _v = 1;
        }
        break;
    }
    loop {
        match y {
            Some(_x) => true,
            None => break,
        };
    }
    loop {
        let x = match y {
            Some(x) => x,
            None => break,
        };
        let _x = x;
        let _str = "foo";
    }
    loop {
        let x = match y {
            Some(x) => x,
            None => break,
        };
        {
            let _a = "bar";
        };
        {
            let _b = "foobar";
        }
    }
    loop {
        // no error, else branch does something other than break
        match y {
            Some(_x) => true,
            _ => {
                let _z = 1;
                break;
            },
        };
    }
    while let Some(x) = y {
        // no error, obviously
        println!("{}", x);
    }

    // #675, this used to have a wrong suggestion
    loop {
        let (e, l) = match "".split_whitespace().next() {
            Some(word) => (word.is_empty(), word.len()),
            None => break,
        };

        let _ = (e, l);
    }

    let mut iter = 1..20;
    while let Option::Some(x) = iter.next() {
        println!("{}", x);
    }

    let mut iter = 1..20;
    while let Some(x) = iter.next() {
        println!("{}", x);
    }

    let mut iter = 1..20;
    while let Some(_) = iter.next() {}

    let mut iter = 1..20;
    while let None = iter.next() {} // this is fine (if nonsensical)

    let mut iter = 1..20;
    if let Some(x) = iter.next() {
        // also fine
        println!("{}", x)
    }

    // the following shouldn't warn because it can't be written with a for loop
    let mut iter = 1u32..20;
    while let Some(x) = iter.next() {
        println!("next: {:?}", iter.next())
    }

    // neither can this
    let mut iter = 1u32..20;
    while let Some(x) = iter.next() {
        println!("next: {:?}", iter.next());
    }

    // or this
    let mut iter = 1u32..20;
    while let Some(x) = iter.next() {
        break;
    }
    println!("Remaining iter {:?}", iter);

    // or this
    let mut iter = 1u32..20;
    while let Some(x) = iter.next() {
        iter = 1..20;
    }
}

// regression test (#360)
// this should not panic
// it's ok if further iterations of the lint
// cause this function to trigger it
fn no_panic<T>(slice: &[T]) {
    let mut iter = slice.iter();
    loop {
        let _ = match iter.next() {
            Some(ele) => ele,
            None => break,
        };
        loop {}
    }
}

fn issue1017() {
    let r: Result<u32, u32> = Ok(42);
    let mut len = 1337;

    loop {
        match r {
            Err(_) => len = 0,
            Ok(length) => {
                len = length;
                break;
            },
        }
    }
}

// Issue #1188
fn refutable() {
    let a = [42, 1337];
    let mut b = a.iter();

    // consume all the 42s
    while let Some(&42) = b.next() {}

    let a = [(1, 2, 3)];
    let mut b = a.iter();

    while let Some(&(1, 2, 3)) = b.next() {}

    let a = [Some(42)];
    let mut b = a.iter();

    while let Some(&None) = b.next() {}

    /* This gives “refutable pattern in `for` loop binding: `&_` not covered”
    for &42 in b {}
    for &(1, 2, 3) in b {}
    for &Option::None in b.next() {}
    // */
}

fn nested_loops() {
    let a = [42, 1337];
    let mut y = a.iter();
    loop {
        // x is reused, so don't lint here
        while let Some(v) = y.next() {}
    }

    let mut y = a.iter();
    for _ in 0..2 {
        while let Some(v) = y.next() {
            // y is reused, don't lint
        }
    }

    loop {
        let mut y = a.iter();
        while let Some(v) = y.next() {
            // use a for loop here
        }
    }
}

fn issue1948() {
    // should not trigger clippy::while_let_loop lint because break passes an expression
    let a = Some(10);
    let b = loop {
        if let Some(c) = a {
            break Some(c);
        } else {
            break None;
        }
    };
}

fn issue1121() {
    use std::collections::HashSet;
    let mut values = HashSet::new();
    values.insert(1);

    while let Some(&value) = values.iter().next() {
        values.remove(&value);
    }
}

fn issue2965() {
    // This should not cause an ICE and suggest:
    //
    // for _ in values.iter() {}
    //
    use std::collections::HashSet;
    let mut values = HashSet::new();
    values.insert(1);

    while let Some(..) = values.iter().next() {
        values.remove(&1);
    }
}

fn issue3670() {
    let array = [Some(0), None, Some(1)];
    let mut iter = array.iter();

    while let Some(elem) = iter.next() {
        let _ = elem.or_else(|| *iter.next()?);
    }
}

fn issue771() {
    let mut a = 100;
    let b = Some(true);
    loop {
        if a > 10 {
            break;
        }

        match b {
            Some(_) => a = 0,
            None => break,
        }
    }
}
<|endoftext|>