<commit_before>use byteorder::{ByteOrder, LittleEndian};

use opcodes::{AddressingMode, OpCode};

pub struct Disassembler;

/// A 6502 instruction disassembler
impl Disassembler {
    /// Accepts a slice of 6502 bytecodes and translates them
    /// into an assembly String representation
    ///
    /// # Example
    /// ```
    /// use rs6502::Disassembler;
    ///
    /// let code: Vec<u8> = vec![0xA9, 0x20, 0x8D, 0x00, 0x44];
    /// let asm = Disassembler::disassemble(&code);
    ///
    /// assert_eq!(Disassembler::clean_asm("
    ///
    ///     0000 LDA #$20
    ///     0002 STA $4400
    ///
    /// "), Disassembler::clean_asm(asm));
    /// ```
    pub fn disassemble(raw: &[u8]) -> String {
        let mut result = String::new();

        let mut i: usize = 0;
        while i < raw.len() {
            let opcode = OpCode::from_raw_byte(raw[i]);
            let val = match opcode.mode {
                AddressingMode::Immediate => format!(" #${:02X}", raw[i + 0x01]),
                AddressingMode::Indirect => {
                    format!(" (${:04X})", LittleEndian::read_u16(&raw[i + 0x01..]))
                }
                AddressingMode::Relative => {
                    let mut offset = raw[i + 0x01] as i8;
                    let addr = if offset < 0 {
                        i - (-offset - 0x02) as usize
                    } else {
                        i + (offset as usize) + 0x02
                    };
                    format!(" ${:04X}", addr)
                }
                AddressingMode::ZeroPage => format!(" ${:02X}", raw[i + 0x01]),
                AddressingMode::ZeroPageX => format!(" ${:02X},X", raw[i + 0x01]),
                AddressingMode::ZeroPageY => format!(" ${:02X},Y", raw[i + 0x01]),
                AddressingMode::Absolute => {
                    format!(" ${:04X}", LittleEndian::read_u16(&raw[i + 0x01..]))
                }
                AddressingMode::AbsoluteX => {
                    format!(" ${:04X},X", LittleEndian::read_u16(&raw[i + 0x01..]))
                }
                AddressingMode::AbsoluteY => {
                    format!(" ${:04X},Y", LittleEndian::read_u16(&raw[i + 0x01..]))
                }
                AddressingMode::IndirectX => format!(" (${:02X},X)", raw[i + 0x01]),
                AddressingMode::IndirectY => format!(" (${:02X}),Y", raw[i + 0x01]),
                _ => "".into(),
            };
            let opcode_text = format!("{:04X} {}{}\n", i, opcode.mnemonic, val);
            result.push_str(&opcode_text);
            i += opcode.length as usize;
        }

        result
    }

    /// Returns a Vector of Strings where each entry
    /// is a non-empty line of assembly instructions, with
    /// all leading and trailing whitespace removed.
    ///
    /// # Example
    ///
    /// ```
    /// use rs6502::Disassembler;
    ///
    /// assert_eq!(Disassembler::clean_asm("
    ///
    ///     0000 LDA #$20
    ///     0002 STA $4400
    ///
    /// "), &["0000 LDA #$20", "0002 STA $4400"]);
    /// ```
    pub fn clean_asm<I>(input: I) -> Vec<String>
        where I: Into<String>
    {
        input.into()
            .lines()
            .map(|line| line.trim())
            .map(String::from)
            .filter(|line| line.len() > 0)
            .collect()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn can_disassemble_basic_instructions() {
        let code: Vec<u8> = vec![0xA9, 0x20, 0x8D, 0x00, 0x44];
        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDA #$20
            0002 STA $4400

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_indirect_jmp() {
        let code: Vec<u8> = vec![0x6C, 0x00, 0x44];
        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 JMP ($4400)

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_relative_addressing() {
        let code: Vec<u8> = vec![0xA9, 0x20, 0x69, 0x10, 0xD0, 0xFA];
        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDA #$20
            0002 ADC #$10
            0004 BNE $0000

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_zero_page_addressing() {
        let code: Vec<u8> = vec![0xA5, 0x35];
        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDA $35

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_zero_page_indexed_addressing() {
        let code: Vec<u8> = vec![0x95, 0x44, 0x96, 0xFE];
        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 STA $44,X
            0002 STX $FE,Y

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_absolute_addressing() {
        let code: Vec<u8> = vec![0x8D, 0x00, 0x44];
        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 STA $4400

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_absolute_indexed_addressing() {
        let code: Vec<u8> = vec![0x9D, 0x00, 0x44, 0x99, 0xFE, 0xFF];
        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 STA $4400,X
            0003 STA $FFFE,Y

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_indirect_indexed_addressing() {
        let code: Vec<u8> = vec![0x81, 0x44, 0x91, 0xFE];
        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 STA ($44,X)
            0002 STA ($FE),Y

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn move_memory_down_test() {
        let code: Vec<u8> = vec![0xA0, 0x00, 0xAE, 0x00, 0x00, 0xF0, 0x10, 0xB1, 0x02, 0x91, 0x03,
                                 0xC8, 0xD0, 0xF9, 0xEE, 0x02, 0x00, 0xEE, 0x03, 0x00, 0xCA, 0xD0,
                                 0xF0, 0xAE, 0x01, 0x00, 0xF0, 0x08, 0xB1, 0x02, 0x91, 0x03, 0xC8,
                                 0xCA, 0xD0, 0xF8, 0x60];

        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDY #$00
            0002 LDX $0000
            0005 BEQ $0017
            0007 LDA ($02),Y
            0009 STA ($03),Y
            000B INY
            000C BNE $0007
            000E INC $0002
            0011 INC $0003
            0014 DEX
            0015 BNE $0007
            0017 LDX $0001
            001A BEQ $0024
            001C LDA ($02),Y
            001E STA ($03),Y
            0020 INY
            0021 DEX
            0022 BNE $001C
            0024 RTS

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn test_memset_implementation() {
        let code: Vec<u8> = vec![0xA9, 0x00, 0xA8, 0x91, 0xFF, 0xC8, 0xCA, 0xD0, 0xFA, 0x60];
        let asm = Disassembler::disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDA #$00
            0002 TAY
            0003 STA ($FF),Y
            0005 INY
            0006 DEX
            0007 BNE $0003
            0009 RTS

        "),
                   Disassembler::clean_asm(asm));
    }
}
<commit_msg>Add 'just_code' flag to Disassembler<commit_after>use byteorder::{ByteOrder, LittleEndian};

use opcodes::{AddressingMode, OpCode};

pub struct Disassembler {
    /// Determines whether byte offsets are generated
    /// in the Assembly output
    just_code: bool,
}

/// A 6502 instruction disassembler
impl Disassembler {
    /// Creates a new, default instance of the Disassembler
    pub fn new() -> Disassembler {
        Disassembler { just_code: false }
    }

    /// Creates an instance of the Disassembler where no
    /// byte offsets are generated in the Assembly output
    pub fn with_code_only() -> Disassembler {
        Disassembler { just_code: true }
    }

    /// Accepts a slice of 6502 bytecodes and translates them
    /// into an assembly String representation
    ///
    /// # Example
    /// ```
    /// use rs6502::Disassembler;
    ///
    /// let dasm = Disassembler::new();
    ///
    /// let code: Vec<u8> = vec![0xA9, 0x20, 0x8D, 0x00, 0x44];
    /// let asm = dasm.disassemble(&code);
    ///
    /// assert_eq!(Disassembler::clean_asm("
    ///
    ///     0000 LDA #$20
    ///     0002 STA $4400
    ///
    /// "), Disassembler::clean_asm(asm));
    /// ```
    pub fn disassemble(&self, raw: &[u8]) -> String {
        let mut result = String::new();

        let mut i: usize = 0;
        while i < raw.len() {
            let opcode = OpCode::from_raw_byte(raw[i]);
            let val = match opcode.mode {
                AddressingMode::Immediate => format!(" #${:02X}", raw[i + 0x01]),
                AddressingMode::Indirect => {
                    format!(" (${:04X})", LittleEndian::read_u16(&raw[i + 0x01..]))
                }
                AddressingMode::Relative => {
                    let mut offset = raw[i + 0x01] as i8;
                    let addr = if offset < 0 {
                        i - (-offset - 0x02) as usize
                    } else {
                        i + (offset as usize) + 0x02
                    };
                    format!(" ${:04X}", addr)
                }
                AddressingMode::ZeroPage => format!(" ${:02X}", raw[i + 0x01]),
                AddressingMode::ZeroPageX => format!(" ${:02X},X", raw[i + 0x01]),
                AddressingMode::ZeroPageY => format!(" ${:02X},Y", raw[i + 0x01]),
                AddressingMode::Absolute => {
                    format!(" ${:04X}", LittleEndian::read_u16(&raw[i + 0x01..]))
                }
                AddressingMode::AbsoluteX => {
                    format!(" ${:04X},X", LittleEndian::read_u16(&raw[i + 0x01..]))
                }
                AddressingMode::AbsoluteY => {
                    format!(" ${:04X},Y", LittleEndian::read_u16(&raw[i + 0x01..]))
                }
                AddressingMode::IndirectX => format!(" (${:02X},X)", raw[i + 0x01]),
                AddressingMode::IndirectY => format!(" (${:02X}),Y", raw[i + 0x01]),
                _ => "".into(),
            };
            let opcode_text = if self.just_code {
                format!("{}{}\n", opcode.mnemonic, val)
            } else {
                format!("{:04X} {}{}\n", i, opcode.mnemonic, val)
            };
            result.push_str(&opcode_text);
            i += opcode.length as usize;
        }

        result
    }

    /// Returns a Vector of Strings where each entry
    /// is a non-empty line of assembly instructions, with
    /// all leading and trailing whitespace removed.
    ///
    /// # Example
    ///
    /// ```
    /// use rs6502::Disassembler;
    ///
    /// assert_eq!(Disassembler::clean_asm("
    ///
    ///     0000 LDA #$20
    ///     0002 STA $4400
    ///
    /// "), &["0000 LDA #$20", "0002 STA $4400"]);
    /// ```
    pub fn clean_asm<I>(input: I) -> Vec<String>
        where I: Into<String>
    {
        input.into()
            .lines()
            .map(|line| line.trim())
            .map(String::from)
            .filter(|line| line.len() > 0)
            .collect()
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn can_disassemble_basic_instructions() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0xA9, 0x20, 0x8D, 0x00, 0x44];
        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDA #$20
            0002 STA $4400

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_indirect_jmp() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0x6C, 0x00, 0x44];
        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 JMP ($4400)

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_relative_addressing() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0xA9, 0x20, 0x69, 0x10, 0xD0, 0xFA];
        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDA #$20
            0002 ADC #$10
            0004 BNE $0000

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_zero_page_addressing() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0xA5, 0x35];
        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDA $35

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_zero_page_indexed_addressing() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0x95, 0x44, 0x96, 0xFE];
        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 STA $44,X
            0002 STX $FE,Y

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_absolute_addressing() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0x8D, 0x00, 0x44];
        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 STA $4400

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_absolute_indexed_addressing() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0x9D, 0x00, 0x44, 0x99, 0xFE, 0xFF];
        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 STA $4400,X
            0003 STA $FFFE,Y

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn can_disassemble_indirect_indexed_addressing() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0x81, 0x44, 0x91, 0xFE];
        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 STA ($44,X)
            0002 STA ($FE),Y

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn move_memory_down_test() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0xA0, 0x00, 0xAE, 0x00, 0x00, 0xF0, 0x10, 0xB1, 0x02, 0x91, 0x03,
                                 0xC8, 0xD0, 0xF9, 0xEE, 0x02, 0x00, 0xEE, 0x03, 0x00, 0xCA, 0xD0,
                                 0xF0, 0xAE, 0x01, 0x00, 0xF0, 0x08, 0xB1, 0x02, 0x91, 0x03, 0xC8,
                                 0xCA, 0xD0, 0xF8, 0x60];

        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDY #$00
            0002 LDX $0000
            0005 BEQ $0017
            0007 LDA ($02),Y
            0009 STA ($03),Y
            000B INY
            000C BNE $0007
            000E INC $0002
            0011 INC $0003
            0014 DEX
            0015 BNE $0007
            0017 LDX $0001
            001A BEQ $0024
            001C LDA ($02),Y
            001E STA ($03),Y
            0020 INY
            0021 DEX
            0022 BNE $001C
            0024 RTS

        "),
                   Disassembler::clean_asm(asm));
    }

    #[test]
    fn test_memset_implementation() {
        let dasm = Disassembler::new();
        let code: Vec<u8> = vec![0xA9, 0x00, 0xA8, 0x91, 0xFF, 0xC8, 0xCA, 0xD0, 0xFA, 0x60];
        let asm = dasm.disassemble(&code);

        assert_eq!(Disassembler::clean_asm("

            0000 LDA #$00
            0002 TAY
            0003 STA ($FF),Y
            0005 INY
            0006 DEX
            0007 BNE $0003
            0009 RTS

        "),
                   Disassembler::clean_asm(asm));
    }
}
<|endoftext|>


<commit_before>// functions to ask the user for data, with crate:spinner
<commit_msg>Add initial codebase for ask_() functions<commit_after>// functions to ask the user for data, with crate:spinner

use std::io::stdin;

use regex::Regex;
use ansi_term::Colour::*;

/// Ask the user for a Yes/No answer. Optionally provide a default value. If none is provided, this
/// keeps loop{}ing
pub fn ask_bool(s: &str, default: Option<bool>) -> bool {
    lazy_static! {
        static ref R_YES: Regex = Regex::new(r"^[Yy]$").unwrap();
        static ref R_NO: Regex  = Regex::new(r"^[Nn]$").unwrap();
    }

    loop {
        ask_question(s, false);
        if match default { Some(s) => s, _ => true } {
            println!(" [Yn]: ");
        } else {
            println!(" [yN]: ");
        }

        let mut s = String::new();
        let _     = stdin().read_line(&mut s);

        if R_YES.is_match(&s[..]) {
            return true
        } else if R_NO.is_match(&s[..]) {
            return false
        } else {
            if default.is_some() {
                return default.unwrap();
            }

            // else again...
        }
    }
}

pub fn ask_uint(s: &str) -> u64 {
    unimplemented!()
}

pub fn ask_string(s: &str) -> String {
    unimplemented!()
}

pub fn ask_enum<E: From<String>>(s: &str) -> E {
    unimplemented!()
}

/// Helper function to print a imag question string. The `question` argument may not contain a
/// trailing questionmark.
///
/// The `nl` parameter can be used to configure whether a newline character should be printed
pub fn ask_question(question: &str, nl: bool) {
    if nl {
        println!("[imag]: {}?", Yellow.paint(question));
    } else {
        print!("[imag]: {}?", Yellow.paint(question));
    }
}

<|endoftext|>


<commit_before>//! String escaping.
//!
//! Although filenames in Linux are commonly represented as UTF-8
//! sequences, there is no system requirement that this be the case.  As a
//! consequence, this means that it is possible for filenames in Linux to
//! not be valid UTF-8, and therefore not representable as strings.
//!
//! To prevent encoding problems, as well as to allow certain characters,
//! such as space, to separate tokens in the sure file format, we escape
//! some bytes in strings by replacing them with "=xx" where "xx" is the
//! lower-cased hex version of the string.  The range of valid characters
//! is fairly straightforward, including all of the printable characters
//! from '!' to '~' except for the '=', which is always escaped.  This
//! means, for example, that a 2-byte encoded UTF-8 sequence will expand to
//! take 6 bytes.

use failure_derive::Fail;
use std::{io::prelude::*, result};

pub trait Escape {
    fn escaped(&self) -> String;
}

pub trait Unescape {
    fn unescape(&self) -> EscapeResult<Vec<u8>>;
}

pub type EscapeResult<T> = result::Result<T, EscapeError>;

#[derive(Fail, Debug)]
pub enum EscapeError {
    #[fail(display = "Invalid hex character: {:?}", _0)]
    InvalidHexCharacter(u8),
    #[fail(display = "Invalid hex length")]
    InvalidHexLength,
}

// The basic encoding converts a sequence of bytes into a string.
impl Escape for [u8] {
    fn escaped(&self) -> String {
        let mut result = vec![];
        for &ch in self.iter() {
            // TODO: Can be made more efficient.
            if b'!' <= ch && ch <= b'~' && ch != b'=' {
                result.push(ch);
            } else {
                write!(&mut result, "={:02x}", ch).unwrap();
            }
        }

        // TODO: String::from_utf8_unchecked(result)
        String::from_utf8(result).unwrap()
    }
}

impl Unescape for str {
    fn unescape(&self) -> EscapeResult<Vec<u8>> {
        // Will overestimate.
        let mut buf = Vec::with_capacity(self.len() / 2);
        let mut phase = 0;
        let mut tmp = 0;

        for byte in self.bytes() {
            if phase == 0 {
                if byte == b'=' {
                    phase = 1;
                } else {
                    buf.push(byte);
                }
            } else {
                tmp <<= 4;
                match byte {
                    b'A'...b'F' => tmp |= byte - b'A' + 10,
                    b'a'...b'f' => tmp |= byte - b'a' + 10,
                    b'0'...b'f' => tmp |= byte - b'0',
                    _ => return Err(EscapeError::InvalidHexCharacter(byte)),
                }
                phase += 1;
                if phase == 3 {
                    buf.push(tmp);
                    phase = 0;
                    tmp = 0;
                }
            }
        }

        if phase != 0 {
            return Err(EscapeError::InvalidHexLength);
        }

        Ok(buf)
    }
}

#[test]
fn test_unescape() {
    macro_rules! assert_error_kind {
        ( $expr:expr, $kind:pat ) => {
            match $expr {
                Err($kind) => (),
                Err(e) => panic!(
                    "Unexpected error kind: {:?} (want {})",
                    e,
                    stringify!($kind)
                ),
                Ok(_) => panic!("Unexpected success"),
            }
        };
    }

    assert_eq!("=00".unescape().unwrap(), vec![0]);
    assert_error_kind!("=00=0".unescape(), EscapeError::InvalidHexLength);
    assert_error_kind!("=00=".unescape(), EscapeError::InvalidHexLength);
    assert_error_kind!("=4g".unescape(), EscapeError::InvalidHexCharacter(b'g'));
}

#[test]
fn test_escape() {
    let buf: Vec<u8> = (0u32..256).map(|i| i as u8).collect();
    let text = (&buf[..]).escaped();
    assert_eq!(text.unescape().unwrap(), buf);
}
<commit_msg>Add '[' and ']' to escaped chars<commit_after>//! String escaping.
//!
//! Although filenames in Linux are commonly represented as UTF-8
//! sequences, there is no system requirement that this be the case.  As a
//! consequence, this means that it is possible for filenames in Linux to
//! not be valid UTF-8, and therefore not representable as strings.
//!
//! To prevent encoding problems, as well as to allow certain characters,
//! such as space, to separate tokens in the sure file format, we escape
//! some bytes in strings by replacing them with "=xx" where "xx" is the
//! lower-cased hex version of the string.  The range of valid characters
//! is fairly straightforward, including all of the printable characters
//! from '!' to '~' except for the '=', which is always escaped.  This
//! means, for example, that a 2-byte encoded UTF-8 sequence will expand to
//! take 6 bytes.

use failure_derive::Fail;
use std::{io::prelude::*, result};

pub trait Escape {
    fn escaped(&self) -> String;
}

pub trait Unescape {
    fn unescape(&self) -> EscapeResult<Vec<u8>>;
}

pub type EscapeResult<T> = result::Result<T, EscapeError>;

#[derive(Fail, Debug)]
pub enum EscapeError {
    #[fail(display = "Invalid hex character: {:?}", _0)]
    InvalidHexCharacter(u8),
    #[fail(display = "Invalid hex length")]
    InvalidHexLength,
}

// The basic encoding converts a sequence of bytes into a string.
impl Escape for [u8] {
    fn escaped(&self) -> String {
        let mut result = vec![];
        for &ch in self.iter() {
            // TODO: Can be made more efficient.
            if b'!' <= ch && ch <= b'~' && ch != b'=' && ch != b'[' && ch != b']' {
                result.push(ch);
            } else {
                write!(&mut result, "={:02x}", ch).unwrap();
            }
        }

        // TODO: String::from_utf8_unchecked(result)
        String::from_utf8(result).unwrap()
    }
}

impl Unescape for str {
    fn unescape(&self) -> EscapeResult<Vec<u8>> {
        // Will overestimate.
        let mut buf = Vec::with_capacity(self.len() / 2);
        let mut phase = 0;
        let mut tmp = 0;

        for byte in self.bytes() {
            if phase == 0 {
                if byte == b'=' {
                    phase = 1;
                } else {
                    buf.push(byte);
                }
            } else {
                tmp <<= 4;
                match byte {
                    b'A'...b'F' => tmp |= byte - b'A' + 10,
                    b'a'...b'f' => tmp |= byte - b'a' + 10,
                    b'0'...b'f' => tmp |= byte - b'0',
                    _ => return Err(EscapeError::InvalidHexCharacter(byte)),
                }
                phase += 1;
                if phase == 3 {
                    buf.push(tmp);
                    phase = 0;
                    tmp = 0;
                }
            }
        }

        if phase != 0 {
            return Err(EscapeError::InvalidHexLength);
        }

        Ok(buf)
    }
}

#[test]
fn test_unescape() {
    macro_rules! assert_error_kind {
        ( $expr:expr, $kind:pat ) => {
            match $expr {
                Err($kind) => (),
                Err(e) => panic!(
                    "Unexpected error kind: {:?} (want {})",
                    e,
                    stringify!($kind)
                ),
                Ok(_) => panic!("Unexpected success"),
            }
        };
    }

    assert_eq!("=00".unescape().unwrap(), vec![0]);
    assert_error_kind!("=00=0".unescape(), EscapeError::InvalidHexLength);
    assert_error_kind!("=00=".unescape(), EscapeError::InvalidHexLength);
    assert_error_kind!("=4g".unescape(), EscapeError::InvalidHexCharacter(b'g'));
}

#[test]
fn test_escape() {
    let buf: Vec<u8> = (0u32..256).map(|i| i as u8).collect();
    let text = (&buf[..]).escaped();
    assert_eq!(text.unescape().unwrap(), buf);
}
<|endoftext|>


<commit_before>#[macro_export]
macro_rules! mock_trait {
    ($mock_name:ident $(, $method:ident($($arg_type:ty),* ) -> $retval:ty )* ) => (
        #[derive(Debug, Clone)]
        struct $mock_name {
            $(
                $method: double::Mock<(($($arg_type),*)), $retval>
            ),*
        }

        impl Default for $mock_name {
            fn default() -> Self {
                $mock_name {
                    $(
                        $method: double::Mock::default()
                    ),*
                }
            }
        }
    );
}

#[macro_export]
macro_rules! mock_method {
    // immutable, no return value, no type parameter, no body
    ( $method:ident(&self, $($arg_name:ident: $arg_type:ty),*)) => (
        fn $method(&self, $($arg_name: $arg_type),*) {
            self.$method.call(($($arg_name),*))
        }
    );
    // immutable, no return value, no type parameter, body
    ( $method:ident(&self, $($arg_name:ident: $arg_type:ty),*), $sel:ident, $body:tt ) => (
        fn $method(&$sel, $($arg_name: $arg_type),*) $body
    );
    // immutable, no return value, type parameter, no body
    ( $method:ident<($($type_params: tt)*)>(&self, $($arg_name:ident: $arg_type:ty),*) ) => (
            fn $method<$($type_params)*>(&$sel, $($arg_name: $arg_type),*) {
                self.$method.call(($($arg_name),*))
            }
    );
    // immutable, no return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&self, $($arg_name:ident: $arg_type:ty),*),
        $sel:ident, $body:tt) => (
            fn $method<$($type_params)*>(&$sel, $($arg_name: $arg_type),*) $body
    );
    // immutable, return value, no type parameter, no body
    ( $method:ident(&self, $($arg_name:ident: $arg_type:ty),*) -> $retval:ty ) => (
        fn $method(&self, $($arg_name: $arg_type),*) -> $retval {
            self.$method.call(($($arg_name),*))
        }
    );
    // immutable, return value, no type parameter, body
    ( $method:ident(&self, $($arg_name:ident: $arg_type:ty),*) -> $retval:ty, $sel:ident, $body:tt ) => (
        fn $method(&$sel, $($arg_name: $arg_type),*) -> $retval $body
    );
    // immutable, return value, type parameter, no body
    ( $method:ident<($($type_params: tt)*)>(&self, $($arg_name:ident: $arg_type:ty),*)
        -> $retval:ty ) => (
            fn $method<$($type_params)*>(&$sel, $($arg_name: $arg_type),*) -> $retval {
                self.$method.call(($($arg_name),*))
            }
    );
    // immutable, return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&self, $($arg_name:ident: $arg_type:ty),*)
        -> $retval:ty, $sel:ident, $body:tt ) => (
            fn $method<$($type_params)*>(&$sel, $($arg_name: $arg_type),*) -> $retval $body
    );
    // mutable, no return value, no type parameter, no body
    ( $method:ident(&mut self, $($arg_name:ident: $arg_type:ty),*)) => (
        fn $method(&mut self, $($arg_name: $arg_type),*) {
            self.$method.call(($($arg_name),*))
        }
    );
    // mutable, no return value, no type parameter, body
    ( $method:ident(&mut self, $($arg_name:ident: $arg_type:ty),*), $sel:ident, $body:tt ) => (
        fn $method(&mut $sel, $($arg_name: $arg_type),*) $body
    );
    // mutable, no return value, type parameter, no body
    ( $method:ident<($($type_params: tt)*)>(&mut self, $($arg_name:ident: $arg_type:ty),*) ) => (
            fn $method<$($type_params)*>(&mut $sel, $($arg_name: $arg_type),*) {
                self.$method.call(($($arg_name),*))
            }
    );
    // mutable, no return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&mut self, $($arg_name:ident: $arg_type:ty),*),
        $sel:ident, $body:tt) => (
            fn $method<$($type_params)*>(&mut $sel, $($arg_name: $arg_type),*) $body
    );
    // mutable, return value, no type parameter, no body
    ( $method:ident(&mut self, $($arg_name:ident: $arg_type:ty),*) -> $retval:ty ) => (
        fn $method(&mut self, $($arg_name: $arg_type),*) -> $retval {
            self.$method.call(($($arg_name),*))
        }
    );
    // mutable, return value, no type parameter, body
    ( $method:ident(&mut self, $($arg_name:ident: $arg_type:ty),*) -> $retval:ty, $sel:ident, $body:tt ) => (
        fn $method(&mut $sel, $($arg_name: $arg_type),*) -> $retval $body
    );
    // mutable, return value, type parameter, no body
    ( $method:ident<($($type_params: tt)*)>(&mut self, $($arg_name:ident: $arg_type:ty),*)
        -> $retval:ty ) => (
            fn $method<$($type_params)*>(&mut $sel, $($arg_name: $arg_type),*) -> $retval {
                self.$method.call(($($arg_name),*))
            }
    );
    // mutable, return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&mut self, $($arg_name:ident: $arg_type:ty),*)
        -> $retval:ty, $sel:ident, $body:tt ) => (
            fn $method<$($type_params)*>(&mut $sel, $($arg_name: $arg_type),*) -> $retval $body
    );
}
<commit_msg>Add basic macro usage examples to rustdoc<commit_after>/// Macro that generates a `struct` implementation of a specified trait.
///
/// This macro generates a `struct` that implements the traits `Clone`, `Debug`
/// and `Default`. Create instances of the mock object by calling the `struct`'s
/// `default()` method.
///
/// The `struct` has a field for each method of the `trait`, which manages their
/// respective method's behaviour and call expectations. For example, if one
/// defines a mock like so:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// mock_trait!(
///     MockTaskManager,
///     max_threads(()) -> u32,
///     set_max_threads(u32) -> ()
/// );
///
/// # fn main() { }
/// ```
///
/// Then the following code is generated:
///
/// ```
/// #[derive(Debug, Clone)]
/// struct MockTaskManager {
///     max_threads: double::Mock<(), u32>,
///     set_max_threads: double::Mock<(u32), ()>,
/// }
///
/// impl Default for MockTaskManager {
///     fn default() -> Self {
///         MockTaskManager {
///             max_threads: double::Mock::default(),
///             set_max_threads: double::Mock::default(),
///         }
///     }
/// }
/// ```
///
/// Note that just defining this macro is not enough. This macro is used to
/// generate the necessary boilerplate, but the generated struct *does not*
/// implement the desired `trait`. To do that, use `double`'s `mock_method`
/// macro.
///
/// # Examples
///
/// ```
/// # #[macro_use] extern crate double;
///
/// trait TaskManager {
///    fn max_threads(&self) -> u32;
///    fn set_max_threads(&mut self, max_threads: u32);
/// }
///
/// mock_trait!(
///     MockTaskManager,
///     max_threads(()) -> u32,
///     set_max_threads(u32) -> ()
/// );
///
/// # fn main() {
/// let mock = MockTaskManager::default();
/// mock.max_threads.return_value(42u32);
/// assert_eq!(42, mock.max_threads.call(()));
/// mock.set_max_threads.call(9001u32);
/// assert!(mock.set_max_threads.called_with(9001u32));
/// # }
/// ```
#[macro_export]
macro_rules! mock_trait {
    ($mock_name:ident $(, $method:ident($($arg_type:ty),* ) -> $retval:ty )* ) => (
        #[derive(Debug, Clone)]
        struct $mock_name {
            $(
                $method: double::Mock<(($($arg_type),*)), $retval>
            ),*
        }

        impl Default for $mock_name {
            fn default() -> Self {
                $mock_name {
                    $(
                        $method: double::Mock::default()
                    ),*
                }
            }
        }
    );
}

/// Macro that generates a mock implementation of a `trait` method.
///
/// This should be used to implement a `trait` on a mock type generated by
/// `double`'s `mock_trait` macro. If one has generated a mock `struct` using
/// `mock_trait`, then the actual *implementation* of the desired trait can be
/// auto-generated using `mock_method`, like so:
///
/// ```
/// # #[macro_use] extern crate double;
///
/// trait TaskManager {
///    fn max_threads(&self) -> u32;
///    fn set_max_threads(&mut self, max_threads: u32);
/// }
///
/// mock_trait!(
///     MockTaskManager,
///     max_threads(()) -> u32,
///     set_max_threads(u32) -> ()
/// );
///
/// // Actually implement the trait that should be mocked
/// impl TaskManager for MockTaskManager {
///     mock_method!(max_threads(&self) -> u32);
///     mock_method!(set_max_threads(&mut self, max_threads: u32));
/// }
///
/// # fn main() {
/// let mut mock = MockTaskManager::default();
/// mock.max_threads.return_value(42u32);
/// assert_eq!(42, mock.max_threads());
/// assert!(mock.max_threads.called_with(()));
/// mock.set_max_threads(9001u32);
/// assert!(mock.set_max_threads.called_with(9001u32));
/// # }
/// ```
///
/// There are many different variants of `mock_method`. In total there are 16
/// variants, each of which provides a combination of the following:
///
/// 1. const method (`&self`) or mutable method (`&mut self`)
/// 2. return value (`fn foo(&self) -> bool`) / no return value (`fn foo(&self)`)
/// 3. type parameters (`fn foo<T: Eq>(&self, a: &T)`) / no type parameters (`fn foo(&self, a: &str)`)
/// 4. custom method body or automatically generated method body
///
/// (1) allows both constant and mutable methods can be mocked, like in the
/// `MockTaskManager` example above.
///
/// (2) is for convenience. It means one doesn't have to specify `-> ()`
/// explicitly for mocked methods that don't return values. This can also be
/// shown in the `MockTaskManager` example. Notice how the return type is not
/// specified when generating the `set_max_threads()` method.
///
/// (3) allows one to generate mock methods which take some generic type
/// parameters. For example, suppose one had a `Comparator` trait that was
/// responsible for comparing any two values in the system. It might look
/// something like this:
///
/// ```
/// trait Comparator {
///    fn is_equal<T: Eq>(&self, a: &T, b: &T) -> bool;
/// }
/// ```
///
/// TODO
///
/// ```
/// # #[macro_use] extern crate double;
/// trait Comparator {
///    fn is_equal<T: Eq>(&self, a: &T, b: &T) -> bool;
/// }
///
/// mock_trait!(
///     MockComparator,
///     is_equal((String, String)) -> bool
/// );
///
/// impl Comparator for MockComparator {
///     mock_method!(is_equal<(T: Eq)>(&self, a: &T, b: &T) -> bool);
/// }
/// # fn main() {
/// // TODO
/// # }
/// ```
///
/// (4) TODO.
///
/// TODO: str / string
///
/// For detailed instructions and examples on how to use the different variants
/// of this macro, take a look at the
/// [**GitHub repo**](https://github.com/DonaldWhyte/double)).
#[macro_export]
macro_rules! mock_method {
    // immutable, no return value, no type parameter, no body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*)) => (
        fn $method(&self $(,$arg_name: $arg_type)*) {
            self.$method.call(($($arg_name),*))
        }
    );
    // immutable, no return value, no type parameter, body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*), $sel:ident, $body:tt ) => (
        fn $method(&$sel $(,$arg_name: $arg_type)*) $body
    );
    // immutable, no return value, type parameter, no body
    ( $method:ident<($($type_params: tt)*)>(&self $(,$arg_name:ident: $arg_type:ty)*) ) => (
            fn $method<$($type_params)*>(&$sel $(,$arg_name: $arg_type)*) {
                self.$method.call(($($arg_name),*))
            }
    );
    // immutable, no return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&self $(,$arg_name:ident: $arg_type:ty)*),
        $sel:ident, $body:tt) => (
            fn $method<$($type_params)*>(&$sel $(,$arg_name: $arg_type)*) $body
    );
    // immutable, return value, no type parameter, no body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty ) => (
        fn $method(&self $(,$arg_name: $arg_type)*) -> $retval {
            self.$method.call(($($arg_name),*))
        }
    );
    // immutable, return value, no type parameter, body
    ( $method:ident(&self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty, $sel:ident, $body:tt ) => (
        fn $method(&$sel $(,$arg_name: $arg_type)*) -> $retval $body
    );
    // immutable, return value, type parameter, no body
    ( $method:ident<($($type_params: tt)*)>(&self $(,$arg_name:ident: $arg_type:ty)*)
        -> $retval:ty ) => (
            fn $method<$($type_params)*>(&self $(,$arg_name: $arg_type)*) -> $retval {
                self.$method.call(($($arg_name),*))
            }
    );
    // immutable, return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&self $(,$arg_name:ident: $arg_type:ty)*)
        -> $retval:ty, $sel:ident, $body:tt ) => (
            fn $method<$($type_params)*>(&$sel $(,$arg_name: $arg_type)*) -> $retval $body
    );
    // mutable, no return value, no type parameter, no body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*)) => (
        fn $method(&mut self $(,$arg_name: $arg_type),*) {
            self.$method.call(($($arg_name),*))
        }
    );
    // mutable, no return value, no type parameter, body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*), $sel:ident, $body:tt ) => (
        fn $method(&mut $sel $(,$arg_name: $arg_type)*) $body
    );
    // mutable, no return value, type parameter, no body
    ( $method:ident<($($type_params: tt)*)>(&mut self $(,$arg_name:ident: $arg_type:ty)*) ) => (
            fn $method<$($type_params)*>(&mut $sel $(,$arg_name: $arg_type)*) {
                self.$method.call(($($arg_name),*))
            }
    );
    // mutable, no return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&mut self $(,$arg_name:ident: $arg_type:ty)*),
        $sel:ident, $body:tt) => (
            fn $method<$($type_params)*>(&mut $sel $(,$arg_name: $arg_type)*) $body
    );
    // mutable, return value, no type parameter, no body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty ) => (
        fn $method(&mut self $(,$arg_name: $arg_type),*) -> $retval {
            self.$method.call(($($arg_name),*))
        }
    );
    // mutable, return value, no type parameter, body
    ( $method:ident(&mut self $(,$arg_name:ident: $arg_type:ty)*) -> $retval:ty, $sel:ident, $body:tt ) => (
        fn $method(&mut $sel $(,$arg_name: $arg_type)*) -> $retval $body
    );
    // mutable, return value, type parameter, no body
    ( $method:ident<($($type_params: tt)*)>(&mut self $(,$arg_name:ident: $arg_type:ty)*)
        -> $retval:ty ) => (
            fn $method<$($type_params)*>(&mut self $(,$arg_name: $arg_type)*) -> $retval {
                self.$method.call(($($arg_name),*))
            }
    );
    // mutable, return value, type parameter, body
    ( $method:ident<($($type_params: tt)*)>(&mut self $(,$arg_name:ident: $arg_type:ty)*)
        -> $retval:ty, $sel:ident, $body:tt ) => (
            fn $method<$($type_params)*>(&mut $sel $(,$arg_name: $arg_type)*) -> $retval $body
    );
}
<|endoftext|>


<commit_before>use super::from_bytes::FromBytes;
use super::uberblock::Uberblock;

#[repr(packed)]
pub struct VdevLabel {
    pub blank: [u8; 8 * 1024],
    pub boot_header: [u8; 8 * 1024],
    pub nv_pairs: [u8; 112 * 1024],
    pub uberblocks: [Uberblock; 128],
}

impl FromBytes for VdevLabel { }
<commit_msg>Added basic Vdev struct<commit_after>use super::from_bytes::FromBytes;
use super::uberblock::Uberblock;

#[repr(packed)]
pub struct VdevLabel {
    pub blank: [u8; 8 * 1024],
    pub boot_header: [u8; 8 * 1024],
    pub nv_pairs: [u8; 112 * 1024],
    pub uberblocks: [Uberblock; 128],
}

impl FromBytes for VdevLabel { }

////////////////////////////////////////////////////////////////////////////////////////////////////

pub struct Vdev {
    id: u64, // child number in vdev parent
    guid: u64, // unique ID for this vdev
    guid_sum: u64, // self guid + all child guids
    orig_guid: u64, // orig. guid prior to remove
    asize: u64, // allocatable device capacity
    min_asize: u64, // min acceptable asize
    max_asize: u64, // max acceptable asize
    ashift: u64, // block alignment shift

    // Top level only
    ms_array: u64,

    // Leaf only
}
<|endoftext|>


<commit_before>use std::io::{self, Write, BufWriter};

use terminal::{self, Terminal};

#[derive(Debug)]
pub enum Error {
    Exit,
    Write(io::Error),
    Reset(terminal::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Write(err)
    }
}

impl From<terminal::Error> for Error {
    fn from(err: terminal::Error) -> Error {
        Error::Reset(err)
    }
}

pub struct Interface {
    lines: Vec<String>,
    terminal: Terminal,
}

impl Interface {
    pub fn new(lines: Vec<String>) -> Interface {
        Interface {
            lines: lines,
            terminal: Terminal::from("/dev/tty").unwrap(),
        }
    }

    pub fn run(&mut self) -> Result<String, Error> {
        let mut term = BufWriter::new(&mut self.terminal);
        let mut search = String::new();

        for line in &self.lines {
            write!(term, "{}\n", line)?;
        }

        return Ok(search)
    }
}
<commit_msg>Add search term to interface<commit_after>use std::io::{self, Write, BufWriter};

use terminal::{self, Terminal};

#[derive(Debug)]
pub enum Error {
    Exit,
    Write(io::Error),
    Reset(terminal::Error)
}

impl From<io::Error> for Error {
    fn from(err: io::Error) -> Error {
        Error::Write(err)
    }
}

impl From<terminal::Error> for Error {
    fn from(err: terminal::Error) -> Error {
        Error::Reset(err)
    }
}

pub struct Interface {
    lines: Vec<String>,
    search: String,
    terminal: Terminal,
}

impl Interface {
    pub fn new(lines: Vec<String>) -> Interface {
        Interface {
            lines: lines,
            search: String::new(),
            terminal: Terminal::from("/dev/tty").unwrap(),
        }
    }

    pub fn run(&mut self) -> Result<&str, Error> {
        Ok(&self.search)
    }
}
<|endoftext|>


<commit_before>use std::sync::Mutex;

lazy_static! {
    static ref CLEANUP: Mutex<Option<Box<Fn() + Send>>> = Mutex::new(None);
}

#[cfg(unix)]
pub fn install_handler<F>(handler: F)
    where F: Fn() + 'static + Send + Sync
{

    use std::thread;
    use nix::sys::signal::*;

    // Mask all termination signals
    // These propagate to all threads started after this point
    let mut mask = SigSet::empty();
    mask.add(SIGTERM);
    mask.add(SIGINT);
    mask.thread_set_mask().expect("unable to set signal mask");

    set_handler(handler);

    // Spawn a thread to catch these signals
    thread::spawn(move || {
        let sig = mask.wait().expect("unable to sigwait");

        // Invoke closure
        invoke();

        // Restore default behavior for received signal and unmask it
        unsafe {
            let _ =
                sigaction(sig,
                          &SigAction::new(SigHandler::SigDfl, SaFlags::empty(), SigSet::empty()));
        }

        let mut new_mask = SigSet::empty();
        new_mask.add(sig);
        let _ = new_mask.thread_unblock();

        // Re-raise, killing the process
        let _ = raise(sig);
    });
}

#[cfg(windows)]
pub fn install_handler<F>(handler: F)
    where F: Fn() + 'static + Send + Sync
{

    use kernel32::SetConsoleCtrlHandler;
    use winapi::{BOOL, DWORD, FALSE, TRUE};

    pub unsafe extern "system" fn ctrl_handler(_: DWORD) -> BOOL {
        invoke();

        FALSE
    }

    set_handler(handler);

    unsafe {
        SetConsoleCtrlHandler(Some(ctrl_handler), TRUE);
    }
}

fn invoke() {
    if let Some(ref handler) = *CLEANUP.lock().unwrap() {
        handler()
    }
}

fn set_handler<F>(handler: F)
    where F: Fn() + 'static + Send + Sync
{

    *CLEANUP.lock().unwrap() = Some(Box::new(handler));
}
<commit_msg>Style fixes<commit_after>use std::sync::Mutex;

lazy_static! {
    static ref CLEANUP: Mutex<Option<Box<Fn() + Send>>> = Mutex::new(None);
}

#[cfg(unix)]
pub fn install_handler<F>(handler: F)
    where F: Fn() + 'static + Send + Sync
{
    use std::thread;
    use nix::sys::signal::*;

    // Mask all termination signals
    // These propagate to all threads started after this point
    let mut mask = SigSet::empty();
    mask.add(SIGTERM);
    mask.add(SIGINT);
    mask.thread_set_mask().expect("unable to set signal mask");

    set_handler(handler);

    // Spawn a thread to catch these signals
    thread::spawn(move || {
        let sig = mask.wait().expect("unable to sigwait");

        // Invoke closure
        invoke();

        // Restore default behavior for received signal and unmask it
        let default_action = SigAction::new(SigHandler::SigDfl, SaFlags::empty(), SigSet::empty());

        unsafe {
            let _ = sigaction(sig, &default_action);
        }

        let mut new_mask = SigSet::empty();
        new_mask.add(sig);
        let _ = new_mask.thread_unblock();

        // Re-raise, killing the process
        let _ = raise(sig);
    });
}

#[cfg(windows)]
pub fn install_handler<F>(handler: F)
    where F: Fn() + 'static + Send + Sync
{
    use kernel32::SetConsoleCtrlHandler;
    use winapi::{BOOL, DWORD, FALSE, TRUE};

    pub unsafe extern "system" fn ctrl_handler(_: DWORD) -> BOOL {
        invoke();

        FALSE
    }

    set_handler(handler);

    unsafe {
        SetConsoleCtrlHandler(Some(ctrl_handler), TRUE);
    }
}

fn invoke() {
    if let Some(ref handler) = *CLEANUP.lock().unwrap() {
        handler()
    }
}

fn set_handler<F>(handler: F)
    where F: Fn() + 'static + Send + Sync
{
    *CLEANUP.lock().unwrap() = Some(Box::new(handler));
}
<|endoftext|>


<commit_before>use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

// A network
#[derive(Debug)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

pub struct Ipv4Network {
    addr: Ipv4Addr,
    prefix: u8,
}

pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv4Network {
    fn new(addr: Ipv4Addr, prefix: u8) -> Ipv4Network {
        Ipv4Network { addr: addr, prefix: prefix }
    }

    fn ip(&self) -> &Ipv4Addr {
        &(self.addr)
    }

    fn prefix(&self) -> u8 {
        self.prefix
    }

    fn mask(&self) -> u32 {
        let prefix = self.prefix;
        !(0xffffffff >> prefix)
    }

    fn mask_to_string(&self) -> String {
        let mask = self.mask();
        Ipv4Network::int_to_ip(mask).to_string()
    }

    fn network_int(&self) -> u32 {
        Ipv4Network::ip_to_int(*(self.ip())) & self.mask()
    }

    fn ip_to_int(addr: Ipv4Addr) -> u32 {
        let ip = addr.octets();
        ((ip[0] as u32) << 24) + ((ip[1] as u32) << 16) + ((ip[2] as u32) << 8) + (ip[3] as u32)
    }

    fn int_to_ip(ip: u32) -> Ipv4Addr {
        Ipv4Addr::new(((ip >> 24) & 0xff) as u8, ((ip >> 16) & 0xff) as u8,
                     ((ip >> 8) & 0xff) as u8, (ip & 0xff) as u8)
    }
}

impl Ipv6Network {
    fn new(addr: Ipv6Addr, prefix: u8) -> Ipv6Network {
        Ipv6Network { addr: addr, prefix: prefix }
    }

    fn ip(&self) -> &Ipv6Addr {
        &(self.addr)
    }

    fn prefix(&self) -> u8 {
        self.prefix
    }
}

impl IpNetwork {
    pub fn new(ip: IpAddr, prefix: u8) -> IpNetwork {
        match ip {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::new(a, prefix)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::new(a, prefix)),
        }
    }

    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(*a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(*a.ip()),
        }
    }

    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

impl fmt::Debug for Ipv4Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

impl fmt::Debug for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

#[cfg(test)]
mod test {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use super::*;

    #[test]
    fn create_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(77, 88, 21, 11), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn mask_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask(), 4294967288);
    }

    #[test]
    fn mask_string_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask_to_string(), "255.255.255.248");
    }

    #[test]
    fn network_as_int() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        assert_eq!(cidr.network_int(), 1249764096);
    }
}
<commit_msg>Add a method to get network as an IPv4 address<commit_after>use std::fmt;
use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};

// A network
#[derive(Debug)]
pub enum IpNetwork {
    V4(Ipv4Network),
    V6(Ipv6Network),
}

pub struct Ipv4Network {
    addr: Ipv4Addr,
    prefix: u8,
}

pub struct Ipv6Network {
    addr: Ipv6Addr,
    prefix: u8,
}

impl Ipv4Network {
    fn new(addr: Ipv4Addr, prefix: u8) -> Ipv4Network {
        Ipv4Network { addr: addr, prefix: prefix }
    }

    fn ip(&self) -> &Ipv4Addr {
        &(self.addr)
    }

    fn prefix(&self) -> u8 {
        self.prefix
    }

    fn mask(&self) -> u32 {
        let prefix = self.prefix;
        !(0xffffffff >> prefix)
    }

    fn mask_to_string(&self) -> String {
        let mask = self.mask();
        Ipv4Network::int_to_ip(mask).to_string()
    }

    fn network_int(&self) -> u32 {
        Ipv4Network::ip_to_int(*(self.ip())) & self.mask()
    }

    fn network(&self) -> Ipv4Addr {
        Ipv4Network::int_to_ip(self.network_int())
    }

    fn ip_to_int(addr: Ipv4Addr) -> u32 {
        let ip = addr.octets();
        ((ip[0] as u32) << 24) + ((ip[1] as u32) << 16) + ((ip[2] as u32) << 8) + (ip[3] as u32)
    }

    fn int_to_ip(ip: u32) -> Ipv4Addr {
        Ipv4Addr::new(((ip >> 24) & 0xff) as u8, ((ip >> 16) & 0xff) as u8,
                     ((ip >> 8) & 0xff) as u8, (ip & 0xff) as u8)
    }
}

impl Ipv6Network {
    fn new(addr: Ipv6Addr, prefix: u8) -> Ipv6Network {
        Ipv6Network { addr: addr, prefix: prefix }
    }

    fn ip(&self) -> &Ipv6Addr {
        &(self.addr)
    }

    fn prefix(&self) -> u8 {
        self.prefix
    }
}

impl IpNetwork {
    pub fn new(ip: IpAddr, prefix: u8) -> IpNetwork {
        match ip {
            IpAddr::V4(a) => IpNetwork::V4(Ipv4Network::new(a, prefix)),
            IpAddr::V6(a) => IpNetwork::V6(Ipv6Network::new(a, prefix)),
        }
    }

    pub fn ip(&self) -> IpAddr {
        match *self {
            IpNetwork::V4(ref a) => IpAddr::V4(*a.ip()),
            IpNetwork::V6(ref a) => IpAddr::V6(*a.ip()),
        }
    }

    pub fn prefix(&self) -> u8 {
        match *self {
            IpNetwork::V4(ref a) => a.prefix(),
            IpNetwork::V6(ref a) => a.prefix(),
        }
    }
}

impl fmt::Debug for Ipv4Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

impl fmt::Debug for Ipv6Network {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "{}/{}", self.ip(), self.prefix())
    }
}

#[cfg(test)]
mod test {
    use std::net::{Ipv4Addr, Ipv6Addr};
    use super::*;

    #[test]
    fn create_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(77, 88, 21, 11), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn create_v6() {
        let cidr = Ipv6Network::new(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 1), 24);
        assert_eq!(cidr.prefix(), 24);
    }

    #[test]
    fn mask_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask(), 4294967288);
    }

    #[test]
    fn mask_string_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 29);
        assert_eq!(cidr.mask_to_string(), "255.255.255.248");
    }

    #[test]
    fn network_int_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        assert_eq!(cidr.network_int(), 1249764096);
    }

    #[test]
    fn network_v4() {
        let cidr = Ipv4Network::new(Ipv4Addr::new(74, 125, 227, 0), 25);
        assert_eq!(cidr.network(), Ipv4Addr::new(74, 125, 227, 0));
    }
}
<|endoftext|>


<commit_before>use std::io::Write;
use std::io::stderr;

use log::{Log, LogLevel, LogRecord, LogMetadata};

pub struct ImagLogger {
    lvl: LogLevel,
}

impl ImagLogger {

    pub fn new(lvl: LogLevel) -> ImagLogger {
        ImagLogger {
            lvl: lvl,
        }
    }

}

impl Log for ImagLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.lvl
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            // TODO: This is just simple logging. Maybe we can enhance this lateron
            writeln!(stderr(), "[imag][{: <5}]: {}", record.level(), record.args()).ok();
        }
    }
}

<commit_msg>logger: Print file and line on debug printing<commit_after>use std::io::Write;
use std::io::stderr;

use log::{Log, LogLevel, LogRecord, LogMetadata};

pub struct ImagLogger {
    lvl: LogLevel,
}

impl ImagLogger {

    pub fn new(lvl: LogLevel) -> ImagLogger {
        ImagLogger {
            lvl: lvl,
        }
    }

}

impl Log for ImagLogger {

    fn enabled(&self, metadata: &LogMetadata) -> bool {
        metadata.level() <= self.lvl
    }

    fn log(&self, record: &LogRecord) {
        if self.enabled(record.metadata()) {
            // TODO: This is just simple logging. Maybe we can enhance this lateron
            if record.metadata().level() == LogLevel::Debug {
                let loc = record.location();
                writeln!(stderr(), "[imag][{: <5}][{}][{: >5}]: {}",
                         record.level(), loc.file(), loc.line(), record.args()).ok();
            } else {
                writeln!(stderr(), "[imag][{: <5}]: {}", record.level(), record.args()).ok();
            }
        }
    }
}

<|endoftext|>


<commit_before>use crate::custom::credential::NewAwsCredsForStsCreds;
use crate::{AssumeRoleWithWebIdentityRequest, Sts, StsClient};
use rusoto_core::credential::{
    AwsCredentials, CredentialsError, ProvideAwsCredentials, Secret, Variable,
};
use rusoto_core::request::HttpClient;
use rusoto_core::{Client, Region};

use async_trait::async_trait;

const AWS_WEB_IDENTITY_TOKEN_FILE: &str = "AWS_WEB_IDENTITY_TOKEN_FILE";

const AWS_ROLE_ARN: &str = "AWS_ROLE_ARN";

const AWS_ROLE_SESSION_NAME: &str = "AWS_ROLE_SESSION_NAME";

/// WebIdentityProvider using OpenID Connect bearer token to retrieve AWS IAM credentials.
///
/// See https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html for
/// more details.
#[derive(Debug, Clone)]
pub struct WebIdentityProvider {
    /// The OAuth 2.0 access token or OpenID Connect ID token that is provided by the identity provider.
    /// Your application must get this token by authenticating the user who is using your application
    /// with a web identity provider before the application makes an AssumeRoleWithWebIdentity call.
    pub web_identity_token: Variable<Secret, CredentialsError>,
    /// The Amazon Resource Name (ARN) of the role that the caller is assuming.
    pub role_arn: Variable<String, CredentialsError>,
    /// An identifier for the assumed role session. Typically, you pass the name or identifier that is
    /// associated with the user who is using your application. That way, the temporary security credentials
    /// that your application will use are associated with that user. This session name is included as part
    /// of the ARN and assumed role ID in the AssumedRoleUser response element.
    pub role_session_name: Variable<Option<String>, CredentialsError>,
}

impl WebIdentityProvider {
    /// Create new WebIdentityProvider by explicitly passing its configuration.
    pub fn new<A, B, C>(web_identity_token: A, role_arn: B, role_session_name: C) -> Self
    where
        A: Into<Variable<Secret, CredentialsError>>,
        B: Into<Variable<String, CredentialsError>>,
        C: Into<Variable<Option<String>, CredentialsError>>,
    {
        Self {
            web_identity_token: web_identity_token.into(),
            role_arn: role_arn.into(),
            role_session_name: role_session_name.into(),
        }
    }

    /// Creat a WebIdentityProvider from the following environment variables:
    ///
    /// - `AWS_WEB_IDENTITY_TOKEN_FILE` path to the web identity token file.
    /// - `AWS_ROLE_ARN` ARN of the role to assume.
    /// - `AWS_ROLE_SESSION_NAME` (optional) name applied to the assume-role session.
    ///
    /// See https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html
    /// for more information about how IAM Roles for Kubernetes Service Accounts works.
    pub fn from_k8s_env() -> Self {
        Self::_from_k8s_env(
            Variable::from_env_var(AWS_WEB_IDENTITY_TOKEN_FILE),
            Variable::from_env_var(AWS_ROLE_ARN),
            Variable::from_env_var_optional(AWS_ROLE_SESSION_NAME),
        )
    }

    /// Used by unit testing
    pub(crate) fn _from_k8s_env(
        token_file: Variable<String, CredentialsError>,
        role: Variable<String, CredentialsError>,
        session_name: Variable<Option<String>, CredentialsError>,
    ) -> Self {
        Self::new(
            Variable::dynamic(move || Variable::from_text_file(token_file.resolve()?).resolve()),
            role,
            session_name,
        )
    }

    #[cfg(test)]
    pub(crate) fn load_token(&self) -> Result<Secret, CredentialsError> {
        self.web_identity_token.resolve()
    }

    fn create_session_name() -> String {
        // TODO can we do better here?
        // - Pod service account, Pod name and Pod namespace
        // - EC2 Instance ID if available
        // - IP address if available
        // - ...
        // Having some information in the session name that identifies the client would enable
        // better correlation analysis in CloudTrail.
        "WebIdentitySession".to_string()
    }
}

#[async_trait]
impl ProvideAwsCredentials for WebIdentityProvider {
    async fn credentials(&self) -> Result<AwsCredentials, CredentialsError> {
        let http_client = match HttpClient::new() {
            Ok(c) => c,
            Err(e) => return Err(CredentialsError::new(e)),
        };
        let client = Client::new_not_signing(http_client);
        let sts = StsClient::new_with_client(client, Region::default());
        let mut req = AssumeRoleWithWebIdentityRequest::default();

        req.role_arn = self.role_arn.resolve()?;
        req.web_identity_token = self.web_identity_token.resolve()?.as_ref().to_string();
        req.role_session_name = match self.role_session_name.resolve()? {
            Some(session_name) => session_name,
            None => Self::create_session_name(),
        };

        let assume_role = sts.assume_role_with_web_identity(req).await;
        match assume_role {
            Err(e) => Err(CredentialsError::new(e)),
            Ok(role) => match role.credentials {
                None => Err(CredentialsError::new(format!(
                    "No credentials found in AssumeRoleWithWebIdentityResponse: {:?}",
                    role
                ))),
                Some(c) => AwsCredentials::new_for_credentials(c),
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Write;
    use tempfile::NamedTempFile;

    #[test]
    fn api_ergonomy() {
        WebIdentityProvider::new(Secret::from("".to_string()), "", Some("".to_string()));
    }

    #[test]
    fn from_k8s_env() -> Result<(), CredentialsError> {
        const TOKEN_VALUE: &str = "secret";
        const ROLE_ARN: &str = "role";
        const SESSION_NAME: &str = "session";
        let mut file = NamedTempFile::new()?;
        // We use writeln to add an extra newline at the end of the token, which should be
        // removed by Variable::from_text_file.
        writeln!(file, "{}", TOKEN_VALUE)?;
        let p = WebIdentityProvider::_from_k8s_env(
            Variable::with_value(file.path().to_string_lossy().to_string()),
            Variable::with_value(ROLE_ARN.to_string()),
            Variable::with_value(SESSION_NAME.to_string()),
        );
        let token = p.load_token()?;
        assert_eq!(token.as_ref(), TOKEN_VALUE);
        Ok(())
    }
}
<commit_msg>address comment<commit_after>use crate::custom::credential::NewAwsCredsForStsCreds;
use crate::{AssumeRoleWithWebIdentityRequest, Sts, StsClient};
use rusoto_core::credential::{
    AwsCredentials, CredentialsError, ProvideAwsCredentials, Secret, Variable,
};
use rusoto_core::request::HttpClient;
use rusoto_core::{Client, Region};

use async_trait::async_trait;

const AWS_WEB_IDENTITY_TOKEN_FILE: &str = "AWS_WEB_IDENTITY_TOKEN_FILE";

const AWS_ROLE_ARN: &str = "AWS_ROLE_ARN";

const AWS_ROLE_SESSION_NAME: &str = "AWS_ROLE_SESSION_NAME";

/// WebIdentityProvider using OpenID Connect bearer token to retrieve AWS IAM credentials.
///
/// See https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoleWithWebIdentity.html for
/// more details.
#[derive(Debug, Clone)]
pub struct WebIdentityProvider {
    /// The OAuth 2.0 access token or OpenID Connect ID token that is provided by the identity provider.
    /// Your application must get this token by authenticating the user who is using your application
    /// with a web identity provider before the application makes an AssumeRoleWithWebIdentity call.
    pub web_identity_token: Variable<Secret, CredentialsError>,
    /// The Amazon Resource Name (ARN) of the role that the caller is assuming.
    pub role_arn: Variable<String, CredentialsError>,
    /// An identifier for the assumed role session. Typically, you pass the name or identifier that is
    /// associated with the user who is using your application. That way, the temporary security credentials
    /// that your application will use are associated with that user. This session name is included as part
    /// of the ARN and assumed role ID in the AssumedRoleUser response element.
    pub role_session_name: Option<Variable<Option<String>, CredentialsError>>,
}

impl WebIdentityProvider {
    /// Create new WebIdentityProvider by explicitly passing its configuration.
    pub fn new<A, B, C>(web_identity_token: A, role_arn: B, role_session_name: Option<C>) -> Self
    where
        A: Into<Variable<Secret, CredentialsError>>,
        B: Into<Variable<String, CredentialsError>>,
        C: Into<Variable<Option<String>, CredentialsError>>,
    {
        Self {
            web_identity_token: web_identity_token.into(),
            role_arn: role_arn.into(),
            role_session_name: role_session_name.map(|v| v.into()),
        }
    }

    /// Creat a WebIdentityProvider from the following environment variables:
    ///
    /// - `AWS_WEB_IDENTITY_TOKEN_FILE` path to the web identity token file.
    /// - `AWS_ROLE_ARN` ARN of the role to assume.
    /// - `AWS_ROLE_SESSION_NAME` (optional) name applied to the assume-role session.
    ///
    /// See https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts-technical-overview.html
    /// for more information about how IAM Roles for Kubernetes Service Accounts works.
    pub fn from_k8s_env() -> Self {
        Self::_from_k8s_env(
            Variable::from_env_var(AWS_WEB_IDENTITY_TOKEN_FILE),
            Variable::from_env_var(AWS_ROLE_ARN),
            Variable::from_env_var_optional(AWS_ROLE_SESSION_NAME),
        )
    }

    /// Used by unit testing
    pub(crate) fn _from_k8s_env(
        token_file: Variable<String, CredentialsError>,
        role: Variable<String, CredentialsError>,
        session_name: Variable<Option<String>, CredentialsError>,
    ) -> Self {
        Self::new(
            Variable::dynamic(move || Variable::from_text_file(token_file.resolve()?).resolve()),
            role,
            Some(session_name),
        )
    }

    #[cfg(test)]
    pub(crate) fn load_token(&self) -> Result<Secret, CredentialsError> {
        self.web_identity_token.resolve()
    }

    fn create_session_name() -> String {
        // TODO can we do better here?
        // - Pod service account, Pod name and Pod namespace
        // - EC2 Instance ID if available
        // - IP address if available
        // - ...
        // Having some information in the session name that identifies the client would enable
        // better correlation analysis in CloudTrail.
        "WebIdentitySession".to_string()
    }
}

#[async_trait]
impl ProvideAwsCredentials for WebIdentityProvider {
    async fn credentials(&self) -> Result<AwsCredentials, CredentialsError> {
        let http_client = match HttpClient::new() {
            Ok(c) => c,
            Err(e) => return Err(CredentialsError::new(e)),
        };
        let client = Client::new_not_signing(http_client);
        let sts = StsClient::new_with_client(client, Region::default());
        let mut req = AssumeRoleWithWebIdentityRequest::default();

        req.role_arn = self.role_arn.resolve()?;
        req.web_identity_token = self.web_identity_token.resolve()?.as_ref().to_string();
        req.role_session_name = match self.role_session_name {
            Some(ref role_session_name) => match role_session_name.resolve()? {
                Some(session_name) => session_name,
                None => Self::create_session_name(),
            },
            None => Self::create_session_name(),
        };

        let assume_role = sts.assume_role_with_web_identity(req).await;
        match assume_role {
            Err(e) => Err(CredentialsError::new(e)),
            Ok(role) => match role.credentials {
                None => Err(CredentialsError::new(format!(
                    "No credentials found in AssumeRoleWithWebIdentityResponse: {:?}",
                    role
                ))),
                Some(c) => AwsCredentials::new_for_credentials(c),
            },
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::io::Write;
    use tempfile::NamedTempFile;

    #[test]
    fn api_ergonomy() {
        WebIdentityProvider::new(Secret::from("".to_string()), "", Some(Some("".to_string())));
    }

    #[test]
    fn from_k8s_env() -> Result<(), CredentialsError> {
        const TOKEN_VALUE: &str = "secret";
        const ROLE_ARN: &str = "role";
        const SESSION_NAME: &str = "session";
        let mut file = NamedTempFile::new()?;
        // We use writeln to add an extra newline at the end of the token, which should be
        // removed by Variable::from_text_file.
        writeln!(file, "{}", TOKEN_VALUE)?;
        let p = WebIdentityProvider::_from_k8s_env(
            Variable::with_value(file.path().to_string_lossy().to_string()),
            Variable::with_value(ROLE_ARN.to_string()),
            Variable::with_value(SESSION_NAME.to_string()),
        );
        let token = p.load_token()?;
        assert_eq!(token.as_ref(), TOKEN_VALUE);
        Ok(())
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate regex;

include!("../clap-test.rs");

use clap::{App, Arg, ErrorKind, ArgGroup};

static CONFLICT_ERR: &'static str = "error: The argument '--flag' cannot be used with '-F'

USAGE:
    clap-test <positional> <positional2> -F --long-option-2 <option2>

For more information try --help";

static CONFLICT_ERR_REV: &'static str = "error: The argument '--flag' cannot be used with '-F'

USAGE:
    clap-test <positional> <positional2> -F --long-option-2 <option2>

For more information try --help";

#[test]
fn flag_conflict() {
    let result = App::new("flag_conflict")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("other"))
        .arg(Arg::from_usage("-o, --other 'some flag'"))
        .get_matches_from_safe(vec!["myprog", "-f", "-o"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::ArgumentConflict);
}

#[test]
fn flag_conflict_2() {
    let result = App::new("flag_conflict")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("other"))
        .arg(Arg::from_usage("-o, --other 'some flag'"))
        .get_matches_from_safe(vec!["myprog", "-o", "-f"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::ArgumentConflict);
}

#[test]
fn group_conflict() {
    let result = App::new("group_conflict")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("gr"))
        .group(ArgGroup::with_name("gr")
            .required(true)
            .arg("some")
            .arg("other"))
        .arg(Arg::from_usage("--some 'some arg'"))
        .arg(Arg::from_usage("--other 'other arg'"))
        .get_matches_from_safe(vec!["myprog", "--other", "-f"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::ArgumentConflict);
}

#[test]
fn group_conflict_2() {
    let result = App::new("group_conflict")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("gr"))
        .group(ArgGroup::with_name("gr")
            .required(true)
            .arg("some")
            .arg("other"))
        .arg(Arg::from_usage("--some 'some arg'"))
        .arg(Arg::from_usage("--other 'other arg'"))
        .get_matches_from_safe(vec!["myprog", "-f", "--some"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::ArgumentConflict);
}

#[test]
fn conflict_output() {
    test::check_err_output(test::complex_app(), "clap-test val1 --flag --long-option-2 val2 -F", CONFLICT_ERR, true);
}

#[test]
fn conflict_output_rev() {
    test::check_err_output(test::complex_app(), "clap-test val1 -F --long-option-2 val2 --flag", CONFLICT_ERR_REV, true);
}
<commit_msg>tests: updates conflict tests to new more precise output<commit_after>extern crate clap;
extern crate regex;

include!("../clap-test.rs");

use clap::{App, Arg, ErrorKind, ArgGroup};

static CONFLICT_ERR: &'static str = "error: The argument '-F' cannot be used with '--flag'

USAGE:
    clap-test <positional> <positional2> --flag --long-option-2 <option2>

For more information try --help";

static CONFLICT_ERR_REV: &'static str = "error: The argument '--flag' cannot be used with '-F'

USAGE:
    clap-test <positional> <positional2> -F --long-option-2 <option2>

For more information try --help";

#[test]
fn flag_conflict() {
    let result = App::new("flag_conflict")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("other"))
        .arg(Arg::from_usage("-o, --other 'some flag'"))
        .get_matches_from_safe(vec!["myprog", "-f", "-o"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::ArgumentConflict);
}

#[test]
fn flag_conflict_2() {
    let result = App::new("flag_conflict")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("other"))
        .arg(Arg::from_usage("-o, --other 'some flag'"))
        .get_matches_from_safe(vec!["myprog", "-o", "-f"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::ArgumentConflict);
}

#[test]
fn group_conflict() {
    let result = App::new("group_conflict")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("gr"))
        .group(ArgGroup::with_name("gr")
            .required(true)
            .arg("some")
            .arg("other"))
        .arg(Arg::from_usage("--some 'some arg'"))
        .arg(Arg::from_usage("--other 'other arg'"))
        .get_matches_from_safe(vec!["myprog", "--other", "-f"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::ArgumentConflict);
}

#[test]
fn group_conflict_2() {
    let result = App::new("group_conflict")
        .arg(Arg::from_usage("-f, --flag 'some flag'")
            .conflicts_with("gr"))
        .group(ArgGroup::with_name("gr")
            .required(true)
            .arg("some")
            .arg("other"))
        .arg(Arg::from_usage("--some 'some arg'"))
        .arg(Arg::from_usage("--other 'other arg'"))
        .get_matches_from_safe(vec!["myprog", "-f", "--some"]);
    assert!(result.is_err());
    let err = result.err().unwrap();
    assert_eq!(err.kind, ErrorKind::ArgumentConflict);
}

#[test]
fn conflict_output() {
    test::check_err_output(test::complex_app(), "clap-test val1 --flag --long-option-2 val2 -F", CONFLICT_ERR, true);
}

#[test]
fn conflict_output_rev() {
    test::check_err_output(test::complex_app(), "clap-test val1 -F --long-option-2 val2 --flag", CONFLICT_ERR_REV, true);
}
<|endoftext|>


<commit_before>use pest::prelude::*;

use std::vec::Vec;
use std::string::String;

impl_rdp! {
    grammar! {
        program = { instruction+ }
        instruction = { opcode ~ operand ~ operand ~ operand ~ ["\n"] }
        opcode = _{ number }
        operand = _{ number }

        number = @{ (['0'..'9'] | ['a'..'f'] | ['A'..'F'])+ }

        whitespace = _{ [" "] }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use pest::*;

    #[test]
    fn it_parses_programs_as_machine_code() {
        let mut parser = Rdp::new(StringInput::new("0 a b c\n1 2 3 4\n"));

        assert!(parser.program());
        assert!(parser.end());

        let tokens = vec![
            Token::new(Rule::program, 0, 16),
            Token::new(Rule::instruction, 0, 8),
            Token::new(Rule::number, 0, 1),
            Token::new(Rule::number, 2, 3),
            Token::new(Rule::number, 4, 5),
            Token::new(Rule::number, 6, 7),
            Token::new(Rule::instruction, 8, 16),
            Token::new(Rule::number, 8, 9),
            Token::new(Rule::number, 10, 11),
            Token::new(Rule::number, 12, 13),
            Token::new(Rule::number, 14, 15),
        ];

        assert_eq!(parser.queue(), &tokens);
    }
}
<commit_msg>Instructions don't have to end with a new line.<commit_after>use pest::prelude::*;

use std::vec::Vec;
use std::string::String;

impl_rdp! {
    grammar! {
        program = { instruction ~ (["\n"] ~ instruction)* }
        instruction = { opcode ~ operand ~ operand ~ operand }
        opcode = _{ number }
        operand = _{ number }

        number = @{ (['0'..'9'] | ['a'..'f'] | ['A'..'F'])+ }

        whitespace = _{ [" "] }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use pest::*;

    #[test]
    fn it_parses_programs_as_machine_code() {
        let mut parser = Rdp::new(StringInput::new("0 a b c\n1 2 3 4"));

        assert!(parser.program());
        assert!(parser.end());

        let tokens = vec![
            Token::new(Rule::program, 0, 15),
            Token::new(Rule::instruction, 0, 7),
            Token::new(Rule::number, 0, 1),
            Token::new(Rule::number, 2, 3),
            Token::new(Rule::number, 4, 5),
            Token::new(Rule::number, 6, 7),
            Token::new(Rule::instruction, 8, 15),
            Token::new(Rule::number, 8, 9),
            Token::new(Rule::number, 10, 11),
            Token::new(Rule::number, 12, 13),
            Token::new(Rule::number, 14, 15),
        ];

        assert_eq!(parser.queue(), &tokens);
    }
}
<|endoftext|>


<commit_before>use std::{
    any::{Any, TypeId},
    collections::{BTreeMap, HashMap},
    marker::PhantomData,
    sync::{mpsc, Arc, Mutex},
};

use crate::shell::WindowRequest;

use dces::entity::Entity;

/// Internal wrapper that stores a message inside a box.
#[derive(Debug)]
pub struct MessageBox {
    message: Box<dyn Any + Send>,
    message_type: TypeId,
    target: Entity,
}

impl MessageBox {
    /// Downcasts the box to a concrete message.
    pub fn downcast<M: Any>(self) -> Result<M, String> {
        if self.message_type == TypeId::of::<M>() {
            return Ok(*self.message.downcast::<M>().unwrap());
        }

        Err("Wrong message type".to_string())
    }

    /// Downcasts the box as reference of a concrete message.
    pub fn downcast_ref<M: Any>(&self) -> Result<&M, String> {
        if self.message_type == TypeId::of::<M>() {
            return Ok(&*self.message.downcast_ref::<M>().unwrap());
        }

        Err("Wrong message type".to_string())
    }

    /// Check if the given type is the type of the message.
    pub fn is_type<M: Any>(&self) -> bool {
        self.message_type == TypeId::of::<M>()
    }

    /// Creates a new `MessageBox`.
    pub fn new<M>(message: M, target: Entity) -> Self
    where
        M: Any + Send,
    {
        MessageBox {
            message: Box::new(message),
            target,
            message_type: TypeId::of::<M>(),
        }
    }

    /// Returns the type of the event.
    pub fn message_type(&self) -> TypeId {
        self.message_type
    }

    /// Returns the target of the event.
    pub fn target(&self) -> Entity {
        self.target
    }
}

/// The `MessageAdapter` provides a thread save entry point to sent
/// and read messages inside widget entities. They are processed inside the
/// method `message` defined in each widgets `State` code.
///
/// # Example
///
/// ```rust
/// // State
/// fn say_hello(entity: Entity, message_adapter: MessageAdapter) {
///     message_adapter.send_message(String::from("Hello rustician"), entity);
///     message_adapter.send_message(String::from("Did you recieve my message?"), entity);
/// }
///
/// impl MyState {}
///
/// // implementation for the State
/// impl State for MyState {
///     fn message(&mut self, mut messages: MessageReader, _registry: &mut Registry, _ctx: &mut Context) {
///         for message in messages.read::<String>() {
///             println!("{}", message);
///         }
///     }
/// }
/// ```
///
/// The example code snippet above will print two lines to stdout:
///
/// ```text
/// $ Hello rustician,
/// $  Did you receive my message?
/// ```
#[derive(Clone, Debug)]
pub struct MessageAdapter {
    messages: Arc<Mutex<BTreeMap<Entity, HashMap<TypeId, Vec<MessageBox>>>>>,
    window_sender: mpsc::Sender<WindowRequest>,
}

impl MessageAdapter {
    /// Creates a new message adapter
    pub fn new(window_sender: mpsc::Sender<WindowRequest>) -> Self {
        MessageAdapter {
            messages: Arc::new(Mutex::new(BTreeMap::new())),
            window_sender,
        }
    }

    /// Send a new message to the message pipeline.
    pub fn send_message<M: Any + Send>(&self, message: M, target: Entity) {
        // Docs say this method must be thread safe
        // to ensure thread safety,
        // do not release this lock until this method execution ends
        let mut locked_messages = self
            .messages
            .lock()
            .expect("MessageAdapter::send_message: Cannot lock messages.");
        locked_messages
            .entry(target)
            .or_insert_with(HashMap::new)
            .entry(TypeId::of::<M>())
            .or_insert_with(Vec::new)
            .push(MessageBox::new(message, target));

        self.window_sender
            .send(WindowRequest::Redraw)
            .expect("MessageAdapter::send_message: Cannot send redraw request.");
    }

    /// Returns a list of entities that has messages.
    pub(crate) fn entities(&self) -> Vec<Entity> {
        self.messages
            .lock()
            .expect("MessageAdapter::entities: Cannot lock messages.")
            .keys()
            .cloned()
            .collect()
    }

    /// Removes all messages for the given target entity. This is used
    /// to remove messages for entities that does not have a `State`
    /// to read the messages.
    pub(crate) fn remove_message_for_entity(&self, target: Entity) {
        self.messages
            .lock()
            .expect("MessageAdapter::remove_message_for_entity: Cannot lock messages.")
            .remove(&target);
    }

    /// Returns the number of messages in the queue.
    pub fn len(&self) -> usize {
        self.messages
            .lock()
            .expect("MessageAdapter::len: Cannot lock messages.")
            .len()
    }

    /// Returns `true` if the event message contains no events.
    pub fn is_empty(&self) -> bool {
        self.messages
            .lock()
            .expect("MessageAdapter::is_empty: Cannot lock messages.")
            .is_empty()
    }

    /// Returns a message reader for the given entity. Moves all
    /// messages for the entity from the adapter to the reader.
    pub(crate) fn message_reader(&self, entity: Entity) -> MessageReader {
        let messages = if let Some(messages) = self
            .messages
            .lock()
            .expect("MessageAdapter::message_reader: Cannot lock messages.")
            .remove(&entity)
        {
            messages
        } else {
            HashMap::new()
        };

        MessageReader::new(messages, entity)
    }
}

/// The `MessageReader` is used to access the messages of a widget.
pub struct MessageReader {
    messages: HashMap<TypeId, Vec<MessageBox>>,
    target: Entity,
}

impl MessageReader {
    /// Creates a new message reader.
    pub fn new(messages: HashMap<TypeId, Vec<MessageBox>>, target: Entity) -> Self {
        MessageReader { messages, target }
    }

    /// Returns the target entity of the reader.
    pub fn entity(&self) -> Entity {
        self.target
    }

    /// Returns `true` if the reader contains message for the specified type.
    pub fn contains_type<M: Any>(&self) -> bool {
        self.messages.contains_key(&TypeId::of::<M>())
    }

    /// Returns `true` if the reader contains no messages.
    pub fn is_empty(&self) -> bool {
        self.messages.is_empty()
    }

    /// Returns a message iterator for the given message type.
    pub fn read<M: Any + Send>(&mut self) -> MessageIterator<M> {
        let messages = if let Some(messages) = self.messages.remove(&TypeId::of::<M>()) {
            messages
        } else {
            vec![]
        };

        MessageIterator::new(messages)
    }
}

/// Iterator of messages.
#[derive(Debug)]
pub struct MessageIterator<M>
where
    M: Any + Send,
{
    messages: Vec<MessageBox>,
    _phantom: PhantomData<M>,
}

impl<M> MessageIterator<M>
where
    M: Any + Send,
{
    pub(crate) fn new(messages: Vec<MessageBox>) -> Self {
        MessageIterator {
            messages,
            _phantom: PhantomData::default(),
        }
    }
}

impl<M> Iterator for MessageIterator<M>
where
    M: Any + Send,
{
    type Item = M;

    fn next(&mut self) -> Option<Self::Item> {
        if self.messages.is_empty() {
            return None;
        }

        // unwrap is ok because only messages of the same type should
        // be stored in the vec
        Some(self.messages.remove(0).downcast::<M>().unwrap())
    }
}
<commit_msg>orbtk_core: linter update<commit_after>use std::{
    any::{Any, TypeId},
    collections::{BTreeMap, HashMap},
    marker::PhantomData,
    sync::{mpsc, Arc, Mutex},
};

use crate::shell::WindowRequest;

use dces::entity::Entity;

/// Internal wrapper that stores a message inside a box.
#[derive(Debug)]
pub struct MessageBox {
    message: Box<dyn Any + Send>,
    message_type: TypeId,
    target: Entity,
}

impl MessageBox {
    /// Downcasts the box to a concrete message.
    pub fn downcast<M: Any>(self) -> Result<M, String> {
        if self.message_type == TypeId::of::<M>() {
            return Ok(*self.message.downcast::<M>().unwrap());
        }

        Err("Wrong message type".to_string())
    }

    /// Downcasts the box as reference of a concrete message.
    pub fn downcast_ref<M: Any>(&self) -> Result<&M, String> {
        if self.message_type == TypeId::of::<M>() {
            return Ok(self.message.downcast_ref::<M>().unwrap());
        }

        Err("Wrong message type".to_string())
    }

    /// Check if the given type is the type of the message.
    pub fn is_type<M: Any>(&self) -> bool {
        self.message_type == TypeId::of::<M>()
    }

    /// Creates a new `MessageBox`.
    pub fn new<M>(message: M, target: Entity) -> Self
    where
        M: Any + Send,
    {
        MessageBox {
            message: Box::new(message),
            target,
            message_type: TypeId::of::<M>(),
        }
    }

    /// Returns the type of the event.
    pub fn message_type(&self) -> TypeId {
        self.message_type
    }

    /// Returns the target of the event.
    pub fn target(&self) -> Entity {
        self.target
    }
}

/// The `MessageAdapter` provides a thread save entry point to sent
/// and read messages inside widget entities. They are processed inside the
/// method `message` defined in each widgets `State` code.
///
/// # Example
///
/// ```rust
/// // State
/// fn say_hello(entity: Entity, message_adapter: MessageAdapter) {
///     message_adapter.send_message(String::from("Hello rustician"), entity);
///     message_adapter.send_message(String::from("Did you recieve my message?"), entity);
/// }
///
/// impl MyState {}
///
/// // implementation for the State
/// impl State for MyState {
///     fn message(&mut self, mut messages: MessageReader, _registry: &mut Registry, _ctx: &mut Context) {
///         for message in messages.read::<String>() {
///             println!("{}", message);
///         }
///     }
/// }
/// ```
///
/// The example code snippet above will print two lines to stdout:
///
/// ```text
/// $ Hello rustician,
/// $  Did you receive my message?
/// ```
#[derive(Clone, Debug)]
pub struct MessageAdapter {
    messages: Arc<Mutex<BTreeMap<Entity, HashMap<TypeId, Vec<MessageBox>>>>>,
    window_sender: mpsc::Sender<WindowRequest>,
}

impl MessageAdapter {
    /// Creates a new message adapter
    pub fn new(window_sender: mpsc::Sender<WindowRequest>) -> Self {
        MessageAdapter {
            messages: Arc::new(Mutex::new(BTreeMap::new())),
            window_sender,
        }
    }

    /// Send a new message to the message pipeline.
    pub fn send_message<M: Any + Send>(&self, message: M, target: Entity) {
        // Docs say this method must be thread safe
        // to ensure thread safety,
        // do not release this lock until this method execution ends
        let mut locked_messages = self
            .messages
            .lock()
            .expect("MessageAdapter::send_message: Cannot lock messages.");
        locked_messages
            .entry(target)
            .or_insert_with(HashMap::new)
            .entry(TypeId::of::<M>())
            .or_insert_with(Vec::new)
            .push(MessageBox::new(message, target));

        self.window_sender
            .send(WindowRequest::Redraw)
            .expect("MessageAdapter::send_message: Cannot send redraw request.");
    }

    /// Returns a list of entities that has messages.
    pub(crate) fn entities(&self) -> Vec<Entity> {
        self.messages
            .lock()
            .expect("MessageAdapter::entities: Cannot lock messages.")
            .keys()
            .cloned()
            .collect()
    }

    /// Removes all messages for the given target entity. This is used
    /// to remove messages for entities that does not have a `State`
    /// to read the messages.
    pub(crate) fn remove_message_for_entity(&self, target: Entity) {
        self.messages
            .lock()
            .expect("MessageAdapter::remove_message_for_entity: Cannot lock messages.")
            .remove(&target);
    }

    /// Returns the number of messages in the queue.
    pub fn len(&self) -> usize {
        self.messages
            .lock()
            .expect("MessageAdapter::len: Cannot lock messages.")
            .len()
    }

    /// Returns `true` if the event message contains no events.
    pub fn is_empty(&self) -> bool {
        self.messages
            .lock()
            .expect("MessageAdapter::is_empty: Cannot lock messages.")
            .is_empty()
    }

    /// Returns a message reader for the given entity. Moves all
    /// messages for the entity from the adapter to the reader.
    pub(crate) fn message_reader(&self, entity: Entity) -> MessageReader {
        let messages = if let Some(messages) = self
            .messages
            .lock()
            .expect("MessageAdapter::message_reader: Cannot lock messages.")
            .remove(&entity)
        {
            messages
        } else {
            HashMap::new()
        };

        MessageReader::new(messages, entity)
    }
}

/// The `MessageReader` is used to access the messages of a widget.
pub struct MessageReader {
    messages: HashMap<TypeId, Vec<MessageBox>>,
    target: Entity,
}

impl MessageReader {
    /// Creates a new message reader.
    pub fn new(messages: HashMap<TypeId, Vec<MessageBox>>, target: Entity) -> Self {
        MessageReader { messages, target }
    }

    /// Returns the target entity of the reader.
    pub fn entity(&self) -> Entity {
        self.target
    }

    /// Returns `true` if the reader contains message for the specified type.
    pub fn contains_type<M: Any>(&self) -> bool {
        self.messages.contains_key(&TypeId::of::<M>())
    }

    /// Returns `true` if the reader contains no messages.
    pub fn is_empty(&self) -> bool {
        self.messages.is_empty()
    }

    /// Returns a message iterator for the given message type.
    pub fn read<M: Any + Send>(&mut self) -> MessageIterator<M> {
        let messages = if let Some(messages) = self.messages.remove(&TypeId::of::<M>()) {
            messages
        } else {
            vec![]
        };

        MessageIterator::new(messages)
    }
}

/// Iterator of messages.
#[derive(Debug)]
pub struct MessageIterator<M>
where
    M: Any + Send,
{
    messages: Vec<MessageBox>,
    _phantom: PhantomData<M>,
}

impl<M> MessageIterator<M>
where
    M: Any + Send,
{
    pub(crate) fn new(messages: Vec<MessageBox>) -> Self {
        MessageIterator {
            messages,
            _phantom: PhantomData::default(),
        }
    }
}

impl<M> Iterator for MessageIterator<M>
where
    M: Any + Send,
{
    type Item = M;

    fn next(&mut self) -> Option<Self::Item> {
        if self.messages.is_empty() {
            return None;
        }

        // unwrap is ok because only messages of the same type should
        // be stored in the vec
        Some(self.messages.remove(0).downcast::<M>().unwrap())
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::io::{ BufRead, BufReader };
use std::path::Path;

fn parse_list(path: &Path) -> Result<Vec<(String, u32)>, String> {
    let list = match File::open(path) {
        Ok(x) => x,
        Err(why) => return Err(format!("{}", why))
    };
    let list = BufReader::new(list);

    let parsed_packages = Vec::new();
    for line in list.lines() {
        let split: Vec<&str> = line.unwrap_or(String::from("")).trim().split('=').collect();
        let package_name = String::from(split[0]);
        let package_version = split[1].parse::<u32>().unwrap_or(0); // For this reason, version of packages MUST NOT BE 0

        if !package_name.is_empty() || package_version != 0 {
            parsed_packages.push((package_name, package_version));
        }
    }

    if parsed_packages.len() > 0 {
        return Ok(parsed_packages)
    } else {
        return Err(String::from("No package found."))
    }
}

pub fn get_version(name: &str, path: &Path) -> Option<u32> {
    //TODO:
    //  Gets the version of the package
    let list = match parse_list(path) {
        Ok(x) => x,
        Err(why) => return None
    };

    for package in list {
        if package.0 == name {
            return Some(package.1)
        }
    }

    return None
}

pub fn update_version() -> Result<bool, String>{
    //TODO:
    // Sets/Updates the version of the package
}<commit_msg>update_version() implementation<commit_after>use std::fs::{ File, OpenOptions };
use std::io::{ BufRead, BufReader, Write };
use std::path::Path;

fn parse_list(path: &Path) -> Result<Vec<(String, u32)>, String> {
    let list = match File::open(path) {
        Ok(x) => x,
        Err(why) => return Err(format!("{}", why))
    };
    let list = BufReader::new(list);

    let mut parsed_packages = Vec::new();
    for line in list.lines() {
        let line = line.unwrap_or("".to_string());
        let split: Vec<&str> = line.trim().split('=').collect();
        let package_name = String::from(split[0]);
        let package_version = split[1].parse::<u32>().unwrap_or(0); // For this reason, version of packages MUST NOT BE 0

        if !package_name.is_empty() || package_version != 0 {
            parsed_packages.push((package_name, package_version));
        }
    }

    if parsed_packages.len() > 0 {
        return Ok(parsed_packages)
    } else {
        return Err(String::from("No package found."))
    }
}

pub fn get_version(name: &str, path: &Path) -> Option<u32> {
    //TODO:
    //  Gets the version of the package
    let list = match parse_list(path) {
        Ok(x) => x,
        Err(why) => return None
    };

    for package in list {
        if package.0 == name {
            return Some(package.1)
        }
    }

    return None
}

pub fn update_version(name: &str, version: u32, path: &Path) -> Result<bool, String>{
    let mut list = match parse_list(path) {
        Ok(x) => x,
        Err(why) => return Err(format!("{}", why))
    };

    list.retain(|ref x| x.0 == name);

    if list.len() == 0 {
        let mut file = match OpenOptions::new()
                    .append(true)
                    .write(true)
                    .create(true)
                    .open("installed_packages") {
            Ok(x) => x,
            Err(why) => return Err(format!("{}", why))
        };

        writeln!(file, "{}={}\n", name, version);
        return Ok(true);
    } else if list.len() == 1 {
        if list[0].1 == version {
            return Ok(false)
        } else {
            let mut updated_list = String::new();
            {
                let file = match File::open("installed_packages") {
                    Ok(x) => x,
                    Err(why) => return Err(format!("{}", why))
                };

                let file = BufReader::new(file);
                for line in file.lines() {
                    let current_line = line.unwrap();
                    if current_line.contains(name) {
                        updated_list += name;
                        updated_list += "=";
                        updated_list += &(version.to_string());
                        updated_list += "\n";
                    } else {
                        updated_list += current_line.trim();
                    }
                }
            }

            {
                let mut file = match File::open("installed_packages") {
                    Ok(x) => x,
                    Err(why) => return Err(format!("{}", why))
                };

                file.write_all(updated_list.as_bytes());
            }
            return Ok(true);
        }
    } else {
        return Err("There are two or more packages with the same name, this shouldn't happen!".to_string());
    }
}<|endoftext|>