<commit_before>#![feature(plugin)]
#![plugin(clippy, docopt_macros)]

extern crate ansi_term;
extern crate docopt;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate nix;
extern crate protobuf;
extern crate record_query;
extern crate rustc_serialize;

use std::env;
use std::io;
use std::path;

use record_query as rq;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

docopt!(pub Args derive Debug, concat!("
rq - record query v", env!("CARGO_PKG_VERSION"), "

A tool for manipulating data records.

Records are read from stdin, processed, and written to stdout.  The tool accepts
a query in the custom rq query language as its main command-line arguments.

See 'man rq' for in-depth documentation.

Usage:
  rq (--help|--version)
  rq [-j|-c|-p <type>] [-J|-C|-P <type>] [-l <level>|-q] [--] [<query>]
  rq [-l <level>|-q] protobuf add <schema>

Options:
  --help
      Show this screen.
  --version
      Show the program name and version.

  -j, --input-json
      Input is white-space separated JSON values.
  -J, --output-json
      Output should be formatted as JSON values.
  -c, --input-cbor
      Input is a series of CBOR values.
  -C, --output-cbor
      Output is a series of CBOR values.
  -p <type>, --input-protobuf <type>
      Input is a single protocol buffer object.  The argument refers to the
      fully qualified name of the message type (including the leading '.').
  -P <type>, --output-protobuf <type>
      Output should be formatted as protocol buffer objects.  The argument
      refers to the fully qualified name of the message type (including the
      leading '.').

  <query>
      A query indicating how to transform each record.

  -l <level>, --log <level>
      Display log messages at and above the specified log level.  The value can
      be one of 'off', 'error', 'warn', 'info', 'debug' or 'trace'.
  -q, --quiet
      Log nothing (alias for '-v off').
"));

fn main() {
    use std::io::Read;

    let args: Args = Args::docopt()
        .version(Some(VERSION.to_owned()))
        .decode().unwrap_or_else(|e| e.exit());

    setup_log(&args.flag_log, args.flag_quiet);

    let paths = rq::config::Paths::new().unwrap();

    if args.cmd_protobuf {
        if args.cmd_add {
            let schema = path::Path::new(&args.arg_schema);
            rq::proto_index::add_file(&paths, schema).unwrap();
        }
    } else {
        let query = rq::query::Query::parse(&args.arg_query);

        let stdin = io::stdin();
        let mut input = stdin.lock();

        if !args.flag_input_protobuf.is_empty() {
            let name = args.flag_input_protobuf;
            debug!("Input is protobuf with argument {}", name);

            let descriptors_proto = rq::proto_index::compile_descriptor_set(&paths).unwrap();
            let descriptors =
                rq::value::protobuf::descriptor::Descriptors::from_protobuf(&descriptors_proto);
            let stream = protobuf::CodedInputStream::new(&mut input);
            let values = rq::value::protobuf::ProtobufValues::new(descriptors,
                                                                  name.to_owned(),
                                                                  stream);
            run(values, query).unwrap_or_else(|e| error!("{:?}", e));
        } else if args.flag_input_cbor {
            run(rq::value::cbor::CborValues::new(input), query)
                .unwrap_or_else(|e| error!("{:?}", e));
        } else {
            run(rq::value::json::JsonValues::new(input.bytes()), query)
                .unwrap_or_else(|e| error!("{:?}", e));
        }
    }
}

fn setup_log(level: &str, quiet: bool) {
    use std::str::FromStr;
    use ansi_term::ANSIStrings;
    use ansi_term::Colour;
    use ansi_term::Style;
    use log::LogLevel;
    use log::LogLevelFilter;
    use nix::unistd;
    use nix::sys::ioctl;

    let normal = Style::new();

    let format = move |record: &log::LogRecord| {
        if unistd::isatty(ioctl::libc::STDERR_FILENO).unwrap_or(false) {
            let (front, back) = match record.level() {
                LogLevel::Error => (Colour::Red.normal(), Colour::Red.dimmed()),
                LogLevel::Warn => (Colour::Yellow.normal(), Colour::Yellow.dimmed()),
                LogLevel::Info => (Colour::Blue.normal(), Colour::Blue.dimmed()),
                LogLevel::Debug => (Colour::Purple.normal(), Colour::Purple.dimmed()),
                LogLevel::Trace => (Colour::White.dimmed(), Colour::Black.normal()),
            };

            let strings = &[back.paint("["),
                            front.paint(format!("{}", record.level())),
                            back.paint("]"),
                            normal.paint(" "),
                            back.paint("["),
                            front.paint(record.location().module_path()),
                            back.paint("]"),
                            normal.paint(" "),
                            back.paint(format!("{}", record.args()))];

            format!("{}", ANSIStrings(strings))
        } else {
            format!("[{}] [{}] {}",
                    record.level(),
                    record.location().module_path(),
                    record.args())
        }
    };

    let mut builder = env_logger::LogBuilder::new();

    let filter = if quiet {
        LogLevelFilter::Off
    } else {
        LogLevelFilter::from_str(level).unwrap_or(LogLevelFilter::Info)
    };

    builder.format(format).filter(None, filter);

    if let Ok(spec) = env::var("RUST_LOG") {
        builder.parse(&spec);
    }

    builder.init().unwrap();
}

fn run<Iter>(input: Iter, query: rq::query::Query) -> rq::error::Result<()>
    where Iter: Iterator<Item = rq::error::Result<rq::value::Value>>
{
    use std::io::Write;
    let mut stdout = io::stdout();
    let context = rq::query::Context::new();

    debug!("Starting input consumption");

    for value in input {
        let value = try!(value);
        debug!("Consuming an input value");
        try!(query.evaluate(&context, value).to_json(&mut stdout));
        try!(stdout.write(&[10]));
        try!(stdout.flush());
    }
    Ok(())
}

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

    fn parse_args(args: &[&str]) -> Args {
        let a = Args::docopt().argv(args).decode().unwrap();
        println!("{:?}", a);
        a
    }

    #[test]
    fn test_docopt_kitchen_sink() {
        let a = parse_args(&["rq", "-l", "info", "-jP", ".foo.Bar", "select x"]);
        assert!(a.flag_input_json);
        assert_eq!(a.flag_output_protobuf, ".foo.Bar");
        assert_eq!(a.flag_log, "info");
        assert_eq!(a.arg_query, "select x");
    }

    #[test]
    fn test_docopt_no_args() {
        parse_args(&["rq"]);
    }

    #[test]
    #[should_panic(expected = "Help")]
    fn test_docopt_help() {
        parse_args(&["rq", "--help"]);
    }

    #[test]
    fn test_docopt_version() {
        let a = parse_args(&["rq", "--version"]);
        assert!(a.flag_version);
    }

    #[test]
    fn test_docopt_input_json() {
        let a = parse_args(&["rq", "-j"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_input_json_long() {
        let a = parse_args(&["rq", "--input-json"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_output_json() {
        let a = parse_args(&["rq", "-J"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_output_json_long() {
        let a = parse_args(&["rq", "--output-json"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_input_cbor() {
        let a = parse_args(&["rq", "-c"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_input_cbor_long() {
        let a = parse_args(&["rq", "--input-cbor"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_output_cbor() {
        let a = parse_args(&["rq", "-C"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_output_cbor_long() {
        let a = parse_args(&["rq", "--output-cbor"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_input_protobuf() {
        let a = parse_args(&["rq", "-p", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, ".foo.Bar");
    }

    #[test]
    fn test_docopt_input_protobuf_long() {
        let a = parse_args(&["rq", "--input-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, ".foo.Bar");
    }

    #[test]
    fn test_docopt_output_protobuf() {
        let a = parse_args(&["rq", "-P", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, ".foo.Bar");
    }

    #[test]
    fn test_docopt_output_protobuf_long() {
        let a = parse_args(&["rq", "--output-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, ".foo.Bar");
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_input_conflict() {
        parse_args(&["rq", "-jc"]);
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_output_conflict() {
        parse_args(&["rq", "-JC"]);
    }

    #[test]
    fn test_docopt_protobuf_add_schema() {
        let a = parse_args(&["rq", "-l", "info", "protobuf", "add", "schema.proto"]);
        assert_eq!(a.flag_log, "info");
        assert!(a.cmd_protobuf);
        assert!(a.cmd_add);
        assert_eq!(a.arg_schema, "schema.proto");
    }
}
<commit_msg>Fix docstring typo<commit_after>#![feature(plugin)]
#![plugin(clippy, docopt_macros)]

extern crate ansi_term;
extern crate docopt;
extern crate env_logger;
#[macro_use]
extern crate log;
extern crate nix;
extern crate protobuf;
extern crate record_query;
extern crate rustc_serialize;

use std::env;
use std::io;
use std::path;

use record_query as rq;

const VERSION: &'static str = env!("CARGO_PKG_VERSION");

docopt!(pub Args derive Debug, concat!("
rq - record query v", env!("CARGO_PKG_VERSION"), "

A tool for manipulating data records.

Records are read from stdin, processed, and written to stdout.  The tool accepts
a query in the custom rq query language as its main command-line arguments.

See 'man rq' for in-depth documentation.

Usage:
  rq (--help|--version)
  rq [-j|-c|-p <type>] [-J|-C|-P <type>] [-l <level>|-q] [--] [<query>]
  rq [-l <level>|-q] protobuf add <schema>

Options:
  --help
      Show this screen.
  --version
      Show the program name and version.

  -j, --input-json
      Input is white-space separated JSON values.
  -J, --output-json
      Output should be formatted as JSON values.
  -c, --input-cbor
      Input is a series of CBOR values.
  -C, --output-cbor
      Output is a series of CBOR values.
  -p <type>, --input-protobuf <type>
      Input is a single protocol buffer object.  The argument refers to the
      fully qualified name of the message type (including the leading '.').
  -P <type>, --output-protobuf <type>
      Output should be formatted as protocol buffer objects.  The argument
      refers to the fully qualified name of the message type (including the
      leading '.').

  <query>
      A query indicating how to transform each record.

  -l <level>, --log <level>
      Display log messages at and above the specified log level.  The value can
      be one of 'off', 'error', 'warn', 'info', 'debug' or 'trace'.
  -q, --quiet
      Log nothing (alias for '-l off').
"));

fn main() {
    use std::io::Read;

    let args: Args = Args::docopt()
        .version(Some(VERSION.to_owned()))
        .decode().unwrap_or_else(|e| e.exit());

    setup_log(&args.flag_log, args.flag_quiet);

    let paths = rq::config::Paths::new().unwrap();

    if args.cmd_protobuf {
        if args.cmd_add {
            let schema = path::Path::new(&args.arg_schema);
            rq::proto_index::add_file(&paths, schema).unwrap();
        }
    } else {
        let query = rq::query::Query::parse(&args.arg_query);

        let stdin = io::stdin();
        let mut input = stdin.lock();

        if !args.flag_input_protobuf.is_empty() {
            let name = args.flag_input_protobuf;
            debug!("Input is protobuf with argument {}", name);

            let descriptors_proto = rq::proto_index::compile_descriptor_set(&paths).unwrap();
            let descriptors =
                rq::value::protobuf::descriptor::Descriptors::from_protobuf(&descriptors_proto);
            let stream = protobuf::CodedInputStream::new(&mut input);
            let values = rq::value::protobuf::ProtobufValues::new(descriptors,
                                                                  name.to_owned(),
                                                                  stream);
            run(values, query).unwrap_or_else(|e| error!("{:?}", e));
        } else if args.flag_input_cbor {
            run(rq::value::cbor::CborValues::new(input), query)
                .unwrap_or_else(|e| error!("{:?}", e));
        } else {
            run(rq::value::json::JsonValues::new(input.bytes()), query)
                .unwrap_or_else(|e| error!("{:?}", e));
        }
    }
}

fn setup_log(level: &str, quiet: bool) {
    use std::str::FromStr;
    use ansi_term::ANSIStrings;
    use ansi_term::Colour;
    use ansi_term::Style;
    use log::LogLevel;
    use log::LogLevelFilter;
    use nix::unistd;
    use nix::sys::ioctl;

    let normal = Style::new();

    let format = move |record: &log::LogRecord| {
        if unistd::isatty(ioctl::libc::STDERR_FILENO).unwrap_or(false) {
            let (front, back) = match record.level() {
                LogLevel::Error => (Colour::Red.normal(), Colour::Red.dimmed()),
                LogLevel::Warn => (Colour::Yellow.normal(), Colour::Yellow.dimmed()),
                LogLevel::Info => (Colour::Blue.normal(), Colour::Blue.dimmed()),
                LogLevel::Debug => (Colour::Purple.normal(), Colour::Purple.dimmed()),
                LogLevel::Trace => (Colour::White.dimmed(), Colour::Black.normal()),
            };

            let strings = &[back.paint("["),
                            front.paint(format!("{}", record.level())),
                            back.paint("]"),
                            normal.paint(" "),
                            back.paint("["),
                            front.paint(record.location().module_path()),
                            back.paint("]"),
                            normal.paint(" "),
                            back.paint(format!("{}", record.args()))];

            format!("{}", ANSIStrings(strings))
        } else {
            format!("[{}] [{}] {}",
                    record.level(),
                    record.location().module_path(),
                    record.args())
        }
    };

    let mut builder = env_logger::LogBuilder::new();

    let filter = if quiet {
        LogLevelFilter::Off
    } else {
        LogLevelFilter::from_str(level).unwrap_or(LogLevelFilter::Info)
    };

    builder.format(format).filter(None, filter);

    if let Ok(spec) = env::var("RUST_LOG") {
        builder.parse(&spec);
    }

    builder.init().unwrap();
}

fn run<Iter>(input: Iter, query: rq::query::Query) -> rq::error::Result<()>
    where Iter: Iterator<Item = rq::error::Result<rq::value::Value>>
{
    use std::io::Write;
    let mut stdout = io::stdout();
    let context = rq::query::Context::new();

    debug!("Starting input consumption");

    for value in input {
        let value = try!(value);
        debug!("Consuming an input value");
        try!(query.evaluate(&context, value).to_json(&mut stdout));
        try!(stdout.write(&[10]));
        try!(stdout.flush());
    }
    Ok(())
}

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

    fn parse_args(args: &[&str]) -> Args {
        let a = Args::docopt().argv(args).decode().unwrap();
        println!("{:?}", a);
        a
    }

    #[test]
    fn test_docopt_kitchen_sink() {
        let a = parse_args(&["rq", "-l", "info", "-jP", ".foo.Bar", "select x"]);
        assert!(a.flag_input_json);
        assert_eq!(a.flag_output_protobuf, ".foo.Bar");
        assert_eq!(a.flag_log, "info");
        assert_eq!(a.arg_query, "select x");
    }

    #[test]
    fn test_docopt_no_args() {
        parse_args(&["rq"]);
    }

    #[test]
    #[should_panic(expected = "Help")]
    fn test_docopt_help() {
        parse_args(&["rq", "--help"]);
    }

    #[test]
    fn test_docopt_version() {
        let a = parse_args(&["rq", "--version"]);
        assert!(a.flag_version);
    }

    #[test]
    fn test_docopt_input_json() {
        let a = parse_args(&["rq", "-j"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_input_json_long() {
        let a = parse_args(&["rq", "--input-json"]);
        assert!(a.flag_input_json);
    }

    #[test]
    fn test_docopt_output_json() {
        let a = parse_args(&["rq", "-J"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_output_json_long() {
        let a = parse_args(&["rq", "--output-json"]);
        assert!(a.flag_output_json);
    }

    #[test]
    fn test_docopt_input_cbor() {
        let a = parse_args(&["rq", "-c"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_input_cbor_long() {
        let a = parse_args(&["rq", "--input-cbor"]);
        assert!(a.flag_input_cbor);
    }

    #[test]
    fn test_docopt_output_cbor() {
        let a = parse_args(&["rq", "-C"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_output_cbor_long() {
        let a = parse_args(&["rq", "--output-cbor"]);
        assert!(a.flag_output_cbor);
    }

    #[test]
    fn test_docopt_input_protobuf() {
        let a = parse_args(&["rq", "-p", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, ".foo.Bar");
    }

    #[test]
    fn test_docopt_input_protobuf_long() {
        let a = parse_args(&["rq", "--input-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_input_protobuf, ".foo.Bar");
    }

    #[test]
    fn test_docopt_output_protobuf() {
        let a = parse_args(&["rq", "-P", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, ".foo.Bar");
    }

    #[test]
    fn test_docopt_output_protobuf_long() {
        let a = parse_args(&["rq", "--output-protobuf", ".foo.Bar"]);
        assert_eq!(a.flag_output_protobuf, ".foo.Bar");
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_input_conflict() {
        parse_args(&["rq", "-jc"]);
    }

    #[test]
    #[should_panic(expected = "NoMatch")]
    fn test_docopt_output_conflict() {
        parse_args(&["rq", "-JC"]);
    }

    #[test]
    fn test_docopt_protobuf_add_schema() {
        let a = parse_args(&["rq", "-l", "info", "protobuf", "add", "schema.proto"]);
        assert_eq!(a.flag_log, "info");
        assert!(a.cmd_protobuf);
        assert!(a.cmd_add);
        assert_eq!(a.arg_schema, "schema.proto");
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::stdio;
use std::collections;

struct Difficulty {
    min: uint,
    max: uint
}

fn main() {

    start();
}

fn start() {
    println!("WELCOME TO HANGMAN");
    println!("Please enter a difficulty: easy, medium, or hard:");

    loop {
        io::print(">");
        let input = &stdio::stdin()
                            .read_line()
                            .ok()
                            .expect("Failed to read line.");

        let difficulty_opt = match input.as_slice() {
            "easy\n"   => Some(Difficulty { min: 3, max: 5 }),
            "medium\n" => Some(Difficulty { min: 5, max: 7 }),
            "hard\n"   => Some(Difficulty { min: 7, max: 9 }),
            _          => None
        };

        let difficulty = match difficulty_opt {
            Some(d) => d,
            None    => {
                println!("Invalid input.");
                println!("Please enter a difficulty: easy, medium, or hard:");
                continue
            }
        };

        println!("Minimum word length set to {}", difficulty.min);
        println!("Maximum word length set to {}", difficulty.max);

        let words = *get_words(&difficulty);

    }
}

fn get_words(difficulty: &Difficulty) -> Box<Vec<String>> {
    let mut words = Vec::new();
    let min = difficulty.min;
    let max = difficulty.max;

    let path = Path::new("/usr/share/dict/words");
    let words_file = io::File::open(&path).ok().expect("Error opening file.");
    let mut reader = io::BufferedReader::new(words_file);
    let mut counter = 0u;
    loop {
        match reader.read_line() {
            Ok(line) => {
                if min < line.len() && line.len() < max {
                    words.push(line
                               .as_slice()
                               .trim_right_chars('\n')
                               .to_string());
                    counter += 1;
                }
            }
            Err(why) => match why.kind {
                io::EndOfFile => break,
                _             => fail!("Error reading file: {}", why)
            }
        }
    }
    println!("Read in {} words.", counter);
    box words
}

<commit_msg>more small changes to hangman after playing around.<commit_after>use std::io;
use std::io::stdio;
use std::collections;

struct Difficulty {
    min: uint,
    max: uint
}

fn main() {

    start();
}

fn start() {
    println!("WELCOME TO HANGMAN");
    println!("Please enter a difficulty: easy, medium, or hard:");

    loop {
        io::print(">");
        let input = &stdio::stdin()
                            .read_line()
                            .ok()
                            .expect("Failed to read line.");

        let difficulty_opt = match input.as_slice() {
            "easy\n"   => Some(Difficulty { min: 3, max: 5 }),
            "medium\n" => Some(Difficulty { min: 5, max: 7 }),
            "hard\n"   => Some(Difficulty { min: 7, max: 9 }),
            _          => None
        };

        let difficulty = match difficulty_opt {
            Some(d) => d,
            None    => {
                println!("Invalid input.");
                println!("Please enter a difficulty: easy, medium, or hard:");
                continue
            }
        };

        println!("Minimum word length set to {}", difficulty.min);
        println!("Maximum word length set to {}", difficulty.max);

        let words: Box<Vec<String>> = get_words(&difficulty);

    }
}

fn get_words(difficulty: &Difficulty) -> Box<Vec<String>> {
    let mut words = Vec::new();
    let min = difficulty.min;
    let max = difficulty.max;

    let path = Path::new("/usr/share/dict/words");
    let words_file = io::File::open(&path).ok().expect("Error opening file.");
    let mut reader = io::BufferedReader::new(words_file);
    let mut counter = 0u;
    loop {
        match reader.read_line() {
            Ok(line) => {
                if min < line.len() && line.len() < max {
                    words.push(line
                               .as_slice()
                               .trim_right_chars('\n')
                               .to_string());
                    counter += 1;
                }
            }
            Err(why) => match why.kind {
                io::EndOfFile => break,
                _             => fail!("Error reading file: {}", why)
            }
        }
    }
    println!("Read in {} words.", counter);
    box words
}

<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

#![allow(clippy::module_inception)]
pub mod stdlib;
pub mod transaction_scripts;
<commit_msg>[stdlib] remove unnecessary mod.rs file<commit_after><|endoftext|>


<commit_before>use amq_protocol::frame::{BackToTheBuffer, GenError, GenResult, WriteContext};
use std::{
    cmp,
    io::{self, IoSlice, IoSliceMut},
};

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Buffer {
    memory: Vec<u8>,
    capacity: usize,
    position: usize,
    end: usize,
}

pub(crate) struct Checkpoint(usize);

impl Buffer {
    pub(crate) fn with_capacity(capacity: usize) -> Buffer {
        Buffer {
            memory: vec![0; capacity],
            capacity,
            position: 0,
            end: 0,
        }
    }

    pub(crate) fn checkpoint(&self) -> Checkpoint {
        Checkpoint(self.end)
    }

    pub(crate) fn rollback(&mut self, checkpoint: Checkpoint) {
        self.end = checkpoint.0;
    }

    pub(crate) fn grow(&mut self, new_size: usize) -> bool {
        if self.capacity >= new_size {
            return false;
        }

        let old_capacity = self.capacity;

        self.memory.resize(new_size, 0);
        self.capacity = new_size;

        if self.end < self.position {
            let (old, new) = self.memory.split_at_mut(old_capacity);
            new[..].copy_from_slice(&old[..self.end]);
            self.end += old_capacity;
        }

        true
    }

    pub(crate) fn available_data(&self) -> usize {
        if self.end >= self.position {
            self.end - self.position
        } else {
            self.end + self.capacity - self.position
        }
    }

    fn available_space(&self) -> usize {
        if self.end >= self.position {
            self.capacity - self.end + self.position
        } else {
            self.position - self.end
        }
    }

    pub(crate) fn consume(&mut self, count: usize, ring: bool) -> usize {
        let cnt = cmp::min(count, self.available_data());
        self.position += cnt;
        if ring {
            self.position %= self.capacity;
        }
        cnt
    }

    pub(crate) fn fill(&mut self, count: usize, ring: bool) -> usize {
        let cnt = cmp::min(count, self.available_space());
        self.end += cnt;
        if ring {
            self.end %= self.capacity;
        }
        cnt
    }

    pub(crate) fn write_to<T: io::Write>(&self, writer: &mut T) -> io::Result<usize> {
        if self.end >= self.position {
            writer.write(&self.memory[self.position..self.end])
        } else {
            writer.write_vectored(&[
                IoSlice::new(&self.memory[self.position..]),
                IoSlice::new(&self.memory[..self.end]),
            ])
        }
    }

    pub(crate) fn read_from<T: io::Read>(
        &mut self,
        reader: &mut T,
        ring: bool,
    ) -> io::Result<usize> {
        if ring {
            if self.end >= self.position {
                let (start, end) = self.memory.split_at_mut(self.end);
                reader.read_vectored(
                    &mut [
                        IoSliceMut::new(&mut end[..]),
                        IoSliceMut::new(&mut start[..self.position]),
                    ][..],
                )
            } else {
                reader.read(&mut self.memory[self.end..self.position])
            }
        } else {
            reader.read(&mut self.memory[self.end..])
        }
    }

    pub(crate) fn offset(&self, buf: &[u8]) -> usize {
        let bufptr = buf.as_ptr() as usize;
        if self.end >= self.position {
            let data = &self.memory[self.position..self.end];
            bufptr - data.as_ptr() as usize
        } else {
            let data = &self.memory[self.position..];
            let dataptr = data.as_ptr() as usize;
            if dataptr < bufptr {
                bufptr - dataptr
            } else {
                let data = &self.memory[..self.end];
                bufptr + self.capacity - self.position - data.as_ptr() as usize
            }
        }
    }

    pub(crate) fn data(&self) -> &[u8] {
        // FIXME: drop
        &self.memory[self.position..self.end]
    }

    pub(crate) fn shift(&mut self) {
        // FIXME: drop
        let length = self.end - self.position;
        if length > self.position {
            return;
        } else {
            let (start, end) = self.memory.split_at_mut(self.position);
            start[..length].copy_from_slice(&end[..length]);
        }
        self.position = 0;
        self.end = length;
    }

    pub(crate) fn shift_unless_available(&mut self, size: usize) {
        // FIXME: drop
        if self.available_space() < size {
            self.shift();
        }
    }
}

impl io::Write for &mut Buffer {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        let amt = if self.end >= self.position {
            let mut space = &mut self.memory[self.end..];
            let mut amt = space.write(data)?;
            if amt == self.capacity - self.end {
                let mut space = &mut self.memory[..self.position];
                amt += space.write(&data[amt..])?;
            }
            amt
        } else {
            let mut space = &mut self.memory[self.end..self.position];
            space.write(data)?
        };
        self.fill(amt, true);
        Ok(amt)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl BackToTheBuffer for &mut Buffer {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        if s.write.available_space() < reserved {
            return Err(GenError::BufferTooSmall(
                reserved - s.write.available_space(),
            ));
        }
        let start = s.write.checkpoint();
        s.write.fill(reserved, true);
        gen(s).and_then(|(s, tmp)| {
            let end = s.write.checkpoint();
            s.write.rollback(start);
            before(s, tmp).and_then(|s| {
                s.write.rollback(end);
                Ok(s)
            })
        })
    }
}
<commit_msg>buffer: make ptr arithmetic more readable<commit_after>use amq_protocol::frame::{BackToTheBuffer, GenError, GenResult, WriteContext};
use std::{
    cmp,
    io::{self, IoSlice, IoSliceMut},
};

#[derive(Debug, PartialEq, Clone)]
pub(crate) struct Buffer {
    memory: Vec<u8>,
    capacity: usize,
    position: usize,
    end: usize,
}

pub(crate) struct Checkpoint(usize);

impl Buffer {
    pub(crate) fn with_capacity(capacity: usize) -> Buffer {
        Buffer {
            memory: vec![0; capacity],
            capacity,
            position: 0,
            end: 0,
        }
    }

    pub(crate) fn checkpoint(&self) -> Checkpoint {
        Checkpoint(self.end)
    }

    pub(crate) fn rollback(&mut self, checkpoint: Checkpoint) {
        self.end = checkpoint.0;
    }

    pub(crate) fn grow(&mut self, new_size: usize) -> bool {
        if self.capacity >= new_size {
            return false;
        }

        let old_capacity = self.capacity;

        self.memory.resize(new_size, 0);
        self.capacity = new_size;

        if self.end < self.position {
            let (old, new) = self.memory.split_at_mut(old_capacity);
            new[..].copy_from_slice(&old[..self.end]);
            self.end += old_capacity;
        }

        true
    }

    pub(crate) fn available_data(&self) -> usize {
        if self.end >= self.position {
            self.end - self.position
        } else {
            self.end + self.capacity - self.position
        }
    }

    fn available_space(&self) -> usize {
        if self.end >= self.position {
            self.capacity - self.end + self.position
        } else {
            self.position - self.end
        }
    }

    pub(crate) fn consume(&mut self, count: usize, ring: bool) -> usize {
        let cnt = cmp::min(count, self.available_data());
        self.position += cnt;
        if ring {
            self.position %= self.capacity;
        }
        cnt
    }

    pub(crate) fn fill(&mut self, count: usize, ring: bool) -> usize {
        let cnt = cmp::min(count, self.available_space());
        self.end += cnt;
        if ring {
            self.end %= self.capacity;
        }
        cnt
    }

    pub(crate) fn write_to<T: io::Write>(&self, writer: &mut T) -> io::Result<usize> {
        if self.end >= self.position {
            writer.write(&self.memory[self.position..self.end])
        } else {
            writer.write_vectored(&[
                IoSlice::new(&self.memory[self.position..]),
                IoSlice::new(&self.memory[..self.end]),
            ])
        }
    }

    pub(crate) fn read_from<T: io::Read>(
        &mut self,
        reader: &mut T,
        ring: bool,
    ) -> io::Result<usize> {
        if ring {
            if self.end >= self.position {
                let (start, end) = self.memory.split_at_mut(self.end);
                reader.read_vectored(
                    &mut [
                        IoSliceMut::new(&mut end[..]),
                        IoSliceMut::new(&mut start[..self.position]),
                    ][..],
                )
            } else {
                reader.read(&mut self.memory[self.end..self.position])
            }
        } else {
            reader.read(&mut self.memory[self.end..])
        }
    }

    pub(crate) fn offset(&self, buf: &[u8]) -> usize {
        let bufptr = buf.as_ptr() as usize;
        if self.end >= self.position {
            let data = &self.memory[self.position..self.end];
            let dataptr = data.as_ptr() as usize;
            bufptr - dataptr
        } else {
            let data = &self.memory[self.position..];
            let dataptr = data.as_ptr() as usize;
            if dataptr < bufptr {
                bufptr - dataptr
            } else {
                let data = &self.memory[..self.end];
                let dataptr = data.as_ptr() as usize;
                bufptr + self.capacity - self.position - dataptr
            }
        }
    }

    pub(crate) fn data(&self) -> &[u8] {
        // FIXME: drop
        &self.memory[self.position..self.end]
    }

    pub(crate) fn shift(&mut self) {
        // FIXME: drop
        let length = self.end - self.position;
        if length > self.position {
            return;
        } else {
            let (start, end) = self.memory.split_at_mut(self.position);
            start[..length].copy_from_slice(&end[..length]);
        }
        self.position = 0;
        self.end = length;
    }

    pub(crate) fn shift_unless_available(&mut self, size: usize) {
        // FIXME: drop
        if self.available_space() < size {
            self.shift();
        }
    }
}

impl io::Write for &mut Buffer {
    fn write(&mut self, data: &[u8]) -> io::Result<usize> {
        let amt = if self.end >= self.position {
            let mut space = &mut self.memory[self.end..];
            let mut amt = space.write(data)?;
            if amt == self.capacity - self.end {
                let mut space = &mut self.memory[..self.position];
                amt += space.write(&data[amt..])?;
            }
            amt
        } else {
            let mut space = &mut self.memory[self.end..self.position];
            space.write(data)?
        };
        self.fill(amt, true);
        Ok(amt)
    }

    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl BackToTheBuffer for &mut Buffer {
    fn reserve_write_use<
        Tmp,
        Gen: Fn(WriteContext<Self>) -> Result<(WriteContext<Self>, Tmp), GenError>,
        Before: Fn(WriteContext<Self>, Tmp) -> GenResult<Self>,
    >(
        s: WriteContext<Self>,
        reserved: usize,
        gen: &Gen,
        before: &Before,
    ) -> Result<WriteContext<Self>, GenError> {
        if s.write.available_space() < reserved {
            return Err(GenError::BufferTooSmall(
                reserved - s.write.available_space(),
            ));
        }
        let start = s.write.checkpoint();
        s.write.fill(reserved, true);
        gen(s).and_then(|(s, tmp)| {
            let end = s.write.checkpoint();
            s.write.rollback(start);
            before(s, tmp).and_then(|s| {
                s.write.rollback(end);
                Ok(s)
            })
        })
    }
}
<|endoftext|>


<commit_before>//! A stably addressed token buffer supporting efficient traversal based on a
//! cheaply copyable cursor.
//!
//! *This module is available only if Syn is built with the `"parsing"` feature.*

// This module is heavily commented as it contains most of the unsafe code in
// Syn, and caution should be used when editing it. The public-facing interface
// is 100% safe but the implementation is fragile internally.

#[cfg(all(
    not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
    feature = "proc-macro"
))]
use crate::proc_macro as pm;
use crate::Lifetime;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::marker::PhantomData;

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
    // Mimicking types from proc-macro.
    // Group entries contain the offset to the matching End entry.
    Group(Group, usize),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal),
    End,
}

/// A buffer that can be efficiently traversed multiple times, unlike
/// `TokenStream` which requires a deep copy in order to traverse more than
/// once.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
    // NOTE: Do not implement clone on this - while the current design could be
    // cloned, other designs which could be desirable may not be cloneable.
    entries: Box<[Entry]>,
}

// Keep the explicit impl for backwards compatibility.
impl Drop for TokenBuffer {
    fn drop(&mut self) {}
}

impl TokenBuffer {
    fn new_inner(entries: &mut Vec<Entry>, stream: TokenStream) {
        for tt in stream {
            match tt {
                TokenTree::Ident(ident) => entries.push(Entry::Ident(ident)),
                TokenTree::Punct(punct) => entries.push(Entry::Punct(punct)),
                TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)),
                TokenTree::Group(group) => {
                    let group_start_index = entries.len();
                    entries.push(Entry::End); // we replace this below
                    Self::new_inner(entries, group.stream());
                    let group_end_index = entries.len();
                    entries.push(Entry::End);
                    let group_end_offset = group_end_index - group_start_index;
                    entries[group_start_index] = Entry::Group(group, group_end_offset);
                }
            }
        }
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `proc_macro::TokenStream`.
    ///
    /// *This method is available only if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
        feature = "proc-macro"
    ))]
    pub fn new(stream: pm::TokenStream) -> Self {
        Self::new2(stream.into())
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `proc_macro2::TokenStream`.
    pub fn new2(stream: TokenStream) -> Self {
        let mut entries = Vec::new();
        Self::new_inner(&mut entries, stream);
        entries.push(Entry::End);
        Self {
            entries: entries.into_boxed_slice(),
        }
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        let ptr = self.entries.as_ptr();
        unsafe { Cursor::create(ptr, ptr.add(self.entries.len() - 1)) }
    }
}

/// A cheaply copyable cursor into a `TokenBuffer`.
///
/// This cursor holds a shared reference into the immutable data which is used
/// internally to represent a `TokenStream`, and can be efficiently manipulated
/// and copied around.
///
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct Cursor<'a> {
    // The current entry which the `Cursor` is pointing at.
    ptr: *const Entry,
    // This is the only `Entry::End` object which this cursor is allowed to
    // point at. All other `End` objects are skipped over in `Cursor::create`.
    scope: *const Entry,
    // Cursor is covariant in 'a. This field ensures that our pointers are still
    // valid.
    marker: PhantomData<&'a Entry>,
}

impl<'a> Cursor<'a> {
    /// Creates a cursor referencing a static empty TokenStream.
    pub fn empty() -> Self {
        // It's safe in this situation for us to put an `Entry` object in global
        // storage, despite it not actually being safe to send across threads
        // (`Ident` is a reference into a thread-local table). This is because
        // this entry never includes a `Ident` object.
        //
        // This wrapper struct allows us to break the rules and put a `Sync`
        // object in global storage.
        struct UnsafeSyncEntry(Entry);
        unsafe impl Sync for UnsafeSyncEntry {}
        static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End);

        Cursor {
            ptr: &EMPTY_ENTRY.0,
            scope: &EMPTY_ENTRY.0,
            marker: PhantomData,
        }
    }

    /// This create method intelligently exits non-explicitly-entered
    /// `None`-delimited scopes when the cursor reaches the end of them,
    /// allowing for them to be treated transparently.
    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
        // NOTE: If we're looking at a `End`, we want to advance the cursor
        // past it, unless `ptr == scope`, which means that we're at the edge of
        // our cursor's scope. We should only have `ptr != scope` at the exit
        // from None-delimited groups entered with `ignore_none`.
        while let Entry::End = *ptr {
            if ptr == scope {
                break;
            }
            ptr = ptr.add(1);
        }

        Cursor {
            ptr,
            scope,
            marker: PhantomData,
        }
    }

    /// Get the current entry.
    fn entry(self) -> &'a Entry {
        unsafe { &*self.ptr }
    }

    /// Bump the cursor to point at the next token after the current one. This
    /// is undefined behavior if the cursor is currently looking at an
    /// `Entry::End`.
    ///
    /// If the cursor is looking at an `Entry::Group`, the bumped cursor will
    /// point at the first token in the group (with the same scope end).
    unsafe fn bump_ignore_group(self) -> Cursor<'a> {
        Cursor::create(self.ptr.offset(1), self.scope)
    }

    /// Bump the cursor to point at the next token after the current one. This
    /// is undefined behavior if the cursor is currently looking at an
    /// `Entry::End`.
    ///
    /// If the cursor is looking at an `Entry::Group`, the bumped cursor will
    /// point at the first token after the group.
    unsafe fn bump_over_group(self) -> Cursor<'a> {
        match self.entry() {
            Entry::Group(_, end_offset) => Cursor::create(self.ptr.add(*end_offset), self.scope),
            _ => self.bump_ignore_group(),
        }
    }

    /// While the cursor is looking at a `None`-delimited group, move it to look
    /// at the first token inside instead. If the group is empty, this will move
    /// the cursor past the `None`-delimited group.
    ///
    /// WARNING: This mutates its argument.
    fn ignore_none(&mut self) {
        while let Entry::Group(group, _) = self.entry() {
            if group.delimiter() == Delimiter::None {
                unsafe { *self = self.bump_ignore_group() };
            } else {
                break;
            }
        }
    }

    /// Checks whether the cursor is currently pointing at the end of its valid
    /// scope.
    pub fn eof(self) -> bool {
        // We're at eof if we're at the end of our scope.
        self.ptr == self.scope
    }

    /// If the cursor is pointing at a `Group` with the given delimiter, returns
    /// a cursor into that group and one pointing to the next `TokenTree`.
    pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
        // If we're not trying to enter a none-delimited group, we want to
        // ignore them. We have to make sure to _not_ ignore them when we want
        // to enter them, of course. For obvious reasons.
        if delim != Delimiter::None {
            self.ignore_none();
        }

        if let Entry::Group(group, end_offset) = self.entry() {
            if group.delimiter() == delim {
                let end_of_group = unsafe { self.ptr.add(*end_offset) };
                let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
                let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
                return Some((inside_of_group, group.span(), after_group));
            }
        }

        None
    }

    /// If the cursor is pointing at a `Ident`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump_ignore_group() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Punct`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(punct) if punct.as_char() != '\'' => {
                Some((punct.clone(), unsafe { self.bump_ignore_group() }))
            }
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Literal`, return it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Lifetime`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
                let next = unsafe { self.bump_ignore_group() };
                match next.ident() {
                    Some((ident, rest)) => {
                        let lifetime = Lifetime {
                            apostrophe: punct.span(),
                            ident,
                        };
                        Some((lifetime, rest))
                    }
                    None => None,
                }
            }
            _ => None,
        }
    }

    /// Copies all remaining tokens visible from this cursor into a
    /// `TokenStream`.
    pub fn token_stream(self) -> TokenStream {
        let mut tts = Vec::new();
        let mut cursor = self;
        while let Some((tt, rest)) = cursor.token_tree() {
            tts.push(tt);
            cursor = rest;
        }
        tts.into_iter().collect()
    }

    /// If the cursor is pointing at a `TokenTree`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    ///
    /// Returns `None` if the cursor has reached the end of its stream.
    ///
    /// This method does not treat `None`-delimited groups as transparent, and
    /// will return a `Group(None, ..)` if the cursor is looking at one.
    pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
        let tree = match self.entry() {
            Entry::Group(group, _) => group.clone().into(),
            Entry::Literal(literal) => literal.clone().into(),
            Entry::Ident(ident) => ident.clone().into(),
            Entry::Punct(punct) => punct.clone().into(),
            Entry::End => return None,
        };

        Some((tree, unsafe { self.bump_over_group() }))
    }

    /// Returns the `Span` of the current token, or `Span::call_site()` if this
    /// cursor points to eof.
    pub fn span(self) -> Span {
        match self.entry() {
            Entry::Group(group, _) => group.span(),
            Entry::Literal(literal) => literal.span(),
            Entry::Ident(ident) => ident.span(),
            Entry::Punct(punct) => punct.span(),
            Entry::End => Span::call_site(),
        }
    }

    /// Skip over the next token without cloning it. Returns `None` if this
    /// cursor points to eof.
    ///
    /// This method treats `'lifetimes` as a single token.
    pub(crate) fn skip(self) -> Option<Cursor<'a>> {
        match self.entry() {
            Entry::End => None,

            // Treat lifetimes as a single tt for the purposes of 'skip'.
            Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
                let next = unsafe { self.bump_ignore_group() };
                match next.entry() {
                    Entry::Ident(_) => Some(unsafe { next.bump_ignore_group() }),
                    _ => Some(next),
                }
            }
            _ => Some(unsafe { self.bump_over_group() }),
        }
    }
}

impl<'a> Copy for Cursor<'a> {}

impl<'a> Clone for Cursor<'a> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<'a> Eq for Cursor<'a> {}

impl<'a> PartialEq for Cursor<'a> {
    fn eq(&self, other: &Self) -> bool {
        let Cursor { ptr, scope, marker } = self;
        let _ = marker;
        *ptr == other.ptr && *scope == other.scope
    }
}

pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
    a.scope == b.scope
}

pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_open(),
        _ => cursor.span(),
    }
}

pub(crate) fn close_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_close(),
        _ => cursor.span(),
    }
}
<commit_msg>Implement skip and token_tree using the 'len' of entries being stepped over<commit_after>//! A stably addressed token buffer supporting efficient traversal based on a
//! cheaply copyable cursor.
//!
//! *This module is available only if Syn is built with the `"parsing"` feature.*

// This module is heavily commented as it contains most of the unsafe code in
// Syn, and caution should be used when editing it. The public-facing interface
// is 100% safe but the implementation is fragile internally.

#[cfg(all(
    not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
    feature = "proc-macro"
))]
use crate::proc_macro as pm;
use crate::Lifetime;
use proc_macro2::{Delimiter, Group, Ident, Literal, Punct, Spacing, Span, TokenStream, TokenTree};
use std::marker::PhantomData;

/// Internal type which is used instead of `TokenTree` to represent a token tree
/// within a `TokenBuffer`.
enum Entry {
    // Mimicking types from proc-macro.
    // Group entries contain the offset to the matching End entry.
    Group(Group, usize),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal),
    End,
}

/// A buffer that can be efficiently traversed multiple times, unlike
/// `TokenStream` which requires a deep copy in order to traverse more than
/// once.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct TokenBuffer {
    // NOTE: Do not implement clone on this - while the current design could be
    // cloned, other designs which could be desirable may not be cloneable.
    entries: Box<[Entry]>,
}

// Keep the explicit impl for backwards compatibility.
impl Drop for TokenBuffer {
    fn drop(&mut self) {}
}

impl TokenBuffer {
    fn new_inner(entries: &mut Vec<Entry>, stream: TokenStream) {
        for tt in stream {
            match tt {
                TokenTree::Ident(ident) => entries.push(Entry::Ident(ident)),
                TokenTree::Punct(punct) => entries.push(Entry::Punct(punct)),
                TokenTree::Literal(literal) => entries.push(Entry::Literal(literal)),
                TokenTree::Group(group) => {
                    let group_start_index = entries.len();
                    entries.push(Entry::End); // we replace this below
                    Self::new_inner(entries, group.stream());
                    let group_end_index = entries.len();
                    entries.push(Entry::End);
                    let group_end_offset = group_end_index - group_start_index;
                    entries[group_start_index] = Entry::Group(group, group_end_offset);
                }
            }
        }
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `proc_macro::TokenStream`.
    ///
    /// *This method is available only if Syn is built with both the `"parsing"` and
    /// `"proc-macro"` features.*
    #[cfg(all(
        not(all(target_arch = "wasm32", any(target_os = "unknown", target_os = "wasi"))),
        feature = "proc-macro"
    ))]
    pub fn new(stream: pm::TokenStream) -> Self {
        Self::new2(stream.into())
    }

    /// Creates a `TokenBuffer` containing all the tokens from the input
    /// `proc_macro2::TokenStream`.
    pub fn new2(stream: TokenStream) -> Self {
        let mut entries = Vec::new();
        Self::new_inner(&mut entries, stream);
        entries.push(Entry::End);
        Self {
            entries: entries.into_boxed_slice(),
        }
    }

    /// Creates a cursor referencing the first token in the buffer and able to
    /// traverse until the end of the buffer.
    pub fn begin(&self) -> Cursor {
        let ptr = self.entries.as_ptr();
        unsafe { Cursor::create(ptr, ptr.add(self.entries.len() - 1)) }
    }
}

/// A cheaply copyable cursor into a `TokenBuffer`.
///
/// This cursor holds a shared reference into the immutable data which is used
/// internally to represent a `TokenStream`, and can be efficiently manipulated
/// and copied around.
///
/// An empty `Cursor` can be created directly, or one may create a `TokenBuffer`
/// object and get a cursor to its first token with `begin()`.
///
/// Two cursors are equal if they have the same location in the same input
/// stream, and have the same scope.
///
/// *This type is available only if Syn is built with the `"parsing"` feature.*
pub struct Cursor<'a> {
    // The current entry which the `Cursor` is pointing at.
    ptr: *const Entry,
    // This is the only `Entry::End` object which this cursor is allowed to
    // point at. All other `End` objects are skipped over in `Cursor::create`.
    scope: *const Entry,
    // Cursor is covariant in 'a. This field ensures that our pointers are still
    // valid.
    marker: PhantomData<&'a Entry>,
}

impl<'a> Cursor<'a> {
    /// Creates a cursor referencing a static empty TokenStream.
    pub fn empty() -> Self {
        // It's safe in this situation for us to put an `Entry` object in global
        // storage, despite it not actually being safe to send across threads
        // (`Ident` is a reference into a thread-local table). This is because
        // this entry never includes a `Ident` object.
        //
        // This wrapper struct allows us to break the rules and put a `Sync`
        // object in global storage.
        struct UnsafeSyncEntry(Entry);
        unsafe impl Sync for UnsafeSyncEntry {}
        static EMPTY_ENTRY: UnsafeSyncEntry = UnsafeSyncEntry(Entry::End);

        Cursor {
            ptr: &EMPTY_ENTRY.0,
            scope: &EMPTY_ENTRY.0,
            marker: PhantomData,
        }
    }

    /// This create method intelligently exits non-explicitly-entered
    /// `None`-delimited scopes when the cursor reaches the end of them,
    /// allowing for them to be treated transparently.
    unsafe fn create(mut ptr: *const Entry, scope: *const Entry) -> Self {
        // NOTE: If we're looking at a `End`, we want to advance the cursor
        // past it, unless `ptr == scope`, which means that we're at the edge of
        // our cursor's scope. We should only have `ptr != scope` at the exit
        // from None-delimited groups entered with `ignore_none`.
        while let Entry::End = *ptr {
            if ptr == scope {
                break;
            }
            ptr = ptr.add(1);
        }

        Cursor {
            ptr,
            scope,
            marker: PhantomData,
        }
    }

    /// Get the current entry.
    fn entry(self) -> &'a Entry {
        unsafe { &*self.ptr }
    }

    /// Bump the cursor to point at the next token after the current one. This
    /// is undefined behavior if the cursor is currently looking at an
    /// `Entry::End`.
    ///
    /// If the cursor is looking at an `Entry::Group`, the bumped cursor will
    /// point at the first token in the group (with the same scope end).
    unsafe fn bump_ignore_group(self) -> Cursor<'a> {
        Cursor::create(self.ptr.offset(1), self.scope)
    }

    /// While the cursor is looking at a `None`-delimited group, move it to look
    /// at the first token inside instead. If the group is empty, this will move
    /// the cursor past the `None`-delimited group.
    ///
    /// WARNING: This mutates its argument.
    fn ignore_none(&mut self) {
        while let Entry::Group(group, _) = self.entry() {
            if group.delimiter() == Delimiter::None {
                unsafe { *self = self.bump_ignore_group() };
            } else {
                break;
            }
        }
    }

    /// Checks whether the cursor is currently pointing at the end of its valid
    /// scope.
    pub fn eof(self) -> bool {
        // We're at eof if we're at the end of our scope.
        self.ptr == self.scope
    }

    /// If the cursor is pointing at a `Group` with the given delimiter, returns
    /// a cursor into that group and one pointing to the next `TokenTree`.
    pub fn group(mut self, delim: Delimiter) -> Option<(Cursor<'a>, Span, Cursor<'a>)> {
        // If we're not trying to enter a none-delimited group, we want to
        // ignore them. We have to make sure to _not_ ignore them when we want
        // to enter them, of course. For obvious reasons.
        if delim != Delimiter::None {
            self.ignore_none();
        }

        if let Entry::Group(group, end_offset) = self.entry() {
            if group.delimiter() == delim {
                let end_of_group = unsafe { self.ptr.add(*end_offset) };
                let inside_of_group = unsafe { Cursor::create(self.ptr.add(1), end_of_group) };
                let after_group = unsafe { Cursor::create(end_of_group, self.scope) };
                return Some((inside_of_group, group.span(), after_group));
            }
        }

        None
    }

    /// If the cursor is pointing at a `Ident`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn ident(mut self) -> Option<(Ident, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Ident(ident) => Some((ident.clone(), unsafe { self.bump_ignore_group() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Punct`, returns it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn punct(mut self) -> Option<(Punct, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(punct) if punct.as_char() != '\'' => {
                Some((punct.clone(), unsafe { self.bump_ignore_group() }))
            }
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Literal`, return it along with a cursor
    /// pointing at the next `TokenTree`.
    pub fn literal(mut self) -> Option<(Literal, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Literal(literal) => Some((literal.clone(), unsafe { self.bump_ignore_group() })),
            _ => None,
        }
    }

    /// If the cursor is pointing at a `Lifetime`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    pub fn lifetime(mut self) -> Option<(Lifetime, Cursor<'a>)> {
        self.ignore_none();
        match self.entry() {
            Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
                let next = unsafe { self.bump_ignore_group() };
                match next.ident() {
                    Some((ident, rest)) => {
                        let lifetime = Lifetime {
                            apostrophe: punct.span(),
                            ident,
                        };
                        Some((lifetime, rest))
                    }
                    None => None,
                }
            }
            _ => None,
        }
    }

    /// Copies all remaining tokens visible from this cursor into a
    /// `TokenStream`.
    pub fn token_stream(self) -> TokenStream {
        let mut tts = Vec::new();
        let mut cursor = self;
        while let Some((tt, rest)) = cursor.token_tree() {
            tts.push(tt);
            cursor = rest;
        }
        tts.into_iter().collect()
    }

    /// If the cursor is pointing at a `TokenTree`, returns it along with a
    /// cursor pointing at the next `TokenTree`.
    ///
    /// Returns `None` if the cursor has reached the end of its stream.
    ///
    /// This method does not treat `None`-delimited groups as transparent, and
    /// will return a `Group(None, ..)` if the cursor is looking at one.
    pub fn token_tree(self) -> Option<(TokenTree, Cursor<'a>)> {
        let (tree, len) = match self.entry() {
            Entry::Group(group, end_offset) => (group.clone().into(), *end_offset),
            Entry::Literal(literal) => (literal.clone().into(), 1),
            Entry::Ident(ident) => (ident.clone().into(), 1),
            Entry::Punct(punct) => (punct.clone().into(), 1),
            Entry::End => return None,
        };

        let rest = unsafe { Cursor::create(self.ptr.add(len), self.scope) };
        Some((tree, rest))
    }

    /// Returns the `Span` of the current token, or `Span::call_site()` if this
    /// cursor points to eof.
    pub fn span(self) -> Span {
        match self.entry() {
            Entry::Group(group, _) => group.span(),
            Entry::Literal(literal) => literal.span(),
            Entry::Ident(ident) => ident.span(),
            Entry::Punct(punct) => punct.span(),
            Entry::End => Span::call_site(),
        }
    }

    /// Skip over the next token without cloning it. Returns `None` if this
    /// cursor points to eof.
    ///
    /// This method treats `'lifetimes` as a single token.
    pub(crate) fn skip(self) -> Option<Cursor<'a>> {
        let len = match self.entry() {
            Entry::End => return None,

            // Treat lifetimes as a single tt for the purposes of 'skip'.
            Entry::Punct(punct) if punct.as_char() == '\'' && punct.spacing() == Spacing::Joint => {
                match unsafe { &*self.ptr.add(1) } {
                    Entry::Ident(_) => 2,
                    _ => 1,
                }
            }

            Entry::Group(_, end_offset) => *end_offset,
            _ => 1,
        };

        Some(unsafe { Cursor::create(self.ptr.add(len), self.scope) })
    }
}

impl<'a> Copy for Cursor<'a> {}

impl<'a> Clone for Cursor<'a> {
    fn clone(&self) -> Self {
        *self
    }
}

impl<'a> Eq for Cursor<'a> {}

impl<'a> PartialEq for Cursor<'a> {
    fn eq(&self, other: &Self) -> bool {
        let Cursor { ptr, scope, marker } = self;
        let _ = marker;
        *ptr == other.ptr && *scope == other.scope
    }
}

pub(crate) fn same_scope(a: Cursor, b: Cursor) -> bool {
    a.scope == b.scope
}

pub(crate) fn open_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_open(),
        _ => cursor.span(),
    }
}

pub(crate) fn close_span_of_group(cursor: Cursor) -> Span {
    match cursor.entry() {
        Entry::Group(group, _) => group.span_close(),
        _ => cursor.span(),
    }
}
<|endoftext|>


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

#![feature(std_misc)]

use std::thread;

macro_rules! expr { ($e: expr) => { $e } }

macro_rules! spawn {
    ($($code: tt)*) => {
        expr!(thread::spawn(move|| {$($code)*}))
    }
}

pub fn main() {
    spawn! {
        println!("stmt");
    };
    let _ = spawn! {
        println!("expr");
    };
}
<commit_msg>test: Join child threads on windows in tests<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::thread;

macro_rules! expr { ($e: expr) => { $e } }

macro_rules! spawn {
    ($($code: tt)*) => {
        expr!(thread::spawn(move|| {$($code)*}).join())
    }
}

pub fn main() {
    spawn! {
        println!("stmt");
    };
    let _ = spawn! {
        println!("expr");
    };
}
<|endoftext|>


<commit_before>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate cc3200_sys;

use core;
use core::result::Result;

use self::cc3200_sys::{board_init, GPIO_IF_LedConfigure, GPIO_IF_LedOn, GPIO_IF_LedOff,
                       MAP_UtilsDelay, I2C_IF_Open, I2C_IF_Close, I2C_IF_Write, I2C_IF_Read,
                       I2C_IF_ReadFrom};
use self::cc3200_sys::simplelink::*;
use logger::SimpleLogger;
use rtc::RTC;
use io::{File, Read, Write};

#[allow(non_camel_case_types, dead_code)]
pub enum LedName {
    NO_LED_IND = 0,
    MCU_SENDING_DATA_IND,
    MCU_ASSOCIATED_IND, // Device associated to an AP
    MCU_IP_ALLOC_IND, // Device acquired an IP
    MCU_SERVER_INIT_IND, // Device connected to remote server
    MCU_CLIENT_CONNECTED_IND, // Any client connects to device
    MCU_ON_IND, // Device SLHost invoked successfully
    MCU_EXECUTE_SUCCESS_IND, // Task executed sucessfully
    MCU_EXECUTE_FAIL_IND, // Task execution failed
    MCU_RED_LED_GPIO, // GP09 for LED RED as per LP 3.0
    MCU_ORANGE_LED_GPIO, // GP10 for LED ORANGE as per LP 3.0
    MCU_GREEN_LED_GPIO, // GP11 for LED GREEN as per LP 3.0
    MCU_ALL_LED_IND,
}

#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub enum LedEnum {
    NO_LED = 0x0,
    LED1 = 0x1, // RED LED D7/GP9/Pin64
    LED2 = 0x2, // ORANGE LED D6/GP10/Pin1
    LED3 = 0x4, // GREEN LED D5/GP11/Pin2
}

pub struct Board { }

impl Board {
    pub fn init() {
        unsafe {
            board_init();
        }
        SimpleLogger::init().unwrap();
        RTC::init();
    }

    pub fn test() {
        unsafe {
            cc3200_sys::board_test();
        }
    }

    pub fn led_configure(leds: &[LedEnum]) {
        let mut val = LedEnum::NO_LED as u8;
        for led in leds {
            val |= *led as u8;
        }
        unsafe {
            GPIO_IF_LedConfigure(val);
        }
    }

    pub fn led_off(led: LedName) {
        unsafe {
            GPIO_IF_LedOff(led as i8);
        }
    }

    pub fn led_on(led: LedName) {
        unsafe {
            GPIO_IF_LedOn(led as i8);
        }
    }

    pub fn start_scheduler() {
        unsafe {
            cc3200_sys::vTaskStartScheduler();
        }
    }

    pub fn disable_irq() {
        unsafe {
            asm!("cpsid i");
        }
    }

    pub fn reset() {
        unsafe {
            cc3200_sys::reset();
        }
    }
}

pub struct Console { }

impl Console {
    pub fn clear_term() {
        unsafe {
            cc3200_sys::ClearTerm();
        }
    }

    pub fn init_term() {
        unsafe {
            cc3200_sys::InitTerm();
        }
    }

    pub fn message(msg: &str) {
        for char in msg.chars() {
            // Lossy converstion from unicode to ASCII
            let ascii_char = {
                if char > '\x7f' { '?' } else { char }
            };
            unsafe {
                cc3200_sys::console_putchar(ascii_char as i8);
            }
        }
    }
}

impl core::fmt::Write for Console {
    fn write_str(&mut self, s: &str) -> core::fmt::Result {
        Console::message(s);
        Ok(())
    }
}

pub enum I2COpenMode {
    MasterModeStd = 0,
    MasterModeFst = 1,
}

static mut I2C_IS_OPEN: bool = false;
static I2C_SUCCESS: i32 = 0;

#[derive(Clone, Copy)]
pub struct I2C { }

impl I2C {
    pub fn open(mode: I2COpenMode) -> Option<Self> {
        unsafe {
            // Only allow one instance to be created in a given open mode.
            if I2C_IS_OPEN || I2C_IF_Open(mode as u32) != I2C_SUCCESS {
                return None;
            }
            I2C_IS_OPEN = true;
        }
        return Some(I2C {});
    }

    pub fn close(&self) {
        unsafe {
            // TODO: decide what to do if we never called I2C_IF_Open
            I2C_IF_Close();
            I2C_IS_OPEN = false;
        }
    }

    pub fn write(&self, addr: u8, data: &[u8], stop: u8) -> Result<(), ()> {
        if data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_Write(addr, data.as_ptr() as *mut u8, data.len() as u8, stop) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read(&self, addr: u8, data: &mut [u8]) -> Result<(), ()> {
        if data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_Read(addr, data.as_ptr() as *mut u8, data.len() as u8) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read_from_with_length(&self,
                                 addr: u8,
                                 wr_data: &[u8],
                                 rd_data: &mut [u8],
                                 rd_len: u8)
                                 -> Result<(), ()> {
        if wr_data.len() > 255 || rd_data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_ReadFrom(addr,
                               wr_data.as_ptr() as *mut u8,
                               wr_data.len() as u8,
                               rd_data.as_ptr() as *mut u8,
                               rd_len) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read_from(&self, addr: u8, wr_data: &[u8], rd_data: &mut [u8]) -> Result<(), ()> {
        let len = rd_data.len() as u8;
        self.read_from_with_length(addr, wr_data, rd_data, len)
    }
}

//
// Image updates
//

#[derive(Copy, Clone)]
pub enum ImageStatus {
    TESTING,
    TESTREADY,
    NOTEST
}

impl ImageStatus {
    pub fn from_u32(value: u32) -> Result<ImageStatus, ()> {
        let image_status = match value {
            IMG_STATUS_TESTING   => ImageStatus::TESTING,
            IMG_STATUS_TESTREADY => ImageStatus::TESTREADY,
            IMG_STATUS_NOTEST    => ImageStatus::NOTEST,
            value => {
                println!("unknwon image status {}", value);
                return Err(());
            }
        };
        Ok(image_status)
    }
    pub fn to_u32(image_status: ImageStatus) -> Result<u32, ()> {
        let value = match image_status {
            ImageStatus::NOTEST    => IMG_STATUS_NOTEST,
            ImageStatus::TESTREADY => IMG_STATUS_TESTREADY,
            ImageStatus::TESTING   => IMG_STATUS_TESTING
        };
        Ok(value)
    }
}

pub struct BootInfo {
    pub active_image: u8,
    pub image_status: ImageStatus,
}

impl BootInfo {

    /// Create a BootInfo structure
    pub fn new(active_image: u8, image_status: ImageStatus) -> BootInfo {
        BootInfo { active_image: active_image,
                   image_status: image_status }
    }

    /// Create a BootInfo structure the represents the factory reset
    pub fn factory_reset() -> BootInfo {
        BootInfo::new(0, ImageStatus::NOTEST)
    }
}

pub struct Update { }

impl Update {

    /// Sets the application to test mode
    pub fn test() -> bool {
        let res = unsafe {
            sl_extlib_FlcTest(FLC_TEST_RESET_MCU |
                              FLC_TEST_RESET_MCU_WITH_APP)
        };
        Update::reset_is_required(res)
    }

    /// Returns true if the application runs in testing mode, false otherwise
    pub fn is_testing() -> bool {
        let res = unsafe {
            sl_extlib_FlcIsPendingCommit()
        };
        res != 0
    }

    /// Commits all changes, moving the application state from 'testing' to 'stable'
    pub fn commit() -> bool {
        let res = unsafe {
            sl_extlib_FlcCommit(FLC_COMMITED)
        };
        Update::reset_is_required(res)
    }

    /// Aborts the update
    pub fn abort() -> bool {
        let res = unsafe {
            sl_extlib_FlcCommit(FLC_NOT_COMMITED)
        };
        Update::reset_is_required(res)
    }

    /// Reads or creates the device's boot-info structure
    pub fn get_boot_info() -> Result<BootInfo, ()> {
        let boot_info = match Update::read_boot_info() {
            Ok(boot_info) => boot_info,
            Err(_) => {
                let boot_info = BootInfo::factory_reset();
                match Update::write_boot_info(&boot_info) {
                    Ok(_)  => { },
                    Err(_) => { return Err(()); }
                };
                boot_info
            }
        };
        Ok(boot_info)
    }

    fn reset_is_required(flags: i32) -> bool {
        (flags & (FLC_TEST_RESET_MCU | FLC_TEST_RESET_NWP)) != 0
    }

    fn encode_boot_info(boot_info: &BootInfo) -> Result<[u8; 8], ()> {
        let active_image = boot_info.active_image;
        let image_status = ImageStatus::to_u32(boot_info.image_status)?;
        let mut buf: [u8; 8] = [0; 8];
        buf[0] = active_image;
        buf[4] = 0xff & (image_status) as u8;
        buf[5] = 0xff & (image_status >> 8) as u8;
        buf[6] = 0xff & (image_status >> 16) as u8;
        buf[7] = 0xff & (image_status >> 24) as u8;
        Ok(buf)
    }

    fn decode_boot_info(buf: [u8; 8]) -> Result<BootInfo, ()> {
        let active_image = buf[0];
        let image_status = ((buf[4] as u32)) |
                           ((buf[5] as u32) << 8) |
                           ((buf[6] as u32) << 16) |
                           ((buf[7] as u32) << 24);
        Ok(BootInfo::new(active_image, ImageStatus::from_u32(image_status)?))
    }

    fn write_boot_info(boot_info: &BootInfo) -> Result<(), ()> {

        let buf = Update::encode_boot_info(boot_info)?;

        let mut file = match File::create(IMG_BOOT_INFO, 8, false) {
            Ok(file) => file,
            Err(_)   => { return Err(()); }
        };
        match file.write(&buf[..]) {
            Ok(buflen) => {
                if buflen < buf.len() {
                    return Err(());
                }
            },
            Err(_) => { return Err(()); }
        }
        Ok(())
    }

    fn read_boot_info() -> Result<BootInfo, ()> {
        let mut buf: [u8; 8] = [0; 8];
        let mut file = match File::open(IMG_BOOT_INFO) {
            Ok(file) => file,
            Err(_)   => return Err(())
        };
        match file.read(&mut buf) {
            Ok(buflen) => {
                if buflen != buf.len() {
                    return Err(());
                }
            },
            Err(_) => { return Err(()); }
        };
        Update::decode_boot_info(buf)
    }
}

pub struct Utils { }

impl Utils {
    pub fn delay(loops: u32) {
        unsafe {
            MAP_UtilsDelay(loops);
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn abort() {
    unimplemented!();
}
<commit_msg>Add Update::next_image() for creating next image file<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
// You can obtain one at http://mozilla.org/MPL/2.0/.

extern crate cc3200_sys;

use core;
use core::result::Result;

use self::cc3200_sys::{board_init, GPIO_IF_LedConfigure, GPIO_IF_LedOn, GPIO_IF_LedOff,
                       MAP_UtilsDelay, I2C_IF_Open, I2C_IF_Close, I2C_IF_Write, I2C_IF_Read,
                       I2C_IF_ReadFrom};
use self::cc3200_sys::simplelink::*;
use logger::SimpleLogger;
use rtc::RTC;
use io::{File, Read, Write};

macro_rules! ignore {
    ($e:expr) => ({
        match $e {
            _ => { },
        }
    })
}

#[allow(non_camel_case_types, dead_code)]
pub enum LedName {
    NO_LED_IND = 0,
    MCU_SENDING_DATA_IND,
    MCU_ASSOCIATED_IND, // Device associated to an AP
    MCU_IP_ALLOC_IND, // Device acquired an IP
    MCU_SERVER_INIT_IND, // Device connected to remote server
    MCU_CLIENT_CONNECTED_IND, // Any client connects to device
    MCU_ON_IND, // Device SLHost invoked successfully
    MCU_EXECUTE_SUCCESS_IND, // Task executed sucessfully
    MCU_EXECUTE_FAIL_IND, // Task execution failed
    MCU_RED_LED_GPIO, // GP09 for LED RED as per LP 3.0
    MCU_ORANGE_LED_GPIO, // GP10 for LED ORANGE as per LP 3.0
    MCU_GREEN_LED_GPIO, // GP11 for LED GREEN as per LP 3.0
    MCU_ALL_LED_IND,
}

#[allow(non_camel_case_types)]
#[derive(Clone, Copy)]
pub enum LedEnum {
    NO_LED = 0x0,
    LED1 = 0x1, // RED LED D7/GP9/Pin64
    LED2 = 0x2, // ORANGE LED D6/GP10/Pin1
    LED3 = 0x4, // GREEN LED D5/GP11/Pin2
}

pub struct Board { }

impl Board {
    pub fn init() {
        unsafe {
            board_init();
        }
        SimpleLogger::init().unwrap();
        RTC::init();
    }

    pub fn test() {
        unsafe {
            cc3200_sys::board_test();
        }
    }

    pub fn led_configure(leds: &[LedEnum]) {
        let mut val = LedEnum::NO_LED as u8;
        for led in leds {
            val |= *led as u8;
        }
        unsafe {
            GPIO_IF_LedConfigure(val);
        }
    }

    pub fn led_off(led: LedName) {
        unsafe {
            GPIO_IF_LedOff(led as i8);
        }
    }

    pub fn led_on(led: LedName) {
        unsafe {
            GPIO_IF_LedOn(led as i8);
        }
    }

    pub fn start_scheduler() {
        unsafe {
            cc3200_sys::vTaskStartScheduler();
        }
    }

    pub fn disable_irq() {
        unsafe {
            asm!("cpsid i");
        }
    }

    pub fn reset() {
        unsafe {
            cc3200_sys::reset();
        }
    }
}

pub struct Console { }

impl Console {
    pub fn clear_term() {
        unsafe {
            cc3200_sys::ClearTerm();
        }
    }

    pub fn init_term() {
        unsafe {
            cc3200_sys::InitTerm();
        }
    }

    pub fn message(msg: &str) {
        for char in msg.chars() {
            // Lossy converstion from unicode to ASCII
            let ascii_char = {
                if char > '\x7f' { '?' } else { char }
            };
            unsafe {
                cc3200_sys::console_putchar(ascii_char as i8);
            }
        }
    }
}

impl core::fmt::Write for Console {
    fn write_str(&mut self, s: &str) -> core::fmt::Result {
        Console::message(s);
        Ok(())
    }
}

pub enum I2COpenMode {
    MasterModeStd = 0,
    MasterModeFst = 1,
}

static mut I2C_IS_OPEN: bool = false;
static I2C_SUCCESS: i32 = 0;

#[derive(Clone, Copy)]
pub struct I2C { }

impl I2C {
    pub fn open(mode: I2COpenMode) -> Option<Self> {
        unsafe {
            // Only allow one instance to be created in a given open mode.
            if I2C_IS_OPEN || I2C_IF_Open(mode as u32) != I2C_SUCCESS {
                return None;
            }
            I2C_IS_OPEN = true;
        }
        return Some(I2C {});
    }

    pub fn close(&self) {
        unsafe {
            // TODO: decide what to do if we never called I2C_IF_Open
            I2C_IF_Close();
            I2C_IS_OPEN = false;
        }
    }

    pub fn write(&self, addr: u8, data: &[u8], stop: u8) -> Result<(), ()> {
        if data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_Write(addr, data.as_ptr() as *mut u8, data.len() as u8, stop) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read(&self, addr: u8, data: &mut [u8]) -> Result<(), ()> {
        if data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_Read(addr, data.as_ptr() as *mut u8, data.len() as u8) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read_from_with_length(&self,
                                 addr: u8,
                                 wr_data: &[u8],
                                 rd_data: &mut [u8],
                                 rd_len: u8)
                                 -> Result<(), ()> {
        if wr_data.len() > 255 || rd_data.len() > 255 {
            return Err(());
        }
        unsafe {
            if I2C_IF_ReadFrom(addr,
                               wr_data.as_ptr() as *mut u8,
                               wr_data.len() as u8,
                               rd_data.as_ptr() as *mut u8,
                               rd_len) == I2C_SUCCESS {
                return Ok(());
            }
        }
        return Err(());
    }

    pub fn read_from(&self, addr: u8, wr_data: &[u8], rd_data: &mut [u8]) -> Result<(), ()> {
        let len = rd_data.len() as u8;
        self.read_from_with_length(addr, wr_data, rd_data, len)
    }
}

//
// Image updates
//

#[derive(Copy, Clone)]
pub enum ImageStatus {
    TESTING,
    TESTREADY,
    NOTEST
}

impl ImageStatus {
    pub fn from_u32(value: u32) -> Result<ImageStatus, ()> {
        let image_status = match value {
            IMG_STATUS_TESTING   => ImageStatus::TESTING,
            IMG_STATUS_TESTREADY => ImageStatus::TESTREADY,
            IMG_STATUS_NOTEST    => ImageStatus::NOTEST,
            value => {
                println!("unknwon image status {}", value);
                return Err(());
            }
        };
        Ok(image_status)
    }
    pub fn to_u32(image_status: ImageStatus) -> Result<u32, ()> {
        let value = match image_status {
            ImageStatus::NOTEST    => IMG_STATUS_NOTEST,
            ImageStatus::TESTREADY => IMG_STATUS_TESTREADY,
            ImageStatus::TESTING   => IMG_STATUS_TESTING
        };
        Ok(value)
    }
}

pub struct BootInfo {
    pub active_image: u8,
    pub image_status: ImageStatus,
}

impl BootInfo {

    /// Create a BootInfo structure
    pub fn new(active_image: u8, image_status: ImageStatus) -> BootInfo {
        BootInfo { active_image: active_image,
                   image_status: image_status }
    }

    /// Create a BootInfo structure the represents the factory reset
    pub fn factory_reset() -> BootInfo {
        BootInfo::new(0, ImageStatus::NOTEST)
    }

    /// Returns the currently active image's filename
    pub fn image_filename(&self) -> &'static str {
        match self.active_image {
            0 => IMG_FACTORY_DEFAULT,
            1 => IMG_USER_1,
            2 => IMG_USER_2,
            _ => IMG_FACTORY_DEFAULT
        }
    }

    /// Returns the filename of the image to update
    pub fn next_image_filename(&self) -> &'static str {
        // If we booted from image 1, we update image 2; in any other case
        // we update image 1. This mirrors the behavior of the TI SDK.
        match self.active_image {
            1 => IMG_USER_2,
            _ => IMG_USER_1
        }
    }
}

pub struct Update { }

impl Update {

    /// Sets the application to test mode
    pub fn test() -> bool {
        let res = unsafe {
            sl_extlib_FlcTest(FLC_TEST_RESET_MCU |
                              FLC_TEST_RESET_MCU_WITH_APP)
        };
        Update::reset_is_required(res)
    }

    /// Returns true if the application runs in testing mode, false otherwise
    pub fn is_testing() -> bool {
        let res = unsafe {
            sl_extlib_FlcIsPendingCommit()
        };
        res != 0
    }

    /// Commits all changes, moving the application state from 'testing' to 'stable'
    pub fn commit() -> bool {
        let res = unsafe {
            sl_extlib_FlcCommit(FLC_COMMITED)
        };
        Update::reset_is_required(res)
    }

    /// Aborts the update
    pub fn abort() -> bool {
        let res = unsafe {
            sl_extlib_FlcCommit(FLC_NOT_COMMITED)
        };
        Update::reset_is_required(res)
    }

    /// Reads or creates the device's boot-info structure
    pub fn get_boot_info() -> Result<BootInfo, ()> {
        let boot_info = match Update::read_boot_info() {
            Ok(boot_info) => boot_info,
            Err(_) => {
                let boot_info = BootInfo::factory_reset();
                match Update::write_boot_info(&boot_info) {
                    Ok(_)  => { },
                    Err(_) => { return Err(()); }
                };
                boot_info
            }
        };
        Ok(boot_info)
    }

    /// Opens the next image for updating; the filename is selected automatically
    pub fn next_image(max_len: usize) -> Result<File, SimpleLinkError> {
        // The TI filesystem doesn't resize files dynamically. Hence, if
        // the image file already exists and is too small, we cannot use
        // it for the update.
        //
        // Below, we read the boot-info file to get next image's filename and
        // its size. We remove the existing file if it's too small. The latter
        // call to File::create() will create a new file.
        let file_name = match Update::get_boot_info() {
            Ok(boot_info) => {
                let file_name = boot_info.next_image_filename();
                match File::get_info(file_name) {
                    Ok(file_info) => {
                        let allocated_length = file_info.allocated_length as usize;
                        if allocated_length < max_len {
                            File::remove(file_name)?;
                        }
                    },
                    Err(_) => {
                        // No file info available; unconditionally remove
                        // file if it exists.
                        ignore!(File::remove(file_name));
                    }
                };
                file_name
            },
            Err(_) => {
                return Result::Err(SimpleLinkError::FileSystem(FileSystemError::NOT_SUPPORTED))
            }
        };
        File::create(file_name, max_len, false)
    }

    fn reset_is_required(flags: i32) -> bool {
        (flags & (FLC_TEST_RESET_MCU | FLC_TEST_RESET_NWP)) != 0
    }

    fn encode_boot_info(boot_info: &BootInfo) -> Result<[u8; 8], ()> {
        let active_image = boot_info.active_image;
        let image_status = ImageStatus::to_u32(boot_info.image_status)?;
        let mut buf: [u8; 8] = [0; 8];
        buf[0] = active_image;
        buf[4] = 0xff & (image_status) as u8;
        buf[5] = 0xff & (image_status >> 8) as u8;
        buf[6] = 0xff & (image_status >> 16) as u8;
        buf[7] = 0xff & (image_status >> 24) as u8;
        Ok(buf)
    }

    fn decode_boot_info(buf: [u8; 8]) -> Result<BootInfo, ()> {
        let active_image = buf[0];
        let image_status = ((buf[4] as u32)) |
                           ((buf[5] as u32) << 8) |
                           ((buf[6] as u32) << 16) |
                           ((buf[7] as u32) << 24);
        Ok(BootInfo::new(active_image, ImageStatus::from_u32(image_status)?))
    }

    fn write_boot_info(boot_info: &BootInfo) -> Result<(), ()> {

        let buf = Update::encode_boot_info(boot_info)?;

        let mut file = match File::create(IMG_BOOT_INFO, 8, false) {
            Ok(file) => file,
            Err(_)   => { return Err(()); }
        };
        match file.write(&buf[..]) {
            Ok(buflen) => {
                if buflen < buf.len() {
                    return Err(());
                }
            },
            Err(_) => { return Err(()); }
        }
        Ok(())
    }

    fn read_boot_info() -> Result<BootInfo, ()> {
        let mut buf: [u8; 8] = [0; 8];
        let mut file = match File::open(IMG_BOOT_INFO) {
            Ok(file) => file,
            Err(_)   => return Err(())
        };
        match file.read(&mut buf) {
            Ok(buflen) => {
                if buflen != buf.len() {
                    return Err(());
                }
            },
            Err(_) => { return Err(()); }
        };
        Update::decode_boot_info(buf)
    }
}

pub struct Utils { }

impl Utils {
    pub fn delay(loops: u32) {
        unsafe {
            MAP_UtilsDelay(loops);
        }
    }
}

#[no_mangle]
pub unsafe extern "C" fn abort() {
    unimplemented!();
}
<|endoftext|>


<commit_before>use std::io::{Read, Write, BufReader, BufRead};
use std::sync::mpsc;

use serde_json;

use query::{Query, Response};

/// Read responses from the renderer process and send them back to the TurtleWindow
pub fn run<R: Read>(renderer_stdout: R, response_tx: mpsc::Sender<Response>) {
    let mut reader = BufReader::new(renderer_stdout);
    loop {
        let mut buffer = String::new();
        let read_bytes = reader.read_line(&mut buffer)
            .expect("bug: unable to read data from renderer process");
        if read_bytes == 0 {
            // Reached EOF, renderer process must have quit
            break;
        }

        let response: Result<Response, _> = serde_json::from_str(&buffer);
        match response {
            Ok(response) => match response_tx.send(response) {
                Ok(_) => {},
                // The main thread is no longer around, so quit
                Err(_) => break,
            },
            Err(err) => {
                if err.is_io() || err.is_syntax() || err.is_data() {
                    panic!("bug: failed to read response from renderer process");
                }
                else if err.is_eof() {
                    // Could not read anymore bytes from stdin, the renderer process must have ended
                    break;
                }
            },
        }
    }
}

/// Sends a query to the renderer process
pub fn send_query<W: Write>(mut renderer_stdin: W, query: &Query) -> Result<(), ()> {
    match serde_json::to_writer(&mut renderer_stdin, query) {
        Ok(_) => {
            writeln!(renderer_stdin)
                .expect("bug: unable to write final newline when sending query");
            Ok(())
        },
        Err(err) => {
            if err.is_io() || err.is_eof() {
                Err(())
            }
            else {
                // The other cases for err all have to do with input, so those should never occur
                unreachable!("bug: got an input error when writing output");
            }
        },
    }
}
<commit_msg>Ignoring unused items during tests in client.rs<commit_after>// During tests, we disable the renderer and that causes a bunch of warnings that we just want
// to get rid of.
// See Cargo.toml for an explanation of this attribute
#![cfg_attr(any(feature = "test", test), allow(dead_code, unused_variables))]

use std::io::{Read, Write, BufReader, BufRead};
use std::sync::mpsc;

use serde_json;

use query::{Query, Response};

/// Read responses from the renderer process and send them back to the TurtleWindow
pub fn run<R: Read>(renderer_stdout: R, response_tx: mpsc::Sender<Response>) {
    let mut reader = BufReader::new(renderer_stdout);
    loop {
        let mut buffer = String::new();
        let read_bytes = reader.read_line(&mut buffer)
            .expect("bug: unable to read data from renderer process");
        if read_bytes == 0 {
            // Reached EOF, renderer process must have quit
            break;
        }

        let response: Result<Response, _> = serde_json::from_str(&buffer);
        match response {
            Ok(response) => match response_tx.send(response) {
                Ok(_) => {},
                // The main thread is no longer around, so quit
                Err(_) => break,
            },
            Err(err) => {
                if err.is_io() || err.is_syntax() || err.is_data() {
                    panic!("bug: failed to read response from renderer process");
                }
                else if err.is_eof() {
                    // Could not read anymore bytes from stdin, the renderer process must have ended
                    break;
                }
            },
        }
    }
}

/// Sends a query to the renderer process
pub fn send_query<W: Write>(mut renderer_stdin: W, query: &Query) -> Result<(), ()> {
    match serde_json::to_writer(&mut renderer_stdin, query) {
        Ok(_) => {
            writeln!(renderer_stdin)
                .expect("bug: unable to write final newline when sending query");
            Ok(())
        },
        Err(err) => {
            if err.is_io() || err.is_eof() {
                Err(())
            }
            else {
                // The other cases for err all have to do with input, so those should never occur
                unreachable!("bug: got an input error when writing output");
            }
        },
    }
}
<|endoftext|>