<commit_before>use std::io::{Cursor, Seek, SeekFrom, Read, Result};
use flate2::read::ZlibDecoder;

use byteorder::{BigEndian, ByteOrder, LittleEndian};
use encoding::DecoderTrap;
use encoding::label::encoding_from_whatwg_label;

macro_rules! read_endian {
    ($this:ident, $size:expr, $end:ident, $method:ident) => {{
        let mut buf = [0; $size];
        try!($this.read_exact(&mut buf));
        Ok($end::$method(&buf))
    }}
}

pub trait KaitaiStream: Read + Seek {
    // ------------------ //
    // Stream positioning //
    // ------------------ //

    fn is_eof(&mut self) -> Result<bool> {
        // TODO: I'm positive there's a better way to do this!
        // See also the `size` implementation
        let pos = try!(self.pos());
        let size = try!(Seek::seek(self, SeekFrom::End(0)));
        try!(Seek::seek(self, SeekFrom::Start(pos)));
        return Ok(pos >= size);
    }

    fn seek(&mut self, position: u64) -> Result<()> {
        match Seek::seek(self, SeekFrom::Start(position)) {
            Ok(_) => Ok(()),
            Err(e) => Err(e),
        }
    }

    fn pos(&mut self) -> Result<u64> {
        match Seek::seek(self, SeekFrom::Current(0)) {
            Ok(i) => Ok(i as u64),
            Err(e) => Err(e),
        }
    }

    fn size(&mut self) -> Result<u64> {
        // TODO: I'm positive there's a better way to do this!
        let pos = try!(self.pos());
        let size = try!(Seek::seek(self, SeekFrom::End(0)));
        try!(Seek::seek(self, SeekFrom::Start(pos)));
        return Ok(size);
    }

    // ---------------------- //
    // Integer types - signed //
    // ---------------------- //

    fn read_s1(&mut self) -> Result<i8> {
        let mut buf = [0; 1];
        try!(self.read_exact(&mut buf));
        Ok(buf[0] as i8)
    }

    // Big endian

    fn read_s2be(&mut self) -> Result<i16> {
        read_endian!(self, 2, BigEndian, read_i16)
    }

    fn read_s4be(&mut self) -> Result<i32> {
        read_endian!(self, 4, BigEndian, read_i32)
    }

    fn read_s8be(&mut self) -> Result<i64> {
        read_endian!(self, 8, BigEndian, read_i64)
    }

    // Little endian

    fn read_s2le(&mut self) -> Result<i16> {
        read_endian!(self, 2, LittleEndian, read_i16)
    }

    fn read_s4le(&mut self) -> Result<i32> {
        read_endian!(self, 4, LittleEndian, read_i32)
    }

    fn read_s8le(&mut self) -> Result<i64> {
        read_endian!(self, 8, LittleEndian, read_i64)
    }

    // ------------------------ //
    // Integer types - unsigned //
    // ------------------------ //

    fn read_u1(&mut self) -> Result<u8> {
        let mut buf = [0; 1];
        try!(self.read_exact(&mut buf));
        Ok(buf[0])
    }

    // Big endian

    fn read_u2be(&mut self) -> Result<u16> {
        read_endian!(self, 2, BigEndian, read_u16)
    }

    fn read_u4be(&mut self) -> Result<u32> {
        read_endian!(self, 4, BigEndian, read_u32)
    }

    fn read_u8be(&mut self) -> Result<u64> {
        read_endian!(self, 8, BigEndian, read_u64)
    }

    // Little endian

    fn read_u2le(&mut self) -> Result<u16> {
        read_endian!(self, 2, LittleEndian, read_u16)
    }

    fn read_u4le(&mut self) -> Result<u32> {
        read_endian!(self, 4, LittleEndian, read_u32)
    }

    fn read_u8le(&mut self) -> Result<u64> {
        read_endian!(self, 8, LittleEndian, read_u64)
    }

    // -------------------- //
    // Floating point types //
    // -------------------- //

    // Big endian

    fn read_f4be(&mut self) -> Result<f32> {
        read_endian!(self, 4, BigEndian, read_f32)
    }

    fn read_f8be(&mut self) -> Result<f64> {
        read_endian!(self, 8, BigEndian, read_f64)
    }

    // Little endian

    fn read_f4le(&mut self) -> Result<f32> {
        read_endian!(self, 4, LittleEndian, read_f32)
    }

    fn read_f8le(&mut self) -> Result<f64> {
        read_endian!(self, 8, LittleEndian, read_f64)
    }

    // ----------- //
    // Byte arrays //
    // ----------- //

    fn read_bytes(&mut self, count: usize) -> Result<Vec<u8>> {
        let mut buffer = vec![0; count];
        match self.read_exact(&mut buffer[..]) {
            Ok(_) => Ok(buffer),
            Err(e) => Err(e),
        }
    }

    fn read_bytes_full(&mut self) -> Result<Vec<u8>> {
        let mut buffer = vec![0; 0];
        match self.read_to_end(&mut buffer) {
            Ok(_) => Ok(buffer),
            Err(e) => Err(e),
        }
    }

    fn ensure_fixed_contents(&mut self, count: usize, expected: Vec<u8>) -> Result<Vec<u8>> {
        let mut buffer = vec![0; count];
        match self.read_exact(&mut buffer[..]) {
            Ok(_) => {
                assert_eq!(buffer, expected);
                Ok(buffer)
            }
            Err(e) => Err(e),
        }
    }

    // ------- //
    // Strings //
    // ------- //

    fn read_str_eos(&mut self, encoding: &str) -> Result<String> {
        match encoding_from_whatwg_label(encoding) {
            Some(enc) => {
                let buffer = try!(self.read_bytes_full());
                match enc.decode(&buffer, DecoderTrap::Strict) {
                    Ok(s) => Ok(s),
                    Err(e) => panic!("Error decoding string: {}", e),
                }
            }
            None => panic!("Unknown encoding: {}", encoding),
        }
    }

    fn read_str_byte_limit(&mut self, length: usize, encoding: &str) -> Result<String> {
        match encoding_from_whatwg_label(encoding) {
            Some(enc) => {
                let buffer = try!(self.read_bytes(length));
                match enc.decode(&buffer, DecoderTrap::Strict) {
                    Ok(s) => Ok(s),
                    Err(e) => panic!("Error decoding string: {}", e),
                }
            }
            None => panic!("Unknown encoding: {}", encoding),
        }
    }

    fn read_strz(&mut self,
                 encoding: &str,
                 terminator: u8,
                 include_terminator: bool,
                 consume_terminator: bool,
                 eos_error: bool)
                 -> Result<String> {
        let enc = match encoding_from_whatwg_label(encoding) {
            Some(enc) => enc,
            None => {
                panic!("Unknown encoding: {}", encoding);
                unreachable!();
            }
        };
        let mut buffer = vec![];
        let mut c = vec![0; 1];
        loop {
            match self.read_exact(&mut c[..]) {
                Ok(_) => {}
                Err(e) => {
                    if eos_error {
                        return Err(e);
                    }
                    break;
                }
            };
            if c[0] == terminator {
                if include_terminator {
                    buffer.push(c[0])
                }
                if !consume_terminator {
                    let pos = try!(self.pos());
                    try!(Seek::seek(self, SeekFrom::Start((pos - 1) as u64)));
                }
                break;
            }
            buffer.push(c[0])
        }
        match enc.decode(&buffer, DecoderTrap::Strict) {
            Ok(s) => Ok(s),
            Err(e) => panic!("Error decoding string: {}", e),
        }
    }

    // --------------------- //
    // Byte array processing //
    // --------------------- //

    fn process_xor_one(&mut self, value: Vec<u8>, key: u8) -> Vec<u8> {
        let mut result = vec![0; value.len()];
        for i in 0..value.len() {
            result[i] = (value[i] ^ key) as u8;
        }
        return result;
    }

    fn process_xor_many(&mut self, value: Vec<u8>, key: Vec<u8>) -> Vec<u8> {
        let mut result = vec![0; value.len()];
        let mut j = 0;
        for i in 0..value.len() {
            result[i] = (value[i] ^ key[j]) as u8;
            j = (j + 1) % key.len();
        }
        return result;
    }

    fn process_rotate_left(&mut self, data: Vec<u8>, amount: i32, group_size: i32) -> Vec<u8> {
        if amount < -7 || amount > 7 {
            panic!("Rotation of more than 7 cannot be performed.");
        }

        let mut rot_amount = amount;
        if rot_amount < 0 {
            rot_amount += 8;
        }

        let mut result = vec![0; data.len()];
        match group_size {
            1 => {
                for i in 0..data.len() {
                    result[i] = data[i].rotate_left(rot_amount as u32);
                }
            }
            _ => return panic!("Unable to rotate a group of {} bytes yet", group_size),
        }
        return result;
    }

    fn process_zlib(&mut self, data: Vec<u8>) -> Result<Vec<u8>> {
        let mut decoder = ZlibDecoder::new(Cursor::new(data));
        let mut result = Vec::new();
        match decoder.read_to_end(&mut result) {
            Ok(_) => Ok(result),
            Err(e) => Err(e),
        }
    }
}

impl<T: Read + Seek> KaitaiStream for T {}<commit_msg>Replace usage of try!{} macro with the ? operator<commit_after>use std::io::{Cursor, Seek, SeekFrom, Read, Result};
use flate2::read::ZlibDecoder;

use byteorder::{BigEndian, ByteOrder, LittleEndian};
use encoding::DecoderTrap;
use encoding::label::encoding_from_whatwg_label;

macro_rules! read_endian {
    ($this:ident, $size:expr, $end:ident, $method:ident) => {{
        let mut buf = [0; $size];
        try!($this.read_exact(&mut buf));
        Ok($end::$method(&buf))
    }}
}

pub trait KaitaiStream: Read + Seek {
    // ------------------ //
    // Stream positioning //
    // ------------------ //

    fn is_eof(&mut self) -> Result<bool> {
        // TODO: I'm positive there's a better way to do this!
        // See also the `size` implementation
        let pos = self.pos()?;
        let size = Seek::seek(self, SeekFrom::End(0))?;
        Seek::seek(self, SeekFrom::Start(pos))?;
        return Ok(pos >= size);
    }

    fn seek(&mut self, position: u64) -> Result<()> {
        match Seek::seek(self, SeekFrom::Start(position)) {
            Ok(_) => Ok(()),
            Err(e) => Err(e),
        }
    }

    fn pos(&mut self) -> Result<u64> {
        match Seek::seek(self, SeekFrom::Current(0)) {
            Ok(i) => Ok(i as u64),
            Err(e) => Err(e),
        }
    }

    fn size(&mut self) -> Result<u64> {
        // TODO: I'm positive there's a better way to do this!
        let pos = self.pos()?;
        let size = Seek::seek(self, SeekFrom::End(0))?;
        Seek::seek(self, SeekFrom::Start(pos))?;
        return Ok(size);
    }

    // ---------------------- //
    // Integer types - signed //
    // ---------------------- //

    fn read_s1(&mut self) -> Result<i8> {
        let mut buf = [0; 1];
        self.read_exact(&mut buf)?;
        Ok(buf[0] as i8)
    }

    // Big endian

    fn read_s2be(&mut self) -> Result<i16> {
        read_endian!(self, 2, BigEndian, read_i16)
    }

    fn read_s4be(&mut self) -> Result<i32> {
        read_endian!(self, 4, BigEndian, read_i32)
    }

    fn read_s8be(&mut self) -> Result<i64> {
        read_endian!(self, 8, BigEndian, read_i64)
    }

    // Little endian

    fn read_s2le(&mut self) -> Result<i16> {
        read_endian!(self, 2, LittleEndian, read_i16)
    }

    fn read_s4le(&mut self) -> Result<i32> {
        read_endian!(self, 4, LittleEndian, read_i32)
    }

    fn read_s8le(&mut self) -> Result<i64> {
        read_endian!(self, 8, LittleEndian, read_i64)
    }

    // ------------------------ //
    // Integer types - unsigned //
    // ------------------------ //

    fn read_u1(&mut self) -> Result<u8> {
        let mut buf = [0; 1];
        self.read_exact(&mut buf)?;
        Ok(buf[0])
    }

    // Big endian

    fn read_u2be(&mut self) -> Result<u16> {
        read_endian!(self, 2, BigEndian, read_u16)
    }

    fn read_u4be(&mut self) -> Result<u32> {
        read_endian!(self, 4, BigEndian, read_u32)
    }

    fn read_u8be(&mut self) -> Result<u64> {
        read_endian!(self, 8, BigEndian, read_u64)
    }

    // Little endian

    fn read_u2le(&mut self) -> Result<u16> {
        read_endian!(self, 2, LittleEndian, read_u16)
    }

    fn read_u4le(&mut self) -> Result<u32> {
        read_endian!(self, 4, LittleEndian, read_u32)
    }

    fn read_u8le(&mut self) -> Result<u64> {
        read_endian!(self, 8, LittleEndian, read_u64)
    }

    // -------------------- //
    // Floating point types //
    // -------------------- //

    // Big endian

    fn read_f4be(&mut self) -> Result<f32> {
        read_endian!(self, 4, BigEndian, read_f32)
    }

    fn read_f8be(&mut self) -> Result<f64> {
        read_endian!(self, 8, BigEndian, read_f64)
    }

    // Little endian

    fn read_f4le(&mut self) -> Result<f32> {
        read_endian!(self, 4, LittleEndian, read_f32)
    }

    fn read_f8le(&mut self) -> Result<f64> {
        read_endian!(self, 8, LittleEndian, read_f64)
    }

    // ----------- //
    // Byte arrays //
    // ----------- //

    fn read_bytes(&mut self, count: usize) -> Result<Vec<u8>> {
        let mut buffer = vec![0; count];
        match self.read_exact(&mut buffer[..]) {
            Ok(_) => Ok(buffer),
            Err(e) => Err(e),
        }
    }

    fn read_bytes_full(&mut self) -> Result<Vec<u8>> {
        let mut buffer = vec![0; 0];
        match self.read_to_end(&mut buffer) {
            Ok(_) => Ok(buffer),
            Err(e) => Err(e),
        }
    }

    fn ensure_fixed_contents(&mut self, count: usize, expected: Vec<u8>) -> Result<Vec<u8>> {
        let mut buffer = vec![0; count];
        match self.read_exact(&mut buffer[..]) {
            Ok(_) => {
                assert_eq!(buffer, expected);
                Ok(buffer)
            }
            Err(e) => Err(e),
        }
    }

    // ------- //
    // Strings //
    // ------- //

    fn read_str_eos(&mut self, encoding: &str) -> Result<String> {
        match encoding_from_whatwg_label(encoding) {
            Some(enc) => {
                let buffer = self.read_bytes_full()?;
                match enc.decode(&buffer, DecoderTrap::Strict) {
                    Ok(s) => Ok(s),
                    Err(e) => panic!("Error decoding string: {}", e),
                }
            }
            None => panic!("Unknown encoding: {}", encoding),
        }
    }

    fn read_str_byte_limit(&mut self, length: usize, encoding: &str) -> Result<String> {
        match encoding_from_whatwg_label(encoding) {
            Some(enc) => {
                let buffer = self.read_bytes(length)?;
                match enc.decode(&buffer, DecoderTrap::Strict) {
                    Ok(s) => Ok(s),
                    Err(e) => panic!("Error decoding string: {}", e),
                }
            }
            None => panic!("Unknown encoding: {}", encoding),
        }
    }

    fn read_strz(&mut self,
                 encoding: &str,
                 terminator: u8,
                 include_terminator: bool,
                 consume_terminator: bool,
                 eos_error: bool)
                 -> Result<String> {
        let enc = match encoding_from_whatwg_label(encoding) {
            Some(enc) => enc,
            None => panic!("Unknown encoding: {}", encoding),
        };
        let mut buffer = vec![];
        let mut c = vec![0; 1];
        loop {
            match self.read_exact(&mut c[..]) {
                Ok(_) => {}
                Err(e) => {
                    if eos_error {
                        return Err(e);
                    }
                    break;
                }
            };
            if c[0] == terminator {
                if include_terminator {
                    buffer.push(c[0])
                }
                if !consume_terminator {
                    let pos = self.pos()?;
                    Seek::seek(self, SeekFrom::Start((pos - 1) as u64))?;
                }
                break;
            }
            buffer.push(c[0])
        }
        match enc.decode(&buffer, DecoderTrap::Strict) {
            Ok(s) => Ok(s),
            Err(e) => panic!("Error decoding string: {}", e),
        }
    }

    // --------------------- //
    // Byte array processing //
    // --------------------- //

    fn process_xor_one(&mut self, value: Vec<u8>, key: u8) -> Vec<u8> {
        let mut result = vec![0; value.len()];
        for i in 0..value.len() {
            result[i] = (value[i] ^ key) as u8;
        }
        return result;
    }

    fn process_xor_many(&mut self, value: Vec<u8>, key: Vec<u8>) -> Vec<u8> {
        let mut result = vec![0; value.len()];
        let mut j = 0;
        for i in 0..value.len() {
            result[i] = (value[i] ^ key[j]) as u8;
            j = (j + 1) % key.len();
        }
        return result;
    }

    fn process_rotate_left(&mut self, data: Vec<u8>, amount: i32, group_size: i32) -> Vec<u8> {
        if amount < -7 || amount > 7 {
            panic!("Rotation of more than 7 cannot be performed.");
        }

        let mut rot_amount = amount;
        if rot_amount < 0 {
            rot_amount += 8;
        }

        let mut result = vec![0; data.len()];
        match group_size {
            1 => {
                for i in 0..data.len() {
                    result[i] = data[i].rotate_left(rot_amount as u32);
                }
            }
            _ => panic!("Unable to rotate a group of {} bytes yet", group_size),
        }
        return result;
    }

    fn process_zlib(&mut self, data: Vec<u8>) -> Result<Vec<u8>> {
        let mut decoder = ZlibDecoder::new(Cursor::new(data));
        let mut result = Vec::new();
        match decoder.read_to_end(&mut result) {
            Ok(_) => Ok(result),
            Err(e) => Err(e),
        }
    }
}

impl<T: Read + Seek> KaitaiStream for T {}<|endoftext|>


<commit_before>use std::fs::{File, OpenOptions};
use std::path::Path;
use std::sync::Mutex;
use std::sync::mpsc::{self, Sender};
use std::time::{Instant, Duration};
use std::{error, io, thread, net};

use csv;
use rustc_serialize;
use iron;
use iron::prelude::*;
use iron::{Handler, AroundMiddleware};
use iron::status::Status;

#[derive(Debug)]
pub struct LogPacket {
    url: iron::Url,
    ip: net::SocketAddr,
    status: Option<Status>,
    timing: Duration,
}

impl rustc_serialize::Encodable for LogPacket {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        try!(self.url.to_string().encode(s));
        try!(self.ip.to_string().encode(s));
        try!(self.status.as_ref().map(|s| format!("{:?}", s)).encode(s));
        format!("{}.{}", self.timing.as_secs(), self.timing.subsec_nanos()).encode(s)
    }
}

pub struct StatisticLogger {
    thread: thread::JoinHandle<()>,
    tx: Sender<LogPacket>,
}

pub trait LogWriter {
    type Error: error::Error;

    fn log(&mut self, log: &LogPacket) -> Result<(), Self::Error>;
}

pub struct FileLogger(csv::Writer<File>);

impl FileLogger {
    pub fn new<P>(path: P) -> io::Result<FileLogger>
        where P: AsRef<Path>
    {
        OpenOptions::new()
            .write(true)
            .append(true)
            .create(true)
            .open(path)
            .map(csv::Writer::from_writer)
            .map(FileLogger)
    }
}

impl LogWriter for FileLogger {
    type Error = csv::Error;

    fn log(&mut self, packet: &LogPacket) -> Result<(), Self::Error> {
        try!(self.0.encode(packet));
        self.0.flush()
    }
}

impl StatisticLogger {
    pub fn new<L>(mut logger: L) -> StatisticLogger
        where L: LogWriter + Send + 'static
    {
        let (tx, rx) = mpsc::channel();

        let handle = thread::spawn(move || {
            for packet in rx {
                logger.log(&packet).expect("Unable to log request");
            }
        });

        StatisticLogger {
            thread: handle,
            tx: tx,
        }
    }
}

impl AroundMiddleware for StatisticLogger {
    fn around(self, handler: Box<Handler>) -> Box<Handler> {
        Box::new(LogHandler {
            handler: handler,
            thread: self.thread,
            tx: Mutex::new(self.tx),
        })
    }
}

struct LogHandler {
    handler: Box<Handler>,
    #[allow(dead_code)] // We should probably join this, right?
    thread: thread::JoinHandle<()>,
    tx: Mutex<Sender<LogPacket>>,
}

impl Handler for LogHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let (timing, response_result) = time_it(|| self.handler.handle(req));

        let status = response_result.as_ref()
            .map(|success| success.status)
            .unwrap_or_else(|failure| failure.response.status);

        let tx = {
            let guard = self.tx.lock().expect("Unable to get logger channel");
            guard.clone()
        };

        tx.send(LogPacket {
            url: req.url.clone(),
            ip: req.remote_addr,
            status: status,
            timing: timing,
        }).expect("Unable to send log to logger thread");

        response_result
    }
}

fn time_it<F, T>(f: F) -> (Duration, T)
    where F: FnOnce() -> T
{
    let before = Instant::now();
    let result = f();
    let after = Instant::now();

    let timing = after.duration_since(before);

    (timing, result)
}
<commit_msg>Track the initial request time<commit_after>use std::fs::{File, OpenOptions};
use std::path::Path;
use std::sync::Mutex;
use std::sync::mpsc::{self, Sender};
use std::time::{Instant, SystemTime, Duration, UNIX_EPOCH};
use std::{error, io, thread, net};

use csv;
use rustc_serialize::{self, Encodable};
use iron;
use iron::prelude::*;
use iron::{Handler, AroundMiddleware};
use iron::status::Status;

#[derive(Debug)]
pub struct LogPacket {
    url: iron::Url,
    ip: net::SocketAddr,
    status: Option<Status>,
    start: SystemTime,
    timing: Duration,
}

fn encode_duration<S: rustc_serialize::Encoder>(s: &mut S, duration: &Duration) -> Result<(), S::Error> {
    format!("{}.{}", duration.as_secs(), duration.subsec_nanos()).encode(s)
}

impl rustc_serialize::Encodable for LogPacket {
    fn encode<S: rustc_serialize::Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
        try!(self.url.to_string().encode(s));
        try!(self.ip.to_string().encode(s));
        try!(self.status.as_ref().map(|s| format!("{:?}", s)).encode(s));
        let start = self.start.duration_since(UNIX_EPOCH).expect("Unable to calculate origin time");
        try!(encode_duration(s, &start));
        encode_duration(s, &self.timing)
    }
}

pub struct StatisticLogger {
    thread: thread::JoinHandle<()>,
    tx: Sender<LogPacket>,
}

pub trait LogWriter {
    type Error: error::Error;

    fn log(&mut self, log: &LogPacket) -> Result<(), Self::Error>;
}

pub struct FileLogger(csv::Writer<File>);

impl FileLogger {
    pub fn new<P>(path: P) -> io::Result<FileLogger>
        where P: AsRef<Path>
    {
        OpenOptions::new()
            .write(true)
            .append(true)
            .create(true)
            .open(path)
            .map(csv::Writer::from_writer)
            .map(FileLogger)
    }
}

impl LogWriter for FileLogger {
    type Error = csv::Error;

    fn log(&mut self, packet: &LogPacket) -> Result<(), Self::Error> {
        try!(self.0.encode(packet));
        self.0.flush()
    }
}

impl StatisticLogger {
    pub fn new<L>(mut logger: L) -> StatisticLogger
        where L: LogWriter + Send + 'static
    {
        let (tx, rx) = mpsc::channel();

        let handle = thread::spawn(move || {
            for packet in rx {
                logger.log(&packet).expect("Unable to log request");
            }
        });

        StatisticLogger {
            thread: handle,
            tx: tx,
        }
    }
}

impl AroundMiddleware for StatisticLogger {
    fn around(self, handler: Box<Handler>) -> Box<Handler> {
        Box::new(LogHandler {
            handler: handler,
            thread: self.thread,
            tx: Mutex::new(self.tx),
        })
    }
}

struct LogHandler {
    handler: Box<Handler>,
    #[allow(dead_code)] // We should probably join this, right?
    thread: thread::JoinHandle<()>,
    tx: Mutex<Sender<LogPacket>>,
}

impl Handler for LogHandler {
    fn handle(&self, req: &mut Request) -> IronResult<Response> {
        let (start, timing, response_result) = time_it(|| self.handler.handle(req));

        let status = response_result.as_ref()
            .map(|success| success.status)
            .unwrap_or_else(|failure| failure.response.status);

        let tx = {
            let guard = self.tx.lock().expect("Unable to get logger channel");
            guard.clone()
        };

        tx.send(LogPacket {
            url: req.url.clone(),
            ip: req.remote_addr,
            status: status,
            start: start,
            timing: timing,
        }).expect("Unable to send log to logger thread");

        response_result
    }
}

fn time_it<F, T>(f: F) -> (SystemTime, Duration, T)
    where F: FnOnce() -> T
{
    let start = SystemTime::now();
    let before = Instant::now();
    let result = f();
    let after = Instant::now();

    let timing = after.duration_since(before);

    (start, timing, result)
}
<|endoftext|>


<commit_before>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use std::cmp;
use std::mem;
use std::ptr;
use libc::c_int;
use num::complex::{
    Complex32,
    Complex64,
};
use error::Error;
use ll::*;
use matrix::{
    Matrix,
};
use scalar::Scalar;
use types::Layout;
use util::transpose_data;

pub trait Gels: Sized {
    fn gels(layout: Layout, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<(), Error>;
    fn gels_work(layout: Layout, a: &mut Matrix<Self>, b: &mut Matrix<Self>, work: &mut [Self]) -> Result<(), Error>;
    fn gels_work_len(a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<usize, Error>;
}

macro_rules! least_sq_impl(($($t: ident), +) => ($(
    impl Gels for $t {
        fn gels(layout: Layout, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<(), Error> {
            //TODO: nancheck

            let work_len = try!(Gels::gels_work_len(a, b));
            let mut work: Vec<$t> = Vec::with_capacity(work_len as usize);
            unsafe {
                work.set_len(work_len as usize);
            }

            Gels::gels_work(layout, a, b, &mut work[..])
        }

        fn gels_work(layout: Layout, a: &mut Matrix<Self>, b: &mut Matrix<Self>, work: &mut [Self]) -> Result<(), Error> {
            let mut info: c_int = 0;

            let m = a.rows();
            let n = a.cols();
            let nrhs = b.cols();
            let lda = m;
            let ldb = b.rows();

            match layout {
                Layout::ColMajor => unsafe {
                    prefix!($t, gels_)(
                        a.transpose().as_i8().as_mut(),
                        m.as_mut(), n.as_mut(),
                        nrhs.as_mut(),
                        a.as_mut_ptr(), lda.as_mut(),
                        b.as_mut_ptr(), ldb.as_mut(),
                        work.as_mut_ptr(), (work.len() as c_int).as_mut(),
                        &mut info as *mut c_int);
                },
                Layout::RowMajor => {
                    let mrhs = cmp::max(m, n);

                    let lda_t = cmp::max(1, m);
                    let ldb_t = cmp::max(1, mrhs);

                    let a_t_len = (lda_t * cmp::max(1, n)) as usize;
                    let b_t_len = (ldb_t * cmp::max(1, nrhs)) as usize;
                    let mut a_t = Vec::with_capacity(a_t_len);
                    let mut b_t = Vec::with_capacity(b_t_len);

                    unsafe {
                        a_t.set_len(a_t_len);
                        b_t.set_len(b_t_len);

                        transpose_data(Layout::RowMajor, m as isize, n as isize, a.as_ptr(), m as isize, a_t.as_mut_ptr(), lda_t as isize);
                        transpose_data(Layout::RowMajor, mrhs as isize, nrhs as isize, b.as_ptr(), mrhs as isize, b_t.as_mut_ptr(), ldb_t as isize);

                        prefix!($t, gels_)(
                            a.transpose().as_i8().as_mut(),
                            m.as_mut(), n.as_mut(),
                            nrhs.as_mut(),
                            a_t.as_mut_ptr(), lda_t.as_mut(),
                            b_t.as_mut_ptr(), ldb_t.as_mut(),
                            work.as_mut_ptr(), (work.len() as c_int).as_mut(),
                            &mut info as *mut c_int);

                        transpose_data(Layout::ColMajor, m as isize, n as isize, a_t.as_ptr(), lda_t as isize, a.as_mut_ptr(), m as isize);
                        transpose_data(Layout::ColMajor, mrhs as isize, nrhs as isize, b_t.as_ptr(), ldb_t as isize, b.as_mut_ptr(), mrhs as isize);
                    }
                }
            }

            match info {
                0 => Ok(()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }

        fn gels_work_len(a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<usize, Error> {
            let mut info: c_int = 0;
            let mut len_info: $t = unsafe { mem::zeroed() };
            let len_ptr = (&mut len_info) as *mut $t;

            let m = a.rows();
            let n = a.cols();
            let nrhs = b.cols();
            let lda_t = cmp::max(1, m);
            let ldb_t = cmp::max(1, cmp::max(m, n));

            unsafe {
                prefix!($t, gels_)(
                    a.transpose().as_i8().as_mut(),
                    m.as_mut(), n.as_mut(),
                    nrhs.as_mut(),
                    a.as_mut_ptr(), lda_t.as_mut(),
                    b.as_mut_ptr(), ldb_t.as_mut(),
                    len_ptr, (-1 as c_int).as_mut(),
                    &mut info as *mut c_int);
            };

            match info {
                0 => Ok(len_info.as_work()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }
    }
)+));

least_sq_impl!(f32, f64, Complex32, Complex64);

#[cfg(test)]
mod gesv_tests {
    use types::Layout::*;
    use least_squares::Gels;

    #[test]
    fn col_major() {
        let mut a = (3i32, 2i32, vec![2.0f32,4.0,7.0,3.0,9.0,4.0]);
        let mut b = (3i32, 2i32, vec![2.0f32,4.0,7.0,6.0,18.0,8.0]);

        Gels::gels(ColMajor, &mut a, &mut b).unwrap();

        let (_, _, x) = b;
        assert_eq!(x, vec![1.0, 0.0, 0.0, 0.0, 2.0, 0.0]);
    }

    #[test]
    fn row_major() {
        let mut a = (3i32, 2i32, vec![2.0f32,3.0,4.0,9.0,7.0,4.0]);
        let mut b = (3i32, 2i32, vec![2.0f32,3.0,4.0,9.0,7.0,4.0]);

        Gels::gels(RowMajor, &mut a, &mut b).unwrap();

        let (_, _, x) = b;
        assert_eq!(x, vec![1.0, 0.0, 4.0, 0.0, 1.0, 4.0]);
    }
}
<commit_msg>Fix transpose issue<commit_after>// Copyright 2014 Michael Yang. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
use std::cmp;
use std::mem;
use std::ptr;
use libc::c_int;
use num::complex::{
    Complex32,
    Complex64,
};
use error::Error;
use ll::*;
use matrix::{
    Matrix,
};
use scalar::Scalar;
use types::Layout;
use util::transpose_data;

pub trait Gels: Sized {
    fn gels(layout: Layout, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<(), Error>;
    fn gels_work(layout: Layout, a: &mut Matrix<Self>, b: &mut Matrix<Self>, work: &mut [Self]) -> Result<(), Error>;
    fn gels_work_len(a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<usize, Error>;
}

macro_rules! least_sq_impl(($($t: ident), +) => ($(
    impl Gels for $t {
        fn gels(layout: Layout, a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<(), Error> {
            //TODO: nancheck

            let work_len = try!(Gels::gels_work_len(a, b));
            let mut work: Vec<$t> = Vec::with_capacity(work_len as usize);
            unsafe {
                work.set_len(work_len as usize);
            }

            Gels::gels_work(layout, a, b, &mut work[..])
        }

        fn gels_work(layout: Layout, a: &mut Matrix<Self>, b: &mut Matrix<Self>, work: &mut [Self]) -> Result<(), Error> {
            let mut info: c_int = 0;

            let m = a.rows();
            let n = a.cols();
            let nrhs = b.cols();

            match layout {
                Layout::ColMajor => unsafe {
                    let lda = m;
                    let ldb = b.rows();

                    prefix!($t, gels_)(
                        a.transpose().as_i8().as_mut(),
                        m.as_mut(), n.as_mut(),
                        nrhs.as_mut(),
                        a.as_mut_ptr(), lda.as_mut(),
                        b.as_mut_ptr(), ldb.as_mut(),
                        work.as_mut_ptr(), (work.len() as c_int).as_mut(),
                        &mut info as *mut c_int);
                },
                Layout::RowMajor => {
                    let lda = n;
                    let ldb = nrhs;
                    let mrhs = cmp::max(m, n);

                    let lda_t = cmp::max(1, m);
                    let ldb_t = cmp::max(1, mrhs);

                    let a_t_len = (lda_t * cmp::max(1, n)) as usize;
                    let b_t_len = (ldb_t * cmp::max(1, nrhs)) as usize;
                    let mut a_t = Vec::with_capacity(a_t_len);
                    let mut b_t = Vec::with_capacity(b_t_len);

                    unsafe {
                        a_t.set_len(a_t_len);
                        b_t.set_len(b_t_len);

                        transpose_data(Layout::RowMajor, m as isize, n as isize, a.as_ptr(), lda as isize, a_t.as_mut_ptr(), lda_t as isize);
                        transpose_data(Layout::RowMajor, mrhs as isize, nrhs as isize, b.as_ptr(), ldb as isize, b_t.as_mut_ptr(), ldb_t as isize);

                        prefix!($t, gels_)(
                            a.transpose().as_i8().as_mut(),
                            m.as_mut(), n.as_mut(),
                            nrhs.as_mut(),
                            a_t.as_mut_ptr(), lda_t.as_mut(),
                            b_t.as_mut_ptr(), ldb_t.as_mut(),
                            work.as_mut_ptr(), (work.len() as c_int).as_mut(),
                            &mut info as *mut c_int);

                        transpose_data(Layout::ColMajor, m as isize, n as isize, a_t.as_ptr(), lda_t as isize, a.as_mut_ptr(), lda as isize);
                        transpose_data(Layout::ColMajor, mrhs as isize, nrhs as isize, b_t.as_ptr(), ldb_t as isize, b.as_mut_ptr(), ldb as isize);
                    }
                }
            }

            match info {
                0 => Ok(()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }

        fn gels_work_len(a: &mut Matrix<Self>, b: &mut Matrix<Self>) -> Result<usize, Error> {
            let mut info: c_int = 0;
            let mut len_info: $t = unsafe { mem::zeroed() };
            let len_ptr = (&mut len_info) as *mut $t;

            let m = a.rows();
            let n = a.cols();
            let nrhs = b.cols();
            let lda_t = cmp::max(1, m);
            let ldb_t = cmp::max(1, cmp::max(m, n));

            unsafe {
                prefix!($t, gels_)(
                    a.transpose().as_i8().as_mut(),
                    m.as_mut(), n.as_mut(),
                    nrhs.as_mut(),
                    a.as_mut_ptr(), lda_t.as_mut(),
                    b.as_mut_ptr(), ldb_t.as_mut(),
                    len_ptr, (-1 as c_int).as_mut(),
                    &mut info as *mut c_int);
            };

            match info {
                0 => Ok(len_info.as_work()),
                x if x < 0 => Err(Error::IllegalParameter(-x as usize)),
                x => Err(Error::DiagonalElementZero(x as usize)),
            }
        }
    }
)+));

least_sq_impl!(f32, f64, Complex32, Complex64);

#[cfg(test)]
mod gesv_tests {
    use types::Layout::*;
    use least_squares::Gels;

    #[test]
    fn col_major() {
        let mut a = (3i32, 2i32, vec![2.0f32,4.0,7.0,3.0,9.0,4.0]);
        let mut b = (3i32, 2i32, vec![2.0f32,4.0,7.0,6.0,18.0,8.0]);

        Gels::gels(ColMajor, &mut a, &mut b).unwrap();

        let (_, _, x) = b;
        assert_eq!(x, vec![1.0, 0.0, 0.0, 0.0, 2.0, 0.0]);
    }

    #[test]
    fn row_major() {
        let mut a = (3i32, 2i32, vec![2.0f32,3.0,4.0,9.0,7.0,4.0]);
        let mut b = (3i32, 2i32, vec![2.0f32,3.0,4.0,9.0,7.0,4.0]);

        Gels::gels(RowMajor, &mut a, &mut b).unwrap();

        let (_, _, x) = b;
        assert_eq!(x, vec![1.0, 0.0, 0.0, 1.0, 0.0, 0.0]);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Code inspired by the monadiccp Haskell library.
// credits to Control/CP/FD/OvertonFD/Domain.hs

use std::collections::BTreeSet;
use domain::Domain::*;
use std::iter::range_inclusive;
use std::cmp::{min, max};

#[deriving(PartialEq, Eq, Clone)]
pub enum Domain {
  Set(BTreeSet<int>),
  Range(int, int)
}

impl Domain {
  pub fn size(&self) -> uint {
    match self {
      &Set(ref ts) => ts.len(),
      &Range(l, u) => (u - l + 1) as uint
    }
  }

  pub fn member(&self, n: int) -> bool {
    match self {
      &Set(ref ts) => ts.contains(&n),
      &Range(l, u) => n >= l && n <= u
    }
  }

  pub fn is_subset_of(&self, d: &Domain) -> bool {
    match (self, d) {
      (&Set(ref ts), &Set(ref ts2)) => ts.is_subset(ts2),
      (&Range(l, u), &Range(l2,u2)) => l >= l2 && u <= u2,
      (&Set(ref ts), r) => // (min, max) inside r.
        Range(ts.iter().next().unwrap().clone(),
              ts.iter().rev().next().unwrap().clone()).is_subset_of(r),
      (&Range(l, u), &Set(ref ts)) =>
        range_inclusive(l, u).all(|i| ts.contains(&i))
    }
  }

  pub fn intersection(&self, d: &Domain) -> Domain {
    match (self, d) {
      (&Set(ref ts), &Set(ref ts2)) => {
        let inter: BTreeSet<int> = ts.intersection(ts2).cloned().collect();
        inter.to_domain()
      }
      (&Range(l, u), &Range(l2, u2)) => Range(max(l, l2), min(u, u2)),
      (&Set(ref ts), ref r) => {
        let inter: BTreeSet<int> = ts.clone().into_iter()
          .filter(|&x| r.member(x)).collect();
        inter.to_domain()
      }
      (r, s) => s.intersection(r)
    }
  }
}

trait ToDomain {
  fn to_domain(self) -> Domain;
}

impl ToDomain for Domain {
  fn to_domain(self) -> Domain { self }
}

impl ToDomain for BTreeSet<int> {
  fn to_domain(self) -> Domain {
    Set(self)
  }
}

impl ToDomain for (int, int) {
  fn to_domain(self) -> Domain {
    let (a, b) = self;
    Range(a, b)
  }
}

impl ToDomain for int {
  fn to_domain(self) -> Domain {
    Range(self.clone(), self)
  }
}

impl ToDomain for Vec<int> {
  fn to_domain(self) -> Domain {
    Set(FromIterator::from_iter(self.into_iter()))
  }
}

#[test]
fn to_domain_id_test() {
  let d1 = Range(1, 2);
  let d1_id = d1.clone().to_domain();
  assert!(d1 == d1_id);
  assert!(d1 == Range(1, 2));
  assert!(d1.size() == 2);
}

#[test]
fn member_test() {
  let d1 = Range(5, 50);
  assert!(d1.member(5));
  assert!(d1.member(50));
  assert!(d1.member(30));

  let d2 = vec![1,4,8,19,25].to_domain();
  assert!(d2.member(1));
  assert!(d2.member(19));
}

#[test]
fn is_subset_of_test() {
  let d1 = Range(2, 10);
  let d2 = Range(2, 10);
  assert!(d1.is_subset_of(&d2));
  assert!(d2.is_subset_of(&d1));
  let d3 = Range(3, 10);
  assert!(d3.is_subset_of(&d1));
  assert!(!d2.is_subset_of(&d3));
  assert!(!Range(3,12).is_subset_of(&d1));
  assert!(!Range(0, 9).is_subset_of(&d1));

  let d4 = vec![4,9,3,2].to_domain();
  let d5 = d4.clone();
  assert!(d4.is_subset_of(&d5));
  assert!(d5.is_subset_of(&d4));

  assert!(d4.is_subset_of(&d1));
  assert!(!d1.is_subset_of(&d4));

  let d6 = Range(2,4);
  assert!(d6.is_subset_of(&d4));
  assert!(!d4.is_subset_of(&d6));

  let d7 = vec![2,9,3].to_domain();
  assert!(d7.is_subset_of(&d4));
  assert!(!d4.is_subset_of(&d7));
}

#[test]
fn intersection_test() {
  let d1 = Range(2, 10);
  let d2 = Range(2, 10);
  assert!(d1.intersection(&d2) == d1);
  let d3 = Range(3, 13);
  assert!(d3.intersection(&d1) == Range(3, 10));
  let d4 = Range(0, 9);
  assert!(d4.intersection(&d1) == Range(2, 9));

  let d5 = vec![3,4,7,8].to_domain();
  assert!(d5.intersection(&d5.clone()) == d5);

  let d6 = vec![1,2,3,10].to_domain();
  assert!(d5.intersection(&d6) == vec![3].to_domain());
  assert!(d6.intersection(&d5) == vec![3].to_domain());

  assert!(d1.intersection(&d5) == d5);
  assert!(d5.intersection(&d1) == d5);
  assert!(d6.intersection(&d4) == vec![1,2,3].to_domain());
  assert!(d4.intersection(&d6) == vec![1,2,3].to_domain());
}
<commit_msg>Add the union operation on domain.<commit_after>// Copyright 2014 Pierre Talbot (IRCAM)

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at

//     http://www.apache.org/licenses/LICENSE-2.0

// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Code inspired by the monadiccp Haskell library.
// credits to Control/CP/FD/OvertonFD/Domain.hs

use std::collections::BTreeSet;
use domain::Domain::*;
use std::iter::range_inclusive;
use std::cmp::{min, max};

#[deriving(PartialEq, Eq, Clone, Show)]
pub enum Domain {
  Set(BTreeSet<int>),
  Range(int, int)
}

impl Domain {
  pub fn empty() -> Domain {
    Range(1, 0)
  }

  pub fn size(&self) -> uint {
    match self {
      &Set(ref ts) => ts.len(),
      &Range(l, u) => (u - l + 1) as uint
    }
  }

  pub fn is_empty(&self) -> bool {
    match self {
      &Set(ref ts) => ts.is_empty(),
      &Range(l, u) => l > u
    }
  }

  pub fn member(&self, n: int) -> bool {
    match self {
      &Set(ref ts) => ts.contains(&n),
      &Range(l, u) => n >= l && n <= u
    }
  }

  pub fn is_subset_of(&self, d: &Domain) -> bool {
    match (self, d) {
      (&Set(ref ts), &Set(ref ts2)) => ts.is_subset(ts2),
      (&Range(l, u), &Range(l2,u2)) => l >= l2 && u <= u2,
      (s@&Set(_), r) => // (min, max) inside r.
        Range(s.min(), s.max()).is_subset_of(r),
      (&Range(l, u), &Set(ref ts)) =>
        range_inclusive(l, u).all(|i| ts.contains(&i))
    }
  }

  pub fn intersection(&self, d: &Domain) -> Domain {
    match (self, d) {
      (&Set(ref ts), &Set(ref ts2)) => {
        let inter: BTreeSet<int> = ts.intersection(ts2).cloned().collect();
        inter.to_domain()
      }
      (&Range(l, u), &Range(l2, u2)) => Range(max(l, l2), min(u, u2)),
      (&Set(ref ts), ref r) => {
        let inter: BTreeSet<int> = ts.clone().into_iter()
          .filter(|&x| r.member(x)).collect();
        inter.to_domain()
      }
      (r, s) => s.intersection(r)
    }
  }

  pub fn union(&self, d: &Domain) -> Domain {
    match (self, d) {
      (&Set(ref ts), &Set(ref ts2)) => {
        let inter: BTreeSet<int> = ts.union(ts2).cloned().collect();
        inter.to_domain()
      }
      (&Range(l, u), &Range(l2, u2)) => {
        if Domain::joinable(l,u,l2,u2) { Domain::join(l,u,l2,u2) }
        else {
          Domain::set_from_range(l, u).union(&Domain::set_from_range(l2, u2))
        }
      }
      (s@&Set(_), &Range(l, u)) => {
        if s.is_empty() { Range(l, u) }
        else {
          let lmin = s.min();
          let umax = s.max();
          if Domain::joinable(lmin, umax, l, u) {
            Domain::join(lmin, umax, l, u)
          } else {
            s.union(&Domain::set_from_range(l, u))
          }
        }
      }
      (x, y) => y.union(x)
    }
  }

  fn joinable(l:int, u: int, l2: int, u2: int) -> bool {
    // sort on the lower bound (factorizing symetric cases).
    if l2 < l { Domain::joinable(l2, u2, l, u) }
    // Only 3 cases.
    // |---|      |---|       |---|
    //   |---|         |---|   |-|
    else { l2 >= l && l2 <= u + 1 }
  }

  fn join(l: int, u: int, l2: int, u2: int) -> Domain {
     Range(min(l,l2), max(u, u2))
  }

  fn set_from_range(l: int, u: int) -> Domain {
    Set(FromIterator::from_iter(range_inclusive(l,u)))
  }

  pub fn min(&self) -> int {
    match self {
      &Set(ref ts) => ts.iter().next().unwrap().clone(),
      &Range(l,_) => l
    }
  }

  pub fn max(&self) -> int {
    match self {
      &Set(ref ts) => ts.iter().rev().next().unwrap().clone(),
      &Range(_,u) => u
    }
  }
}

trait ToDomain {
  fn to_domain(self) -> Domain;
}

impl ToDomain for Domain {
  fn to_domain(self) -> Domain { self }
}

impl ToDomain for BTreeSet<int> {
  fn to_domain(self) -> Domain {
    Set(self)
  }
}

impl ToDomain for (int, int) {
  fn to_domain(self) -> Domain {
    let (a, b) = self;
    Range(a, b)
  }
}

impl ToDomain for int {
  fn to_domain(self) -> Domain {
    Range(self.clone(), self)
  }
}

impl ToDomain for Vec<int> {
  fn to_domain(self) -> Domain {
    Set(FromIterator::from_iter(self.into_iter()))
  }
}

#[test]
fn to_domain_id_test() {
  let d1 = Range(1, 2);
  let d1_id = d1.clone().to_domain();
  assert!(d1 == d1_id);
  assert!(d1 == Range(1, 2));
  assert!(d1.size() == 2);
}

#[test]
fn member_test() {
  let d1 = Range(5, 50);
  assert!(d1.member(5));
  assert!(d1.member(50));
  assert!(d1.member(30));

  let d2 = vec![1,4,8,19,25].to_domain();
  assert!(d2.member(1));
  assert!(d2.member(19));
}

#[test]
fn is_subset_of_test() {
  let d1 = Range(2, 10);
  let d2 = Range(2, 10);
  assert!(d1.is_subset_of(&d2));
  assert!(d2.is_subset_of(&d1));
  let d3 = Range(3, 10);
  assert!(d3.is_subset_of(&d1));
  assert!(!d2.is_subset_of(&d3));
  assert!(!Range(3,12).is_subset_of(&d1));
  assert!(!Range(0, 9).is_subset_of(&d1));

  let d4 = vec![4,9,3,2].to_domain();
  let d5 = d4.clone();
  assert!(d4.is_subset_of(&d5));
  assert!(d5.is_subset_of(&d4));

  assert!(d4.is_subset_of(&d1));
  assert!(!d1.is_subset_of(&d4));

  let d6 = Range(2,4);
  assert!(d6.is_subset_of(&d4));
  assert!(!d4.is_subset_of(&d6));

  let d7 = vec![2,9,3].to_domain();
  assert!(d7.is_subset_of(&d4));
  assert!(!d4.is_subset_of(&d7));
}

#[test]
fn intersection_test() {
  let d1 = Range(2, 10);
  let d2 = Range(2, 10);
  assert!(d1.intersection(&d2) == d1);
  let d3 = Range(3, 13);
  assert!(d3.intersection(&d1) == Range(3, 10));
  let d4 = Range(0, 9);
  assert!(d4.intersection(&d1) == Range(2, 9));

  let d5 = vec![3,4,7,8].to_domain();
  assert!(d5.intersection(&d5.clone()) == d5);

  let d6 = vec![1,2,3,10].to_domain();
  assert!(d5.intersection(&d6) == vec![3].to_domain());
  assert!(d6.intersection(&d5) == vec![3].to_domain());

  assert!(d1.intersection(&d5) == d5);
  assert!(d5.intersection(&d1) == d5);
  assert!(d6.intersection(&d4) == vec![1,2,3].to_domain());
  assert!(d4.intersection(&d6) == vec![1,2,3].to_domain());
}

#[test]
fn union_test() {
  let d1 = Range(2, 4);
  assert!(d1.union(&d1.clone()) == d1);
  let d2 = Range(5, 7);
  assert!(d1.union(&d2) == Range(2,7));
  assert!(d2.union(&d1) == Range(2,7));
  let d3 = Range(6, 7);
  assert!(d1.union(&d3) == vec![2,3,4,6,7].to_domain());
  assert!(d3.union(&d1) == vec![2,3,4,6,7].to_domain());
  assert!(d2.union(&d3) == Range(5,7));
  let d4 = vec![1,5].to_domain();
  assert!(d1.union(&d4) == Range(1,5));
  assert!(d2.union(&d4) == Range(1,7));
  assert!(d3.union(&d4) == Range(1,7));
  // disjoint test.
  let d5 = Range(8,9);
  assert!(d5.union(&d4) == vec![1,5,8,9].to_domain());
  assert!(d4.union(&d5) == vec![1,5,8,9].to_domain());
  let d6 = vec![8,9].to_domain();
  let d7 = Range(1,5);
  assert!(d6.union(&d7) == vec![1,2,3,4,5,8,9].to_domain());
  assert!(d7.union(&d6) == vec![1,2,3,4,5,8,9].to_domain());
}<|endoftext|>


<commit_before>use winapi::shared::ws2def::{AF_INET, AF_INET6, AF_UNSPEC, SOCKADDR};
use winapi::shared::winerror::{ERROR_BUFFER_OVERFLOW, ERROR_SUCCESS};
use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH;
use winapi::shared::minwindef::*;
use winapi::ctypes::*;
use libc::{size_t, c_void,  malloc, free};

use data::*;

use std::{io, ptr};
use std::io::Error;
use std::mem;
use std::collections::BTreeMap;

// unions with non-`Copy` fields are unstable (see issue #32836)
// #[repr(C)]
// union AlimentOrLengthIfIndex {
//     aliment: c_ulonglong,
//     length_ifindex: LengthIfIndex,
// }

#[repr(C)]
struct LengthIfIndex{
    length: ULONG,
    ifindex: DWORD,
}

#[repr(C)]
struct LengthFlags{
    length: ULONG,
    flags: DWORD,
}

#[repr(C)]
struct SoketAddress{
    lp_sockaddr: *mut SOCKADDR,
    i_sockaddr_length: c_int
}

#[repr(C)]
struct IpAdapterPrefix{
    aol: LengthIfIndex,
    next: *mut IpAdapterPrefix,
    address: SoketAddress,
    prefix_length: ULONG,
}

#[repr(C)]
struct IpAdapterUnicastAddress {
    aol: LengthFlags,
    next: *mut IpAdapterUnicastAddress,
    address: SoketAddress,
    prefix_origin: c_int,
    suffix_origin: c_int,
    dad_state: c_int,
    valid_lifetime: ULONG,
    preferred_lifetime: ULONG,
    lease_lifetime: ULONG,
}

const MAX_ADAPTER_ADDRESS_LENGTH: usize = 8;

#[repr(C)]
struct IpAdapterAddresses{
    aol: LengthIfIndex,
    next: *mut IpAdapterAddresses,
    adapter_name:  *mut c_char,
    first_unicass_address: *mut IpAdapterUnicastAddress,
    first_anycass_address: *const c_void,
    first_multicass_address: *const c_void,
    first_dns_server_address: *const c_void,
    dns_suffix: *mut wchar_t,
    description: *mut wchar_t,
    friendly_name:  *mut wchar_t,
    physical_address: [u8; MAX_ADAPTER_ADDRESS_LENGTH],
    physical_address_length: DWORD,
    flags: DWORD,
    mtu: DWORD,
    if_type: DWORD,
    oper_status: c_int,
    ipv6_if_index: DWORD,
    zone_indices:  [DWORD;16],
    first_prefix: *mut IpAdapterPrefix,
}

// https://msdn.microsoft.com/en-us/library/aa365915(v=vs.85).aspx
// C:\Program Files (x86)\Windows Kits\8.1\Include\um\IPHlpApi.h
#[link(name = "Iphlpapi")]
extern "system" {
    fn GetAdaptersAddresses(
        family: ULONG,
        flags: ULONG,
        reserved: *const c_void,
        addresses: *mut IpAdapterAddresses,
        size: *mut ULONG,
    ) -> ULONG;
}

const WORKING_BUFFER_SIZEL: size_t = 15000;

pub fn interfaces() -> io::Result<BTreeMap<String, Network>> {
    let mut new_size:ULONG = WORKING_BUFFER_SIZEL as ULONG;
    let mut p_adapter: *mut IpAdapterAddresses;
    loop {
        unsafe {
            p_adapter = malloc( WORKING_BUFFER_SIZEL) as *mut IpAdapterAddresses;
            if p_adapter.is_null() {
                panic!("Failed: malloc!");
            }
            let res_code = GetAdaptersAddresses (
                0,
                AF_UNSPEC as ULONG, // ipv4 & ipv6
                ptr::null(),
                p_adapter,
                &mut new_size as *mut ULONG
            );
            match res_code {
                // 0
                ERROR_SUCCESS => break,
                // 111, retry
                ERROR_BUFFER_OVERFLOW => {
                    new_size*=2;
                    free(p_adapter as *mut c_void);
                    continue;
                }
                _=> {
                    return Err( Error::last_os_error());
                }
            }
        }
    }

    let mut map = BTreeMap::new();
    // key->adapter_name, name-> friendly_name, maybe should use the adapter_name all.
    unsafe {
        let mut cur_p_adapter = p_adapter;
        while !cur_p_adapter.is_null() {
            // name, mac, etc
            let adapter_name = c_char_array_to_string( (*cur_p_adapter).adapter_name);
            // println!("adapter_name : {}", adapter_name);

            // let dns_suffix = u16_array_to_string((*cur_p_adapter).dns_suffix);
            // println!("dns_suffix   : {}", dns_suffix);

            let friendly_name =  u16_array_to_string((*cur_p_adapter).friendly_name);
            // println!("friendly_name: {}", friendly_name);

            // let description = u16_array_to_string((*cur_p_adapter).description);
            // println!("description  : {}", description);

            // let mac = physical_address_to_string(&(*cur_p_adapter).physical_address, (*cur_p_adapter).physical_address_length);
            // println!("mac          : {}", mac);

            let mut addrs = Vec::new();
            // ip
            let mut cur_p_addr = (*cur_p_adapter).first_unicass_address;
            while !cur_p_addr.is_null() {
                let addr = parse_addr((*cur_p_addr).address.lp_sockaddr);
                addrs.push(addr);
               // println!("{:?}", addr);
               // next addr
               cur_p_addr =(*cur_p_addr).next;
            }
            let network = Network {
                name: friendly_name,
                addrs: addrs.iter().map(|addr| NetworkAddrs {addr: addr.clone(), netmask: IpAddr::Unsupported}).collect()
            };
            map.insert(adapter_name,network);

            // next adapter
            cur_p_adapter = (*cur_p_adapter).next;
        }
    }

    unsafe { free(p_adapter as *mut c_void); }
    Ok(map)
}

use std::slice::from_raw_parts;
fn u16_array_to_string(p: *const u16) ->String {
    use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
    unsafe {
        if p.is_null() {
            return String::new();
        }
        let mut amt = 0usize;
        while !p.offset(amt as isize).is_null() &&  *p.offset(amt as isize) != 0u16 {
            amt+=1;
        }
        let u16s = from_raw_parts(p, amt);
        decode_utf16(u16s.iter().cloned())
        .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
        .collect::<String>()
    }
}

use std::ffi::CStr;
fn c_char_array_to_string(p: *const c_char) -> String {
    unsafe {
        CStr::from_ptr(p).to_string_lossy().into_owned()
    }
}

use std::io::Write;

fn physical_address_to_string(array: &[u8;8], length: DWORD) -> String {
    let mut bytes = Vec::with_capacity(length as usize);
    for idx in 0..length as usize {
        if idx == 0  {
            write!(&mut bytes, "{:02X}", array[idx]).unwrap();
        } else {
            write!(&mut bytes, "-{:02X}", array[idx]).unwrap();
        }
    }
    String::from_utf8_lossy(&bytes[..]).into_owned()
}

// Thanks , copy from unix.rs and some modify
fn parse_addr(aptr: *const SOCKADDR) -> IpAddr {
    if aptr == ptr::null() {
        return IpAddr::Empty;
    }
    let addr = unsafe { *aptr };
    match addr.sa_family as i32 {
        AF_INET => IpAddr::V4(Ipv4Addr::new(addr.sa_data[2] as u8, addr.sa_data[3] as u8,
                                            addr.sa_data[4] as u8, addr.sa_data[5] as u8)),
        AF_INET6 => {
            // This is horrible.
            let addr6: *const SOCKADDR_IN6_LH = unsafe { mem::transmute(aptr) };
            let mut a: [u8; 16] = unsafe { *(*addr6).sin6_addr.u.Byte() };
            &mut a[..].reverse();
            let a: [u16; 8] = unsafe { mem::transmute(a) };
            IpAddr::V6(Ipv6Addr::new(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]))
        },
        _ => IpAddr::Unsupported,
    }
}<commit_msg>clear up the code.<commit_after>use winapi::shared::ws2def::{AF_INET, AF_INET6, AF_UNSPEC, SOCKADDR};
use winapi::shared::winerror::{ERROR_BUFFER_OVERFLOW, ERROR_SUCCESS};
use winapi::shared::ws2ipdef::SOCKADDR_IN6_LH;
use winapi::shared::minwindef::*;
use winapi::ctypes::*;
use libc::{size_t, c_void,  malloc, free};

use data::*;

use std::collections::BTreeMap;
use std::io::{Write, Error};
use std::slice::from_raw_parts;
use std::{io, ptr, mem};
use std::ffi::CStr;

// unions with non-`Copy` fields are unstable (see issue #32836)
// #[repr(C)]
// union AlimentOrLengthIfIndex {
//     aliment: c_ulonglong,
//     length_ifindex: LengthIfIndex,
// }

#[repr(C)]
struct LengthIfIndex{
    length: ULONG,
    ifindex: DWORD,
}

#[repr(C)]
struct LengthFlags{
    length: ULONG,
    flags: DWORD,
}

#[repr(C)]
struct SoketAddress{
    lp_sockaddr: *mut SOCKADDR,
    i_sockaddr_length: c_int
}

#[repr(C)]
struct IpAdapterPrefix{
    aol: LengthIfIndex,
    next: *mut IpAdapterPrefix,
    address: SoketAddress,
    prefix_length: ULONG,
}

#[repr(C)]
struct IpAdapterUnicastAddress {
    aol: LengthFlags,
    next: *mut IpAdapterUnicastAddress,
    address: SoketAddress,
    prefix_origin: c_int,
    suffix_origin: c_int,
    dad_state: c_int,
    valid_lifetime: ULONG,
    preferred_lifetime: ULONG,
    lease_lifetime: ULONG,
}

const MAX_ADAPTER_ADDRESS_LENGTH: usize = 8;

#[repr(C)]
struct IpAdapterAddresses{
    aol: LengthIfIndex,
    next: *mut IpAdapterAddresses,
    adapter_name:  *mut c_char,
    first_unicass_address: *mut IpAdapterUnicastAddress,
    first_anycass_address: *const c_void,
    first_multicass_address: *const c_void,
    first_dns_server_address: *const c_void,
    dns_suffix: *mut wchar_t,
    description: *mut wchar_t,
    friendly_name:  *mut wchar_t,
    physical_address: [u8; MAX_ADAPTER_ADDRESS_LENGTH],
    physical_address_length: DWORD,
    flags: DWORD,
    mtu: DWORD,
    if_type: DWORD,
    oper_status: c_int,
    ipv6_if_index: DWORD,
    zone_indices:  [DWORD;16],
    first_prefix: *mut IpAdapterPrefix,
}

// https://msdn.microsoft.com/en-us/library/aa365915(v=vs.85).aspx
// C:\Program Files (x86)\Windows Kits\8.1\Include\um\IPHlpApi.h
#[link(name = "Iphlpapi")]
extern "system" {
    fn GetAdaptersAddresses(
        family: ULONG,
        flags: ULONG,
        reserved: *const c_void,
        addresses: *mut IpAdapterAddresses,
        size: *mut ULONG,
    ) -> ULONG;
}

const WORKING_BUFFER_SIZEL: size_t = 15000;

pub fn interfaces() -> io::Result<BTreeMap<String, Network>> {
    let mut new_size:ULONG = WORKING_BUFFER_SIZEL as ULONG;
    let mut p_adapter: *mut IpAdapterAddresses;
    loop {
        unsafe {
            p_adapter = malloc( WORKING_BUFFER_SIZEL) as *mut IpAdapterAddresses;
            if p_adapter.is_null() {
                panic!("Failed: malloc!");
            }
            let res_code = GetAdaptersAddresses (
                0,
                AF_UNSPEC as ULONG, // ipv4 & ipv6
                ptr::null(),
                p_adapter,
                &mut new_size as *mut ULONG
            );
            match res_code {
                // 0
                ERROR_SUCCESS => break,
                // 111, retry
                ERROR_BUFFER_OVERFLOW => {
                    new_size*=2;
                    free(p_adapter as *mut c_void);
                    continue;
                }
                _=> {
                    return Err( Error::last_os_error());
                }
            }
        }
    }

    let mut map = BTreeMap::new();
    // key->adapter_name, name-> friendly_name, maybe should use the adapter_name all.
    unsafe {
        let mut cur_p_adapter = p_adapter;
        while !cur_p_adapter.is_null() {
            // name, mac, etc
            let adapter_name = c_char_array_to_string( (*cur_p_adapter).adapter_name);
            // println!("adapter_name : {}", adapter_name);

            // let dns_suffix = u16_array_to_string((*cur_p_adapter).dns_suffix);
            // println!("dns_suffix   : {}", dns_suffix);

            let friendly_name =  u16_array_to_string((*cur_p_adapter).friendly_name);
            // println!("friendly_name: {}", friendly_name);

            // let description = u16_array_to_string((*cur_p_adapter).description);
            // println!("description  : {}", description);

            // let mac = physical_address_to_string(&(*cur_p_adapter).physical_address, (*cur_p_adapter).physical_address_length);
            // println!("mac          : {}", mac);

            let mut addrs = Vec::new();
            // ip
            let mut cur_p_addr = (*cur_p_adapter).first_unicass_address;
            while !cur_p_addr.is_null() {
                let addr = parse_addr((*cur_p_addr).address.lp_sockaddr);
                addrs.push(addr);
               // println!("{:?}", addr);
               // next addr
               cur_p_addr =(*cur_p_addr).next;
            }
            let network = Network {
                name: friendly_name,
                addrs: addrs.into_iter().map(|addr| NetworkAddrs {addr: addr, netmask: IpAddr::Unsupported}).collect()
            };
            map.insert(adapter_name,network);

            // next adapter
            cur_p_adapter = (*cur_p_adapter).next;
        }
    }

    unsafe { free(p_adapter as *mut c_void); }
    Ok(map)
}

fn u16_array_to_string(p: *const u16) ->String {
    use std::char::{decode_utf16, REPLACEMENT_CHARACTER};
    unsafe {
        if p.is_null() {
            return String::new();
        }
        let mut amt = 0usize;
        while !p.offset(amt as isize).is_null() &&  *p.offset(amt as isize) != 0u16 {
            amt+=1;
        }
        let u16s = from_raw_parts(p, amt);
        decode_utf16(u16s.iter().cloned())
        .map(|r| r.unwrap_or(REPLACEMENT_CHARACTER))
        .collect::<String>()
    }
}

fn c_char_array_to_string(p: *const c_char) -> String {
    unsafe {
        CStr::from_ptr(p).to_string_lossy().into_owned()
    }
}

fn physical_address_to_string(array: &[u8;8], length: DWORD) -> String {
    let mut bytes = Vec::with_capacity(length as usize);
    for idx in 0..length as usize {
        if idx == 0  {
            write!(&mut bytes, "{:02X}", array[idx]).unwrap();
        } else {
            write!(&mut bytes, "-{:02X}", array[idx]).unwrap();
        }
    }
    String::from_utf8_lossy(&bytes[..]).into_owned()
}

// Thanks , copy from unix.rs and some modify
fn parse_addr(aptr: *const SOCKADDR) -> IpAddr {
    if aptr == ptr::null() {
        return IpAddr::Empty;
    }
    let addr = unsafe { *aptr };
    match addr.sa_family as i32 {
        AF_INET => IpAddr::V4(Ipv4Addr::new(addr.sa_data[2] as u8, addr.sa_data[3] as u8,
                                            addr.sa_data[4] as u8, addr.sa_data[5] as u8)),
        AF_INET6 => {
            // This is horrible.
            let addr6: *const SOCKADDR_IN6_LH = unsafe { mem::transmute(aptr) };
            let mut a: [u8; 16] = unsafe { *(*addr6).sin6_addr.u.Byte() };
            &mut a[..].reverse();
            let a: [u16; 8] = unsafe { mem::transmute(a) };
            IpAddr::V6(Ipv6Addr::new(a[7], a[6], a[5], a[4], a[3], a[2], a[1], a[0]))
        },
        _ => IpAddr::Unsupported,
    }
}<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::rc::Rc;
use syntax::abi;
use syntax::ast::TokenTree;
use syntax::ast;
use syntax::ast_util::empty_generics;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::{ToTokens, ExtParseUtils};
use syntax::parse::token::InternedString;
use syntax::ptr::P;

use node;

mod mcu;
mod os;
pub mod meta_args;

pub struct Builder {
  main_stmts: Vec<P<ast::Stmt>>,
  type_items: Vec<P<ast::Item>>,
  pt: Rc<node::PlatformTree>,
}

impl Builder {
  pub fn build(cx: &mut ExtCtxt, pt: Rc<node::PlatformTree>) -> Option<Builder> {
    let mut builder = Builder::new(pt.clone());

    if !pt.expect_subnodes(cx, ["mcu", "os", "drivers"]) {
      return None;
    }

    match pt.get_by_path("mcu") {
      Some(node) => mcu::attach(&mut builder, cx, node),
      None => (),  // TODO(farcaller): should it actaully fail?
    }

    match pt.get_by_path("os") {
      Some(node) => os::attach(&mut builder, cx, node),
      None => (),  // TODO(farcaller): this should fail.
    }

    match pt.get_by_path("drivers") {
      Some(node) => ::drivers_pt::attach(&mut builder, cx, node),
      None => (),
    }

    for sub in pt.nodes().iter() {
      Builder::walk_mutate(&mut builder, cx, sub);
    }

    let base_node = pt.get_by_path("mcu").and_then(|mcu|{mcu.get_by_path("clock")});
    match base_node {
      Some(node) => Builder::walk_materialize(&mut builder, cx, node),
      None => {
        cx.parse_sess().span_diagnostic.span_err(DUMMY_SP,
            "root node `mcu::clock` must be present");
      }
    }

    Some(builder)
  }

  fn walk_mutate(builder: &mut Builder, cx: &mut ExtCtxt, node: &Rc<node::Node>) {
    let maybe_mut = node.mutator.get();
    if maybe_mut.is_some() {
      maybe_mut.unwrap()(builder, cx, node.clone());
    }
    for sub in node.subnodes().iter() {
      Builder::walk_mutate(builder, cx, sub);
    }
  }

  // FIXME(farcaller): verify that all nodes have been materialized
  fn walk_materialize(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
    let maybe_mat = node.materializer.get();
    if maybe_mat.is_some() {
      maybe_mat.unwrap()(builder, cx, node.clone());
    }
    let rev_depends = node.rev_depends_on.borrow();
    for weak_sub in rev_depends.iter() {
      let sub = weak_sub.upgrade().unwrap();
      let mut sub_deps = sub.depends_on.borrow_mut();
      let deps = sub_deps.deref_mut();
      let mut index = None;
      let mut i = 0u;
      // FIXME: iter().position()
      for dep in deps.iter() {
        let strong_dep = dep.upgrade().unwrap();
        if node == strong_dep {
          index = Some(i);
          break;
        }
        i = i + 1;
      }
      if index.is_none() {
        fail!("no index found");
      } else {
        deps.remove(index.unwrap());
        if deps.len() == 0 {
          Builder::walk_materialize(builder, cx, sub.clone());
        }
      }
    }
  }

  pub fn new(pt: Rc<node::PlatformTree>) -> Builder {
    Builder {
      main_stmts: Vec::new(),
      type_items: Vec::new(),
      pt: pt,
    }
  }

  pub fn main_stmts(&self) -> Vec<P<ast::Stmt>> {
    self.main_stmts.clone()
  }

  pub fn pt(&self) -> Rc<node::PlatformTree> {
    self.pt.clone()
  }

  pub fn add_main_statement(&mut self, stmt: P<ast::Stmt>) {
    self.main_stmts.push(stmt);
  }

  pub fn add_type_item(&mut self, item: P<ast::Item>) {
    self.type_items.push(item);
  }

  fn emit_main(&self, cx: &ExtCtxt) -> P<ast::Item> {
    // init stack
    let init_stack_stmt = cx.stmt_expr(quote_expr!(&*cx,
        zinc::hal::mem_init::init_stack();
    ));

    // init data
    let init_data_stmt = cx.stmt_expr(quote_expr!(&*cx,
        zinc::hal::mem_init::init_data();
    ));

    let mut stmts = vec!(init_stack_stmt, init_data_stmt);
    stmts.push_all(self.main_stmts.as_slice());

    let body = cx.block(DUMMY_SP, stmts, None);

    let unused_variable = cx.meta_word(DUMMY_SP,
        InternedString::new("unused_variable"));
    let allow = cx.meta_list(
        DUMMY_SP,
        InternedString::new("allow"), vec!(unused_variable));
    let allow_noncamel = cx.attribute(DUMMY_SP, allow);

    self.item_fn(cx, DUMMY_SP, "main", [allow_noncamel], body)
  }

  fn emit_morestack(&self, cx: &ExtCtxt) -> P<ast::Item> {
    let stmt = cx.stmt_expr(quote_expr!(&*cx,
        core::intrinsics::abort()
        // or
        // zinc::os::task::morestack();
    ));
    let empty_span = DUMMY_SP;
    let body = cx.block(empty_span, vec!(stmt), None);
    self.item_fn(cx, empty_span, "__morestack", [], body)
  }

  pub fn emit_items(&self, cx: &ExtCtxt) -> Vec<P<ast::Item>> {
    let non_camel_case_types = cx.meta_word(DUMMY_SP,
        InternedString::new("non_camel_case_types"));
    let allow = cx.meta_list(
        DUMMY_SP,
        InternedString::new("allow"), vec!(non_camel_case_types));
    let allow_noncamel = cx.attribute(DUMMY_SP, allow);
    let use_zinc = cx.view_use_simple(DUMMY_SP, ast::Inherited, cx.path_ident(
        DUMMY_SP, cx.ident_of("zinc")));
    let pt_mod_item = cx.item_mod(DUMMY_SP, DUMMY_SP, cx.ident_of("pt"),
        vec!(allow_noncamel), vec!(use_zinc), self.type_items.clone());

    if self.type_items.len() > 0 {
      vec!(pt_mod_item, self.emit_main(cx), self.emit_morestack(cx))
    } else {
      vec!(self.emit_main(cx), self.emit_morestack(cx))
    }
  }

  fn item_fn(&self, cx: &ExtCtxt, span: Span, name: &str,
      local_attrs: &[ast::Attribute], body: P<ast::Block>)
      -> P<ast::Item> {
    let attr_no_mangle = cx.attribute(span, cx.meta_word(
        span, InternedString::new("no_mangle")));
    let attr_no_stack_check = cx.attribute(span, cx.meta_word(
        span, InternedString::new("no_stack_check")));
    let mut attrs = vec!(attr_no_mangle, attr_no_stack_check);
    attrs.push_all(local_attrs);

    P(ast::Item {
      ident: cx.ident_of(name),
      attrs: attrs,
      id: ast::DUMMY_NODE_ID,
      node: ast::ItemFn(
          cx.fn_decl(Vec::new(), cx.ty_nil()),
          ast::UnsafeFn,
          abi::Rust, // TODO(farcaller): should this be abi::C?
          empty_generics(),
          body),
      vis: ast::Public,
      span: span,
    })
  }
}

pub struct TokenString(pub String);

impl ToTokens for TokenString {
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
    let &TokenString(ref s) = self;
    (cx as &ExtParseUtils).parse_tts(s.clone())
  }
}

pub fn add_node_dependency(node: &Rc<node::Node>, dep: &Rc<node::Node>) {
  let mut depends_on = node.depends_on.borrow_mut();
  depends_on.deref_mut().push(dep.downgrade());

  let mut rev_depends_on = dep.rev_depends_on.borrow_mut();
  rev_depends_on.push(node.downgrade());
}

#[cfg(test)]
mod test {
  use test_helpers::fails_to_build;

  #[test]
  fn fails_to_parse_pt_with_unknown_root_node() {
    fails_to_build("unknown@node {}");
  }

  #[test]
  fn fails_to_parse_pt_with_unknown_mcu() {
    fails_to_build("mcu@bad {}");
  }
}
<commit_msg>Removed missing #[no_stack_check] from test; unbreaks master<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::rc::Rc;
use syntax::abi;
use syntax::ast::TokenTree;
use syntax::ast;
use syntax::ast_util::empty_generics;
use syntax::codemap::{Span, DUMMY_SP};
use syntax::ext::base::ExtCtxt;
use syntax::ext::build::AstBuilder;
use syntax::ext::quote::rt::{ToTokens, ExtParseUtils};
use syntax::parse::token::InternedString;
use syntax::ptr::P;

use node;

mod mcu;
mod os;
pub mod meta_args;

pub struct Builder {
  main_stmts: Vec<P<ast::Stmt>>,
  type_items: Vec<P<ast::Item>>,
  pt: Rc<node::PlatformTree>,
}

impl Builder {
  pub fn build(cx: &mut ExtCtxt, pt: Rc<node::PlatformTree>) -> Option<Builder> {
    let mut builder = Builder::new(pt.clone());

    if !pt.expect_subnodes(cx, ["mcu", "os", "drivers"]) {
      return None;
    }

    match pt.get_by_path("mcu") {
      Some(node) => mcu::attach(&mut builder, cx, node),
      None => (),  // TODO(farcaller): should it actaully fail?
    }

    match pt.get_by_path("os") {
      Some(node) => os::attach(&mut builder, cx, node),
      None => (),  // TODO(farcaller): this should fail.
    }

    match pt.get_by_path("drivers") {
      Some(node) => ::drivers_pt::attach(&mut builder, cx, node),
      None => (),
    }

    for sub in pt.nodes().iter() {
      Builder::walk_mutate(&mut builder, cx, sub);
    }

    let base_node = pt.get_by_path("mcu").and_then(|mcu|{mcu.get_by_path("clock")});
    match base_node {
      Some(node) => Builder::walk_materialize(&mut builder, cx, node),
      None => {
        cx.parse_sess().span_diagnostic.span_err(DUMMY_SP,
            "root node `mcu::clock` must be present");
      }
    }

    Some(builder)
  }

  fn walk_mutate(builder: &mut Builder, cx: &mut ExtCtxt, node: &Rc<node::Node>) {
    let maybe_mut = node.mutator.get();
    if maybe_mut.is_some() {
      maybe_mut.unwrap()(builder, cx, node.clone());
    }
    for sub in node.subnodes().iter() {
      Builder::walk_mutate(builder, cx, sub);
    }
  }

  // FIXME(farcaller): verify that all nodes have been materialized
  fn walk_materialize(builder: &mut Builder, cx: &mut ExtCtxt, node: Rc<node::Node>) {
    let maybe_mat = node.materializer.get();
    if maybe_mat.is_some() {
      maybe_mat.unwrap()(builder, cx, node.clone());
    }
    let rev_depends = node.rev_depends_on.borrow();
    for weak_sub in rev_depends.iter() {
      let sub = weak_sub.upgrade().unwrap();
      let mut sub_deps = sub.depends_on.borrow_mut();
      let deps = sub_deps.deref_mut();
      let mut index = None;
      let mut i = 0u;
      // FIXME: iter().position()
      for dep in deps.iter() {
        let strong_dep = dep.upgrade().unwrap();
        if node == strong_dep {
          index = Some(i);
          break;
        }
        i = i + 1;
      }
      if index.is_none() {
        fail!("no index found");
      } else {
        deps.remove(index.unwrap());
        if deps.len() == 0 {
          Builder::walk_materialize(builder, cx, sub.clone());
        }
      }
    }
  }

  pub fn new(pt: Rc<node::PlatformTree>) -> Builder {
    Builder {
      main_stmts: Vec::new(),
      type_items: Vec::new(),
      pt: pt,
    }
  }

  pub fn main_stmts(&self) -> Vec<P<ast::Stmt>> {
    self.main_stmts.clone()
  }

  pub fn pt(&self) -> Rc<node::PlatformTree> {
    self.pt.clone()
  }

  pub fn add_main_statement(&mut self, stmt: P<ast::Stmt>) {
    self.main_stmts.push(stmt);
  }

  pub fn add_type_item(&mut self, item: P<ast::Item>) {
    self.type_items.push(item);
  }

  fn emit_main(&self, cx: &ExtCtxt) -> P<ast::Item> {
    // init stack
    let init_stack_stmt = cx.stmt_expr(quote_expr!(&*cx,
        zinc::hal::mem_init::init_stack();
    ));

    // init data
    let init_data_stmt = cx.stmt_expr(quote_expr!(&*cx,
        zinc::hal::mem_init::init_data();
    ));

    let mut stmts = vec!(init_stack_stmt, init_data_stmt);
    stmts.push_all(self.main_stmts.as_slice());

    let body = cx.block(DUMMY_SP, stmts, None);

    let unused_variable = cx.meta_word(DUMMY_SP,
        InternedString::new("unused_variable"));
    let allow = cx.meta_list(
        DUMMY_SP,
        InternedString::new("allow"), vec!(unused_variable));
    let allow_noncamel = cx.attribute(DUMMY_SP, allow);

    self.item_fn(cx, DUMMY_SP, "main", [allow_noncamel], body)
  }

  fn emit_morestack(&self, cx: &ExtCtxt) -> P<ast::Item> {
    let stmt = cx.stmt_expr(quote_expr!(&*cx,
        core::intrinsics::abort()
        // or
        // zinc::os::task::morestack();
    ));
    let empty_span = DUMMY_SP;
    let body = cx.block(empty_span, vec!(stmt), None);
    self.item_fn(cx, empty_span, "__morestack", [], body)
  }

  pub fn emit_items(&self, cx: &ExtCtxt) -> Vec<P<ast::Item>> {
    let non_camel_case_types = cx.meta_word(DUMMY_SP,
        InternedString::new("non_camel_case_types"));
    let allow = cx.meta_list(
        DUMMY_SP,
        InternedString::new("allow"), vec!(non_camel_case_types));
    let allow_noncamel = cx.attribute(DUMMY_SP, allow);
    let use_zinc = cx.view_use_simple(DUMMY_SP, ast::Inherited, cx.path_ident(
        DUMMY_SP, cx.ident_of("zinc")));
    let pt_mod_item = cx.item_mod(DUMMY_SP, DUMMY_SP, cx.ident_of("pt"),
        vec!(allow_noncamel), vec!(use_zinc), self.type_items.clone());

    if self.type_items.len() > 0 {
      vec!(pt_mod_item, self.emit_main(cx), self.emit_morestack(cx))
    } else {
      vec!(self.emit_main(cx), self.emit_morestack(cx))
    }
  }

  fn item_fn(&self, cx: &ExtCtxt, span: Span, name: &str,
      local_attrs: &[ast::Attribute], body: P<ast::Block>)
      -> P<ast::Item> {
    let attr_no_mangle = cx.attribute(span, cx.meta_word(
        span, InternedString::new("no_mangle")));
    let mut attrs = vec!(attr_no_mangle);
    attrs.push_all(local_attrs);

    P(ast::Item {
      ident: cx.ident_of(name),
      attrs: attrs,
      id: ast::DUMMY_NODE_ID,
      node: ast::ItemFn(
          cx.fn_decl(Vec::new(), cx.ty_nil()),
          ast::UnsafeFn,
          abi::Rust, // TODO(farcaller): should this be abi::C?
          empty_generics(),
          body),
      vis: ast::Public,
      span: span,
    })
  }
}

pub struct TokenString(pub String);

impl ToTokens for TokenString {
  fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
    let &TokenString(ref s) = self;
    (cx as &ExtParseUtils).parse_tts(s.clone())
  }
}

pub fn add_node_dependency(node: &Rc<node::Node>, dep: &Rc<node::Node>) {
  let mut depends_on = node.depends_on.borrow_mut();
  depends_on.deref_mut().push(dep.downgrade());

  let mut rev_depends_on = dep.rev_depends_on.borrow_mut();
  rev_depends_on.push(node.downgrade());
}

#[cfg(test)]
mod test {
  use test_helpers::fails_to_build;

  #[test]
  fn fails_to_parse_pt_with_unknown_root_node() {
    fails_to_build("unknown@node {}");
  }

  #[test]
  fn fails_to_parse_pt_with_unknown_mcu() {
    fails_to_build("mcu@bad {}");
  }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate type_operators;

pub trait Array<T> {}

type_operators! {
    [A, B, C, D, E]

    (Reify) Arrayify(_, T: _): (Array T) {

    }

    (Foo) Bar(All, All, All, All): All {

    }
}
<commit_msg>Note to self: Wait for travis build to finish before publishing to crates.io<commit_after>#[macro_use]
extern crate type_operators;
use type_operators::All;

pub trait Array<T> {}

type_operators! {
    [A, B, C, D, E]

    (Reify) Arrayify(_, T: _): (Array T) {

    }

    (Foo) Bar(All, All, All, All): All {

    }
}
<|endoftext|>