<commit_before>//use std::collections::HashMap;
use std::ops::Index;

use library;
use nameutil;
use version::Version;

pub type NsId = u16;
pub const MAIN: NsId = library::MAIN_NAMESPACE;
pub const INTERNAL: NsId = library::INTERNAL_NAMESPACE;

#[derive(Debug)]
pub struct Namespace {
    pub name: String,
    pub crate_name: String,
    pub package_name: Option<String>,
    pub shared_libs: Vec<String>,
    pub versions: Vec<Version>,
}

#[derive(Debug)]
pub struct Info {
    namespaces: Vec<Namespace>,
    //name_index: HashMap<String, NsId>,
    pub glib_ns_id: NsId,
}

impl Info {
    /*
    pub fn by_name(&self, name: &str) -> Option<NsId> {
        self.name_index.get(name).cloned()
    }
    */

    pub fn main(&self) -> &Namespace {
        &self[MAIN]
    }
}

impl Index<NsId> for Info {
    type Output = Namespace;

    fn index(&self, index: NsId) -> &Namespace {
        &self.namespaces[index as usize]
    }
}

pub fn run(gir: &library::Library) -> Info {
    let mut namespaces = Vec::with_capacity(gir.namespaces.len());
    //let mut name_index = HashMap::with_capacity(gir.namespaces.len());
    let mut glib_ns_id = None;

    for (ns_id, ns) in gir.namespaces.iter().enumerate() {
        let ns_id = ns_id as NsId;
        namespaces.push(Namespace {
            name: ns.name.clone(),
            crate_name: nameutil::crate_name(&ns.name),
            package_name: ns.package_name.clone(),
            shared_libs: ns.shared_library.clone(),
            versions: ns.versions.iter().cloned().collect(),
        });
        //name_index.insert(ns.name.clone(), ns_id);
        if ns.name == "GLib" {
            glib_ns_id = Some(ns_id);
        }
    }

    Info {
        namespaces: namespaces,
        //name_index: name_index,
        glib_ns_id: glib_ns_id.expect("Missing `GLib` namespace!"),
    }
}
<commit_msg>Add higher_crate_name to namespace analysis<commit_after>//use std::collections::HashMap;
use std::ops::Index;

use library;
use nameutil;
use version::Version;

pub type NsId = u16;
pub const MAIN: NsId = library::MAIN_NAMESPACE;
pub const INTERNAL: NsId = library::INTERNAL_NAMESPACE;

#[derive(Debug)]
pub struct Namespace {
    pub name: String,
    pub crate_name: String,
    pub higher_crate_name: String,
    pub package_name: Option<String>,
    pub shared_libs: Vec<String>,
    pub versions: Vec<Version>,
}

#[derive(Debug)]
pub struct Info {
    namespaces: Vec<Namespace>,
    //name_index: HashMap<String, NsId>,
    pub glib_ns_id: NsId,
}

impl Info {
    /*
    pub fn by_name(&self, name: &str) -> Option<NsId> {
        self.name_index.get(name).cloned()
    }
    */

    pub fn main(&self) -> &Namespace {
        &self[MAIN]
    }
}

impl Index<NsId> for Info {
    type Output = Namespace;

    fn index(&self, index: NsId) -> &Namespace {
        &self.namespaces[index as usize]
    }
}

pub fn run(gir: &library::Library) -> Info {
    let mut namespaces = Vec::with_capacity(gir.namespaces.len());
    //let mut name_index = HashMap::with_capacity(gir.namespaces.len());
    let mut glib_ns_id = None;

    for (ns_id, ns) in gir.namespaces.iter().enumerate() {
        let ns_id = ns_id as NsId;
        let crate_name = nameutil::crate_name(&ns.name);
        let higher_crate_name = match &crate_name[..] {
            "gobject" | "gio" => "glib".to_owned(),
            _ => crate_name.clone(),
        };
        namespaces.push(Namespace {
            name: ns.name.clone(),
            crate_name: crate_name,
            higher_crate_name: higher_crate_name,
            package_name: ns.package_name.clone(),
            shared_libs: ns.shared_library.clone(),
            versions: ns.versions.iter().cloned().collect(),
        });
        //name_index.insert(ns.name.clone(), ns_id);
        if ns.name == "GLib" {
            glib_ns_id = Some(ns_id);
        }
    }

    Info {
        namespaces: namespaces,
        //name_index: name_index,
        glib_ns_id: glib_ns_id.expect("Missing `GLib` namespace!"),
    }
}
<|endoftext|>


<commit_before>use std;

use std::collections::HashMap;
use std::fmt::Display;
use std::path::Path;

use ::opcodes::{AddressingMode, OpCode};
use assembler::lexer::{Lexer, LexerError};
use assembler::parser::{Parser, ParserError};
use assembler::token::{LexerToken, ParserToken};

#[derive(Debug, PartialEq)]
pub struct Label(u16);

#[derive(Debug)]
pub struct AssemblerError {
    message: String,
}

impl AssemblerError {
    fn unknown_label<S>(label: S) -> AssemblerError
        where S: Into<String> + std::fmt::Display
    {
        AssemblerError::from(format!("Unknown label: '{}'", label))
    }

    fn relative_offset_too_large<S>(context: S) -> AssemblerError
        where S: Into<String> + Display
    {
        AssemblerError::from(format!("Branch too far: {}", context))
    }
}

impl From<String> for AssemblerError {
    fn from(error: String) -> AssemblerError {
        AssemblerError { message: error }
    }
}

impl From<LexerError> for AssemblerError {
    fn from(error: LexerError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

impl From<ParserError> for AssemblerError {
    fn from(error: ParserError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

#[derive(Debug)]
pub struct CodeSegment {
    pub address: u16,
    pub code: Vec<u8>,
}

pub struct Assembler {
    symbol_table: HashMap<String, Label>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { symbol_table: HashMap::new() }
    }

    pub fn assemble_string<S, O>(&mut self,
                                 code: S,
                                 offset: O)
                                 -> Result<Vec<CodeSegment>, AssemblerError>
        where S: Into<String>,
              O: Into<Option<u16>>
    {
        let code = code.into();
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_string(code)?;
        let mut parser = Parser::new();
        let tokens = parser.parse(tokens)?;

        Ok(self.assemble(tokens, offset)?)
    }

    pub fn assemble_file<P, O>(&mut self,
                               path: P,
                               offset: O)
                               -> Result<Vec<CodeSegment>, AssemblerError>
        where P: AsRef<Path>,
              O: Into<Option<u16>>
    {
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_file(path)?;
        let mut parser = Parser::new();
        let tokens = parser.parse(tokens)?;

        Ok(self.assemble(tokens, offset)?)
    }

    fn assemble<O>(&mut self,
                   tokens: Vec<ParserToken>,
                   offset: O)
                   -> Result<Vec<CodeSegment>, AssemblerError>
        where O: Into<Option<u16>>
    {
        let mut addr: u16 = offset.into().unwrap_or(0);

        // First, index the labels so we have addresses for them
        self.index_labels(&tokens, addr);

        // Now assemble the code
        let mut result = Vec::new();
        let mut last_addressing_mode = AddressingMode::Absolute;
        let mut current_segment = CodeSegment {
            address: addr,
            code: Vec::new(),
        };

        for token in tokens {
            // Push an opcode into the output and increment our address
            // offset
            if let ParserToken::OpCode(opcode) = token {
                current_segment.code.push(opcode.code);
                addr += opcode.length as u16;
                last_addressing_mode = opcode.mode;
            } else if let ParserToken::OrgDirective(org_addr) = token {
                if current_segment.code.len() > 0 {
                    result.push(current_segment);
                }
                current_segment = CodeSegment {
                    address: org_addr,
                    code: Vec::new(),
                };
            } else if let ParserToken::RawByte(byte) = token {
                // Push raw bytes directly into the output
                current_segment.code.push(byte);
            } else if let ParserToken::LabelArg(ref label) = token {
                // Labels as arguments should be in the symbol table, look
                // it up and calculate the address direction/location
                if let Some(&Label(label_addr)) = self.symbol_table.get(label) {
                    if last_addressing_mode == AddressingMode::Absolute {
                        let low_byte = (label_addr & 0xFF) as u8;
                        let high_byte = ((label_addr >> 8) & 0xFF) as u8;

                        current_segment.code.push(low_byte);
                        current_segment.code.push(high_byte);
                    } else {
                        // Its relative.. lets generate a relative branch
                        if addr > label_addr {
                            let distance = (label_addr as i16 - addr as i16) as i8;
                            if distance < -128 || distance > 127 {
                                return Err(AssemblerError::relative_offset_too_large(format!("Attempted jump to {} at {:04X}", label, addr)));
                            }
                            current_segment.code.push(distance as u8);
                        } else {
                            let distance = label_addr - addr;
                            if distance > 127 {
                                return Err(AssemblerError::relative_offset_too_large(format!("Attempted jump to {} at {:04X}", label, addr)));
                            }
                            current_segment.code.push(distance as u8);
                        }
                    }
                } else {
                    return Err(AssemblerError::unknown_label(label.clone()));
                }
            }
        }

        result.push(current_segment);

        Ok(result)
    }

    /// Stores all labels in the code in a Symbol table for lookup later
    fn index_labels(&mut self, tokens: &[ParserToken], offset: u16) {
        let mut addr: u16 = offset;
        let mut last_addressing_mode = AddressingMode::Absolute;

        for token in tokens {
            if let &ParserToken::Label(ref label) = token {
                // Insert a label with the specified memory address
                // as its offset
                self.symbol_table.insert(label.clone(), Label(addr));
            } else if let &ParserToken::OpCode(opcode) = token {
                // Add the length of this opcode to our
                // address offset
                addr += opcode.length as u16;
                last_addressing_mode = opcode.mode;
            } else if let &ParserToken::OrgDirective(new_addr) = token {
                addr = new_addr
            }
        }
    }
}

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

    #[test]
    fn can_assemble_basic_code() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            LDA $4400
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44], &segments[0].code[..]);
    }

    #[test]
    fn can_jump_to_label_behind() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN LDA $4400
            PHA
            JMP MAIN
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44, 0x48, 0x4C, 0x00, 0x00],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_jump_to_label_with_colon_behind() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN:
                LDA $4400
                PHA
                JMP MAIN
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44, 0x48, 0x4C, 0x00, 0x00],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_jump_to_label_ahead() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            JMP MAIN
            PHA
            LDX #15
            MAIN LDA $4400
            RTS
        ",
                             None)
            .unwrap();

        assert_eq!(&[0x4C, 0x06, 0x00, 0x48, 0xA2, 0x0F, 0xAD, 0x00, 0x44, 0x60],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_use_variables() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN:
            LDX #15
            JMP MAIN_ADDRESS
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0x4C, 0x00, 0x00], &segments[0].code[..]);
    }

    #[test]
    fn can_use_variables_assigned_to_variables() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN_ADDRESS_INDIRECT_ONE = MAIN_ADDRESS
            MAIN_ADDRESS_INDIRECT_TWO = MAIN_ADDRESS_INDIRECT_ONE
            MAIN:
            LDX #15
            JMP MAIN_ADDRESS_INDIRECT_TWO
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0x4C, 0x00, 0x00], &segments[0].code[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            CLRMEM  LDA #$00
                    TAY
            CLRM1   STA ($FF),Y
                    INY
                    DEX
                    BNE CLRM1
                    RTS
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xA9, 0x00, 0xA8, 0x91, 0xFF, 0xC8, 0xCA, 0xD0, 0xFA, 0x60],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation_that_jumps_forward_and_is_lowercase() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            jmp     clrmem
            lda     #$00
            beq     clrm1
            nop
            nop
            clrm1   sta ($ff),y
                    iny
                    dex
                    bne clrm1
                    rts
            clrmem  lda #$00
                    tay
            jmp     clrm1
        ",
                             None)
            .unwrap();

        assert_eq!(&[0x4C, 0x10, 0x00, 0xA9, 0x00, 0xF0, 0x02, 0xEA, 0xEA, 0x91, 0xFF, 0xC8,
                     0xCA, 0xD0, 0xFA, 0x60, 0xA9, 0x00, 0xA8, 0x4C, 0x09, 0x00],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation_that_jumps_forward() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            JMP     CLRMEM
            LDA     #$00
            BEQ     CLRM1
            NOP
            NOP
            BRK
            CLRM1   STA ($FF),Y
                    INY
                    DEX
                    BNE CLRM1
                    RTS
            CLRMEM  LDA #$00
                    TAY
            JMP     CLRM1
        ",
                             None)
            .unwrap();

        assert_eq!(&[0x4C, 0x11, 0x00, 0xA9, 0x00, 0xF0, 0x03, 0xEA, 0xEA, 0x00, 0x91, 0xFF,
                     0xC8, 0xCA, 0xD0, 0xFA, 0x60, 0xA9, 0x00, 0xA8, 0x4C, 0x0A, 0x00],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_use_variables_for_indirect_addressing() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN:
            LDX #15
            LDA (MAIN_ADDRESS),Y
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0xB1, 0x00, 0x00], &segments[0].code[..]);
    }

    #[test]
    fn can_assign_code_segments_to_different_memory_addresses() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            .ORG $C000
            LDA #$FF
            STA $2000

            .ORG $100
            LDA #$AA
            STA $2001
        ",
                             None)
            .unwrap();

        println!("SEGMENTS: {:?}", segments);

        assert_eq!(0xC000, segments[0].address);
        assert_eq!(0x0100, segments[1].address);
    }
}<commit_msg>Add a test to assert that its possible to assembler jumps across code segments<commit_after>use std;

use std::collections::HashMap;
use std::fmt::Display;
use std::path::Path;

use ::opcodes::{AddressingMode, OpCode};
use assembler::lexer::{Lexer, LexerError};
use assembler::parser::{Parser, ParserError};
use assembler::token::{LexerToken, ParserToken};

#[derive(Debug, PartialEq)]
pub struct Label(u16);

#[derive(Debug)]
pub struct AssemblerError {
    message: String,
}

impl AssemblerError {
    fn unknown_label<S>(label: S) -> AssemblerError
        where S: Into<String> + std::fmt::Display
    {
        AssemblerError::from(format!("Unknown label: '{}'", label))
    }

    fn relative_offset_too_large<S>(context: S) -> AssemblerError
        where S: Into<String> + Display
    {
        AssemblerError::from(format!("Branch too far: {}", context))
    }
}

impl From<String> for AssemblerError {
    fn from(error: String) -> AssemblerError {
        AssemblerError { message: error }
    }
}

impl From<LexerError> for AssemblerError {
    fn from(error: LexerError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

impl From<ParserError> for AssemblerError {
    fn from(error: ParserError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

#[derive(Debug)]
pub struct CodeSegment {
    pub address: u16,
    pub code: Vec<u8>,
}

pub struct Assembler {
    symbol_table: HashMap<String, Label>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { symbol_table: HashMap::new() }
    }

    pub fn assemble_string<S, O>(&mut self,
                                 code: S,
                                 offset: O)
                                 -> Result<Vec<CodeSegment>, AssemblerError>
        where S: Into<String>,
              O: Into<Option<u16>>
    {
        let code = code.into();
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_string(code)?;
        let mut parser = Parser::new();
        let tokens = parser.parse(tokens)?;

        Ok(self.assemble(tokens, offset)?)
    }

    pub fn assemble_file<P, O>(&mut self,
                               path: P,
                               offset: O)
                               -> Result<Vec<CodeSegment>, AssemblerError>
        where P: AsRef<Path>,
              O: Into<Option<u16>>
    {
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_file(path)?;
        let mut parser = Parser::new();
        let tokens = parser.parse(tokens)?;

        Ok(self.assemble(tokens, offset)?)
    }

    fn assemble<O>(&mut self,
                   tokens: Vec<ParserToken>,
                   offset: O)
                   -> Result<Vec<CodeSegment>, AssemblerError>
        where O: Into<Option<u16>>
    {
        let mut addr: u16 = offset.into().unwrap_or(0);

        // First, index the labels so we have addresses for them
        self.index_labels(&tokens, addr);

        // Now assemble the code
        let mut result = Vec::new();
        let mut last_addressing_mode = AddressingMode::Absolute;
        let mut current_segment = CodeSegment {
            address: addr,
            code: Vec::new(),
        };

        for token in tokens {
            // Push an opcode into the output and increment our address
            // offset
            if let ParserToken::OpCode(opcode) = token {
                current_segment.code.push(opcode.code);
                addr += opcode.length as u16;
                last_addressing_mode = opcode.mode;
            } else if let ParserToken::OrgDirective(org_addr) = token {
                if current_segment.code.len() > 0 {
                    result.push(current_segment);
                }
                current_segment = CodeSegment {
                    address: org_addr,
                    code: Vec::new(),
                };
            } else if let ParserToken::RawByte(byte) = token {
                // Push raw bytes directly into the output
                current_segment.code.push(byte);
            } else if let ParserToken::LabelArg(ref label) = token {
                // Labels as arguments should be in the symbol table, look
                // it up and calculate the address direction/location
                if let Some(&Label(label_addr)) = self.symbol_table.get(label) {
                    if last_addressing_mode == AddressingMode::Absolute {
                        let low_byte = (label_addr & 0xFF) as u8;
                        let high_byte = ((label_addr >> 8) & 0xFF) as u8;

                        current_segment.code.push(low_byte);
                        current_segment.code.push(high_byte);
                    } else {
                        // Its relative.. lets generate a relative branch
                        if addr > label_addr {
                            let distance = (label_addr as i16 - addr as i16) as i8;
                            if distance < -128 || distance > 127 {
                                return Err(AssemblerError::relative_offset_too_large(format!("Attempted jump to {} at {:04X}", label, addr)));
                            }
                            current_segment.code.push(distance as u8);
                        } else {
                            let distance = label_addr - addr;
                            if distance > 127 {
                                return Err(AssemblerError::relative_offset_too_large(format!("Attempted jump to {} at {:04X}", label, addr)));
                            }
                            current_segment.code.push(distance as u8);
                        }
                    }
                } else {
                    return Err(AssemblerError::unknown_label(label.clone()));
                }
            }
        }

        result.push(current_segment);

        Ok(result)
    }

    /// Stores all labels in the code in a Symbol table for lookup later
    fn index_labels(&mut self, tokens: &[ParserToken], offset: u16) {
        let mut addr: u16 = offset;
        let mut last_addressing_mode = AddressingMode::Absolute;

        for token in tokens {
            if let &ParserToken::Label(ref label) = token {
                // Insert a label with the specified memory address
                // as its offset
                self.symbol_table.insert(label.clone(), Label(addr));
            } else if let &ParserToken::OpCode(opcode) = token {
                // Add the length of this opcode to our
                // address offset
                addr += opcode.length as u16;
                last_addressing_mode = opcode.mode;
            } else if let &ParserToken::OrgDirective(new_addr) = token {
                addr = new_addr
            }
        }
    }
}

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

    #[test]
    fn can_assemble_basic_code() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            LDA $4400
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44], &segments[0].code[..]);
    }

    #[test]
    fn can_jump_to_label_behind() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN LDA $4400
            PHA
            JMP MAIN
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44, 0x48, 0x4C, 0x00, 0x00],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_jump_to_label_with_colon_behind() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN:
                LDA $4400
                PHA
                JMP MAIN
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44, 0x48, 0x4C, 0x00, 0x00],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_jump_to_label_ahead() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            JMP MAIN
            PHA
            LDX #15
            MAIN LDA $4400
            RTS
        ",
                             None)
            .unwrap();

        assert_eq!(&[0x4C, 0x06, 0x00, 0x48, 0xA2, 0x0F, 0xAD, 0x00, 0x44, 0x60],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_use_variables() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN:
            LDX #15
            JMP MAIN_ADDRESS
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0x4C, 0x00, 0x00], &segments[0].code[..]);
    }

    #[test]
    fn can_use_variables_assigned_to_variables() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN_ADDRESS_INDIRECT_ONE = MAIN_ADDRESS
            MAIN_ADDRESS_INDIRECT_TWO = MAIN_ADDRESS_INDIRECT_ONE
            MAIN:
            LDX #15
            JMP MAIN_ADDRESS_INDIRECT_TWO
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0x4C, 0x00, 0x00], &segments[0].code[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            CLRMEM  LDA #$00
                    TAY
            CLRM1   STA ($FF),Y
                    INY
                    DEX
                    BNE CLRM1
                    RTS
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xA9, 0x00, 0xA8, 0x91, 0xFF, 0xC8, 0xCA, 0xD0, 0xFA, 0x60],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation_that_jumps_forward_and_is_lowercase() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            jmp     clrmem
            lda     #$00
            beq     clrm1
            nop
            nop
            clrm1   sta ($ff),y
                    iny
                    dex
                    bne clrm1
                    rts
            clrmem  lda #$00
                    tay
            jmp     clrm1
        ",
                             None)
            .unwrap();

        assert_eq!(&[0x4C, 0x10, 0x00, 0xA9, 0x00, 0xF0, 0x02, 0xEA, 0xEA, 0x91, 0xFF, 0xC8,
                     0xCA, 0xD0, 0xFA, 0x60, 0xA9, 0x00, 0xA8, 0x4C, 0x09, 0x00],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation_that_jumps_forward() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            JMP     CLRMEM
            LDA     #$00
            BEQ     CLRM1
            NOP
            NOP
            BRK
            CLRM1   STA ($FF),Y
                    INY
                    DEX
                    BNE CLRM1
                    RTS
            CLRMEM  LDA #$00
                    TAY
            JMP     CLRM1
        ",
                             None)
            .unwrap();

        assert_eq!(&[0x4C, 0x11, 0x00, 0xA9, 0x00, 0xF0, 0x03, 0xEA, 0xEA, 0x00, 0x91, 0xFF,
                     0xC8, 0xCA, 0xD0, 0xFA, 0x60, 0xA9, 0x00, 0xA8, 0x4C, 0x0A, 0x00],
                   &segments[0].code[..]);
    }

    #[test]
    fn can_use_variables_for_indirect_addressing() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN:
            LDX #15
            LDA (MAIN_ADDRESS),Y
        ",
                             None)
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0xB1, 0x00, 0x00], &segments[0].code[..]);
    }

    #[test]
    fn can_assign_code_segments_to_different_memory_addresses() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            .ORG $C000
            LDA #$FF
            STA $2000

            .ORG $100
            LDA #$AA
            STA $2001
        ",
                             None)
            .unwrap();

        assert_eq!(0xC000, segments[0].address);
        assert_eq!(0x0100, segments[1].address);
    }

    #[test]
    fn can_jump_between_code_segments() {
        let mut assembler = Assembler::new();
        let segments = assembler.assemble_string("
            .ORG $C000
            JMP CALLBACK

            .ORG $2000
            LDA #$AA
            STA $2001

            CALLBACK
            LDX #$0A
        ",
                             None)
            .unwrap();

        assert_eq!(0xC000, segments[0].address);
        assert_eq!(0x2000, segments[1].address);

        assert_eq!(0x05, segments[0].code[0x01]);
        assert_eq!(0x20, segments[0].code[0x02]);
    }
}<|endoftext|>


<commit_before>use std::ops::Range;

use crate::fastfield::{
    BitpackedFastFieldReader, DynamicFastFieldReader, FastFieldReader, FastValue, MultiValueLength,
};
use crate::DocId;

/// Reader for a multivalued `u64` fast field.
///
/// The reader is implemented as two `u64` fast field.
///
/// The `vals_reader` will access the concatenated list of all
/// values for all reader.
/// The `idx_reader` associated, for each document, the index of its first value.
///
#[derive(Clone)]
pub struct MultiValuedFastFieldReader<Item: FastValue> {
    idx_reader: DynamicFastFieldReader<u64>,
    vals_reader: BitpackedFastFieldReader<Item>,
}

impl<Item: FastValue> MultiValuedFastFieldReader<Item> {
    pub(crate) fn open(
        idx_reader: DynamicFastFieldReader<u64>,
        vals_reader: BitpackedFastFieldReader<Item>,
    ) -> MultiValuedFastFieldReader<Item> {
        MultiValuedFastFieldReader {
            idx_reader,
            vals_reader,
        }
    }

    /// Returns `(start, stop)`, such that the values associated
    /// to the given document are `start..stop`.
    fn range(&self, doc: DocId) -> Range<u64> {
        let start = self.idx_reader.get(doc);
        let stop = self.idx_reader.get(doc + 1);
        start..stop
    }

    /// Returns the array of values associated to the given `doc`.
    pub fn get_vals(&self, doc: DocId, vals: &mut Vec<Item>) {
        let range = self.range(doc);
        let len = (range.end - range.start) as usize;
        vals.resize(len, Item::make_zero());
        self.vals_reader.get_range_u64(range.start, &mut vals[..]);
    }

    /// Returns the number of values associated with the document `DocId`.
    pub fn num_vals(&self, doc: DocId) -> usize {
        let range = self.range(doc);
        (range.end - range.start) as usize
    }

    /// Returns the overall number of values in this field  .
    pub fn total_num_vals(&self) -> u64 {
        self.idx_reader.max_value()
    }
}

impl<Item: FastValue> MultiValueLength for MultiValuedFastFieldReader<Item> {
    fn get_len(&self, doc_id: DocId) -> u64 {
        self.num_vals(doc_id) as u64
    }

    fn get_total_len(&self) -> u64 {
        self.total_num_vals() as u64
    }
}
#[cfg(test)]
mod tests {

    use crate::core::Index;
    use crate::schema::{Facet, Schema, INDEXED};

    #[test]
    fn test_multifastfield_reader() {
        let mut schema_builder = Schema::builder();
        let facet_field = schema_builder.add_facet_field("facets", INDEXED);
        let schema = schema_builder.build();
        let index = Index::create_in_ram(schema);
        let mut index_writer = index
            .writer_for_tests()
            .expect("Failed to create index writer.");
        index_writer.add_document(doc!(
            facet_field => Facet::from("/category/cat2"),
            facet_field => Facet::from("/category/cat1"),
        ));
        index_writer.add_document(doc!(facet_field => Facet::from("/category/cat2")));
        index_writer.add_document(doc!(facet_field => Facet::from("/category/cat3")));
        index_writer.commit().expect("Commit failed");
        let searcher = index.reader().unwrap().searcher();
        let segment_reader = searcher.segment_reader(0);
        let mut facet_reader = segment_reader.facet_reader(facet_field).unwrap();

        let mut facet = Facet::root();
        {
            facet_reader.facet_from_ord(1, &mut facet).unwrap();
            assert_eq!(facet, Facet::from("/category"));
        }
        {
            facet_reader.facet_from_ord(2, &mut facet).unwrap();
            assert_eq!(facet, Facet::from("/category/cat1"));
        }
        {
            facet_reader.facet_from_ord(3, &mut facet).unwrap();
            assert_eq!(format!("{}", facet), "/category/cat2");
            assert_eq!(facet, Facet::from("/category/cat2"));
        }
        {
            facet_reader.facet_from_ord(4, &mut facet).unwrap();
            assert_eq!(facet, Facet::from("/category/cat3"));
        }

        let mut vals = Vec::new();
        {
            facet_reader.facet_ords(0, &mut vals);
            assert_eq!(&vals[..], &[2, 3]);
        }
        {
            facet_reader.facet_ords(1, &mut vals);
            assert_eq!(&vals[..], &[3]);
        }
        {
            facet_reader.facet_ords(2, &mut vals);
            assert_eq!(&vals[..], &[4]);
        }
    }
}
<commit_msg>Exposing min/max value interface on MultiValuedFastField Reader (#1094)<commit_after>use std::ops::Range;

use crate::fastfield::{
    BitpackedFastFieldReader, DynamicFastFieldReader, FastFieldReader, FastValue, MultiValueLength,
};
use crate::DocId;

/// Reader for a multivalued `u64` fast field.
///
/// The reader is implemented as two `u64` fast field.
///
/// The `vals_reader` will access the concatenated list of all
/// values for all reader.
/// The `idx_reader` associated, for each document, the index of its first value.
///
#[derive(Clone)]
pub struct MultiValuedFastFieldReader<Item: FastValue> {
    idx_reader: DynamicFastFieldReader<u64>,
    vals_reader: BitpackedFastFieldReader<Item>,
}

impl<Item: FastValue> MultiValuedFastFieldReader<Item> {
    pub(crate) fn open(
        idx_reader: DynamicFastFieldReader<u64>,
        vals_reader: BitpackedFastFieldReader<Item>,
    ) -> MultiValuedFastFieldReader<Item> {
        MultiValuedFastFieldReader {
            idx_reader,
            vals_reader,
        }
    }

    /// Returns `(start, stop)`, such that the values associated
    /// to the given document are `start..stop`.
    fn range(&self, doc: DocId) -> Range<u64> {
        let start = self.idx_reader.get(doc);
        let stop = self.idx_reader.get(doc + 1);
        start..stop
    }

    /// Returns the array of values associated to the given `doc`.
    pub fn get_vals(&self, doc: DocId, vals: &mut Vec<Item>) {
        let range = self.range(doc);
        let len = (range.end - range.start) as usize;
        vals.resize(len, Item::make_zero());
        self.vals_reader.get_range_u64(range.start, &mut vals[..]);
    }

    /// Returns the minimum value for this fast field.
    ///
    /// The max value does not take in account of possible
    /// deleted document, and should be considered as an upper bound
    /// of the actual maximum value.
    pub fn min_value(&self) -> Item {
        self.vals_reader.max_value()
    }

    /// Returns the maximum value for this fast field.
    ///
    /// The max value does not take in account of possible
    /// deleted document, and should be considered as an upper bound
    /// of the actual maximum value.
    pub fn max_value(&self) -> Item {
        self.vals_reader.min_value()
    }

    /// Returns the number of values associated with the document `DocId`.
    pub fn num_vals(&self, doc: DocId) -> usize {
        let range = self.range(doc);
        (range.end - range.start) as usize
    }

    /// Returns the overall number of values in this field  .
    pub fn total_num_vals(&self) -> u64 {
        self.idx_reader.max_value()
    }
}

impl<Item: FastValue> MultiValueLength for MultiValuedFastFieldReader<Item> {
    fn get_len(&self, doc_id: DocId) -> u64 {
        self.num_vals(doc_id) as u64
    }

    fn get_total_len(&self) -> u64 {
        self.total_num_vals() as u64
    }
}
#[cfg(test)]
mod tests {

    use crate::core::Index;
    use crate::schema::{Facet, Schema, INDEXED};

    #[test]
    fn test_multifastfield_reader() {
        let mut schema_builder = Schema::builder();
        let facet_field = schema_builder.add_facet_field("facets", INDEXED);
        let schema = schema_builder.build();
        let index = Index::create_in_ram(schema);
        let mut index_writer = index
            .writer_for_tests()
            .expect("Failed to create index writer.");
        index_writer.add_document(doc!(
            facet_field => Facet::from("/category/cat2"),
            facet_field => Facet::from("/category/cat1"),
        ));
        index_writer.add_document(doc!(facet_field => Facet::from("/category/cat2")));
        index_writer.add_document(doc!(facet_field => Facet::from("/category/cat3")));
        index_writer.commit().expect("Commit failed");
        let searcher = index.reader().unwrap().searcher();
        let segment_reader = searcher.segment_reader(0);
        let mut facet_reader = segment_reader.facet_reader(facet_field).unwrap();

        let mut facet = Facet::root();
        {
            facet_reader.facet_from_ord(1, &mut facet).unwrap();
            assert_eq!(facet, Facet::from("/category"));
        }
        {
            facet_reader.facet_from_ord(2, &mut facet).unwrap();
            assert_eq!(facet, Facet::from("/category/cat1"));
        }
        {
            facet_reader.facet_from_ord(3, &mut facet).unwrap();
            assert_eq!(format!("{}", facet), "/category/cat2");
            assert_eq!(facet, Facet::from("/category/cat2"));
        }
        {
            facet_reader.facet_from_ord(4, &mut facet).unwrap();
            assert_eq!(facet, Facet::from("/category/cat3"));
        }

        let mut vals = Vec::new();
        {
            facet_reader.facet_ords(0, &mut vals);
            assert_eq!(&vals[..], &[2, 3]);
        }
        {
            facet_reader.facet_ords(1, &mut vals);
            assert_eq!(&vals[..], &[3]);
        }
        {
            facet_reader.facet_ords(2, &mut vals);
            assert_eq!(&vals[..], &[4]);
        }
    }
}
<|endoftext|>


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

fn write(data:&mut String)  {
	let mut buffer = File::create("foo.txt").unwrap();
	buffer.write(b"as bytese");
}

fn main() {
	let mut buffer = File::create("foo.txt").unwrap();
	let f = File::open("paragraph.txt").unwrap();
	let mut reader = BufReader::new(&f);
   	let line = &mut String::new();
   	reader.read_line(line);
   	while(line.trim()!="") {
   		println!("{:?}",line.trim());
   		line.clear();
   		reader.read_line(line);
   	}
}
<commit_msg>Update replace_word.rs<commit_after>// Implements http://rosettacode.org/wiki/Globally_replace_text_in_several_files
// Author: Rahul Sharma
// Github: https://github.com/creativcoder

use std::io::BufReader;
use std::io::BufWriter;
use std::io::BufRead;
use std::fs::File;
use std::fs::OpenOptions;
use std::io::Write;

#[allow(unused_must_use)]
fn main() {
	// opens file for writing replaced lines
	let out_fd = OpenOptions::new()
					.write(true)
					.create(true)
					.open("resources/output.txt");

	// defining a closure write_line
	let write_line = |line:&str| {
	match out_fd {
		Ok(ref v) => {
			let mut writer = BufWriter::new(v);
			writer.write_all(line.as_bytes());
		},
		Err(ref e) => {println!("Error:{}",e);},
	}
};
	// read input file
	match File::open("resources/paragraph.txt") {
		Ok(handle) => {
			let mut reader = BufReader::new(handle);
			let mut line = String::new();
			// read the first line
			reader.read_line(&mut line);
			// loop until line end
			while line.trim()!="" {
			let mut replaced_line = line.trim().replace("Goodbye London!","Hello New York!");
			replaced_line = replaced_line + "\n";
   			write_line(&replaced_line[..]);
   			line.clear();
   			reader.read_line(&mut line);
   			}
		},
		Err(e) => println!("Error:{}",e),
	}
}
<|endoftext|>


<commit_before>extern crate serde_json;

use errors::anoncreds::AnoncredsError;
use services::crypto::CryptoService;
use services::pool::PoolService;
use services::wallet::WalletService;
use std::rc::Rc;

pub enum ProverCommand {
    StoreClaimOffer(
        i32, // wallet handle
        String, // claim offer json
        Box<Fn(Result<(), AnoncredsError>) + Send>),
    GetClaimOffers(
        i32, // wallet handle
        String, // filter json
        Box<Fn(Result<String, AnoncredsError>) + Send>),
    CreateMasterSecret(
        i32, // wallet handle
        String, // master secret name
        Box<Fn(Result<(), AnoncredsError>) + Send>),
    CreateAndStoreClaimRequest(
        i32, // wallet handle
        String, // claim offer json
        String, // claim def json
        String, // master secret name
        Box<Fn(Result<String, AnoncredsError>) + Send>),
    StoreClaim(
        i32, // wallet handle
        String, // claims json
        Box<Fn(Result<(), AnoncredsError>) + Send>),
    GetClaims(
        i32, // wallet handle
        String, // filter json
        Box<Fn(Result<String, AnoncredsError>) + Send>),
    GetClaimsForProofReq(
        i32, // wallet handle
        String, // proof request json
        Box<Fn(Result<String, AnoncredsError>) + Send>),
    CreateProof(
        i32, // wallet handle
        String, // proof request json
        String, // requested claims json
        String, // schemas json
        String, // claim defs json
        String, // revoc regs json
        Box<Fn(Result<String, AnoncredsError>) + Send>),
}

pub struct ProverCommandExecutor {
    crypto_service: Rc<CryptoService>,
    pool_service: Rc<PoolService>,
    wallet_service: Rc<WalletService>
}

impl ProverCommandExecutor {
    pub fn new(crypto_service: Rc<CryptoService>,
               pool_service: Rc<PoolService>,
               wallet_service: Rc<WalletService>) -> ProverCommandExecutor {
        ProverCommandExecutor {
            crypto_service: crypto_service,
            pool_service: pool_service,
            wallet_service: wallet_service,
        }
    }

    pub fn execute(&self, command: ProverCommand) {
        match command {
            ProverCommand::StoreClaimOffer(wallet_handle, claim_offer_json, cb) => {
                info!(target: "prover_command_executor", "StoreClaimOffer command received");
                self.store_claim_offer(wallet_handle, &claim_offer_json, cb);
            },
            ProverCommand::GetClaimOffers(wallet_handle, filter_json, cb) => {
                info!(target: "prover_command_executor", "GetClaimOffers command received");
                self.get_claim_offers(wallet_handle, &filter_json, cb);
            },
            ProverCommand::CreateMasterSecret(wallet_handle, master_secret_name, cb) => {
                info!(target: "prover_command_executor", "CreateMasterSecret command received");
                self.create_master_secret(wallet_handle, &master_secret_name, cb);
            },
            ProverCommand::CreateAndStoreClaimRequest(wallet_handle, claim_offer_json,
                                                      claim_def_json, master_secret_name, cb) => {
                info!(target: "prover_command_executor", "CreateAndStoreClaimRequest command received");
                self.create_and_store_claim_request(wallet_handle, &claim_offer_json,
                                                    &claim_def_json, &master_secret_name, cb);
            },
            ProverCommand::StoreClaim(wallet_handle, claims_json, cb) => {
                info!(target: "prover_command_executor", "StoreClaim command received");
                self.store_claim(wallet_handle, &claims_json, cb);
            },
            ProverCommand::GetClaims(wallet_handle, filter_json, cb) => {
                info!(target: "prover_command_executor", "GetClaims command received");
                self.get_claims(wallet_handle, &filter_json, cb);
            },
            ProverCommand::GetClaimsForProofReq(wallet_handle, proof_req_json, cb) => {
                info!(target: "prover_command_executor", "GetClaimsForProofReq command received");
                self.get_claims_for_proof_req(wallet_handle, &proof_req_json, cb);
            },
            ProverCommand::CreateProof(wallet_handle, proof_req_json, requested_claims_json, schemas_jsons,
                                       claim_def_jsons, revoc_regs_jsons, cb) => {
                info!(target: "prover_command_executor", "CreateProof command received");
                self.create_proof(wallet_handle, &proof_req_json, &requested_claims_json, &schemas_jsons,
                                  &claim_def_jsons, &revoc_regs_jsons, cb);
            }
        };
    }

    fn store_claim_offer(&self,
                         wallet_handle: i32,
                         claim_offer_json: &str,
                         cb: Box<Fn(Result<(), AnoncredsError>) + Send>) {
        unimplemented!();
//        let result =
//            ClaimOffer::from_str(&claim_offer_json)
//                .map_err(|err| AnoncredsError::CryptoError(CryptoError::InvalidStructure(err.to_string())))
//                .and_then(|claim_offer| {
//                    self.wallet_service.set(wallet_handle, &format!("claim_offer {}", &claim_offer.issuer_did), claim_offer_json)?;
//
//                    Ok(())
//                });
//
//        match result {
//            Ok(()) => cb(Ok(())),
//            Err(err) => cb(Err(err))
//        }
    }

    fn get_claim_offers(&self,
                        wallet_handle: i32,
                        filter_json: &str,
                        cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        unimplemented!();
//        let result =
//            serde_json::from_str(&filter_json)
//                .map_err(|err| AnoncredsError::CryptoError(CryptoError::InvalidStructure(err.to_string())))
//                .and_then(|filter: Value| {
//                    let claim_offers =
//                        self.wallet_service.get(wallet_handle, &format!("claim_offer {}", &filter["issuer_did"]))?; //TODO LIST METHOD
//
//                    Ok((claim_offers))
//                });
//
//        match result {
//            Ok(claim_offers) => cb(Ok(claim_offers)),
//            Err(err) => cb(Err(err))
//        }
    }

    fn create_master_secret(&self,
                            wallet_handle: i32,
                            master_secret_name: &str,
                            cb: Box<Fn(Result<(), AnoncredsError>) + Send>) {
        unimplemented!();
//        let result =
//            self.crypto_service.anoncreds.prover.generate_master_secret()
//                .map_err(|err| AnoncredsError::CryptoError(CryptoError::InvalidStructure(err.to_string())))
//                .and_then(|master_secret| {
//                    let master_secret_string = master_secret.to_dec()?;
//
//                    self.wallet_service.set(wallet_handle, &format!("master_secret {}", &master_secret_name), &master_secret_string)?;
//
//                    Ok(())
//                });
//
//        match result {
//            Ok(()) => cb(Ok(())),
//            Err(err) => cb(Err(err))
//        }
    }

    fn create_and_store_claim_request(&self,
                                      wallet_handle: i32,
                                      claim_offer_json: &str,
                                      claim_def_json: &str,
                                      master_secret_name: &str,
                                      cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        unimplemented!();
//        let result =
//            ClaimOffer::from_str(&claim_offer_json)
//                .map_err(|err| AnoncredsError::CryptoError(CryptoError::InvalidStructure(err.to_string())))
//                .and_then(|claim_offer| {
//                    let claim_def_json = ClaimDefinition::from_str(&claim_def_json)?;
//
//                    let pk_string = self.wallet_service.get(wallet_handle, &format!("public_key {}", &claim_offer.issuer_did))?;
//                    let pkr_string = self.wallet_service.get(wallet_handle, &format!("public_key_revocation {}", &claim_offer.issuer_did))?;
//                    let ms_string = self.wallet_service.get(wallet_handle,&format!("master_secret {}", master_secret_name))?;
//
//                    let pk = PublicKey::from_str(&pk_string)?;
//                    let pkr = RevocationPublicKey::from_str(&pkr_string)?;
//                    let ms = BigNumber::from_dec(&ms_string)?;
//
//                    let (claim_request, claim_init_data, revocation_claim_init_data) =
//                        self.crypto_service.anoncreds.prover.create_claim_request(pk, pkr, ms, "1".to_string(), true)?;
//
//                    let claim_request_json = ClaimRequest::to_string(&claim_request)?;
//                    let claim_init_data_json = ClaimRequest::to_string(&claim_request);
//                    let revocation_claim_init_data_json = ClaimRequest::to_string(&claim_request)?;
//
//                    Ok(claim_request_json)
//                });
//
//        match result {
//            Ok(claim_request_json) => cb(Ok(claim_request_json)),
//            Err(err) => cb(Err(err))
//        }
    }

    fn store_claim(&self,
                   wallet_handle: i32,
                   claims_json: &str,
                   cb: Box<Fn(Result<(), AnoncredsError>) + Send>) {
        cb(Ok(()));
    }

    fn get_claims(&self,
                  wallet_handle: i32,
                  filter_json: &str,
                  cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        cb(Ok("".to_string()));
    }

    fn get_claims_for_proof_req(&self,
                                wallet_handle: i32,
                                proof_req_json: &str,
                                cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        cb(Ok("".to_string()));
    }

    fn parse_proof_request(&self,
                           wallet_handle: i32,
                           proof_request_json: &str,
                           cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        cb(Ok("".to_string()));
    }

    fn create_proof(&self,
                    wallet_handle: i32,
                    proof_req_json: &str,
                    requested_claims_json: &str,
                    schemas_jsons: &str,
                    claim_def_jsons: &str,
                    revoc_regs_jsons: &str,
                    cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        cb(Ok("".to_string()));
    }
}<commit_msg>added StoreClaimOffer command<commit_after>extern crate serde_json;
extern crate uuid;

use self::uuid::Uuid;
use errors::anoncreds::AnoncredsError;
use services::crypto::CryptoService;
use services::pool::PoolService;
use services::wallet::WalletService;
use std::rc::Rc;

pub enum ProverCommand {
    StoreClaimOffer(
        i32, // wallet handle
        String, // claim offer json
        Box<Fn(Result<(), AnoncredsError>) + Send>),
    GetClaimOffers(
        i32, // wallet handle
        String, // filter json
        Box<Fn(Result<String, AnoncredsError>) + Send>),
    CreateMasterSecret(
        i32, // wallet handle
        String, // master secret name
        Box<Fn(Result<(), AnoncredsError>) + Send>),
    CreateAndStoreClaimRequest(
        i32, // wallet handle
        String, // claim offer json
        String, // claim def json
        String, // master secret name
        Box<Fn(Result<String, AnoncredsError>) + Send>),
    StoreClaim(
        i32, // wallet handle
        String, // claims json
        Box<Fn(Result<(), AnoncredsError>) + Send>),
    GetClaims(
        i32, // wallet handle
        String, // filter json
        Box<Fn(Result<String, AnoncredsError>) + Send>),
    GetClaimsForProofReq(
        i32, // wallet handle
        String, // proof request json
        Box<Fn(Result<String, AnoncredsError>) + Send>),
    CreateProof(
        i32, // wallet handle
        String, // proof request json
        String, // requested claims json
        String, // schemas json
        String, // claim defs json
        String, // revoc regs json
        Box<Fn(Result<String, AnoncredsError>) + Send>),
}

pub struct ProverCommandExecutor {
    crypto_service: Rc<CryptoService>,
    pool_service: Rc<PoolService>,
    wallet_service: Rc<WalletService>
}

impl ProverCommandExecutor {
    pub fn new(crypto_service: Rc<CryptoService>,
               pool_service: Rc<PoolService>,
               wallet_service: Rc<WalletService>) -> ProverCommandExecutor {
        ProverCommandExecutor {
            crypto_service: crypto_service,
            pool_service: pool_service,
            wallet_service: wallet_service,
        }
    }

    pub fn execute(&self, command: ProverCommand) {
        match command {
            ProverCommand::StoreClaimOffer(wallet_handle, claim_offer_json, cb) => {
                info!(target: "prover_command_executor", "StoreClaimOffer command received");
                self.store_claim_offer(wallet_handle, &claim_offer_json, cb);
            },
            ProverCommand::GetClaimOffers(wallet_handle, filter_json, cb) => {
                info!(target: "prover_command_executor", "GetClaimOffers command received");
                self.get_claim_offers(wallet_handle, &filter_json, cb);
            },
            ProverCommand::CreateMasterSecret(wallet_handle, master_secret_name, cb) => {
                info!(target: "prover_command_executor", "CreateMasterSecret command received");
                self.create_master_secret(wallet_handle, &master_secret_name, cb);
            },
            ProverCommand::CreateAndStoreClaimRequest(wallet_handle, claim_offer_json,
                                                      claim_def_json, master_secret_name, cb) => {
                info!(target: "prover_command_executor", "CreateAndStoreClaimRequest command received");
                self.create_and_store_claim_request(wallet_handle, &claim_offer_json,
                                                    &claim_def_json, &master_secret_name, cb);
            },
            ProverCommand::StoreClaim(wallet_handle, claims_json, cb) => {
                info!(target: "prover_command_executor", "StoreClaim command received");
                self.store_claim(wallet_handle, &claims_json, cb);
            },
            ProverCommand::GetClaims(wallet_handle, filter_json, cb) => {
                info!(target: "prover_command_executor", "GetClaims command received");
                self.get_claims(wallet_handle, &filter_json, cb);
            },
            ProverCommand::GetClaimsForProofReq(wallet_handle, proof_req_json, cb) => {
                info!(target: "prover_command_executor", "GetClaimsForProofReq command received");
                self.get_claims_for_proof_req(wallet_handle, &proof_req_json, cb);
            },
            ProverCommand::CreateProof(wallet_handle, proof_req_json, requested_claims_json, schemas_jsons,
                                       claim_def_jsons, revoc_regs_jsons, cb) => {
                info!(target: "prover_command_executor", "CreateProof command received");
                self.create_proof(wallet_handle, &proof_req_json, &requested_claims_json, &schemas_jsons,
                                  &claim_def_jsons, &revoc_regs_jsons, cb);
            }
        };
    }

    fn store_claim_offer(&self,
                         wallet_handle: i32,
                         claim_offer_json: &str,
                         cb: Box<Fn(Result<(), AnoncredsError>) + Send>) {
        cb(self._store_claim_offer(wallet_handle, claim_offer_json));
    }

    fn _store_claim_offer(&self, wallet_handle: i32,  claim_offer_json: &str) -> Result<(), AnoncredsError> {
        let uuid = Uuid::new_v4().to_string();
        self.wallet_service.set(wallet_handle, &format!("claim_offer_json::{}", &uuid), &claim_offer_json)?;

        Ok(())
    }

    fn get_claim_offers(&self,
                        wallet_handle: i32,
                        filter_json: &str,
                        cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        unimplemented!();
//        let result =
//            serde_json::from_str(&filter_json)
//                .map_err(|err| AnoncredsError::CryptoError(CryptoError::InvalidStructure(err.to_string())))
//                .and_then(|filter: Value| {
//                    let claim_offers =
//                        self.wallet_service.get(wallet_handle, &format!("claim_offer {}", &filter["issuer_did"]))?; //TODO LIST METHOD
//
//                    Ok((claim_offers))
//                });
//
//        match result {
//            Ok(claim_offers) => cb(Ok(claim_offers)),
//            Err(err) => cb(Err(err))
//        }
    }

    fn create_master_secret(&self,
                            wallet_handle: i32,
                            master_secret_name: &str,
                            cb: Box<Fn(Result<(), AnoncredsError>) + Send>) {
        unimplemented!();
//        let result =
//            self.crypto_service.anoncreds.prover.generate_master_secret()
//                .map_err(|err| AnoncredsError::CryptoError(CryptoError::InvalidStructure(err.to_string())))
//                .and_then(|master_secret| {
//                    let master_secret_string = master_secret.to_dec()?;
//
//                    self.wallet_service.set(wallet_handle, &format!("master_secret {}", &master_secret_name), &master_secret_string)?;
//
//                    Ok(())
//                });
//
//        match result {
//            Ok(()) => cb(Ok(())),
//            Err(err) => cb(Err(err))
//        }
    }

    fn create_and_store_claim_request(&self,
                                      wallet_handle: i32,
                                      claim_offer_json: &str,
                                      claim_def_json: &str,
                                      master_secret_name: &str,
                                      cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        unimplemented!();
//        let result =
//            ClaimOffer::from_str(&claim_offer_json)
//                .map_err(|err| AnoncredsError::CryptoError(CryptoError::InvalidStructure(err.to_string())))
//                .and_then(|claim_offer| {
//                    let claim_def_json = ClaimDefinition::from_str(&claim_def_json)?;
//
//                    let pk_string = self.wallet_service.get(wallet_handle, &format!("public_key {}", &claim_offer.issuer_did))?;
//                    let pkr_string = self.wallet_service.get(wallet_handle, &format!("public_key_revocation {}", &claim_offer.issuer_did))?;
//                    let ms_string = self.wallet_service.get(wallet_handle,&format!("master_secret {}", master_secret_name))?;
//
//                    let pk = PublicKey::from_str(&pk_string)?;
//                    let pkr = RevocationPublicKey::from_str(&pkr_string)?;
//                    let ms = BigNumber::from_dec(&ms_string)?;
//
//                    let (claim_request, claim_init_data, revocation_claim_init_data) =
//                        self.crypto_service.anoncreds.prover.create_claim_request(pk, pkr, ms, "1".to_string(), true)?;
//
//                    let claim_request_json = ClaimRequest::to_string(&claim_request)?;
//                    let claim_init_data_json = ClaimRequest::to_string(&claim_request);
//                    let revocation_claim_init_data_json = ClaimRequest::to_string(&claim_request)?;
//
//                    Ok(claim_request_json)
//                });
//
//        match result {
//            Ok(claim_request_json) => cb(Ok(claim_request_json)),
//            Err(err) => cb(Err(err))
//        }
    }

    fn store_claim(&self,
                   wallet_handle: i32,
                   claims_json: &str,
                   cb: Box<Fn(Result<(), AnoncredsError>) + Send>) {
        cb(Ok(()));
    }

    fn get_claims(&self,
                  wallet_handle: i32,
                  filter_json: &str,
                  cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        cb(Ok("".to_string()));
    }

    fn get_claims_for_proof_req(&self,
                                wallet_handle: i32,
                                proof_req_json: &str,
                                cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        cb(Ok("".to_string()));
    }

    fn parse_proof_request(&self,
                           wallet_handle: i32,
                           proof_request_json: &str,
                           cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        cb(Ok("".to_string()));
    }

    fn create_proof(&self,
                    wallet_handle: i32,
                    proof_req_json: &str,
                    requested_claims_json: &str,
                    schemas_jsons: &str,
                    claim_def_jsons: &str,
                    revoc_regs_jsons: &str,
                    cb: Box<Fn(Result<String, AnoncredsError>) + Send>) {
        cb(Ok("".to_string()));
    }
}<|endoftext|>


<commit_before>use crate::{
    compiler::{hir_to_lir::HirToLir, lir::Lir},
    database::Database,
    input::{Input, InputDb},
};

pub trait UseProvider {
    fn use_asset(&self, input: Input) -> Result<Vec<u8>, String>;
    fn use_local_module(&self, input: Input) -> Option<Lir>;
}

pub struct DbUseProvider<'a> {
    pub db: &'a Database,
}
impl<'a> UseProvider for DbUseProvider<'a> {
    fn use_asset(&self, input: Input) -> Result<Vec<u8>, String> {
        self.db
            .get_input(input.clone())
            .map(|bytes| (*bytes).clone())
            .ok_or_else(|| format!("Couldn't import file '{}'.", input))
    }

    fn use_local_module(&self, input: Input) -> Option<Lir> {
        self.db.lir(input).map(|lir| (*lir).clone())
    }
}

pub struct FunctionUseProvider<'a, U1, U2>
where
    U1: Fn(Input) -> Result<Vec<u8>, String>,
    U2: Fn(Input) -> Option<Lir>,
{
    pub use_asset: &'a U1,
    pub use_local_module: &'a U2,
}
impl<'a, U1, U2> UseProvider for FunctionUseProvider<'a, U1, U2>
where
    U1: Fn(Input) -> Result<Vec<u8>, String>,
    U2: Fn(Input) -> Option<Lir>,
{
    fn use_asset(&self, input: Input) -> Result<Vec<u8>, String> {
        (self.use_asset)(input)
    }

    fn use_local_module(&self, input: Input) -> Option<Lir> {
        (self.use_local_module)(input)
    }
}
<commit_msg>Remove FunctionUseProvider<commit_after>use crate::{
    compiler::{hir_to_lir::HirToLir, lir::Lir},
    database::Database,
    input::{Input, InputDb},
};

pub trait UseProvider {
    fn use_asset(&self, input: Input) -> Result<Vec<u8>, String>;
    fn use_local_module(&self, input: Input) -> Option<Lir>;
}

pub struct DbUseProvider<'a> {
    pub db: &'a Database,
}
impl<'a> UseProvider for DbUseProvider<'a> {
    fn use_asset(&self, input: Input) -> Result<Vec<u8>, String> {
        self.db
            .get_input(input.clone())
            .map(|bytes| (*bytes).clone())
            .ok_or_else(|| format!("Couldn't import file '{}'.", input))
    }

    fn use_local_module(&self, input: Input) -> Option<Lir> {
        self.db.lir(input).map(|lir| (*lir).clone())
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate itertools;

use itertools::Itertools;
use std::collections::HashSet;

#[derive(Debug, PartialEq, Clone, Copy, Hash, Eq)]
enum ItemType {
    Generator,
    Microchip,
}

#[derive(Debug, Clone, PartialEq, Hash, Eq)]
struct Item {
    what: ItemType,
    compatible: &'static str,
    floor: u32,
}

impl Item {
    fn new(what: ItemType, compatible: &'static str, floor: u32) -> Item {
        Item {
            what: what,
            compatible: compatible,
            floor: floor,
        }
    }
}

fn valid_floor(items: &[&Item]) -> bool {
    let generators = items.iter()
        .filter(|&item| item.what == ItemType::Generator)
        .map(|item| item.compatible)
        .collect::<HashSet<_>>();
    if generators.is_empty() {
        return true;
    }

    let chips = items.iter()
        .filter(|&item| item.what == ItemType::Microchip)
        .map(|item| item.compatible)
        .collect::<HashSet<_>>();
    if chips.is_empty() {
        return true;
    }

    chips.is_subset(&generators)
}

fn valid_layout(items: &Vec<Item>) -> bool {
    [0, 1, 2, 3]
        .iter()
        .all(|&i| valid_floor(&items.iter().filter(|&item| item.floor == i).collect::<Vec<_>>()))
}

fn done(items: &Vec<Item>) -> bool {
    items.iter().all(|i| i.floor == 3)
}

fn steps(current_floor: u32, layout: &Vec<Item>) -> Vec<(Vec<Item>, u32)> {
    let mut possible_layouts = Vec::new();

    // items on current floor
    let items = layout.iter()
        .enumerate()
        .filter(|&(_, ref item)| item.floor == current_floor)
        .collect::<Vec<_>>();

    // possible single item moves
    for &(i, _) in &items {
        // down
        if current_floor != 0 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if i == j {
                    Item::new(item.what, item.compatible, item.floor - 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor - 1));
            }
        }

        // up
        if current_floor != 3 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if i == j {
                    Item::new(item.what, item.compatible, item.floor + 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor + 1));
            }
        }
    }

    // possible double moves
    for (i1, i2) in items.iter().tuple_combinations() {
        let &(i1, _) = i1;
        let &(i2, _) = i2;
        if current_floor != 3 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if j == i1 || j == i2 {
                    Item::new(item.what, item.compatible, item.floor + 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor + 1));
            }
        }

        if current_floor != 0 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if j == i1 || j == i2 {
                    Item::new(item.what, item.compatible, item.floor - 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor - 1));
            }
        }
    }

    possible_layouts
}

fn main() {
    use ItemType::*;

    // puzzle input state
    let start_layout = vec![Item::new(Generator, "polonium", 0),
                            Item::new(Generator, "thulium", 0),
                            Item::new(Microchip, "thulium", 0),
                            Item::new(Generator, "promethium", 0),
                            Item::new(Generator, "ruthenium", 0),
                            Item::new(Microchip, "ruthenium", 0),
                            Item::new(Generator, "cobalt", 0),
                            Item::new(Microchip, "cobalt", 0),
                            Item::new(Microchip, "polonium", 1),
                            Item::new(Microchip, "promethium", 1)];

    let mut layouts = steps(0, &start_layout);
    let mut cache: HashSet<(Vec<Item>, u32)> = HashSet::new();
    cache.insert((start_layout, 0));
    let mut stepcount = 1;
    loop {
        stepcount += 1;
        let mut next = Vec::new();
        for (layout, floor) in layouts {
            let new_steps = steps(floor, &layout);
            for new_layout in new_steps {
                if done(&new_layout.0) {
                    println!("part 1: {}", stepcount);
                    std::process::exit(0);
                }
                if !cache.contains(&new_layout) {
                    cache.insert(new_layout.clone());
                    next.push(new_layout);
                }
            }
        }
        layouts = next;
    }
}
<commit_msg>rust day11 part 2<commit_after>#[macro_use]
extern crate itertools;

use itertools::Itertools;
use std::collections::HashSet;

#[derive(Debug, PartialEq, Clone, Copy, Hash, Eq)]
enum ItemType {
    Generator,
    Microchip,
}

#[derive(Debug, Clone, PartialEq, Hash, Eq)]
struct Item {
    what: ItemType,
    compatible: &'static str,
    floor: u32,
}

impl Item {
    fn new(what: ItemType, compatible: &'static str, floor: u32) -> Item {
        Item {
            what: what,
            compatible: compatible,
            floor: floor,
        }
    }
}

fn valid_floor(items: &[&Item]) -> bool {
    let generators = items.iter()
        .filter(|&item| item.what == ItemType::Generator)
        .map(|item| item.compatible)
        .collect::<HashSet<_>>();
    if generators.is_empty() {
        return true;
    }

    let chips = items.iter()
        .filter(|&item| item.what == ItemType::Microchip)
        .map(|item| item.compatible)
        .collect::<HashSet<_>>();
    if chips.is_empty() {
        return true;
    }

    chips.is_subset(&generators)
}

fn valid_layout(items: &Vec<Item>) -> bool {
    [0, 1, 2, 3]
        .iter()
        .all(|&i| valid_floor(&items.iter().filter(|&item| item.floor == i).collect::<Vec<_>>()))
}

fn done(items: &Vec<Item>) -> bool {
    items.iter().all(|i| i.floor == 3)
}

fn steps(current_floor: u32, layout: &Vec<Item>) -> Vec<(Vec<Item>, u32)> {
    let mut possible_layouts = Vec::new();

    // items on current floor
    let items = layout.iter()
        .enumerate()
        .filter(|&(_, ref item)| item.floor == current_floor)
        .collect::<Vec<_>>();

    // possible single item moves
    for &(i, _) in &items {
        // down
        if current_floor != 0 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if i == j {
                    Item::new(item.what, item.compatible, item.floor - 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor - 1));
            }
        }

        // up
        if current_floor != 3 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if i == j {
                    Item::new(item.what, item.compatible, item.floor + 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor + 1));
            }
        }
    }

    // possible double moves
    for (i1, i2) in items.iter().tuple_combinations() {
        let &(i1, _) = i1;
        let &(i2, _) = i2;
        if current_floor != 3 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if j == i1 || j == i2 {
                    Item::new(item.what, item.compatible, item.floor + 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor + 1));
            }
        }

        if current_floor != 0 {
            let new = layout.iter()
                .enumerate()
                .map(|(j, ref item)| if j == i1 || j == i2 {
                    Item::new(item.what, item.compatible, item.floor - 1)
                } else {
                    Item::new(item.what, item.compatible, item.floor)
                })
                .collect::<Vec<Item>>();
            if valid_layout(&new) {
                possible_layouts.push((new, current_floor - 1));
            }
        }
    }

    possible_layouts
}

fn solve(start_layout: Vec<Item>) {
    let mut layouts = steps(0, &start_layout);
    let mut cache: HashSet<(Vec<Item>, u32)> = HashSet::new();
    cache.insert((start_layout, 0));
    let mut stepcount = 1;
    loop {
        stepcount += 1;
        let mut next = Vec::new();
        for (layout, floor) in layouts {
            let new_steps = steps(floor, &layout);
            for new_layout in new_steps {
                if done(&new_layout.0) {
                    println!("result: {}", stepcount);
                    return;
                }
                if !cache.contains(&new_layout) {
                    cache.insert(new_layout.clone());
                    next.push(new_layout);
                }
            }
        }
        layouts = next;
    }
}

fn main() {
    use ItemType::*;

    let part1_layout = vec![Item::new(Generator, "polonium", 0),
                            Item::new(Generator, "thulium", 0),
                            Item::new(Microchip, "thulium", 0),
                            Item::new(Generator, "promethium", 0),
                            Item::new(Generator, "ruthenium", 0),
                            Item::new(Microchip, "ruthenium", 0),
                            Item::new(Generator, "cobalt", 0),
                            Item::new(Microchip, "cobalt", 0),
                            Item::new(Microchip, "polonium", 1),
                            Item::new(Microchip, "promethium", 1)];

    let part2_layout = vec![Item::new(Generator, "polonium", 0),
                            Item::new(Generator, "thulium", 0),
                            Item::new(Microchip, "thulium", 0),
                            Item::new(Generator, "promethium", 0),
                            Item::new(Generator, "ruthenium", 0),
                            Item::new(Microchip, "ruthenium", 0),
                            Item::new(Generator, "cobalt", 0),
                            Item::new(Microchip, "cobalt", 0),
                            Item::new(Microchip, "elerium", 0),
                            Item::new(Generator, "elerium", 0),
                            Item::new(Microchip, "dilithium", 0),
                            Item::new(Generator, "dilithium", 0),
                            Item::new(Microchip, "polonium", 1),
                            Item::new(Microchip, "promethium", 1)];
    //solve(part1_layout);
    solve(part2_layout);
}
<|endoftext|>


<commit_before>use cairo;
use cairo::surface::CairoSurface;
use core::slice;
use os::{OSMem, Result, SharedMem};

pub enum Buffer {
    OSMem(OSMem),
    SharedMem(SharedMem),
    Ptr(*mut u8),
}

pub struct FrameBuffer {
    pub width: f64,
    pub height: f64,
    pub buffer: Buffer,
}

fn byte_len(width: f64, height: f64) -> usize {
    let width = (width + 0.5) as u16;
    let height = (height + 0.5) as u16;
    let stride = cairo::stride_for_width(cairo::bindings::CAIRO_FORMAT_ARGB32, width);
    stride * height as usize
}

impl FrameBuffer {
    pub fn from_os_mem(width: f64, height: f64, os_mem: OSMem) -> Self {
        Self {
            width,
            height,
            buffer: Buffer::OSMem(os_mem),
        }
    }

    pub fn from_shared_mem(width: f64, height: f64, mut shared_mem: SharedMem) -> Result<Self> {
        let len = byte_len(width, height);
        shared_mem.resize(len)?;

        Ok(Self {
            width,
            height,
            buffer: Buffer::SharedMem(shared_mem),
        })
    }

    pub unsafe fn from_ptr(width: f64, height: f64, ptr: *mut u8) -> Self {
        Self {
            width,
            height,
            buffer: Buffer::Ptr(ptr),
        }
    }

    pub fn resize(&mut self, width: f64, height: f64) -> Result<()> {
        let len = byte_len(width, height);
        match &mut self.buffer {
            Buffer::OSMem(_) => panic!("can't resize OSMem"),
            Buffer::SharedMem(shared_mem) => shared_mem.resize(len)?,
            Buffer::Ptr(_) => panic!("can't resize Ptr"),
        }

        self.width = width;
        self.height = height;
        Ok(())
    }

    pub fn width_i(&self) -> u16 {
        (self.width + 0.5) as u16
    }

    pub fn height_i(&self) -> u16 {
        (self.height + 0.5) as u16
    }

    pub fn stride(&self) -> usize {
        cairo::stride_for_width(cairo::bindings::CAIRO_FORMAT_ARGB32, self.width_i())
    }

    pub fn as_mut_slice(&mut self) -> &mut [u8] {
        let height = self.height_i();
        let stride = self.stride();

        match self.buffer {
            Buffer::OSMem(ref mut os_mem) => &mut *os_mem,
            Buffer::SharedMem(ref mut shared_mem) => &mut *shared_mem,
            Buffer::Ptr(ptr) => {
                let len = stride * height as usize;
                unsafe { slice::from_raw_parts_mut(ptr, len) }
            }
        }
    }

    pub fn as_surface(&mut self) -> CairoSurface {
        let width = self.width_i();
        let height = self.height_i();
        let stride = self.stride();
        let data = self.as_mut_slice();
        CairoSurface::from_slice(data, cairo::bindings::CAIRO_FORMAT_ARGB32, width, height, stride)
    }
}
<commit_msg>Remove alpha channel on client frame buffers<commit_after>use cairo;
use cairo::surface::CairoSurface;
use core::slice;
use os::{OSMem, Result, SharedMem};

pub enum Buffer {
    OSMem(OSMem),
    SharedMem(SharedMem),
    Ptr(*mut u8),
}

pub struct FrameBuffer {
    pub width: f64,
    pub height: f64,
    pub buffer: Buffer,
}

fn byte_len(width: f64, height: f64) -> usize {
    let width = (width + 0.5) as u16;
    let height = (height + 0.5) as u16;
    let stride = cairo::stride_for_width(cairo::bindings::CAIRO_FORMAT_ARGB32, width);
    stride * height as usize
}

impl FrameBuffer {
    pub fn from_os_mem(width: f64, height: f64, os_mem: OSMem) -> Self {
        Self {
            width,
            height,
            buffer: Buffer::OSMem(os_mem),
        }
    }

    pub fn from_shared_mem(width: f64, height: f64, mut shared_mem: SharedMem) -> Result<Self> {
        let len = byte_len(width, height);
        shared_mem.resize(len)?;

        Ok(Self {
            width,
            height,
            buffer: Buffer::SharedMem(shared_mem),
        })
    }

    pub unsafe fn from_ptr(width: f64, height: f64, ptr: *mut u8) -> Self {
        Self {
            width,
            height,
            buffer: Buffer::Ptr(ptr),
        }
    }

    pub fn resize(&mut self, width: f64, height: f64) -> Result<()> {
        let len = byte_len(width, height);
        match &mut self.buffer {
            Buffer::OSMem(_) => panic!("can't resize OSMem"),
            Buffer::SharedMem(shared_mem) => shared_mem.resize(len)?,
            Buffer::Ptr(_) => panic!("can't resize Ptr"),
        }

        self.width = width;
        self.height = height;
        Ok(())
    }

    pub fn width_i(&self) -> u16 {
        (self.width + 0.5) as u16
    }

    pub fn height_i(&self) -> u16 {
        (self.height + 0.5) as u16
    }

    pub fn stride(&self) -> usize {
        cairo::stride_for_width(cairo::bindings::CAIRO_FORMAT_ARGB32, self.width_i())
    }

    pub fn as_mut_slice(&mut self) -> &mut [u8] {
        let height = self.height_i();
        let stride = self.stride();

        match self.buffer {
            Buffer::OSMem(ref mut os_mem) => &mut *os_mem,
            Buffer::SharedMem(ref mut shared_mem) => &mut *shared_mem,
            Buffer::Ptr(ptr) => {
                let len = stride * height as usize;
                unsafe { slice::from_raw_parts_mut(ptr, len) }
            }
        }
    }

    pub fn as_surface(&mut self) -> CairoSurface {
        let width = self.width_i();
        let height = self.height_i();
        let stride = self.stride();
        let data = self.as_mut_slice();
        CairoSurface::from_slice(data, cairo::bindings::CAIRO_FORMAT_RGB24, width, height, stride)
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::collections::{BTreeMap, HashMap};
use itertools::free::join;
use ast::{Type, FunctionSignature};
use bytecode::llinstruction::LLInstruction;

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Var
{
    pub name: String,
    pub typ: Type,
}

impl Var
{
    pub fn new(idx: usize, typ: Type) -> Var
    {
        Var{
            name: format!("$var{}", idx),
            typ: typ,
        }
    }

    pub fn named(name: &str, typ: Type) -> Var
    {
        Var{
            name: name.into(),
            typ: typ,
        }
    }
}

impl fmt::Display for Var
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        write!(f, "({}: {})", self.name, self.typ)
    }
}

#[derive(Debug)]
pub struct Scope
{
    named_vars: HashMap<String, Var>,
    to_dec_ref: Vec<Var>,
}

impl Scope
{
    pub fn new() -> Scope
    {
        Scope{
            named_vars: HashMap::new(),
            to_dec_ref: Vec::new(),
        }
    }

    pub fn add_named_var(&mut self, var: Var)
    {
        self.named_vars.insert(var.name.clone(), var);
    }

    pub fn add_dec_ref_target(&mut self, v: &Var) -> bool
    {
        if self.named_vars.get(&v.name).is_none() {
            false
        } else {
            self.to_dec_ref.push(v.clone());
            true
        }
    }

    pub fn remove_dec_ref_target(&mut self, v: &Var) -> bool
    {
        let len = self.to_dec_ref.len();
        self.to_dec_ref.retain(|e| e != v);
        self.to_dec_ref.len() < len
    }

    pub fn cleanup(&self, func: &mut LLFunction)
    {
        // Cleanup in reverse construction order
        for v in self.to_dec_ref.iter().rev() {
            func.add(LLInstruction::DecRef(v.clone()));
        }
    }
}

pub type BasicBlockRef = usize;

pub fn bb_name(bb: BasicBlockRef) -> String
{
    if bb == 0 {
        "entry".into()
    } else {
        format!("block{}", bb)
    }
}

#[derive(Debug)]
pub struct LLBasicBlock
{
    pub name: String,
    pub instructions: Vec<LLInstruction>
}

impl LLBasicBlock
{
    pub fn new(name: String) -> LLBasicBlock
    {
        LLBasicBlock{
            name: name,
            instructions: Vec::new(),
        }
    }
}

#[derive(Debug)]
pub struct LLFunction
{
    pub sig: FunctionSignature,
    pub blocks: BTreeMap<BasicBlockRef, LLBasicBlock>,
    pub block_order: Vec<BasicBlockRef>,
    pub lambdas: Vec<LLFunction>,
    current_bb: usize,
    bb_counter: usize,
    var_counter: usize,
    scopes: Vec<Scope>,
    destinations: Vec<Option<Var>>,
}

impl LLFunction
{
    pub fn new(sig: &FunctionSignature) -> LLFunction
    {
        let mut f = LLFunction{
            sig: sig.clone(),
            blocks: BTreeMap::new(),
            block_order: Vec::new(),
            lambdas: Vec::new(),
            current_bb: 0,
            bb_counter: 0,
            var_counter: 0,
            scopes: vec![Scope::new()],
            destinations: Vec::new(),
        };

        let entry = f.create_basic_block();
        f.add_basic_block(entry);

        for arg in &sig.args {
            f.add_named_var(Var::named(&arg.name, arg.typ.clone()));
        }
        f
    }

    pub fn is_empty(&self) -> bool
    {
        self.blocks.get(&0).map(|bb| bb.instructions.is_empty()).unwrap_or(false)
    }

    pub fn add(&mut self, inst: LLInstruction)
    {
        // Pop final scope before returning
        match inst
        {
            LLInstruction::Return(_) => self.pop_scope(),
            _ => (),
        }

        let idx = self.current_bb;
        self.blocks.get_mut(&idx).map(|bb| bb.instructions.push(inst));
    }

    pub fn create_basic_block(&mut self) -> BasicBlockRef
    {
        let bb_ref = self.bb_counter;
        self.bb_counter += 1;
        let name = bb_name(bb_ref);
        self.blocks.insert(bb_ref, LLBasicBlock::new(name));
        bb_ref
    }

    pub fn add_basic_block(&mut self, bb_ref: BasicBlockRef)
    {
        self.block_order.push(bb_ref);
    }

    pub fn set_current_bb(&mut self, bb_ref: BasicBlockRef)
    {
        assert!(bb_ref < self.blocks.len());
        self.current_bb = bb_ref;
    }

    pub fn new_var(&mut self, typ: Type) -> Var
    {
        let idx = self.var_counter;
        self.var_counter += 1;
        let v = Var::new(idx, typ);
        self.add_named_var(v.clone());
        v
    }

    pub fn push_scope(&mut self)
    {
        self.scopes.push(Scope::new());
        self.add(LLInstruction::StartScope);
    }

    pub fn pop_scope(&mut self)
    {
        let s = self.scopes.pop().expect("Empty Scope Stack");
        s.cleanup(self);
        if !self.scopes.is_empty() {
            // Add an endscope instruction, but not at function exit
            self.add(LLInstruction::EndScope);
        }
    }

    pub fn push_destination(&mut self, var: Option<Var>)
    {
        self.destinations.push(var);
    }

    pub fn pop_destination(&mut self)
    {
        let _ = self.destinations.pop();
    }

    pub fn get_destination(&self) -> Option<Var>
    {
        match self.destinations.last() {
            Some(&Some(ref var)) => Some(var.clone()),
            _ => None
        }
    }

    pub fn add_named_var(&mut self, var: Var)
    {
        let scope = self.scopes.last_mut().expect("Empty Scope Stack");
        scope.add_named_var(var);
    }

    pub fn add_dec_ref_target(&mut self, v: &Var)
    {
        for scope in self.scopes.iter_mut().rev() {
            if scope.add_dec_ref_target(v) {
                break;
            }
        }
    }

    pub fn remove_dec_ref_target(&mut self, v: &Var) -> bool
    {
        let scope = self.scopes.last_mut().expect("Empty Scope Stack");
        scope.remove_dec_ref_target(v)
    }
}

impl fmt::Display for LLFunction
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        for lambda in &self.lambdas {
            lambda.fmt(f)?;
            writeln!(f, "")?;
        }

        writeln!(f, "{}({}) -> {}:",
            self.sig.name,
            join(self.sig.args.iter().map(|arg| format!("{}: {}", arg.name, arg.typ)), ", "),
            self.sig.return_type)?;
        for bb_ref in &self.block_order {
            let bb = self.blocks.get(bb_ref).expect("Unknown basic block");
            writeln!(f, " {}:", bb.name)?;
            for inst in &bb.instructions {
                inst.fmt(f)?;
            }
        }

        Ok(())
    }
}
<commit_msg>LLBasicBlock -> BasicBlock<commit_after>use std::fmt;
use std::collections::{BTreeMap, HashMap};
use itertools::free::join;
use ast::{Type, FunctionSignature};
use bytecode::llinstruction::LLInstruction;

#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Var
{
    pub name: String,
    pub typ: Type,
}

impl Var
{
    pub fn new(idx: usize, typ: Type) -> Var
    {
        Var{
            name: format!("$var{}", idx),
            typ: typ,
        }
    }

    pub fn named(name: &str, typ: Type) -> Var
    {
        Var{
            name: name.into(),
            typ: typ,
        }
    }
}

impl fmt::Display for Var
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        write!(f, "({}: {})", self.name, self.typ)
    }
}

#[derive(Debug)]
pub struct Scope
{
    named_vars: HashMap<String, Var>,
    to_dec_ref: Vec<Var>,
}

impl Scope
{
    pub fn new() -> Scope
    {
        Scope{
            named_vars: HashMap::new(),
            to_dec_ref: Vec::new(),
        }
    }

    pub fn add_named_var(&mut self, var: Var)
    {
        self.named_vars.insert(var.name.clone(), var);
    }

    pub fn add_dec_ref_target(&mut self, v: &Var) -> bool
    {
        if self.named_vars.get(&v.name).is_none() {
            false
        } else {
            self.to_dec_ref.push(v.clone());
            true
        }
    }

    pub fn remove_dec_ref_target(&mut self, v: &Var) -> bool
    {
        let len = self.to_dec_ref.len();
        self.to_dec_ref.retain(|e| e != v);
        self.to_dec_ref.len() < len
    }

    pub fn cleanup(&self, func: &mut LLFunction)
    {
        // Cleanup in reverse construction order
        for v in self.to_dec_ref.iter().rev() {
            func.add(LLInstruction::DecRef(v.clone()));
        }
    }
}

pub type BasicBlockRef = usize;

pub fn bb_name(bb: BasicBlockRef) -> String
{
    if bb == 0 {
        "entry".into()
    } else {
        format!("block{}", bb)
    }
}

#[derive(Debug)]
pub struct BasicBlock
{
    pub name: String,
    pub instructions: Vec<LLInstruction>
}

impl BasicBlock
{
    pub fn new(name: String) -> BasicBlock
    {
        BasicBlock{
            name: name,
            instructions: Vec::new(),
        }
    }
}

#[derive(Debug)]
pub struct LLFunction
{
    pub sig: FunctionSignature,
    pub blocks: BTreeMap<BasicBlockRef, BasicBlock>,
    pub block_order: Vec<BasicBlockRef>,
    pub lambdas: Vec<LLFunction>,
    current_bb: usize,
    bb_counter: usize,
    var_counter: usize,
    scopes: Vec<Scope>,
    destinations: Vec<Option<Var>>,
}

impl LLFunction
{
    pub fn new(sig: &FunctionSignature) -> LLFunction
    {
        let mut f = LLFunction{
            sig: sig.clone(),
            blocks: BTreeMap::new(),
            block_order: Vec::new(),
            lambdas: Vec::new(),
            current_bb: 0,
            bb_counter: 0,
            var_counter: 0,
            scopes: vec![Scope::new()],
            destinations: Vec::new(),
        };

        let entry = f.create_basic_block();
        f.add_basic_block(entry);

        for arg in &sig.args {
            f.add_named_var(Var::named(&arg.name, arg.typ.clone()));
        }
        f
    }

    pub fn is_empty(&self) -> bool
    {
        self.blocks.get(&0).map(|bb| bb.instructions.is_empty()).unwrap_or(false)
    }

    pub fn add(&mut self, inst: LLInstruction)
    {
        // Pop final scope before returning
        match inst
        {
            LLInstruction::Return(_) => self.pop_scope(),
            _ => (),
        }

        let idx = self.current_bb;
        self.blocks.get_mut(&idx).map(|bb| bb.instructions.push(inst));
    }

    pub fn create_basic_block(&mut self) -> BasicBlockRef
    {
        let bb_ref = self.bb_counter;
        self.bb_counter += 1;
        let name = bb_name(bb_ref);
        self.blocks.insert(bb_ref, BasicBlock::new(name));
        bb_ref
    }

    pub fn add_basic_block(&mut self, bb_ref: BasicBlockRef)
    {
        self.block_order.push(bb_ref);
    }

    pub fn set_current_bb(&mut self, bb_ref: BasicBlockRef)
    {
        assert!(bb_ref < self.blocks.len());
        self.current_bb = bb_ref;
    }

    pub fn new_var(&mut self, typ: Type) -> Var
    {
        let idx = self.var_counter;
        self.var_counter += 1;
        let v = Var::new(idx, typ);
        self.add_named_var(v.clone());
        v
    }

    pub fn push_scope(&mut self)
    {
        self.scopes.push(Scope::new());
        self.add(LLInstruction::StartScope);
    }

    pub fn pop_scope(&mut self)
    {
        let s = self.scopes.pop().expect("Empty Scope Stack");
        s.cleanup(self);
        if !self.scopes.is_empty() {
            // Add an endscope instruction, but not at function exit
            self.add(LLInstruction::EndScope);
        }
    }

    pub fn push_destination(&mut self, var: Option<Var>)
    {
        self.destinations.push(var);
    }

    pub fn pop_destination(&mut self)
    {
        let _ = self.destinations.pop();
    }

    pub fn get_destination(&self) -> Option<Var>
    {
        match self.destinations.last() {
            Some(&Some(ref var)) => Some(var.clone()),
            _ => None
        }
    }

    pub fn add_named_var(&mut self, var: Var)
    {
        let scope = self.scopes.last_mut().expect("Empty Scope Stack");
        scope.add_named_var(var);
    }

    pub fn add_dec_ref_target(&mut self, v: &Var)
    {
        for scope in self.scopes.iter_mut().rev() {
            if scope.add_dec_ref_target(v) {
                break;
            }
        }
    }

    pub fn remove_dec_ref_target(&mut self, v: &Var) -> bool
    {
        let scope = self.scopes.last_mut().expect("Empty Scope Stack");
        scope.remove_dec_ref_target(v)
    }
}

impl fmt::Display for LLFunction
{
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error>
    {
        for lambda in &self.lambdas {
            lambda.fmt(f)?;
            writeln!(f, "")?;
        }

        writeln!(f, "{}({}) -> {}:",
            self.sig.name,
            join(self.sig.args.iter().map(|arg| format!("{}: {}", arg.name, arg.typ)), ", "),
            self.sig.return_type)?;
        for bb_ref in &self.block_order {
            let bb = self.blocks.get(bb_ref).expect("Unknown basic block");
            writeln!(f, " {}:", bb.name)?;
            for inst in &bb.instructions {
                inst.fmt(f)?;
            }
        }

        Ok(())
    }
}
<|endoftext|>