<commit_before>use std::io::{self, Buffer, Reader, Writer, IoResult, BufferedStream, standard_error};
use std::mem;
use std::collections::BTreeMap;
use std::rand::{thread_rng, Rng};
use std::{u64, u16};
use std::num::{Int, FromPrimitive, ToPrimitive};
use url::Url;

#[cfg(test)]
use test::Bencher;

use nonce::Nonce;
use message::{WSMessage, WSHeader, WS_MASK, WS_LEN, WS_LEN16, WS_LEN64, WS_OPCONT, WS_OPCODE, WS_OPTERM, WS_FIN};
use stream::NetworkStream;

pub struct WebSocket<S = NetworkStream> {
    stream: Option<BufferedStream<S>>,
    pub url: Url,
    hostname: String,
    use_ssl: bool,
}

impl WebSocket {
    pub fn new(url: Url) -> WebSocket {
        let use_ssl = url.scheme[] == "wss";

        let port = match url.port() {
            Some(p) => p,
            None if use_ssl => 443,
            _ => 80
        };

        WebSocket {
            stream: None,
            hostname: format!("{}:{}", url.serialize_host().unwrap(), port),
            url: url,
            use_ssl: use_ssl,
        }
    }

    fn try_connect(&mut self) -> IoResult<()> {
        self.stream = Some(BufferedStream::new(try!(NetworkStream::connect(self.hostname[], self.use_ssl))));
        Ok(())
    }

    fn write_request(&mut self, nonce: &str) -> IoResult<()> {
        let s = match self.stream { Some(ref mut s) => s, None => return Err(standard_error(io::IoErrorKind::NotConnected)) };

        try!(s.write(format!("GET {} HTTP/1.1\r\n", self.url.serialize_path().unwrap_or("/".to_string())).as_bytes()));
        try!(s.write(format!("Host: {}\r\n", self.url.host().unwrap()).as_bytes()));
        try!(s.write(format!("Origin: {}\r\n", self.url.serialize_no_fragment()).as_bytes()));
        try!(s.write(format!("Sec-WebSocket-Key: {}\r\n", nonce).as_bytes()));

        try!(s.write(b"Upgrade: websocket\r\n"));
        try!(s.write(b"Connection: Upgrade\r\n"));
        try!(s.write(b"Sec-WebSocket-Protocol: char, superchat\r\n"));
        try!(s.write(b"Sec-WebSocket-Version: 13\r\n"));
        try!(s.write(b"\r\n"));

        s.flush()
    }

    fn read_response(&mut self, nonce: &str) -> IoResult<()> {
        let spaces: &[_] = &[' ', '\t', '\r', '\n'];
        let s = match self.stream { Some(ref mut s) => s, None => return Err(standard_error(io::IoErrorKind::NotConnected)) };
        let status = try!(s.read_line())[].splitn(2, ' ').nth(1).and_then(|s| s.parse::<uint>());

        match status {
            Some(101) => (),
            _ => return Err(standard_error(io::InvalidInput))
        }

        let headers = s.lines().map(|r| r.unwrap_or("\r\n".to_string())) .take_while(|l| l[] != "\r\n")
            .map(|s| s[].splitn(1, ':').map(|s| s.trim_matches(spaces).to_string()).collect::<Vec<String>>())
            .map(|p| (p[0].to_string(), p[1].to_string()))
            .collect::<BTreeMap<String, String>>();

        try!(s.flush());

        let response = headers.get("Sec-WebSocket-Accept");
        match response {
            Some(r) if nonce == r[] => (),
            _ => return Err(standard_error(io::InvalidInput))
        }

        Ok(())
    }

    pub fn connect(&mut self) -> IoResult<()> {
        let mut nonce = Nonce::new();

        try!(self.try_connect());
        try!(self.write_request(nonce[]));

        nonce = nonce.encode();
        try!(self.read_response(nonce[]));

        Ok(())
    }

    fn read_header(&mut self) -> IoResult<WSHeader> {
        // XXX: this is a bug, WSHeader should accept u16
        Ok(WSHeader::from_bits_truncate(try!(self.read_be_u16())))
    }

    fn read_length(&mut self, header: &WSHeader) -> IoResult<uint> {
        let wslen = *header & WS_LEN;
        if wslen == WS_LEN16 { self.read_be_u16().map(|v| v as uint) }
        else if wslen == WS_LEN64 { self.read_be_u64().map(|v| v as uint) }
        else { Ok(wslen.bits() as uint) }
    }

    pub fn read_message(&mut self) -> IoResult<WSMessage> {
        let header = try!(self.read_header());
        let mut len = try!(self.read_length(&header));

        let mask = if header.contains(WS_MASK) {
            Some(try!(self.read_be_u32()))
        } else {
            None
        };

        // If this is the terminating frame (close command),
        // first two bytes of data MUST BE u16 status code
        let mut status = if header.contains(WS_OPTERM) {
            // compensate length of status code
            len = len - 2;
            Some(try!(self.read_be_u16()))
        } else {
            None
        };

        let mut data = try!(self.read_exact(len));

        // If we have mask, decrypt data
        if let Some(mut m) = mask {
            // decrypt status if present
            if let Some(s) = status {
                status = Some(s ^ (m & 0xffff) as u16);
                // compensate the usage of two mask bytes
                m = m.rotate_right(16);
            }
            data = WebSocket::mask_data(data[], m);
        }

        Ok(WSMessage { header: header, data: data, status: status.and_then(FromPrimitive::from_u16) })
    }

    fn mask_data(data: &[u8], mask: u32) -> Vec<u8> {
        data.iter().enumerate().map(|(i, b)| *b ^ (mask >> ((i % 4) << 3) & 0xff) as u8).collect::<Vec<u8>>()
    }

    pub fn send_message(&mut self, msg: &WSMessage) -> IoResult<()> {
        let mut len = msg.data.len();
        let mut hdr = msg.header - WS_LEN;

        // If we have status set, the data length is increased by status size
        if msg.status.is_some() {
            len = len + 2;
        }

        // Encode and send length along with header
        if len < u16::MAX as uint {
            hdr = hdr | WSHeader::from_bits_truncate(len as u16);
            try!(self.write_be_u16(hdr.bits()));

        } else if len < u64::MAX as uint {
            hdr = hdr | WS_LEN16;
            try!(self.write_be_u16(hdr.bits()));
            try!(self.write_be_u16(len as u16));

        } else {
            hdr = hdr | WS_LEN64;
            try!(self.write_be_u16(hdr.bits()));
            try!(self.write_be_u64(len as u64));
        }

        // If user required masking, encrypt all data
        if hdr.contains(WS_MASK) {
            // Generate and send random mask
            let mut mask = thread_rng().gen::<u32>();
            try!(self.write_be_u32(mask));

            // Encrypt status code if present
            if let Some(status) = msg.status {
                try!(self.write_be_u16(status.to_u16().unwrap() ^ (mask & 0xffff) as u16));
                // compensate for mask already used for status encryption
                mask = mask.rotate_right(16);
            }

            try!(self.write(WebSocket::mask_data(msg.data[], mask)[]));
        } else {
            // Send status code if present
            if let Some(status) = msg.status {
                try!(self.write_be_u16(status.to_u16().unwrap()));
            }
            try!(self.write(msg.data[]));
        }

        self.flush()
    }

    pub fn iter(&mut self) -> WSMessages {
        WSMessages { sock: self }
    }
}

impl Reader for WebSocket {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        match self.stream {
            Some(ref mut s) => s.read(buf),
            None => Err(standard_error(io::IoErrorKind::NotConnected))
        }
    }
}

impl Writer for WebSocket {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        match self.stream {
            Some(ref mut s) => s.write(buf),
            None => Err(standard_error(io::IoErrorKind::NotConnected))
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match self.stream {
            Some(ref mut s) => s.flush(),
            None => Err(standard_error(io::IoErrorKind::NotConnected))
        }
    }
}

impl Buffer for WebSocket {
    fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
        match self.stream {
            Some(ref mut s) => s.fill_buf(),
            None => Err(standard_error(io::IoErrorKind::NotConnected))
        }
    }

    fn consume(&mut self, amt: uint) {
        match self.stream {
            Some(ref mut s) => s.consume(amt),
            None => ()
        }
    }
}

pub struct WSMessages<'a> {
    sock: &'a mut WebSocket
}

pub struct WSDefragMessages<'a> {
    underlying: &'a mut WSMessages<'a>,
    buffer: WSMessage
}

impl<'a> WSMessages<'a> {
    pub fn defrag(&'a mut self) -> WSDefragMessages<'a> {
        WSDefragMessages{ underlying: self, buffer: WSMessage{ header: WSHeader::empty(), data: Vec::new(), status: None } }
    }
}

impl<'a> Iterator for WSMessages<'a> {
    type Item = WSMessage;
    fn next(&mut self) -> Option<WSMessage> {
        self.sock.read_message().ok()
    }
}

impl<'a> WSDefragMessages<'a> {
    fn popbuf(&mut self) -> Option<WSMessage> {
        if self.buffer.data.is_empty() {
            None
        } else {
            let mut buf = WSMessage{ header: WSHeader::empty(), data: Vec::new(), status: None };
            mem::swap(&mut self.buffer, &mut buf);
            Some(buf)
        }
    }

    fn swapbuf(&mut self, msg: &mut WSMessage) -> () {
        mem::swap(&mut self.buffer, msg);
    }
}

impl<'a> Iterator for WSDefragMessages<'a> {
    type Item = WSMessage;
    fn next(&mut self) -> Option<WSMessage> {
        loop {
            match self.underlying.next() {
                None => return self.popbuf(),
                Some(mut msg) => if msg.header.contains(WS_FIN) {
                    if msg.header & WS_OPCODE == WS_OPCONT {
                        self.buffer.push(msg);
                        return self.popbuf();
                    } else {
                        return Some(msg);
                    }

                } else {
                    if msg.header & WS_OPCODE == WS_OPCONT {
                        self.buffer.push(msg);
                    } else {
                        self.swapbuf(&mut msg);
                        return Some(msg);
                    }
                }
            }
        }
    }
}

#[bench]
#[allow(dead_code, unused_variables)]
fn test_connect(b: &mut Bencher) {
    //let url = Url::parse("wss://stream.pushbullet.com/websocket/").unwrap();
    let url = Url::parse("ws://echo.websocket.org").unwrap();
    let mut ws = WebSocket::new(url);
    ws.connect().unwrap();

    let msg = WSMessage::text("Hello, World!");
    b.bytes = msg.data.len() as u64;

    b.auto_bench(|b| {
        b.iter(|| {
            ws.send_message(&msg).unwrap();
            let msg = ws.read_message().unwrap();
            //println!("received: {} {}", msg, msg.to_string());
        })
    });

    //for msg in ws.iter() {
        //println!("{}", msg.to_string());
    //}
}
<commit_msg>test update<commit_after>use std::io::{self, Buffer, Reader, Writer, IoResult, BufferedStream, standard_error};
use std::mem;
use std::collections::BTreeMap;
use std::rand::{thread_rng, Rng};
use std::{u64, u16};
use std::num::{Int, FromPrimitive, ToPrimitive};
use url::Url;

#[cfg(test)]
use test::Bencher;

use nonce::Nonce;
use message::{WSMessage, WSHeader, WS_MASK, WS_LEN, WS_LEN16, WS_LEN64, WS_OPCONT, WS_OPCODE, WS_OPTERM, WS_FIN};
use stream::NetworkStream;

pub struct WebSocket<S = NetworkStream> {
    stream: Option<BufferedStream<S>>,
    pub url: Url,
    hostname: String,
    use_ssl: bool,
}

impl WebSocket {
    pub fn new(url: Url) -> WebSocket {
        let use_ssl = url.scheme[] == "wss";

        let port = match url.port() {
            Some(p) => p,
            None if use_ssl => 443,
            _ => 80
        };

        WebSocket {
            stream: None,
            hostname: format!("{}:{}", url.serialize_host().unwrap(), port),
            url: url,
            use_ssl: use_ssl,
        }
    }

    fn try_connect(&mut self) -> IoResult<()> {
        self.stream = Some(BufferedStream::new(try!(NetworkStream::connect(self.hostname[], self.use_ssl))));
        Ok(())
    }

    fn write_request(&mut self, nonce: &str) -> IoResult<()> {
        let s = match self.stream { Some(ref mut s) => s, None => return Err(standard_error(io::IoErrorKind::NotConnected)) };

        try!(s.write(format!("GET {} HTTP/1.1\r\n", self.url.serialize_path().unwrap_or("/".to_string())).as_bytes()));
        try!(s.write(format!("Host: {}\r\n", self.url.host().unwrap()).as_bytes()));
        try!(s.write(format!("Origin: {}\r\n", self.url.serialize_no_fragment()).as_bytes()));
        try!(s.write(format!("Sec-WebSocket-Key: {}\r\n", nonce).as_bytes()));

        try!(s.write(b"Upgrade: websocket\r\n"));
        try!(s.write(b"Connection: Upgrade\r\n"));
        try!(s.write(b"Sec-WebSocket-Protocol: char, superchat\r\n"));
        try!(s.write(b"Sec-WebSocket-Version: 13\r\n"));
        try!(s.write(b"\r\n"));

        s.flush()
    }

    fn read_response(&mut self, nonce: &str) -> IoResult<()> {
        let spaces: &[_] = &[' ', '\t', '\r', '\n'];
        let s = match self.stream { Some(ref mut s) => s, None => return Err(standard_error(io::IoErrorKind::NotConnected)) };
        let status = try!(s.read_line())[].splitn(2, ' ').nth(1).and_then(|s| s.parse::<uint>());

        match status {
            Some(101) => (),
            _ => return Err(standard_error(io::InvalidInput))
        }

        let headers = s.lines().map(|r| r.unwrap_or("\r\n".to_string())) .take_while(|l| l[] != "\r\n")
            .map(|s| s[].splitn(1, ':').map(|s| s.trim_matches(spaces).to_string()).collect::<Vec<String>>())
            .map(|p| (p[0].to_string(), p[1].to_string()))
            .collect::<BTreeMap<String, String>>();

        try!(s.flush());

        let response = headers.get("Sec-WebSocket-Accept");
        match response {
            Some(r) if nonce == r[] => (),
            _ => return Err(standard_error(io::InvalidInput))
        }

        Ok(())
    }

    pub fn connect(&mut self) -> IoResult<()> {
        let mut nonce = Nonce::new();

        try!(self.try_connect());
        try!(self.write_request(nonce[]));

        nonce = nonce.encode();
        try!(self.read_response(nonce[]));

        Ok(())
    }

    fn read_header(&mut self) -> IoResult<WSHeader> {
        // XXX: this is a bug, WSHeader should accept u16
        Ok(WSHeader::from_bits_truncate(try!(self.read_be_u16())))
    }

    fn read_length(&mut self, header: &WSHeader) -> IoResult<uint> {
        let wslen = *header & WS_LEN;
        if wslen == WS_LEN16 { self.read_be_u16().map(|v| v as uint) }
        else if wslen == WS_LEN64 { self.read_be_u64().map(|v| v as uint) }
        else { Ok(wslen.bits() as uint) }
    }

    pub fn read_message(&mut self) -> IoResult<WSMessage> {
        let header = try!(self.read_header());
        let mut len = try!(self.read_length(&header));

        let mask = if header.contains(WS_MASK) {
            Some(try!(self.read_be_u32()))
        } else {
            None
        };

        // If this is the terminating frame (close command),
        // first two bytes of data MUST BE u16 status code
        let mut status = if header.contains(WS_OPTERM) {
            // compensate length of status code
            len = len - 2;
            Some(try!(self.read_be_u16()))
        } else {
            None
        };

        let mut data = try!(self.read_exact(len));

        // If we have mask, decrypt data
        if let Some(mut m) = mask {
            // decrypt status if present
            if let Some(s) = status {
                status = Some(s ^ (m & 0xffff) as u16);
                // compensate the usage of two mask bytes
                m = m.rotate_right(16);
            }
            data = WebSocket::mask_data(data[], m);
        }

        Ok(WSMessage { header: header, data: data, status: status.and_then(FromPrimitive::from_u16) })
    }

    fn mask_data(data: &[u8], mask: u32) -> Vec<u8> {
        data.iter().enumerate().map(|(i, b)| *b ^ (mask >> ((i % 4) << 3) & 0xff) as u8).collect::<Vec<u8>>()
    }

    pub fn send_message(&mut self, msg: &WSMessage) -> IoResult<()> {
        let mut len = msg.data.len();
        let mut hdr = msg.header - WS_LEN;

        // If we have status set, the data length is increased by status size
        if msg.status.is_some() {
            len = len + 2;
        }

        // Encode and send length along with header
        if len < u16::MAX as uint {
            hdr = hdr | WSHeader::from_bits_truncate(len as u16);
            try!(self.write_be_u16(hdr.bits()));

        } else if len < u64::MAX as uint {
            hdr = hdr | WS_LEN16;
            try!(self.write_be_u16(hdr.bits()));
            try!(self.write_be_u16(len as u16));

        } else {
            hdr = hdr | WS_LEN64;
            try!(self.write_be_u16(hdr.bits()));
            try!(self.write_be_u64(len as u64));
        }

        // If user required masking, encrypt all data
        if hdr.contains(WS_MASK) {
            // Generate and send random mask
            let mut mask = thread_rng().gen::<u32>();
            try!(self.write_be_u32(mask));

            // Encrypt status code if present
            if let Some(status) = msg.status {
                try!(self.write_be_u16(status.to_u16().unwrap() ^ (mask & 0xffff) as u16));
                // compensate for mask already used for status encryption
                mask = mask.rotate_right(16);
            }

            try!(self.write(WebSocket::mask_data(msg.data[], mask)[]));
        } else {
            // Send status code if present
            if let Some(status) = msg.status {
                try!(self.write_be_u16(status.to_u16().unwrap()));
            }
            try!(self.write(msg.data[]));
        }

        self.flush()
    }

    pub fn iter(&mut self) -> WSMessages {
        WSMessages { sock: self }
    }
}

impl Reader for WebSocket {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        match self.stream {
            Some(ref mut s) => s.read(buf),
            None => Err(standard_error(io::IoErrorKind::NotConnected))
        }
    }
}

impl Writer for WebSocket {
    fn write(&mut self, buf: &[u8]) -> IoResult<()> {
        match self.stream {
            Some(ref mut s) => s.write(buf),
            None => Err(standard_error(io::IoErrorKind::NotConnected))
        }
    }

    fn flush(&mut self) -> IoResult<()> {
        match self.stream {
            Some(ref mut s) => s.flush(),
            None => Err(standard_error(io::IoErrorKind::NotConnected))
        }
    }
}

impl Buffer for WebSocket {
    fn fill_buf<'a>(&'a mut self) -> IoResult<&'a [u8]> {
        match self.stream {
            Some(ref mut s) => s.fill_buf(),
            None => Err(standard_error(io::IoErrorKind::NotConnected))
        }
    }

    fn consume(&mut self, amt: uint) {
        match self.stream {
            Some(ref mut s) => s.consume(amt),
            None => ()
        }
    }
}

pub struct WSMessages<'a> {
    sock: &'a mut WebSocket
}

pub struct WSDefragMessages<'a> {
    underlying: &'a mut WSMessages<'a>,
    buffer: WSMessage
}

impl<'a> WSMessages<'a> {
    pub fn defrag(&'a mut self) -> WSDefragMessages<'a> {
        WSDefragMessages{ underlying: self, buffer: WSMessage{ header: WSHeader::empty(), data: Vec::new(), status: None } }
    }
}

impl<'a> Iterator for WSMessages<'a> {
    type Item = WSMessage;
    fn next(&mut self) -> Option<WSMessage> {
        self.sock.read_message().ok()
    }
}

impl<'a> WSDefragMessages<'a> {
    fn popbuf(&mut self) -> Option<WSMessage> {
        if self.buffer.data.is_empty() {
            None
        } else {
            let mut buf = WSMessage{ header: WSHeader::empty(), data: Vec::new(), status: None };
            mem::swap(&mut self.buffer, &mut buf);
            Some(buf)
        }
    }

    fn swapbuf(&mut self, msg: &mut WSMessage) -> () {
        mem::swap(&mut self.buffer, msg);
    }
}

impl<'a> Iterator for WSDefragMessages<'a> {
    type Item = WSMessage;
    fn next(&mut self) -> Option<WSMessage> {
        loop {
            match self.underlying.next() {
                None => return self.popbuf(),
                Some(mut msg) => if msg.header.contains(WS_FIN) {
                    if msg.header & WS_OPCODE == WS_OPCONT {
                        self.buffer.push(msg);
                        return self.popbuf();
                    } else {
                        return Some(msg);
                    }

                } else {
                    if msg.header & WS_OPCODE == WS_OPCONT {
                        self.buffer.push(msg);
                    } else {
                        self.swapbuf(&mut msg);
                        return Some(msg);
                    }
                }
            }
        }
    }
}

#[bench]
#[allow(dead_code, unused_variables, unused_imports)]
fn test_connect(b: &mut Bencher) {
    use message::WSStatusCode;
    use rustc_serialize::json::ToJson;

    let url = Url::parse("ws://echo.websocket.org").unwrap();
    let mut ws = WebSocket::new(url);
    ws.connect().unwrap();

    let msg = WSMessage::text("Hello, World!"); //.mask();
    b.bytes = msg.data.len() as u64;

    //b.bench_n(1, |b| {
        //b.iter(|| {
            println!("sent: {} {}", msg, msg.to_string());
            ws.send_message(&msg).unwrap();
            let reply = ws.read_message().unwrap();
            println!("received: {} {}", reply, reply.to_string());
        //})
    //});

    //for msg in ws.iter() {
        //println!("{}", msg.to_string());
    //}
}
<|endoftext|>


<commit_before>use super::protos::{Action, ExplanationPoint,ExplanationPoints};
use scaii_core::{ActionWrapper,ReplayAction};
use std::path::PathBuf;
use std::collections::BTreeMap;
use std::error::Error;
use super::ReplayError;
use prost::Message;

pub struct Explanations {
    pub step_indices: Vec<u32>,
    pub expl_map:  BTreeMap<u32, ExplanationPoint>,
}

pub fn is_empty(explanations_option : &Option<Explanations>) -> bool {
    match explanations_option {
        &None => {
            println!("is_empty()? FOUND NONE");
            true
        }
        &Some(ref explanations) => {
            println!("is_empty()? FOUND SOME:{}", explanations.step_indices.len());
            explanations.step_indices.len() == 0
        }
    }
}
pub fn map_explanations(explanation_points: Vec<ExplanationPoint>) -> Result<Option<Explanations>, Box<Error>> {
    println!("MAPPING EXPL POINTS recieved this many {}", explanation_points.len());
    let mut step_indices : Vec<u32> = Vec::new();
    let mut expl_map: BTreeMap<u32, ExplanationPoint> = BTreeMap::new();
    for expl_point in explanation_points {
        let step = expl_point.step.unwrap();
        step_indices.push(step.clone());
        expl_map.insert(step,expl_point.clone());
    }
    Ok(Some(Explanations {
        step_indices: step_indices,
        expl_map: expl_map,
    }))
}

pub fn extract_explanations(replay_actions: Vec<ReplayAction>, r_actions_sans_explanations: &mut Vec<ReplayAction>) -> Result<Vec<ExplanationPoint>, Box<Error>> {
    let mut explanation_points: Vec<ExplanationPoint> = Vec::new();
    for replay_action in replay_actions {
        match replay_action {
            ReplayAction::Delta(action_wrapper) => {
                let new_action_wrapper = extract_explanation_from_action_wrapper(action_wrapper, &mut explanation_points)?;
                let new_replay_action = ReplayAction::Delta(new_action_wrapper);
                r_actions_sans_explanations.push(new_replay_action);
            }
            ReplayAction::Keyframe(ser_info, action_wrapper) => {
                let new_action_wrapper = extract_explanation_from_action_wrapper(action_wrapper, &mut explanation_points)?;
                let new_replay_action = ReplayAction::Keyframe(ser_info, new_action_wrapper);
                r_actions_sans_explanations.push(new_replay_action);
            }
            ReplayAction::Header(_) => {
                r_actions_sans_explanations.push(replay_action);
            },
        }
    }
    Ok(explanation_points)
}

fn get_serialized_action(action: &Action) -> Result<Vec<u8>, Box<Error>> {
    let mut action_data: Vec<u8> = Vec::new();
    action.encode(&mut action_data)?;
    Ok(action_data)
}

fn extract_explanation_from_action_wrapper(action_wrapper : ActionWrapper, explanation_points : &mut Vec<ExplanationPoint>) -> Result<ActionWrapper, Box<Error>> {
    let data = action_wrapper.serialized_action;
    let action_decode_result = Action::decode(data);
    match action_decode_result {
        Ok(action) =>  {
            match action.explanation_point {
                None => {
                    println!("Explanation?  None");
                },
                Some(explanation_point) => {
                    println!("Explanation?  YES");
                    explanation_points.push(explanation_point);
                },
            }
            // make new Action without Explanation
            let new_action = Action{
                discrete_actions : action.discrete_actions,
                continuous_actions : action.continuous_actions,
                alternate_actions : action.alternate_actions,
                explanation_point : Option::None,
            };
            let mut new_action_data: Vec<u8> = Vec::new();
            new_action.encode(&mut new_action_data)?;
            Ok(ActionWrapper {
                has_explanation: false,
                step: action_wrapper.step,
                title: action_wrapper.title,
                serialized_action: new_action_data,
            })
        }
        Err(err) => {
            Err(Box::new(ReplayError::new("could not decode ActionWrapper during explanation stripping")))
        }
    }
}

pub fn get_explanations_for_replay_file(mut path: PathBuf) -> Result<Option<Explanations>, Box<Error>> {
    let path_clone = path.clone();
    let filestem_option = path_clone.file_stem();
    match filestem_option {
        Some(os_stem_string) => {
            println!("os_stem_string is {:?}", os_stem_string);
            let filestem: String = os_stem_string.to_str().unwrap().to_string();
            let explanation_filename = format!("{}.exp", filestem);
            path.pop(); // parent dir
            path.push(explanation_filename);
            println!("explanation filepath is {:?}", path);
            get_explanations_for_explanations_file(path)
        },
        None => Ok(None)
    }
}

pub fn get_explanations_for_explanations_file(path: PathBuf) -> Result<Option<Explanations>, Box<Error>> {
    use std::fs::File;
    use std::io::BufReader;
    use std::io::Read;
    use super::prost::Message;

    if !path.as_path().exists() {
        return Ok(None);
    }
    let replay_file = File::open(path.clone()).expect("file not found");
    let mut bytes : Vec<u8> = Vec::new();
    let mut reader = BufReader::new(replay_file);
    let read_result = reader.read_to_end(&mut bytes);
    match read_result {
        Ok(read_usize) => {
            println!("read this many bytes {:?}", read_usize);
            let explanation_points =
                ExplanationPoints::decode(bytes)?;
           // assert!(explanation_points.explanation_points.len() == 3);
            println!("explanation point count {}", explanation_points.explanation_points.len());
            let explanations_option = get_explanations_for_explanation_points(explanation_points)?;
            Ok(explanations_option)
        },
        Err(err) => {
            return Err(Box::new(ReplayError::new(&format!("ERROR - failed to read explanations file {:?}", path))));
        },
    }
}

fn get_explanations_for_explanation_points(expl_points : ExplanationPoints) -> Result<Option<Explanations>, Box<Error>> {
    let mut step_indices : Vec<u32> = Vec::new();
    let mut expl_map: BTreeMap<u32, ExplanationPoint> = BTreeMap::new();
    for expl_point in expl_points.explanation_points{
        let step = expl_point.step.unwrap();
        step_indices.push(step.clone());
        expl_map.insert(step,expl_point.clone());
    }
    Ok(Some(Explanations {
        step_indices: step_indices,
        expl_map: expl_map,
    }))
}<commit_msg>warn rather than assert! over missing explanations<commit_after>use super::protos::{Action, ExplanationPoint,ExplanationPoints};
use scaii_core::{ActionWrapper,ReplayAction};
use std::path::PathBuf;
use std::collections::BTreeMap;
use std::error::Error;
use super::ReplayError;
use prost::Message;

pub struct Explanations {
    pub step_indices: Vec<u32>,
    pub expl_map:  BTreeMap<u32, ExplanationPoint>,
}

pub fn is_empty(explanations_option : &Option<Explanations>) -> bool {
    match explanations_option {
        &None => {
            println!("is_empty()? FOUND NONE");
            true
        }
        &Some(ref explanations) => {
            println!("is_empty()? FOUND SOME:{}", explanations.step_indices.len());
            explanations.step_indices.len() == 0
        }
    }
}
pub fn map_explanations(explanation_points: Vec<ExplanationPoint>) -> Result<Option<Explanations>, Box<Error>> {
    println!("MAPPING EXPL POINTS recieved this many {}", explanation_points.len());
    let mut step_indices : Vec<u32> = Vec::new();
    let mut expl_map: BTreeMap<u32, ExplanationPoint> = BTreeMap::new();
    for expl_point in explanation_points {
        let step = expl_point.step.unwrap();
        step_indices.push(step.clone());
        expl_map.insert(step,expl_point.clone());
    }
    Ok(Some(Explanations {
        step_indices: step_indices,
        expl_map: expl_map,
    }))
}

pub fn extract_explanations(replay_actions: Vec<ReplayAction>, r_actions_sans_explanations: &mut Vec<ReplayAction>) -> Result<Vec<ExplanationPoint>, Box<Error>> {
    let mut explanation_points: Vec<ExplanationPoint> = Vec::new();
    for replay_action in replay_actions {
        match replay_action {
            ReplayAction::Delta(action_wrapper) => {
                let new_action_wrapper = extract_explanation_from_action_wrapper(action_wrapper, &mut explanation_points)?;
                let new_replay_action = ReplayAction::Delta(new_action_wrapper);
                r_actions_sans_explanations.push(new_replay_action);
            }
            ReplayAction::Keyframe(ser_info, action_wrapper) => {
                let new_action_wrapper = extract_explanation_from_action_wrapper(action_wrapper, &mut explanation_points)?;
                let new_replay_action = ReplayAction::Keyframe(ser_info, new_action_wrapper);
                r_actions_sans_explanations.push(new_replay_action);
            }
            ReplayAction::Header(_) => {
                r_actions_sans_explanations.push(replay_action);
            },
        }
    }
    Ok(explanation_points)
}

fn get_serialized_action(action: &Action) -> Result<Vec<u8>, Box<Error>> {
    let mut action_data: Vec<u8> = Vec::new();
    action.encode(&mut action_data)?;
    Ok(action_data)
}

fn extract_explanation_from_action_wrapper(action_wrapper : ActionWrapper, explanation_points : &mut Vec<ExplanationPoint>) -> Result<ActionWrapper, Box<Error>> {
    let data = action_wrapper.serialized_action;
    let action_decode_result = Action::decode(data);
    match action_decode_result {
        Ok(action) =>  {
            match action.explanation {
                None => {
                    println!("Explanation?  None");
                },
                Some(explanation_point) => {
                    println!("Explanation?  YES");
                    explanation_points.push(explanation_point);
                },
            }
            // make new Action without Explanation
            let new_action = Action{
                discrete_actions : action.discrete_actions,
                continuous_actions : action.continuous_actions,
                alternate_actions : action.alternate_actions,
                explanation : Option::None,
            };
            let mut new_action_data: Vec<u8> = Vec::new();
            new_action.encode(&mut new_action_data)?;
            Ok(ActionWrapper {
                has_explanation: false,
                step: action_wrapper.step,
                title: action_wrapper.title,
                serialized_action: new_action_data,
            })
        }
        Err(err) => {
            Err(Box::new(ReplayError::new("could not decode ActionWrapper during explanation stripping")))
        }
    }
}

pub fn get_explanations_for_replay_file(mut path: PathBuf) -> Result<Option<Explanations>, Box<Error>> {
    let path_clone = path.clone();
    let filestem_option = path_clone.file_stem();
    match filestem_option {
        Some(os_stem_string) => {
            println!("os_stem_string is {:?}", os_stem_string);
            let filestem: String = os_stem_string.to_str().unwrap().to_string();
            let explanation_filename = format!("{}.exp", filestem);
            path.pop(); // parent dir
            path.push(explanation_filename);
            println!("explanation filepath is {:?}", path);
            get_explanations_for_explanations_file(path)
        },
        None => Ok(None)
    }
}

pub fn get_explanations_for_explanations_file(path: PathBuf) -> Result<Option<Explanations>, Box<Error>> {
    use std::fs::File;
    use std::io::BufReader;
    use std::io::Read;
    use super::prost::Message;

    if !path.as_path().exists() {
        return Ok(None);
    }
    let replay_file = File::open(path.clone()).expect("file not found");
    let mut bytes : Vec<u8> = Vec::new();
    let mut reader = BufReader::new(replay_file);
    let read_result = reader.read_to_end(&mut bytes);
    match read_result {
        Ok(read_usize) => {
            println!("read this many bytes {:?}", read_usize);
            let explanation_points =
                ExplanationPoints::decode(bytes)?;
           // assert!(explanation_points.explanation_points.len() == 3);
            println!("explanation point count {}", explanation_points.explanation_points.len());
            let explanations_option = get_explanations_for_explanation_points(explanation_points)?;
            Ok(explanations_option)
        },
        Err(err) => {
            return Err(Box::new(ReplayError::new(&format!("ERROR - failed to read explanations file {:?}", path))));
        },
    }
}

fn get_explanations_for_explanation_points(expl_points : ExplanationPoints) -> Result<Option<Explanations>, Box<Error>> {
    let mut step_indices : Vec<u32> = Vec::new();
    let mut expl_map: BTreeMap<u32, ExplanationPoint> = BTreeMap::new();
    for expl_point in expl_points.explanation_points{
        let step = expl_point.step.unwrap();
        step_indices.push(step.clone());
        expl_map.insert(step,expl_point.clone());
    }
    Ok(Some(Explanations {
        step_indices: step_indices,
        expl_map: expl_map,
    }))
}<|endoftext|>


<commit_before>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module crawls a `clean::Crate` and produces a summarization of the
//! stability levels within the crate. The summary contains the module
//! hierarchy, with item counts for every stability level per module. A parent
//! module's count includes its children's.

use std::ops::Add;
use std::num::Zero;
use std::iter::AdditiveIterator;

use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked};
use syntax::ast::Public;

use clean::{Crate, Item, ModuleItem, Module, StructItem, Struct, EnumItem, Enum};
use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod};
use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability};

use html::render::cache_key;

#[deriving(Zero, Encodable, Decodable, PartialEq, Eq)]
/// The counts for each stability level.
pub struct Counts {
    pub deprecated: uint,
    pub experimental: uint,
    pub unstable: uint,
    pub stable: uint,
    pub frozen: uint,
    pub locked: uint,

    /// No stability level, inherited or otherwise.
    pub unmarked: uint,
}

impl Add<Counts, Counts> for Counts {
    fn add(&self, other: &Counts) -> Counts {
        Counts {
            deprecated:   self.deprecated   + other.deprecated,
            experimental: self.experimental + other.experimental,
            unstable:     self.unstable     + other.unstable,
            stable:       self.stable       + other.stable,
            frozen:       self.frozen       + other.frozen,
            locked:       self.locked       + other.locked,
            unmarked:     self.unmarked     + other.unmarked,
        }
    }
}

impl Counts {
    fn zero() -> Counts {
        Counts {
            deprecated:   0,
            experimental: 0,
            unstable:     0,
            stable:       0,
            frozen:       0,
            locked:       0,
            unmarked:     0,
        }
    }

    pub fn total(&self) -> uint {
        self.deprecated + self.experimental + self.unstable + self.stable +
            self.frozen + self.locked + self.unmarked
    }
}

#[deriving(Encodable, Decodable, PartialEq, Eq)]
/// A summarized module, which includes total counts and summarized children
/// modules.
pub struct ModuleSummary {
    pub name: String,
    pub counts: Counts,
    pub submodules: Vec<ModuleSummary>,
}

impl PartialOrd for ModuleSummary {
    fn partial_cmp(&self, other: &ModuleSummary) -> Option<Ordering> {
        self.name.partial_cmp(&other.name)
    }
}

impl Ord for ModuleSummary {
    fn cmp(&self, other: &ModuleSummary) -> Ordering {
        self.name.cmp(&other.name)
    }
}

// is the item considered publically visible?
fn visible(item: &Item) -> bool {
    match item.inner {
        ImplItem(_) => true,
        _ => item.visibility == Some(Public)
    }
}

fn count_stability(stab: Option<&Stability>) -> Counts {
    match stab {
        None             => Counts { unmarked: 1,     .. Counts::zero() },
        Some(ref stab) => match stab.level {
            Deprecated   => Counts { deprecated: 1,   .. Counts::zero() },
            Experimental => Counts { experimental: 1, .. Counts::zero() },
            Unstable     => Counts { unstable: 1,     .. Counts::zero() },
            Stable       => Counts { stable: 1,       .. Counts::zero() },
            Frozen       => Counts { frozen: 1,       .. Counts::zero() },
            Locked       => Counts { locked: 1,       .. Counts::zero() },
        }
    }
}

fn summarize_methods(item: &Item) -> Counts {
    match cache_key.get().unwrap().impls.get(&item.def_id) {
        Some(v) => {
            v.iter().map(|i| {
                let mut count = count_stability(i.stability.as_ref());
                if i.impl_.trait_.is_none() {
                    count = count +
                        i.impl_.items.iter().map(|ti| summarize_item(ti).0).sum();
                }
                count
            }).sum()
        }
        None    => Zero::zero()
    }
}

// Produce the summary for an arbitrary item. If the item is a module, include a
// module summary. The counts for items with nested items (e.g. modules, traits,
// impls) include all children counts.
fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
    let item_counts = count_stability(item.stability.as_ref()) + summarize_methods(item);

    // Count this item's children, if any. Note that a trait impl is
    // considered to have no children.
    match item.inner {
        // Require explicit `pub` to be visible
        StructItem(Struct { fields: ref subitems, .. }) |
        ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
            let subcounts = subitems.iter().filter(|i| visible(*i))
                                           .map(summarize_item)
                                           .map(|s| s.val0())
                                           .sum(Counts::zero());
            (item_counts + subcounts, None)
        }
        // `pub` automatically
        EnumItem(Enum { variants: ref subitems, .. }) => {
            let subcounts = subitems.iter().map(summarize_item)
                                           .map(|s| s.val0())
                                           .sum(Counts::zero());
            (item_counts + subcounts, None)
        }
        TraitItem(Trait {
            items: ref trait_items,
            ..
        }) => {
            fn extract_item<'a>(trait_item: &'a TraitMethod) -> &'a Item {
                match *trait_item {
                    ProvidedMethod(ref item) |
                    RequiredMethod(ref item) |
                    TypeTraitItem(ref item) => item
                }
            }
            let subcounts = trait_items.iter()
                                       .map(extract_item)
                                       .map(summarize_item)
                                       .map(|s| s.val0())
                                       .sum(Counts::zero());
            (item_counts + subcounts, None)
        }
        ModuleItem(Module { ref items, .. }) => {
            let mut counts = item_counts;
            let mut submodules = Vec::new();

            for (subcounts, submodule) in items.iter().filter(|i| visible(*i))
                                                      .map(summarize_item) {
                counts = counts + subcounts;
                submodule.map(|m| submodules.push(m));
            }
            submodules.sort();

            (counts, Some(ModuleSummary {
                name: item.name.as_ref().map_or("".to_string(), |n| n.clone()),
                counts: counts,
                submodules: submodules,
            }))
        }
        // no stability information for the following items:
        ViewItemItem(_) | PrimitiveItem(_) => (Counts::zero(), None),
        _ => (item_counts, None)
    }
}

/// Summarizes the stability levels in a crate.
pub fn build(krate: &Crate) -> ModuleSummary {
    match krate.module {
        None => ModuleSummary {
            name: krate.name.clone(),
            counts: Counts::zero(),
            submodules: Vec::new(),
        },
        Some(ref item) => ModuleSummary {
            name: krate.name.clone(), .. summarize_item(item).val1().unwrap()
        }
    }
}
<commit_msg>Fix stability_summary fallout<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! This module crawls a `clean::Crate` and produces a summarization of the
//! stability levels within the crate. The summary contains the module
//! hierarchy, with item counts for every stability level per module. A parent
//! module's count includes its children's.

use std::ops::Add;
use std::num::Zero;
use std::iter::AdditiveIterator;

use syntax::attr::{Deprecated, Experimental, Unstable, Stable, Frozen, Locked};
use syntax::ast::Public;

use clean::{Crate, Item, ModuleItem, Module, StructItem, Struct, EnumItem, Enum};
use clean::{ImplItem, Impl, Trait, TraitItem, TraitMethod, ProvidedMethod, RequiredMethod};
use clean::{TypeTraitItem, ViewItemItem, PrimitiveItem, Stability};

use html::render::cache_key;

#[deriving(Zero, Encodable, Decodable, PartialEq, Eq)]
/// The counts for each stability level.
pub struct Counts {
    pub deprecated: uint,
    pub experimental: uint,
    pub unstable: uint,
    pub stable: uint,
    pub frozen: uint,
    pub locked: uint,

    /// No stability level, inherited or otherwise.
    pub unmarked: uint,
}

impl Add<Counts, Counts> for Counts {
    fn add(&self, other: &Counts) -> Counts {
        Counts {
            deprecated:   self.deprecated   + other.deprecated,
            experimental: self.experimental + other.experimental,
            unstable:     self.unstable     + other.unstable,
            stable:       self.stable       + other.stable,
            frozen:       self.frozen       + other.frozen,
            locked:       self.locked       + other.locked,
            unmarked:     self.unmarked     + other.unmarked,
        }
    }
}

impl Counts {
    fn zero() -> Counts {
        Counts {
            deprecated:   0,
            experimental: 0,
            unstable:     0,
            stable:       0,
            frozen:       0,
            locked:       0,
            unmarked:     0,
        }
    }

    pub fn total(&self) -> uint {
        self.deprecated + self.experimental + self.unstable + self.stable +
            self.frozen + self.locked + self.unmarked
    }
}

#[deriving(Encodable, Decodable, PartialEq, Eq)]
/// A summarized module, which includes total counts and summarized children
/// modules.
pub struct ModuleSummary {
    pub name: String,
    pub counts: Counts,
    pub submodules: Vec<ModuleSummary>,
}

impl PartialOrd for ModuleSummary {
    fn partial_cmp(&self, other: &ModuleSummary) -> Option<Ordering> {
        self.name.partial_cmp(&other.name)
    }
}

impl Ord for ModuleSummary {
    fn cmp(&self, other: &ModuleSummary) -> Ordering {
        self.name.cmp(&other.name)
    }
}

// is the item considered publically visible?
fn visible(item: &Item) -> bool {
    match item.inner {
        ImplItem(_) => true,
        _ => item.visibility == Some(Public)
    }
}

fn count_stability(stab: Option<&Stability>) -> Counts {
    match stab {
        None             => Counts { unmarked: 1,     .. Counts::zero() },
        Some(ref stab) => match stab.level {
            Deprecated   => Counts { deprecated: 1,   .. Counts::zero() },
            Experimental => Counts { experimental: 1, .. Counts::zero() },
            Unstable     => Counts { unstable: 1,     .. Counts::zero() },
            Stable       => Counts { stable: 1,       .. Counts::zero() },
            Frozen       => Counts { frozen: 1,       .. Counts::zero() },
            Locked       => Counts { locked: 1,       .. Counts::zero() },
        }
    }
}

fn summarize_methods(item: &Item) -> Counts {
    match cache_key.get().unwrap().impls.get(&item.def_id) {
        Some(v) => {
            v.iter().map(|i| {
                let count = count_stability(i.stability.as_ref());
                if i.impl_.trait_.is_none() {
                    count + i.impl_.items.iter()
                        .map(|ti| summarize_item(ti).0)
                        .fold(Counts::zero(), |acc, c| acc + c)
                } else {
                    count
                }
            }).fold(Counts::zero(), |acc, c| acc + c)
        },
        None => {
            Counts::zero()
        },
    }
}

// Produce the summary for an arbitrary item. If the item is a module, include a
// module summary. The counts for items with nested items (e.g. modules, traits,
// impls) include all children counts.
fn summarize_item(item: &Item) -> (Counts, Option<ModuleSummary>) {
    let item_counts = count_stability(item.stability.as_ref()) + summarize_methods(item);

    // Count this item's children, if any. Note that a trait impl is
    // considered to have no children.
    match item.inner {
        // Require explicit `pub` to be visible
        StructItem(Struct { fields: ref subitems, .. }) |
        ImplItem(Impl { items: ref subitems, trait_: None, .. }) => {
            let subcounts = subitems.iter().filter(|i| visible(*i))
                                           .map(summarize_item)
                                           .map(|s| s.val0())
                                           .sum(Counts::zero());
            (item_counts + subcounts, None)
        }
        // `pub` automatically
        EnumItem(Enum { variants: ref subitems, .. }) => {
            let subcounts = subitems.iter().map(summarize_item)
                                           .map(|s| s.val0())
                                           .sum(Counts::zero());
            (item_counts + subcounts, None)
        }
        TraitItem(Trait {
            items: ref trait_items,
            ..
        }) => {
            fn extract_item<'a>(trait_item: &'a TraitMethod) -> &'a Item {
                match *trait_item {
                    ProvidedMethod(ref item) |
                    RequiredMethod(ref item) |
                    TypeTraitItem(ref item) => item
                }
            }
            let subcounts = trait_items.iter()
                                       .map(extract_item)
                                       .map(summarize_item)
                                       .map(|s| s.val0())
                                       .sum(Counts::zero());
            (item_counts + subcounts, None)
        }
        ModuleItem(Module { ref items, .. }) => {
            let mut counts = item_counts;
            let mut submodules = Vec::new();

            for (subcounts, submodule) in items.iter().filter(|i| visible(*i))
                                                      .map(summarize_item) {
                counts = counts + subcounts;
                submodule.map(|m| submodules.push(m));
            }
            submodules.sort();

            (counts, Some(ModuleSummary {
                name: item.name.as_ref().map_or("".to_string(), |n| n.clone()),
                counts: counts,
                submodules: submodules,
            }))
        }
        // no stability information for the following items:
        ViewItemItem(_) | PrimitiveItem(_) => (Counts::zero(), None),
        _ => (item_counts, None)
    }
}

/// Summarizes the stability levels in a crate.
pub fn build(krate: &Crate) -> ModuleSummary {
    match krate.module {
        None => ModuleSummary {
            name: krate.name.clone(),
            counts: Counts::zero(),
            submodules: Vec::new(),
        },
        Some(ref item) => ModuleSummary {
            name: krate.name.clone(), .. summarize_item(item).val1().unwrap()
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use clap::ArgMatches;

use runtime::Runtime;
use module::Module;

pub struct BM<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> BM<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> BM<'a> {
        BM {
            rt: rt,
        }
    }

    fn runtime(&self) -> &Runtime {
        &self.rt
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

}

impl<'a> Module<'a> for BM<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str {
        "bm"
    }
}

impl<'a> Debug for BM<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "BM");
        Ok(())
    }

}

<commit_msg>Implement: BM::command_add()<commit_after>use std::fmt::{Debug, Display, Formatter};
use std::fmt;

use clap::ArgMatches;

use runtime::Runtime;
use module::Module;

use storage::parser::FileHeaderParser;
use storage::parser::Parser;
use storage::json::parser::JsonHeaderParser;

pub struct BM<'a> {
    rt: &'a Runtime<'a>,
}

impl<'a> BM<'a> {

    pub fn new(rt: &'a Runtime<'a>) -> BM<'a> {
        BM {
            rt: rt,
        }
    }

    fn runtime(&self) -> &Runtime {
        &self.rt
    }

    fn command_add(&self, matches: &ArgMatches) -> bool {
        use self::header::build_header;

        let parser = Parser::new(JsonHeaderParser::new(None));

        let url    = matches.value_of("url").map(String::from).unwrap(); // clap ensures this is present
        let tags   = matches.value_of("tags").and_then(|s| {
            Some(s.split(",").map(String::from).collect())
        }).unwrap_or(vec![]);

        debug!("Building header with");
        debug!("    url  = '{:?}'", url);
        debug!("    tags = '{:?}'", tags);
        let header = build_header(url, tags);

        let fileid = self.rt.store().new_file_with_header(self, header);
        self.rt.store().load(&fileid).and_then(|file| {
            info!("Created file in memory: {}", fileid);
            Some(self.rt.store().persist(&parser, file))
        }).unwrap_or(false)
    }

    fn command_list(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

    fn command_remove(&self, matches: &ArgMatches) -> bool {
        unimplemented!()
    }

}

impl<'a> Module<'a> for BM<'a> {

    fn exec(&self, matches: &ArgMatches) -> bool {
        match matches.subcommand_name() {
            Some("add") => {
                self.command_add(matches.subcommand_matches("add").unwrap())
            },

            Some("list") => {
                self.command_list(matches.subcommand_matches("list").unwrap())
            },

            Some("remove") => {
                self.command_remove(matches.subcommand_matches("remove").unwrap())
            },

            Some(_) | None => {
                info!("No command given, doing nothing");
                false
            },
        }
    }

    fn name(&self) -> &'static str {
        "bm"
    }
}

impl<'a> Debug for BM<'a> {

    fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
        write!(fmt, "BM");
        Ok(())
    }

}

<|endoftext|>


<commit_before>use crate::crypto::PublicKey;
use std::borrow::Cow;
use std::ops::Deref;

pub mod builder;
pub mod engine;
pub mod error;
pub mod op;
mod stack;

pub use self::builder::*;
pub use self::engine::*;
pub use self::error::*;
pub use self::op::*;

pub const MAX_FRAME_STACK: usize = 64;
pub const MAX_BYTE_SIZE: usize = 2048;

#[derive(Debug, Clone, PartialEq)]
pub struct Script(Vec<u8>);

impl Script {
    #[inline]
    pub fn new(byte_code: Vec<u8>) -> Self {
        Script(byte_code)
    }
}

impl From<&[u8]> for Script {
    #[inline]
    fn from(slice: &[u8]) -> Self {
        Script::new(slice.to_owned())
    }
}

impl From<Vec<u8>> for Script {
    #[inline]
    fn from(vec: Vec<u8>) -> Self {
        Script::new(vec)
    }
}

impl From<Builder> for Script {
    #[inline]
    fn from(b: Builder) -> Self {
        b.build()
    }
}

impl From<PublicKey> for Script {
    fn from(key: PublicKey) -> Self {
        let builder = Builder::new()
            .push(OpFrame::PubKey(key))
            .push(OpFrame::OpCheckSig);
        builder.build()
    }
}

impl From<&PublicKey> for Script {
    fn from(key: &PublicKey) -> Self {
        let builder = Builder::new()
            .push(OpFrame::PubKey(key.clone()))
            .push(OpFrame::OpCheckSig);
        builder.build()
    }
}

impl<'a> Into<Cow<'a, Script>> for Script {
    #[inline]
    fn into(self) -> Cow<'a, Script> {
        Cow::Owned(self)
    }
}

impl<'a> Into<Cow<'a, Script>> for &'a Script {
    #[inline]
    fn into(self) -> Cow<'a, Script> {
        Cow::Borrowed(self)
    }
}

impl Deref for Script {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        &self.0
    }
}
<commit_msg>Remove unused From<&PublicKey> for Script<commit_after>use crate::crypto::PublicKey;
use std::borrow::Cow;
use std::ops::Deref;

pub mod builder;
pub mod engine;
pub mod error;
pub mod op;
mod stack;

pub use self::builder::*;
pub use self::engine::*;
pub use self::error::*;
pub use self::op::*;

pub const MAX_FRAME_STACK: usize = 64;
pub const MAX_BYTE_SIZE: usize = 2048;

#[derive(Debug, Clone, PartialEq)]
pub struct Script(Vec<u8>);

impl Script {
    #[inline]
    pub fn new(byte_code: Vec<u8>) -> Self {
        Script(byte_code)
    }
}

impl From<&[u8]> for Script {
    #[inline]
    fn from(slice: &[u8]) -> Self {
        Script::new(slice.to_owned())
    }
}

impl From<Vec<u8>> for Script {
    #[inline]
    fn from(vec: Vec<u8>) -> Self {
        Script::new(vec)
    }
}

impl From<Builder> for Script {
    #[inline]
    fn from(b: Builder) -> Self {
        b.build()
    }
}

impl From<PublicKey> for Script {
    fn from(key: PublicKey) -> Self {
        let builder = Builder::new()
            .push(OpFrame::PubKey(key))
            .push(OpFrame::OpCheckSig);
        builder.build()
    }
}

impl<'a> Into<Cow<'a, Script>> for Script {
    #[inline]
    fn into(self) -> Cow<'a, Script> {
        Cow::Owned(self)
    }
}

impl<'a> Into<Cow<'a, Script>> for &'a Script {
    #[inline]
    fn into(self) -> Cow<'a, Script> {
        Cow::Borrowed(self)
    }
}

impl Deref for Script {
    type Target = [u8];

    #[inline]
    fn deref(&self) -> &[u8] {
        &self.0
    }
}
<|endoftext|>


<commit_before>pub mod expressions;
pub mod statements;
pub mod terminals;

use std;
use parser::js::statements::*;

#[derive(Debug)]
pub struct Program<'a>(pub Option<SourceElements<'a>>);

#[derive(Debug, PartialEq)]
pub struct SourceElements<'a>(pub std::vec::Vec<SourceElement<'a>>);

#[derive(Debug, PartialEq)]
pub enum SourceElement<'a> {
    Statement(Statement<'a>),
    FunctionDeclaration(FunctionDeclaration<'a>),
}

#[derive(Debug, PartialEq)]
pub struct FunctionDeclaration<'a> {
    pub name: &'a str,
    pub formals: Option<FormalParameterList<'a>>,
    pub body: Option<FunctionBody<'a>>,
}

#[derive(Debug, PartialEq)]
pub struct FormalParameterList<'a>(pub std::vec::Vec<FormalParameter<'a>>);
#[derive(Debug, PartialEq)]
pub struct FormalParameter<'a>(pub &'a str);

#[derive(Debug, PartialEq)]
pub struct FunctionBody<'a>(pub SourceElements<'a>);

pub mod parsing {

    use parser::helpers::parsing::*;
    use parser::js::*;
    use parser::js::statements::parsing::*;
    use parser::js::terminals::parsing::*;

    named!(pub program<&str, Program>, conv!(Program(opt!(source_elements))));

    named!(source_elements<&str, SourceElements>, conv!(SourceElements(many1!(source_element))));

    named!(pub source_element<&str, SourceElement>, alt!(
        conv!(SourceElement::Statement(statement))
        |
        conv!(SourceElement::FunctionDeclaration(function_declaration))
    ));

    named!(pub function_declaration<&str, FunctionDeclaration>, do_parse!(
        keyword!("function") >>
        name: js_identifier >>
        keyword!("(") >>
        formal_parameter_list: opt!(formal_parameter_list) >>
        keyword!(")") >>
        keyword!("{") >>
        body: opt!(function_body) >>
        keyword!("}") >>
        (FunctionDeclaration {
            name: name,
            formals: formal_parameter_list,
            body: body,
        })
    ));

    named!(pub formal_parameter_list<&str, FormalParameterList>, conv!(FormalParameterList(separated_nonempty_list!(
        keyword!(","),
        conv!(FormalParameter(js_identifier))
    ))));

    named!(pub function_body<&str, FunctionBody>, conv!(FunctionBody(source_elements)));

}<commit_msg>Add unit tests for function_declaration<commit_after>pub mod expressions;
pub mod statements;
pub mod terminals;

use std;
use parser::js::statements::*;

#[derive(Debug)]
pub struct Program<'a>(pub Option<SourceElements<'a>>);

#[derive(Debug, PartialEq)]
pub struct SourceElements<'a>(pub std::vec::Vec<SourceElement<'a>>);

#[derive(Debug, PartialEq)]
pub enum SourceElement<'a> {
    Statement(Statement<'a>),
    FunctionDeclaration(FunctionDeclaration<'a>),
}

#[derive(Debug, PartialEq)]
pub struct FunctionDeclaration<'a> {
    pub name: &'a str,
    pub formals: Option<FormalParameterList<'a>>,
    pub body: Option<FunctionBody<'a>>,
}

#[derive(Debug, PartialEq)]
pub struct FormalParameterList<'a>(pub std::vec::Vec<FormalParameter<'a>>);
#[derive(Debug, PartialEq)]
pub struct FormalParameter<'a>(pub &'a str);

#[derive(Debug, PartialEq)]
pub struct FunctionBody<'a>(pub SourceElements<'a>);

pub mod parsing {

    use parser::helpers::parsing::*;
    use parser::js::*;
    use parser::js::statements::parsing::*;
    use parser::js::terminals::parsing::*;

    named!(pub program<&str, Program>, conv!(Program(opt!(source_elements))));

    named!(source_elements<&str, SourceElements>, conv!(SourceElements(many1!(source_element))));

    named!(pub source_element<&str, SourceElement>, alt!(
        conv!(SourceElement::Statement(statement))
        |
        conv!(SourceElement::FunctionDeclaration(function_declaration))
    ));

    named!(pub function_declaration<&str, FunctionDeclaration>, do_parse!(
        keyword!("function") >>
        name: js_identifier >>
        keyword!("(") >>
        formal_parameter_list: opt!(formal_parameter_list) >>
        keyword!(")") >>
        keyword!("{") >>
        body: opt!(function_body) >>
        keyword!("}") >>
        (FunctionDeclaration {
            name: name,
            formals: formal_parameter_list,
            body: body,
        })
    ));

    named!(pub formal_parameter_list<&str, FormalParameterList>, conv!(FormalParameterList(separated_nonempty_list!(
        keyword!(","),
        conv!(FormalParameter(js_identifier))
    ))));

    named!(pub function_body<&str, FunctionBody>, conv!(FunctionBody(source_elements)));

    #[cfg(test)]
    mod tests {
        use nom::{IResult, ErrorKind};
        use super::*;

        #[test]
        fn function_declaration() {
            assert!(super::function_declaration("").is_incomplete());

            {
                let name = "test";

                let input = format!("function {}() {{}} ", name);
                assert_eq!(
                    super::function_declaration(&input),
                    IResult::Done(" ", FunctionDeclaration {
                        name: super::js_identifier(name).unwrap().1,
                        formals: None,
                        body: None,
                    })
                );
            }

            {
                let name = "test";
                let formals = "test";
                let body = ";;";

                let input = format!("function {}({}) {{{}}} ", name, formals, body);
                assert_eq!(
                    super::function_declaration(&input),
                    IResult::Done(" ", FunctionDeclaration {
                        name: super::js_identifier(name).unwrap().1,
                        formals: Some(super::formal_parameter_list(formals).unwrap().1),
                        body: Some(super::function_body(body).unwrap().1),
                    })
                );
            }

            assert!(super::function_declaration(" function ").is_incomplete());
            assert!(super::function_declaration(" function test ").is_incomplete());
            assert!(super::function_declaration(" function test (").is_incomplete());
            assert!(super::function_declaration(" function test (test) ").is_incomplete());
            assert!(super::function_declaration(" function test (test) { ").is_incomplete());

            assert_eq!(
                super::function_declaration("function () {{}} "),
                IResult::Error(ErrorKind::Alt)
            );

            assert_eq!(
                super::function_declaration("function test {{}} "),
                IResult::Error(ErrorKind::Tag)
            );

            assert_eq!(
                super::function_declaration("function {{}} "),
                IResult::Error(ErrorKind::Alt)
            );

            assert_eq!(
                super::function_declaration("function test( {{}} "),
                IResult::Error(ErrorKind::Tag)
            );
        }
    }
}<|endoftext|>


<commit_before>// This module implements configuration related stuff.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use std::os;
use std::io::File;
use std::collections::TreeMap;
use serialize::json::{Object, Json};

/// We provide ways to fill it from JSON files:
///
/// ```rust,no_run
/// let mut app = pencil::Pencil::new("/demo");
/// app.config.from_jsonfile("yourconfig.json")
/// ```
///
/// You can also load configurations from an environment variable
/// pointing to a file:
///
/// ```rust,no_run
/// let mut app = pencil::Pencil::new("/demo");
/// app.config.from_envvar("YOURAPPLICATION_SETTINGS")
/// ```
///
/// In this case, you have to set this environment variable to the file
/// you want to use.  On Linux and OS X you can use the export statement:
///
/// ```bash
/// export YOURAPPLICATION_SETTINGS="/path/to/config/file"
/// ```
#[deriving(Clone)]
pub struct Config {
    config: Object,
}

impl Config {
    /// Create a `Config` object.
    pub fn new() -> Config {
        let json_object: Object = TreeMap::new();
        Config {
            config: json_object,
        }
    }

    /// Set a value for the key.
    pub fn set(&mut self, key: &str, value: Json) {
        self.config.insert(key.to_string(), value);
    }

    /// Returns a reference to the value corresponding to the key.
    pub fn get(&self, key: &str) -> Option<&Json> {
        self.config.get(&key.to_string())
    }

    /// Loads a configuration from an environment variable pointing to
    /// a JSON configuration file.
    pub fn from_envvar(&mut self, variable_name: &str) {
        match os::getenv(variable_name) {
            Some(value) => self.from_jsonfile(value.as_slice()),
            None => panic!("The environment variable {} is not set.", variable_name),
        }
    }

    /// Updates the values in the config from a JSON file.
    pub fn from_jsonfile(&mut self, filepath: &str) {
        let path = Path::new(filepath);
        let mut file = File::open(&path).unwrap();
        let content = file.read_to_string().unwrap();
        let object: Json = from_str(content.as_slice()).unwrap();
        match object {
            Json::Object(object) => { self.from_object(object); },
            _ => { panic!("The configuration file is not an JSON object."); }
        }
    }

    /// Updates the values from the given `Object`.
    pub fn from_object(&mut self, object: Object) {
        for (key, value) in object.iter() {
            self.set(key.as_slice(), value.clone());
        }
    }
}
<commit_msg>Improved config doc<commit_after>// This module implements configuration related stuff.
// Copyright (c) 2014 by Shipeng Feng.
// Licensed under the BSD License, see LICENSE for more details.

use std::os;
use std::io::File;
use std::collections::TreeMap;
use serialize::json::{Object, Json};

/// The pencil `Config` type, We provide ways to fill it from JSON files:
///
/// ```rust,no_run
/// let mut app = pencil::Pencil::new("/demo");
/// app.config.from_jsonfile("yourconfig.json")
/// ```
///
/// You can also load configurations from an environment variable
/// pointing to a file:
///
/// ```rust,no_run
/// let mut app = pencil::Pencil::new("/demo");
/// app.config.from_envvar("YOURAPPLICATION_SETTINGS")
/// ```
///
/// In this case, you have to set this environment variable to the file
/// you want to use.  On Linux and OS X you can use the export statement:
///
/// ```bash
/// export YOURAPPLICATION_SETTINGS="/path/to/config/file"
/// ```
#[deriving(Clone)]
pub struct Config {
    config: Object,
}

impl Config {
    /// Create a `Config` object.
    pub fn new() -> Config {
        let json_object: Object = TreeMap::new();
        Config {
            config: json_object,
        }
    }

    /// Set a value for the key.
    pub fn set(&mut self, key: &str, value: Json) {
        self.config.insert(key.to_string(), value);
    }

    /// Returns a reference to the value corresponding to the key.
    pub fn get(&self, key: &str) -> Option<&Json> {
        self.config.get(&key.to_string())
    }

    /// Loads a configuration from an environment variable pointing to
    /// a JSON configuration file.
    pub fn from_envvar(&mut self, variable_name: &str) {
        match os::getenv(variable_name) {
            Some(value) => self.from_jsonfile(value.as_slice()),
            None => panic!("The environment variable {} is not set.", variable_name),
        }
    }

    /// Updates the values in the config from a JSON file.
    pub fn from_jsonfile(&mut self, filepath: &str) {
        let path = Path::new(filepath);
        let mut file = File::open(&path).unwrap();
        let content = file.read_to_string().unwrap();
        let object: Json = from_str(content.as_slice()).unwrap();
        match object {
            Json::Object(object) => { self.from_object(object); },
            _ => { panic!("The configuration file is not an JSON object."); }
        }
    }

    /// Updates the values from the given `Object`.
    pub fn from_object(&mut self, object: Object) {
        for (key, value) in object.iter() {
            self.set(key.as_slice(), value.clone());
        }
    }
}
<|endoftext|>


<commit_before>
use std::sync::{Arc, RwLock};

use cgmath::{Point3, Matrix4};
use byteorder::{WriteBytesExt, NativeEndian};
use gl;
use super::glsl;

pub struct Clouds {
    program: gl::Program,
    // Shader props
    _a_position: gl::Attribute,
    u_perspective_matrix: gl::Uniform,
    u_camera_matrix: gl::Uniform,
    u_light_level: gl::Uniform,
    u_sky_offset: gl::Uniform,
    u_offset: gl::Uniform,
    u_texture_info: gl::Uniform,
    u_atlas: gl::Uniform,
    u_textures: gl::Uniform,
    u_cloud_map: gl::Uniform,
    u_cloud_offset: gl::Uniform,

    array: gl::VertexArray,
    _buffer: gl::Buffer,

    textures: Arc<RwLock<super::TextureManager>>,

    texture: gl::Texture,
    pub heightmap_data: Vec<u8>,
    pub dirty: bool,

    offset: f64,
    num_points: usize,
}

impl Clouds {
    pub fn new(greg: &glsl::Registry, textures: Arc<RwLock<super::TextureManager>>) -> Clouds {
        let program = gl::Program::new();

        let vertex = greg.get("clouds_vertex");
        let geo = greg.get("clouds_geo");
        let fragment = greg.get("clouds_frag");

        let v = gl::Shader::new(gl::VERTEX_SHADER);
        v.set_source(&vertex);
        v.compile();

        if v.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", vertex);
            panic!("Shader error: {}", v.get_info_log());
        } else {
            let log = v.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        let g = gl::Shader::new(gl::GEOMETRY_SHADER);
        g.set_source(&geo);
        g.compile();

        if g.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", geo);
            panic!("Shader error: {}", g.get_info_log());
        } else {
            let log = g.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        let f = gl::Shader::new(gl::FRAGMENT_SHADER);
        f.set_source(&fragment);
        f.compile();

        if f.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", fragment);
            panic!("Shader error: {}", f.get_info_log());
        } else {
            let log = f.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        program.attach_shader(v);
        program.attach_shader(g);
        program.attach_shader(f);
        program.link();
        program.use_program();

        let a_position = program.attribute_location("aPosition");
        let u_perspective_matrix = program.uniform_location("perspectiveMatrix");
        let u_camera_matrix = program.uniform_location("cameraMatrix");
        let u_light_level = program.uniform_location("lightLevel");
        let u_sky_offset = program.uniform_location("skyOffset");
        let u_offset = program.uniform_location("offset");
        let u_texture_info = program.uniform_location("textureInfo");
        let u_atlas = program.uniform_location("atlas");
        let u_textures = program.uniform_location("textures");
        let u_cloud_map = program.uniform_location("cloudMap");
        let u_cloud_offset = program.uniform_location("cloudOffset");

        let array = gl::VertexArray::new();
        array.bind();
        let buffer = gl::Buffer::new();
        buffer.bind(gl::ARRAY_BUFFER);
        a_position.enable();
        a_position.vertex_pointer(3, gl::FLOAT, false, 12, 0);

        let mut data = vec![];
        let mut num_points = 0;
        for x in -160 .. 160 {
            for z in -160 .. 160 {
                let _ = data.write_f32::<NativeEndian>(x as f32);
                let _ = data.write_f32::<NativeEndian>(128.0);
                let _ = data.write_f32::<NativeEndian>(z as f32);
                num_points += 1;
            }
        }

        buffer.set_data(gl::ARRAY_BUFFER, &data, gl::STATIC_DRAW);

        let heightmap_data = vec![120; 512*512];

        let texture = gl::Texture::new();
        texture.bind(gl::TEXTURE_2D);
        texture.image_2d(gl::TEXTURE_2D, 0, 512, 512, gl::RED, gl::UNSIGNED_BYTE, Some(&heightmap_data));
        texture.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST);
        texture.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST);

        Clouds {
            program: program,
            // Shader props
            _a_position: a_position,
            u_perspective_matrix: u_perspective_matrix,
            u_camera_matrix: u_camera_matrix,
            u_light_level: u_light_level,
            u_sky_offset: u_sky_offset,
            u_offset: u_offset,
            u_texture_info: u_texture_info,
            u_atlas: u_atlas,
            u_textures: u_textures,
            u_cloud_map: u_cloud_map,
            u_cloud_offset: u_cloud_offset,

            array: array,
            _buffer: buffer,

            textures: textures,

            texture: texture,
            heightmap_data: heightmap_data,
            dirty: false,

            offset: 0.0,
            num_points: num_points,
        }
    }

    pub fn draw(&mut self, camera_pos: &Point3<f64>, perspective_matrix: &Matrix4<f32>, camera_matrix: &Matrix4<f32>, sky_offset: f32, light_level: f32, delta: f64) {
        self.offset += delta;

        let tex = super::Renderer::get_texture(&self.textures, "steven:environment/clouds");

        self.program.use_program();
        self.u_perspective_matrix.set_matrix4(perspective_matrix);
        self.u_camera_matrix.set_matrix4(camera_matrix);
        self.u_sky_offset.set_float(sky_offset);
        self.u_light_level.set_float(light_level);
        self.u_offset.set_float3(camera_pos.x.floor() as f32, 0.0, camera_pos.z.floor() as f32);
        self.u_texture_info.set_float4(
            tex.get_x() as f32,
            tex.get_y() as f32,
            tex.get_width() as f32,
            tex.get_height() as f32
        );
        self.u_atlas.set_float(tex.atlas as f32);
        self.u_cloud_offset.set_float((self.offset / 60.0) as f32);
        self.u_textures.set_int(0);

        gl::active_texture(1);
        self.texture.bind(gl::TEXTURE_2D);
        if self.dirty {
            self.texture.sub_image_2d(gl::TEXTURE_2D, 0, 0, 0, 512, 512, gl::RED, gl::UNSIGNED_BYTE, &self.heightmap_data);
            self.dirty = false;
        }
        self.u_cloud_map.set_int(1);
        self.array.bind();
        gl::draw_arrays(gl::POINTS, 0, self.num_points);
    }
}
<commit_msg>Fix light_level and sky_offset being swapped for clouds<commit_after>
use std::sync::{Arc, RwLock};

use cgmath::{Point3, Matrix4};
use byteorder::{WriteBytesExt, NativeEndian};
use gl;
use super::glsl;

pub struct Clouds {
    program: gl::Program,
    // Shader props
    _a_position: gl::Attribute,
    u_perspective_matrix: gl::Uniform,
    u_camera_matrix: gl::Uniform,
    u_light_level: gl::Uniform,
    u_sky_offset: gl::Uniform,
    u_offset: gl::Uniform,
    u_texture_info: gl::Uniform,
    u_atlas: gl::Uniform,
    u_textures: gl::Uniform,
    u_cloud_map: gl::Uniform,
    u_cloud_offset: gl::Uniform,

    array: gl::VertexArray,
    _buffer: gl::Buffer,

    textures: Arc<RwLock<super::TextureManager>>,

    texture: gl::Texture,
    pub heightmap_data: Vec<u8>,
    pub dirty: bool,

    offset: f64,
    num_points: usize,
}

impl Clouds {
    pub fn new(greg: &glsl::Registry, textures: Arc<RwLock<super::TextureManager>>) -> Clouds {
        let program = gl::Program::new();

        let vertex = greg.get("clouds_vertex");
        let geo = greg.get("clouds_geo");
        let fragment = greg.get("clouds_frag");

        let v = gl::Shader::new(gl::VERTEX_SHADER);
        v.set_source(&vertex);
        v.compile();

        if v.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", vertex);
            panic!("Shader error: {}", v.get_info_log());
        } else {
            let log = v.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        let g = gl::Shader::new(gl::GEOMETRY_SHADER);
        g.set_source(&geo);
        g.compile();

        if g.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", geo);
            panic!("Shader error: {}", g.get_info_log());
        } else {
            let log = g.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        let f = gl::Shader::new(gl::FRAGMENT_SHADER);
        f.set_source(&fragment);
        f.compile();

        if f.get_parameter(gl::COMPILE_STATUS) == 0 {
            println!("Src: {}", fragment);
            panic!("Shader error: {}", f.get_info_log());
        } else {
            let log = f.get_info_log();
            let log = log.trim().trim_matches('\u{0}');
            if !log.is_empty() {
                println!("{}", log);
            }
        }

        program.attach_shader(v);
        program.attach_shader(g);
        program.attach_shader(f);
        program.link();
        program.use_program();

        let a_position = program.attribute_location("aPosition");
        let u_perspective_matrix = program.uniform_location("perspectiveMatrix");
        let u_camera_matrix = program.uniform_location("cameraMatrix");
        let u_light_level = program.uniform_location("lightLevel");
        let u_sky_offset = program.uniform_location("skyOffset");
        let u_offset = program.uniform_location("offset");
        let u_texture_info = program.uniform_location("textureInfo");
        let u_atlas = program.uniform_location("atlas");
        let u_textures = program.uniform_location("textures");
        let u_cloud_map = program.uniform_location("cloudMap");
        let u_cloud_offset = program.uniform_location("cloudOffset");

        let array = gl::VertexArray::new();
        array.bind();
        let buffer = gl::Buffer::new();
        buffer.bind(gl::ARRAY_BUFFER);
        a_position.enable();
        a_position.vertex_pointer(3, gl::FLOAT, false, 12, 0);

        let mut data = vec![];
        let mut num_points = 0;
        for x in -160 .. 160 {
            for z in -160 .. 160 {
                let _ = data.write_f32::<NativeEndian>(x as f32);
                let _ = data.write_f32::<NativeEndian>(128.0);
                let _ = data.write_f32::<NativeEndian>(z as f32);
                num_points += 1;
            }
        }

        buffer.set_data(gl::ARRAY_BUFFER, &data, gl::STATIC_DRAW);

        let heightmap_data = vec![120; 512*512];

        let texture = gl::Texture::new();
        texture.bind(gl::TEXTURE_2D);
        texture.image_2d(gl::TEXTURE_2D, 0, 512, 512, gl::RED, gl::UNSIGNED_BYTE, Some(&heightmap_data));
        texture.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST);
        texture.set_parameter(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST);

        Clouds {
            program: program,
            // Shader props
            _a_position: a_position,
            u_perspective_matrix: u_perspective_matrix,
            u_camera_matrix: u_camera_matrix,
            u_light_level: u_light_level,
            u_sky_offset: u_sky_offset,
            u_offset: u_offset,
            u_texture_info: u_texture_info,
            u_atlas: u_atlas,
            u_textures: u_textures,
            u_cloud_map: u_cloud_map,
            u_cloud_offset: u_cloud_offset,

            array: array,
            _buffer: buffer,

            textures: textures,

            texture: texture,
            heightmap_data: heightmap_data,
            dirty: false,

            offset: 0.0,
            num_points: num_points,
        }
    }

    pub fn draw(&mut self, camera_pos: &Point3<f64>, perspective_matrix: &Matrix4<f32>, camera_matrix: &Matrix4<f32>, light_level: f32, sky_offset: f32, delta: f64) {
        self.offset += delta;

        let tex = super::Renderer::get_texture(&self.textures, "steven:environment/clouds");

        self.program.use_program();
        self.u_perspective_matrix.set_matrix4(perspective_matrix);
        self.u_camera_matrix.set_matrix4(camera_matrix);
        self.u_sky_offset.set_float(sky_offset);
        self.u_light_level.set_float(light_level);
        self.u_offset.set_float3(camera_pos.x.floor() as f32, 0.0, camera_pos.z.floor() as f32);
        self.u_texture_info.set_float4(
            tex.get_x() as f32,
            tex.get_y() as f32,
            tex.get_width() as f32,
            tex.get_height() as f32
        );
        self.u_atlas.set_float(tex.atlas as f32);
        self.u_cloud_offset.set_float((self.offset / 60.0) as f32);
        self.u_textures.set_int(0);

        gl::active_texture(1);
        self.texture.bind(gl::TEXTURE_2D);
        if self.dirty {
            self.texture.sub_image_2d(gl::TEXTURE_2D, 0, 0, 0, 512, 512, gl::RED, gl::UNSIGNED_BYTE, &self.heightmap_data);
            self.dirty = false;
        }
        self.u_cloud_map.set_int(1);
        self.array.bind();
        gl::draw_arrays(gl::POINTS, 0, self.num_points);
    }
}
<|endoftext|>


<commit_before>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

//! Render target specification.

use device;
use device::target::{Level, Layer, Mask};

#[derive(Copy, Clone, PartialEq, Debug)]
/// A single buffer that can be bound to a render target.
pub enum Plane {
    /// Render to a `Surface` (corresponds to a renderbuffer in GL).
    Surface(device::SurfaceHandle),
    /// Render to a texture at a specific mipmap level
    /// If `Layer` is set, it is selecting a single 2D slice of a given 3D texture
    Texture(device::TextureHandle, Level, Option<Layer>),
}

impl Plane {
    /// Get the surface info
    pub fn get_surface_info(&self) -> device::tex::SurfaceInfo {
        match *self {
            Plane::Surface(ref suf) => *suf.get_info(),
            Plane::Texture(ref tex, _, _) => tex.get_info().to_surface_info(),
        }
    }
}

/// A complete `Frame`, which is the result of rendering.
#[derive(Clone, PartialEq, Debug)]
pub struct Frame {
    /// The width of the viewport.
    pub width: u16,
    /// The height of the viewport.
    pub height: u16,
    /// Each color component has its own buffer.
    pub colors: Vec<Plane>,
    /// The depth buffer for this frame.
    pub depth: Option<Plane>,
    /// The stencil buffer for this frame.
    pub stencil: Option<Plane>,
}

impl Frame {
    /// Create an empty `Frame`, which corresponds to the 'default framebuffer',
    /// which renders directly to the window that was created with the OpenGL context.
    pub fn new(width: u16, height: u16) -> Frame {
        Frame {
            width: width,
            height: height,
            colors: Vec::new(),
            depth: None,
            stencil: None,
        }
    }

    /// Return true if this framebuffer is associated with the main window
    /// (matches `Frame::new` exactly).
    pub fn is_default(&self) -> bool {
        self.colors.is_empty() &&
        self.depth.is_none() &&
        self.stencil.is_none()
    }

    /// Return a mask of contained planes.
    pub fn get_mask(&self) -> Mask {
        use device::target as t;
        let mut mask = [t::COLOR0, t::COLOR1, t::COLOR2, t::COLOR3]
            .iter().zip(self.colors.iter())
            .fold(Mask::empty(), |u, (&m, _)| (u | m));
        if self.depth.is_some() {
            mask.insert(t::DEPTH);
        }
        if self.stencil.is_some() {
            mask.insert(t::STENCIL);
        }
        mask
    }
}
<commit_msg>Added a hack into Frame::get_mask to work with the default frame<commit_after>// Copyright 2014 The Gfx-rs Developers.
//
// 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.

//! Render target specification.

use device;
use device::target::{Level, Layer, Mask};

#[derive(Copy, Clone, PartialEq, Debug)]
/// A single buffer that can be bound to a render target.
pub enum Plane {
    /// Render to a `Surface` (corresponds to a renderbuffer in GL).
    Surface(device::SurfaceHandle),
    /// Render to a texture at a specific mipmap level
    /// If `Layer` is set, it is selecting a single 2D slice of a given 3D texture
    Texture(device::TextureHandle, Level, Option<Layer>),
}

impl Plane {
    /// Get the surface info
    pub fn get_surface_info(&self) -> device::tex::SurfaceInfo {
        match *self {
            Plane::Surface(ref suf) => *suf.get_info(),
            Plane::Texture(ref tex, _, _) => tex.get_info().to_surface_info(),
        }
    }
}

/// A complete `Frame`, which is the result of rendering.
#[derive(Clone, PartialEq, Debug)]
pub struct Frame {
    /// The width of the viewport.
    pub width: u16,
    /// The height of the viewport.
    pub height: u16,
    /// Each color component has its own buffer.
    pub colors: Vec<Plane>,
    /// The depth buffer for this frame.
    pub depth: Option<Plane>,
    /// The stencil buffer for this frame.
    pub stencil: Option<Plane>,
}

impl Frame {
    /// Create an empty `Frame`, which corresponds to the 'default framebuffer',
    /// which renders directly to the window that was created with the OpenGL context.
    pub fn new(width: u16, height: u16) -> Frame {
        Frame {
            width: width,
            height: height,
            colors: Vec::new(),
            depth: None,
            stencil: None,
        }
    }

    /// Return true if this framebuffer is associated with the main window
    /// (matches `Frame::new` exactly).
    pub fn is_default(&self) -> bool {
        self.colors.is_empty() &&
        self.depth.is_none() &&
        self.stencil.is_none()
    }

    /// Return a mask of contained planes.
    pub fn get_mask(&self) -> Mask {
        use device::target as t;
        let mut mask = [t::COLOR0, t::COLOR1, t::COLOR2, t::COLOR3]
            .iter().zip(self.colors.iter())
            .fold(Mask::empty(), |u, (&m, _)| (u | m));
        if self.depth.is_some() {
            mask.insert(t::DEPTH);
        }
        if self.stencil.is_some() {
            mask.insert(t::STENCIL);
        }
        if mask.is_empty() {
            // hack: assuming the default FBO has all planes
            t::COLOR | t::DEPTH | t::STENCIL
        }else {
            mask
        }
    }
}
<|endoftext|>