<commit_before>// https://github.com/serde-rs/serde/issues/927

use std::collections::HashMap;

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
#[macro_use] extern crate serde_json;
extern crate serde_yaml;
#[macro_use] extern crate serde_derive;

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
}

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgsTag {
    Args,
    Rets,
}

#[derive(Serialize, Deserialize, Debug)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArgs = HashMap<String, ArgValue>;
type NamedArgs2 = HashMap<String, serde_json::value::Value>;

#[derive(Serialize, Deserialize)]
struct DbusMessage {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    args: NamedArgs,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting(String, String, String, Vec<DbusMessage>);

#[derive(Serialize, Deserialize)]
struct ConfYaml(Vec<DbusMessageRouting>);

#[derive(Serialize, Deserialize, Debug)]
struct ClientRequest {
    #[serde(rename = "type")]
    tp: DbusMessageType,
    name: String,
    args: NamedArgs2,
}

#[derive(Serialize, Deserialize)]
struct ClientRequestBody(DbusMessageType, NamedArgs);

type CRequest = HashMap<String, ClientRequestBody>;

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: [
                                    ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                    ("param2".to_string(), ArgValue::Bool(true)),
                                    ("param3".to_string(), ArgValue::Int64(17i64)),
                                    ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest { tp: DbusMessageType::Method, name: "api_name".to_string(),
                            args: [     ("param1".to_string(), json!("Hi")),
                                        ("param2".to_string(), json!(true)),
                                        ("param3".to_string(), json!(17i64)),
                                        ("param4".to_string(), json!(2.718281828f64)),
                                ].iter().cloned().collect()
                          };
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let d: ClientRequest = serde_json::from_str(&rs).expect("json deserialization error");
    println!("d: {:?}", d);

    let rb = ClientRequestBody(DbusMessageType::Method, [
                                        ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                        ("param2".to_string(), ArgValue::Bool(true)),
                                        ("param3".to_string(), ArgValue::Int64(17i64)),
                                        ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );

    let mut a_request: CRequest = HashMap::new();
    a_request.insert("api_name".to_string(), rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

    let de: CRequest = serde_json::from_str(&rsq).expect("json deserialization error");

    let rsq2 = serde_json::to_string(&de).expect("json serialization error");
    println!("rsq2 : {}", rsq2);

    for key in de.keys() {
        println!("key {}", key);
    }
    println!("key[0] : {}", de.keys().nth(0).unwrap());

}
<commit_msg>args are optional.<commit_after>// https://github.com/serde-rs/serde/issues/927

use std::collections::HashMap;

extern crate yaml_rust;
extern crate argparse;
#[macro_use] extern crate log;
#[macro_use] extern crate from_variants;

extern crate serde;
#[macro_use] extern crate serde_json;
extern crate serde_yaml;
#[macro_use] extern crate serde_derive;

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgValue {
    None,
    Str(String),
    Bool(bool),
    Byte(u8),
    Int16(i16),
    Int32(i32),
    Int64(i64),
    UInt16(u16),
    UInt32(u32),
    UInt64(u64),
    Double(f64),
}

#[derive(Clone, Serialize, Deserialize, Debug)]
enum ArgsTag {
    Args,
    Rets,
}

#[derive(Serialize, Deserialize, Debug)]
enum DbusMessageType {
    Method,
    Signal,
}

type NamedArgs = HashMap<String, ArgValue>;
type NamedArgs2 = HashMap<String, serde_json::value::Value>;

#[derive(Serialize, Deserialize)]
struct DbusMessage {
    api_name: String,
    dbus_name: String,
    message_type: DbusMessageType,
    args: NamedArgs,
}

#[derive(Serialize, Deserialize)]
struct DbusMessageRouting(String, String, String, Vec<DbusMessage>);

#[derive(Serialize, Deserialize)]
struct ConfYaml(Vec<DbusMessageRouting>);

#[derive(Serialize, Deserialize, Debug)]
struct ClientRequest {
    #[serde(rename = "type")]
    tp: DbusMessageType,
    name: String,
    args: Option<NamedArgs2>,
}

#[derive(Serialize, Deserialize)]
struct ClientRequestBody(DbusMessageType, NamedArgs);

type CRequest = HashMap<String, ClientRequestBody>;

fn main()
{
    let conf = vec![
        DbusMessageRouting(
            "com.a.b.servicetest".to_string(),
            "/com/a/b/servicetest".to_string(),
            "com.a.b.IServiceTest".to_string(),
            vec![ DbusMessage { api_name: "api_name".to_string(),
                                dbus_name: "dbus_name".to_string(),
                                message_type: DbusMessageType::Method,
                                args: [
                                    ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                    ("param2".to_string(), ArgValue::Bool(true)),
                                    ("param3".to_string(), ArgValue::Int64(17i64)),
                                    ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                              }
            ]
        )
    ];

    let s = serde_yaml::to_string(&conf).unwrap();
    println!("s : {}", s);

    let r = ClientRequest { tp: DbusMessageType::Method, name: "api_name".to_string(),
                            args: Some([    ("param1".to_string(), json!("Hi")),
                                            ("param2".to_string(), json!(true)),
                                            ("param3".to_string(), json!(17i64)),
                                            ("param4".to_string(), json!(2.718281828f64)),
                                       ].iter().cloned().collect())
                          };
    let rs = serde_json::to_string(&r).unwrap();
    println!("rs : {}", rs);

    let d: ClientRequest = serde_json::from_str(&rs).expect("json deserialization error");
    println!("d: {:?}", d);

    let rb = ClientRequestBody(DbusMessageType::Method, [
                                        ("param1".to_string(), ArgValue::Str("Hi".to_string())),
                                        ("param2".to_string(), ArgValue::Bool(true)),
                                        ("param3".to_string(), ArgValue::Int64(17i64)),
                                        ("param4".to_string(), ArgValue::Double(2.718281828f64)),
                                ].iter().cloned().collect()
                          );

    let mut a_request: CRequest = HashMap::new();
    a_request.insert("api_name".to_string(), rb);

    let rsq = serde_json::to_string(&a_request).unwrap();
    println!("rsq : {}", rsq);

    let de: CRequest = serde_json::from_str(&rsq).expect("json deserialization error");

    let rsq2 = serde_json::to_string(&de).expect("json serialization error");
    println!("rsq2 : {}", rsq2);

    for key in de.keys() {
        println!("key {}", key);
    }
    println!("key[0] : {}", de.keys().nth(0).unwrap());

}
<|endoftext|>


<commit_before>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! Boundary parsing for `multipart` requests.

use ::safemem;

use super::buf_redux::BufReader;
use super::twoway;

use log::LogLevel;

use std::cmp;
use std::borrow::Borrow;

use std::io;
use std::io::prelude::*;

/// A struct implementing `Read` and `BufRead` that will yield bytes until it sees a given sequence.
#[derive(Debug)]
pub struct BoundaryReader<R> {
    source: BufReader<R>,
    boundary: Vec<u8>,
    search_idx: usize,
    boundary_read: bool,
    at_end: bool,
}

impl<R> BoundaryReader<R> where R: Read {
    #[doc(hidden)]
    pub fn from_reader<B: Into<Vec<u8>>>(reader: R, boundary: B) -> BoundaryReader<R> {
        let mut boundary = boundary.into();
        safemem::prepend(b"--", &mut boundary);

        BoundaryReader {
            source: BufReader::new(reader),
            boundary: boundary,
            search_idx: 0,
            boundary_read: false,
            at_end: false,
        }
    }

    fn read_to_boundary(&mut self) -> io::Result<&[u8]> {
        // Make sure there's enough bytes in the buffer to positively identify the boundary.
        let min_len = self.search_idx + (self.boundary.len() * 2);

        let buf = fill_buf_min(&mut self.source, min_len)?;

        if buf.is_empty() {
            debug!("fill_buf_min returned zero-sized buf");
            self.at_end = true;
            return Ok(buf);
        }

        trace!("Buf: {:?}", String::from_utf8_lossy(buf));

        debug!("Before-loop Buf len: {} Search idx: {} Boundary read: {:?}",
               buf.len(), self.search_idx, self.boundary_read);

        if !self.boundary_read && self.search_idx < buf.len() {
            let lookahead = &buf[self.search_idx..];

            debug!("Find boundary loop! Lookahead len: {}", lookahead.len());

            // Look for the boundary, or if it isn't found, stop near the end.
            match twoway::find_bytes(lookahead, &self.boundary) {
                Some(found_idx) => {
                    self.search_idx += found_idx;
                    self.boundary_read = true;
                },
                None => {
                    self.search_idx += lookahead.len().saturating_sub(self.boundary.len() + 2);
                }
            }
        }

        debug!("After-loop Buf len: {} Search idx: {} Boundary read: {:?}",
               buf.len(), self.search_idx, self.boundary_read);

        // If the two bytes before the boundary are a CR-LF, we need to back up
        // the cursor so we don't yield bytes that client code isn't expecting.
        if self.boundary_read && self.search_idx >= 2 {
            let two_bytes_before = &buf[self.search_idx - 2 .. self.search_idx];

            trace!("Two bytes before: {:?} ({:?}) (\"\\r\\n\": {:?})",
                   String::from_utf8_lossy(two_bytes_before), two_bytes_before, b"\r\n");

            if two_bytes_before == &*b"\r\n" {
                debug!("Subtract two!");
                self.search_idx -= 2;
            }
        }

        let ret_buf = &buf[..self.search_idx];

        trace!("Returning buf: {:?}", String::from_utf8_lossy(ret_buf));

        Ok(ret_buf)
    }

    #[doc(hidden)]
    pub fn consume_boundary(&mut self) -> io::Result<bool> {
        if self.at_end {
            return Ok(true);
        }

        while !(self.boundary_read || self.at_end){
            debug!("Boundary not found yet");

            let buf_len = self.read_to_boundary()?.len();

            debug!("Discarding {} bytes", buf_len);

            if buf_len == 0 {
                break;
            }

            self.consume(buf_len);
        }

        self.source.consume(self.search_idx);
        self.search_idx = 0;

        trace!("Consumed up to self.search_idx, remaining buf: {:?}",
               String::from_utf8_lossy(self.source.get_buf()));

        let consume_amt = {
            let buf = self.source.get_buf();
            self.boundary.len() + if buf.len() >=2 && buf[..2] == *b"\r\n" { 2 } else { 0 }
        };

        self.source.consume(consume_amt);
        self.boundary_read = false;

        let mut bytes_after = [0, 0];

        let read = self.source.read(&mut bytes_after)?;

        if read == 1 {
            let _ = self.source.read(&mut bytes_after[1..])?;
        }

        if bytes_after == *b"--" {
            self.at_end = true;
        } else if bytes_after != *b"\r\n" {
            debug!("Unexpected bytes following boundary: {:?}", String::from_utf8_lossy(&bytes_after));
        }

        trace!("Consumed boundary (at_end: {:?}), remaining buf: {:?}", self.at_end,
               String::from_utf8_lossy(self.source.get_buf()));

        Ok(self.at_end)
    }
}

#[cfg(feature = "bench")]
impl<'a> BoundaryReader<io::Cursor<&'a [u8]>> {
    fn new_with_bytes(bytes: &'a [u8], boundary: &str) -> Self {
        Self::from_reader(io::Cursor::new(bytes), boundary)
    }

    fn reset(&mut self) {
        // Dump buffer and reset cursor
        self.source.seek(io::SeekFrom::Start(0));
        self.at_end = false;
        self.boundary_read = false;
        self.search_idx = 0;
    }
}

impl<R> Borrow<R> for BoundaryReader<R> {
    fn borrow(&self) -> &R {
        self.source.get_ref()
    }
}

impl<R> Read for BoundaryReader<R> where R: Read {
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        let read = {
            let mut buf = self.read_to_boundary()?;
            // This shouldn't ever be an error so unwrapping is fine.
            buf.read(out).unwrap()
        };

        self.consume(read);
        Ok(read)
    }
}

impl<R> BufRead for BoundaryReader<R> where R: Read {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.read_to_boundary()
    }

    fn consume(&mut self, amt: usize) {
        let true_amt = cmp::min(amt, self.search_idx);

        debug!("Consume! amt: {} true amt: {}", amt, true_amt);

        self.source.consume(true_amt);
        self.search_idx -= true_amt;
    }
}

fn fill_buf_min<R: Read>(buf: &mut BufReader<R>, min: usize) -> io::Result<&[u8]> {
    const MAX_ATTEMPTS: usize = 3;

    let mut attempts = 0;

    while buf.available() < min && attempts < MAX_ATTEMPTS {
        if buf.read_into_buf()? == 0 { break; };
        attempts += 1;
    }

    Ok(buf.get_buf())
}

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

    use std::io;
    use std::io::prelude::*;

    const BOUNDARY: &'static str = "boundary";
    const TEST_VAL: &'static str = "--boundary\r\n\
                                    dashed-value-1\r\n\
                                    --boundary\r\n\
                                    dashed-value-2\r\n\
                                    --boundary--";

    #[test]
    fn test_boundary() {
        let _ = ::env_logger::init();
        debug!("Testing boundary (no split)");

        let src = &mut TEST_VAL.as_bytes();
        let mut reader = BoundaryReader::from_reader(src, BOUNDARY);

        let mut buf = String::new();

        test_boundary_reader(&mut reader, &mut buf);
    }

    struct SplitReader<'a> {
        left: &'a [u8],
        right: &'a [u8],
    }

    impl<'a> SplitReader<'a> {
        fn split(data: &'a [u8], at: usize) -> SplitReader<'a> {
            let (left, right) = data.split_at(at);

            SplitReader {
                left: left,
                right: right,
            }
        }
    }

    impl<'a> Read for SplitReader<'a> {
        fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
            fn copy_bytes_partial(src: &mut &[u8], dst: &mut [u8]) -> usize {
                src.read(dst).unwrap()
            }

            let mut copy_amt = copy_bytes_partial(&mut self.left, dst);

            if copy_amt == 0 {
                copy_amt = copy_bytes_partial(&mut self.right, dst)
            };

            Ok(copy_amt)
        }
    }

    #[test]
    fn test_split_boundary() {
        let _ = ::env_logger::init();
        debug!("Testing boundary (split)");

        let mut buf = String::new();

        // Substitute for `.step_by()` being unstable.
        for split_at in 0 .. TEST_VAL.len(){
            debug!("Testing split at: {}", split_at);

            let src = SplitReader::split(TEST_VAL.as_bytes(), split_at);
            let mut reader = BoundaryReader::from_reader(src, BOUNDARY);
            test_boundary_reader(&mut reader, &mut buf);
        }

    }

    fn test_boundary_reader<R: Read>(reader: &mut BoundaryReader<R>, buf: &mut String) {
        buf.clear();

        debug!("Read 1");
        let _ = reader.read_to_string(buf).unwrap();
        assert!(buf.is_empty(), "Buffer not empty: {:?}", buf);
        buf.clear();

        debug!("Consume 1");
        reader.consume_boundary().unwrap();

        debug!("Read 2");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "dashed-value-1");
        buf.clear();

        debug!("Consume 2");
        reader.consume_boundary().unwrap();

        debug!("Read 3");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "dashed-value-2");
        buf.clear();

        debug!("Consume 3");
        reader.consume_boundary().unwrap();

        debug!("Read 4");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "");
    }

    #[cfg(feature = "bench")]
    mod bench {
        extern crate test;
        use self::test::Bencher;

        use super::*;

        #[bench]
        fn bench_boundary_reader(b: &mut Bencher) {
            let mut reader = BoundaryReader::new_with_bytes(TEST_VAL.as_bytes(), BOUNDARY);
            let mut buf = String::with_capacity(256);

            b.iter(|| {
                reader.reset();
                test_boundary_reader(&mut reader, &mut buf);
            });
        }
    }
}
<commit_msg>Consume multiple \r\n when needed<commit_after>// Copyright 2016 `multipart` Crate Developers
//
// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
// http://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.

//! Boundary parsing for `multipart` requests.

use ::safemem;

use super::buf_redux::BufReader;
use super::twoway;

use log::LogLevel;

use std::cmp;
use std::borrow::Borrow;

use std::io;
use std::io::prelude::*;

/// A struct implementing `Read` and `BufRead` that will yield bytes until it sees a given sequence.
#[derive(Debug)]
pub struct BoundaryReader<R> {
    source: BufReader<R>,
    boundary: Vec<u8>,
    search_idx: usize,
    boundary_read: bool,
    at_end: bool,
}

impl<R> BoundaryReader<R> where R: Read {
    #[doc(hidden)]
    pub fn from_reader<B: Into<Vec<u8>>>(reader: R, boundary: B) -> BoundaryReader<R> {
        let mut boundary = boundary.into();
        safemem::prepend(b"--", &mut boundary);

        BoundaryReader {
            source: BufReader::new(reader),
            boundary: boundary,
            search_idx: 0,
            boundary_read: false,
            at_end: false,
        }
    }

    fn read_to_boundary(&mut self) -> io::Result<&[u8]> {
        // Make sure there's enough bytes in the buffer to positively identify the boundary.
        let min_len = self.search_idx + (self.boundary.len() * 2);

        let buf = fill_buf_min(&mut self.source, min_len)?;

        if buf.is_empty() {
            debug!("fill_buf_min returned zero-sized buf");
            self.at_end = true;
            return Ok(buf);
        }

        trace!("Buf: {:?}", String::from_utf8_lossy(buf));

        debug!("Before-loop Buf len: {} Search idx: {} Boundary read: {:?}",
               buf.len(), self.search_idx, self.boundary_read);

        if !self.boundary_read && self.search_idx < buf.len() {
            let lookahead = &buf[self.search_idx..];

            debug!("Find boundary loop! Lookahead len: {}", lookahead.len());

            // Look for the boundary, or if it isn't found, stop near the end.
            match twoway::find_bytes(lookahead, &self.boundary) {
                Some(found_idx) => {
                    self.search_idx += found_idx;
                    self.boundary_read = true;
                },
                None => {
                    self.search_idx += lookahead.len().saturating_sub(self.boundary.len() + 2);
                }
            }
        }

        debug!("After-loop Buf len: {} Search idx: {} Boundary read: {:?}",
               buf.len(), self.search_idx, self.boundary_read);

        // If the two bytes before the boundary are a CR-LF, we need to back up
        // the cursor so we don't yield bytes that client code isn't expecting.
        if self.boundary_read && self.search_idx >= 2 {
            let two_bytes_before = &buf[self.search_idx - 2 .. self.search_idx];

            trace!("Two bytes before: {:?} ({:?}) (\"\\r\\n\": {:?})",
                   String::from_utf8_lossy(two_bytes_before), two_bytes_before, b"\r\n");

            if two_bytes_before == &*b"\r\n" {
                debug!("Subtract two!");
                self.search_idx -= 2;
            }
        }

        let ret_buf = &buf[..self.search_idx];

        trace!("Returning buf: {:?}", String::from_utf8_lossy(ret_buf));

        Ok(ret_buf)
    }

    #[doc(hidden)]
    pub fn consume_boundary(&mut self) -> io::Result<bool> {
        if self.at_end {
            return Ok(true);
        }

        while !(self.boundary_read || self.at_end){
            debug!("Boundary not found yet");

            let buf_len = self.read_to_boundary()?.len();

            debug!("Discarding {} bytes", buf_len);

            if buf_len == 0 {
                break;
            }

            self.consume(buf_len);
        }

        self.source.consume(self.search_idx);
        self.search_idx = 0;

        trace!("Consumed up to self.search_idx, remaining buf: {:?}",
               String::from_utf8_lossy(self.source.get_buf()));

        let consume_amt = {
            let buf = self.source.get_buf();
            let mut skip_size = 0;
            while buf.len() >= skip_size + 2 && buf[skip_size..(skip_size + 2)] == *b"\r\n" {
                skip_size += 2;
            }
            self.boundary.len() + skip_size
        };

        self.source.consume(consume_amt);
        self.boundary_read = false;

        let mut bytes_after = [0, 0];

        let read = self.source.read(&mut bytes_after)?;

        if read == 1 {
            let _ = self.source.read(&mut bytes_after[1..])?;
        }

        if bytes_after == *b"--" {
            self.at_end = true;
        } else if bytes_after != *b"\r\n" {
            debug!("Unexpected bytes following boundary: {:?}", String::from_utf8_lossy(&bytes_after));
        }

        trace!("Consumed boundary (at_end: {:?}), remaining buf: {:?}", self.at_end,
               String::from_utf8_lossy(self.source.get_buf()));

        Ok(self.at_end)
    }
}

#[cfg(feature = "bench")]
impl<'a> BoundaryReader<io::Cursor<&'a [u8]>> {
    fn new_with_bytes(bytes: &'a [u8], boundary: &str) -> Self {
        Self::from_reader(io::Cursor::new(bytes), boundary)
    }

    fn reset(&mut self) {
        // Dump buffer and reset cursor
        self.source.seek(io::SeekFrom::Start(0));
        self.at_end = false;
        self.boundary_read = false;
        self.search_idx = 0;
    }
}

impl<R> Borrow<R> for BoundaryReader<R> {
    fn borrow(&self) -> &R {
        self.source.get_ref()
    }
}

impl<R> Read for BoundaryReader<R> where R: Read {
    fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
        let read = {
            let mut buf = self.read_to_boundary()?;
            // This shouldn't ever be an error so unwrapping is fine.
            buf.read(out).unwrap()
        };

        self.consume(read);
        Ok(read)
    }
}

impl<R> BufRead for BoundaryReader<R> where R: Read {
    fn fill_buf(&mut self) -> io::Result<&[u8]> {
        self.read_to_boundary()
    }

    fn consume(&mut self, amt: usize) {
        let true_amt = cmp::min(amt, self.search_idx);

        debug!("Consume! amt: {} true amt: {}", amt, true_amt);

        self.source.consume(true_amt);
        self.search_idx -= true_amt;
    }
}

fn fill_buf_min<R: Read>(buf: &mut BufReader<R>, min: usize) -> io::Result<&[u8]> {
    const MAX_ATTEMPTS: usize = 3;

    let mut attempts = 0;

    while buf.available() < min && attempts < MAX_ATTEMPTS {
        if buf.read_into_buf()? == 0 { break; };
        attempts += 1;
    }

    Ok(buf.get_buf())
}

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

    use std::io;
    use std::io::prelude::*;

    const BOUNDARY: &'static str = "boundary";
    const TEST_VAL: &'static str = "--boundary\r\n\
                                    dashed-value-1\r\n\
                                    --boundary\r\n\
                                    dashed-value-2\r\n\
                                    --boundary--";

    #[test]
    fn test_boundary() {
        let _ = ::env_logger::init();
        debug!("Testing boundary (no split)");

        let src = &mut TEST_VAL.as_bytes();
        let mut reader = BoundaryReader::from_reader(src, BOUNDARY);

        let mut buf = String::new();

        test_boundary_reader(&mut reader, &mut buf);
    }

    struct SplitReader<'a> {
        left: &'a [u8],
        right: &'a [u8],
    }

    impl<'a> SplitReader<'a> {
        fn split(data: &'a [u8], at: usize) -> SplitReader<'a> {
            let (left, right) = data.split_at(at);

            SplitReader {
                left: left,
                right: right,
            }
        }
    }

    impl<'a> Read for SplitReader<'a> {
        fn read(&mut self, dst: &mut [u8]) -> io::Result<usize> {
            fn copy_bytes_partial(src: &mut &[u8], dst: &mut [u8]) -> usize {
                src.read(dst).unwrap()
            }

            let mut copy_amt = copy_bytes_partial(&mut self.left, dst);

            if copy_amt == 0 {
                copy_amt = copy_bytes_partial(&mut self.right, dst)
            };

            Ok(copy_amt)
        }
    }

    #[test]
    fn test_split_boundary() {
        let _ = ::env_logger::init();
        debug!("Testing boundary (split)");

        let mut buf = String::new();

        // Substitute for `.step_by()` being unstable.
        for split_at in 0 .. TEST_VAL.len(){
            debug!("Testing split at: {}", split_at);

            let src = SplitReader::split(TEST_VAL.as_bytes(), split_at);
            let mut reader = BoundaryReader::from_reader(src, BOUNDARY);
            test_boundary_reader(&mut reader, &mut buf);
        }

    }

    fn test_boundary_reader<R: Read>(reader: &mut BoundaryReader<R>, buf: &mut String) {
        buf.clear();

        debug!("Read 1");
        let _ = reader.read_to_string(buf).unwrap();
        assert!(buf.is_empty(), "Buffer not empty: {:?}", buf);
        buf.clear();

        debug!("Consume 1");
        reader.consume_boundary().unwrap();

        debug!("Read 2");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "dashed-value-1");
        buf.clear();

        debug!("Consume 2");
        reader.consume_boundary().unwrap();

        debug!("Read 3");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "dashed-value-2");
        buf.clear();

        debug!("Consume 3");
        reader.consume_boundary().unwrap();

        debug!("Read 4");
        let _ = reader.read_to_string(buf).unwrap();
        assert_eq!(buf, "");
    }

    #[cfg(feature = "bench")]
    mod bench {
        extern crate test;
        use self::test::Bencher;

        use super::*;

        #[bench]
        fn bench_boundary_reader(b: &mut Bencher) {
            let mut reader = BoundaryReader::new_with_bytes(TEST_VAL.as_bytes(), BOUNDARY);
            let mut buf = String::with_capacity(256);

            b.iter(|| {
                reader.reset();
                test_boundary_reader(&mut reader, &mut buf);
            });
        }
    }
}
<|endoftext|>


<commit_before>extern crate protobuf;
extern crate rand;
extern crate time;

use std::io::File;
use std::io::MemWriter;
use std::default::Default;
use std::os;

use std::rand::Rng;
use std::rand::StdRng;
use std::rand::SeedableRng;

use protobuf::Message;
use perftest_data::PerftestData;

mod perftest_data;

fn measure_ns<R>(f: || -> R) -> (u64, R) {
    let start = time::precise_time_ns();
    let r = f();
    (time::precise_time_ns() - start, r)
}

fn measure_and_print<R>(title: &str, iter: u64, f: || -> R) -> R {
    let (ns, r) = measure_ns(f);
    let ns_per_iter = ns / iter;
    println!("{}: {} ns per iter", title, ns_per_iter);
    r
}

fn run_test<M : Message>(name: &str, data: &[M]) {
    let mut rng: StdRng = SeedableRng::from_seed([10, 20, 30, 40].as_slice());
    let mut random_data: Vec<M> = Vec::new();

    let mut total_size = 0;
    while total_size < 1000000 {
        let ref item = data[rng.gen_range(0, data.len())];
        random_data.push(item.clone());
        total_size += item.compute_size();
    }

    let mut writer = MemWriter::new();
    measure_and_print(format!("{}: write", name).as_slice(), random_data.len() as u64, || {
        for m in random_data.iter() {
            m.write_length_delimited_to_writer(&mut writer).unwrap();
        }
    });

    let buf = writer.unwrap();

    let read_data = measure_and_print(format!("{}: read", name).as_slice(), random_data.len() as u64, || {
        let mut r = Vec::new();
        let mut coded_input_stream = protobuf::CodedInputStream::from_bytes(buf.as_slice());
        while !coded_input_stream.eof().unwrap() {
            r.push(protobuf::parse_length_delimited_from::<M>(&mut coded_input_stream).unwrap());
        }
        r
    });

    assert_eq!(random_data, read_data);

    let merged = measure_and_print(format!("{}: read reuse", name).as_slice(), random_data.len() as u64, || {
        let mut coded_input_stream = protobuf::CodedInputStream::from_bytes(buf.as_slice());
        let mut msg: M = Default::default();
        let mut count = 0;
        while !coded_input_stream.eof().unwrap() {
            msg.clear();
            coded_input_stream.merge_message(&mut msg).unwrap();
            count += 1;
        }
        count
    });

    assert_eq!(random_data.len(), merged);
}

struct TestRunner {
    selected: Option<String>,
    any_matched: bool,
}

impl TestRunner {
    fn test<M : Message>(&mut self, name: &str, data: &[M]) {
        if self.selected.is_none() || name == self.selected.as_ref().unwrap().as_slice() {
            run_test(name, data);
            self.any_matched = true;
        }
    }

    fn check(&self) {
        if !self.any_matched {
            let name = self.selected.as_ref().map(|s| s.as_slice()).unwrap_or("bug");
            panic!("no tests found with name {}", name);
        }
    }
}

fn main() {
    let selected = match os::args().as_slice() {
        [_] => None,
        [_, ref test] => Some(test.to_string()),
        v => panic!("usage: {} <test>", v[0]),
    };

    let mut runner = TestRunner { selected: selected, any_matched: false };

    let mut is = File::open(&Path::new("perftest_data.pbbin"));
    let test_data = protobuf::parse_from_reader::<PerftestData>(&mut is).unwrap();

    runner.test("test1", test_data.get_test1());
    runner.test("test_repeated_bool", test_data.get_test_repeated_bool());
    runner.test("test_repeated_packed_int32", test_data.get_test_repeated_packed_int32());
    runner.test("test_repeated_messages", test_data.get_test_repeated_messages());
    runner.test("test_optional_messages", test_data.get_test_optional_messages());
    runner.test("test_strings", test_data.get_test_strings());
    runner.check();
}
<commit_msg>Fix warning<commit_after>extern crate protobuf;
extern crate rand;
extern crate time;

use std::io::File;
use std::io::MemWriter;
use std::default::Default;
use std::os;

use std::rand::Rng;
use std::rand::StdRng;
use std::rand::SeedableRng;

use protobuf::Message;
use perftest_data::PerftestData;

mod perftest_data;

fn measure_ns<R>(f: || -> R) -> (u64, R) {
    let start = time::precise_time_ns();
    let r = f();
    (time::precise_time_ns() - start, r)
}

fn measure_and_print<R>(title: &str, iter: u64, f: || -> R) -> R {
    let (ns, r) = measure_ns(f);
    let ns_per_iter = ns / iter;
    println!("{}: {} ns per iter", title, ns_per_iter);
    r
}

fn run_test<M : Message>(name: &str, data: &[M]) {
    let mut rng: StdRng = SeedableRng::from_seed([10, 20, 30, 40].as_slice());
    let mut random_data: Vec<M> = Vec::new();

    let mut total_size = 0;
    while total_size < 1000000 {
        let ref item = data[rng.gen_range(0, data.len())];
        random_data.push(item.clone());
        total_size += item.compute_size();
    }

    let mut writer = MemWriter::new();
    measure_and_print(format!("{}: write", name).as_slice(), random_data.len() as u64, || {
        for m in random_data.iter() {
            m.write_length_delimited_to_writer(&mut writer).unwrap();
        }
    });

    let buf = writer.into_inner();

    let read_data = measure_and_print(format!("{}: read", name).as_slice(), random_data.len() as u64, || {
        let mut r = Vec::new();
        let mut coded_input_stream = protobuf::CodedInputStream::from_bytes(buf.as_slice());
        while !coded_input_stream.eof().unwrap() {
            r.push(protobuf::parse_length_delimited_from::<M>(&mut coded_input_stream).unwrap());
        }
        r
    });

    assert_eq!(random_data, read_data);

    let merged = measure_and_print(format!("{}: read reuse", name).as_slice(), random_data.len() as u64, || {
        let mut coded_input_stream = protobuf::CodedInputStream::from_bytes(buf.as_slice());
        let mut msg: M = Default::default();
        let mut count = 0;
        while !coded_input_stream.eof().unwrap() {
            msg.clear();
            coded_input_stream.merge_message(&mut msg).unwrap();
            count += 1;
        }
        count
    });

    assert_eq!(random_data.len(), merged);
}

struct TestRunner {
    selected: Option<String>,
    any_matched: bool,
}

impl TestRunner {
    fn test<M : Message>(&mut self, name: &str, data: &[M]) {
        if self.selected.is_none() || name == self.selected.as_ref().unwrap().as_slice() {
            run_test(name, data);
            self.any_matched = true;
        }
    }

    fn check(&self) {
        if !self.any_matched {
            let name = self.selected.as_ref().map(|s| s.as_slice()).unwrap_or("bug");
            panic!("no tests found with name {}", name);
        }
    }
}

fn main() {
    let selected = match os::args().as_slice() {
        [_] => None,
        [_, ref test] => Some(test.to_string()),
        v => panic!("usage: {} <test>", v[0]),
    };

    let mut runner = TestRunner { selected: selected, any_matched: false };

    let mut is = File::open(&Path::new("perftest_data.pbbin"));
    let test_data = protobuf::parse_from_reader::<PerftestData>(&mut is).unwrap();

    runner.test("test1", test_data.get_test1());
    runner.test("test_repeated_bool", test_data.get_test_repeated_bool());
    runner.test("test_repeated_packed_int32", test_data.get_test_repeated_packed_int32());
    runner.test("test_repeated_messages", test_data.get_test_repeated_messages());
    runner.test("test_optional_messages", test_data.get_test_optional_messages());
    runner.test("test_strings", test_data.get_test_strings());
    runner.check();
}
<|endoftext|>


<commit_before>use std::collections::{BTreeMap, HashSet};
use std::ascii::AsciiExt;
use std::cmp::Ordering;

use syntax::{ast, visit};
use syntax::parse::token;
use syntax::codemap::{Span, BytePos};
use syntax::attr::AttrMetaMethods;
use syntax::ast::NodeId;

use rustc::middle::privacy::ExportedItems;

use words;
use stem;

#[derive(Copy)]
pub struct Position {
    pub span: Span,
    pub id: NodeId,
}

impl Position {
    fn new(sp: Span, id: NodeId) -> Position {
        Position { span: sp, id: id, }
    }
}

impl PartialEq for Position {
    fn eq(&self, other: &Position) -> bool {
        self.cmp(other) == Ordering::Equal
    }
}
impl Eq for Position {}
impl PartialOrd for Position {
    fn partial_cmp(&self, other: &Position) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for Position {
    fn cmp(&self, other: &Position) -> Ordering {
        let Span { lo: BytePos(slo), hi: BytePos(shi), .. } = self.span;
        let Span { lo: BytePos(olo), hi: BytePos(ohi), .. } = other.span;
        // order by span, and then by ID.
        (slo, shi, self.id).cmp(&(olo, ohi, other.id))
    }
}

/// Keeps track of the reference dictionary and the misspelled words
/// through a traversal of the whole ast.
pub struct SpellingVisitor<'a> {
    /// The reference dictionary.
    words: &'a HashSet<String>,

    /// The truly exported items.
    exported: &'a ExportedItems,

    /// The misspelled words
    pub misspellings: BTreeMap<Position, Vec<String>>,

    /// Whether the traversal should only check documentation, not
    /// idents; gets controlled internally, e.g. for `extern` blocks.
    doc_only: bool
}

impl<'a> SpellingVisitor<'a> {
    /// ast::Create a new Spelling Visitor.
    pub fn new<'b>(words: &'b HashSet<String>,
                   exported: &'b ExportedItems) -> SpellingVisitor<'b> {
        SpellingVisitor {
            words: words,
            exported: exported,
            misspellings: BTreeMap::new(),
            doc_only: false
        }
    }

    /// Checks if the given string is a correct "word", without
    /// splitting it at all. Any word that isn't entirely alphabetic
    /// is automatically considered a proper word.
    fn raw_word_is_correct(&mut self, w: &str) -> bool {
        self.words.contains(w) ||
            !w.chars().all(|c| c.is_alphabetic()) || {
                let lower = w.to_ascii_lowercase();
                self.words.contains(&lower) ||
                self.stemmed_word_is_correct(&lower)
            }
    }

    fn stemmed_word_is_correct(&self, w: &str) -> bool {
        stem::get(w).ok().map_or(false, |s| self.words.contains(&s))
    }

    /// Check a word for correctness, including splitting `foo_bar`
    /// and `FooBar` into `foo` & `bar` and `Foo` & `Bar`
    /// respectively. This inserts any incorrect word(s) into the
    /// misspelling map.
    fn check_subwords(&mut self, w: &str, pos: Position) {
        for w in words::subwords(w) {
            if !self.raw_word_is_correct(w) {
                let w = w.to_string();
                self.misspellings.entry(pos).get().unwrap_or_else(|v| v.insert(vec![])).push(w);
            }
        }
    }

    /// Check a single ident for misspellings; possibly separating it
    /// into subwords.
    fn check_ident(&mut self, ident: ast::Ident, pos: Position) {
        if self.doc_only { return }

        // spooky action at a distance; extracts the string
        // representation from TLS.
        let word = token::get_ident(ident);
        // secret rust internals, e.g. __std_macros
        if word.starts_with("__") { return }

        // the ident itself is correct, so shortcircuit to avoid doing
        // any of the submatching done below.
        if self.raw_word_is_correct(&word) {
            return
        }

        self.check_subwords(&word, pos);
    }

    /// Check the #[doc="..."] (and the commment forms) attributes for
    /// spelling.
    fn check_doc_attrs(&mut self, attrs: &[ast::Attribute], id: NodeId) {
        for attr in attrs.iter() {
            if attr.check_name("doc") {
                match attr.value_str() {
                    Some(s) => self.check_subwords(&s, Position::new(attr.span, id)),
                    None => {}
                }
            }
        }
    }

    /// Spell-check a whole krate.
    pub fn check_crate(&mut self, krate: &ast::Crate) {
        self.check_doc_attrs(&krate.attrs, ast::CRATE_NODE_ID);
        visit::walk_crate(self, krate)
    }
}

// visits anything that could be visible to the outside world,
// e.g. documentation, pub fns, pub mods etc and checks their
// spelling.
impl<'a, 'v> visit::Visitor<'v> for SpellingVisitor<'a> {
    fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) {
        if self.exported.contains(&foreign_item.id) {
            // don't check the ident; there's nothing the user can do to
            // control the name.
            self.check_doc_attrs(&foreign_item.attrs, foreign_item.id);
        }
    }

    fn visit_item(&mut self, item: &ast::Item) {
        let is_impl = match item.node {
            ast::ItemImpl(..) => true,
            _ => false
        };
        let is_exported = self.exported.contains(&item.id);

        // checking names in impl headers is pointless: they're declared elsewhere.
        if is_exported && !is_impl {
            self.check_ident(item.ident, Position::new(item.span, item.id));
        }
        if is_exported {
            self.check_doc_attrs(&item.attrs, item.id);
        }

        match item.node {
            // no visitor method for enum variants so have to do it by
            // hand. This is probably (subtly or otherwise) incorrect
            // wrt to visibility.
            ast::ItemEnum(ref ed, _) => {
                for var in ed.variants.iter() {
                    if self.exported.contains(&var.node.id) {
                        self.check_ident(var.node.name, Position::new(var.span, var.node.id));
                        self.check_doc_attrs(&var.node.attrs, var.node.id);
                    }
                }
            }
            ast::ItemMod(..) | ast::ItemForeignMod(..) | ast::ItemStruct(..) => {
                visit::walk_item(self, item)
            }
            // impl Type { ... }
            ast::ItemImpl(_, _, _, ref trait_, _, ref items) => {
                let is_trait = trait_.is_some();
                for item in items.iter() {
                    self.check_doc_attrs(&item.attrs, item.id);
                    if !is_trait {
                        // name comes from the trait
                        self.check_ident(item.ident, Position::new(item.span, item.id));
                    }
                }
            }
            ast::ItemTrait(..) if item.vis == ast::Public => {
                visit::walk_item(self, item)
            }
            _ => {}
        }
    }

    fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
        self.check_doc_attrs(&trait_item.attrs, trait_item.id);
        self.check_ident(trait_item.ident, Position::new(trait_item.span, trait_item.id));
    }

    fn visit_struct_def(&mut self,
                        struct_definition: &ast::StructDef,
                        _identifier: ast::Ident,
                        _generics: &ast::Generics,
                        _node_id: ast::NodeId) {
        visit::walk_struct_def(self,
                               struct_definition)
    }
    fn visit_struct_field(&mut self, struct_field: &ast::StructField) {
        match struct_field.node.kind {
            ast::NamedField(ident, vis) => {
                match vis {
                    ast::Public => {
                        self.check_ident(ident,
                                         Position::new(struct_field.span, struct_field.node.id));
                        self.check_doc_attrs(&struct_field.node.attrs,
                                             struct_field.node.id);
                    }
                    ast::Inherited => {}
                }
            }
            ast::UnnamedField(_) => {}
        }

        // no need to recur; nothing below this level to check.
    }

    /// we're only interested in top-level things, so we can just
    /// ignore these entirely.
    fn visit_local(&mut self, _local: &ast::Local) {}
    fn visit_block(&mut self, _block: &ast::Block) {}
    fn visit_stmt(&mut self, _statement: &ast::Stmt) {}
    fn visit_arm(&mut self, _arm: &ast::Arm) {}
    fn visit_pat(&mut self, _pattern: &ast::Pat) {}
    fn visit_decl(&mut self, _declaration: &ast::Decl) {}
    fn visit_expr(&mut self, _expression: &ast::Expr) {}
    fn visit_expr_post(&mut self, _expression: &ast::Expr) {}
    fn visit_ty(&mut self, _typ: &ast::Ty) {}
    fn visit_generics(&mut self, _generics: &ast::Generics) {}
    fn visit_fn(&mut self,
                _function_kind: visit::FnKind,
                _function_declaration: &ast::FnDecl,
                _block: &ast::Block,
                _span: Span,
                _node_id: ast::NodeId) {}
}
<commit_msg>Fix inverted condition that caused a_b to be considered correct.<commit_after>use std::collections::{BTreeMap, HashSet};
use std::ascii::AsciiExt;
use std::cmp::Ordering;

use syntax::{ast, visit};
use syntax::parse::token;
use syntax::codemap::{Span, BytePos};
use syntax::attr::AttrMetaMethods;
use syntax::ast::NodeId;

use rustc::middle::privacy::ExportedItems;

use words;
use stem;

#[derive(Copy)]
pub struct Position {
    pub span: Span,
    pub id: NodeId,
}

impl Position {
    fn new(sp: Span, id: NodeId) -> Position {
        Position { span: sp, id: id, }
    }
}

impl PartialEq for Position {
    fn eq(&self, other: &Position) -> bool {
        self.cmp(other) == Ordering::Equal
    }
}
impl Eq for Position {}
impl PartialOrd for Position {
    fn partial_cmp(&self, other: &Position) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}
impl Ord for Position {
    fn cmp(&self, other: &Position) -> Ordering {
        let Span { lo: BytePos(slo), hi: BytePos(shi), .. } = self.span;
        let Span { lo: BytePos(olo), hi: BytePos(ohi), .. } = other.span;
        // order by span, and then by ID.
        (slo, shi, self.id).cmp(&(olo, ohi, other.id))
    }
}

/// Keeps track of the reference dictionary and the misspelled words
/// through a traversal of the whole ast.
pub struct SpellingVisitor<'a> {
    /// The reference dictionary.
    words: &'a HashSet<String>,

    /// The truly exported items.
    exported: &'a ExportedItems,

    /// The misspelled words
    pub misspellings: BTreeMap<Position, Vec<String>>,

    /// Whether the traversal should only check documentation, not
    /// idents; gets controlled internally, e.g. for `extern` blocks.
    doc_only: bool
}

impl<'a> SpellingVisitor<'a> {
    /// ast::Create a new Spelling Visitor.
    pub fn new<'b>(words: &'b HashSet<String>,
                   exported: &'b ExportedItems) -> SpellingVisitor<'b> {
        SpellingVisitor {
            words: words,
            exported: exported,
            misspellings: BTreeMap::new(),
            doc_only: false
        }
    }

    /// Checks if the given string is a correct "word", without
    /// splitting it at all. Any word that isn't entirely alphabetic
    /// is automatically considered a proper word.
    fn raw_word_is_correct(&mut self, w: &str) -> bool {
        self.words.contains(w) ||
            (w.chars().all(|c| c.is_alphabetic()) && {
                let lower = w.to_ascii_lowercase();
                self.words.contains(&lower) ||
                self.stemmed_word_is_correct(&lower)
            })
    }

    fn stemmed_word_is_correct(&self, w: &str) -> bool {
        stem::get(w).ok().map_or(false, |s| self.words.contains(&s))
    }

    /// Check a word for correctness, including splitting `foo_bar`
    /// and `FooBar` into `foo` & `bar` and `Foo` & `Bar`
    /// respectively. This inserts any incorrect word(s) into the
    /// misspelling map.
    fn check_subwords(&mut self, w: &str, pos: Position) {
        for w in words::subwords(w) {
            if !self.raw_word_is_correct(w) {
                let w = w.to_string();
                self.misspellings.entry(pos).get().unwrap_or_else(|v| v.insert(vec![])).push(w);
            }
        }
    }

    /// Check a single ident for misspellings; possibly separating it
    /// into subwords.
    fn check_ident(&mut self, ident: ast::Ident, pos: Position) {
        if self.doc_only { return }

        // spooky action at a distance; extracts the string
        // representation from TLS.
        let word = token::get_ident(ident);
        // secret rust internals, e.g. __std_macros
        if word.starts_with("__") { return }

        // the ident itself is correct, so shortcircuit to avoid doing
        // any of the submatching done below.
        if self.raw_word_is_correct(&word) {
            return
        }

        self.check_subwords(&word, pos);
    }

    /// Check the #[doc="..."] (and the commment forms) attributes for
    /// spelling.
    fn check_doc_attrs(&mut self, attrs: &[ast::Attribute], id: NodeId) {
        for attr in attrs.iter() {
            if attr.check_name("doc") {
                match attr.value_str() {
                    Some(s) => self.check_subwords(&s, Position::new(attr.span, id)),
                    None => {}
                }
            }
        }
    }

    /// Spell-check a whole krate.
    pub fn check_crate(&mut self, krate: &ast::Crate) {
        self.check_doc_attrs(&krate.attrs, ast::CRATE_NODE_ID);
        visit::walk_crate(self, krate)
    }
}

// visits anything that could be visible to the outside world,
// e.g. documentation, pub fns, pub mods etc and checks their
// spelling.
impl<'a, 'v> visit::Visitor<'v> for SpellingVisitor<'a> {
    fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) {
        if self.exported.contains(&foreign_item.id) {
            // don't check the ident; there's nothing the user can do to
            // control the name.
            self.check_doc_attrs(&foreign_item.attrs, foreign_item.id);
        }
    }

    fn visit_item(&mut self, item: &ast::Item) {
        let is_impl = match item.node {
            ast::ItemImpl(..) => true,
            _ => false
        };
        let is_exported = self.exported.contains(&item.id);

        // checking names in impl headers is pointless: they're declared elsewhere.
        if is_exported && !is_impl {
            self.check_ident(item.ident, Position::new(item.span, item.id));
        }
        if is_exported {
            self.check_doc_attrs(&item.attrs, item.id);
        }

        match item.node {
            // no visitor method for enum variants so have to do it by
            // hand. This is probably (subtly or otherwise) incorrect
            // wrt to visibility.
            ast::ItemEnum(ref ed, _) => {
                for var in ed.variants.iter() {
                    if self.exported.contains(&var.node.id) {
                        self.check_ident(var.node.name, Position::new(var.span, var.node.id));
                        self.check_doc_attrs(&var.node.attrs, var.node.id);
                    }
                }
            }
            ast::ItemMod(..) | ast::ItemForeignMod(..) | ast::ItemStruct(..) => {
                visit::walk_item(self, item)
            }
            // impl Type { ... }
            ast::ItemImpl(_, _, _, ref trait_, _, ref items) => {
                let is_trait = trait_.is_some();
                for item in items.iter() {
                    self.check_doc_attrs(&item.attrs, item.id);
                    if !is_trait {
                        // name comes from the trait
                        self.check_ident(item.ident, Position::new(item.span, item.id));
                    }
                }
            }
            ast::ItemTrait(..) if item.vis == ast::Public => {
                visit::walk_item(self, item)
            }
            _ => {}
        }
    }

    fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
        self.check_doc_attrs(&trait_item.attrs, trait_item.id);
        self.check_ident(trait_item.ident, Position::new(trait_item.span, trait_item.id));
    }

    fn visit_struct_def(&mut self,
                        struct_definition: &ast::StructDef,
                        _identifier: ast::Ident,
                        _generics: &ast::Generics,
                        _node_id: ast::NodeId) {
        visit::walk_struct_def(self,
                               struct_definition)
    }
    fn visit_struct_field(&mut self, struct_field: &ast::StructField) {
        match struct_field.node.kind {
            ast::NamedField(ident, vis) => {
                match vis {
                    ast::Public => {
                        self.check_ident(ident,
                                         Position::new(struct_field.span, struct_field.node.id));
                        self.check_doc_attrs(&struct_field.node.attrs,
                                             struct_field.node.id);
                    }
                    ast::Inherited => {}
                }
            }
            ast::UnnamedField(_) => {}
        }

        // no need to recur; nothing below this level to check.
    }

    /// we're only interested in top-level things, so we can just
    /// ignore these entirely.
    fn visit_local(&mut self, _local: &ast::Local) {}
    fn visit_block(&mut self, _block: &ast::Block) {}
    fn visit_stmt(&mut self, _statement: &ast::Stmt) {}
    fn visit_arm(&mut self, _arm: &ast::Arm) {}
    fn visit_pat(&mut self, _pattern: &ast::Pat) {}
    fn visit_decl(&mut self, _declaration: &ast::Decl) {}
    fn visit_expr(&mut self, _expression: &ast::Expr) {}
    fn visit_expr_post(&mut self, _expression: &ast::Expr) {}
    fn visit_ty(&mut self, _typ: &ast::Ty) {}
    fn visit_generics(&mut self, _generics: &ast::Generics) {}
    fn visit_fn(&mut self,
                _function_kind: visit::FnKind,
                _function_declaration: &ast::FnDecl,
                _block: &ast::Block,
                _span: Span,
                _node_id: ast::NodeId) {}
}
<|endoftext|>


<commit_before>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Support for discrete probability distributions in terms of cumulative distribution
//! functions (CDF).

use std::f64;
use std::iter;
use std::slice;
use std::ops::Range;

use itertools::Itertools;
use ordered_float::OrderedFloat;

use stats::LogProb;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entry<T: Ord> {
    pub value: T,
    pub prob: LogProb,
}

impl<T: Ord> Entry<T> {
    pub fn new(value: T, prob: LogProb) -> Self {
        Entry {
            value: value,
            prob: prob,
        }
    }
}

/// Implementation of a cumulative distribution function.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CDF<T: Ord> {
    inner: Vec<Entry<T>>,
}

impl<T: Ord> CDF<T> {
    /// Create CDF from given probability mass function (PMF). The PMF may contain duplicate values
    /// the probabilities of which are summed during generation of the CDF.
    ///
    /// # Arguments
    ///
    /// * `pmf` - the PMF as a vector of `Entry` objects
    pub fn from_pmf(mut entries: Vec<Entry<T>>) -> Self {
        entries.sort_by(|a, b| a.value.cmp(&b.value));
        let mut inner: Vec<Entry<T>> = Vec::new();
        for mut e in entries {
            let p = inner
                .last()
                .map_or(LogProb::ln_zero(), |e| e.prob)
                .ln_add_exp(e.prob);
            if !inner.is_empty() && inner.last().unwrap().value == e.value {
                inner.last_mut().unwrap().prob = p;
            } else {
                e.prob = p;
                inner.push(e);
            }
        }
        let mut cdf = CDF { inner: inner };

        if relative_eq!(*cdf.total_prob(), *LogProb::ln_one()) &&
           *cdf.total_prob() > *LogProb::ln_one() {
            cdf.inner.last_mut().unwrap().prob = LogProb::ln_one();
        }

        cdf
    }

    /// Create CDF from iterator. This can be used to replace the values of a CDF.
    pub fn from_cdf<I: Iterator<Item = Entry<T>>>(entries: I) -> Self {
        CDF { inner: entries.collect_vec() }
    }

    /// Reduce CDF by omitting values with zero probability.
    pub fn reduce(self) -> Self {
        let mut inner = Vec::new();
        let mut last = LogProb::ln_zero();
        for e in self.inner {
            if last != e.prob {
                last = e.prob;
                inner.push(e);
            }
        }
        CDF { inner: inner }
    }

    /// Downsample CDF to n entries. Panics if n <= 1 and returns identity if n is greater
    /// than the number of entries.
    pub fn sample(mut self, n: usize) -> Self {
        assert!(n > 1);
        if self.inner.len() <= n {
            self
        } else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step(s).collect_vec();
            inner.push(last);
            CDF { inner: inner }
        }
    }

    /// Provide iterator.
    pub fn iter(&self) -> slice::Iter<Entry<T>> {
        self.inner.iter()
    }

    /// Iterator over corresponding PMF.
    pub fn iter_pmf(&self) -> CDFPMFIter<T> {
        fn cdf_to_pmf<'a, G: Ord>(last_prob: &mut LogProb,
                                  e: &'a Entry<G>)
                                  -> Option<Entry<&'a G>> {
            let prob = e.prob.ln_sub_exp(*last_prob);
            *last_prob = e.prob;
            Some(Entry::new(&e.value, prob))
        }
        self.inner.iter().scan(LogProb::ln_zero(), cdf_to_pmf)
    }

    /// Get cumulative probability for a given value. If the value is not present,
    /// return the probability of the previous value. Complexity O(log n).
    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        } else {
            Some(match self.inner.binary_search_by(|e| e.value.cmp(value)) {
                     Ok(i) => self.inner[i].prob,
                     Err(i) => {
                         if i > 0 {
                             self.inner[i - 1].prob
                         } else {
                             LogProb::ln_zero()
                         }
                     }
                 })
        }
    }

    /// Get probability (i.e. probability mass) for a given value. Complexity O(log n).
    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        } else {
            Some(match self.inner.binary_search_by(|e| e.value.cmp(value)) {
                     Ok(i) => {
                         if i > 0 {
                             self.inner[i].prob.ln_sub_exp(self.inner[i - 1].prob)
                         } else {
                             self.inner[0].prob
                         }
                     }
                     Err(i) => {
                         if i > 0 {
                             self.inner[i - 1].prob
                         } else {
                             LogProb::ln_zero()
                         }
                     }
                 })
        }
    }

    /// Return total probability.
    pub fn total_prob(&self) -> LogProb {
        self.inner.last().map_or(LogProb::ln_zero(), |e| e.prob)
    }

    /// Return maximum a posteriori probability estimate (MAP).
    pub fn map(&self) -> Option<&T> {
        if let Some(mut max) = self.iter_pmf().next() {
            for e in self.iter_pmf() {
                if e.prob >= max.prob {
                    max = e;
                }
            }
            Some(max.value)
        } else {
            None
        }
    }

    /// Return w%-credible interval. The width w is a float between 0 and 1. Panics otherwise.
    /// E.g. provide `width=0.95` for the 95% credible interval.
    pub fn credible_interval(&self, width: f64) -> Range<&T> {
        assert!(width >= 0.0 && width <= 1.0);
        let margin = 1.0 - width;
        let p_lower = OrderedFloat((margin / 2.0).ln());
        let p_upper = OrderedFloat((1.0 - margin / 2.0).ln());
        let lower = self.inner
            .binary_search_by(|e| OrderedFloat(*e.prob).cmp(&p_lower))
            .unwrap_or_else(|i| i);
        let upper = self.inner
            .binary_search_by(|e| OrderedFloat(*e.prob).cmp(&p_upper))
            .unwrap_or_else(|i| i - 1);

        &self.inner[lower].value..&self.inner[upper].value
    }

    /// Number of entries in the CDF.
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }
}

impl<T: Clone + Ord> CDF<T>
    where f64: From<T>
{
    /// Calculate expected value.
    pub fn expected_value(&self) -> f64 {
        self.iter_pmf()
            .map(|e| f64::from(e.value.clone()) * e.prob.exp())
            .fold(0.0f64, |s, e| s + e)
    }

    /// Calculate variance.
    pub fn variance(&self) -> f64 {
        let ev = self.expected_value();
        self.iter_pmf()
            .map(|e| (f64::from(e.value.clone()) - ev).powi(2) * e.prob.exp())
            .fold(0.0, |s, e| s + e)
    }

    /// Calculate standard deviation.
    pub fn standard_deviation(&self) -> f64 {
        self.variance().sqrt()
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<slice::Iter<'a, Entry<T>>,
                                        LogProb,
                                        fn(&mut LogProb, &'a Entry<T>) -> Option<Entry<&'a T>>>;

#[cfg(test)]
mod test {
    use super::*;
    use stats::LogProb;
    use ordered_float::NotNaN;

    #[test]
    fn test_cdf() {
        let mut pmf = vec![Entry::new(NotNaN::new(0.0).unwrap(), LogProb(0.1f64.ln()))];
        for i in 0..9 {
            pmf.push(Entry::new(NotNaN::new(i as f64).unwrap(), LogProb(0.1f64.ln())));
        }
        println!("{:?}", pmf);

        let cdf = CDF::from_pmf(pmf.clone());
        println!("{:?}", cdf);
        for e in pmf.iter().skip(2) {
            assert_ulps_eq!(*e.prob,
                            *cdf.get_pmf(&e.value).unwrap(),
                            epsilon = 0.0000000000001);
        }
        assert_relative_eq!(*cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(*cdf.get(&NotNaN::new(1.0).unwrap()).unwrap(),
                            0.3f64.ln(),
                            epsilon = 0.00000001);
        let ci = cdf.credible_interval(0.95);
        assert_relative_eq!(**ci.start, 0.0);
        assert_relative_eq!(**ci.end, 7.0);
    }
}
<commit_msg>Test CDF sampling.<commit_after>// Copyright 2016 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

//! Support for discrete probability distributions in terms of cumulative distribution
//! functions (CDF).

use std::f64;
use std::iter;
use std::slice;
use std::ops::Range;

use itertools::Itertools;
use ordered_float::OrderedFloat;

use stats::LogProb;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Entry<T: Ord> {
    pub value: T,
    pub prob: LogProb,
}

impl<T: Ord> Entry<T> {
    pub fn new(value: T, prob: LogProb) -> Self {
        Entry {
            value: value,
            prob: prob,
        }
    }
}

/// Implementation of a cumulative distribution function.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CDF<T: Ord> {
    inner: Vec<Entry<T>>,
}

impl<T: Ord> CDF<T> {
    /// Create CDF from given probability mass function (PMF). The PMF may contain duplicate values
    /// the probabilities of which are summed during generation of the CDF.
    ///
    /// # Arguments
    ///
    /// * `pmf` - the PMF as a vector of `Entry` objects
    pub fn from_pmf(mut entries: Vec<Entry<T>>) -> Self {
        entries.sort_by(|a, b| a.value.cmp(&b.value));
        let mut inner: Vec<Entry<T>> = Vec::new();
        for mut e in entries {
            let p = inner
                .last()
                .map_or(LogProb::ln_zero(), |e| e.prob)
                .ln_add_exp(e.prob);
            if !inner.is_empty() && inner.last().unwrap().value == e.value {
                inner.last_mut().unwrap().prob = p;
            } else {
                e.prob = p;
                inner.push(e);
            }
        }
        let mut cdf = CDF { inner: inner };

        if relative_eq!(*cdf.total_prob(), *LogProb::ln_one()) &&
           *cdf.total_prob() > *LogProb::ln_one() {
            cdf.inner.last_mut().unwrap().prob = LogProb::ln_one();
        }

        cdf
    }

    /// Create CDF from iterator. This can be used to replace the values of a CDF.
    pub fn from_cdf<I: Iterator<Item = Entry<T>>>(entries: I) -> Self {
        CDF { inner: entries.collect_vec() }
    }

    /// Reduce CDF by omitting values with zero probability.
    pub fn reduce(self) -> Self {
        let mut inner = Vec::new();
        let mut last = LogProb::ln_zero();
        for e in self.inner {
            if last != e.prob {
                last = e.prob;
                inner.push(e);
            }
        }
        CDF { inner: inner }
    }

    /// Downsample CDF to n entries. Panics if n <= 1 and returns identity if n is greater
    /// than the number of entries.
    pub fn sample(mut self, n: usize) -> Self {
        assert!(n > 1);
        if self.inner.len() <= n {
            self
        } else {
            let s = self.inner.len() / (n - 1);
            let last = self.inner.pop().unwrap();
            let mut inner = self.inner.into_iter().step(s).collect_vec();
            inner.push(last);
            CDF { inner: inner }
        }
    }

    /// Provide iterator.
    pub fn iter(&self) -> slice::Iter<Entry<T>> {
        self.inner.iter()
    }

    /// Iterator over corresponding PMF.
    pub fn iter_pmf(&self) -> CDFPMFIter<T> {
        fn cdf_to_pmf<'a, G: Ord>(last_prob: &mut LogProb,
                                  e: &'a Entry<G>)
                                  -> Option<Entry<&'a G>> {
            let prob = e.prob.ln_sub_exp(*last_prob);
            *last_prob = e.prob;
            Some(Entry::new(&e.value, prob))
        }
        self.inner.iter().scan(LogProb::ln_zero(), cdf_to_pmf)
    }

    /// Get cumulative probability for a given value. If the value is not present,
    /// return the probability of the previous value. Complexity O(log n).
    pub fn get(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        } else {
            Some(match self.inner.binary_search_by(|e| e.value.cmp(value)) {
                     Ok(i) => self.inner[i].prob,
                     Err(i) => {
                         if i > 0 {
                             self.inner[i - 1].prob
                         } else {
                             LogProb::ln_zero()
                         }
                     }
                 })
        }
    }

    /// Get probability (i.e. probability mass) for a given value. Complexity O(log n).
    pub fn get_pmf(&self, value: &T) -> Option<LogProb> {
        if self.inner.is_empty() {
            None
        } else {
            Some(match self.inner.binary_search_by(|e| e.value.cmp(value)) {
                     Ok(i) => {
                         if i > 0 {
                             self.inner[i].prob.ln_sub_exp(self.inner[i - 1].prob)
                         } else {
                             self.inner[0].prob
                         }
                     }
                     Err(i) => {
                         if i > 0 {
                             self.inner[i - 1].prob
                         } else {
                             LogProb::ln_zero()
                         }
                     }
                 })
        }
    }

    /// Return total probability.
    pub fn total_prob(&self) -> LogProb {
        self.inner.last().map_or(LogProb::ln_zero(), |e| e.prob)
    }

    /// Return maximum a posteriori probability estimate (MAP).
    pub fn map(&self) -> Option<&T> {
        if let Some(mut max) = self.iter_pmf().next() {
            for e in self.iter_pmf() {
                if e.prob >= max.prob {
                    max = e;
                }
            }
            Some(max.value)
        } else {
            None
        }
    }

    /// Return w%-credible interval. The width w is a float between 0 and 1. Panics otherwise.
    /// E.g. provide `width=0.95` for the 95% credible interval.
    pub fn credible_interval(&self, width: f64) -> Range<&T> {
        assert!(width >= 0.0 && width <= 1.0);
        let margin = 1.0 - width;
        let p_lower = OrderedFloat((margin / 2.0).ln());
        let p_upper = OrderedFloat((1.0 - margin / 2.0).ln());
        let lower = self.inner
            .binary_search_by(|e| OrderedFloat(*e.prob).cmp(&p_lower))
            .unwrap_or_else(|i| i);
        let upper = self.inner
            .binary_search_by(|e| OrderedFloat(*e.prob).cmp(&p_upper))
            .unwrap_or_else(|i| i - 1);

        &self.inner[lower].value..&self.inner[upper].value
    }

    /// Number of entries in the CDF.
    pub fn len(&self) -> usize {
        self.inner.len()
    }

    pub fn is_empty(&self) -> bool {
        self.inner.is_empty()
    }
}

impl<T: Clone + Ord> CDF<T>
    where f64: From<T>
{
    /// Calculate expected value.
    pub fn expected_value(&self) -> f64 {
        self.iter_pmf()
            .map(|e| f64::from(e.value.clone()) * e.prob.exp())
            .fold(0.0f64, |s, e| s + e)
    }

    /// Calculate variance.
    pub fn variance(&self) -> f64 {
        let ev = self.expected_value();
        self.iter_pmf()
            .map(|e| (f64::from(e.value.clone()) - ev).powi(2) * e.prob.exp())
            .fold(0.0, |s, e| s + e)
    }

    /// Calculate standard deviation.
    pub fn standard_deviation(&self) -> f64 {
        self.variance().sqrt()
    }
}

pub type CDFPMFIter<'a, T> = iter::Scan<slice::Iter<'a, Entry<T>>,
                                        LogProb,
                                        fn(&mut LogProb, &'a Entry<T>) -> Option<Entry<&'a T>>>;

#[cfg(test)]
mod test {
    use super::*;
    use stats::LogProb;
    use ordered_float::NotNaN;

    #[test]
    fn test_cdf() {
        let mut pmf = vec![Entry::new(NotNaN::new(0.0).unwrap(), LogProb(0.1f64.ln()))];
        for i in 0..9 {
            pmf.push(Entry::new(NotNaN::new(i as f64).unwrap(), LogProb(0.1f64.ln())));
        }
        println!("{:?}", pmf);

        let cdf = CDF::from_pmf(pmf.clone());
        println!("{:?}", cdf);
        for e in pmf.iter().skip(2) {
            assert_ulps_eq!(*e.prob,
                            *cdf.get_pmf(&e.value).unwrap(),
                            epsilon = 0.0000000000001);
        }
        assert_relative_eq!(*cdf.total_prob(), 1.0f64.ln());
        assert_relative_eq!(*cdf.get(&NotNaN::new(1.0).unwrap()).unwrap(),
                            0.3f64.ln(),
                            epsilon = 0.00000001);
        {
            let ci = cdf.credible_interval(0.95);
            assert_relative_eq!(**ci.start, 0.0);
            assert_relative_eq!(**ci.end, 7.0);
        }

        assert_relative_eq!(cdf.sample(5).total_prob().exp(), 1.0);
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2016-2019 Fabian Schuiki

//! An implementation of the visitor pattern for the HIR.
//!
//! This module defines the [`Visitor`] trait that allows the HIR tree graph to
//! be visited.

use super::{nodes::*, HirNode};
use crate::{
    common::{name::Name, source::Spanned, NodeId},
    Context,
};

/// A visitor of the HIR.
pub trait Visitor<'a>: Sized {
    /// The type of context that this visitor uses.
    type Context: Context<'a>;

    /// Get the context to be used to resolve queries.
    fn context(&self) -> &Self::Context;

    fn visit_node_with_id(&mut self, node_id: NodeId, lvalue: bool) {
        match self.context().hir_of(node_id) {
            Ok(x) => self.visit_node(x, lvalue),
            Err(()) => (),
        }
    }

    fn visit_node(&mut self, node: HirNode<'a>, lvalue: bool) {
        match node {
            HirNode::Proc(x) => self.visit_proc(x),
            HirNode::Stmt(x) => self.visit_stmt(x),
            HirNode::Expr(x) => self.visit_expr(x, lvalue),
            HirNode::EventExpr(x) => self.visit_event_expr(x),
            HirNode::Typedef(x) => self.visit_typedef(x),
            _ => (),
        }
    }

    fn visit_ident(&mut self, _ident: Spanned<Name>) {}
    fn visit_unary_op(&mut self, _op: UnaryOp) {}
    fn visit_binary_op(&mut self, _op: BinaryOp) {}

    fn visit_proc(&mut self, prok: &'a Proc) {
        walk_proc(self, prok)
    }

    fn visit_stmt(&mut self, stmt: &'a Stmt) {
        walk_stmt(self, stmt)
    }

    fn visit_expr(&mut self, expr: &'a Expr, lvalue: bool) {
        walk_expr(self, expr, lvalue);
    }

    fn visit_timing_control(&mut self, ctrl: &'a TimingControl) {
        walk_timing_control(self, ctrl);
    }

    fn visit_event_expr(&mut self, expr: &'a EventExpr) {
        walk_event_expr(self, expr);
    }

    fn visit_event(&mut self, event: &'a Event) {
        walk_event(self, event);
    }

    fn visit_typedef(&mut self, typedef: &'a Typedef) {
        walk_typedef(self, typedef);
    }
}

/// Walk the contents of a procedure.
pub fn walk_proc<'a>(visitor: &mut impl Visitor<'a>, prok: &'a Proc) {
    visitor.visit_node_with_id(prok.stmt, false);
}

/// Walk the contents of a statement.
pub fn walk_stmt<'a>(visitor: &mut impl Visitor<'a>, stmt: &'a Stmt) {
    #[allow(unreachable_patterns)]
    match stmt.kind {
        StmtKind::Null => (),
        StmtKind::Block(ref stmts) => {
            for &id in stmts {
                visitor.visit_node_with_id(id, false);
            }
        }
        StmtKind::Assign { lhs, rhs, .. } => {
            visitor.visit_node_with_id(lhs, true);
            visitor.visit_node_with_id(rhs, false);
        }
        StmtKind::Timed { ref control, stmt } => {
            visitor.visit_timing_control(control);
            visitor.visit_node_with_id(stmt, false);
        }
        StmtKind::Expr(expr) => visitor.visit_node_with_id(expr, false),
        StmtKind::If {
            cond,
            main_stmt,
            else_stmt,
        } => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(main_stmt, false);
            if let Some(else_stmt) = else_stmt {
                visitor.visit_node_with_id(else_stmt, false);
            }
        }
        StmtKind::Loop { kind, body } => {
            match kind {
                LoopKind::Forever => (),
                LoopKind::Repeat(id) | LoopKind::While(id) | LoopKind::Do(id) => {
                    visitor.visit_node_with_id(id, false);
                }
                LoopKind::For(init, cond, step) => {
                    visitor.visit_node_with_id(init, false);
                    visitor.visit_node_with_id(cond, false);
                    visitor.visit_node_with_id(step, false);
                }
            }
            visitor.visit_node_with_id(body, false);
        }
        StmtKind::InlineGroup { ref stmts, .. } => {
            for &stmt in stmts {
                visitor.visit_node_with_id(stmt, false);
            }
        }
    }
}

/// Walk the contents of an expression.
pub fn walk_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a Expr, lvalue: bool) {
    match expr.kind {
        ExprKind::IntConst(..) | ExprKind::UnsizedConst(_) | ExprKind::TimeConst(_) => (),
        ExprKind::Ident(x) => {
            visitor.visit_ident(x);
        }
        ExprKind::Unary(op, arg) => {
            visitor.visit_unary_op(op);
            visitor.visit_node_with_id(arg, lvalue);
        }
        ExprKind::Binary(op, lhs, rhs) => {
            visitor.visit_binary_op(op);
            visitor.visit_node_with_id(lhs, lvalue);
            visitor.visit_node_with_id(rhs, lvalue);
        }
        ExprKind::Field(expr, _) => {
            visitor.visit_node_with_id(expr, lvalue);
        }
        ExprKind::Index(expr, mode) => {
            visitor.visit_node_with_id(expr, lvalue);
            match mode {
                IndexMode::One(expr) => visitor.visit_node_with_id(expr, false),
                IndexMode::Many(_, lhs, rhs) => {
                    visitor.visit_node_with_id(lhs, false);
                    visitor.visit_node_with_id(rhs, false);
                }
            }
        }
        ExprKind::Builtin(BuiltinCall::Clog2(arg)) => {
            visitor.visit_node_with_id(arg, false);
        }
        ExprKind::Ternary(cond, true_expr, false_expr) => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(true_expr, lvalue);
            visitor.visit_node_with_id(false_expr, lvalue);
        }
    }
}

/// Walk the contents of a timing control block.
pub fn walk_timing_control<'a>(visitor: &mut impl Visitor<'a>, ctrl: &'a TimingControl) {
    match *ctrl {
        TimingControl::Delay(id) => visitor.visit_node_with_id(id, false),
        TimingControl::ImplicitEvent => (),
        TimingControl::ExplicitEvent(id) => visitor.visit_node_with_id(id, false),
    }
}

/// Walk the contents of an event expression.
pub fn walk_event_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a EventExpr) {
    for event in &expr.events {
        visitor.visit_event(event);
    }
}

/// Walk the contents of an event.
pub fn walk_event<'a>(visitor: &mut impl Visitor<'a>, event: &'a Event) {
    visitor.visit_node_with_id(event.expr, false);
    for &iff in &event.iff {
        visitor.visit_node_with_id(iff, false);
    }
}

/// Walk the contents of a typedef.
pub fn walk_typedef<'a>(visitor: &mut impl Visitor<'a>, typedef: &'a Typedef) {
    visitor.visit_node_with_id(typedef.ty, false);
}
<commit_msg>hir: fix var decl visit<commit_after>// Copyright (c) 2016-2019 Fabian Schuiki

//! An implementation of the visitor pattern for the HIR.
//!
//! This module defines the [`Visitor`] trait that allows the HIR tree graph to
//! be visited.

use super::{nodes::*, HirNode};
use crate::{
    common::{name::Name, source::Spanned, NodeId},
    Context,
};

/// A visitor of the HIR.
pub trait Visitor<'a>: Sized {
    /// The type of context that this visitor uses.
    type Context: Context<'a>;

    /// Get the context to be used to resolve queries.
    fn context(&self) -> &Self::Context;

    fn visit_node_with_id(&mut self, node_id: NodeId, lvalue: bool) {
        match self.context().hir_of(node_id) {
            Ok(x) => self.visit_node(x, lvalue),
            Err(()) => (),
        }
    }

    fn visit_node(&mut self, node: HirNode<'a>, lvalue: bool) {
        match node {
            HirNode::Proc(x) => self.visit_proc(x),
            HirNode::Stmt(x) => self.visit_stmt(x),
            HirNode::Expr(x) => self.visit_expr(x, lvalue),
            HirNode::EventExpr(x) => self.visit_event_expr(x),
            HirNode::Typedef(x) => self.visit_typedef(x),
            HirNode::VarDecl(x) => self.visit_var_decl(x),
            _ => (),
        }
    }

    fn visit_ident(&mut self, _ident: Spanned<Name>) {}
    fn visit_unary_op(&mut self, _op: UnaryOp) {}
    fn visit_binary_op(&mut self, _op: BinaryOp) {}

    fn visit_proc(&mut self, prok: &'a Proc) {
        walk_proc(self, prok)
    }

    fn visit_stmt(&mut self, stmt: &'a Stmt) {
        walk_stmt(self, stmt)
    }

    fn visit_expr(&mut self, expr: &'a Expr, lvalue: bool) {
        walk_expr(self, expr, lvalue);
    }

    fn visit_timing_control(&mut self, ctrl: &'a TimingControl) {
        walk_timing_control(self, ctrl);
    }

    fn visit_event_expr(&mut self, expr: &'a EventExpr) {
        walk_event_expr(self, expr);
    }

    fn visit_event(&mut self, event: &'a Event) {
        walk_event(self, event);
    }

    fn visit_typedef(&mut self, typedef: &'a Typedef) {
        walk_typedef(self, typedef);
    }

    fn visit_var_decl(&mut self, decl: &'a VarDecl) {
        walk_var_decl(self, decl);
    }
}

/// Walk the contents of a procedure.
pub fn walk_proc<'a>(visitor: &mut impl Visitor<'a>, prok: &'a Proc) {
    visitor.visit_node_with_id(prok.stmt, false);
}

/// Walk the contents of a statement.
pub fn walk_stmt<'a>(visitor: &mut impl Visitor<'a>, stmt: &'a Stmt) {
    #[allow(unreachable_patterns)]
    match stmt.kind {
        StmtKind::Null => (),
        StmtKind::Block(ref stmts) => {
            for &id in stmts {
                visitor.visit_node_with_id(id, false);
            }
        }
        StmtKind::Assign { lhs, rhs, .. } => {
            visitor.visit_node_with_id(lhs, true);
            visitor.visit_node_with_id(rhs, false);
        }
        StmtKind::Timed { ref control, stmt } => {
            visitor.visit_timing_control(control);
            visitor.visit_node_with_id(stmt, false);
        }
        StmtKind::Expr(expr) => visitor.visit_node_with_id(expr, false),
        StmtKind::If {
            cond,
            main_stmt,
            else_stmt,
        } => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(main_stmt, false);
            if let Some(else_stmt) = else_stmt {
                visitor.visit_node_with_id(else_stmt, false);
            }
        }
        StmtKind::Loop { kind, body } => {
            match kind {
                LoopKind::Forever => (),
                LoopKind::Repeat(id) | LoopKind::While(id) | LoopKind::Do(id) => {
                    visitor.visit_node_with_id(id, false);
                }
                LoopKind::For(init, cond, step) => {
                    visitor.visit_node_with_id(init, false);
                    visitor.visit_node_with_id(cond, false);
                    visitor.visit_node_with_id(step, false);
                }
            }
            visitor.visit_node_with_id(body, false);
        }
        StmtKind::InlineGroup { ref stmts, .. } => {
            for &stmt in stmts {
                visitor.visit_node_with_id(stmt, false);
            }
        }
    }
}

/// Walk the contents of an expression.
pub fn walk_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a Expr, lvalue: bool) {
    match expr.kind {
        ExprKind::IntConst(..) | ExprKind::UnsizedConst(_) | ExprKind::TimeConst(_) => (),
        ExprKind::Ident(x) => {
            visitor.visit_ident(x);
        }
        ExprKind::Unary(op, arg) => {
            visitor.visit_unary_op(op);
            visitor.visit_node_with_id(arg, lvalue);
        }
        ExprKind::Binary(op, lhs, rhs) => {
            visitor.visit_binary_op(op);
            visitor.visit_node_with_id(lhs, lvalue);
            visitor.visit_node_with_id(rhs, lvalue);
        }
        ExprKind::Field(expr, _) => {
            visitor.visit_node_with_id(expr, lvalue);
        }
        ExprKind::Index(expr, mode) => {
            visitor.visit_node_with_id(expr, lvalue);
            match mode {
                IndexMode::One(expr) => visitor.visit_node_with_id(expr, false),
                IndexMode::Many(_, lhs, rhs) => {
                    visitor.visit_node_with_id(lhs, false);
                    visitor.visit_node_with_id(rhs, false);
                }
            }
        }
        ExprKind::Builtin(BuiltinCall::Clog2(arg)) => {
            visitor.visit_node_with_id(arg, false);
        }
        ExprKind::Ternary(cond, true_expr, false_expr) => {
            visitor.visit_node_with_id(cond, false);
            visitor.visit_node_with_id(true_expr, lvalue);
            visitor.visit_node_with_id(false_expr, lvalue);
        }
    }
}

/// Walk the contents of a timing control block.
pub fn walk_timing_control<'a>(visitor: &mut impl Visitor<'a>, ctrl: &'a TimingControl) {
    match *ctrl {
        TimingControl::Delay(id) => visitor.visit_node_with_id(id, false),
        TimingControl::ImplicitEvent => (),
        TimingControl::ExplicitEvent(id) => visitor.visit_node_with_id(id, false),
    }
}

/// Walk the contents of an event expression.
pub fn walk_event_expr<'a>(visitor: &mut impl Visitor<'a>, expr: &'a EventExpr) {
    for event in &expr.events {
        visitor.visit_event(event);
    }
}

/// Walk the contents of an event.
pub fn walk_event<'a>(visitor: &mut impl Visitor<'a>, event: &'a Event) {
    visitor.visit_node_with_id(event.expr, false);
    for &iff in &event.iff {
        visitor.visit_node_with_id(iff, false);
    }
}

/// Walk the contents of a typedef.
pub fn walk_typedef<'a>(visitor: &mut impl Visitor<'a>, typedef: &'a Typedef) {
    visitor.visit_node_with_id(typedef.ty, false);
}

/// Walk the contents of a variable declaration.
pub fn walk_var_decl<'a>(visitor: &mut impl Visitor<'a>, decl: &'a VarDecl) {
    visitor.visit_node_with_id(decl.ty, false);
    if let Some(init) = decl.init {
        visitor.visit_node_with_id(init, false);
    }
}
<|endoftext|>


<commit_before>#![warn(dead_code)]

use telebot;
use serde_json;
use futures::Future;

#[derive(Serialize)]
pub struct GetChatString {
    chat_id: String,
}

pub struct WrapperGetChatString {
    bot: telebot::RcBot,
    inner: GetChatString,
}

impl WrapperGetChatString {
    pub fn send<'a>(self) -> impl Future<Item = (telebot::RcBot, telebot::objects::Chat), Error = telebot::Error> + 'a {
        let msg = serde_json::to_string(&self.inner).unwrap();
        self.bot
            .inner
            .fetch_json("getChat", &msg)
            .map(move |x| (self.bot.clone(), serde_json::from_str::<telebot::objects::Chat>(&x).unwrap()))
    }
}

#[derive(Serialize)]
pub struct EditMessageText {
    chat_id: i64,
    message_id: i64,
    text: String,
    #[serde(skip_serializing_if="Option::is_none")]
    parse_mode: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    disable_web_page_preview: Option<bool>,
}

pub fn get_chat_string(bot: &telebot::RcBot, chat: String) -> WrapperGetChatString {
    WrapperGetChatString {
        bot: bot.clone(),
        inner: GetChatString { chat_id: chat },
    }
}

pub struct WrapperEditMessageText {
    bot: telebot::RcBot,
    inner: EditMessageText,
}

impl WrapperEditMessageText {
    pub fn send<'a>(self) -> impl Future<Item = (telebot::RcBot, telebot::objects::Message), Error = telebot::Error> + 'a {
        let msg = serde_json::to_string(&self.inner).unwrap();
        self.bot
            .inner
            .fetch_json("editMessageText", &msg)
            .map(move |x| (self.bot.clone(), serde_json::from_str::<telebot::objects::Message>(&x).unwrap()))
    }

    pub fn parse_mode<S>(mut self, val: S) -> Self
        where S: Into<String>
    {
        self.inner.parse_mode = Some(val.into());
        self
    }

    pub fn disable_web_page_preview<S>(mut self, val: S) -> Self
        where S: Into<bool>
    {
        self.inner.disable_web_page_preview = Some(val.into());
        self
    }
}

pub fn edit_message_text(bot: &telebot::RcBot, chat_id: i64, message_id: i64, text: String) -> WrapperEditMessageText {
    WrapperEditMessageText {
        bot: bot.clone(),
        inner: EditMessageText {
            chat_id: chat_id,
            message_id: message_id,
            text: text,
            parse_mode: None,
            disable_web_page_preview: None,
        },
    }
}
<commit_msg>allow dead code in tlelebot_missing.rs<commit_after>#![allow(dead_code)]

use telebot;
use serde_json;
use futures::Future;

#[derive(Serialize)]
pub struct GetChatString {
    chat_id: String,
}

pub struct WrapperGetChatString {
    bot: telebot::RcBot,
    inner: GetChatString,
}

impl WrapperGetChatString {
    pub fn send<'a>(self) -> impl Future<Item = (telebot::RcBot, telebot::objects::Chat), Error = telebot::Error> + 'a {
        let msg = serde_json::to_string(&self.inner).unwrap();
        self.bot
            .inner
            .fetch_json("getChat", &msg)
            .map(move |x| (self.bot.clone(), serde_json::from_str::<telebot::objects::Chat>(&x).unwrap()))
    }
}

#[derive(Serialize)]
pub struct EditMessageText {
    chat_id: i64,
    message_id: i64,
    text: String,
    #[serde(skip_serializing_if="Option::is_none")]
    parse_mode: Option<String>,
    #[serde(skip_serializing_if="Option::is_none")]
    disable_web_page_preview: Option<bool>,
}

pub fn get_chat_string(bot: &telebot::RcBot, chat: String) -> WrapperGetChatString {
    WrapperGetChatString {
        bot: bot.clone(),
        inner: GetChatString { chat_id: chat },
    }
}

pub struct WrapperEditMessageText {
    bot: telebot::RcBot,
    inner: EditMessageText,
}

impl WrapperEditMessageText {
    pub fn send<'a>(self) -> impl Future<Item = (telebot::RcBot, telebot::objects::Message), Error = telebot::Error> + 'a {
        let msg = serde_json::to_string(&self.inner).unwrap();
        self.bot
            .inner
            .fetch_json("editMessageText", &msg)
            .map(move |x| (self.bot.clone(), serde_json::from_str::<telebot::objects::Message>(&x).unwrap()))
    }

    pub fn parse_mode<S>(mut self, val: S) -> Self
        where S: Into<String>
    {
        self.inner.parse_mode = Some(val.into());
        self
    }

    pub fn disable_web_page_preview<S>(mut self, val: S) -> Self
        where S: Into<bool>
    {
        self.inner.disable_web_page_preview = Some(val.into());
        self
    }
}

pub fn edit_message_text(bot: &telebot::RcBot, chat_id: i64, message_id: i64, text: String) -> WrapperEditMessageText {
    WrapperEditMessageText {
        bot: bot.clone(),
        inner: EditMessageText {
            chat_id: chat_id,
            message_id: message_id,
            text: text,
            parse_mode: None,
            disable_web_page_preview: None,
        },
    }
}
<|endoftext|>


<commit_before>use shaders::TileMapData;
use data::{load_map_file, get_map_tile};
use game::constants::{MAP_FILE_PATH, TILEMAP_BUF_LENGTH, TILES_PCS_W, TILES_PCS_H};
use tiled::{Map, Tileset};

fn calc_index(xpos: usize, ypos: usize) -> usize {
  (ypos * TILES_PCS_W) + xpos
}

fn populate_tilemap(mut tiles: Vec<TileMapData>, map: &Map) -> Vec<TileMapData> {
  for ypos in 0..TILES_PCS_H {
    for xpos in 0..TILES_PCS_W {
      let map_val = get_map_tile(&map, 0, xpos, ypos);
      let tex_x = map_val % 32;
      let y = (map_val - tex_x) / 32;
      let x = if tex_x < 1 { 1 } else { tex_x - 1 };
      let idx = calc_index(xpos, ypos);
      tiles[idx] = TileMapData::new([x as f32, y as f32, 0.0, 0.0]);
    }
  }
  tiles
}

#[derive(Debug)]
pub struct Terrain {
  pub tiles: Vec<TileMapData>,
  pub tilesets: Vec<Tileset>,
}

impl Terrain {
  pub fn new() -> Terrain {
    let mut charmap_data = Vec::with_capacity(TILEMAP_BUF_LENGTH);

    for _ in 0..TILEMAP_BUF_LENGTH {
      charmap_data.push(TileMapData::new_empty());
    }

    let map = load_map_file(MAP_FILE_PATH);

    Terrain {
      tiles: populate_tilemap(charmap_data, &map),
      tilesets: map.tilesets,
    }
  }
}
<commit_msg>Remove extra reference<commit_after>use shaders::TileMapData;
use data::{load_map_file, get_map_tile};
use game::constants::{MAP_FILE_PATH, TILEMAP_BUF_LENGTH, TILES_PCS_W, TILES_PCS_H};
use tiled::{Map, Tileset};

fn calc_index(xpos: usize, ypos: usize) -> usize {
  (ypos * TILES_PCS_W) + xpos
}

fn populate_tilemap(mut tiles: Vec<TileMapData>, map: &Map) -> Vec<TileMapData> {
  for ypos in 0..TILES_PCS_H {
    for xpos in 0..TILES_PCS_W {
      let map_val = get_map_tile(map, 0, xpos, ypos);
      let tex_x = map_val % 32;
      let y = (map_val - tex_x) / 32;
      let x = if tex_x < 1 { 1 } else { tex_x - 1 };
      let idx = calc_index(xpos, ypos);
      tiles[idx] = TileMapData::new([x as f32, y as f32, 0.0, 0.0]);
    }
  }
  tiles
}

#[derive(Debug)]
pub struct Terrain {
  pub tiles: Vec<TileMapData>,
  pub tilesets: Vec<Tileset>,
}

impl Terrain {
  pub fn new() -> Terrain {
    let mut charmap_data = Vec::with_capacity(TILEMAP_BUF_LENGTH);

    for _ in 0..TILEMAP_BUF_LENGTH {
      charmap_data.push(TileMapData::new_empty());
    }

    let map = load_map_file(MAP_FILE_PATH);

    Terrain {
      tiles: populate_tilemap(charmap_data, &map),
      tilesets: map.tilesets,
    }
  }
}
<|endoftext|>