<commit_before>#![feature(box_syntax)]
extern crate curl;
extern crate serde;
extern crate num_cpus;
extern crate serde_json;
extern crate getopts;
extern crate crossbeam;
extern crate define;
use define::dictionaries::{Dictionary, Definition, wordnik};
use define::thesaureses::Thesaurus;
use std::collections::HashMap;
use std::sync::Arc;
use std::env;
use std::sync::mpsc;
use getopts::{Matches, Options};

static KEY: &'static str = "a2a73e7b926c924fad7001ca3111acd55af2ffabf50eb4ae5";
static UKEY: &'static str = "ub2JDDg9Iumsh1HfdO3a3HQbZi0up1qe8LkjsnWQvyVvQLFn1q";
const THREAD_ENABLED: bool = true;
struct Config {
    max_definitions: i16,
}

fn parse_args() -> (Options, Matches) {
    let argv: Vec<String> = { let mut args: Vec<String> = env::args().collect(); args.dedup(); args };
    let mut parser = Options::new();
    parser.optflag("t", "thesaurus", "Finds synonyms for word");
    parser.optflag("u", "urban", "Urban Dictionary");
    parser.optopt("", "source", "Set dictionary source", "SOURCE");
    parser.optopt("",
                  "thesaurus-source",
                  "Set thesaurus source (not functional yet)",
                  "SOURCE");
    let parsed = parser.parse(&argv[1..]).unwrap();
    (parser, parsed)
}

fn get_sources()
    -> (HashMap<String, Box<Dictionary + Send + Sync>>,
        HashMap<String, Box<Thesaurus>>)
{
    // insert your dictionaries here
    let mut dictionaries: HashMap<String, Box<Dictionary + Send + Sync>> = HashMap::new();
    let wordnik = wordnik::Wordnik::new(KEY);
    dictionaries.insert(String::from("wordnik"), box wordnik.clone());
    dictionaries.insert(String::from("example"),
                        box define::dictionaries::example::ExampleDictionary);
    dictionaries.insert(String::from("urban"),
                        box define::dictionaries::urban::Urban::new(UKEY));
    let mut thesaureses: HashMap<String, Box<Thesaurus>> = HashMap::new();
    thesaureses.insert(String::from("wordnik"), box wordnik.clone());
    (dictionaries, thesaureses)
}

fn print_definition<'a, T: Dictionary + ?Sized>(dict: &'a mut Box<T>,
                                                word: &str,
                                                max_definitions: Option<usize>)
                                                -> Result<(), &'a str> {
    let definitions = try!(dict.get_definitions(word));
    let max_definitions = max_definitions.unwrap_or(1);
    if max_definitions > 1 {
        for (wordnumber, word) in definitions.iter().take(max_definitions).enumerate() {
            println!("{}. {}", wordnumber + 1, word.text);
        }
    } else {
        println!("{}", definitions[0].text);
    }
    Ok(())
}

fn print_synonyms<'a, T: Thesaurus + ?Sized>(thes: &'a mut Box<T>,
                                             word: &str)
                                             -> Result<(), &'a str> {
    let synonyms = try!(thes.get_synonyms(word));
    println!("{}", synonyms.join(", "));
    Ok(())
}

fn get_source<'a, T: Dictionary + ?Sized + Send + Sync, K: Thesaurus + ?Sized>
    (dictionaries: &'a mut HashMap<String, Box<T>>,
     thesaureses: &'a mut HashMap<String, Box<K>>,
     args: &Matches)
     -> (&'a mut Box<T>, &'a mut Box<K>) {

    let mut source: String = "wordnik".to_owned();
    let tsource: String;
    tsource = args.opt_str("thesaurus-source").unwrap_or("wordnik".to_owned()).to_owned();
    if !args.opt_present("source") {
        for dictionary_source in dictionaries.keys() {
            if args.opt_defined(&dictionary_source) && args.opt_present(&dictionary_source) {
                source = dictionary_source.clone();
            }
        }
    }
    else if args.opt_present("source") {
        source = args.opt_str("source").unwrap_or("wordnik".to_owned()).to_owned();
    }
    let dict: Option<&mut Box<T>> = dictionaries.get_mut(&source);
    let thes: Option<&mut Box<K>> = thesaureses.get_mut(&tsource);
    (dict.unwrap(), thes.unwrap())
}

fn main() {
    let (mut dictionaries, mut thesaureses) = get_sources();
    let (opts, args) = parse_args(); //we needs opts too for printing brief description
    let (dictionary, thesaurus) = get_source(&mut dictionaries, &mut thesaureses, &args);
    if args.free.is_empty() {
        println!("{}", opts.usage("USAGE: define WORD"));
    }
    if ! THREAD_ENABLED {
        for word in &args.free {
            println!("{}:", word.to_uppercase());
            print_definition(dictionary, &word.to_lowercase(), Some(3)).unwrap_or_else(|err| println!("{}", err));
            if args.opt_present("t") {
                println!("SYNONYMS:");
                print_synonyms(thesaurus, word).unwrap_or_else(|err| println!("{}", err));
            }
        }
    }
    else {
        let free_clone = args.free.clone();
        let dict_arc = Arc::new(dictionary.clone_to_box());
        //chunks.map(|chunk| chunks_vec.push(chunk));
        let (tx, rx) = mpsc::channel::<Vec<Definition>>();
        let mut words: Vec<&[String]> = Vec::new();
        let threads = num_cpus::get();;
        {
            let threads = num_cpus::get();
            for chunk in free_clone.chunks((free_clone.len() + threads - 1) / threads) {
                words.push(chunk);
            }
        }
        let words_arc = Arc::new(words);
        for num in 0..words_arc.len() {
            let dict = dict_arc.clone();
            let tx = tx.clone();
            let words = words_arc.clone()[num];
            unsafe {
            crossbeam::spawn_unsafe(move || {
                let mut dictionary = dict.clone_to_box();
                let mut definitions = Vec::new();
                for word in words.iter() {
                    let defs = dictionary.get_definitions(word).unwrap_or(Vec::new());
                    for definition in &defs {
                        definitions.push(definition.clone());
                    }
                }
                tx.send(definitions);
            });
            }
        }
        let mut definitions: HashMap<String, Vec<Definition>> = HashMap::new();
        for _ in 0..words_arc.len() {
            let thread_definitions = rx.recv().unwrap();
            for definition in thread_definitions {
                if definitions.contains_key(&definition.word) {
                    definitions.get_mut(&definition.word).unwrap().push(definition);
                }

                else {
                    definitions.insert(definition.word.clone().to_lowercase(), vec![definition]); //lowercase is necessary because some dictionaries return the definitions in different cases
                }
            }
        }
        for (word, definitions) in definitions.iter() {
                println!("{}:", word.to_uppercase());
                for (number, definition) in definitions.iter().take(3).enumerate() {
                    println!("{}. {}", number + 1, definition.text);
                }
            }
    }
}
<commit_msg>Revert to disabled threading<commit_after>#![feature(box_syntax)]
extern crate curl;
extern crate serde;
extern crate num_cpus;
extern crate serde_json;
extern crate getopts;
extern crate crossbeam;
extern crate define;
use define::dictionaries::{Dictionary, Definition, wordnik};
use define::thesaureses::Thesaurus;
use std::collections::HashMap;
use std::sync::Arc;
use std::env;
use std::sync::mpsc;
use getopts::{Matches, Options};

static KEY: &'static str = "a2a73e7b926c924fad7001ca3111acd55af2ffabf50eb4ae5";
static UKEY: &'static str = "ub2JDDg9Iumsh1HfdO3a3HQbZi0up1qe8LkjsnWQvyVvQLFn1q";
const THREAD_ENABLED: bool = false;
struct Config {
    max_definitions: i16,
}

fn parse_args() -> (Options, Matches) {
    let argv: Vec<String> = { let mut args: Vec<String> = env::args().collect(); args.dedup(); args };
    let mut parser = Options::new();
    parser.optflag("t", "thesaurus", "Finds synonyms for word");
    parser.optflag("u", "urban", "Urban Dictionary");
    parser.optopt("", "source", "Set dictionary source", "SOURCE");
    parser.optopt("",
                  "thesaurus-source",
                  "Set thesaurus source (not functional yet)",
                  "SOURCE");
    let parsed = parser.parse(&argv[1..]).unwrap();
    (parser, parsed)
}

fn get_sources()
    -> (HashMap<String, Box<Dictionary + Send + Sync>>,
        HashMap<String, Box<Thesaurus>>)
{
    // insert your dictionaries here
    let mut dictionaries: HashMap<String, Box<Dictionary + Send + Sync>> = HashMap::new();
    let wordnik = wordnik::Wordnik::new(KEY);
    dictionaries.insert(String::from("wordnik"), box wordnik.clone());
    dictionaries.insert(String::from("example"),
                        box define::dictionaries::example::ExampleDictionary);
    dictionaries.insert(String::from("urban"),
                        box define::dictionaries::urban::Urban::new(UKEY));
    let mut thesaureses: HashMap<String, Box<Thesaurus>> = HashMap::new();
    thesaureses.insert(String::from("wordnik"), box wordnik.clone());
    (dictionaries, thesaureses)
}

fn print_definition<'a, T: Dictionary + ?Sized>(dict: &'a mut Box<T>,
                                                word: &str,
                                                max_definitions: Option<usize>)
                                                -> Result<(), &'a str> {
    let definitions = try!(dict.get_definitions(word));
    let max_definitions = max_definitions.unwrap_or(1);
    if max_definitions > 1 {
        for (wordnumber, word) in definitions.iter().take(max_definitions).enumerate() {
            println!("{}. {}", wordnumber + 1, word.text);
        }
    } else {
        println!("{}", definitions[0].text);
    }
    Ok(())
}

fn print_synonyms<'a, T: Thesaurus + ?Sized>(thes: &'a mut Box<T>,
                                             word: &str)
                                             -> Result<(), &'a str> {
    let synonyms = try!(thes.get_synonyms(word));
    println!("{}", synonyms.join(", "));
    Ok(())
}

fn get_source<'a, T: Dictionary + ?Sized + Send + Sync, K: Thesaurus + ?Sized>
    (dictionaries: &'a mut HashMap<String, Box<T>>,
     thesaureses: &'a mut HashMap<String, Box<K>>,
     args: &Matches)
     -> (&'a mut Box<T>, &'a mut Box<K>) {

    let mut source: String = "wordnik".to_owned();
    let tsource: String;
    tsource = args.opt_str("thesaurus-source").unwrap_or("wordnik".to_owned()).to_owned();
    if !args.opt_present("source") {
        for dictionary_source in dictionaries.keys() {
            if args.opt_defined(&dictionary_source) && args.opt_present(&dictionary_source) {
                source = dictionary_source.clone();
            }
        }
    }
    else if args.opt_present("source") {
        source = args.opt_str("source").unwrap_or("wordnik".to_owned()).to_owned();
    }
    let dict: Option<&mut Box<T>> = dictionaries.get_mut(&source);
    let thes: Option<&mut Box<K>> = thesaureses.get_mut(&tsource);
    (dict.unwrap(), thes.unwrap())
}

fn main() {
    let (mut dictionaries, mut thesaureses) = get_sources();
    let (opts, args) = parse_args(); //we needs opts too for printing brief description
    let (dictionary, thesaurus) = get_source(&mut dictionaries, &mut thesaureses, &args);
    if args.free.is_empty() {
        println!("{}", opts.usage("USAGE: define WORD"));
    }
    if ! THREAD_ENABLED {
        for word in &args.free {
            println!("{}:", word.to_uppercase());
            print_definition(dictionary, &word.to_lowercase(), Some(3)).unwrap_or_else(|err| println!("{}", err));
            if args.opt_present("t") {
                println!("SYNONYMS:");
                print_synonyms(thesaurus, word).unwrap_or_else(|err| println!("{}", err));
            }
        }
    }
    else {
        let free_clone = args.free.clone();
        let dict_arc = Arc::new(dictionary.clone_to_box());
        //chunks.map(|chunk| chunks_vec.push(chunk));
        let (tx, rx) = mpsc::channel::<Vec<Definition>>();
        let mut words: Vec<&[String]> = Vec::new();
        let threads = num_cpus::get();;
        {
            let threads = num_cpus::get();
            for chunk in free_clone.chunks((free_clone.len() + threads - 1) / threads) {
                words.push(chunk);
            }
        }
        let words_arc = Arc::new(words);
        for num in 0..words_arc.len() {
            let dict = dict_arc.clone();
            let tx = tx.clone();
            let words = words_arc.clone()[num];
            unsafe {
            crossbeam::spawn_unsafe(move || {
                let mut dictionary = dict.clone_to_box();
                let mut definitions = Vec::new();
                for word in words.iter() {
                    let defs = dictionary.get_definitions(word).unwrap_or(Vec::new());
                    for definition in &defs {
                        definitions.push(definition.clone());
                    }
                }
                tx.send(definitions);
            });
            }
        }
        let mut definitions: HashMap<String, Vec<Definition>> = HashMap::new();
        for _ in 0..words_arc.len() {
            let thread_definitions = rx.recv().unwrap();
            for definition in thread_definitions {
                if definitions.contains_key(&definition.word) {
                    definitions.get_mut(&definition.word).unwrap().push(definition);
                }

                else {
                    definitions.insert(definition.word.clone().to_lowercase(), vec![definition]); //lowercase is necessary because some dictionaries return the definitions in different cases
                }
            }
        }
        for (word, definitions) in definitions.iter() {
                println!("{}:", word.to_uppercase());
                for (number, definition) in definitions.iter().take(3).enumerate() {
                    println!("{}. {}", number + 1, definition.text);
                }
            }
    }
}
<|endoftext|>


<commit_before>// TODO: many items from tokio-core::io have been deprecated in favour of tokio-io
#![allow(deprecated)]

#[cfg(debug_assertions)]
#[macro_use] extern crate log;
#[cfg(debug_assertions)]
extern crate env_logger;
extern crate futures;
extern crate getopts;
extern crate librespot;
extern crate tokio_core;
extern crate tokio_signal;

#[cfg(debug_assertions)]
use env_logger::LogBuilder;
use futures::{Future, Async, Poll, Stream};
#[cfg(debug_assertions)]
use std::env;
use std::io::{self, stderr, Write};
use std::path::PathBuf;
use std::process::exit;
use std::str::FromStr;
use tokio_core::reactor::{Handle, Core};
use tokio_core::io::IoStream;
use std::mem;

use librespot::spirc::{Spirc, SpircTask};
use librespot::authentication::{get_credentials, Credentials};
#[cfg(not(target_os="windows"))]
use librespot::authentication::discovery::{discovery, DiscoveryStream};
use librespot::audio_backend;
use librespot::cache::Cache;
use librespot::player::Player;
use librespot::session::{Bitrate, Config, Session};
use librespot::mixer::{self, Mixer};
use librespot::util::SpotifyId;

const VERSION: &'static str = concat!(env!("CARGO_PKG_NAME"), " v", env!("CARGO_PKG_VERSION"));

fn usage(program: &str, opts: &getopts::Options) -> String {
   	println!("{}", VERSION.to_string());

    let brief = format!("Usage: {} [options]", program);
    opts.usage(&brief)
}

#[cfg(debug_assertions)]
fn setup_logging(verbose: bool) {
    let mut builder = LogBuilder::new();
    match env::var("RUST_LOG") {
        Ok(config) => {
            builder.parse(&config);
            builder.init().unwrap();

            if verbose {
                warn!("`--verbose` flag overidden by `RUST_LOG` environment variable");
            }
        }
        Err(_) => {
            if verbose {
                builder.parse("mdns=info,librespot=trace");
            } else {
                builder.parse("mdns=error,librespot=warn");
            }
            builder.init().unwrap();
        }
    }
}

#[derive(Clone)]
struct Setup {
    mixer: fn() -> Box<Mixer>,

	name: String,
    cache: Option<Cache>,
    config: Config,
    credentials: Option<Credentials>,
    authenticate: bool,
    enable_discovery: bool,

    single_track: Option<String>,
    start_position: u32,
}

fn setup(args: &[String]) -> Setup {
    let mut opts = getopts::Options::new();
    opts.optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE")
        .reqopt("n", "name", "Device name", "NAME")
        .optopt("b", "bitrate", "Bitrate (96, 160 or 320). Defaults to 160", "BITRATE")
        .optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM")
        .optopt("", "onstop", "Run PROGRAM when playback has ended.", "PROGRAM")
        .optopt("", "single-track", "Play a single track ID and exit.", "ID")
        .optopt("", "start-position", "Position (in ms) where playback should be started. Only valid with the --single-track option.", "STARTPOSITION")
        .optopt("u", "username", "Username to sign in with", "USERNAME")
        .optopt("p", "password", "Password", "PASSWORD")
        .optflag("a", "authenticate", "Authenticate given username and password. Make sure you define a cache folder to store credentials.")
        .optflag("", "disable-discovery", "Disable discovery mode")
        .optflag("x", "check", "Run quick internal check")
        .optopt("", "mixer", "Mixer to use", "MIXER");

	#[cfg(debug_assertions)]
    opts.optflag("v", "verbose", "Enable verbose output");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            writeln!(stderr(), "error: {}\n{}", f.to_string(), usage(&args[0], &opts)).unwrap();
            exit(1);
        }
    };

    if matches.opt_present("check") {
    	println!("ok {}", VERSION.to_string());
    	exit(1);
    }

	#[cfg(debug_assertions)]
	{
	    let verbose = matches.opt_present("verbose");
	    setup_logging(verbose);
	}

    let mixer_name = matches.opt_str("mixer");
    let mixer = mixer::find(mixer_name.as_ref())
        .expect("Invalid mixer");

    let bitrate = matches.opt_str("b").as_ref()
        .map(|bitrate| Bitrate::from_str(bitrate).expect("Invalid bitrate"))
        .unwrap_or(Bitrate::Bitrate160);

    let name = matches.opt_str("name").unwrap();
    let device_id = librespot::session::device_id(&name);

    let cache = matches.opt_str("c").map(|cache_location| {
        Cache::new(PathBuf::from(cache_location))
    });

    let cached_credentials = cache.as_ref().and_then(Cache::credentials);

    let credentials = get_credentials(matches.opt_str("username"),
                                      matches.opt_str("password"),
                                      cached_credentials);

    let authenticate = matches.opt_present("authenticate");

#[cfg(not(target_os="windows"))]
    let enable_discovery = !matches.opt_present("disable-discovery");
#[cfg(target_os="windows")]
    let enable_discovery = false;

    let start_position = matches.opt_str("start-position")
    	.unwrap_or("0".to_string())
    	.parse().unwrap_or(0.0);

    let config = Config {
        user_agent: VERSION.to_string(),
        device_id: device_id,
        bitrate: bitrate,
        onstart: matches.opt_str("onstart"),
        onstop: matches.opt_str("onstop"),
    };

    Setup {
		name: name,
        cache: cache,
        config: config,
        credentials: credentials,
        authenticate: authenticate,
        enable_discovery: enable_discovery,
        mixer: mixer,

        single_track: matches.opt_str("single-track"),
        start_position: (start_position * 1000.0) as u32,
    }
}

struct Main {
	name: String,
    cache: Option<Cache>,
    config: Config,
    mixer: fn() -> Box<Mixer>,
    handle: Handle,

#[cfg(not(target_os="windows"))]
    discovery: Option<DiscoveryStream>,
#[cfg(target_os="windows")]
    discovery: Option<String>,
    signal: IoStream<()>,

    spirc: Option<Spirc>,
    spirc_task: Option<SpircTask>,
    connect: Box<Future<Item=Session, Error=io::Error>>,

    player: Option<Player>,

    shutdown: bool,
    authenticate: bool,
}

impl Main {
    fn new(handle: Handle,
           name: String,
           config: Config,
           cache: Option<Cache>,
           mixer: fn() -> Box<Mixer>,
           authenticate: bool,
    ) -> Main
    {
        Main {
            handle: handle.clone(),
            name: name,
            cache: cache,
            config: config,
            mixer: mixer,

            connect: Box::new(futures::future::empty()),
            discovery: None,
            spirc: None,
            spirc_task: None,

            player: None,

            shutdown: false,
            authenticate: authenticate,
            signal: tokio_signal::ctrl_c(&handle).flatten_stream().boxed(),
        }
    }

#[cfg(not(target_os="windows"))]
    fn discovery(&mut self) {
        let device_id = self.config.device_id.clone();
        let name = self.name.clone();

        self.discovery = Some(discovery(&self.handle, name, device_id).unwrap());
    }

    fn credentials(&mut self, credentials: Credentials) {
        let config = self.config.clone();
        let handle = self.handle.clone();

        let connection = Session::connect(config, credentials, self.cache.clone(), handle);

        self.connect = connection;
        self.spirc = None;
        let task = mem::replace(&mut self.spirc_task, None);
        if let Some(task) = task {
            self.handle.spawn(task);
        }
    }
}

impl Future for Main {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        loop {
            let mut progress = false;

#[cfg(not(target_os="windows"))] {
            if let Some(Async::Ready(Some(creds))) = self.discovery.as_mut().map(|d| d.poll().unwrap()) {
                if let Some(ref spirc) = self.spirc {
                    spirc.shutdown();
                }
                self.credentials(creds);

                progress = true;
            }
}

            if let Async::Ready(session) = self.connect.poll().unwrap() {
            	if self.authenticate {
					if !self.shutdown {
						if let Some(ref spirc) = self.spirc {
							spirc.shutdown();
						}
						self.shutdown = true;
					} else {
						return Ok(Async::Ready(()));
					}
            	}
            	else {
					self.connect = Box::new(futures::future::empty());
					let mixer = (self.mixer)();

					let audio_filter = mixer.get_audio_filter();
					let backend = audio_backend::find(None).unwrap();
					let player = Player::new(session.clone(), audio_filter, move || {
						(backend)(None)
					});

					self.player = Some(player.clone());

					let (spirc, spirc_task) = Spirc::new(self.name.clone(), session, player, mixer);
					self.spirc = Some(spirc);
					self.spirc_task = Some(spirc_task);
				}

                progress = true;
            }

            if let Async::Ready(Some(())) = self.signal.poll().unwrap() {
                if !self.shutdown {
                    if let Some(ref spirc) = self.spirc {
                        spirc.shutdown();
                    }
                    self.shutdown = true;
                } else {
                    return Ok(Async::Ready(()));
                }

                progress = true;
            }

            if let Some(ref mut spirc_task) = self.spirc_task {
                if let Async::Ready(()) = spirc_task.poll().unwrap() {
                    if self.shutdown {
                        return Ok(Async::Ready(()));
                    } else {
                        panic!("Spirc shut down unexpectedly");
                    }
                }
            }

            if !progress {
                return Ok(Async::NotReady);
            }
        }
    }
}

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let args: Vec<String> = std::env::args().collect();
    let Setup { name, config, cache, enable_discovery, credentials, authenticate, mixer, single_track, start_position } = setup(&args);

	if let Some(ref track_id) = single_track {
		match credentials {
			Some(credentials) => {
				let backend = audio_backend::find(None).unwrap();

				let track = SpotifyId::from_base62(
									track_id.replace("spotty://", "")
									.replace("spotify://", "")
									.replace("track:", "")
									.as_str());

				let session = core.run(Session::connect(config, credentials, None, handle)).unwrap();

				let player = Player::new(session.clone(), None, move || (backend)(None));

				core.run(player.load(track, true, start_position)).unwrap();
			}
			None => {
				println!("Missing credentials");
			}
	    }
	}
	else if authenticate && !enable_discovery {
        core.run(Session::connect(config, credentials.unwrap(), cache.clone(), handle)).unwrap();
		println!("authorized");
	}
	else {
		let mut task = Main::new(handle, name, config, cache, mixer, authenticate);
		if enable_discovery {
#[cfg(not(target_os="windows"))]
			task.discovery();
		}
		if let Some(credentials) = credentials {
			task.credentials(credentials);
		}

		core.run(task).unwrap()
    }
}

<commit_msg>Remove mixer and bitrate options, add get-token<commit_after>// TODO: many items from tokio-core::io have been deprecated in favour of tokio-io
#![allow(deprecated)]

#[cfg(debug_assertions)]
#[macro_use] extern crate log;
#[cfg(debug_assertions)]
extern crate env_logger;
extern crate futures;
extern crate getopts;
extern crate librespot;
extern crate tokio_core;
extern crate tokio_signal;

#[cfg(debug_assertions)]
use env_logger::LogBuilder;
use futures::{Future, Async, Poll, Stream};
#[cfg(debug_assertions)]
use std::env;
use std::io::{self, stderr, Write};
use std::path::PathBuf;
use std::process::exit;
use tokio_core::reactor::{Handle, Core};
use tokio_core::io::IoStream;
use std::mem;

use librespot::spirc::{Spirc, SpircTask};
use librespot::authentication::{get_credentials, Credentials};
#[cfg(not(target_os="windows"))]
use librespot::authentication::discovery::{discovery, DiscoveryStream};
use librespot::audio_backend;
use librespot::cache::Cache;
use librespot::player::Player;
use librespot::session::{Bitrate, Config, Session};
use librespot::mixer;
use librespot::util::SpotifyId;

const VERSION: &'static str = concat!(env!("CARGO_PKG_NAME"), " v", env!("CARGO_PKG_VERSION"));

fn usage(program: &str, opts: &getopts::Options) -> String {
   	println!("{}", VERSION.to_string());

    let brief = format!("Usage: {} [options]", program);
    opts.usage(&brief)
}

#[cfg(debug_assertions)]
fn setup_logging(verbose: bool) {
    let mut builder = LogBuilder::new();
    match env::var("RUST_LOG") {
        Ok(config) => {
            builder.parse(&config);
            builder.init().unwrap();

            if verbose {
                warn!("`--verbose` flag overidden by `RUST_LOG` environment variable");
            }
        }
        Err(_) => {
            if verbose {
                builder.parse("mdns=info,librespot=trace");
            } else {
                builder.parse("mdns=error,librespot=warn");
            }
            builder.init().unwrap();
        }
    }
}

#[derive(Clone)]
struct Setup {
	name: String,
    cache: Option<Cache>,
    config: Config,
    credentials: Option<Credentials>,
    authenticate: bool,
    enable_discovery: bool,

    get_token: bool,
    client_id: Option<String>,
    scope: Option<String>,

    single_track: Option<String>,
    start_position: u32,
}

fn setup(args: &[String]) -> Setup {
    let mut opts = getopts::Options::new();
    opts.optopt("c", "cache", "Path to a directory where files will be cached.", "CACHE")
        .reqopt("n", "name", "Device name", "NAME")
        .optopt("", "onstart", "Run PROGRAM when playback is about to begin.", "PROGRAM")
        .optopt("", "onstop", "Run PROGRAM when playback has ended.", "PROGRAM")
        .optopt("", "single-track", "Play a single track ID and exit.", "ID")
        .optopt("", "start-position", "Position (in ms) where playback should be started. Only valid with the --single-track option.", "STARTPOSITION")
        .optopt("u", "username", "Username to sign in with", "USERNAME")
        .optopt("p", "password", "Password", "PASSWORD")
        .optflag("a", "authenticate", "Authenticate given username and password. Make sure you define a cache folder to store credentials.")
        .optflag("", "disable-discovery", "Disable discovery mode")
        .optflag("t", "get-token", "Get oauth token to be used with the web API etc.")
        .optopt("", "client-id", "A Spotify client_id to be used to get the oauth token. Required with the --get-token request.", "CLIENT_ID")
        .optopt("", "scope", "The scopes you want to have access to with the oauth token.", "SCOPE")
        .optflag("x", "check", "Run quick internal check");

	#[cfg(debug_assertions)]
    opts.optflag("v", "verbose", "Enable verbose output");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => {
            writeln!(stderr(), "error: {}\n{}", f.to_string(), usage(&args[0], &opts)).unwrap();
            exit(1);
        }
    };

    if matches.opt_present("check") {
    	println!("ok {}", VERSION.to_string());
    	exit(1);
    }

	#[cfg(debug_assertions)]
	{
	    let verbose = matches.opt_present("verbose");
	    setup_logging(verbose);
	}

    let name = matches.opt_str("name").unwrap();
    let device_id = librespot::session::device_id(&name);

    let cache = matches.opt_str("c").map(|cache_location| {
        Cache::new(PathBuf::from(cache_location))
    });

    let cached_credentials = cache.as_ref().and_then(Cache::credentials);

    let credentials = get_credentials(matches.opt_str("username"),
                                      matches.opt_str("password"),
                                      cached_credentials);

    let authenticate = matches.opt_present("authenticate");

#[cfg(not(target_os="windows"))]
    let enable_discovery = !matches.opt_present("disable-discovery");
#[cfg(target_os="windows")]
    let enable_discovery = false;

    let start_position = matches.opt_str("start-position")
    	.unwrap_or("0".to_string())
    	.parse().unwrap_or(0.0);

	    let config = Config {
        user_agent: VERSION.to_string(),
        device_id: device_id,
        bitrate: Bitrate::Bitrate320,
        onstart: matches.opt_str("onstart"),
        onstop: matches.opt_str("onstop"),
    };

    Setup {
		name: name,
        cache: cache,
        config: config,
        credentials: credentials,
        authenticate: authenticate,
        enable_discovery: enable_discovery,

        get_token: matches.opt_present("get-token"),
        client_id: matches.opt_str("client-id"),
        scope: matches.opt_str("scope"),

        single_track: matches.opt_str("single-track"),
        start_position: (start_position * 1000.0) as u32,
    }
}

struct Main {
	name: String,
    cache: Option<Cache>,
    config: Config,
    handle: Handle,

#[cfg(not(target_os="windows"))]
    discovery: Option<DiscoveryStream>,
#[cfg(target_os="windows")]
    discovery: Option<String>,
    signal: IoStream<()>,

    spirc: Option<Spirc>,
    spirc_task: Option<SpircTask>,
    connect: Box<Future<Item=Session, Error=io::Error>>,

    player: Option<Player>,

    shutdown: bool,
    authenticate: bool,
}

impl Main {
    fn new(handle: Handle,
           name: String,
           config: Config,
           cache: Option<Cache>,
           authenticate: bool,
    ) -> Main
    {
        Main {
            handle: handle.clone(),
            name: name,
            cache: cache,
            config: config,

            connect: Box::new(futures::future::empty()),
            discovery: None,
            spirc: None,
            spirc_task: None,

            player: None,

            shutdown: false,
            authenticate: authenticate,
            signal: tokio_signal::ctrl_c(&handle).flatten_stream().boxed(),
        }
    }

#[cfg(not(target_os="windows"))]
    fn discovery(&mut self) {
        let device_id = self.config.device_id.clone();
        let name = self.name.clone();

        self.discovery = Some(discovery(&self.handle, name, device_id).unwrap());
    }

    fn credentials(&mut self, credentials: Credentials) {
        let config = self.config.clone();
        let handle = self.handle.clone();

        let connection = Session::connect(config, credentials, self.cache.clone(), handle);

        self.connect = connection;
        self.spirc = None;
        let task = mem::replace(&mut self.spirc_task, None);
        if let Some(task) = task {
            self.handle.spawn(task);
        }
    }
}

impl Future for Main {
    type Item = ();
    type Error = ();

    fn poll(&mut self) -> Poll<(), ()> {
        loop {
            let mut progress = false;

#[cfg(not(target_os="windows"))] {
            if let Some(Async::Ready(Some(creds))) = self.discovery.as_mut().map(|d| d.poll().unwrap()) {
                if let Some(ref spirc) = self.spirc {
                    spirc.shutdown();
                }
                self.credentials(creds);

                progress = true;
            }
}

            if let Async::Ready(session) = self.connect.poll().unwrap() {
            	if self.authenticate {
					if !self.shutdown {
						if let Some(ref spirc) = self.spirc {
							spirc.shutdown();
						}
						self.shutdown = true;
					} else {
						return Ok(Async::Ready(()));
					}
            	}
            	else {
					self.connect = Box::new(futures::future::empty());

				    let mixer = (mixer::find(Some("softvol")).unwrap())();

					let audio_filter = mixer.get_audio_filter();
					let backend = audio_backend::find(None).unwrap();
					let player = Player::new(session.clone(), audio_filter, move || {
						(backend)(None)
					});

					self.player = Some(player.clone());

					let (spirc, spirc_task) = Spirc::new(self.name.clone(), session, player, mixer);
					self.spirc = Some(spirc);
					self.spirc_task = Some(spirc_task);
				}

                progress = true;
            }

            if let Async::Ready(Some(())) = self.signal.poll().unwrap() {
                if !self.shutdown {
                    if let Some(ref spirc) = self.spirc {
                        spirc.shutdown();
                    }
                    self.shutdown = true;
                } else {
                    return Ok(Async::Ready(()));
                }

                progress = true;
            }

            if let Some(ref mut spirc_task) = self.spirc_task {
                if let Async::Ready(()) = spirc_task.poll().unwrap() {
                    if self.shutdown {
                        return Ok(Async::Ready(()));
                    } else {
                        panic!("Spirc shut down unexpectedly");
                    }
                }
            }

            if !progress {
                return Ok(Async::NotReady);
            }
        }
    }
}

fn main() {
    let mut core = Core::new().unwrap();
    let handle = core.handle();

    let args: Vec<String> = std::env::args().collect();
    let Setup { name, config, cache, enable_discovery, credentials, authenticate, get_token, client_id, scope, single_track, start_position } = setup(&args);

	if let Some(ref track_id) = single_track {
		match credentials {
			Some(credentials) => {
				let backend = audio_backend::find(None).unwrap();

				let track = SpotifyId::from_base62(
									track_id.replace("spotty://", "")
									.replace("spotify://", "")
									.replace("track:", "")
									.as_str());

				let session = core.run(Session::connect(config, credentials, None, handle)).unwrap();

				let player = Player::new(session.clone(), None, move || (backend)(None));

				core.run(player.load(track, true, start_position)).unwrap();
			}
			None => {
				println!("Missing credentials");
			}
	    }
	}
	else if authenticate && !enable_discovery {
        core.run(Session::connect(config, credentials.unwrap(), cache.clone(), handle)).unwrap();
		println!("authorized");
	}
	else if get_token {
		if let Some(client_id) = client_id {
			let session = core.run(Session::connect(config, credentials.unwrap(), cache.clone(), handle)).unwrap();
			let scope = scope.unwrap_or("playlist-read-private,playlist-read-collaborative".to_string());
		    let url = format!("hm://keymaster/token/authenticated?client_id={}&scope={}", client_id, scope);
			core.run(session.mercury().get(url).map(move |response| {
		        let data = response.payload.first().expect("Empty payload");
		        let token = String::from_utf8(data.clone()).unwrap();
				println!("{}", token);
		    }).boxed()).unwrap();
		}
		else {
			println!("Use --client-id to provide a CLIENT_ID");
		}
	}
	else {
		let mut task = Main::new(handle, name, config, cache, authenticate);
		if enable_discovery {
#[cfg(not(target_os="windows"))]
			task.discovery();
		}
		if let Some(credentials) = credentials {
			task.credentials(credentials);
		}

		core.run(task).unwrap()
    }
}

<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

use std::fs;
use std::path::{Path,PathBuf};
use std::fmt;
use std::slice::Iter;

mod arguments;
mod utils;

use utils::SizeDisplay;

struct Entry {
    path: PathBuf,
    self_size: u64,
    children: Vec<Entry>,
}

impl Entry {
    fn from_metadata(path: PathBuf, metadata: &fs::Metadata) -> Result<Entry, String> {
        let children = if metadata.is_dir() {
            Entry::in_directory(&path)
        } else if metadata.is_file() {
            vec![]
        } else {
            return Err("not a file or directory".to_string());
        };

        Ok(Entry {children: children, path: path, self_size: metadata.len()})
    }

    fn for_path(path: PathBuf) -> Result<Entry, String> {
        match fs::metadata(&path) {
            Ok(metadata) => Entry::from_metadata(path, &metadata),
            Err(error) => Err(utils::describe_io_error(error))
        }
    }

    fn in_directory(dir: &Path) -> Vec<Entry> {
        match fs::read_dir(dir) {
            Ok(read_dir) => {
                read_dir.filter_map(|child| {
                    match child {
                        Ok(child) => Entry::for_path(child.path()).ok(),
                        Err(..) => None,
                    }
                }).collect()
            },
            Err(..) => Vec::new()
        }
    }

    fn descendent_size(&self) -> u64 {
        self.children.iter().map(|child| child.size()).fold(0, |a, n| a + n)
    }
}

trait DisplayableEntry : fmt::Display + Sized {
    type Child: DisplayableEntry;

    fn size(&self) -> u64;
    fn name(&self) -> &str;
    fn children_iter(&self) -> Iter<Self::Child>;
}

impl DisplayableEntry for Entry {
    type Child = Entry;

    fn size(&self) -> u64 {
        self.self_size + self.descendent_size()
    }

    fn name(&self) -> &str {
        // Converting paths to strings might fail. We start by trying to convert the
        // filename. If the path is something like ".", it will fail as there is no "file
        // name" in that path. We fall back to the entire path in that case. If that also
        // fails, we fall back to hardcoded representation.
        let file_name = self.path.file_name().and_then(|s| s.to_str());
        file_name.or_else(|| self.path.to_str()).unwrap_or("(no name)")
    }

    fn children_iter(&self) -> Iter<Entry> {
        self.children.iter()
    }
}

impl fmt::Display for Entry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.name(), self.size().as_size_display())
    }
}

struct Root {
    entry: Entry,
}

impl Root {
    fn new(entry: Entry) -> Root {
        Root{entry: entry}
    }
}

impl DisplayableEntry for Root {
    type Child = Entry;

    fn size(&self) -> u64 {
        self.entry.size()
    }

    fn name(&self) -> &str {
        self.entry.path.to_str().unwrap_or("(no name)")
    }

    fn children_iter(&self) -> Iter<Entry> {
        self.entry.children_iter()
    }
}

impl fmt::Display for Root {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.name(), self.entry.size().as_size_display())
    }
}

fn print_tree<T: DisplayableEntry>(entry: &T) {
    print_indented_tree(entry, 0);
}

fn print_indented_tree<T: DisplayableEntry>(entry: &T, indent: usize) {
    println!("{0:1$}{2}", "", indent * 2, entry);
    for child in entry.children_iter() {
        print_indented_tree(child, indent + 1);
    }
}

fn main() {
    let options = arguments::parse();
    for root in options.roots() {
        match Entry::for_path(root.clone()) {
            Ok(root) => print_tree(&Root::new(root)),
            Err(message) =>
                println!("{} ERROR: {}", root.to_string_lossy(), message)
        }
    }
}
<commit_msg>Actually sort entries in the tree<commit_after>#[macro_use]
extern crate clap;

use std::fs;
use std::path::{Path,PathBuf};
use std::fmt;
use std::slice::Iter;

mod arguments;
mod utils;

use utils::SizeDisplay;

struct Entry {
    path: PathBuf,
    self_size: u64,
    children: Vec<Entry>,
}

impl Entry {
    fn from_metadata(path: PathBuf, metadata: &fs::Metadata) -> Result<Entry, String> {
        let mut children = if metadata.is_dir() {
            Entry::in_directory(&path)
        } else if metadata.is_file() {
            vec![]
        } else {
            return Err("not a file or directory".to_string());
        };

        children.sort_by(
            // Note: We change the ordering to get in descending order
            |a, b| b.size().cmp(&a.size())
        );

        Ok(Entry {children: children, path: path, self_size: metadata.len()})
    }

    fn for_path(path: PathBuf) -> Result<Entry, String> {
        match fs::metadata(&path) {
            Ok(metadata) => Entry::from_metadata(path, &metadata),
            Err(error) => Err(utils::describe_io_error(error))
        }
    }

    fn in_directory(dir: &Path) -> Vec<Entry> {
        match fs::read_dir(dir) {
            Ok(read_dir) => {
                read_dir.filter_map(|child| {
                    match child {
                        Ok(child) => Entry::for_path(child.path()).ok(),
                        Err(..) => None,
                    }
                }).collect()
            },
            Err(..) => Vec::new()
        }
    }

    fn descendent_size(&self) -> u64 {
        self.children.iter().map(|child| child.size()).fold(0, |a, n| a + n)
    }
}

trait DisplayableEntry : fmt::Display + Sized {
    type Child: DisplayableEntry;

    fn size(&self) -> u64;
    fn name(&self) -> &str;
    fn children_iter(&self) -> Iter<Self::Child>;
}

impl DisplayableEntry for Entry {
    type Child = Entry;

    fn size(&self) -> u64 {
        self.self_size + self.descendent_size()
    }

    fn name(&self) -> &str {
        // Converting paths to strings might fail. We start by trying to convert the
        // filename. If the path is something like ".", it will fail as there is no "file
        // name" in that path. We fall back to the entire path in that case. If that also
        // fails, we fall back to hardcoded representation.
        let file_name = self.path.file_name().and_then(|s| s.to_str());
        file_name.or_else(|| self.path.to_str()).unwrap_or("(no name)")
    }

    fn children_iter(&self) -> Iter<Entry> {
        self.children.iter()
    }
}

impl fmt::Display for Entry {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.name(), self.size().as_size_display())
    }
}

struct Root {
    entry: Entry,
}

impl Root {
    fn new(entry: Entry) -> Root {
        Root{entry: entry}
    }
}

impl DisplayableEntry for Root {
    type Child = Entry;

    fn size(&self) -> u64 {
        self.entry.size()
    }

    fn name(&self) -> &str {
        self.entry.path.to_str().unwrap_or("(no name)")
    }

    fn children_iter(&self) -> Iter<Entry> {
        self.entry.children_iter()
    }
}

impl fmt::Display for Root {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} {}", self.name(), self.entry.size().as_size_display())
    }
}

fn print_tree<T: DisplayableEntry>(entry: &T) {
    print_indented_tree(entry, 0);
}

fn print_indented_tree<T: DisplayableEntry>(entry: &T, indent: usize) {
    println!("{0:1$}{2}", "", indent * 2, entry);
    for child in entry.children_iter() {
        print_indented_tree(child, indent + 1);
    }
}

fn main() {
    let options = arguments::parse();
    for root in options.roots() {
        match Entry::for_path(root.clone()) {
            Ok(root) => print_tree(&Root::new(root)),
            Err(message) =>
                println!("{} ERROR: {}", root.to_string_lossy(), message)
        }
    }
}
<|endoftext|>


<commit_before>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

/// Rosten
/// Track Bring packages in Rust
/// For testing use "TESTPACKAGE-AT-PICKUPPOINT" as tracking number
/// https://www.mybring.com/tracking/api

extern crate serde;
extern crate serde_json;
extern crate hyper;
extern crate clap;

mod json_response;
// mod json_test;
use std::io::Read;
use hyper::{Client};
use clap::{Arg, App};
use json_response::{BringResponse, Json};
// use json_test::Json;
pub fn main() {
    let matches = App::new("Rosten")
        .version("1.0")
        .author("Stian Eklund. <stiane@protonmail.com>")
        .about("Get shipment status of your Bring / Posten packages")
        .arg(Arg::with_name("track")
             .help("Get package status")
             .short("t")
             .long("track")
             .takes_value(true))
        .get_matches();

    let input = matches.value_of("track").unwrap();
    let url = format!("https://tracking.bring.com/tracking.json?q={}", input);
    let url = url.as_str(); // convert &str into a String

    fn get_content(url: &str) -> hyper::Result<String> {
        let client = Client::new();
        let mut response = try!(client.get(url).send());
        let mut buf = String::new();
        try!(response.read_to_string(&mut buf));
        Ok(buf)
    }

    let buf = get_content(url).unwrap();

    fn deserialize(buf: &str) {
        // let deserialized: BringResponse = serde_json::from_str(&buf).unwrap();
        let deserialized: Result<BringResponse, serde_json::Error> = serde_json::from_str(&buf);
        match deserialized {
            Ok(deserialized) => {
                let sets = deserialized.consignmentSet;
                for i in 0..sets.len() {
                    let consignment_set = &sets[i];
                    for x in 0..consignment_set.packageSet.len() {
                        let package_set = &consignment_set.packageSet[x];
                        println!("Package number: {}", package_set.packageNumber);
                        println!("Sender name: {}", package_set.senderName);
                        for n in 0..package_set.eventSet.len() {
                            let event_set = &package_set.eventSet[n];
                            println!("Event status: {}", event_set.status);
                            println!("Event description: {}", event_set.description);
                            break;
                        }
                    }
                }
            },
            Err(_) => deserialize_err(&buf)
        }
    }
    fn deserialize_err(buf: &str) {
        let deserialized: Result<Json, serde_json::Error> = serde_json::from_str(&buf);
        match deserialized {
            Ok(deserialized) => {
                let set = deserialized.consignmentSet;
                println!("Check your tracking number. {:?}, code: {:?}", &set[0].error.message, &set[0].error.code);
            },
            Err(_) => println!("Error deserializing error response")
        }
    }
    deserialize(&buf);
}
<commit_msg>remove unused code<commit_after>#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]

/// Rosten
/// Track Bring packages in Rust
/// For testing use "TESTPACKAGE-AT-PICKUPPOINT" as tracking number
/// https://www.mybring.com/tracking/api

extern crate serde;
extern crate serde_json;
extern crate hyper;
extern crate clap;

mod json_response;
use std::io::Read;
use hyper::{Client};
use clap::{Arg, App};
use json_response::{BringResponse, Json};

pub fn main() {
    let matches = App::new("Rosten")
        .version("1.0")
        .author("Stian Eklund. <stiane@protonmail.com>")
        .about("Get shipment status of your Bring / Posten packages")
        .arg(Arg::with_name("track")
             .help("Get package status")
             .short("t")
             .long("track")
             .takes_value(true))
        .get_matches();

    let input = matches.value_of("track").unwrap();
    let url = format!("https://tracking.bring.com/tracking.json?q={}", input);
    let url = url.as_str(); // convert &str into a String

    fn get_content(url: &str) -> hyper::Result<String> {
        let client = Client::new();
        let mut response = try!(client.get(url).send());
        let mut buf = String::new();
        try!(response.read_to_string(&mut buf));
        Ok(buf)
    }

    let buf = get_content(url).unwrap();

    fn deserialize(buf: &str) {
        let deserialized: Result<BringResponse, serde_json::Error> = serde_json::from_str(&buf);
        match deserialized {
            Ok(deserialized) => {
                let sets = deserialized.consignmentSet;
                for i in 0..sets.len() {
                    let consignment_set = &sets[i];

                    for x in 0..consignment_set.packageSet.len() {
                        let package_set = &consignment_set.packageSet[x];
                        println!("Package number: {}", package_set.packageNumber);
                        println!("Sender name: {}", package_set.senderName);
                        for n in 0..package_set.eventSet.len() {
                            let event_set = &package_set.eventSet[n];
                            println!("Event status: {}", event_set.status);
                            println!("Event description: {}", event_set.description);
                            break;
                        }
                    }
                }
            },
            Err(_) => deserialize_err(&buf)
        }
    }
    fn deserialize_err(buf: &str) {
        let deserialized: Result<Json, serde_json::Error> = serde_json::from_str(&buf);
        match deserialized {
            Ok(deserialized) => {
                let set = deserialized.consignmentSet;
                println!("Check your tracking number. {:?}, code: {:?}", &set[0].error.message, &set[0].error.code);
            },
            Err(_) => println!("Error deserializing error response")
        }
    }
    deserialize(&buf);
}
<|endoftext|>


<commit_before>extern crate csv;
#[macro_use]
extern crate lazy_static;
extern crate prettytable;
extern crate regex;
extern crate rusqlite;
extern crate rustyline;

use std::env;
use std::error::Error;

fn _normalize_col(col: &str) -> String {
    lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)").unwrap();
    }
    return RE.replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("?", "");
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &Vec<String>) {
    let create_columns = cols.iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(&format!("CREATE TABLE {} ({})", table_name, create_columns), &[])
        .unwrap();
}

fn _insert_row(
    db: &mut rusqlite::Connection,
    table_name: &str,
    row: Vec<String>,
    cols: &Vec<String>,
) {
    let placeholders = cols.iter()
        .map(|_| "?")
        .collect::<Vec<_>>()
        .join(", ");
    let mut stmt = db.prepare(&format!(
        "INSERT INTO {} VALUES ({})",
        table_name,
        placeholders
    )).unwrap();

    let params = row.iter().map(|p| p as &rusqlite::types::ToSql).collect::<Vec<&rusqlite::types::ToSql>>();
    let res = stmt.execute(&params);
    assert!(res.is_ok());
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: String,
) -> Vec<String> {
    let mut num_rows = 0;
    let mut reader = csv::Reader::from_path(path).unwrap();

    let normalized_cols = reader
        .headers()
        .unwrap()
        .iter()
        .map(_normalize_col)
        .collect();
    _create_table(db, table_name, &normalized_cols);

    for row in reader.records() {
        _insert_row(db, table_name, row.unwrap().iter().map(|s| s.to_string()).collect(), &normalized_cols);
        num_rows += 1;
    }

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    return normalized_cols;
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(value: rusqlite::types::ValueRef) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Text(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) => String::from_utf8(v.to_vec()).unwrap()
        };
        Ok(FromAnySqlType{value: result})
    }
}

fn _print_table(conn: &mut rusqlite::Connection, line: &str) {
    let mut table = prettytable::Table::new();
    table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
    let mut stmt = match conn.prepare(&line) {
        Ok(stmt) => stmt,
        Err(e) => {
            println!("{}", e.description());
            return;
        }
    };
    let mut results = stmt.query(&[]).unwrap();
    while let Some(Ok(r)) = results.next() {
        let mut row = prettytable::Row::new(vec![]);
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i);
            row.add_cell(prettytable::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    table.printstd();
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [b' ', b'(', b')', b','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        return SimpleWordCompleter { words: words };
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    fn hint(&self, _line: &str, _pos: usize) -> Option<String> {
        return None;
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(&self, line: &str, pos: usize) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) =
            rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self.words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        return Ok((start, matches));
    }
}

fn main() {
    let mut paths = env::args().skip(1);

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = vec![
        "distinct",
        "select",
        "from",
        "group",
        "by",
        "order",
        "where",
        "count",
        "limit",
        "offset",
    ].iter()
        .map(|s| s.to_string())
        .collect::<Vec<String>>();

    if paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", paths.next().unwrap());
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in paths.enumerate() {
            let mut col_names = _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path);
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                rl.add_history_entry(line.clone());
                _print_table(&mut conn, &line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }
}
<commit_msg>cargo fmt<commit_after>extern crate csv;
#[macro_use]
extern crate lazy_static;
extern crate prettytable;
extern crate regex;
extern crate rusqlite;
extern crate rustyline;

use std::env;
use std::error::Error;

fn _normalize_col(col: &str) -> String {
    lazy_static! {
        static ref RE: regex::Regex = regex::Regex::new(r"\(.*?\)").unwrap();
    }
    return RE
        .replace_all(col, "")
        .to_lowercase()
        .trim()
        .replace(" ", "_")
        .replace(".", "_")
        .replace("?", "");
}

fn _create_table(db: &mut rusqlite::Connection, table_name: &str, cols: &Vec<String>) {
    let create_columns = cols
        .iter()
        .map(|c| format!("{} varchar", c))
        .collect::<Vec<String>>()
        .join(", ");
    db.execute(
        &format!("CREATE TABLE {} ({})", table_name, create_columns),
        &[],
    ).unwrap();
}

fn _insert_row(
    db: &mut rusqlite::Connection,
    table_name: &str,
    row: Vec<String>,
    cols: &Vec<String>,
) {
    let placeholders = cols.iter().map(|_| "?").collect::<Vec<_>>().join(", ");
    let mut stmt = db
        .prepare(&format!(
            "INSERT INTO {} VALUES ({})",
            table_name, placeholders
        )).unwrap();

    let params = row
        .iter()
        .map(|p| p as &rusqlite::types::ToSql)
        .collect::<Vec<&rusqlite::types::ToSql>>();
    let res = stmt.execute(&params);
    assert!(res.is_ok());
}

fn _load_table_from_path(
    db: &mut rusqlite::Connection,
    table_name: &str,
    path: String,
) -> Vec<String> {
    let mut num_rows = 0;
    let mut reader = csv::Reader::from_path(path).unwrap();

    let normalized_cols = reader
        .headers()
        .unwrap()
        .iter()
        .map(_normalize_col)
        .collect();
    _create_table(db, table_name, &normalized_cols);

    for row in reader.records() {
        _insert_row(
            db,
            table_name,
            row.unwrap().iter().map(|s| s.to_string()).collect(),
            &normalized_cols,
        );
        num_rows += 1;
    }

    println!(
        "Loaded {} rows into {}({})",
        num_rows,
        table_name,
        normalized_cols.join(", "),
    );
    return normalized_cols;
}

struct FromAnySqlType {
    value: String,
}

impl rusqlite::types::FromSql for FromAnySqlType {
    fn column_result(
        value: rusqlite::types::ValueRef,
    ) -> Result<FromAnySqlType, rusqlite::types::FromSqlError> {
        let result = match value {
            rusqlite::types::ValueRef::Null => "null".to_string(),
            rusqlite::types::ValueRef::Integer(v) => v.to_string(),
            rusqlite::types::ValueRef::Real(v) => v.to_string(),
            rusqlite::types::ValueRef::Text(v) => v.to_string(),
            rusqlite::types::ValueRef::Blob(v) => String::from_utf8(v.to_vec()).unwrap(),
        };
        Ok(FromAnySqlType { value: result })
    }
}

fn _print_table(conn: &mut rusqlite::Connection, line: &str) {
    let mut table = prettytable::Table::new();
    table.set_format(*prettytable::format::consts::FORMAT_NO_LINESEP_WITH_TITLE);
    let mut stmt = match conn.prepare(&line) {
        Ok(stmt) => stmt,
        Err(e) => {
            println!("{}", e.description());
            return;
        }
    };
    let mut results = stmt.query(&[]).unwrap();
    while let Some(Ok(r)) = results.next() {
        let mut row = prettytable::Row::new(vec![]);
        for i in 0..r.column_count() {
            let cell: FromAnySqlType = r.get(i);
            row.add_cell(prettytable::Cell::new(&cell.value));
        }
        table.add_row(row);
    }
    table.printstd();
}

struct SimpleWordCompleter {
    words: Vec<String>,
}

static BREAK_CHARS: [u8; 4] = [b' ', b'(', b')', b','];
impl SimpleWordCompleter {
    fn new(words: Vec<String>) -> SimpleWordCompleter {
        return SimpleWordCompleter { words: words };
    }
}

impl rustyline::Helper for SimpleWordCompleter {}

impl rustyline::hint::Hinter for SimpleWordCompleter {
    fn hint(&self, _line: &str, _pos: usize) -> Option<String> {
        return None;
    }
}

impl rustyline::highlight::Highlighter for SimpleWordCompleter {}

impl rustyline::completion::Completer for SimpleWordCompleter {
    type Candidate = String;

    fn complete(&self, line: &str, pos: usize) -> rustyline::Result<(usize, Vec<String>)> {
        let (start, word) = rustyline::completion::extract_word(line, pos, None, &BREAK_CHARS);

        let matches = self
            .words
            .iter()
            .filter(|w| w.starts_with(word))
            .cloned()
            .collect();
        return Ok((start, matches));
    }
}

fn main() {
    let mut paths = env::args().skip(1);

    let mut conn = rusqlite::Connection::open_in_memory().unwrap();

    let mut base_words = vec![
        "distinct", "select", "from", "group", "by", "order", "where", "count", "limit", "offset",
    ].iter()
    .map(|s| s.to_string())
    .collect::<Vec<String>>();

    if paths.len() == 1 {
        let mut col_names = _load_table_from_path(&mut conn, "t", paths.next().unwrap());
        base_words.append(&mut col_names);
    } else {
        for (idx, path) in paths.enumerate() {
            let mut col_names = _load_table_from_path(&mut conn, &format!("t{}", idx + 1), path);
            base_words.append(&mut col_names);
        }
    }

    let completer = SimpleWordCompleter::new(base_words);
    let mut rl = rustyline::Editor::new();
    rl.set_helper(Some(completer));
    loop {
        match rl.readline("> ") {
            Ok(line) => {
                if line.trim().is_empty() {
                    continue;
                }
                rl.add_history_entry(line.clone());
                _print_table(&mut conn, &line);
            }
            Err(rustyline::error::ReadlineError::Interrupted) => {
                println!("Interrupted");
                continue;
            }
            Err(rustyline::error::ReadlineError::Eof) => {
                break;
            }
            Err(err) => {
                println!("Error: {}", err);
                break;
            }
        }
    }
}
<|endoftext|>


<commit_before>#![feature(io)]
//#![feature(path)]

extern crate time;

use std::old_io::net::udp::UdpSocket;
use std::old_io::net::ip::{ Ipv4Addr, SocketAddr };
//use std::old_io::net::pipe::UnixStream;

fn main() {
  let msg = format!("{} hi from Rust", time::now().rfc3339());

  let addr = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 514 };
  let client_addr = SocketAddr { ip: Ipv4Addr(0,0,0,0), port: 0 };
  let mut udp = match UdpSocket::bind(client_addr) {
    Err(e) => panic!("error binding to {} -- {}", addr, e),
    Ok(s) => s
  };

  //let path = Path::new("unix:///var/run/syslog");
  //let mut stream = match UnixStream::connect(&path) {
  //  Err(e) => panic!("error connecting to path -- {}", e),
  //  Ok(s) => s,
  //};

  //let stream_result = stream.write_line(
  //  "2012-07-22T00:06:26-00:00 somehost Rust console 2 Hi from Rust");
  //match stream_result {
  //    Err(e) => panic!("err {}", e),
  //    Ok(_) => println!("stream send result ok")
  //};

  let udp_result = udp.send_to(msg.as_bytes(), addr);
  match udp_result {
      Err(e) => panic!("err {}", e),
      Ok(_) => println!("upd send result ok")
  };
}
<commit_msg>little more structure<commit_after>#![feature(old_io)]
//#![feature(path)]

extern crate time;

use std::old_io::IoError;
use std::old_io::net::udp::UdpSocket;
use std::old_io::net::ip::{ Ipv4Addr, SocketAddr };
//use std::old_io::net::pipe::UnixStream;

struct Syslog {
  host: SocketAddr,
  socket: UdpSocket
}

impl Syslog {
   fn new(host: SocketAddr) -> Syslog {
     Syslog {
       host: host,
       socket: match UdpSocket::bind(SocketAddr { ip: Ipv4Addr(0,0,0,0), port: 0 }) {
         Err(e) => panic!("error binding to local addr {}", e),
         Ok(s) => s
       }
     }
   }

   fn log(&mut self, msg: &str) -> Result<(), IoError> {
     self.socket.send_to(msg.as_bytes(), self.host)
   }
}

fn main() {
  let msg = format!("<19>5 {} mbp hi from Rust", time::now().rfc3339());
  println!("msg -> {}", msg);
  let host = SocketAddr { ip: Ipv4Addr(127,0,0,1), port: 514 };
  let mut syslog = Syslog::new(host);
  match syslog.log(&msg) {
    Err(e) => panic!("error sending -- {}", e),
    Ok(_) => println!("sent")
  };
  //let path = Path::new("unix:///var/run/syslog");
  //let mut stream = match UnixStream::connect(&path) {
  //  Err(e) => panic!("error connecting to path -- {}", e),
  //  Ok(s) => s,
  //};

  //let stream_result = stream.write_line(
  //  "2012-07-22T00:06:26-00:00 somehost Rust console 2 Hi from Rust");
  //match stream_result {
  //    Err(e) => panic!("err {}", e),
  //    Ok(_) => println!("stream send result ok")
  //};

}
<|endoftext|>


<commit_before>struct Item(str);

struct Location {
    // literal string as this is static
    description: Box<str>,
    items: Vec<Box<Item>>,
}

fn main() {
    println!("Hello, world!");
}
<commit_msg>String type mismatch. Item needs a string reference rather than a copy.<commit_after>struct Item(str);

struct Location {
    // literal string as this is static
    description: Box<str>,
    items: Vec<Box<Item>>,
}

fn main() {
    let item1 = Item("Little key");
    let item2 = Item("Big key");
    let hall = Location{ description: "A wide open space. Streams of lava flow on both sides of the entry gate.",
                         items: vec![item1, item2] };
}
<|endoftext|>


<commit_before>extern crate mush;

use mush::{ToolPane};

extern crate conrod;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate piston;

use conrod::{Background, Button, Colorable, Labelable, Sizeable, Theme, Ui,
             Positionable, TextBox, CustomWidget};
use glutin_window::GlutinWindow;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event::*;
use piston::window::{ WindowSettings, Size };
use std::path::Path;

//fn resized(w:u32,h:u32) {width=w; height=h;}

fn main () {
    mush::graphs();

    let mut width = 1024;
    let mut height = 768;

    let opengl = OpenGL::_3_2;
    let mut window = GlutinWindow::new(
        opengl,
        WindowSettings::new(
            "mush -> graph library gui".to_string(),
            Size { width: width, height: height }
            )
            .exit_on_esc(true)
            .samples(4)
       );

   // window.window.set_window_resize_callback(Some(resized as fn(u32,u32)));

    let event_iter = window.events().ups(180).max_fps(60);
    let mut gl = GlGraphics::new(opengl);
    let font_path = Path::new("fonts/SourceCodePro-Regular.otf");
    let theme = Theme::default();
    let glyph_cache = GlyphCache::new(&font_path).unwrap();
    let ui = &mut Ui::new(glyph_cache, theme);

    let mut count: u32 = 0;

    for event in event_iter {
        ui.handle_event(&event);
        if let Some(args) = event.render_args() {
            gl.draw(args.viewport(), |_, gl| {

                // Draw the background.
                Background::new().rgb(0.2, 0.2, 0.2).draw(ui, gl);

                TextBox::new(&mut "Node".to_string())
                    .dimensions(100.0,60.0)
                    .xy(width as f64/2.0*-1.0+100.0,0.0)
                    .react(|_s: &mut String|{println!("{:?}",_s)})
                    .set(0,ui);

                // Draw the button and increment count if pressed..
                Button::new()
                    .dimensions(80.0, 40.0)
                    .label(&args.width.to_string())
                    .rgba(0.9,0.9,0.9,0.8)
                    .right(10.0)
                    .react(|| {})
                    .set(1, ui);

                mush::node::Node::new()
                    .label("Thingy")
                    .xy(100.0, 100.0)
                    .dimensions(100.0, 40.0)
                    .set(2, ui);

                // Draw our Ui!
                ui.draw(gl);

            });
        }
    }

}
<commit_msg>Conrod widgets still not playing nicely with our custom widget<commit_after>extern crate mush;

use mush::{ToolPane};

extern crate conrod;
extern crate glutin_window;
extern crate opengl_graphics;
extern crate piston;

use conrod::{Background, Button, Colorable, Labelable, Sizeable, Theme, Ui,
             Positionable, TextBox, CustomWidget};
use glutin_window::GlutinWindow;
use opengl_graphics::{ GlGraphics, OpenGL };
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event::*;
use piston::window::{ WindowSettings, Size };
use std::path::Path;

//fn resized(w:u32,h:u32) {width=w; height=h;}

fn main () {
    mush::graphs();

    let mut width = 1024;
    let mut height = 768;

    let opengl = OpenGL::_3_2;
    let mut window = GlutinWindow::new(
        opengl,
        WindowSettings::new(
            "mush -> graph library gui".to_string(),
            Size { width: width, height: height }
            )
            .exit_on_esc(true)
            .samples(4)
       );

   // window.window.set_window_resize_callback(Some(resized as fn(u32,u32)));

    let event_iter = window.events().ups(180).max_fps(60);
    let mut gl = GlGraphics::new(opengl);
    let font_path = Path::new("fonts/SourceCodePro-Regular.otf");
    let theme = Theme::default();
    let glyph_cache = GlyphCache::new(&font_path).unwrap();
    let ui = &mut Ui::new(glyph_cache, theme);

    let mut count: u32 = 0;

    for event in event_iter {
        ui.handle_event(&event);
        if let Some(args) = event.render_args() {
            gl.draw(args.viewport(), |_, gl| {

                // Draw the background.
                // Background::new().rgb(0.2, 0.2, 0.2).draw(ui, gl);

                // TextBox::new(&mut "Node".to_string())
                //     .dimensions(100.0,60.0)
                //     .xy(width as f64/2.0*-1.0+100.0,0.0)
                //     .react(|_s: &mut String|{println!("{:?}",_s)})
                //     .set(0,ui);

                // // Draw the button and increment count if pressed..
                // Button::new()
                //     .dimensions(80.0, 40.0)
                //     .label(&args.width.to_string())
                //     .rgba(0.9,0.9,0.9,0.8)
                //     .right(10.0)
                //     .react(|| {})
                //     .set(1, ui);

                mush::node::Node::new()
                    .label("Thingy")
                    .xy(100.0, 100.0)
                    .dimensions(100.0, 40.0)
                    .set(2, ui);

                // Draw our Ui!
                ui.draw(gl);

            });
        }
    }

}
<|endoftext|>


<commit_before>#[macro_use]
extern crate nom;

use std::str;
use nom::{
    IResult,
    ErrorKind,
    is_hex_digit
};

fn is_pn_chars_base(c: char) -> bool {
    let u = c as u32;
    match u {
        0x41    ... 0x5A   | 0x61   ... 0x7A   |
        0xC0    ... 0xD6   | 0xD8   ... 0xF6   |
        0xF8    ... 0x2FF  | 0x370  ... 0x37D  |
        0x37F   ... 0x1FFF | 0x200C ... 0x200D |
        0x2C00  ... 0x2FEF | 0x3001 ... 0xD7FF |
        0xF900  ... 0xFDCF | 0xFDF0 ... 0xFFFD |
        0x10000 ... 0xEFFFF
          => true,
        _ => false,
    }
}

fn is_pn_chars_u(c: char) -> bool {
    is_pn_chars_base(c) || c == '_'
}

fn is_pn_chars(c: char) -> bool {
    let u = c as u32;
    match u {
        0x2d | 0xB7 | 0x30...0x39 | 0x300...0x36F | 0x203F...0x2040
          => true,
        _ => is_pn_chars_base(c),
    }
}

fn is_pn_local_esc(c: char) -> bool {
    match "_~.-!$&'()*+,;=/?#@%".find(c) {
        Some(_) => true,
        _       => false,
    }
}

fn is_ws(c: char) -> bool {
    let u = c as u32;
    u == 0x20 || u == 0x9 || u == 0xD || u == 0xA
}

fn is_anon(c: char) -> bool {
    c == '[' || c == ']' || is_ws(c)
}

/* [161s] WS */
named!(ws<&str, &str>, take_while_s!(is_ws));

/* [162s] ANON */
named!(anon<&str, &str>, verify!(
    take_while_s!(is_anon),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                c == '['
            } else if idx == len - 1 {
                c == ']'
            } else {
                is_ws(c)
            }
        })
    }
));

/* [163s] PN_CHARS_BASE */
named!(pn_chars_base<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_base(c)
        }
        false
    }
));

/* [164s] PN_CHARS_U */
named!(pn_chars_u<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_u(c)
        }
        false
    }
));

/* [166s] PN_CHARS */
named!(pn_chars<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars(c)
        }
        false
    }
));

/* [167s] PN_PREFIX */
named!(pn_prefix<&str, &str>, verify!(
    take_until!(":"),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                is_pn_chars_base(c)
            } else if idx == len - 1 {
                c != '.'
            } else {
                is_pn_chars(c) || c == '.'
            }
        })
    }
));

fn is_pn_local(c: char) -> bool {
    is_pn_chars(c) ||
    c == '.'  || c == ':'              ||
    c == '%'  || is_hex_digit(c as u8) ||
    c == '\\' || is_pn_local_esc(c)
}
/* [168s] PN_LOCAL */
named!(pn_local<&str, &str>, verify!(
    take_while_s!(is_pn_local),
    |val:&str| {
        let len = val.char_indices().count();
        let mut percent_count = 0;
        let mut pn_local_esc_count = 0;
        val.char_indices().all(|(idx, c)| {
            if percent_count > 0 {
                percent_count = percent_count - 1;
                is_hex_digit(c as u8)
            } else if c == '%' {
                percent_count = 2;
                true
            } else if pn_local_esc_count > 0 {
                pn_local_esc_count = pn_local_esc_count - 1;
                is_pn_local_esc(c)
            } else if c == '\\' {
                pn_local_esc_count = 1;
                true
            } else if idx == 0 {
                is_pn_chars_u(c) || c == ':'
            } else if idx == len - 1 {
                is_pn_chars(c) || c == ':'
            } else {
                is_pn_chars(c) || c == ':' || c == '.'
            }
        }) && percent_count == 0 && pn_local_esc_count == 0
    }
));

/* [169s] PLX */
named!(plx<&str, &str>, alt!(percent | pn_local_esc));

/* [170s] PERCENT */
named!(percent<&str, &str>, verify!(
    take_s!(3),
    |val:&str| {
        let bytes = val.as_bytes();
        bytes[0] == 0x25 && is_hex_digit(bytes[1]) && is_hex_digit(bytes[2])
    }
));

/* [172s]  PN_LOCAL_ESC */
named!(pn_local_esc<&str, &str>, verify!(
    take_s!(2),
    |val:&str| {
        let c1 = val.chars().nth(0).unwrap();
        let c2 = val.chars().nth(1).unwrap();
        c1 == '\\' && is_pn_local_esc(c2)
    }
));

fn main() {
    assert_eq!(ws("   a")                , IResult::Done("a", "   ")          );
    assert_eq!(anon("[ ]a")              , IResult::Done("a", "[ ]")          );
    assert_eq!(pn_chars_base("a%2Ab")    , IResult::Done("%2Ab", "a")         );
    assert_eq!(pn_chars_u("_a")          , IResult::Done("a"   , "_")         );
    assert_eq!(pn_chars("-_a")           , IResult::Done("_a"  , "-")         );
    assert_eq!(pn_chars(":a2Ab")         , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_prefix("hog.e:")       , IResult::Done(":", "hog.e")        );
    assert_eq!(pn_prefix("hoge.:")       , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:fuga piyo"), IResult::Done(" piyo", "hoge:fuga"));
    assert_eq!(pn_local("hoge:%28 piyo") , IResult::Done(" piyo", "hoge:%28") );
    assert_eq!(pn_local("hoge:%2 piyo")  , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:%__ piyo") , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:\\* piyo") , IResult::Done(" piyo", "hoge:\\*") );
    assert_eq!(pn_local("%28\\* piyo")   , IResult::Done(" piyo", "%28\\*")   );
    assert_eq!(pn_local("%28\\ piyo")    , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(plx("%2Abc")              , IResult::Done("bc"   , "%2A")      );
    assert_eq!(plx("\\.%2A")             , IResult::Done("%2A"  , "\\.")      );
    assert_eq!(percent("%2Abc")          , IResult::Done("bc"   , "%2A")      );
    assert_eq!(pn_local_esc("\\.a b c")  , IResult::Done("a b c", "\\.")      );
}
<commit_msg>Implement ECHAR<commit_after>#[macro_use]
extern crate nom;

use std::str;
use nom::{
    IResult,
    ErrorKind,
    is_hex_digit
};

fn is_pn_chars_base(c: char) -> bool {
    let u = c as u32;
    match u {
        0x41    ... 0x5A   | 0x61   ... 0x7A   |
        0xC0    ... 0xD6   | 0xD8   ... 0xF6   |
        0xF8    ... 0x2FF  | 0x370  ... 0x37D  |
        0x37F   ... 0x1FFF | 0x200C ... 0x200D |
        0x2C00  ... 0x2FEF | 0x3001 ... 0xD7FF |
        0xF900  ... 0xFDCF | 0xFDF0 ... 0xFFFD |
        0x10000 ... 0xEFFFF
          => true,
        _ => false,
    }
}

fn is_pn_chars_u(c: char) -> bool {
    is_pn_chars_base(c) || c == '_'
}

fn is_pn_chars(c: char) -> bool {
    let u = c as u32;
    match u {
        0x2d | 0xB7 | 0x30...0x39 | 0x300...0x36F | 0x203F...0x2040
          => true,
        _ => is_pn_chars_base(c),
    }
}

fn is_pn_local_esc(c: char) -> bool {
    match "_~.-!$&'()*+,;=/?#@%".find(c) {
        Some(_) => true,
        _       => false,
    }
}

fn is_ws(c: char) -> bool {
    let u = c as u32;
    u == 0x20 || u == 0x9 || u == 0xD || u == 0xA
}

fn is_anon(c: char) -> bool {
    c == '[' || c == ']' || is_ws(c)
}

fn is_echar(c: char) -> bool {
    c == '\\' || c == 't' || c == 'b' || c == 'n' || c == 'r' || c == 'f' || c == '"'
}

/* [159s] ECHAR */
named!(echar<&str, &str>, verify!(
    take_s!(2),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                c == '\\'
            } else {
                is_echar(c)
            }
        })
    }
));

/* [161s] WS */
named!(ws<&str, &str>, take_while_s!(is_ws));

/* [162s] ANON */
named!(anon<&str, &str>, verify!(
    take_while_s!(is_anon),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                c == '['
            } else if idx == len - 1 {
                c == ']'
            } else {
                is_ws(c)
            }
        })
    }
));

/* [163s] PN_CHARS_BASE */
named!(pn_chars_base<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_base(c)
        }
        false
    }
));

/* [164s] PN_CHARS_U */
named!(pn_chars_u<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars_u(c)
        }
        false
    }
));

/* [166s] PN_CHARS */
named!(pn_chars<&str, &str>, verify!(
    take_s!(1),
    |val:&str| {
        if let Some(c) = val.chars().next() {
            return is_pn_chars(c)
        }
        false
    }
));

/* [167s] PN_PREFIX */
named!(pn_prefix<&str, &str>, verify!(
    take_until!(":"),
    |val:&str| {
        let len = val.char_indices().count();
        val.char_indices().all(|(idx, c)| {
            if idx == 0 {
                is_pn_chars_base(c)
            } else if idx == len - 1 {
                c != '.'
            } else {
                is_pn_chars(c) || c == '.'
            }
        })
    }
));

fn is_pn_local(c: char) -> bool {
    is_pn_chars(c) ||
    c == '.'  || c == ':'              ||
    c == '%'  || is_hex_digit(c as u8) ||
    c == '\\' || is_pn_local_esc(c)
}
/* [168s] PN_LOCAL */
named!(pn_local<&str, &str>, verify!(
    take_while_s!(is_pn_local),
    |val:&str| {
        let len = val.char_indices().count();
        let mut percent_count = 0;
        let mut pn_local_esc_count = 0;
        val.char_indices().all(|(idx, c)| {
            if percent_count > 0 {
                percent_count = percent_count - 1;
                is_hex_digit(c as u8)
            } else if c == '%' {
                percent_count = 2;
                true
            } else if pn_local_esc_count > 0 {
                pn_local_esc_count = pn_local_esc_count - 1;
                is_pn_local_esc(c)
            } else if c == '\\' {
                pn_local_esc_count = 1;
                true
            } else if idx == 0 {
                is_pn_chars_u(c) || c == ':'
            } else if idx == len - 1 {
                is_pn_chars(c) || c == ':'
            } else {
                is_pn_chars(c) || c == ':' || c == '.'
            }
        }) && percent_count == 0 && pn_local_esc_count == 0
    }
));

/* [169s] PLX */
named!(plx<&str, &str>, alt!(percent | pn_local_esc));

/* [170s] PERCENT */
named!(percent<&str, &str>, verify!(
    take_s!(3),
    |val:&str| {
        let bytes = val.as_bytes();
        bytes[0] == 0x25 && is_hex_digit(bytes[1]) && is_hex_digit(bytes[2])
    }
));

/* [172s]  PN_LOCAL_ESC */
named!(pn_local_esc<&str, &str>, verify!(
    take_s!(2),
    |val:&str| {
        let c1 = val.chars().nth(0).unwrap();
        let c2 = val.chars().nth(1).unwrap();
        c1 == '\\' && is_pn_local_esc(c2)
    }
));

fn main() {
    assert_eq!(echar("\\ta")             , IResult::Done("a", "\\t")          );
    assert_eq!(ws("   a")                , IResult::Done("a", "   ")          );
    assert_eq!(anon("[ ]a")              , IResult::Done("a", "[ ]")          );
    assert_eq!(pn_chars_base("a%2Ab")    , IResult::Done("%2Ab", "a")         );
    assert_eq!(pn_chars_u("_a")          , IResult::Done("a"   , "_")         );
    assert_eq!(pn_chars("-_a")           , IResult::Done("_a"  , "-")         );
    assert_eq!(pn_chars(":a2Ab")         , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_prefix("hog.e:")       , IResult::Done(":", "hog.e")        );
    assert_eq!(pn_prefix("hoge.:")       , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:fuga piyo"), IResult::Done(" piyo", "hoge:fuga"));
    assert_eq!(pn_local("hoge:%28 piyo") , IResult::Done(" piyo", "hoge:%28") );
    assert_eq!(pn_local("hoge:%2 piyo")  , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:%__ piyo") , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(pn_local("hoge:\\* piyo") , IResult::Done(" piyo", "hoge:\\*") );
    assert_eq!(pn_local("%28\\* piyo")   , IResult::Done(" piyo", "%28\\*")   );
    assert_eq!(pn_local("%28\\ piyo")    , IResult::Error(ErrorKind::Verify)  );
    assert_eq!(plx("%2Abc")              , IResult::Done("bc"   , "%2A")      );
    assert_eq!(plx("\\.%2A")             , IResult::Done("%2A"  , "\\.")      );
    assert_eq!(percent("%2Abc")          , IResult::Done("bc"   , "%2A")      );
    assert_eq!(pn_local_esc("\\.a b c")  , IResult::Done("a b c", "\\.")      );
}
<|endoftext|>


<commit_before>extern crate ppbert;
#[macro_use] extern crate clap;

use std::io::{self, Read};
use std::fs::File;
use std::process::exit;
use std::time::Instant;

use clap::{Arg, App};

use ppbert::bertterm::{
    self,
    BertTerm,
    DEFAULT_INDENT_WIDTH,
    DEFAULT_MAX_TERMS_PER_LINE
};
use ppbert::error::Result;
use ppbert::parser;

fn main() {
    let matches = App::new("ppbert")
        .version(crate_version!())
        .author("Vincent Foley")
        .about("Pretty print structure encoded in Erlang's External Term Format")
        .arg(Arg::with_name("input_files")
             .value_name("FILES")
             .multiple(true))
        .arg(Arg::with_name("indent_width")
             .help("Number of spaces to indent nested terms")
             .value_name("num")
             .short("i")
             .long("--indent-width")
             .takes_value(true))
        .arg(Arg::with_name("max_per_line")
             .help("Number of spaces to indent nested terms")
             .value_name("num")
             .short("m")
             .long("--max-terms-per-line")
             .takes_value(true))
        .arg(Arg::with_name("verbose")
             .help("Enable verbose mode")
             .short("v")
             .long("--verbose"))
        .arg(Arg::with_name("parse")
             .help("Parse the input, don't pretty print it")
             .short("p")
             .long("--parse"))
        .arg(Arg::with_name("bert2")
             .help("Parse .bert2 files")
             .short("2")
             .long("bert2"))
        .arg(Arg::with_name("json")
             .help("Output in JSON")
             .short("j")
             .long("json"))
        .arg(Arg::with_name("transform-proplists")
             .help("Transform proplists into JSON objects (only valid with --json)")
             .long("transform-proplists"))
        .get_matches();

    let files: Vec<&str> = match matches.values_of("input_files") {
        Some(files) => files.collect(),
        None => vec!["-"]
    };

    let indent_level = value_t!(matches, "indent_width", usize)
        .unwrap_or(DEFAULT_INDENT_WIDTH);
    let max_per_line = value_t!(matches, "max_per_line", usize)
        .unwrap_or(DEFAULT_MAX_TERMS_PER_LINE);
    let verbose = matches.is_present("verbose");
    let parse_only = matches.is_present("parse");

    let transform_proplists =
        matches.is_present("transform-proplists");
    let parse_fn =
        if matches.is_present("bert2") {parse_bert2} else {parse_bert1};
    let output_fn =
        if matches.is_present("json") {
            if transform_proplists {
                bertterm::pp_json_proplist
            } else {
                bertterm::pp_json
            }
        } else {
            if transform_proplists {
                eprintln!("Warning: --transform-proplists is only valid with the --json flag");
            }
            bertterm::pp_bert
        };

    let mut return_code = 0;
    for file in files {
        let res = handle_file(file, parse_only, verbose,
                              indent_level, max_per_line,
                              parse_fn, output_fn);
        match res {
            Ok(()) => (),
            Err(e) => {
                return_code = 1;
                eprintln!("ppbert: {}: {}", file, e);
            }
        }
    }
    exit(return_code);
}

fn handle_file<T>(
    file: &str,
    parse_only: bool,
    verbose: bool,
    indent: usize,
    terms_per_line: usize,
    parse_fn: fn(Vec<u8>) -> Result<T>,
    pp_fn: fn(T, usize, usize) -> ()
) -> Result<()> {

    // Read file or stdin into buffer
    let mut buf: Vec<u8> = Vec::new();
    if file == "-" {
        let mut stdin = io::stdin();
        stdin.read_to_end(&mut buf)?;
    } else {
        let mut f = File::open(file)?;
        f.read_to_end(&mut buf)?;
    }

    // Parse input
    let now = Instant::now();
    let parse_output = parse_fn(buf)?;
    let dur1 = now.elapsed();

    if verbose {
        eprintln!("ppbert: parse time: {}.{:09}s", dur1.as_secs(), dur1.subsec_nanos());
    }

    // Early exit if parse-only
    if parse_only {
        return Ok(());
    }

    // Pretty print
    let now = Instant::now();
    pp_fn(parse_output, indent, terms_per_line);
    let dur2 = now.elapsed();

    if verbose {
        eprintln!("ppbert: print time: {}.{:09}s", dur2.as_secs(), dur2.subsec_nanos());
    }

    return Ok(());
}

fn parse_bert1(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    let term = parser.parse()?;
    return Ok(vec![term]);
}

fn parse_bert2(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    return parser.parse_bert2();
}
<commit_msg>Fix grammar in ppbert's help<commit_after>extern crate ppbert;
#[macro_use] extern crate clap;

use std::io::{self, Read};
use std::fs::File;
use std::process::exit;
use std::time::Instant;

use clap::{Arg, App};

use ppbert::bertterm::{
    self,
    BertTerm,
    DEFAULT_INDENT_WIDTH,
    DEFAULT_MAX_TERMS_PER_LINE
};
use ppbert::error::Result;
use ppbert::parser;

fn main() {
    let matches = App::new("ppbert")
        .version(crate_version!())
        .author("Vincent Foley")
        .about("Pretty print structure encoded in Erlang's External Term Format")
        .arg(Arg::with_name("input_files")
             .value_name("FILES")
             .multiple(true))
        .arg(Arg::with_name("indent_width")
             .help("Indents with <num> spaces")
             .value_name("num")
             .short("i")
             .long("--indent-width")
             .takes_value(true))
        .arg(Arg::with_name("max_per_line")
             .help("Prints at most <num> basic terms per line")
             .value_name("num")
             .short("m")
             .long("--max-terms-per-line")
             .takes_value(true))
        .arg(Arg::with_name("verbose")
             .help("Enables verbose mode")
             .short("v")
             .long("--verbose"))
        .arg(Arg::with_name("parse")
             .help("Parses the input, doesn't pretty print it")
             .short("p")
             .long("--parse"))
        .arg(Arg::with_name("bert2")
             .help("Parses .bert2 files")
             .short("2")
             .long("bert2"))
        .arg(Arg::with_name("json")
             .help("Outputs in JSON")
             .short("j")
             .long("json"))
        .arg(Arg::with_name("transform-proplists")
             .help("Transforms proplists into JSON objects (only valid with --json)")
             .long("transform-proplists"))
        .get_matches();

    let files: Vec<&str> = match matches.values_of("input_files") {
        Some(files) => files.collect(),
        None => vec!["-"]
    };

    let indent_level = value_t!(matches, "indent_width", usize)
        .unwrap_or(DEFAULT_INDENT_WIDTH);
    let max_per_line = value_t!(matches, "max_per_line", usize)
        .unwrap_or(DEFAULT_MAX_TERMS_PER_LINE);
    let verbose = matches.is_present("verbose");
    let parse_only = matches.is_present("parse");

    let transform_proplists =
        matches.is_present("transform-proplists");
    let parse_fn =
        if matches.is_present("bert2") {parse_bert2} else {parse_bert1};
    let output_fn =
        if matches.is_present("json") {
            if transform_proplists {
                bertterm::pp_json_proplist
            } else {
                bertterm::pp_json
            }
        } else {
            if transform_proplists {
                eprintln!("Warning: --transform-proplists is only valid with the --json flag");
            }
            bertterm::pp_bert
        };

    let mut return_code = 0;
    for file in files {
        let res = handle_file(file, parse_only, verbose,
                              indent_level, max_per_line,
                              parse_fn, output_fn);
        match res {
            Ok(()) => (),
            Err(e) => {
                return_code = 1;
                eprintln!("ppbert: {}: {}", file, e);
            }
        }
    }
    exit(return_code);
}

fn handle_file<T>(
    file: &str,
    parse_only: bool,
    verbose: bool,
    indent: usize,
    terms_per_line: usize,
    parse_fn: fn(Vec<u8>) -> Result<T>,
    pp_fn: fn(T, usize, usize) -> ()
) -> Result<()> {

    // Read file or stdin into buffer
    let mut buf: Vec<u8> = Vec::new();
    if file == "-" {
        let mut stdin = io::stdin();
        stdin.read_to_end(&mut buf)?;
    } else {
        let mut f = File::open(file)?;
        f.read_to_end(&mut buf)?;
    }

    // Parse input
    let now = Instant::now();
    let parse_output = parse_fn(buf)?;
    let dur1 = now.elapsed();

    if verbose {
        eprintln!("ppbert: parse time: {}.{:09}s", dur1.as_secs(), dur1.subsec_nanos());
    }

    // Early exit if parse-only
    if parse_only {
        return Ok(());
    }

    // Pretty print
    let now = Instant::now();
    pp_fn(parse_output, indent, terms_per_line);
    let dur2 = now.elapsed();

    if verbose {
        eprintln!("ppbert: print time: {}.{:09}s", dur2.as_secs(), dur2.subsec_nanos());
    }

    return Ok(());
}

fn parse_bert1(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    let term = parser.parse()?;
    return Ok(vec![term]);
}

fn parse_bert2(buf: Vec<u8>) -> Result<Vec<BertTerm>> {
    let mut parser = parser::Parser::new(buf);
    return parser.parse_bert2();
}
<|endoftext|>


<commit_before>extern crate reqwest;
extern crate select;
use std::io::Read;
use select::document::Document;
use select::predicate::{Name};

fn main() {
    // https://coinmarketcap.com/
    // http://crix.hu-berlin.de/
    let mut response = reqwest::get("https://coinmarketcap.com/#MXN").unwrap();
    assert!(response.status().is_success());

    let mut body = String::new();
    response.read_to_string(&mut body).expect("Read failed");

    let document = Document::from(body.as_str());
    for node in document.find(Name("tbody"))
        .next()
        .unwrap()
        .parent()
        .unwrap()
        .find(Name("tr"))
        .take(3)
    {
        /*  TODO:
            - Avoid table headers
            - Get coin name.
            - Get coin price.
            - Format and print coin name and price.
        */
        println!("{}", node.text());
    }

}<commit_msg>To-Do.<commit_after>extern crate reqwest;
extern crate select;
use std::io::Read;
use select::document::Document;
use select::predicate::{Name};

fn main() {
    // https://coinmarketcap.com/
    // http://crix.hu-berlin.de/
    let mut response = reqwest::get("https://coinmarketcap.com/").unwrap();
    assert!(response.status().is_success());

    let mut body = String::new();
    response.read_to_string(&mut body).expect("Read failed");

    let document = Document::from(body.as_str());
    for node in document.find(Name("tbody"))
        .next()
        .unwrap()
        //.parent()
        //.unwrap()
        .find(Name("tr"))
        .take(3)
    {
        /*  TODO:
            - Get coin name.
            - Get coin price.
            - Format and print coin name and price.
        */
        println!("{}", node.text());
    }

}<|endoftext|>


<commit_before>// Crates
extern crate chrono;
extern crate docopt;
extern crate rustc_serialize;
extern crate time;
extern crate libaltdate;

// Standard library imports

//Crate imports
use chrono::{NaiveDate, Datelike};
use docopt::Docopt;
use libaltdate::ddate;

const YEAR_OFFSET: i32 = 1900;

static VERSION: &'static str = "ddate (RUST implementaion of gnucoreutils) 0.1
Copyright (C) 2016 Marco Kaulea
License GPLv2: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Marco 'don' Kaulea.
";

const USAGE: &'static str = "
ddate

USAGE:
    ddate [options] [<timestamp>]
    ddate [options] date <date>

Options:
    -h --help               Dispaly this help message and exit
    -v --version            Output version information and exit
    -d --discordian         Switch to output discordian dates. This is the default.
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_timestamp: Option<i64>,
    arg_date: Option<String>,
    flag_help: bool,
    flag_version: bool,
    flag_discordian: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                             .and_then(|d| d.decode())
                             .unwrap_or_else(|e| e.exit());
    if args.flag_version {
        println!("{}", VERSION);
        return;
        }
    let date = if args.arg_date.is_some() {
        let input_date = NaiveDate::parse_from_str(args.arg_date.unwrap().as_str(),
                                                   "%Y-%m-%d").unwrap();
        ddate::convert(input_date.ordinal0() as u16,
                       input_date.year() as i32).unwrap()
    } else {
        let greg_date = match args.arg_timestamp {
            Some(t) => time::at(time::Timespec {sec: t, nsec: 0}),
            None => time::now(),
        };
        ddate::convert(greg_date.tm_yday as u16,
                                  greg_date.tm_year + YEAR_OFFSET).unwrap()
    };
    println!("{:?}, ", date);
}

<commit_msg>Restructure cli interface This allows the user to choose between isoformat and unix timestamp as input format.<commit_after>// Crates
extern crate chrono;
extern crate docopt;
extern crate rustc_serialize;
extern crate time;
extern crate libaltdate;

// Standard library imports

//Crate imports
use chrono::{NaiveDate, Datelike};
use docopt::Docopt;
use libaltdate::ddate;

const YEAR_OFFSET: i32 = 1900;

static VERSION: &'static str = "ddate (RUST implementaion of gnucoreutils) 0.1
Copyright (C) 2016 Marco Kaulea
License GPLv2: GNU GPL version 2 or later <http://gnu.org/licenses/gpl.html>.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Written by Marco 'don' Kaulea.
";

const USAGE: &'static str = "
ddate

USAGE:
    ddate [options] [<date>]

Options:
    -h --help               Dispaly this help message and exit
    -v --version            Output version information and exit
    -d --discordian         Switch to output discordian dates. This is the default
    -t --timestamp          Date specifies a timestamp, instead of an isodate
";

#[derive(Debug, RustcDecodable)]
struct Args {
    arg_date: Option<String>,
    flag_help: bool,
    flag_version: bool,
    flag_discordian: bool,
    flag_timestamp: bool,
}

fn main() {
    let args: Args = Docopt::new(USAGE)
                             .and_then(|d| d.decode())
                             .unwrap_or_else(|e| e.exit());
    if args.flag_version {
        println!("{}", VERSION);
        return;
        }

    let input_date = match args.arg_date {
        None => {
            let today = chrono::offset::local::Local::today();
            today.naive_local()
        },
        Some(raw_date) => if args.flag_timestamp {
            let timestamp = time::at(time::Timespec{
                    sec: raw_date.parse().expect("Timestamp"), nsec: 0});
            NaiveDate::from_yo(timestamp.tm_year + YEAR_OFFSET, timestamp.tm_yday as u32)
        } else {
            NaiveDate::parse_from_str(raw_date.as_str(), "%Y-%m-%d")
                       .expect("Can't parse date")
        },

    };
    let date = ddate::convert(input_date.ordinal0() as u16,
                   input_date.year() as i32).unwrap();
    println!("{:?}, ", date);
}

<|endoftext|>