<commit_before>use std::fmt;
use std::vec::Vec;
use std::collections::HashMap;

pub enum Value {
    Null,
    Boolean(bool),
    Integer(i64),
    Float(f64),
    String(String),
    List(Vec<Value>),
    Map(HashMap<String, Value>),
    Structure { signature: u8, fields: Vec<Value> },
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Value::Null => write!(f, "null"),
            &Value::Boolean(ref value) => write!(f, "{:?}", value),
            &Value::Integer(ref value) => write!(f, "{:?}", value),
            &Value::String(ref value) => write!(f, "{:?}", value),
            // TODO
            _ => write!(f, "?"),
        }
    }
}

pub trait Pack {
    fn pack_null(&mut self);
    fn pack_boolean(&mut self, value: bool);
    fn pack_integer(&mut self, value: i64);
    fn pack_string(&mut self, value: &str);
    fn pack_map_header(&mut self, size: usize);
    fn pack_structure_header(&mut self, size: usize, signature: u8);
}

pub struct Packer {
    buffer: Vec<u8>,
}

impl Packer {
    pub fn new() -> Packer {
        Packer { buffer: vec![0u8; 0] }
    }

    pub fn clear(&mut self) {
        self.buffer.clear()
    }

    pub fn len(&self) -> usize {
        self.buffer.len()
    }

    pub fn get_chunk(&mut self, start: usize, end: usize) -> &[u8] {
        &self.buffer[start..end]
    }

    pub fn pack_null(&mut self) {
        let _ = self.write(0xC0);
    }

    pub fn pack_boolean(&mut self, value: bool) {
        if value {
            let _ = self.write_slice(&[0xC3]);
        }
        else {
            let _ = self.write_slice(&[0xC2]);
        }
    }

    pub fn pack_integer(&mut self, value: i64) {
        if -0x10 <= value && value < 0x80 {
            // TINY_INT
            let _ = self.write_slice(&[value as u8]);
        }
        else if -0x80 <= value && value < 0x80 {
            // INT_8
            let _ = self.write_slice(&[0xC8, value as u8]);
        }
        else if -0x8000 <= value && value < 0x8000 {
            // INT_16
            let _ = self.write_slice(&[0xC9, (value >> 8) as u8,
                                        value       as u8]);
        }
        else if -0x80000000 <= value && value < 0x80000000 {
            // INT_32
            let _ = self.write_slice(&[0xCA, (value >> 24) as u8,
                                       (value >> 16) as u8,
                                       (value >> 8)  as u8,
                                        value        as u8]);
        }
        else {
            // INT_64
            let _ = self.write_slice(&[0xCB, (value >> 56) as u8,
                                       (value >> 48) as u8,
                                       (value >> 40) as u8,
                                       (value >> 32) as u8,
                                       (value >> 24) as u8,
                                       (value >> 16) as u8,
                                       (value >> 8)  as u8,
                                        value        as u8]);
        }
    }

    pub fn pack_string(&mut self, value: &str) {
        let size: usize = value.len();
        if size < 0x10 {
            let _ = self.write(0x80 + size as u8);
        }
        else if size < 0x100 {
            let _ = self.write_slice(&[0xD0, size as u8]);
        }
        else if size < 0x10000 {
            let _ = self.write_slice(&[0xD1, (size >> 8) as u8, size as u8]);
        }
        else if size < 0x100000000 {
            let _ = self.write_slice(&[0xD2, (size >> 24) as u8, (size >> 16) as u8,
                                       (size >> 8) as u8, size as u8]);
        }
        else {
            panic!("String too long to pack");
        }
        let _ = self.write_slice(value.as_bytes());
    }

    pub fn pack_map_header(&mut self, size: usize) {
        if size < 0x10 {
            let _ = self.write_slice(&[0xA0 + size as u8]);
        }
        else if size < 0x100 {
            let _ = self.write_slice(&[0xD8, size as u8]);
        }
        else if size < 0x10000 {
            let _ = self.write_slice(&[0xD9, (size >> 8) as u8, size as u8]);
        }
        else if size < 0x100000000 {
            let _ = self.write_slice(&[0xDA, (size >> 24) as u8, (size >> 16) as u8,
                                       (size >> 8) as u8, size as u8]);
        }
        else {
            panic!("Map too big to pack");
        }
    }

    pub fn pack_structure_header(&mut self, size: usize, signature: u8) {
        if size < 0x10 {
            let _ = self.write_slice(&[0xB0 + size as u8, signature]);
        }
        else if size < 0x100 {
            let _ = self.write_slice(&[0xDC, size as u8, signature]);
        }
        else if size < 0x10000 {
            let _ = self.write_slice(&[0xDD, (size >> 8) as u8, size as u8, signature]);
        }
        else {
            panic!("Structure too big to pack");
        }
    }

    fn write(&mut self, byte: u8) {
        let start: usize = self.buffer.len();
        let end: usize = start + 1;
        self.buffer.resize(end, 0);
        self.buffer[start] = byte;
    }

    fn write_slice(&mut self, buf: &[u8]) {
        let start: usize = self.buffer.len();
        let end: usize = start + buf.len();
        self.buffer.resize(end, 0);
        &mut self.buffer[start..end].copy_from_slice(&buf[..]);
    }

}

pub struct Unpacker {
    buffer: Vec<u8>,
    unpack_ptr: usize,
}

impl Unpacker {
    pub fn new() -> Unpacker {
        Unpacker { buffer: vec![0u8; 0], unpack_ptr: 0 }
    }

    pub fn clear(&mut self) {
        self.buffer.clear();
        self.unpack_ptr = 0;
    }

    pub fn buffer(&mut self, size: usize) -> &mut [u8] {
        let start: usize = self.buffer.len();
        let end: usize = start + size;
        self.buffer.resize(end, 0);

        &mut self.buffer[start..end]
    }

    pub fn unpack(&mut self) -> Value {
        let marker = self.unpack_u8();
        match marker {
            0x00...0x7F => Value::Integer(marker as i64),
            0x80...0x8F => self.unpack_string((marker & 0x0F) as usize),
            0x90...0x9F => self.unpack_list((marker & 0x0F) as usize),
            0xA0...0xAF => self.unpack_map((marker & 0x0F) as usize),
            0xB0...0xBF => self.unpack_structure((marker & 0x0F) as usize),
            0xC0 => Value::Null,
            // TODO: C1
            0xC2 => Value::Boolean(false),
            0xC3 => Value::Boolean(true),
            0xD0 => {
                let size: usize = self.unpack_u8() as usize;
                self.unpack_string(size)
            },
            0xF0...0xFF => Value::Integer(marker as i64 - 0x100),
            _ => panic!("Illegal value with marker {:02X}", marker),
        }
    }

    fn unpack_string(&mut self, size: usize) -> Value {
        let end_offset = self.unpack_ptr + size;
        let value = String::from_utf8_lossy(&self.buffer[self.unpack_ptr..end_offset]).into_owned();
        self.unpack_ptr = end_offset;
        Value::String(value)
    }

    fn unpack_list(&mut self, size: usize) -> Value {
        let mut value = Vec::with_capacity(size);
        for _ in 0..size {
            value.push(self.unpack());
        }
        Value::List(value)
    }

    fn unpack_map(&mut self, size: usize) -> Value {
        let mut value = HashMap::with_capacity(size);
        for _ in 0..size {
            let key = self.unpack();
            match key {
                Value::String(k) => {
                    value.insert(k, self.unpack());
                },
                _ => panic!("Key is not a string"),
            }
        }
        Value::Map(value)
    }

    fn unpack_structure(&mut self, size: usize) -> Value {
        let signature: u8 = self.unpack_u8();
        let mut fields: Vec<Value> = vec!();
        for _ in 0..size {
            fields.push(self.unpack());
        }
        Value::Structure { signature: signature, fields: fields }
    }

    fn unpack_u8(&mut self) -> u8 {
        let value: u8 = self.buffer[self.unpack_ptr];
        self.unpack_ptr += 1;
        value
    }

}<commit_msg>Few more types<commit_after>use std::fmt;
use std::vec::Vec;
use std::collections::HashMap;

pub enum Value {
    Null,
    Boolean(bool),
    Integer(i64),
    Float(f64),
    String(String),
    List(Vec<Value>),
    Map(HashMap<String, Value>),
    Structure { signature: u8, fields: Vec<Value> },
}

impl fmt::Debug for Value {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Value::Null => write!(f, "null"),
            &Value::Boolean(ref value) => write!(f, "{:?}", value),
            &Value::Integer(ref value) => write!(f, "{:?}", value),
            &Value::String(ref value) => write!(f, "{:?}", value),
//            &Value::List(ref values) => write!(f, "[{:?}]", values.connect(", ")),
            // TODO
            _ => write!(f, "?"),
        }
    }
}

pub trait Pack {
    fn pack_null(&mut self);
    fn pack_boolean(&mut self, value: bool);
    fn pack_integer(&mut self, value: i64);
    fn pack_string(&mut self, value: &str);
    fn pack_map_header(&mut self, size: usize);
    fn pack_structure_header(&mut self, size: usize, signature: u8);
}

pub struct Packer {
    buffer: Vec<u8>,
}

impl Packer {
    pub fn new() -> Packer {
        Packer { buffer: vec![0u8; 0] }
    }

    pub fn clear(&mut self) {
        self.buffer.clear()
    }

    pub fn len(&self) -> usize {
        self.buffer.len()
    }

    pub fn get_chunk(&mut self, start: usize, end: usize) -> &[u8] {
        &self.buffer[start..end]
    }

    pub fn pack_null(&mut self) {
        let _ = self.write(0xC0);
    }

    pub fn pack_boolean(&mut self, value: bool) {
        if value {
            let _ = self.write_slice(&[0xC3]);
        }
        else {
            let _ = self.write_slice(&[0xC2]);
        }
    }

    pub fn pack_integer(&mut self, value: i64) {
        if -0x10 <= value && value < 0x80 {
            // TINY_INT
            let _ = self.write_slice(&[value as u8]);
        }
        else if -0x80 <= value && value < 0x80 {
            // INT_8
            let _ = self.write_slice(&[0xC8, value as u8]);
        }
        else if -0x8000 <= value && value < 0x8000 {
            // INT_16
            let _ = self.write_slice(&[0xC9, (value >> 8) as u8,
                                        value       as u8]);
        }
        else if -0x80000000 <= value && value < 0x80000000 {
            // INT_32
            let _ = self.write_slice(&[0xCA, (value >> 24) as u8,
                                       (value >> 16) as u8,
                                       (value >> 8)  as u8,
                                        value        as u8]);
        }
        else {
            // INT_64
            let _ = self.write_slice(&[0xCB, (value >> 56) as u8,
                                       (value >> 48) as u8,
                                       (value >> 40) as u8,
                                       (value >> 32) as u8,
                                       (value >> 24) as u8,
                                       (value >> 16) as u8,
                                       (value >> 8)  as u8,
                                        value        as u8]);
        }
    }

    pub fn pack_string(&mut self, value: &str) {
        let size: usize = value.len();
        if size < 0x10 {
            let _ = self.write(0x80 + size as u8);
        }
        else if size < 0x100 {
            let _ = self.write_slice(&[0xD0, size as u8]);
        }
        else if size < 0x10000 {
            let _ = self.write_slice(&[0xD1, (size >> 8) as u8, size as u8]);
        }
        else if size < 0x100000000 {
            let _ = self.write_slice(&[0xD2, (size >> 24) as u8, (size >> 16) as u8,
                                       (size >> 8) as u8, size as u8]);
        }
        else {
            panic!("String too long to pack");
        }
        let _ = self.write_slice(value.as_bytes());
    }

    pub fn pack_map_header(&mut self, size: usize) {
        if size < 0x10 {
            let _ = self.write_slice(&[0xA0 + size as u8]);
        }
        else if size < 0x100 {
            let _ = self.write_slice(&[0xD8, size as u8]);
        }
        else if size < 0x10000 {
            let _ = self.write_slice(&[0xD9, (size >> 8) as u8, size as u8]);
        }
        else if size < 0x100000000 {
            let _ = self.write_slice(&[0xDA, (size >> 24) as u8, (size >> 16) as u8,
                                       (size >> 8) as u8, size as u8]);
        }
        else {
            panic!("Map too big to pack");
        }
    }

    pub fn pack_structure_header(&mut self, size: usize, signature: u8) {
        if size < 0x10 {
            let _ = self.write_slice(&[0xB0 + size as u8, signature]);
        }
        else if size < 0x100 {
            let _ = self.write_slice(&[0xDC, size as u8, signature]);
        }
        else if size < 0x10000 {
            let _ = self.write_slice(&[0xDD, (size >> 8) as u8, size as u8, signature]);
        }
        else {
            panic!("Structure too big to pack");
        }
    }

    fn write(&mut self, byte: u8) {
        let start: usize = self.buffer.len();
        let end: usize = start + 1;
        self.buffer.resize(end, 0);
        self.buffer[start] = byte;
    }

    fn write_slice(&mut self, buf: &[u8]) {
        let start: usize = self.buffer.len();
        let end: usize = start + buf.len();
        self.buffer.resize(end, 0);
        &mut self.buffer[start..end].copy_from_slice(&buf[..]);
    }

}

pub struct Unpacker {
    buffer: Vec<u8>,
    unpack_ptr: usize,
}

impl Unpacker {
    pub fn new() -> Unpacker {
        Unpacker { buffer: vec![0u8; 0], unpack_ptr: 0 }
    }

    pub fn clear(&mut self) {
        self.buffer.clear();
        self.unpack_ptr = 0;
    }

    pub fn buffer(&mut self, size: usize) -> &mut [u8] {
        let start: usize = self.buffer.len();
        let end: usize = start + size;
        self.buffer.resize(end, 0);

        &mut self.buffer[start..end]
    }

    pub fn unpack(&mut self) -> Value {
        let marker = self.unpack_u8();
        match marker {
            0x00...0x7F => Value::Integer(marker as i64),
            0x80...0x8F => self.unpack_string((marker & 0x0F) as usize),
            0x90...0x9F => self.unpack_list((marker & 0x0F) as usize),
            0xA0...0xAF => self.unpack_map((marker & 0x0F) as usize),
            0xB0...0xBF => self.unpack_structure((marker & 0x0F) as usize),
            0xC0 => Value::Null,
            // TODO: C1
            0xC2 => Value::Boolean(false),
            0xC3 => Value::Boolean(true),
            0xC8 => Value::Integer(self.unpack_i8() as i64),
            0xC9 => Value::Integer(self.unpack_i16() as i64),
            0xCA => Value::Integer(self.unpack_i32() as i64),
            0xCB => Value::Integer(self.unpack_i64() as i64),
            0xD0 => {
                let size: usize = self.unpack_u8() as usize;
                self.unpack_string(size)
            },
            0xF0...0xFF => Value::Integer(marker as i64 - 0x100),
            _ => panic!("Illegal value with marker {:02X}", marker),
        }
    }

    fn unpack_string(&mut self, size: usize) -> Value {
        let end_offset = self.unpack_ptr + size;
        let value = String::from_utf8_lossy(&self.buffer[self.unpack_ptr..end_offset]).into_owned();
        self.unpack_ptr = end_offset;
        Value::String(value)
    }

    fn unpack_list(&mut self, size: usize) -> Value {
        let mut value = Vec::with_capacity(size);
        for _ in 0..size {
            value.push(self.unpack());
        }
        Value::List(value)
    }

    fn unpack_map(&mut self, size: usize) -> Value {
        let mut value = HashMap::with_capacity(size);
        for _ in 0..size {
            let key = self.unpack();
            match key {
                Value::String(k) => {
                    value.insert(k, self.unpack());
                },
                _ => panic!("Key is not a string"),
            }
        }
        Value::Map(value)
    }

    fn unpack_structure(&mut self, size: usize) -> Value {
        let signature: u8 = self.unpack_u8();
        let mut fields: Vec<Value> = vec!();
        for _ in 0..size {
            fields.push(self.unpack());
        }
        Value::Structure { signature: signature, fields: fields }
    }

    fn unpack_u8(&mut self) -> u8 {
        let value: u8 = self.buffer[self.unpack_ptr];
        self.unpack_ptr += 1;
        value
    }

    fn unpack_i8(&mut self) -> i8 {
        let value: i8 = self.buffer[self.unpack_ptr] as i8;
        self.unpack_ptr += 1;
        value
    }

    fn unpack_i16(&mut self) -> i16 {
        (self.unpack_i8() as i16) << 8 | self.unpack_u8() as i16
    }

    fn unpack_i32(&mut self) -> i32 {
        (self.unpack_i8() as i32) << 24 |
        (self.unpack_u8() as i32) << 16 |
        (self.unpack_u8() as i32) << 8 |
         self.unpack_u8() as i32
    }

    fn unpack_i64(&mut self) -> i64 {
        (self.unpack_i8() as i64) << 56 |
        (self.unpack_u8() as i64) << 48 |
        (self.unpack_u8() as i64) << 40 |
        (self.unpack_u8() as i64) << 32 |
        (self.unpack_u8() as i64) << 24 |
        (self.unpack_u8() as i64) << 16 |
        (self.unpack_u8() as i64) << 8 |
         self.unpack_u8() as i64
    }

}<|endoftext|>


<commit_before>extern crate fuse;
extern crate threadpool;
extern crate time;

use self::fuse::{Filesystem, Request, ReplyEntry, ReplyAttr, ReplyOpen, ReplyEmpty,
                 ReplyDirectory, ReplyData, ReplyWrite, ReplyCreate, ReplyStatfs};
use self::threadpool::ThreadPool;
use self::time::Timespec;

use std::ffi::OsStr;
use std::ops::Deref;

use catfs::CatFS;

pub struct PCatFS {
    tp: ThreadPool,
    fs: CatFS,
}

impl Drop for PCatFS {
    fn drop(&mut self) {
        self.tp.join();
    }
}

pub fn make_self<T>(s: &mut T) -> &'static mut T {
    return unsafe { ::std::mem::transmute(s) };
}

impl PCatFS {
    pub fn new(fs: CatFS) -> PCatFS {
        PCatFS {
            tp: ThreadPool::new(100),
            fs: fs,
        }
    }
}

impl Deref for PCatFS {
    type Target = CatFS;

    fn deref(&self) -> &CatFS {
        &self.fs
    }
}

macro_rules! run_in_threadpool {
    ($( fn $name:ident(&mut self, _req: &Request, parent: u64, name: &OsStr, $($arg:ident : $argtype:ty),* $(,)*) $body:block )*) => (
        $(
            fn $name(&mut self, _req: &Request, parent: u64, name: &OsStr, $($arg : $argtype),*) {
                let mut s = make_self(self);
                let name = name.to_os_string();
                self.tp.execute(
                    move || {
                        s.fs.$name(parent, name, $($arg),*);
                        debug!("queue size is {}", s.tp.queued_count());
                    }
                );
            }
        )*
    );
    ($( fn $name:ident(&mut self, _req: &Request, $($arg:ident : $argtype:ty),* $(,)*) $body:block )*) => (
        $(
            fn $name(&mut self, _req: &Request, $($arg : $argtype),*) {
                let mut s = make_self(self);
                self.tp.execute(
                    move || {
                        s.fs.$name($($arg),*);
                        debug!("queue size is {}", s.tp.queued_count());
                    }
                );
            }
        )*
    );
}

impl Filesystem for PCatFS {
    fn write(
        &mut self,
        _req: &Request,
        ino: u64,
        fh: u64,
        offset: u64,
        data: &[u8],
        _flags: u32,
        reply: ReplyWrite,
    ) {
        let mut s = make_self(self);
        let data = data.to_vec();
        self.tp.execute(move || {
            s.fs.write(ino, fh, offset, data, _flags, reply);
        });
    }

    fn rename(
        &mut self,
        _req: &Request,
        parent: u64,
        name: &OsStr,
        newparent: u64,
        newname: &OsStr,
        reply: ReplyEmpty,
    ) {
        let mut s = make_self(self);
        let name = name.to_os_string();
        let newname = newname.to_os_string();
        self.tp.execute(move || {
            s.fs.rename(parent, name, newparent, newname, reply);
        });
    }

    run_in_threadpool!{
        fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        }

        fn setattr(
            &mut self,
            _req: &Request,
            ino: u64,
            mode: Option<u32>,
            uid: Option<u32>,
            gid: Option<u32>,
            size: Option<u64>,
            atime: Option<Timespec>,
            mtime: Option<Timespec>,
            fh: Option<u64>,
            crtime: Option<Timespec>,
            chgtime: Option<Timespec>,
            bkuptime: Option<Timespec>,
            flags: Option<u32>,
            reply: ReplyAttr,
        ) {
        }

        fn forget(&mut self, _req: &Request, ino: u64, nlookup: u64) {
        }

        fn opendir(&mut self, _req: &Request, ino: u64, flags: u32, reply: ReplyOpen) {
        }

        fn readdir(
            &mut self,
            _req: &Request,
            _ino: u64,
            dh: u64,
            offset: u64,
            reply: ReplyDirectory,
        ) {
        }

        fn releasedir(&mut self, _req: &Request, _ino: u64, dh: u64, _flags: u32, reply: ReplyEmpty) {
        }

        fn open(&mut self, _req: &Request, ino: u64, flags: u32, reply: ReplyOpen) {
        }

        fn read(
            &mut self,
            _req: &Request,
            _ino: u64,
            fh: u64,
            offset: u64,
            size: u32,
            reply: ReplyData,
        ) {
        }

        fn flush(&mut self, _req: &Request, ino: u64, fh: u64, _lock_owner: u64, reply: ReplyEmpty) {
        }

        fn release(
            &mut self,
            _req: &Request,
            _ino: u64,
            fh: u64,
            _flags: u32,
            _lock_owner: u64,
            _flush: bool,
            reply: ReplyEmpty,
        ) {
        }

        fn statfs(&mut self, _req: &Request, ino: u64, reply: ReplyStatfs) {
        }
    }

    run_in_threadpool!{
        fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) {
        }

        fn create(
            &mut self,
            _req: &Request,
            parent: u64,
            name: &OsStr,
            mode: u32,
            flags: u32,
            reply: ReplyCreate,
        ) {
        }

        fn unlink(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEmpty) {
        }

        fn rmdir(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEmpty) {
        }

        fn mkdir(&mut self, _req: &Request, parent: u64, name: &OsStr, mode: u32, reply: ReplyEntry) {
        }
    }
}
<commit_msg>invoke forget inline instead of in thread<commit_after>extern crate fuse;
extern crate threadpool;
extern crate time;

use self::fuse::{Filesystem, Request, ReplyEntry, ReplyAttr, ReplyOpen, ReplyEmpty,
                 ReplyDirectory, ReplyData, ReplyWrite, ReplyCreate, ReplyStatfs};
use self::threadpool::ThreadPool;
use self::time::Timespec;

use std::ffi::OsStr;
use std::ops::Deref;

use catfs::CatFS;

pub struct PCatFS {
    tp: ThreadPool,
    fs: CatFS,
}

impl Drop for PCatFS {
    fn drop(&mut self) {
        self.tp.join();
    }
}

pub fn make_self<T>(s: &mut T) -> &'static mut T {
    return unsafe { ::std::mem::transmute(s) };
}

impl PCatFS {
    pub fn new(fs: CatFS) -> PCatFS {
        PCatFS {
            tp: ThreadPool::new(100),
            fs: fs,
        }
    }
}

impl Deref for PCatFS {
    type Target = CatFS;

    fn deref(&self) -> &CatFS {
        &self.fs
    }
}

macro_rules! run_in_threadpool {
    ($( fn $name:ident(&mut self, _req: &Request, parent: u64, name: &OsStr, $($arg:ident : $argtype:ty),* $(,)*) $body:block )*) => (
        $(
            fn $name(&mut self, _req: &Request, parent: u64, name: &OsStr, $($arg : $argtype),*) {
                let mut s = make_self(self);
                let name = name.to_os_string();
                self.tp.execute(
                    move || {
                        s.fs.$name(parent, name, $($arg),*);
                        debug!("queue size is {}", s.tp.queued_count());
                    }
                );
            }
        )*
    );
    ($( fn $name:ident(&mut self, _req: &Request, $($arg:ident : $argtype:ty),* $(,)*) $body:block )*) => (
        $(
            fn $name(&mut self, _req: &Request, $($arg : $argtype),*) {
                let mut s = make_self(self);
                self.tp.execute(
                    move || {
                        s.fs.$name($($arg),*);
                        debug!("queue size is {}", s.tp.queued_count());
                    }
                );
            }
        )*
    );
}

impl Filesystem for PCatFS {
    fn write(
        &mut self,
        _req: &Request,
        ino: u64,
        fh: u64,
        offset: u64,
        data: &[u8],
        _flags: u32,
        reply: ReplyWrite,
    ) {
        let mut s = make_self(self);
        let data = data.to_vec();
        self.tp.execute(move || {
            s.fs.write(ino, fh, offset, data, _flags, reply);
        });
    }

    fn rename(
        &mut self,
        _req: &Request,
        parent: u64,
        name: &OsStr,
        newparent: u64,
        newname: &OsStr,
        reply: ReplyEmpty,
    ) {
        let mut s = make_self(self);
        let name = name.to_os_string();
        let newname = newname.to_os_string();
        self.tp.execute(move || {
            s.fs.rename(parent, name, newparent, newname, reply);
        });
    }

    fn forget(&mut self, _req: &Request, ino: u64, nlookup: u64) {
        self.fs.forget(ino, nlookup);
    }

    run_in_threadpool!{
        fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        }

        fn setattr(
            &mut self,
            _req: &Request,
            ino: u64,
            mode: Option<u32>,
            uid: Option<u32>,
            gid: Option<u32>,
            size: Option<u64>,
            atime: Option<Timespec>,
            mtime: Option<Timespec>,
            fh: Option<u64>,
            crtime: Option<Timespec>,
            chgtime: Option<Timespec>,
            bkuptime: Option<Timespec>,
            flags: Option<u32>,
            reply: ReplyAttr,
        ) {
        }

        fn opendir(&mut self, _req: &Request, ino: u64, flags: u32, reply: ReplyOpen) {
        }

        fn readdir(
            &mut self,
            _req: &Request,
            _ino: u64,
            dh: u64,
            offset: u64,
            reply: ReplyDirectory,
        ) {
        }

        fn releasedir(&mut self, _req: &Request, _ino: u64, dh: u64, _flags: u32, reply: ReplyEmpty) {
        }

        fn open(&mut self, _req: &Request, ino: u64, flags: u32, reply: ReplyOpen) {
        }

        fn read(
            &mut self,
            _req: &Request,
            _ino: u64,
            fh: u64,
            offset: u64,
            size: u32,
            reply: ReplyData,
        ) {
        }

        fn flush(&mut self, _req: &Request, ino: u64, fh: u64, _lock_owner: u64, reply: ReplyEmpty) {
        }

        fn release(
            &mut self,
            _req: &Request,
            _ino: u64,
            fh: u64,
            _flags: u32,
            _lock_owner: u64,
            _flush: bool,
            reply: ReplyEmpty,
        ) {
        }

        fn statfs(&mut self, _req: &Request, ino: u64, reply: ReplyStatfs) {
        }
    }

    run_in_threadpool!{
        fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) {
        }

        fn create(
            &mut self,
            _req: &Request,
            parent: u64,
            name: &OsStr,
            mode: u32,
            flags: u32,
            reply: ReplyCreate,
        ) {
        }

        fn unlink(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEmpty) {
        }

        fn rmdir(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEmpty) {
        }

        fn mkdir(&mut self, _req: &Request, parent: u64, name: &OsStr, mode: u32, reply: ReplyEntry) {
        }
    }
}
<|endoftext|>


<commit_before>extern crate brotli2;
extern crate flate2;

use structs::*;
use errors::*;
use std::fs::File;
use std::io::{Read, Write};

use std::path::Path;

impl CompressionFormat for CompressionAlgorithm {
    fn extension(&self) -> &'static str {
        match self {
            &CompressionAlgorithm::Brotli => "br",
            &CompressionAlgorithm::GZip => "gz",
            &CompressionAlgorithm::Zopfli => "gz",
        }
    }
}

impl DefaultFileCompressor for CompressionAlgorithm {
    fn compress(&self, src: &Path, dst: &Path) -> Result<()> {
        match self {
            &CompressionAlgorithm::GZip => gzip_compress(src, dst),
            &CompressionAlgorithm::Brotli => brotli_compress(src, dst),
            _ => bail!("Compression algorithm not implemented!"),
        }
    }
}

fn gzip_compress(src_path: &Path, dst_path: &Path) -> Result<()> {
    let mut src = File::open(src_path)?;
    let dst = File::create(dst_path)?;

    let mut buf = [0u8; 1024];
    let mut encoder = flate2::write::GzEncoder::new(dst, flate2::Compression::Default);
    loop {
        let bytes_read = src.read(&mut buf).chain_err(|| "Error reading from source file!")?;
        match bytes_read {
            0 => break, //end of file
            l => encoder.write_all(&buf[0..l]).chain_err(|| "Fatal gzip encoder error!")?,
        };
    }

    Ok(())
}

fn brotli_compress(src_path: &Path, dst_path: &Path) -> Result<()> {
    let mut src = File::open(src_path)?;
    let dst = File::create(dst_path)?;

    let mut buf = [0u8; 1024];
    let mut encoder = brotli2::write::BrotliEncoder::new(dst, 6);
    loop {
        let bytes_read = src.read(&mut buf).chain_err(|| "Error reading from source file!")?;
        match bytes_read {
            0 => break, //end of file
            l => encoder.write_all(&buf[0..l]).chain_err(|| "Fatal gzip encoder error!")?,
        };
    }

    Ok(())
}
<commit_msg>Zopfli compression support<commit_after>extern crate brotli2;
extern crate flate2;
extern crate zopfli;

use structs::*;
use errors::*;
use std::fs::File;
use std::io::{Read, Write};

use std::path::Path;

impl CompressionFormat for CompressionAlgorithm {
    fn extension(&self) -> &'static str {
        match self {
            &CompressionAlgorithm::Brotli => "br",
            &CompressionAlgorithm::GZip => "gz",
            &CompressionAlgorithm::Zopfli => "gz",
        }
    }
}

impl DefaultFileCompressor for CompressionAlgorithm {
    fn compress(&self, src: &Path, dst: &Path) -> Result<()> {
        match self {
            &CompressionAlgorithm::GZip => gzip_compress(src, dst),
            &CompressionAlgorithm::Brotli => brotli_compress(src, dst),
            &CompressionAlgorithm::Zopfli => zopfli_compress(src, dst),
            // _ => bail!("Compression algorithm not implemented!"),
        }
    }
}

fn gzip_compress(src_path: &Path, dst_path: &Path) -> Result<()> {
    let mut src = File::open(src_path)?;
    let dst = File::create(dst_path)?;

    let mut buf = [0u8; 1024];
    let mut encoder = flate2::write::GzEncoder::new(dst, flate2::Compression::Default);
    loop {
        let bytes_read = src.read(&mut buf).chain_err(|| "Error reading from source file!")?;
        match bytes_read {
            0 => break, //end of file
            l => encoder.write_all(&buf[0..l]).chain_err(|| "Fatal gzip encoder error!")?,
        };
    }

    Ok(())
}

fn brotli_compress(src_path: &Path, dst_path: &Path) -> Result<()> {
    let mut src = File::open(src_path)?;
    let dst = File::create(dst_path)?;

    let mut buf = [0u8; 1024];
    let mut encoder = brotli2::write::BrotliEncoder::new(dst, 6);
    loop {
        let bytes_read = src.read(&mut buf).chain_err(|| "Error reading from source file!")?;
        match bytes_read {
            0 => break, //end of file
            l => encoder.write_all(&buf[0..l]).chain_err(|| "Fatal gzip encoder error!")?,
        };
    }

    Ok(())
}

fn zopfli_compress(src_path: &Path, dst_path: &Path) -> Result<()> {
    let mut src = File::open(src_path)?;
    let mut dst = File::create(dst_path)?;

    let mut src_data = Vec::<u8>::new();
    src.read_to_end(&mut src_data)?;

    zopfli::compress(&zopfli::Options::default(), &zopfli::Format::Gzip, &mut src_data, &mut dst)?;

    Ok(())
}
<|endoftext|>


<commit_before>pub fn clean_string(mut input: String) -> String {
    if input == "" {
        return input;
    }

    input.trim();

    // remove line-comments
    let mut last = '\0';
    let mut len = input.len();
    for (i, c) in input.chars().enumerate() {
        if last == '/' && c == '/' {
            len = i-1;
            break;
        }
        last = c;
    }

    input.truncate(len);

    input
}

pub fn add_semicolon(mut input: String) -> String {
    if !input.ends_with(';') && !input.ends_with("*/") && !input.ends_with('}') {
        input.push_str(";")
    }
    input
}
<commit_msg>Use trimmed string in preprocessing<commit_after>pub fn clean_string(mut input: String) -> String {
    input = String::from(input.trim());

    if input == "" {
        return input;
    }

    // remove line-comments
    let mut last = '\0';
    let mut len = input.len();
    for (i, c) in input.chars().enumerate() {
        if last == '/' && c == '/' {
            len = i-1;
            break;
        }
        last = c;
    }

    input.truncate(len);

    input
}

pub fn add_semicolon(mut input: String) -> String {
    if !input.ends_with(';') && !input.ends_with("*/") && !input.ends_with('}') {
        input.push_str(";")
    }
    input
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::cmp;
use std::io;
use std::ops::Deref;

pub use self::Doc::{
    Nil,
    Append,
    Group,
    Nest,
    Newline,
    Text,
};

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
enum Mode {
    Break,
    Flat,
}

/// The concrete document type. This type is not meant to be used directly. Instead use the static
/// functions on `Doc` or the methods on an `Allocator`.
///
/// The `B` paramater is used to abstract over pointers to `Doc`. See `RefDoc` and `BoxDoc` for how
/// it is used
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc<'a, B> {
    Nil,
    Append(B, B),
    Group(B),
    Nest(usize, B),
    Newline,
    Text(Cow<'a, str>),
}

impl<'a, B, S> From<S> for Doc<'a, B> where S: Into<Cow<'a, str>> {
    fn from(s: S) -> Doc<'a, B> {
        Doc::Text(s.into())
    }
}

impl<'a, B> Doc<'a, B> {

    /// Writes a rendered document.
    #[inline]
    pub fn render<'b, W: ?Sized + io::Write>(&'b self, width: usize, out: &mut W) -> io::Result<()>
    where B: Deref<Target = Doc<'b, B>>
    {
        best(self, width, out).and_then(|()| out.write_all(b"\n"))
    }
}

type Cmd<'a, B> = (usize, Mode, &'a Doc<'a, B>);

#[inline]
fn fitting<'a, B>(
    next: Cmd<'a, B>,
    bcmds: &Vec<Cmd<'a, B>>,
    fcmds: &mut Vec<Cmd<'a, B>>,
    mut rem: isize,
) -> bool
where B: Deref<Target = Doc<'a, B>>
{
    let mut bidx = bcmds.len();
    fcmds.clear(); // clear from previous calls from best
    fcmds.push(next);
    while rem >= 0 {
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    // All commands have been processed
                    return true;
                } else {
                    fcmds.push(bcmds[ bidx - 1 ]);
                    bidx -= 1;
                }
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    fcmds.push((ind, mode, rdoc));
                    fcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => {
                    fcmds.push((ind, mode, doc));
                },
                &Nest(off, ref doc) => {
                    fcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    match mode {
                        Mode::Flat => {
                            rem -= 1;
                        },
                        Mode::Break => {
                            return true;
                        },
                    }
                },
                &Text(ref str) => {
                    rem -= str.len() as isize;
                },
            }
        }
    }
    false
}

#[inline]
pub fn best<'a, W: ?Sized + io::Write, B>(
    doc: &'a Doc<'a, B>,
    width: usize,
    out: &mut W,
) -> io::Result<()>
where B: Deref<Target = Doc<'a, B>>
{
    let mut pos = 0usize;
    let mut bcmds = vec![(0usize, Mode::Break, doc)];
    let mut fcmds = vec![];
    while let Some((ind, mode, doc)) = bcmds.pop() {
        match doc {
            &Nil => {
            },
            &Append(ref ldoc, ref rdoc) => {
                bcmds.push((ind, mode, rdoc));
                bcmds.push((ind, mode, ldoc));
            },
            &Group(ref doc) => match mode {
                Mode::Flat => {
                    bcmds.push((ind, Mode::Flat, doc));
                },
                Mode::Break => {
                    let next = (ind, Mode::Flat, &**doc);
                    let rem = width as isize - pos as isize;
                    if fitting(next, &bcmds, &mut fcmds, rem) {
                        bcmds.push(next);
                    } else {
                        bcmds.push((ind, Mode::Break, doc));
                    }
                }
            },
            &Nest(off, ref doc) => {
                bcmds.push((ind + off, mode, doc));
            },
            &Newline => {
                match mode {
                    Mode::Flat => {
                        try!(out.write_all(b" "));
                    },
                    Mode::Break => {
                        const SPACES: [u8; 100] = [b' '; 100];
                        try!(out.write_all(b"\n"));
                        let mut inserted = 0;
                        while inserted < ind {
                            let insert = cmp::min(100, ind - inserted);
                            inserted += insert;
                            try!(out.write_all(&SPACES[..insert]));
                        }
                    },
                }
                pos = ind;
            },
            &Text(ref s) => {
                try!(out.write_all(&s.as_bytes()));
                pos += s.len();
            },
        }
    }
    Ok(())
}
<commit_msg>Use write directly instead of write_all when writing spaces<commit_after>use std::borrow::Cow;
use std::cmp;
use std::io;
use std::ops::Deref;

pub use self::Doc::{
    Nil,
    Append,
    Group,
    Nest,
    Newline,
    Text,
};

#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
enum Mode {
    Break,
    Flat,
}

/// The concrete document type. This type is not meant to be used directly. Instead use the static
/// functions on `Doc` or the methods on an `Allocator`.
///
/// The `B` parameter is used to abstract over pointers to `Doc`. See `RefDoc` and `BoxDoc` for how
/// it is used
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub enum Doc<'a, B> {
    Nil,
    Append(B, B),
    Group(B),
    Nest(usize, B),
    Newline,
    Text(Cow<'a, str>),
}

impl<'a, B, S> From<S> for Doc<'a, B> where S: Into<Cow<'a, str>> {
    fn from(s: S) -> Doc<'a, B> {
        Doc::Text(s.into())
    }
}

impl<'a, B> Doc<'a, B> {

    /// Writes a rendered document.
    #[inline]
    pub fn render<'b, W: ?Sized + io::Write>(&'b self, width: usize, out: &mut W) -> io::Result<()>
    where B: Deref<Target = Doc<'b, B>>
    {
        best(self, width, out).and_then(|()| out.write_all(b"\n"))
    }
}

type Cmd<'a, B> = (usize, Mode, &'a Doc<'a, B>);

#[inline]
fn fitting<'a, B>(
    next: Cmd<'a, B>,
    bcmds: &Vec<Cmd<'a, B>>,
    fcmds: &mut Vec<Cmd<'a, B>>,
    mut rem: isize,
) -> bool
where B: Deref<Target = Doc<'a, B>>
{
    let mut bidx = bcmds.len();
    fcmds.clear(); // clear from previous calls from best
    fcmds.push(next);
    while rem >= 0 {
        match fcmds.pop() {
            None => {
                if bidx == 0 {
                    // All commands have been processed
                    return true;
                } else {
                    fcmds.push(bcmds[ bidx - 1 ]);
                    bidx -= 1;
                }
            },
            Some((ind, mode, doc)) => match doc {
                &Nil => {
                },
                &Append(ref ldoc, ref rdoc) => {
                    fcmds.push((ind, mode, rdoc));
                    fcmds.push((ind, mode, ldoc));
                },
                &Group(ref doc) => {
                    fcmds.push((ind, mode, doc));
                },
                &Nest(off, ref doc) => {
                    fcmds.push((ind + off, mode, doc));
                },
                &Newline => {
                    match mode {
                        Mode::Flat => {
                            rem -= 1;
                        },
                        Mode::Break => {
                            return true;
                        },
                    }
                },
                &Text(ref str) => {
                    rem -= str.len() as isize;
                },
            }
        }
    }
    false
}

#[inline]
pub fn best<'a, W: ?Sized + io::Write, B>(
    doc: &'a Doc<'a, B>,
    width: usize,
    out: &mut W,
) -> io::Result<()>
where B: Deref<Target = Doc<'a, B>>
{
    let mut pos = 0usize;
    let mut bcmds = vec![(0usize, Mode::Break, doc)];
    let mut fcmds = vec![];
    while let Some((ind, mode, doc)) = bcmds.pop() {
        match doc {
            &Nil => {
            },
            &Append(ref ldoc, ref rdoc) => {
                bcmds.push((ind, mode, rdoc));
                bcmds.push((ind, mode, ldoc));
            },
            &Group(ref doc) => match mode {
                Mode::Flat => {
                    bcmds.push((ind, Mode::Flat, doc));
                },
                Mode::Break => {
                    let next = (ind, Mode::Flat, &**doc);
                    let rem = width as isize - pos as isize;
                    if fitting(next, &bcmds, &mut fcmds, rem) {
                        bcmds.push(next);
                    } else {
                        bcmds.push((ind, Mode::Break, doc));
                    }
                }
            },
            &Nest(off, ref doc) => {
                bcmds.push((ind + off, mode, doc));
            },
            &Newline => {
                match mode {
                    Mode::Flat => {
                        try!(out.write_all(b" "));
                    },
                    Mode::Break => {
                        const SPACES: [u8; 100] = [b' '; 100];
                        try!(out.write_all(b"\n"));
                        let mut inserted = 0;
                        while inserted < ind {
                            let insert = cmp::min(100, ind - inserted);
                            inserted += try!(out.write(&SPACES[..insert]));
                        }
                    },
                }
                pos = ind;
            },
            &Text(ref s) => {
                try!(out.write_all(&s.as_bytes()));
                pos += s.len();
            },
        }
    }
    Ok(())
}
<|endoftext|>


<commit_before>//! GDAL Raster Data

pub use raster::dataset::{Dataset, Buffer, ByteBuffer};
pub use raster::driver::Driver;
pub use raster::warp::reproject;
pub use raster::rasterband::{RasterBand};

// pub use gdal_sys::gdal_enums;
// pub use gdal_sys::{CPLErr};

mod types;
pub mod dataset;
pub mod driver;
pub mod warp;
pub mod rasterband;

#[cfg(test)]
mod tests;
<commit_msg>Remove CPLErr re-export<commit_after>//! GDAL Raster Data

pub use raster::dataset::{Dataset, Buffer, ByteBuffer};
pub use raster::driver::Driver;
pub use raster::warp::reproject;
pub use raster::rasterband::{RasterBand};

mod types;
pub mod dataset;
pub mod driver;
pub mod warp;
pub mod rasterband;

#[cfg(test)]
mod tests;
<|endoftext|>


<commit_before>//! Entry point for the CSS filters infrastructure.

use cssparser::{BasicParseError, Parser};
use markup5ever::{expanded_name, local_name, namespace_url, ns};
use std::time::Instant;

use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::{ElementError, ParseError, RenderingError};
use crate::length::*;
use crate::node::{Node, NodeBorrow};
use crate::paint_server::UserSpacePaintSource;
use crate::parsers::{CustomIdent, Parse, ParseValue};
use crate::properties::ComputedValues;
use crate::property_defs::ColorInterpolationFilters;
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use crate::transform::Transform;
use crate::xml::Attributes;

mod bounds;
use self::bounds::BoundsBuilder;

pub mod context;
use self::context::{FilterContext, FilterOutput, FilterResult};

mod error;
use self::error::FilterError;

/// A filter primitive interface.
pub trait FilterEffect: SetAttributes + Draw {
    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError>;
}

// Filter Effects do not need to draw themselves
impl<T: FilterEffect> Draw for T {}

pub mod blend;
pub mod color_matrix;
pub mod component_transfer;
pub mod composite;
pub mod convolve_matrix;
pub mod displacement_map;
pub mod flood;
pub mod gaussian_blur;
pub mod image;
pub mod lighting;
pub mod merge;
pub mod morphology;
pub mod offset;
pub mod tile;
pub mod turbulence;

/// Resolved parameters for each filter primitive.
///
/// These gather all the data that a primitive may need during rendering:
/// the `feFoo` element's attributes, any computed values from its properties,
/// and parameters extracted from the element's children (for example,
/// `feMerge` gathers info from its `feMergNode` children).
pub enum PrimitiveParams {
    Blend(blend::Blend),
    ColorMatrix(color_matrix::ColorMatrix),
    ComponentTransfer(component_transfer::ComponentTransfer),
    Composite(composite::Composite),
    ConvolveMatrix(convolve_matrix::ConvolveMatrix),
    DiffuseLighting(lighting::DiffuseLighting),
    DisplacementMap(displacement_map::DisplacementMap),
    Flood(flood::Flood),
    GaussianBlur(gaussian_blur::GaussianBlur),
    Image(image::Image),
    Merge(merge::Merge),
    Morphology(morphology::Morphology),
    Offset(offset::Offset),
    SpecularLighting(lighting::SpecularLighting),
    Tile(tile::Tile),
    Turbulence(turbulence::Turbulence),
}

impl PrimitiveParams {
    /// Returns a human-readable name for a primitive.
    #[rustfmt::skip]
    fn name(&self) -> &'static str {
        use PrimitiveParams::*;
        match self {
            Blend(..)             => "feBlend",
            ColorMatrix(..)       => "feColorMatrix",
            ComponentTransfer(..) => "feComponentTransfer",
            Composite(..)         => "feComposite",
            ConvolveMatrix(..)    => "feConvolveMatrix",
            DiffuseLighting(..)   => "feDiffuseLighting",
            DisplacementMap(..)   => "feDisplacementMap",
            Flood(..)             => "feFlood",
            GaussianBlur(..)      => "feGaussianBlur",
            Image(..)             => "feImage",
            Merge(..)             => "feMerge",
            Morphology(..)        => "feMorphology",
            Offset(..)            => "feOffset",
            SpecularLighting(..)  => "feSpecularLighting",
            Tile(..)              => "feTile",
            Turbulence(..)        => "feTurbulence",
        }
    }
}

/// The base filter primitive node containing common properties.
#[derive(Default, Clone)]
pub struct Primitive {
    x: Option<Length<Horizontal>>,
    y: Option<Length<Vertical>>,
    width: Option<ULength<Horizontal>>,
    height: Option<ULength<Vertical>>,
    result: Option<CustomIdent>,
}

/// Common properties for filter primitives, with all lengths in user space coordinates.
pub struct UserSpacePrimitive {
    x: Option<f64>,
    y: Option<f64>,
    width: Option<f64>,
    height: Option<f64>,
    result: Option<CustomIdent>,
}

/// An enumeration of possible inputs for a filter primitive.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Input {
    Unspecified,
    SourceGraphic,
    SourceAlpha,
    BackgroundImage,
    BackgroundAlpha,
    FillPaint,
    StrokePaint,
    FilterOutput(CustomIdent),
}

enum_default!(Input, Input::Unspecified);

impl Parse for Input {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        parser
            .try_parse(|p| {
                parse_identifiers!(
                    p,
                    "SourceGraphic" => Input::SourceGraphic,
                    "SourceAlpha" => Input::SourceAlpha,
                    "BackgroundImage" => Input::BackgroundImage,
                    "BackgroundAlpha" => Input::BackgroundAlpha,
                    "FillPaint" => Input::FillPaint,
                    "StrokePaint" => Input::StrokePaint,
                )
            })
            .or_else(|_: BasicParseError<'_>| {
                let ident = CustomIdent::parse(parser)?;
                Ok(Input::FilterOutput(ident))
            })
    }
}

impl Primitive {
    fn to_user_space(
        &self,
        primitive_units: CoordUnits,
        values: &ComputedValues,
        draw_ctx: &DrawingCtx,
    ) -> UserSpacePrimitive {
        let params = draw_ctx.push_coord_units(primitive_units);

        let x = self.x.map(|l| l.normalize(values, &params));
        let y = self.y.map(|l| l.normalize(values, &params));
        let width = self.width.map(|l| l.normalize(values, &params));
        let height = self.height.map(|l| l.normalize(values, &params));

        UserSpacePrimitive {
            x,
            y,
            width,
            height,
            result: self.result.clone(),
        }
    }
}

impl UserSpacePrimitive {
    /// Validates attributes and returns the `BoundsBuilder` for bounds computation.
    #[inline]
    fn get_bounds(&self, ctx: &FilterContext) -> BoundsBuilder {
        BoundsBuilder::new(self.x, self.y, self.width, self.height, ctx.paffine())
    }
}

impl Primitive {
    fn parse_standard_attributes(
        &mut self,
        attrs: &Attributes,
    ) -> Result<(Input, Input), ElementError> {
        let mut input_1 = Input::Unspecified;
        let mut input_2 = Input::Unspecified;

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "x") => self.x = attr.parse(value)?,
                expanded_name!("", "y") => self.y = attr.parse(value)?,
                expanded_name!("", "width") => self.width = attr.parse(value)?,
                expanded_name!("", "height") => self.height = attr.parse(value)?,
                expanded_name!("", "result") => self.result = attr.parse(value)?,
                expanded_name!("", "in") => input_1 = attr.parse(value)?,
                expanded_name!("", "in2") => input_2 = attr.parse(value)?,
                _ => (),
            }
        }

        Ok((input_1, input_2))
    }

    pub fn parse_no_inputs(&mut self, attrs: &Attributes) -> ElementResult {
        let (_, _) = self.parse_standard_attributes(attrs)?;
        Ok(())
    }

    pub fn parse_one_input(&mut self, attrs: &Attributes) -> Result<Input, ElementError> {
        let (input_1, _) = self.parse_standard_attributes(attrs)?;
        Ok(input_1)
    }

    pub fn parse_two_inputs(&mut self, attrs: &Attributes) -> Result<(Input, Input), ElementError> {
        self.parse_standard_attributes(attrs)
    }
}

/// Applies a filter and returns the resulting surface.
pub fn render(
    filter_node: &Node,
    stroke_paint_source: UserSpacePaintSource,
    fill_paint_source: UserSpacePaintSource,
    source_surface: SharedImageSurface,
    acquired_nodes: &mut AcquiredNodes<'_>,
    draw_ctx: &mut DrawingCtx,
    transform: Transform,
    node_bbox: BoundingBox,
) -> Result<SharedImageSurface, RenderingError> {
    let filter_node = &*filter_node;
    assert!(is_element_of_type!(filter_node, Filter));

    let primitive_nodes: Vec<Node> = filter_node
        .children()
        .filter(|c| c.is_element())
        // Skip nodes in error.
        .filter(|c| {
            let in_error = c.borrow_element().is_in_error();

            if in_error {
                rsvg_log!("(ignoring filter primitive {} because it is in error)", c);
            }

            !in_error
        })
        // Keep only filter primitives (those that implement the Filter trait)
        .filter(|c| c.borrow_element().as_filter_effect().is_some())
        .map(|n| n.clone())
        .collect();

    let filter_element = filter_node.borrow_element();

    if filter_element.is_in_error() {
        return Ok(source_surface);
    }

    let filter_values = filter_element.get_computed_values();

    let filter = borrow_element_as!(filter_node, Filter);

    let resolved_filter = {
        // This is in a temporary scope so we don't leave the coord_units pushed during
        // the execution of all the filter primitives.
        let params = draw_ctx.push_coord_units(filter.get_filter_units());
        filter.to_user_space(filter_values, &params)
    };

    if let Ok(mut filter_ctx) = FilterContext::new(
        &resolved_filter,
        stroke_paint_source,
        fill_paint_source,
        &source_surface,
        transform,
        node_bbox,
    ) {
        for primitive_node in primitive_nodes {
            let elt = primitive_node.borrow_element();
            let effect = elt.as_filter_effect().unwrap();

            let primitive_values = elt.get_computed_values();

            let primitive_name = format!("{}", primitive_node);

            let start = Instant::now();

            if let Err(err) = effect
                .resolve(&primitive_node)
                .and_then(|(primitive, params)| {
                    let user_space_primitive = primitive.to_user_space(
                        resolved_filter.primitive_units,
                        primitive_values,
                        draw_ctx,
                    );

                    let output = render_primitive(
                        &user_space_primitive,
                        &params,
                        &filter_ctx,
                        acquired_nodes,
                        draw_ctx,
                    )?;

                    let elapsed = start.elapsed();
                    rsvg_log!(
                        "(rendered filter primitive {} in\n    {} seconds)",
                        params.name(),
                        elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) / 1e9
                    );

                    Ok(FilterResult {
                        name: user_space_primitive.result,
                        output,
                    })
                })
                .and_then(|result| filter_ctx.store_result(result))
            {
                rsvg_log!(
                    "(filter primitive {} returned an error: {})",
                    primitive_name,
                    err
                );

                // Exit early on Cairo errors. Continue rendering otherwise.
                if let FilterError::CairoError(status) = err {
                    return Err(RenderingError::from(status));
                }
            }
        }

        Ok(filter_ctx.into_output()?)
    } else {
        // Ignore errors that happened when creating the FilterContext
        Ok(SharedImageSurface::empty(
            source_surface.width(),
            source_surface.height(),
            SurfaceType::AlphaOnly,
        )?)
    }
}

#[rustfmt::skip]
fn render_primitive(
    primitive: &UserSpacePrimitive,
    params: &PrimitiveParams,
    ctx: &FilterContext,
    acquired_nodes: &mut AcquiredNodes<'_>,
    draw_ctx: &mut DrawingCtx,
) -> Result<FilterOutput, FilterError> {
    use PrimitiveParams::*;

    let bounds_builder = primitive.get_bounds(ctx);

    match params {
        Blend(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ColorMatrix(p)       => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ComponentTransfer(p) => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Composite(p)         => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ConvolveMatrix(p)    => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        DiffuseLighting(p)   => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        DisplacementMap(p)   => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Flood(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        GaussianBlur(p)      => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Image(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Merge(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Morphology(p)        => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Offset(p)            => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        SpecularLighting(p)  => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Tile(p)              => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Turbulence(p)        => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
    }
}

impl From<ColorInterpolationFilters> for SurfaceType {
    fn from(c: ColorInterpolationFilters) -> Self {
        match c {
            ColorInterpolationFilters::LinearRgb => SurfaceType::LinearRgb,
            _ => SurfaceType::SRgb,
        }
    }
}
<commit_msg>Rename variable<commit_after>//! Entry point for the CSS filters infrastructure.

use cssparser::{BasicParseError, Parser};
use markup5ever::{expanded_name, local_name, namespace_url, ns};
use std::time::Instant;

use crate::bbox::BoundingBox;
use crate::coord_units::CoordUnits;
use crate::document::AcquiredNodes;
use crate::drawing_ctx::DrawingCtx;
use crate::element::{Draw, ElementResult, SetAttributes};
use crate::error::{ElementError, ParseError, RenderingError};
use crate::length::*;
use crate::node::{Node, NodeBorrow};
use crate::paint_server::UserSpacePaintSource;
use crate::parsers::{CustomIdent, Parse, ParseValue};
use crate::properties::ComputedValues;
use crate::property_defs::ColorInterpolationFilters;
use crate::surface_utils::shared_surface::{SharedImageSurface, SurfaceType};
use crate::transform::Transform;
use crate::xml::Attributes;

mod bounds;
use self::bounds::BoundsBuilder;

pub mod context;
use self::context::{FilterContext, FilterOutput, FilterResult};

mod error;
use self::error::FilterError;

/// A filter primitive interface.
pub trait FilterEffect: SetAttributes + Draw {
    fn resolve(&self, node: &Node) -> Result<(Primitive, PrimitiveParams), FilterError>;
}

// Filter Effects do not need to draw themselves
impl<T: FilterEffect> Draw for T {}

pub mod blend;
pub mod color_matrix;
pub mod component_transfer;
pub mod composite;
pub mod convolve_matrix;
pub mod displacement_map;
pub mod flood;
pub mod gaussian_blur;
pub mod image;
pub mod lighting;
pub mod merge;
pub mod morphology;
pub mod offset;
pub mod tile;
pub mod turbulence;

/// Resolved parameters for each filter primitive.
///
/// These gather all the data that a primitive may need during rendering:
/// the `feFoo` element's attributes, any computed values from its properties,
/// and parameters extracted from the element's children (for example,
/// `feMerge` gathers info from its `feMergNode` children).
pub enum PrimitiveParams {
    Blend(blend::Blend),
    ColorMatrix(color_matrix::ColorMatrix),
    ComponentTransfer(component_transfer::ComponentTransfer),
    Composite(composite::Composite),
    ConvolveMatrix(convolve_matrix::ConvolveMatrix),
    DiffuseLighting(lighting::DiffuseLighting),
    DisplacementMap(displacement_map::DisplacementMap),
    Flood(flood::Flood),
    GaussianBlur(gaussian_blur::GaussianBlur),
    Image(image::Image),
    Merge(merge::Merge),
    Morphology(morphology::Morphology),
    Offset(offset::Offset),
    SpecularLighting(lighting::SpecularLighting),
    Tile(tile::Tile),
    Turbulence(turbulence::Turbulence),
}

impl PrimitiveParams {
    /// Returns a human-readable name for a primitive.
    #[rustfmt::skip]
    fn name(&self) -> &'static str {
        use PrimitiveParams::*;
        match self {
            Blend(..)             => "feBlend",
            ColorMatrix(..)       => "feColorMatrix",
            ComponentTransfer(..) => "feComponentTransfer",
            Composite(..)         => "feComposite",
            ConvolveMatrix(..)    => "feConvolveMatrix",
            DiffuseLighting(..)   => "feDiffuseLighting",
            DisplacementMap(..)   => "feDisplacementMap",
            Flood(..)             => "feFlood",
            GaussianBlur(..)      => "feGaussianBlur",
            Image(..)             => "feImage",
            Merge(..)             => "feMerge",
            Morphology(..)        => "feMorphology",
            Offset(..)            => "feOffset",
            SpecularLighting(..)  => "feSpecularLighting",
            Tile(..)              => "feTile",
            Turbulence(..)        => "feTurbulence",
        }
    }
}

/// The base filter primitive node containing common properties.
#[derive(Default, Clone)]
pub struct Primitive {
    x: Option<Length<Horizontal>>,
    y: Option<Length<Vertical>>,
    width: Option<ULength<Horizontal>>,
    height: Option<ULength<Vertical>>,
    result: Option<CustomIdent>,
}

/// Common properties for filter primitives, with all lengths in user space coordinates.
pub struct UserSpacePrimitive {
    x: Option<f64>,
    y: Option<f64>,
    width: Option<f64>,
    height: Option<f64>,
    result: Option<CustomIdent>,
}

/// An enumeration of possible inputs for a filter primitive.
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Input {
    Unspecified,
    SourceGraphic,
    SourceAlpha,
    BackgroundImage,
    BackgroundAlpha,
    FillPaint,
    StrokePaint,
    FilterOutput(CustomIdent),
}

enum_default!(Input, Input::Unspecified);

impl Parse for Input {
    fn parse<'i>(parser: &mut Parser<'i, '_>) -> Result<Self, ParseError<'i>> {
        parser
            .try_parse(|p| {
                parse_identifiers!(
                    p,
                    "SourceGraphic" => Input::SourceGraphic,
                    "SourceAlpha" => Input::SourceAlpha,
                    "BackgroundImage" => Input::BackgroundImage,
                    "BackgroundAlpha" => Input::BackgroundAlpha,
                    "FillPaint" => Input::FillPaint,
                    "StrokePaint" => Input::StrokePaint,
                )
            })
            .or_else(|_: BasicParseError<'_>| {
                let ident = CustomIdent::parse(parser)?;
                Ok(Input::FilterOutput(ident))
            })
    }
}

impl Primitive {
    fn to_user_space(
        &self,
        primitive_units: CoordUnits,
        values: &ComputedValues,
        draw_ctx: &DrawingCtx,
    ) -> UserSpacePrimitive {
        let params = draw_ctx.push_coord_units(primitive_units);

        let x = self.x.map(|l| l.normalize(values, &params));
        let y = self.y.map(|l| l.normalize(values, &params));
        let width = self.width.map(|l| l.normalize(values, &params));
        let height = self.height.map(|l| l.normalize(values, &params));

        UserSpacePrimitive {
            x,
            y,
            width,
            height,
            result: self.result.clone(),
        }
    }
}

impl UserSpacePrimitive {
    /// Validates attributes and returns the `BoundsBuilder` for bounds computation.
    #[inline]
    fn get_bounds(&self, ctx: &FilterContext) -> BoundsBuilder {
        BoundsBuilder::new(self.x, self.y, self.width, self.height, ctx.paffine())
    }
}

impl Primitive {
    fn parse_standard_attributes(
        &mut self,
        attrs: &Attributes,
    ) -> Result<(Input, Input), ElementError> {
        let mut input_1 = Input::Unspecified;
        let mut input_2 = Input::Unspecified;

        for (attr, value) in attrs.iter() {
            match attr.expanded() {
                expanded_name!("", "x") => self.x = attr.parse(value)?,
                expanded_name!("", "y") => self.y = attr.parse(value)?,
                expanded_name!("", "width") => self.width = attr.parse(value)?,
                expanded_name!("", "height") => self.height = attr.parse(value)?,
                expanded_name!("", "result") => self.result = attr.parse(value)?,
                expanded_name!("", "in") => input_1 = attr.parse(value)?,
                expanded_name!("", "in2") => input_2 = attr.parse(value)?,
                _ => (),
            }
        }

        Ok((input_1, input_2))
    }

    pub fn parse_no_inputs(&mut self, attrs: &Attributes) -> ElementResult {
        let (_, _) = self.parse_standard_attributes(attrs)?;
        Ok(())
    }

    pub fn parse_one_input(&mut self, attrs: &Attributes) -> Result<Input, ElementError> {
        let (input_1, _) = self.parse_standard_attributes(attrs)?;
        Ok(input_1)
    }

    pub fn parse_two_inputs(&mut self, attrs: &Attributes) -> Result<(Input, Input), ElementError> {
        self.parse_standard_attributes(attrs)
    }
}

/// Applies a filter and returns the resulting surface.
pub fn render(
    filter_node: &Node,
    stroke_paint_source: UserSpacePaintSource,
    fill_paint_source: UserSpacePaintSource,
    source_surface: SharedImageSurface,
    acquired_nodes: &mut AcquiredNodes<'_>,
    draw_ctx: &mut DrawingCtx,
    transform: Transform,
    node_bbox: BoundingBox,
) -> Result<SharedImageSurface, RenderingError> {
    let filter_node = &*filter_node;
    assert!(is_element_of_type!(filter_node, Filter));

    let primitive_nodes: Vec<Node> = filter_node
        .children()
        .filter(|c| c.is_element())
        // Skip nodes in error.
        .filter(|c| {
            let in_error = c.borrow_element().is_in_error();

            if in_error {
                rsvg_log!("(ignoring filter primitive {} because it is in error)", c);
            }

            !in_error
        })
        // Keep only filter primitives (those that implement the Filter trait)
        .filter(|c| c.borrow_element().as_filter_effect().is_some())
        .map(|n| n.clone())
        .collect();

    let filter_element = filter_node.borrow_element();

    if filter_element.is_in_error() {
        return Ok(source_surface);
    }

    let filter_values = filter_element.get_computed_values();

    let filter = borrow_element_as!(filter_node, Filter);

    let user_space_filter = {
        // This is in a temporary scope so we don't leave the coord_units pushed during
        // the execution of all the filter primitives.
        let params = draw_ctx.push_coord_units(filter.get_filter_units());
        filter.to_user_space(filter_values, &params)
    };

    if let Ok(mut filter_ctx) = FilterContext::new(
        &user_space_filter,
        stroke_paint_source,
        fill_paint_source,
        &source_surface,
        transform,
        node_bbox,
    ) {
        for primitive_node in primitive_nodes {
            let elt = primitive_node.borrow_element();
            let effect = elt.as_filter_effect().unwrap();

            let primitive_values = elt.get_computed_values();

            let primitive_name = format!("{}", primitive_node);

            let start = Instant::now();

            if let Err(err) = effect
                .resolve(&primitive_node)
                .and_then(|(primitive, params)| {
                    let user_space_primitive = primitive.to_user_space(
                        user_space_filter.primitive_units,
                        primitive_values,
                        draw_ctx,
                    );

                    let output = render_primitive(
                        &user_space_primitive,
                        &params,
                        &filter_ctx,
                        acquired_nodes,
                        draw_ctx,
                    )?;

                    let elapsed = start.elapsed();
                    rsvg_log!(
                        "(rendered filter primitive {} in\n    {} seconds)",
                        params.name(),
                        elapsed.as_secs() as f64 + f64::from(elapsed.subsec_nanos()) / 1e9
                    );

                    Ok(FilterResult {
                        name: user_space_primitive.result,
                        output,
                    })
                })
                .and_then(|result| filter_ctx.store_result(result))
            {
                rsvg_log!(
                    "(filter primitive {} returned an error: {})",
                    primitive_name,
                    err
                );

                // Exit early on Cairo errors. Continue rendering otherwise.
                if let FilterError::CairoError(status) = err {
                    return Err(RenderingError::from(status));
                }
            }
        }

        Ok(filter_ctx.into_output()?)
    } else {
        // Ignore errors that happened when creating the FilterContext
        Ok(SharedImageSurface::empty(
            source_surface.width(),
            source_surface.height(),
            SurfaceType::AlphaOnly,
        )?)
    }
}

#[rustfmt::skip]
fn render_primitive(
    primitive: &UserSpacePrimitive,
    params: &PrimitiveParams,
    ctx: &FilterContext,
    acquired_nodes: &mut AcquiredNodes<'_>,
    draw_ctx: &mut DrawingCtx,
) -> Result<FilterOutput, FilterError> {
    use PrimitiveParams::*;

    let bounds_builder = primitive.get_bounds(ctx);

    match params {
        Blend(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ColorMatrix(p)       => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ComponentTransfer(p) => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Composite(p)         => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        ConvolveMatrix(p)    => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        DiffuseLighting(p)   => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        DisplacementMap(p)   => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Flood(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        GaussianBlur(p)      => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Image(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Merge(p)             => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Morphology(p)        => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Offset(p)            => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        SpecularLighting(p)  => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Tile(p)              => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
        Turbulence(p)        => p.render(bounds_builder, ctx, acquired_nodes, draw_ctx),
    }
}

impl From<ColorInterpolationFilters> for SurfaceType {
    fn from(c: ColorInterpolationFilters) -> Self {
        match c {
            ColorInterpolationFilters::LinearRgb => SurfaceType::LinearRgb,
            _ => SurfaceType::SRgb,
        }
    }
}
<|endoftext|>


<commit_before>use gfx;
use gfx::format::SurfaceType;
use gfx::handle::{DepthStencilView, RenderTargetView};
use gfx::memory::Typed;
use gfx_device_gl;
use glutin;
use glutin::{KeyboardInput, MouseButton, PossiblyCurrent, WindowedContext};
use glutin::dpi::LogicalSize;
use glutin::ElementState::{Pressed, Released};
use glutin::VirtualKeyCode::{A, D, Escape, R, S, W, X, Z};

use crate::character::controls::CharacterControl;
use crate::game::constants::{GAME_TITLE, RESOLUTION_X, RESOLUTION_Y};
use crate::gfx_app::controls::{Control, TilemapControls};

pub mod init;
pub mod renderer;
pub mod system;
pub mod controls;
pub mod mouse_controls;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

pub const COLOR_FORMAT_VALUE: SurfaceType = SurfaceType::R8_G8_B8_A8;
pub const DEPTH_FORMAT_VALUE: SurfaceType = SurfaceType::D24_S8;

#[derive(Debug)]
pub struct GameOptions {
  windowed_mode: bool,
  frame_rate: bool,
}

impl GameOptions {
  pub fn new(windowed_mode: bool, frame_rate: bool) -> GameOptions {
    GameOptions {
      windowed_mode,
      frame_rate,
    }
  }
}

pub struct WindowContext {
  window_context: WindowedContext<PossiblyCurrent>,
  controls: Option<controls::TilemapControls>,
  events_loop: glutin::EventsLoop,
  device: gfx_device_gl::Device,
  factory: gfx_device_gl::Factory,
  render_target_view: RenderTargetView<gfx_device_gl::Resources, ColorFormat>,
  depth_stencil_view: DepthStencilView<gfx_device_gl::Resources, DepthFormat>,
  mouse_pos: (f64, f64),
  game_options: GameOptions
}

impl WindowContext {
  pub fn new(game_options: GameOptions) -> WindowContext {
    let events_loop = glutin::EventsLoop::new();

    let window_title = glutin::WindowBuilder::new()
      .with_title(GAME_TITLE);

    println!("{:#?}", game_options);

    let builder = if game_options.windowed_mode {
      let logical_size = LogicalSize::new(RESOLUTION_X.into(), RESOLUTION_Y.into());
      window_title
        .with_dimensions(logical_size)
        .with_decorations(false)
    } else {
      let monitor = {
        events_loop.get_available_monitors().nth(0).expect("No monitor found")
      };
      let monitor_resolution = monitor.get_dimensions();

      let resolution = ((monitor_resolution.width as f32 * 16.0 / 9.0) as u32, monitor_resolution.height);

      let logical_size = LogicalSize::new(resolution.0.into(), resolution.1);
      window_title.with_fullscreen(Some(monitor))
        .with_decorations(false)
        .with_dimensions(logical_size)
    };

    let window_context = glutin::ContextBuilder::new()
      .with_vsync(true)
      .with_double_buffer(Some(true))
      .with_pixel_format(24, 8)
      .with_srgb(true)
      .build_windowed(builder, &events_loop)
      .expect("Window context creation failed");

    let window_context = unsafe {
      window_context
        .make_current()
        .expect("Window focus failed")
    };

    let (width, height) = {
      let inner_size = window_context.window().get_inner_size().expect("get_inner_size failed");
      let size = inner_size.to_physical(window_context.window().get_hidpi_factor());
      (size.width as _, size.height as _)
    };

    let aa = window_context
      .get_pixel_format().multisampling
      .unwrap_or(0) as u8;

    let window_dimensions = (width, height, 1, aa.into());

    let (device, factory) = gfx_device_gl::create(|s|
      window_context.get_proc_address(s) as *const std::os::raw::c_void);

    let (rtv, dsv) =
      gfx_device_gl::create_main_targets_raw(window_dimensions,
                                             COLOR_FORMAT_VALUE,
                                             DEPTH_FORMAT_VALUE);

    WindowContext {
      window_context,
      controls: None,
      events_loop,
      device,
      factory,
      render_target_view: RenderTargetView::new(rtv),
      depth_stencil_view: DepthStencilView::new(dsv),
      mouse_pos: (0.0, 0.0),
      game_options,
    }
  }
}

#[derive(PartialEq, Eq)]
pub enum WindowStatus {
  Open,
  Close,
}

pub trait Window<D: gfx::Device, F: gfx::Factory<D::Resources>> {
  fn swap_window(&mut self);
  fn create_buffers(&mut self, count: usize) -> Vec<D::CommandBuffer>;
  fn set_controls(&mut self, controls: controls::TilemapControls);
  fn get_viewport_size(&mut self) -> (f32, f32);
  fn get_device(&mut self) -> &mut D;
  fn get_factory(&mut self) -> &mut F;
  fn get_hidpi_factor(&mut self) -> f32;
  fn get_render_target_view(&mut self) -> RenderTargetView<D::Resources, ColorFormat>;
  fn get_depth_stencil_view(&mut self) -> DepthStencilView<D::Resources, DepthFormat>;
  fn poll_events(&mut self) -> WindowStatus;
  fn is_windowed(&self) -> bool;
  fn print_frame_rate(&self) -> bool;
}

impl Window<gfx_device_gl::Device, gfx_device_gl::Factory> for WindowContext {
  fn swap_window(&mut self) {
    use gfx::Device;
    self.window_context
      .swap_buffers()
      .expect("Unable to swap buffers");
    self.device.cleanup();
  }

  fn create_buffers(&mut self, count: usize) -> Vec<gfx_device_gl::CommandBuffer> {
    let mut bufs = Vec::new();
    for _ in 0..count {
      bufs.push(self.factory.create_command_buffer());
    }
    bufs
  }

  fn set_controls(&mut self, controls: controls::TilemapControls) {
    self.controls = Some(controls);
  }

  fn is_windowed(&self) -> bool {
    self.game_options.windowed_mode || cfg!(feature = "windowed")
  }

  fn print_frame_rate(&self) -> bool {
    self.game_options.frame_rate || cfg!(feature = "framerate")
  }

  fn get_viewport_size(&mut self) -> (f32, f32) {
    if self.game_options.windowed_mode {
      (RESOLUTION_X as f32, RESOLUTION_Y as f32)
    } else {
      let monitor = self.events_loop.get_available_monitors().nth(0).expect("No monitor found");
      let monitor_resolution = monitor.get_dimensions();
      (monitor_resolution.width as f32, monitor_resolution.height as f32)
    }
  }

  fn get_device(&mut self) -> &mut gfx_device_gl::Device {
    &mut self.device
  }

  fn get_factory(&mut self) -> &mut gfx_device_gl::Factory {
    &mut self.factory
  }

  fn get_hidpi_factor(&mut self) -> f32 {
    if self.game_options.windowed_mode {
      1.0
    } else {
      self.window_context.window().get_hidpi_factor() as f32
    }
  }

  fn get_render_target_view(&mut self) -> RenderTargetView<gfx_device_gl::Resources, ColorFormat> {
    self.render_target_view.clone()
  }

  fn get_depth_stencil_view(&mut self) -> DepthStencilView<gfx_device_gl::Resources, DepthFormat> {
    self.depth_stencil_view.clone()
  }

  fn poll_events(&mut self) -> WindowStatus {
    use glutin::WindowEvent::{CursorMoved, CloseRequested, MouseInput};

    let controls = match self.controls {
      Some(ref mut c) => c,
      None => panic!("Terrain controls have not been initialized"),
    };

    let m_pos = &mut self.mouse_pos;
    let mut game_status = WindowStatus::Open;

    self.events_loop.poll_events(|event| {
      game_status = if let glutin::Event::WindowEvent { event, .. } = event {
        match event {
          glutin::WindowEvent::KeyboardInput { input, .. } => { process_keyboard_input(input, controls) }
          MouseInput { state: Pressed, button: MouseButton::Left, .. } => {
            controls.mouse_left_click(Some(*m_pos));
            WindowStatus::Open
          }
          MouseInput { state: Released, button: MouseButton::Left, .. } => {
            controls.mouse_left_click(None);
            WindowStatus::Open
          }
          CursorMoved { position, .. } => {
            *m_pos = ((position.x as f32).into(), (position.y as f32).into());
            WindowStatus::Open
          }
          CloseRequested => WindowStatus::Close,
          _ => WindowStatus::Open,
        }
      } else {
        WindowStatus::Open
      };
    });
    game_status
  }
}

fn process_keyboard_input(input: glutin::KeyboardInput, controls: &mut TilemapControls) -> WindowStatus {
  match input {
    KeyboardInput { state: Pressed, virtual_keycode: Some(Z), .. } => {
      controls.zoom(&Control::Negative);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(X), .. } => {
      controls.zoom(&Control::Plus);
    }
    KeyboardInput { state: Released, virtual_keycode: Some(Z), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(X), .. } => {
      controls.zoom(&Control::Released);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(W), .. } => {
      controls.move_character(CharacterControl::Up);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(S), .. } => {
      controls.move_character(CharacterControl::Down);
    }
    KeyboardInput { state: Released, virtual_keycode: Some(W), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(S), .. } => {
      controls.move_character(CharacterControl::YMoveStop);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(A), .. } => {
      controls.move_character(CharacterControl::Left);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(D), .. } => {
      controls.move_character(CharacterControl::Right);
    }
    KeyboardInput { state: Released, virtual_keycode: Some(A), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(D), .. } => {
      controls.move_character(CharacterControl::XMoveStop);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(R), .. } => {
      controls.reload_weapon(true);
    }
    KeyboardInput { state: Released, virtual_keycode: Some(R), .. } => {
      controls.reload_weapon(false);
    }
    KeyboardInput { state: Pressed, modifiers, .. } => {
      if modifiers.ctrl {
        controls.ctrl_pressed(true);
      }
    }
    KeyboardInput { state: Released, modifiers, .. } => {
      if !modifiers.ctrl {
        controls.ctrl_pressed(false);
      }
    }
  }
  if let Some(Escape) = input.virtual_keycode {
    WindowStatus::Close
  } else {
    WindowStatus::Open
  }
}

<commit_msg>Format game options log message<commit_after>use gfx;
use gfx::format::SurfaceType;
use gfx::handle::{DepthStencilView, RenderTargetView};
use gfx::memory::Typed;
use gfx_device_gl;
use glutin;
use glutin::{KeyboardInput, MouseButton, PossiblyCurrent, WindowedContext};
use glutin::dpi::LogicalSize;
use glutin::ElementState::{Pressed, Released};
use glutin::VirtualKeyCode::{A, D, Escape, R, S, W, X, Z};
use std::fmt::{Display, Formatter, Result};

use crate::character::controls::CharacterControl;
use crate::game::constants::{GAME_TITLE, RESOLUTION_X, RESOLUTION_Y};
use crate::gfx_app::controls::{Control, TilemapControls};

pub mod init;
pub mod renderer;
pub mod system;
pub mod controls;
pub mod mouse_controls;

pub type ColorFormat = gfx::format::Rgba8;
pub type DepthFormat = gfx::format::DepthStencil;

pub const COLOR_FORMAT_VALUE: SurfaceType = SurfaceType::R8_G8_B8_A8;
pub const DEPTH_FORMAT_VALUE: SurfaceType = SurfaceType::D24_S8;

#[derive(Debug)]
pub struct GameOptions {
  windowed_mode: bool,
  frame_rate: bool,
}

impl Display for GameOptions {
  fn fmt(&self, f: &mut Formatter) -> Result {
    write!(f, "{}", format!("windowed_mode={}\nframe_rate={}", self.windowed_mode, self.frame_rate))
  }
}

impl GameOptions {
  pub fn new(windowed_mode: bool, frame_rate: bool) -> GameOptions {
    GameOptions {
      windowed_mode,
      frame_rate,
    }
  }
}

pub struct WindowContext {
  window_context: WindowedContext<PossiblyCurrent>,
  controls: Option<controls::TilemapControls>,
  events_loop: glutin::EventsLoop,
  device: gfx_device_gl::Device,
  factory: gfx_device_gl::Factory,
  render_target_view: RenderTargetView<gfx_device_gl::Resources, ColorFormat>,
  depth_stencil_view: DepthStencilView<gfx_device_gl::Resources, DepthFormat>,
  mouse_pos: (f64, f64),
  game_options: GameOptions
}

impl WindowContext {
  pub fn new(game_options: GameOptions) -> WindowContext {
    let events_loop = glutin::EventsLoop::new();

    let window_title = glutin::WindowBuilder::new()
      .with_title(GAME_TITLE);

    println!("{}", game_options);

    let builder = if game_options.windowed_mode {
      let logical_size = LogicalSize::new(RESOLUTION_X.into(), RESOLUTION_Y.into());
      window_title
        .with_dimensions(logical_size)
        .with_decorations(false)
    } else {
      let monitor = {
        events_loop.get_available_monitors().nth(0).expect("No monitor found")
      };
      let monitor_resolution = monitor.get_dimensions();

      let resolution = ((monitor_resolution.width as f32 * 16.0 / 9.0) as u32, monitor_resolution.height);

      let logical_size = LogicalSize::new(resolution.0.into(), resolution.1);
      window_title.with_fullscreen(Some(monitor))
        .with_decorations(false)
        .with_dimensions(logical_size)
    };

    let window_context = glutin::ContextBuilder::new()
      .with_vsync(true)
      .with_double_buffer(Some(true))
      .with_pixel_format(24, 8)
      .with_srgb(true)
      .build_windowed(builder, &events_loop)
      .expect("Window context creation failed");

    let window_context = unsafe {
      window_context
        .make_current()
        .expect("Window focus failed")
    };

    let (width, height) = {
      let inner_size = window_context.window().get_inner_size().expect("get_inner_size failed");
      let size = inner_size.to_physical(window_context.window().get_hidpi_factor());
      (size.width as _, size.height as _)
    };

    let aa = window_context
      .get_pixel_format().multisampling
      .unwrap_or(0) as u8;

    let window_dimensions = (width, height, 1, aa.into());

    let (device, factory) = gfx_device_gl::create(|s|
      window_context.get_proc_address(s) as *const std::os::raw::c_void);

    let (rtv, dsv) =
      gfx_device_gl::create_main_targets_raw(window_dimensions,
                                             COLOR_FORMAT_VALUE,
                                             DEPTH_FORMAT_VALUE);

    WindowContext {
      window_context,
      controls: None,
      events_loop,
      device,
      factory,
      render_target_view: RenderTargetView::new(rtv),
      depth_stencil_view: DepthStencilView::new(dsv),
      mouse_pos: (0.0, 0.0),
      game_options,
    }
  }
}

#[derive(PartialEq, Eq)]
pub enum WindowStatus {
  Open,
  Close,
}

pub trait Window<D: gfx::Device, F: gfx::Factory<D::Resources>> {
  fn swap_window(&mut self);
  fn create_buffers(&mut self, count: usize) -> Vec<D::CommandBuffer>;
  fn set_controls(&mut self, controls: controls::TilemapControls);
  fn get_viewport_size(&mut self) -> (f32, f32);
  fn get_device(&mut self) -> &mut D;
  fn get_factory(&mut self) -> &mut F;
  fn get_hidpi_factor(&mut self) -> f32;
  fn get_render_target_view(&mut self) -> RenderTargetView<D::Resources, ColorFormat>;
  fn get_depth_stencil_view(&mut self) -> DepthStencilView<D::Resources, DepthFormat>;
  fn poll_events(&mut self) -> WindowStatus;
  fn is_windowed(&self) -> bool;
  fn print_frame_rate(&self) -> bool;
}

impl Window<gfx_device_gl::Device, gfx_device_gl::Factory> for WindowContext {
  fn swap_window(&mut self) {
    use gfx::Device;
    self.window_context
      .swap_buffers()
      .expect("Unable to swap buffers");
    self.device.cleanup();
  }

  fn create_buffers(&mut self, count: usize) -> Vec<gfx_device_gl::CommandBuffer> {
    let mut bufs = Vec::new();
    for _ in 0..count {
      bufs.push(self.factory.create_command_buffer());
    }
    bufs
  }

  fn set_controls(&mut self, controls: controls::TilemapControls) {
    self.controls = Some(controls);
  }

  fn is_windowed(&self) -> bool {
    self.game_options.windowed_mode || cfg!(feature = "windowed")
  }

  fn print_frame_rate(&self) -> bool {
    self.game_options.frame_rate || cfg!(feature = "framerate")
  }

  fn get_viewport_size(&mut self) -> (f32, f32) {
    if self.game_options.windowed_mode {
      (RESOLUTION_X as f32, RESOLUTION_Y as f32)
    } else {
      let monitor = self.events_loop.get_available_monitors().nth(0).expect("No monitor found");
      let monitor_resolution = monitor.get_dimensions();
      (monitor_resolution.width as f32, monitor_resolution.height as f32)
    }
  }

  fn get_device(&mut self) -> &mut gfx_device_gl::Device {
    &mut self.device
  }

  fn get_factory(&mut self) -> &mut gfx_device_gl::Factory {
    &mut self.factory
  }

  fn get_hidpi_factor(&mut self) -> f32 {
    if self.game_options.windowed_mode {
      1.0
    } else {
      self.window_context.window().get_hidpi_factor() as f32
    }
  }

  fn get_render_target_view(&mut self) -> RenderTargetView<gfx_device_gl::Resources, ColorFormat> {
    self.render_target_view.clone()
  }

  fn get_depth_stencil_view(&mut self) -> DepthStencilView<gfx_device_gl::Resources, DepthFormat> {
    self.depth_stencil_view.clone()
  }

  fn poll_events(&mut self) -> WindowStatus {
    use glutin::WindowEvent::{CursorMoved, CloseRequested, MouseInput};

    let controls = match self.controls {
      Some(ref mut c) => c,
      None => panic!("Terrain controls have not been initialized"),
    };

    let m_pos = &mut self.mouse_pos;
    let mut game_status = WindowStatus::Open;

    self.events_loop.poll_events(|event| {
      game_status = if let glutin::Event::WindowEvent { event, .. } = event {
        match event {
          glutin::WindowEvent::KeyboardInput { input, .. } => { process_keyboard_input(input, controls) }
          MouseInput { state: Pressed, button: MouseButton::Left, .. } => {
            controls.mouse_left_click(Some(*m_pos));
            WindowStatus::Open
          }
          MouseInput { state: Released, button: MouseButton::Left, .. } => {
            controls.mouse_left_click(None);
            WindowStatus::Open
          }
          CursorMoved { position, .. } => {
            *m_pos = ((position.x as f32).into(), (position.y as f32).into());
            WindowStatus::Open
          }
          CloseRequested => WindowStatus::Close,
          _ => WindowStatus::Open,
        }
      } else {
        WindowStatus::Open
      };
    });
    game_status
  }
}

fn process_keyboard_input(input: glutin::KeyboardInput, controls: &mut TilemapControls) -> WindowStatus {
  match input {
    KeyboardInput { state: Pressed, virtual_keycode: Some(Z), .. } => {
      controls.zoom(&Control::Negative);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(X), .. } => {
      controls.zoom(&Control::Plus);
    }
    KeyboardInput { state: Released, virtual_keycode: Some(Z), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(X), .. } => {
      controls.zoom(&Control::Released);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(W), .. } => {
      controls.move_character(CharacterControl::Up);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(S), .. } => {
      controls.move_character(CharacterControl::Down);
    }
    KeyboardInput { state: Released, virtual_keycode: Some(W), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(S), .. } => {
      controls.move_character(CharacterControl::YMoveStop);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(A), .. } => {
      controls.move_character(CharacterControl::Left);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(D), .. } => {
      controls.move_character(CharacterControl::Right);
    }
    KeyboardInput { state: Released, virtual_keycode: Some(A), .. } |
    KeyboardInput { state: Released, virtual_keycode: Some(D), .. } => {
      controls.move_character(CharacterControl::XMoveStop);
    }
    KeyboardInput { state: Pressed, virtual_keycode: Some(R), .. } => {
      controls.reload_weapon(true);
    }
    KeyboardInput { state: Released, virtual_keycode: Some(R), .. } => {
      controls.reload_weapon(false);
    }
    KeyboardInput { state: Pressed, modifiers, .. } => {
      if modifiers.ctrl {
        controls.ctrl_pressed(true);
      }
    }
    KeyboardInput { state: Released, modifiers, .. } => {
      if !modifiers.ctrl {
        controls.ctrl_pressed(false);
      }
    }
  }
  if let Some(Escape) = input.virtual_keycode {
    WindowStatus::Close
  } else {
    WindowStatus::Open
  }
}

<|endoftext|>


<commit_before>#![feature(plugin)]
#![plugin(interpolate_idents)]

#[macro_use] extern crate cpython;

use cpython::{PyResult, Python, PyTuple};

mod foo {
    pub fn hello_world() -> () {
        println!("Hello, world!");
    }
}

py_module_initializer!(libhello_world, |_py, m| {
    try!(m.add("__doc__", "Module docstring"));
    try!(m.add("hello_world", py_fn!(hello_world)));
    Ok(())
});

fn hello_world<'p>(py: Python<'p>, args: &PyTuple<'p>) -> PyResult<'p, u64> {
    foo::hello_world();
    Ok(0)
}
<commit_msg>change return return none instead of u64<commit_after>#![feature(plugin)]
#![plugin(interpolate_idents)]

#[macro_use] extern crate cpython;

use cpython::{PyResult, Python, PyTuple, PyObject};

mod foo {
    pub fn hello_world() -> () {
        println!("Hello, world!");
    }
}

py_module_initializer!(libhello_world, |_py, m| {
    try!(m.add("__doc__", "Module docstring"));
    try!(m.add("hello_world", py_fn!(hello_world)));
    Ok(())
});

fn hello_world<'p>(py: Python<'p>, args: &PyTuple<'p>) -> PyResult<'p, PyObject<'p>> {
    foo::hello_world();
    Ok(py.None())
}
<|endoftext|>