<commit_before>#![feature(phase, slicing_syntax)]
#![allow(unused_must_use)]

#[phase(plugin)]
extern crate regex_macros;
extern crate regex;
extern crate core;
extern crate getopts;

use std::io::{stdin, stderr, BufferedWriter};
use std::io::stdio::{stdout_raw};
use std::os::{args, set_exit_status};
use std::{uint, str};

use getopts::{getopts, optopt, optflag, usage};

use Alignment::{Left, Right, Centered};

struct DynVec<T> {
    vec: Vec<T>,
    default: T,
}

impl<T: Clone> DynVec<T> {
    fn new(default: T) -> DynVec<T> {
        DynVec { vec: Vec::new(), default: default }
    }

    fn get(&self, i: uint) -> T {
        if i < self.vec.len() {
            self.vec[i].clone()
        } else {
            self.default.clone()
        }
    }

    fn set(&mut self, index: uint, v: T) {
        let l = self.vec.len();
        if index >= l {
            self.vec.grow(index - l + 1u, self.default.clone());
        }
        self.vec[index] = v
    }

    fn push(&mut self, v: T) {
        self.default = v.clone();
        self.vec.push(v);
    }
}

#[deriving(Clone)]
enum Alignment {
    Left,
    Right,
    Centered,
}

struct Opts {
    str_delim: char,
    out_sep:   Vec<u8>,
    until:     uint,
    unicode:   bool,
    align:     DynVec<Alignment>,
    max_width: DynVec<uint>,
}

fn parse_opts() -> Result<Opts, ()> {
    let args = args();
    let prog_name = &args[0];

    let opts = [
        optopt("o", "", "set the output separator", "output separator"),
        optopt("s", "", "set the string delimiter", "string delimiter"),
        optopt("u", "", "set the maximum column", "until"),
        optflag("U", "", "read as UTF8 and use unicode width"),
        optflag("h", "", "print this help menu"),
    ];
    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f);
            set_exit_status(1);
            return Err(());
        }
    };
    if matches.opt_present("h") {
        print!("{}", usage(prog_name[], &opts));
        return Err(());
    }
    let unicode = matches.opt_present("U");
    let out_sep = match matches.opt_str("o") {
        Some(s) => s.into_bytes(),
        None => " ".to_string().into_bytes(),
    };
    let str_delim = match matches.opt_str("s") {
        Some(s) => {
            match s.len() {
                0 => 0u8 as char,
                _ => s.as_bytes()[0] as char,
            }
        },
        None => '"',
    };
    let until = match matches.opt_str("u") {
        Some(s) => match s.parse() {
            Some(u) => u,
            None => {
                let _ = writeln!(&mut stderr(), "-u argument has to be a number");
                set_exit_status(1);
                return Err(());
            },
        },
        None => uint::MAX,
    };
    let mut align = DynVec::new(Left);
    let mut max_width = DynVec::new(0u);
    if matches.free.len() > 0 {
        let fmt = &matches.free[0];
        let test = regex!(r"(\d*)([<>=])");
        for c in test.captures_iter(fmt[]) {
            match c.at(1).unwrap() {
                p if p.len() > 0 => max_width.push(p.parse().unwrap()),
                _ => max_width.push(0),
            }
            match c.at(2).unwrap() {
                "<" => align.push(Left),
                ">" => align.push(Right),
                "=" => align.push(Centered),
                _ => unreachable!(),
            }
        }
        max_width.push(0);
    }
    Ok(Opts {
        str_delim: str_delim,
        out_sep: out_sep,
        until: until,
        unicode: unicode,
        align: align,
        max_width: max_width
    })
}

struct Words {
    line: Vec<u8>,
    words: Vec<(uint, uint)>,
}

impl Words {
    fn new(line: Vec<u8>, str_delim: char, until: uint) -> Words {
        let mut words = Vec::new();
        let mut pos = 0;
        loop {
            pos += match line[pos..].iter().position(|&c| !(c as char).is_whitespace()) {
                Some(i) => i,
                None => break,
            };
            if words.len() == until {
                let end = match line[pos..].iter().position(|&c| c == b'\n') {
                    Some(e) => pos + e,
                    None => line.len(),
                };
                words.push((pos, end));
                break;
            }
            let start = pos;
            let mut esc = false;
            let mut string = false;
            for (i, &c) in line[start..].iter().enumerate() {
                if !esc && c == str_delim as u8 {
                    string = !string;
                }
                esc = !esc && c == b'\\';
                if c == b'\n' || (!string && (c == b' ' || c == b'\t')) {
                    pos += i;
                    break;
                }
            }
            words.push((start, pos));
        }
        Words { line: line, words: words }
    }

    fn iter<'a>(&'a self) -> WordIter<'a> {
        WordIter {
            pos: 0,
            line: &self.line,
            words: &self.words,
        }
    }
}

struct WordIter<'a> {
    pos: uint,
    line: &'a Vec<u8>,
    words: &'a Vec<(uint, uint)>,
}

impl<'a> Iterator<&'a [u8]> for WordIter<'a> {
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.pos < self.words.len() {
            let (start, end) = self.words[self.pos];
            self.pos += 1;
            Some(self.line[start..end])
        } else {
            None
        }
    }
}

fn is_indent(c: u8) -> bool {
    c == b' ' || c == b'\t'
}

fn unsafe_byte_unicode_width(s: &[u8]) -> uint {
    unsafe { str::from_utf8_unchecked(s).width(false) }
}

fn read_as_bytes(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        let line = match stdin.read_until(b'\n') {
            Ok(l) => l,
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            if word.len() > opts.max_width.get(i) {
                opts.max_width.set(i, word.len());
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn read_as_unicode(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        // Unicode validation up here
        let line = match stdin.read_line() {
            Ok(l) => l.into_bytes(),
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            let width = unsafe_byte_unicode_width(word);
            if width > opts.max_width.get(i) {
                opts.max_width.set(i, width);
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn main() {
    let mut opts = match parse_opts() {
        Ok(o) => o,
        Err(..) => return,
    };

    let (indent, lines) = if opts.unicode {
        read_as_unicode(&mut opts)
    } else {
        read_as_bytes(&mut opts)
    };
    if lines.len() == 0 {
        return;
    }
    let indent = indent.unwrap();
    let padding = {
        let max_max_width = *opts.max_width.vec.iter().max().unwrap_or(&0);
        Vec::from_elem(max_max_width, b' ')
    };

    let mut stdout = BufferedWriter::new(stdout_raw());
    for line in lines.iter() {
        if line.words.len() > 0 {
            stdout.write(indent[]);
        }
        let mut words = line.iter().enumerate().peekable();
        while let Some((i, word)) = words.next() {
            let pad = opts.max_width.get(i) - if opts.unicode {
                unsafe_byte_unicode_width(word)
            } else {
                word.len()
            };
            match opts.align.get(i) {
                Left => {
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad]);
                    }
                },
                Right => {
                    stdout.write(padding[0..pad]);
                    stdout.write(word);
                },
                Centered => {
                    stdout.write(padding[0..pad/2]);
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad-pad/2]);
                    }
                },
            }
            if words.peek().is_some() {
                stdout.write(opts.out_sep[]);
            }
        }
        stdout.write_str("\n");
    }
}
<commit_msg>remove regex<commit_after>#![feature(slicing_syntax, macro_rules)]
#![allow(unused_must_use)]

extern crate getopts;

use std::io::{stdin, stderr, BufferedWriter};
use std::io::stdio::{stdout_raw};
use std::os::{args, set_exit_status};
use std::{uint, str};
use getopts::{getopts, optopt, optflag, usage};

use Alignment::{Left, Right, Centered};

struct DynVec<T> {
    vec: Vec<T>,
    default: T,
}

impl<T: Copy+Clone> DynVec<T> {
    fn new(default: T) -> DynVec<T> {
        DynVec { vec: Vec::new(), default: default }
    }

    fn get(&self, i: uint) -> T {
        if i < self.vec.len() {
            self.vec[i]
        } else {
            self.default
        }
    }

    fn set(&mut self, index: uint, v: T) {
        let l = self.vec.len();
        if index >= l {
            self.vec.grow(index - l + 1u, self.default);
        }
        self.vec[index] = v
    }

    fn push(&mut self, v: T) {
        self.default = v;
        self.vec.push(v);
    }
}

#[deriving(Copy, Clone)]
enum Alignment {
    Left,
    Right,
    Centered,
}

struct Opts {
    str_delim: char,
    out_sep:   Vec<u8>,
    until:     uint,
    unicode:   bool,
    align:     DynVec<Alignment>,
    max_width: DynVec<uint>,
}

macro_rules! err {
    ($fmt:expr $($arg:tt)*) => {{
        set_exit_status(1);
        writeln!(&mut stderr(), $fmt $($arg)*);
        return Err(());
    }}
}

fn parse_opts() -> Result<Opts, ()> {
    let args = args();
    let prog_name = &args[0];

    let opts = [
        optopt("o", "", "set the output separator", "output separator"),
        optopt("s", "", "set the string delimiter", "string delimiter"),
        optopt("u", "", "set the maximum column", "until"),
        optflag("U", "", "read as UTF8 and use unicode width"),
        optflag("h", "", "print this help menu"),
    ];
    let matches = match getopts(args.tail(), &opts) {
        Ok(m) => m,
        Err(f) => {
            println!("{}", f);
            set_exit_status(1);
            return Err(());
        }
    };
    if matches.opt_present("h") {
        print!("{}", usage(prog_name[], &opts));
        return Err(());
    }
    let unicode = matches.opt_present("U");
    let out_sep = match matches.opt_str("o") {
        Some(s) => s.into_bytes(),
        None => " ".to_string().into_bytes(),
    };
    let str_delim = match matches.opt_str("s") {
        Some(s) => {
            match s.len() {
                0 => 0u8 as char,
                _ => s.as_bytes()[0] as char,
            }
        },
        None => '"',
    };
    let until = match matches.opt_str("u") {
        Some(s) => match s.parse() {
            Some(u) => u,
            None => err!("-u argument has to be a number"),
        },
        None => uint::MAX,
    };
    let mut align = DynVec::new(Left);
    let mut max_width = DynVec::new(0u);
    if matches.free.len() > 0 {
        let mut fmt = matches.free[0][];
        while fmt.len() > 0 {
            let non_digit = match fmt.as_bytes().iter()
                                  .position(|&c| c < b'0' || c > b'9') {
                Some(i) => i,
                _ => err!("Invalid format sequence"),
            };
            if non_digit > 0 {
                match fmt[0..non_digit].parse() {
                    Some(i) => max_width.push(i),
                    _ => err!("Invalid format sequence"),
                }
            } else {
                max_width.push(0);
            }
            match fmt.as_bytes()[non_digit] {
                b'<' => align.push(Left),
                b'>' => align.push(Right),
                b'=' => align.push(Centered),
                _ => err!("Invalid format sequence"),
            }
            fmt = fmt[non_digit+1..];
        }
        max_width.push(0);
    }
    Ok(Opts {
        str_delim: str_delim,
        out_sep:   out_sep,
        until:     until,
        unicode:   unicode,
        align:     align,
        max_width: max_width
    })
}

struct Words {
    line: Vec<u8>,
    words: Vec<(uint, uint)>,
}

impl Words {
    fn new(line: Vec<u8>, str_delim: char, until: uint) -> Words {
        let mut words = Vec::new();
        let mut pos = 0;
        loop {
            pos += match line[pos..].iter().position(|&c| !(c as char).is_whitespace()) {
                Some(i) => i,
                None => break,
            };
            if words.len() == until {
                let end = match line[pos..].iter().position(|&c| c == b'\n') {
                    Some(e) => pos + e,
                    None => line.len(),
                };
                words.push((pos, end));
                break;
            }
            let start = pos;
            let mut esc = false;
            let mut string = false;
            for (i, &c) in line[start..].iter().enumerate() {
                if !esc && c == str_delim as u8 {
                    string = !string;
                }
                esc = !esc && c == b'\\';
                if c == b'\n' || (!string && (c == b' ' || c == b'\t')) {
                    pos += i;
                    break;
                }
            }
            words.push((start, pos));
        }
        Words { line: line, words: words }
    }

    fn iter<'a>(&'a self) -> WordIter<'a> {
        WordIter {
            pos: 0,
            line: &self.line,
            words: &self.words,
        }
    }
}

struct WordIter<'a> {
    pos: uint,
    line: &'a Vec<u8>,
    words: &'a Vec<(uint, uint)>,
}

impl<'a> Iterator<&'a [u8]> for WordIter<'a> {
    fn next(&mut self) -> Option<&'a [u8]> {
        if self.pos < self.words.len() {
            let (start, end) = self.words[self.pos];
            self.pos += 1;
            Some(self.line[start..end])
        } else {
            None
        }
    }
}

fn is_indent(c: u8) -> bool {
    c == b' ' || c == b'\t'
}

fn unsafe_byte_unicode_width(s: &[u8]) -> uint {
    unsafe { str::from_utf8_unchecked(s).width(false) }
}

fn read_as_bytes(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        let line = match stdin.read_until(b'\n') {
            Ok(l) => l,
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            if word.len() > opts.max_width.get(i) {
                opts.max_width.set(i, word.len());
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn read_as_unicode(opts: &mut Opts) -> (Option<Vec<u8>>, Vec<Words>) {
    let mut stdin = stdin();
    let mut indent: Option<Vec<u8>> = None;
    let mut lines = Vec::new();
    loop {
        // Unicode validation up here
        let line = match stdin.read_line() {
            Ok(l) => l.into_bytes(),
            Err(..) => break,
        };
        if indent.is_none() {
            let tmp = line.iter().map(|c| *c).take_while(|c| is_indent(*c)).collect();
            indent = Some(tmp);
        }
        let line = Words::new(line, opts.str_delim, opts.until);
        for (i, word) in line.iter().enumerate() {
            let width = unsafe_byte_unicode_width(word);
            if width > opts.max_width.get(i) {
                opts.max_width.set(i, width);
            }
        }
        lines.push(line);
    }
    (indent, lines)
}

fn main() {
    let mut opts = match parse_opts() {
        Ok(o) => o,
        Err(..) => return,
    };

    let (indent, lines) = if opts.unicode {
        read_as_unicode(&mut opts)
    } else {
        read_as_bytes(&mut opts)
    };
    if lines.len() == 0 {
        return;
    }
    let indent = indent.unwrap();
    let padding = {
        let max_max_width = *opts.max_width.vec.iter().max().unwrap_or(&0);
        Vec::from_elem(max_max_width, b' ')
    };

    let mut stdout = BufferedWriter::new(stdout_raw());
    for line in lines.iter() {
        if line.words.len() > 0 {
            stdout.write(indent[]);
        }
        let mut words = line.iter().enumerate().peekable();
        while let Some((i, word)) = words.next() {
            let pad = opts.max_width.get(i) - if opts.unicode {
                unsafe_byte_unicode_width(word)
            } else {
                word.len()
            };
            match opts.align.get(i) {
                Left => {
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad]);
                    }
                },
                Right => {
                    stdout.write(padding[0..pad]);
                    stdout.write(word);
                },
                Centered => {
                    stdout.write(padding[0..pad/2]);
                    stdout.write(word);
                    if words.peek().is_some() {
                        stdout.write(padding[0..pad-pad/2]);
                    }
                },
            }
            if words.peek().is_some() {
                stdout.write(opts.out_sep[]);
            }
        }
        stdout.write_str("\n");
    }
}
<|endoftext|>


<commit_before>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate serde_json;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate task_hookrs;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagtodo;

use std::process::exit;
use std::process::{Command, Stdio};
use std::io::stdin;
use std::io::BufRead;

use task_hookrs::import::{import_task, import_tasks};

use libimagrt::runtime::Runtime;
use libimagtodo::task::IntoTask;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;
fn main() {
    let name = "imag-todo";
    let version = &version!()[..];
    let about = "Interface with taskwarrior";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));

    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.unwrap_err());
            exit(1);
        }
    };

    match rt.cli().subcommand_name() {
        Some("tw-hook") => tw_hook(&rt),
        Some("list") => list(&rt),
        _ => unimplemented!(),
    } // end match scmd
} // end main

fn tw_hook(rt: &Runtime) {
    let subcmd = rt.cli().subcommand_matches("tw-hook").unwrap();
    if subcmd.is_present("add") {
        let stdin     = stdin();
        let mut stdin = stdin.lock();
        let mut line  = String::new();

        if let Err(e) = stdin.read_line(&mut line) {
            trace_error(&e);
            exit(1);
        };

        if let Ok(ttask) = import_task(&line.as_str()) {
            match serde_json::ser::to_string(&ttask) {
                Ok(val) => println!("{}", val),
                Err(e) => {
                    trace_error(&e);
                    exit(1);
                }
            }

            let uuid = *ttask.uuid();
            match ttask.into_filelockentry(rt.store()) {
                Ok(val) => {
                    println!("Task {} stored in imag", uuid);
                    val
                },
                Err(e) => {
                    trace_error(&e);
                    exit(1);
                }
            };
        } else {
            error!("No usable input");
            exit(1);
        }
    } else if subcmd.is_present("delete") {
        // The used hook is "on-modify". This hook gives two json-objects
        // per usage und wants one (the second one) back.
        let mut counter   = 0;
        let stdin         = stdin();
        let stdin         = stdin.lock();

        match import_tasks(stdin) {
            Ok(ttasks) => for ttask in ttasks {
                if counter % 2 == 1 {
                    // Only every second task is needed, the first one is the
                    // task before the change, and the second one after
                    // the change. The (maybe modified) second one is
                    // expected by taskwarrior.
                    match serde_json::ser::to_string(&ttask) {
                        Ok(val) => println!("{}", val),
                        Err(e) => {
                            trace_error(&e);
                            exit(1);
                        }
                    }

                    match ttask.status() {
                        &task_hookrs::status::TaskStatus::Deleted => {
                            match libimagtodo::delete::delete(rt.store(), *ttask.uuid()) {
                                Ok(_) => println!("Deleted task {}", *ttask.uuid()),
                                Err(e) => {
                                    trace_error(&e);
                                    exit(1);
                                }
                            }
                        }
                        _ => {
                        }
                    } // end match ttask.status()
                } // end if c % 2
                counter += 1;
            },
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
        }
    } else {
        // Should not be possible, as one argument is required via
        // ArgGroup
        unreachable!();
    }
}

fn list(rt: &Runtime) {
    let subcmd   = rt.cli().subcommand_matches("list").unwrap();
    let mut args = Vec::new();
    let verbose  = subcmd.is_present("verbose");
    let iter     = match libimagtodo::read::get_todo_iterator(rt.store()) {
        Err(e) => {
            trace_error(&e);
            exit(1);
        }
        Ok(val) => val,
    };

    for task in iter {
        match task {
            Ok(val) => {
                let uuid = match val.flentry.get_header().read("todo.uuid") {
                    Ok(Some(u)) => u,
                    Ok(None)    => continue,
                    Err(e)      => {
                        trace_error(&e);
                        continue;
                    }
                };

                if verbose {
                    args.clear();
                    args.push(format!("uuid:{}", uuid));
                    args.push(format!("{}", "information"));
                    let tw_process = Command::new("task").stdin(Stdio::null()).args(&args).spawn()
                        .unwrap_or_else(|e| {
                            trace_error(&e);
                            panic!("failed");
                        });
                    let output = tw_process.wait_with_output().unwrap_or_else(|e| {
                        panic!("failed to unwrap output: {}", e);
                    });
                    let outstring = String::from_utf8(output.stdout).unwrap_or_else(|e| {
                        panic!("failed to execute: {}", e);
                    });
                    println!("{}", outstring);
                } else {
                    println!("{}", match uuid {
                        toml::Value::String(s) => s,
                        _ => {
                            error!("Unexpected type for todo.uuid: {}", uuid);
                            continue;
                        },
                    });
                }
            }
            Err(e) => {
                trace_error(&e);
                continue;
            }
        } // end match task
    } // end for
}

<commit_msg>We do not need to String::push() here twice<commit_after>extern crate clap;
extern crate glob;
#[macro_use] extern crate log;
extern crate serde_json;
extern crate semver;
extern crate toml;
#[macro_use] extern crate version;

extern crate task_hookrs;

extern crate libimagrt;
extern crate libimagstore;
extern crate libimagerror;
extern crate libimagtodo;

use std::process::exit;
use std::process::{Command, Stdio};
use std::io::stdin;
use std::io::BufRead;

use task_hookrs::import::{import_task, import_tasks};

use libimagrt::runtime::Runtime;
use libimagtodo::task::IntoTask;
use libimagerror::trace::trace_error;

mod ui;

use ui::build_ui;
fn main() {
    let name = "imag-todo";
    let version = &version!()[..];
    let about = "Interface with taskwarrior";
    let ui = build_ui(Runtime::get_default_cli_builder(name, version, about));

    let rt = {
        let rt = Runtime::new(ui);
        if rt.is_ok() {
            rt.unwrap()
        } else {
            println!("Could not set up Runtime");
            println!("{:?}", rt.unwrap_err());
            exit(1);
        }
    };

    match rt.cli().subcommand_name() {
        Some("tw-hook") => tw_hook(&rt),
        Some("list") => list(&rt),
        _ => unimplemented!(),
    } // end match scmd
} // end main

fn tw_hook(rt: &Runtime) {
    let subcmd = rt.cli().subcommand_matches("tw-hook").unwrap();
    if subcmd.is_present("add") {
        let stdin     = stdin();
        let mut stdin = stdin.lock();
        let mut line  = String::new();

        if let Err(e) = stdin.read_line(&mut line) {
            trace_error(&e);
            exit(1);
        };

        if let Ok(ttask) = import_task(&line.as_str()) {
            match serde_json::ser::to_string(&ttask) {
                Ok(val) => println!("{}", val),
                Err(e) => {
                    trace_error(&e);
                    exit(1);
                }
            }

            let uuid = *ttask.uuid();
            match ttask.into_filelockentry(rt.store()) {
                Ok(val) => {
                    println!("Task {} stored in imag", uuid);
                    val
                },
                Err(e) => {
                    trace_error(&e);
                    exit(1);
                }
            };
        } else {
            error!("No usable input");
            exit(1);
        }
    } else if subcmd.is_present("delete") {
        // The used hook is "on-modify". This hook gives two json-objects
        // per usage und wants one (the second one) back.
        let mut counter   = 0;
        let stdin         = stdin();
        let stdin         = stdin.lock();

        match import_tasks(stdin) {
            Ok(ttasks) => for ttask in ttasks {
                if counter % 2 == 1 {
                    // Only every second task is needed, the first one is the
                    // task before the change, and the second one after
                    // the change. The (maybe modified) second one is
                    // expected by taskwarrior.
                    match serde_json::ser::to_string(&ttask) {
                        Ok(val) => println!("{}", val),
                        Err(e) => {
                            trace_error(&e);
                            exit(1);
                        }
                    }

                    match ttask.status() {
                        &task_hookrs::status::TaskStatus::Deleted => {
                            match libimagtodo::delete::delete(rt.store(), *ttask.uuid()) {
                                Ok(_) => println!("Deleted task {}", *ttask.uuid()),
                                Err(e) => {
                                    trace_error(&e);
                                    exit(1);
                                }
                            }
                        }
                        _ => {
                        }
                    } // end match ttask.status()
                } // end if c % 2
                counter += 1;
            },
            Err(e) => {
                trace_error(&e);
                exit(1);
            },
        }
    } else {
        // Should not be possible, as one argument is required via
        // ArgGroup
        unreachable!();
    }
}

fn list(rt: &Runtime) {
    let subcmd   = rt.cli().subcommand_matches("list").unwrap();
    let mut args = Vec::new();
    let verbose  = subcmd.is_present("verbose");
    let iter     = match libimagtodo::read::get_todo_iterator(rt.store()) {
        Err(e) => {
            trace_error(&e);
            exit(1);
        }
        Ok(val) => val,
    };

    for task in iter {
        match task {
            Ok(val) => {
                let uuid = match val.flentry.get_header().read("todo.uuid") {
                    Ok(Some(u)) => u,
                    Ok(None)    => continue,
                    Err(e)      => {
                        trace_error(&e);
                        continue;
                    }
                };

                if verbose {
                    args.clear();
                    args.push(format!("uuid:{} information", uuid));
                    let tw_process = Command::new("task").stdin(Stdio::null()).args(&args).spawn()
                        .unwrap_or_else(|e| {
                            trace_error(&e);
                            panic!("failed");
                        });
                    let output = tw_process.wait_with_output().unwrap_or_else(|e| {
                        panic!("failed to unwrap output: {}", e);
                    });
                    let outstring = String::from_utf8(output.stdout).unwrap_or_else(|e| {
                        panic!("failed to execute: {}", e);
                    });
                    println!("{}", outstring);
                } else {
                    println!("{}", match uuid {
                        toml::Value::String(s) => s,
                        _ => {
                            error!("Unexpected type for todo.uuid: {}", uuid);
                            continue;
                        },
                    });
                }
            }
            Err(e) => {
                trace_error(&e);
                continue;
            }
        } // end match task
    } // end for
}

<|endoftext|>


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

//! Suppose we have the following data structure in a smart contract:
//!
//! struct B {
//!   Map<String, String> mymap;
//! }
//!
//! struct A {
//!   B b;
//!   int my_int;
//! }
//!
//! struct C {
//!   List<int> mylist;
//! }
//!
//! A a;
//! C c;
//!
//! and the data belongs to Alice. Then an access to `a.b.mymap` would be translated to an access
//! to an entry in key-value store whose key is `<Alice>/a/b/mymap`. In the same way, the access to
//! `c.mylist` would need to query `<Alice>/c/mylist`.
//!
//! So an account stores its data in a directory structure, for example:
//!   <Alice>/balance:   10
//!   <Alice>/a/b/mymap: {"Bob" => "abcd", "Carol" => "efgh"}
//!   <Alice>/a/myint:   20
//!   <Alice>/c/mylist:  [3, 5, 7, 9]
//!
//! If someone needs to query the map above and find out what value associated with "Bob" is,
//! `address` will be set to Alice and `path` will be set to "/a/b/mymap/Bob".
//!
//! On the other hand, if you want to query only <Alice>/a/*, `address` will be set to Alice and
//! `path` will be set to "/a" and use the `get_prefix()` method from statedb

use crate::{
    account_address::AccountAddress,
    account_config::{ACCOUNT_RECEIVED_EVENT_PATH, ACCOUNT_SENT_EVENT_PATH},
};
use libra_crypto::hash::HashValue;
use move_core_types::language_storage::{ModuleId, ResourceKey, StructTag, CODE_TAG, RESOURCE_TAG};
#[cfg(any(test, feature = "fuzzing"))]
use proptest_derive::Arbitrary;
use serde::{Deserialize, Serialize};
use std::fmt;

#[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Ord, PartialOrd)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
pub struct AccessPath {
    pub address: AccountAddress,
    pub path: Vec<u8>,
}

impl AccessPath {
    pub const CODE_TAG: u8 = 0;
    pub const RESOURCE_TAG: u8 = 1;

    pub fn new(address: AccountAddress, path: Vec<u8>) -> Self {
        AccessPath { address, path }
    }

    /// Create an AccessPath to the event for the sender account in a deposit operation.
    /// The sent counter in LibraAccount.T (LibraAccount.T.sent_events_count) is used to generate
    /// the AccessPath.
    /// That AccessPath can be used as a key into the event storage to retrieve all sent
    /// events for a given account.
    pub fn new_for_sent_event(address: AccountAddress) -> Self {
        Self::new(address, ACCOUNT_SENT_EVENT_PATH.to_vec())
    }

    /// Create an AccessPath to the event for the target account (the receiver)
    /// in a deposit operation.
    /// The received counter in LibraAccount.T (LibraAccount.T.received_events_count) is used to
    /// generate the AccessPath.
    /// That AccessPath can be used as a key into the event storage to retrieve all received
    /// events for a given account.
    pub fn new_for_received_event(address: AccountAddress) -> Self {
        Self::new(address, ACCOUNT_RECEIVED_EVENT_PATH.to_vec())
    }

    pub fn resource_access_vec(tag: &StructTag) -> Vec<u8> {
        tag.access_vector()
    }

    /// Convert Accesses into a byte offset which would be used by the storage layer to resolve
    /// where fields are stored.
    pub fn resource_access_path(key: &ResourceKey) -> AccessPath {
        let path = AccessPath::resource_access_vec(&key.type_());
        AccessPath {
            address: key.address().to_owned(),
            path,
        }
    }

    fn code_access_path_vec(key: &ModuleId) -> Vec<u8> {
        key.access_vector()
    }

    pub fn code_access_path(key: &ModuleId) -> AccessPath {
        let path = AccessPath::code_access_path_vec(key);
        AccessPath {
            address: *key.address(),
            path,
        }
    }
}

impl fmt::Debug for AccessPath {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "AccessPath {{ address: {:x}, path: {} }}",
            self.address,
            hex::encode(&self.path)
        )
    }
}

impl fmt::Display for AccessPath {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.path.len() < 1 + HashValue::LENGTH {
            write!(f, "{:?}", self)
        } else {
            write!(f, "AccessPath {{ address: {:x}, ", self.address)?;
            match self.path[0] {
                RESOURCE_TAG => write!(f, "type: Resource, ")?,
                CODE_TAG => write!(f, "type: Module, ")?,
                tag => write!(f, "type: {:?}, ", tag)?,
            };
            write!(
                f,
                "hash: {:?}, ",
                hex::encode(&self.path[1..=HashValue::LENGTH])
            )?;
            write!(
                f,
                "suffix: {:?} }} ",
                String::from_utf8_lossy(&self.path[1 + HashValue::LENGTH..])
            )
        }
    }
}

impl From<&ModuleId> for AccessPath {
    fn from(id: &ModuleId) -> AccessPath {
        AccessPath {
            address: *id.address(),
            path: id.access_vector(),
        }
    }
}
<commit_msg>Removing new_for_sent_event from types/src/access_path.rs<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

//! Suppose we have the following data structure in a smart contract:
//!
//! struct B {
//!   Map<String, String> mymap;
//! }
//!
//! struct A {
//!   B b;
//!   int my_int;
//! }
//!
//! struct C {
//!   List<int> mylist;
//! }
//!
//! A a;
//! C c;
//!
//! and the data belongs to Alice. Then an access to `a.b.mymap` would be translated to an access
//! to an entry in key-value store whose key is `<Alice>/a/b/mymap`. In the same way, the access to
//! `c.mylist` would need to query `<Alice>/c/mylist`.
//!
//! So an account stores its data in a directory structure, for example:
//!   <Alice>/balance:   10
//!   <Alice>/a/b/mymap: {"Bob" => "abcd", "Carol" => "efgh"}
//!   <Alice>/a/myint:   20
//!   <Alice>/c/mylist:  [3, 5, 7, 9]
//!
//! If someone needs to query the map above and find out what value associated with "Bob" is,
//! `address` will be set to Alice and `path` will be set to "/a/b/mymap/Bob".
//!
//! On the other hand, if you want to query only <Alice>/a/*, `address` will be set to Alice and
//! `path` will be set to "/a" and use the `get_prefix()` method from statedb

use crate::{
    account_address::AccountAddress,
    account_config::{ACCOUNT_RECEIVED_EVENT_PATH, ACCOUNT_SENT_EVENT_PATH},
};
use libra_crypto::hash::HashValue;
use move_core_types::language_storage::{ModuleId, ResourceKey, StructTag, CODE_TAG, RESOURCE_TAG};
#[cfg(any(test, feature = "fuzzing"))]
use proptest_derive::Arbitrary;
use serde::{Deserialize, Serialize};
use std::fmt;

#[derive(Clone, Eq, PartialEq, Hash, Serialize, Deserialize, Ord, PartialOrd)]
#[cfg_attr(any(test, feature = "fuzzing"), derive(Arbitrary))]
pub struct AccessPath {
    pub address: AccountAddress,
    pub path: Vec<u8>,
}

impl AccessPath {
    pub const CODE_TAG: u8 = 0;
    pub const RESOURCE_TAG: u8 = 1;

    pub fn new(address: AccountAddress, path: Vec<u8>) -> Self {
        AccessPath { address, path }
    }

    pub fn resource_access_vec(tag: &StructTag) -> Vec<u8> {
        tag.access_vector()
    }

    /// Convert Accesses into a byte offset which would be used by the storage layer to resolve
    /// where fields are stored.
    pub fn resource_access_path(key: &ResourceKey) -> AccessPath {
        let path = AccessPath::resource_access_vec(&key.type_());
        AccessPath {
            address: key.address().to_owned(),
            path,
        }
    }

    fn code_access_path_vec(key: &ModuleId) -> Vec<u8> {
        key.access_vector()
    }

    pub fn code_access_path(key: &ModuleId) -> AccessPath {
        let path = AccessPath::code_access_path_vec(key);
        AccessPath {
            address: *key.address(),
            path,
        }
    }
}

impl fmt::Debug for AccessPath {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "AccessPath {{ address: {:x}, path: {} }}",
            self.address,
            hex::encode(&self.path)
        )
    }
}

impl fmt::Display for AccessPath {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if self.path.len() < 1 + HashValue::LENGTH {
            write!(f, "{:?}", self)
        } else {
            write!(f, "AccessPath {{ address: {:x}, ", self.address)?;
            match self.path[0] {
                RESOURCE_TAG => write!(f, "type: Resource, ")?,
                CODE_TAG => write!(f, "type: Module, ")?,
                tag => write!(f, "type: {:?}, ", tag)?,
            };
            write!(
                f,
                "hash: {:?}, ",
                hex::encode(&self.path[1..=HashValue::LENGTH])
            )?;
            write!(
                f,
                "suffix: {:?} }} ",
                String::from_utf8_lossy(&self.path[1 + HashValue::LENGTH..])
            )
        }
    }
}

impl From<&ModuleId> for AccessPath {
    fn from(id: &ModuleId) -> AccessPath {
        AccessPath {
            address: *id.address(),
            path: id.access_vector(),
        }
    }
}
<|endoftext|>


<commit_before>use std::ptr;

use env::NapiEnv;
use result::NapiResult;
use sys;

mod array;
mod boolean;
mod number;
mod object;
mod string;
mod undefined;

pub use self::array::NapiArray;
pub use self::boolean::NapiBoolean;
pub use self::number::NapiNumber;
pub use self::object::NapiObject;
pub use self::string::NapiString;
pub use self::undefined::NapiUndefined;

macro_rules! coercion_method {
    ($name:ident, $type:ident, $napi_fn:expr) => {
        fn $name(&self, env: &NapiEnv) -> NapiResult<$type> {
            let mut value = ptr::null_mut();
            let status = unsafe {
                $napi_fn(
                    env.as_sys_env(),
                    self.as_sys_value(),
                    &mut value,
                )
            };
            env.handle_status(status)?;
            Ok($type::from_sys_value(value))
        }
    }
}

pub trait NapiValue {
    fn as_sys_value(&self) -> sys::napi_value;
    fn from_sys_value(value: sys::napi_value) -> Self;

    coercion_method!(to_napi_boolean, NapiBoolean, sys::napi_coerce_to_bool);
    coercion_method!(to_napi_number, NapiNumber, sys::napi_coerce_to_number);
    coercion_method!(to_napi_object, NapiObject, sys::napi_coerce_to_object);
    coercion_method!(to_napi_string, NapiString, sys::napi_coerce_to_string);
}
<commit_msg>refactor(napi): get rid of a macro in value/mod.rs<commit_after>use std::ptr;

use env::NapiEnv;
use result::NapiResult;
use sys;

mod array;
mod boolean;
mod number;
mod object;
mod string;
mod undefined;

pub use self::array::NapiArray;
pub use self::boolean::NapiBoolean;
pub use self::number::NapiNumber;
pub use self::object::NapiObject;
pub use self::string::NapiString;
pub use self::undefined::NapiUndefined;

fn coerce<T, U>(
    value: &T,
    env: &NapiEnv,
    napi_fn: unsafe extern "C" fn(
        sys::napi_env,
        sys::napi_value,
        *mut sys::napi_value,
    ) -> sys::napi_status,
) -> NapiResult<U>
where
    T: NapiValue + ?Sized,
    U: NapiValue,
{
    let mut coerced_value = ptr::null_mut();

    env.handle_status(unsafe {
        napi_fn(env.as_sys_env(), value.as_sys_value(), &mut coerced_value)
    })?;

    Ok(U::from_sys_value(coerced_value))
}

pub trait NapiValue {
    fn as_sys_value(&self) -> sys::napi_value;
    fn from_sys_value(value: sys::napi_value) -> Self;

    fn to_napi_boolean(&self, env: &NapiEnv) -> NapiResult<NapiBoolean> {
        coerce(self, env, sys::napi_coerce_to_bool)
    }

    fn to_napi_number(&self, env: &NapiEnv) -> NapiResult<NapiNumber> {
        coerce(self, env, sys::napi_coerce_to_number)
    }

    fn to_napi_object(&self, env: &NapiEnv) -> NapiResult<NapiObject> {
        coerce(self, env, sys::napi_coerce_to_object)
    }

    fn to_napi_string(&self, env: &NapiEnv) -> NapiResult<NapiString> {
        coerce(self, env, sys::napi_coerce_to_string)
    }
}
<|endoftext|>


<commit_before>extern crate rand;
extern crate serde_json;

use utils::error;
use std::collections::HashMap;
use api::CxsStateType;
use rand::Rng;
use std::sync::Mutex;

lazy_static! {
    static ref CONNECTION_MAP: Mutex<HashMap<u32, Box<Connection>>> = Default::default();
}

#[derive(Serialize, Deserialize)]
struct Connection {
    info: String,
    handle: u32,
    did: String,
    did_endpoint: String,
    wallet: String,
    state: CxsStateType,
}

pub fn build_connection (info_string: String) -> u32 {
    let new_handle = rand::thread_rng().gen::<u32>();

    let c = Box::new(Connection {
            info: info_string,
            handle: new_handle,
            did: String::new(),
            did_endpoint: String::new(),
            wallet: String::new(),
            state: CxsStateType::CxsStateInitialized,
        });

    let mut m = CONNECTION_MAP.lock().unwrap();
    m.insert(new_handle, c);

    new_handle
}

impl Connection {
    fn connect(&mut self) -> u32 { self.state = CxsStateType::CxsStateOfferSent; error::SUCCESS.code_num }
    fn get_state(&self) -> u32 { let state = self.state as u32; state }
}

impl Drop for Connection {
    fn drop(&mut self) {}
}

pub fn get_state(handle: u32) -> u32 {
    let m = CONNECTION_MAP.lock().unwrap();
    let result = m.get(&handle);

    let rc = match result {
        Some(t) => t.get_state(),
        None => CxsStateType::CxsStateNone as u32,
    };

    rc
}

pub fn connect(handle: u32) -> u32 {
    let mut m = CONNECTION_MAP.lock().unwrap();
    let result = m.get_mut(&handle);

    let rc = match result {
       Some(t) => t.connect(),
       None => error::UNKNOWN_ERROR.code_num,
    };

    rc
}

pub fn to_string(handle:u32) -> String {
    let m = CONNECTION_MAP.lock().unwrap();
    let result = m.get(&handle);

    let connection_json = match result {
        Some(t) => serde_json::to_string(&t).unwrap(),
        None => String::new(),
    };

    connection_json.to_owned()
}

#[allow(unused_variables)]
pub fn release(handle:u32) -> u32 {
    let mut m = CONNECTION_MAP.lock().unwrap();
    let result = m.remove(&handle);

    let rc = match result {
        Some(t) => error::SUCCESS.code_num,
        None => error::UNKNOWN_ERROR.code_num,
    };

    rc
}

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

    #[test]
    fn test_create_connection() {
        let handle = build_connection("Whatever".to_owned());

        assert!(handle > 0);

        release(handle);
    }

    #[test]
    fn test_connection_release() {
        let handle = build_connection("Whatever".to_owned());

        assert!(handle > 0);

        let rc = release(handle);

        assert_eq!(rc, error::SUCCESS.code_num);
    }

    #[test]
    fn test_connect() {
        let handle = build_connection("Whatever".to_owned());

        assert!(handle > 0);

        let rc = connect(handle);

        assert_eq!(rc, error::SUCCESS.code_num);

        let state = get_state(handle);

        assert_eq!(state, CxsStateType::CxsStateOfferSent as u32);
        release(handle);
    }

    #[test]
    fn test_connect_fails() {
        // Need to add content here once we've implemented connected
        assert_eq!(0,0);
    }

    #[test]
    fn test_connection_release_fails() {
        let rc = release(1);

        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);
    }

    #[test]
    fn test_get_state() {
        let handle = build_connection("Whatever".to_owned());

        let state = get_state(handle);

        assert_eq!(state, CxsStateType::CxsStateInitialized as u32);
        release(handle);
    }

    #[test]
    fn test_get_state_fails() {
        let state = get_state(1);

        assert_eq!(state, CxsStateType::CxsStateNone as u32);
    }

    #[test]
    fn test_get_string_fails() {
        let string = to_string(1);

        assert_eq!(string.len(), 0);
    }

    #[test]
    fn test_get_string() {
        let handle = build_connection("".to_owned());

        let string = to_string(handle);

        println!("string: {}", string);
        assert!(string.len() > 10);
        release(handle);
    }

    #[test]
    fn test_many_handles() {

        let handle1 = build_connection("handle1".to_owned());
        let handle2 = build_connection("handle2".to_owned());
        let handle3 = build_connection("handle3".to_owned());
        let handle4 = build_connection("handle4".to_owned());
        let handle5 = build_connection("handle5".to_owned());

        connect(handle1);
        connect(handle2);
        connect(handle3);
        connect(handle4);
        connect(handle5);

        let data1 = to_string(handle1);
        let data2 = to_string(handle2);
        let data3 = to_string(handle3);
        let data4 = to_string(handle4);
        let data5 = to_string(handle5);

        println!("handle1: {}", data1);
        println!("handle2: {}", data2);
        println!("handle3: {}", data3);
        println!("handle4: {}", data4);
        println!("handle5: {}", data5);

        release(handle1);
        release(handle2);
        release(handle3);
        release(handle4);
        release(handle5);

        /* This only works when you run "cargo test -- --test-threads=1 */
        //let m = CONNECTION_MAP.lock().unwrap();
        //assert_eq!(0,m.len());
    }
}
<commit_msg>ensure unique connections during creation (#17)<commit_after>extern crate rand;
extern crate serde_json;

use utils::error;
use std::collections::HashMap;
use api::CxsStateType;
use rand::Rng;
use std::sync::Mutex;

lazy_static! {
    static ref CONNECTION_MAP: Mutex<HashMap<u32, Box<Connection>>> = Default::default();
}

#[derive(Serialize, Deserialize)]
struct Connection {
    info: String,
    handle: u32,
    did: String,
    did_endpoint: String,
    wallet: String,
    state: CxsStateType,
}

fn find_connection(info_string: &str) -> u32 {
    let connection_table = CONNECTION_MAP.lock().unwrap();

    for (handle, connection) in connection_table.iter() {
        if connection.info == info_string {
            return *handle;
        }
    };

    return 0;
}

pub fn build_connection (info_string: String) -> u32 {
    // Check to make sure info_string is unique
    let new_handle = find_connection(&info_string);

    if new_handle > 0 {return new_handle}

    // This is a new connection
    let new_handle = rand::thread_rng().gen::<u32>();

    let c = Box::new(Connection {
            info: info_string,
            handle: new_handle,
            did: String::new(),
            did_endpoint: String::new(),
            wallet: String::new(),
            state: CxsStateType::CxsStateInitialized,
        });

    let mut m = CONNECTION_MAP.lock().unwrap();
    m.insert(new_handle, c);

    new_handle
}

impl Connection {
    fn connect(&mut self) -> u32 {
        //TODO: check current state is valid for initiating connection
        self.state = CxsStateType::CxsStateOfferSent;
        error::SUCCESS.code_num
    }

    fn get_state(&self) -> u32 { let state = self.state as u32; state }
}

impl Drop for Connection {
    fn drop(&mut self) {}
}

pub fn get_state(handle: u32) -> u32 {
    let m = CONNECTION_MAP.lock().unwrap();
    let result = m.get(&handle);

    let rc = match result {
        Some(t) => t.get_state(),
        None => CxsStateType::CxsStateNone as u32,
    };

    rc
}

pub fn connect(handle: u32) -> u32 {
    let mut m = CONNECTION_MAP.lock().unwrap();
    let result = m.get_mut(&handle);

    let rc = match result {
       Some(t) => t.connect(),
       None => error::UNKNOWN_ERROR.code_num,
    };

    rc
}

pub fn to_string(handle:u32) -> String {
    let m = CONNECTION_MAP.lock().unwrap();
    let result = m.get(&handle);

    let connection_json = match result {
        Some(t) => serde_json::to_string(&t).unwrap(),
        None => String::new(),
    };

    connection_json.to_owned()
}

#[allow(unused_variables)]
pub fn release(handle:u32) -> u32 {
    let mut m = CONNECTION_MAP.lock().unwrap();
    let result = m.remove(&handle);

    let rc = match result {
        Some(t) => error::SUCCESS.code_num,
        None => error::UNKNOWN_ERROR.code_num,
    };

    rc
}

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

    #[test]
    fn test_create_connection() {
        let handle = build_connection("Whatever".to_owned());

        assert!(handle > 0);

        release(handle);
    }

    #[test]
    fn test_create_idempotency() {
        let handle = build_connection("Whatever".to_owned());
        let handle2 = build_connection("Whatever".to_owned());
        assert_eq!(handle,handle2);
    }

    #[test]
    fn test_connection_release() {
        let handle = build_connection("Whatever".to_owned());

        assert!(handle > 0);

        let rc = release(handle);

        assert_eq!(rc, error::SUCCESS.code_num);
    }

    #[test]
    fn test_connect() {
        let handle = build_connection("Whatever".to_owned());

        assert!(handle > 0);

        let rc = connect(handle);

        assert_eq!(rc, error::SUCCESS.code_num);

        let state = get_state(handle);

        assert_eq!(state, CxsStateType::CxsStateOfferSent as u32);
        release(handle);
    }

    #[test]
    fn test_connect_fails() {
        // Need to add content here once we've implemented connected
        assert_eq!(0,0);
    }

    #[test]
    fn test_connection_release_fails() {
        let rc = release(1);

        assert_eq!(rc, error::UNKNOWN_ERROR.code_num);
    }

    #[test]
    fn test_get_state() {
        let handle = build_connection("Whatever".to_owned());

        let state = get_state(handle);

        assert_eq!(state, CxsStateType::CxsStateInitialized as u32);
        release(handle);
    }

    #[test]
    fn test_get_state_fails() {
        let state = get_state(1);

        assert_eq!(state, CxsStateType::CxsStateNone as u32);
    }

    #[test]
    fn test_get_string_fails() {
        let string = to_string(1);

        assert_eq!(string.len(), 0);
    }

    #[test]
    fn test_get_string() {
        let handle = build_connection("".to_owned());

        let string = to_string(handle);

        println!("string: {}", string);
        assert!(string.len() > 10);
        release(handle);
    }

    #[test]
    fn test_many_handles() {

        let handle1 = build_connection("handle1".to_owned());
        let handle2 = build_connection("handle2".to_owned());
        let handle3 = build_connection("handle3".to_owned());
        let handle4 = build_connection("handle4".to_owned());
        let handle5 = build_connection("handle5".to_owned());

        connect(handle1);
        connect(handle2);
        connect(handle3);
        connect(handle4);
        connect(handle5);

        let data1 = to_string(handle1);
        let data2 = to_string(handle2);
        let data3 = to_string(handle3);
        let data4 = to_string(handle4);
        let data5 = to_string(handle5);

        println!("handle1: {}", data1);
        println!("handle2: {}", data2);
        println!("handle3: {}", data3);
        println!("handle4: {}", data4);
        println!("handle5: {}", data5);

        release(handle1);
        release(handle2);
        release(handle3);
        release(handle4);
        release(handle5);

        /* This only works when you run "cargo test -- --test-threads=1 */
        //let m = CONNECTION_MAP.lock().unwrap();
        //assert_eq!(0,m.len());
    }
}
<|endoftext|>


<commit_before>// /// Reference to the material icon font.
pub const MATERIAL_ICONS_REGULAR_FONT: &[u8] = include_bytes!("MaterialIcons-Regular.ttf");
pub const ROBOTO_REGULAR_FONT: &[u8] = include_bytes!("Roboto-Regular.ttf");

pub const ROBOTO_MEDIUM_FONT: &[u8] = include_bytes!("Roboto-Medium.ttf");

// font sizes
pub const FONT_SIZE_12: f64 = 12.0;

// icon sizes
pub const ICON_FONT_SIZE_12: f64 = 12.0;
<commit_msg>fonts: update and documenting new font identifier<commit_after>/// The 'Material Design Icons' is the official icon set from Google.
/// The icons are designed under the material design guidelines.
/// Because the official repository is no longer maintained from Google,
/// source code is now maintained and hosted at:
/// https://github.com/material-icons/material-icons-font
/// Package-Info: package.json

// TL;DR
// https://stackoverflow.com/questions/11002820/why-should-we-include-ttf-eot-woff-svg-in-a-font-face
// ... woff2 gets drafted and accepted, which improves the compression
// leading to even smaller files, along with the ability to load a single font
// "in parts" so that a font that supports 20 scripts can be stored as "chunks"
// on disk instead, with browsers automatically able to load the font "in parts"
// as needed, rather than needing to transfer the entire font up front, further
// improving the typesetting experience.
// If you don't want to support IE 8 and lower, and iOS 4 and lower,
// and android 4.3 or earlier, then you can just use WOFF
// (and WOFF2, a more highly compressed WOFF, for the newest browsers that support it.)

// Reference to the material icon fonts.
pub const MATERIAL_ICONS_FONT_TTF: &[u8] = include_bytes!("MaterialIcons.ttf");
pub const MATERIAL_ICONS_REGULAR_FONT: &[u8] = include_bytes!("MaterialIcons-Regular.ttf");

pub const MATERIAL_ICONS_FONT: &[u8] = include_bytes!("MaterialIcons.woff2");
pub const MATERIAL_ICONS_OUTLINED_FONT: &[u8] = include_bytes!("MaterialIcons-Outlined.woff2");
pub const MATERIAL_ICONS_ROUND_FONT: &[u8] = include_bytes!("MaterialIcons-Round.woff2");
pub const MATERIAL_ICONS_SHARP_FONT: &[u8] = include_bytes!("MaterialIcons-Sharp.woff2");
pub const MATERIAL_ICONS_TWOTONE_FONT: &[u8] = include_bytes!("MaterialIcons-TwoTone.woff2");

// Reference to the roboto fonts.
pub const ROBOTO_REGULAR_FONT: &[u8] = include_bytes!("Roboto-Regular.ttf");
pub const ROBOTO_MEDIUM_FONT: &[u8] = include_bytes!("Roboto-Medium.ttf");

// font sizes
pub const FONT_SIZE_12: f64 = 12.0;

// icon sizes
pub const ICON_FONT_SIZE_12: f64 = 12.0;
<|endoftext|>


<commit_before>// Copyright 2012-2013 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.

//! Helper functions corresponding to lifetime errors due to
//! anonymous regions.
use hir;
use infer::InferCtxt;
use ty::{self, Region, Ty};
use hir::def_id::DefId;
use hir::map as hir_map;
use syntax_pos::Span;

macro_rules! or_false {
     ($v:expr) => {
         match $v {
             Some(v) => v,
             None => {
                 debug!("or_false failed: {}", stringify!($v));
                 return false;
             }
         }
     }
}

// The struct contains the information about the anonymous region
// we are searching for.
#[derive(Debug)]
pub struct AnonymousArgInfo<'tcx> {
    // the argument corresponding to the anonymous region
    pub arg: &'tcx hir::Arg,
    // the type corresponding to the anonymopus region argument
    pub arg_ty: Ty<'tcx>,
    // the ty::BoundRegion corresponding to the anonymous region
    pub bound_region: ty::BoundRegion,
    // corresponds to id the argument is the first parameter
    // in the declaration
    pub is_first: bool,
}

// This struct contains information regarding the
// Refree((FreeRegion) corresponding to lifetime conflict
#[derive(Debug)]
pub struct FreeRegionInfo {
    // def id corresponding to FreeRegion
    pub def_id: DefId,
    // the bound region corresponding to FreeRegion
    pub boundregion: ty::BoundRegion,
    // checks if bound region is in Impl Item
    pub is_impl_item: bool,
}

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
    // This method walks the Type of the function body arguments using
    // `fold_regions()` function and returns the
    // &hir::Arg of the function argument corresponding to the anonymous
    // region and the Ty corresponding to the named region.
    // Currently only the case where the function declaration consists of
    // one named region and one anonymous region is handled.
    // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32`
    // Here, we would return the hir::Arg for y, we return the type &'a
    // i32, which is the type of y but with the anonymous region replaced
    // with 'a, the corresponding bound region and is_first which is true if
    // the hir::Arg is the first argument in the function declaration.
    pub fn find_arg_with_region(&self,
                                anon_region: Region<'tcx>,
                                replace_region: Region<'tcx>)
                                -> Option<AnonymousArgInfo> {

        let (id, bound_region) = match *anon_region {
            ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
            ty::ReEarlyBound(ref ebr) => {
                (self.tcx.parent_def_id(ebr.def_id).unwrap(),
                 ty::BoundRegion::BrNamed(ebr.def_id, ebr.name))
            }
            _ => return None, // not a free region
        };

        let hir = &self.tcx.hir;
        if let Some(node_id) = hir.as_local_node_id(id) {
            if let Some(body_id) = hir.maybe_body_owned_by(node_id) {
                let body = hir.body(body_id);
                if let Some(tables) = self.in_progress_tables {
                    body.arguments
                        .iter()
                        .enumerate()
                        .filter_map(|(index, arg)| {
                            // May return None; sometimes the tables are not yet populated.
                            let ty = tables.borrow().node_id_to_type_opt(arg.hir_id)?;
                            let mut found_anon_region = false;
                            let new_arg_ty = self.tcx
                                .fold_regions(&ty, &mut false, |r, _| if *r == *anon_region {
                                    found_anon_region = true;
                                    replace_region
                                } else {
                                    r
                                });
                            if found_anon_region {
                                let is_first = index == 0;
                                Some(AnonymousArgInfo {
                                         arg: arg,
                                         arg_ty: new_arg_ty,
                                         bound_region: bound_region,
                                         is_first: is_first,
                                     })
                            } else {
                                None
                            }
                        })
                        .next()
                } else {
                    None
                }
            } else {
                None
            }
        } else {
            None
        }
    }

    // This method returns the DefId and the BoundRegion corresponding to the given region.
    pub fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {

        let (suitable_region_binding_scope, bound_region) = match *region {
            ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
            ty::ReEarlyBound(ref ebr) => {
                (self.tcx.parent_def_id(ebr.def_id).unwrap(),
                 ty::BoundRegion::BrNamed(ebr.def_id, ebr.name))
            }
            _ => return None, // not a free region
        };

        let node_id = self.tcx
            .hir
            .as_local_node_id(suitable_region_binding_scope)
            .unwrap();
        let is_impl_item = match self.tcx.hir.find(node_id) {

            Some(hir_map::NodeItem(..)) |
            Some(hir_map::NodeTraitItem(..)) => false,
            Some(hir_map::NodeImplItem(..)) => {
                self.is_bound_region_in_impl_item(suitable_region_binding_scope)
            }
            _ => return None,
        };

        return Some(FreeRegionInfo {
                        def_id: suitable_region_binding_scope,
                        boundregion: bound_region,
                        is_impl_item: is_impl_item,
                    });

    }

    // Here, we check for the case where the anonymous region
    // is in the return type.
    // FIXME(#42703) - Need to handle certain cases here.
    pub fn is_return_type_anon(&self,
                               scope_def_id: DefId,
                               br: ty::BoundRegion,
                               decl: &hir::FnDecl)
                               -> Option<Span> {
        let ret_ty = self.tcx.type_of(scope_def_id);
        match ret_ty.sty {
            ty::TyFnDef(_, _) => {
                let sig = ret_ty.fn_sig(self.tcx);
                let late_bound_regions = self.tcx
                    .collect_referenced_late_bound_regions(&sig.output());
                if late_bound_regions.iter().any(|r| *r == br) {
                    return Some(decl.output.span());
                }
            }
            _ => {}
        }
        None
    }
    // Here we check for the case where anonymous region
    // corresponds to self and if yes, we display E0312.
    // FIXME(#42700) - Need to format self properly to
    // enable E0621 for it.
    pub fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool {
        is_first &&
        self.tcx
            .opt_associated_item(scope_def_id)
            .map(|i| i.method_has_self_argument) == Some(true)
    }

    // Here we check if the bound region is in Impl Item.
    pub fn is_bound_region_in_impl_item(&self, suitable_region_binding_scope: DefId) -> bool {
        let container_id = self.tcx
            .associated_item(suitable_region_binding_scope)
            .container
            .id();
        if self.tcx.impl_trait_ref(container_id).is_some() {
            // For now, we do not try to target impls of traits. This is
            // because this message is going to suggest that the user
            // change the fn signature, but they may not be free to do so,
            // since the signature must match the trait.
            //
            // FIXME(#42706) -- in some cases, we could do better here.
            return true;
        }
        false
    }

    // This method returns whether the given Region is Named
    pub fn is_named_region(&self, region: Region<'tcx>) -> bool {
        match *region {
            ty::ReFree(ref free_region) => {
                match free_region.bound_region {
                    ty::BrNamed(..) => true,
                    _ => false,
                }
            }
            ty::ReEarlyBound(_) => true,
            _ => false,
        }
    }
}
<commit_msg>make `util` fns private to nice_region_error<commit_after>// Copyright 2012-2013 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.

//! Helper functions corresponding to lifetime errors due to
//! anonymous regions.
use hir;
use infer::InferCtxt;
use ty::{self, Region, Ty};
use hir::def_id::DefId;
use hir::map as hir_map;
use syntax_pos::Span;

macro_rules! or_false {
     ($v:expr) => {
         match $v {
             Some(v) => v,
             None => {
                 debug!("or_false failed: {}", stringify!($v));
                 return false;
             }
         }
     }
}

// The struct contains the information about the anonymous region
// we are searching for.
#[derive(Debug)]
pub(super) struct AnonymousArgInfo<'tcx> {
    // the argument corresponding to the anonymous region
    pub arg: &'tcx hir::Arg,
    // the type corresponding to the anonymopus region argument
    pub arg_ty: Ty<'tcx>,
    // the ty::BoundRegion corresponding to the anonymous region
    pub bound_region: ty::BoundRegion,
    // corresponds to id the argument is the first parameter
    // in the declaration
    pub is_first: bool,
}

// This struct contains information regarding the
// Refree((FreeRegion) corresponding to lifetime conflict
#[derive(Debug)]
pub(super) struct FreeRegionInfo {
    // def id corresponding to FreeRegion
    pub def_id: DefId,
    // the bound region corresponding to FreeRegion
    pub boundregion: ty::BoundRegion,
    // checks if bound region is in Impl Item
    pub is_impl_item: bool,
}

impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
    // This method walks the Type of the function body arguments using
    // `fold_regions()` function and returns the
    // &hir::Arg of the function argument corresponding to the anonymous
    // region and the Ty corresponding to the named region.
    // Currently only the case where the function declaration consists of
    // one named region and one anonymous region is handled.
    // Consider the example `fn foo<'a>(x: &'a i32, y: &i32) -> &'a i32`
    // Here, we would return the hir::Arg for y, we return the type &'a
    // i32, which is the type of y but with the anonymous region replaced
    // with 'a, the corresponding bound region and is_first which is true if
    // the hir::Arg is the first argument in the function declaration.
    pub(super) fn find_arg_with_region(&self,
                                anon_region: Region<'tcx>,
                                replace_region: Region<'tcx>)
                                -> Option<AnonymousArgInfo> {

        let (id, bound_region) = match *anon_region {
            ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
            ty::ReEarlyBound(ref ebr) => {
                (self.tcx.parent_def_id(ebr.def_id).unwrap(),
                 ty::BoundRegion::BrNamed(ebr.def_id, ebr.name))
            }
            _ => return None, // not a free region
        };

        let hir = &self.tcx.hir;
        if let Some(node_id) = hir.as_local_node_id(id) {
            if let Some(body_id) = hir.maybe_body_owned_by(node_id) {
                let body = hir.body(body_id);
                if let Some(tables) = self.in_progress_tables {
                    body.arguments
                        .iter()
                        .enumerate()
                        .filter_map(|(index, arg)| {
                            // May return None; sometimes the tables are not yet populated.
                            let ty = tables.borrow().node_id_to_type_opt(arg.hir_id)?;
                            let mut found_anon_region = false;
                            let new_arg_ty = self.tcx
                                .fold_regions(&ty, &mut false, |r, _| if *r == *anon_region {
                                    found_anon_region = true;
                                    replace_region
                                } else {
                                    r
                                });
                            if found_anon_region {
                                let is_first = index == 0;
                                Some(AnonymousArgInfo {
                                         arg: arg,
                                         arg_ty: new_arg_ty,
                                         bound_region: bound_region,
                                         is_first: is_first,
                                     })
                            } else {
                                None
                            }
                        })
                        .next()
                } else {
                    None
                }
            } else {
                None
            }
        } else {
            None
        }
    }

    // This method returns the DefId and the BoundRegion corresponding to the given region.
    pub(super) fn is_suitable_region(&self, region: Region<'tcx>) -> Option<FreeRegionInfo> {

        let (suitable_region_binding_scope, bound_region) = match *region {
            ty::ReFree(ref free_region) => (free_region.scope, free_region.bound_region),
            ty::ReEarlyBound(ref ebr) => {
                (self.tcx.parent_def_id(ebr.def_id).unwrap(),
                 ty::BoundRegion::BrNamed(ebr.def_id, ebr.name))
            }
            _ => return None, // not a free region
        };

        let node_id = self.tcx
            .hir
            .as_local_node_id(suitable_region_binding_scope)
            .unwrap();
        let is_impl_item = match self.tcx.hir.find(node_id) {

            Some(hir_map::NodeItem(..)) |
            Some(hir_map::NodeTraitItem(..)) => false,
            Some(hir_map::NodeImplItem(..)) => {
                self.is_bound_region_in_impl_item(suitable_region_binding_scope)
            }
            _ => return None,
        };

        return Some(FreeRegionInfo {
                        def_id: suitable_region_binding_scope,
                        boundregion: bound_region,
                        is_impl_item: is_impl_item,
                    });

    }

    // Here, we check for the case where the anonymous region
    // is in the return type.
    // FIXME(#42703) - Need to handle certain cases here.
    pub(super) fn is_return_type_anon(&self,
                               scope_def_id: DefId,
                               br: ty::BoundRegion,
                               decl: &hir::FnDecl)
                               -> Option<Span> {
        let ret_ty = self.tcx.type_of(scope_def_id);
        match ret_ty.sty {
            ty::TyFnDef(_, _) => {
                let sig = ret_ty.fn_sig(self.tcx);
                let late_bound_regions = self.tcx
                    .collect_referenced_late_bound_regions(&sig.output());
                if late_bound_regions.iter().any(|r| *r == br) {
                    return Some(decl.output.span());
                }
            }
            _ => {}
        }
        None
    }
    // Here we check for the case where anonymous region
    // corresponds to self and if yes, we display E0312.
    // FIXME(#42700) - Need to format self properly to
    // enable E0621 for it.
    pub(super) fn is_self_anon(&self, is_first: bool, scope_def_id: DefId) -> bool {
        is_first &&
        self.tcx
            .opt_associated_item(scope_def_id)
            .map(|i| i.method_has_self_argument) == Some(true)
    }

    // Here we check if the bound region is in Impl Item.
    pub(super) fn is_bound_region_in_impl_item(&self, suitable_region_binding_scope: DefId) -> bool {
        let container_id = self.tcx
            .associated_item(suitable_region_binding_scope)
            .container
            .id();
        if self.tcx.impl_trait_ref(container_id).is_some() {
            // For now, we do not try to target impls of traits. This is
            // because this message is going to suggest that the user
            // change the fn signature, but they may not be free to do so,
            // since the signature must match the trait.
            //
            // FIXME(#42706) -- in some cases, we could do better here.
            return true;
        }
        false
    }

    // This method returns whether the given Region is Named
    pub(super) fn is_named_region(&self, region: Region<'tcx>) -> bool {
        match *region {
            ty::ReFree(ref free_region) => {
                match free_region.bound_region {
                    ty::BrNamed(..) => true,
                    _ => false,
                }
            }
            ty::ReEarlyBound(_) => true,
            _ => false,
        }
    }
}
<|endoftext|>


<commit_before>use stdx::{format_to, to_lower_snake_case};
use syntax::ast::VisibilityOwner;
use syntax::ast::{self, AstNode, NameOwner};
use test_utils::mark;

use crate::{
    utils::{find_impl_block_end, find_struct_impl, generate_impl_text},
    AssistContext, AssistId, AssistKind, Assists,
};

// Assist: generate_enum_is_method
//
// Generate an `is_` method for an enum variant.
//
// ```
// enum Version {
//  Undefined,
//  Minor$0,
//  Major,
// }
// ```
// ->
// ```
// enum Version {
//  Undefined,
//  Minor,
//  Major,
// }
//
// impl Version {
//     /// Returns `true` if the version is [`Minor`].
//     fn is_minor(&self) -> bool {
//         matches!(self, Self::Minor)
//     }
// }
// ```
pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let variant = ctx.find_node_at_offset::<ast::Variant>()?;
    let variant_name = variant.name()?;
    let parent_enum = variant.parent_enum();
    if !matches!(variant.kind(), ast::StructKind::Unit) {
        mark::hit!(test_gen_enum_match_on_non_unit_variant_not_implemented);
        return None;
    }

    let enum_lowercase_name = to_lower_snake_case(&parent_enum.name()?.to_string());
    let fn_name = to_lower_snake_case(&variant_name.to_string());

    // Return early if we've found an existing new fn
    let impl_def = find_struct_impl(
        &ctx,
        &ast::Adt::Enum(parent_enum.clone()),
        format!("is_{}", fn_name).as_str(),
    )?;

    let target = variant.syntax().text_range();
    acc.add(
        AssistId("generate_enum_is_method", AssistKind::Generate),
        "Generate an `is_` method for an enum variant",
        target,
        |builder| {
            let mut buf = String::with_capacity(512);

            if impl_def.is_some() {
                buf.push('\n');
            }

            let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
            format_to!(
                buf,
                "    /// Returns `true` if the {} is [`{}`].
    {}fn is_{}(&self) -> bool {{
        matches!(self, Self::{})
    }}",
                enum_lowercase_name,
                variant_name,
                vis,
                fn_name,
                variant_name
            );

            let start_offset = impl_def
                .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf))
                .unwrap_or_else(|| {
                    buf = generate_impl_text(&ast::Adt::Enum(parent_enum.clone()), &buf);
                    parent_enum.syntax().text_range().end()
                });

            builder.insert(start_offset, buf);
        },
    )
}

#[cfg(test)]
mod tests {
    use test_utils::mark;

    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    fn check_not_applicable(ra_fixture: &str) {
        check_assist_not_applicable(generate_enum_is_method, ra_fixture)
    }

    #[test]
    fn test_generate_enum_match_from_variant() {
        check_assist(
            generate_enum_is_method,
            r#"
enum Variant {
    Undefined,
    Minor$0,
    Major,
}"#,
            r#"enum Variant {
    Undefined,
    Minor,
    Major,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }
}"#,
        );
    }

    #[test]
    fn test_generate_enum_match_already_implemented() {
        check_not_applicable(
            r#"
enum Variant {
    Undefined,
    Minor$0,
    Major,
}

impl Variant {
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }
}"#,
        );
    }

    #[test]
    fn test_add_from_impl_no_element() {
        mark::check!(test_gen_enum_match_on_non_unit_variant_not_implemented);
        check_not_applicable(
            r#"
enum Variant {
    Undefined,
    Minor(u32)$0,
    Major,
}"#,
        );
    }

    #[test]
    fn test_generate_enum_match_from_variant_with_one_variant() {
        check_assist(
            generate_enum_is_method,
            r#"enum Variant { Undefi$0ned }"#,
            r#"
enum Variant { Undefined }

impl Variant {
    /// Returns `true` if the variant is [`Undefined`].
    fn is_undefined(&self) -> bool {
        matches!(self, Self::Undefined)
    }
}"#,
        );
    }

    #[test]
    fn test_generate_enum_match_from_variant_with_visibility_marker() {
        check_assist(
            generate_enum_is_method,
            r#"
pub(crate) enum Variant {
    Undefined,
    Minor$0,
    Major,
}"#,
            r#"pub(crate) enum Variant {
    Undefined,
    Minor,
    Major,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    pub(crate) fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }
}"#,
        );
    }

    #[test]
    fn test_multiple_generate_enum_match_from_variant() {
        check_assist(
            generate_enum_is_method,
            r#"
enum Variant {
    Undefined,
    Minor,
    Major$0,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }
}"#,
            r#"enum Variant {
    Undefined,
    Minor,
    Major,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }

    /// Returns `true` if the variant is [`Major`].
    fn is_major(&self) -> bool {
        matches!(self, Self::Major)
    }
}"#,
        );
    }
}
<commit_msg>make generate_enum_is_method work on any variants<commit_after>use stdx::{format_to, to_lower_snake_case};
use syntax::ast::VisibilityOwner;
use syntax::ast::{self, AstNode, NameOwner};

use crate::{
    utils::{find_impl_block_end, find_struct_impl, generate_impl_text},
    AssistContext, AssistId, AssistKind, Assists,
};

// Assist: generate_enum_is_method
//
// Generate an `is_` method for an enum variant.
//
// ```
// enum Version {
//  Undefined,
//  Minor$0,
//  Major,
// }
// ```
// ->
// ```
// enum Version {
//  Undefined,
//  Minor,
//  Major,
// }
//
// impl Version {
//     /// Returns `true` if the version is [`Minor`].
//     fn is_minor(&self) -> bool {
//         matches!(self, Self::Minor)
//     }
// }
// ```
pub(crate) fn generate_enum_is_method(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
    let variant = ctx.find_node_at_offset::<ast::Variant>()?;
    let variant_name = variant.name()?;
    let parent_enum = ast::Adt::Enum(variant.parent_enum());
    let variant_kind = variant_kind(&variant);

    let enum_lowercase_name = to_lower_snake_case(&parent_enum.name()?.to_string());
    let fn_name = format!("is_{}", &to_lower_snake_case(variant_name.text()));

    // Return early if we've found an existing new fn
    let impl_def = find_struct_impl(
        &ctx,
        &parent_enum,
        &fn_name,
    )?;

    let target = variant.syntax().text_range();
    acc.add(
        AssistId("generate_enum_is_method", AssistKind::Generate),
        "Generate an `is_` method for an enum variant",
        target,
        |builder| {
            let mut buf = String::with_capacity(512);

            if impl_def.is_some() {
                buf.push('\n');
            }

            let vis = parent_enum.visibility().map_or(String::new(), |v| format!("{} ", v));
            format_to!(
                buf,
                "    /// Returns `true` if the {} is [`{}`].
    {}fn {}(&self) -> bool {{
        matches!(self, Self::{}{})
    }}",
                enum_lowercase_name,
                variant_name,
                vis,
                fn_name,
                variant_name,
                variant_kind.pattern_suffix(),
            );

            let start_offset = impl_def
                .and_then(|impl_def| find_impl_block_end(impl_def, &mut buf))
                .unwrap_or_else(|| {
                    buf = generate_impl_text(&parent_enum, &buf);
                    parent_enum.syntax().text_range().end()
                });

            builder.insert(start_offset, buf);
        },
    )
}

enum VariantKind {
    Unit,
    /// Tuple with a single field
    NewtypeTuple,
    /// Tuple with 0 or more than 2 fields
    Tuple,
    /// Record with a single field
    NewtypeRecord { field_name: Option<ast::Name> },
    /// Record with 0 or more than 2 fields
    Record,
}

impl VariantKind {
    fn pattern_suffix(&self) -> &'static str {
        match self {
            VariantKind::Unit => "",
            VariantKind::NewtypeTuple |
            VariantKind::Tuple => "(..)",
            VariantKind::NewtypeRecord { .. } |
            VariantKind::Record => " { .. }",
        }
    }
}

fn variant_kind(variant: &ast::Variant) -> VariantKind {
    match variant.kind() {
        ast::StructKind::Record(record) => {
            if record.fields().count() == 1 {
                let field_name = record.fields().nth(0).unwrap().name();
                VariantKind::NewtypeRecord { field_name }
            } else {
                VariantKind::Record
            }
        }
        ast::StructKind::Tuple(tuple) => {
            if tuple.fields().count() == 1 {
                VariantKind::NewtypeTuple
            } else {
                VariantKind::Tuple
            }
        }
        ast::StructKind::Unit => VariantKind::Unit,
    }
}

#[cfg(test)]
mod tests {
    use crate::tests::{check_assist, check_assist_not_applicable};

    use super::*;

    fn check_not_applicable(ra_fixture: &str) {
        check_assist_not_applicable(generate_enum_is_method, ra_fixture)
    }

    #[test]
    fn test_generate_enum_match_from_variant() {
        check_assist(
            generate_enum_is_method,
            r#"
enum Variant {
    Undefined,
    Minor$0,
    Major,
}"#,
            r#"enum Variant {
    Undefined,
    Minor,
    Major,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }
}"#,
        );
    }

    #[test]
    fn test_generate_enum_match_already_implemented() {
        check_not_applicable(
            r#"
enum Variant {
    Undefined,
    Minor$0,
    Major,
}

impl Variant {
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }
}"#,
        );
    }

    #[test]
    fn test_generate_enum_match_from_tuple_variant() {
        check_assist(
            generate_enum_is_method,
            r#"
enum Variant {
    Undefined,
    Minor(u32)$0,
    Major,
}"#,
            r#"enum Variant {
    Undefined,
    Minor(u32),
    Major,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor(..))
    }
}"#,
        );
    }

    #[test]
    fn test_generate_enum_match_from_record_variant() {
        check_assist(
            generate_enum_is_method,
            r#"
enum Variant {
    Undefined,
    Minor { foo: i32 }$0,
    Major,
}"#,
            r#"enum Variant {
    Undefined,
    Minor { foo: i32 },
    Major,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor { .. })
    }
}"#,
        );
    }

    #[test]
    fn test_generate_enum_match_from_variant_with_one_variant() {
        check_assist(
            generate_enum_is_method,
            r#"enum Variant { Undefi$0ned }"#,
            r#"
enum Variant { Undefined }

impl Variant {
    /// Returns `true` if the variant is [`Undefined`].
    fn is_undefined(&self) -> bool {
        matches!(self, Self::Undefined)
    }
}"#,
        );
    }

    #[test]
    fn test_generate_enum_match_from_variant_with_visibility_marker() {
        check_assist(
            generate_enum_is_method,
            r#"
pub(crate) enum Variant {
    Undefined,
    Minor$0,
    Major,
}"#,
            r#"pub(crate) enum Variant {
    Undefined,
    Minor,
    Major,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    pub(crate) fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }
}"#,
        );
    }

    #[test]
    fn test_multiple_generate_enum_match_from_variant() {
        check_assist(
            generate_enum_is_method,
            r#"
enum Variant {
    Undefined,
    Minor,
    Major$0,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }
}"#,
            r#"enum Variant {
    Undefined,
    Minor,
    Major,
}

impl Variant {
    /// Returns `true` if the variant is [`Minor`].
    fn is_minor(&self) -> bool {
        matches!(self, Self::Minor)
    }

    /// Returns `true` if the variant is [`Major`].
    fn is_major(&self) -> bool {
        matches!(self, Self::Major)
    }
}"#,
        );
    }
}
<|endoftext|>


<commit_before>//! The `join` macro.

use proc_macro_hack::proc_macro_hack;

macro_rules! document_join_macro {
    ($join:item $try_join:item) => {
        /// Polls multiple futures simultaneously, returning a tuple
        /// of all results once complete.
        ///
        /// While `join!(a, b)` is similar to `(a.await, b.await)`,
        /// `join!` polls both futures concurrently and therefore is more efficent.
        ///
        /// This macro is only usable inside of async functions, closures, and blocks.
        /// It is also gated behind the `async-await` feature of this library, which is
        /// activated by default.
        ///
        /// # Examples
        ///
        /// ```
        /// # futures::executor::block_on(async {
        /// use futures::join;
        ///
        /// let a = async { 1 };
        /// let b = async { 2 };
        ///
        /// assert_eq!(join!(a, b), (1, 2));
        /// # });
        /// ```
        $join

        /// Polls multiple futures simultaneously, resolving to a [`Result`] containing
        /// either a tuple of the successful outputs or an error.
        ///
        /// `try_join!` is similar to [`join!`], but completes immediately if any of
        /// the futures return an error.
        ///
        /// This macro is only usable inside of async functions, closures, and blocks.
        /// It is also gated behind the `async-await` feature of this library, which is
        /// activated by default.
        ///
        /// # Examples
        ///
        /// When used on multiple futures that return `Ok`, `try_join!` will return
        /// `Ok` of a tuple of the values:
        ///
        /// ```
        /// # futures::executor::block_on(async {
        /// use futures::try_join;
        ///
        /// let a = async { Ok::<i32, i32>(1) };
        /// let b = async { Ok::<u64, i32>(2) };
        ///
        /// assert_eq!(try_join!(a, b), Ok((1, 2)));
        /// # });
        /// ```
        ///
        /// If one of the futures resolves to an error, `try_join!` will return
        /// that error:
        ///
        /// ```
        /// # futures::executor::block_on(async {
        /// use futures::try_join;
        ///
        /// let a = async { Ok::<i32, i32>(1) };
        /// let b = async { Err::<u64, i32>(2) };
        ///
        /// assert_eq!(try_join!(a, b), Err(2));
        /// # });
        /// ```
        $try_join
    }
}

#[doc(hidden)]
#[proc_macro_hack(support_nested)]
pub use futures_macro::join_internal;

#[doc(hidden)]
#[proc_macro_hack(support_nested)]
pub use futures_macro::try_join_internal;

document_join_macro! {
    #[macro_export]
    macro_rules! join {
        ($($tokens:tt)*) => {{
            use $crate::__reexport as __futures_crate;
            $crate::join_internal! {
                $( $tokens )*
            }
        }}
    }

    #[macro_export]
    macro_rules! try_join {
        ($($tokens:tt)*) => {{
            use $crate::__reexport as __futures_crate;
            $crate::try_join_internal! {
                $( $tokens )*
            }
        }}
    }
}
<commit_msg>Extend example for join!/try_join! (#2195)<commit_after>//! The `join` macro.

use proc_macro_hack::proc_macro_hack;

macro_rules! document_join_macro {
    ($join:item $try_join:item) => {
        /// Polls multiple futures simultaneously, returning a tuple
        /// of all results once complete.
        ///
        /// While `join!(a, b)` is similar to `(a.await, b.await)`,
        /// `join!` polls both futures concurrently and therefore is more efficent.
        ///
        /// This macro is only usable inside of async functions, closures, and blocks.
        /// It is also gated behind the `async-await` feature of this library, which is
        /// activated by default.
        ///
        /// # Examples
        ///
        /// ```
        /// # futures::executor::block_on(async {
        /// use futures::join;
        ///
        /// let a = async { 1 };
        /// let b = async { 2 };
        /// assert_eq!(join!(a, b), (1, 2));
        ///
        /// // `join!` is variadic, so you can pass any number of futures
        /// let c = async { 3 };
        /// let d = async { 4 };
        /// let e = async { 5 };
        /// assert_eq!(join!(c, d, e), (3, 4, 5));
        /// # });
        /// ```
        $join

        /// Polls multiple futures simultaneously, resolving to a [`Result`] containing
        /// either a tuple of the successful outputs or an error.
        ///
        /// `try_join!` is similar to [`join!`], but completes immediately if any of
        /// the futures return an error.
        ///
        /// This macro is only usable inside of async functions, closures, and blocks.
        /// It is also gated behind the `async-await` feature of this library, which is
        /// activated by default.
        ///
        /// # Examples
        ///
        /// When used on multiple futures that return `Ok`, `try_join!` will return
        /// `Ok` of a tuple of the values:
        ///
        /// ```
        /// # futures::executor::block_on(async {
        /// use futures::try_join;
        ///
        /// let a = async { Ok::<i32, i32>(1) };
        /// let b = async { Ok::<i32, i32>(2) };
        /// assert_eq!(try_join!(a, b), Ok((1, 2)));
        ///
        /// // `try_join!` is variadic, so you can pass any number of futures
        /// let c = async { Ok::<i32, i32>(3) };
        /// let d = async { Ok::<i32, i32>(4) };
        /// let e = async { Ok::<i32, i32>(5) };
        /// assert_eq!(try_join!(c, d, e), Ok((3, 4, 5)));
        /// # });
        /// ```
        ///
        /// If one of the futures resolves to an error, `try_join!` will return
        /// that error:
        ///
        /// ```
        /// # futures::executor::block_on(async {
        /// use futures::try_join;
        ///
        /// let a = async { Ok::<i32, i32>(1) };
        /// let b = async { Err::<u64, i32>(2) };
        ///
        /// assert_eq!(try_join!(a, b), Err(2));
        /// # });
        /// ```
        $try_join
    }
}

#[doc(hidden)]
#[proc_macro_hack(support_nested)]
pub use futures_macro::join_internal;

#[doc(hidden)]
#[proc_macro_hack(support_nested)]
pub use futures_macro::try_join_internal;

document_join_macro! {
    #[macro_export]
    macro_rules! join {
        ($($tokens:tt)*) => {{
            use $crate::__reexport as __futures_crate;
            $crate::join_internal! {
                $( $tokens )*
            }
        }}
    }

    #[macro_export]
    macro_rules! try_join {
        ($($tokens:tt)*) => {{
            use $crate::__reexport as __futures_crate;
            $crate::try_join_internal! {
                $( $tokens )*
            }
        }}
    }
}
<|endoftext|>


<commit_before>//! This crate contains functionality for the client only. This is mainly
//! graphics and input handling.
//!

extern crate base;
#[macro_use]
extern crate glium;
#[macro_use]
extern crate log;

mod camera;
mod config;
mod game;
mod game_context;
mod ghost;
mod renderer;
mod world;
mod world_manager;
mod event_manager;
pub mod view;
pub mod util;

pub mod daytime;

pub use daytime::*;
pub use camera::Camera;
pub use config::Config;
pub use event_manager::*;
pub use game_context::GameContext;
pub use renderer::Renderer;
pub use world_manager::WorldManager;

use game::Game;
use std::net::SocketAddr;
use std::error::Error;

pub fn start_game(config: Config, server: SocketAddr) -> Result<(), Box<Error>> {
    let game = try!(Game::new(config, server));
    game.run()
}
<commit_msg>remove unnecessary empty lines<commit_after>//! This crate contains functionality for the client only. This is mainly
//! graphics and input handling.
//!

extern crate base;
#[macro_use]
extern crate glium;
#[macro_use]
extern crate log;

mod camera;
mod config;
mod game;
mod game_context;
mod ghost;
mod renderer;
mod world;
mod world_manager;
mod event_manager;
pub mod view;
pub mod util;
pub mod daytime;

pub use daytime::*;
pub use camera::Camera;
pub use config::Config;
pub use event_manager::*;
pub use game_context::GameContext;
pub use renderer::Renderer;
pub use world_manager::WorldManager;

use game::Game;
use std::net::SocketAddr;
use std::error::Error;

pub fn start_game(config: Config, server: SocketAddr) -> Result<(), Box<Error>> {
    let game = try!(Game::new(config, server));
    game.run()
}
<|endoftext|>