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

use app_units::Au;
use core_foundation::array::CFArray;
use core_foundation::base::{CFType, TCFType};
use core_foundation::dictionary::CFDictionary;
use core_foundation::number::CFNumber;
use core_foundation::string::CFString;
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::CGFont;
use core_text::font::CTFont;
use core_text::font_collection;
use core_text::font_descriptor;
use serde::de::{Error, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::fmt;
use std::fs::{self, File};
use std::io::{Error as IoError, Read};
use std::ops::Deref;
use std::path::Path;
use std::sync::{Arc, Mutex};
use webrender_api::NativeFontHandle;

/// Platform specific font representation for mac.
/// The identifier is a PostScript font name. The
/// CTFont object is cached here for use by the
/// paint functions that create CGFont references.
#[derive(Deserialize, Serialize)]
pub struct FontTemplateData {
    // If you add members here, review the Debug impl below
    /// The `CTFont` object, if present. This is cached here so that we don't have to keep creating
    /// `CTFont` instances over and over. It can always be recreated from the `identifier` and/or
    /// `font_data` fields.
    ///
    /// When sending a `FontTemplateData` instance across processes, this will be cleared out on
    /// the other side, because `CTFont` instances cannot be sent across processes. This is
    /// harmless, however, because it can always be recreated.
    ctfont: CachedCTFont,

    pub identifier: Atom,
    pub font_data: Option<Arc<Vec<u8>>>,
}

impl fmt::Debug for FontTemplateData {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("FontTemplateData")
            .field("ctfont", &self.ctfont)
            .field("identifier", &self.identifier)
            .field(
                "font_data",
                &self
                    .font_data
                    .as_ref()
                    .map(|bytes| format!("[{} bytes]", bytes.len())),
            )
            .finish()
    }
}

unsafe impl Send for FontTemplateData {}
unsafe impl Sync for FontTemplateData {}

impl FontTemplateData {
    pub fn new(identifier: Atom, font_data: Option<Vec<u8>>) -> Result<FontTemplateData, IoError> {
        Ok(FontTemplateData {
            ctfont: CachedCTFont(Mutex::new(HashMap::new())),
            identifier: identifier.to_owned(),
            font_data: font_data.map(Arc::new),
        })
    }

    /// Retrieves the Core Text font instance, instantiating it if necessary.
    pub fn ctfont(&self, pt_size: f64) -> Option<CTFont> {
        let mut ctfonts = self.ctfont.lock().unwrap();
        let pt_size_key = Au::from_f64_px(pt_size);
        if !ctfonts.contains_key(&pt_size_key) {
            // If you pass a zero font size to one of the Core Text APIs, it'll replace it with
            // 12.0. We don't want that! (Issue #10492.)
            let clamped_pt_size = pt_size.max(0.01);
            let ctfont = match self.font_data {
                Some(ref bytes) => {
                    let fontprov = CGDataProvider::from_buffer(bytes.clone());
                    let cgfont_result = CGFont::from_data_provider(fontprov);
                    match cgfont_result {
                        Ok(cgfont) => {
                            Some(core_text::font::new_from_CGFont(&cgfont, clamped_pt_size))
                        },
                        Err(_) => None,
                    }
                },
                None => {
                    // We can't rely on Core Text to load a font for us by postscript
                    // name here, due to https://github.com/servo/servo/issues/23290.
                    // The APIs will randomly load the wrong font, forcing us to use
                    // the roundabout route of creating a Core Graphics font from a
                    // a set of descriptors and then creating a Core Text font from
                    // that one.

                    let attributes: CFDictionary<CFString, CFType> =
                        CFDictionary::from_CFType_pairs(&[
                            (
                                CFString::new("NSFontNameAttribute"),
                                CFString::new(&*self.identifier).as_CFType(),
                            ),
                            (
                                CFString::new("NSFontSizeAttribute"),
                                CFNumber::from(clamped_pt_size).as_CFType(),
                            ),
                        ]);

                    let descriptor = font_descriptor::new_from_attributes(&attributes);
                    let descriptors = CFArray::from_CFTypes(&[descriptor]);
                    let collection = font_collection::new_from_descriptors(&descriptors);
                    collection.get_descriptors().and_then(|descriptors| {
                        let descriptor = descriptors.get(0).unwrap();
                        let font_path = Path::new(&descriptor.font_path().unwrap()).to_owned();
                        fs::read(&font_path).ok().and_then(|bytes| {
                            let fontprov = CGDataProvider::from_buffer(Arc::new(bytes));
                            CGFont::from_data_provider(fontprov).ok().map(|cgfont| {
                                core_text::font::new_from_CGFont(&cgfont, clamped_pt_size)
                            })
                        })
                    })
                },
            };
            if let Some(ctfont) = ctfont {
                ctfonts.insert(pt_size_key, ctfont);
            }
        }
        ctfonts.get(&pt_size_key).map(|ctfont| (*ctfont).clone())
    }

    /// Returns a clone of the data in this font. This may be a hugely expensive
    /// operation (depending on the platform) which performs synchronous disk I/O
    /// and should never be done lightly.
    pub fn bytes(&self) -> Vec<u8> {
        if let Some(font_data) = self.bytes_if_in_memory() {
            return font_data;
        }

        let path = ServoUrl::parse(
            &*self
                .ctfont(0.0)
                .expect("No Core Text font available!")
                .url()
                .expect("No URL for Core Text font!")
                .get_string()
                .to_string(),
        )
        .expect("Couldn't parse Core Text font URL!")
        .as_url()
        .to_file_path()
        .expect("Core Text font didn't name a path!");
        let mut bytes = Vec::new();
        File::open(path)
            .expect("Couldn't open font file!")
            .read_to_end(&mut bytes)
            .unwrap();
        bytes
    }

    /// Returns a clone of the bytes in this font if they are in memory. This function never
    /// performs disk I/O.
    pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> {
        self.font_data.as_ref().map(|bytes| (**bytes).clone())
    }

    /// Returns the native font that underlies this font template, if applicable.
    pub fn native_font(&self) -> Option<NativeFontHandle> {
        self.ctfont(0.0)
            .map(|ctfont| NativeFontHandle(ctfont.copy_to_CGFont()))
    }
}

#[derive(Debug)]
pub struct CachedCTFont(Mutex<HashMap<Au, CTFont>>);

impl Deref for CachedCTFont {
    type Target = Mutex<HashMap<Au, CTFont>>;
    fn deref(&self) -> &Mutex<HashMap<Au, CTFont>> {
        &self.0
    }
}

impl Serialize for CachedCTFont {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_none()
    }
}

impl<'de> Deserialize<'de> for CachedCTFont {
    fn deserialize<D>(deserializer: D) -> Result<CachedCTFont, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct NoneOptionVisitor;

        impl<'de> Visitor<'de> for NoneOptionVisitor {
            type Value = CachedCTFont;

            fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                write!(fmt, "none")
            }

            #[inline]
            fn visit_none<E>(self) -> Result<CachedCTFont, E>
            where
                E: Error,
            {
                Ok(CachedCTFont(Mutex::new(HashMap::new())))
            }
        }

        deserializer.deserialize_option(NoneOptionVisitor)
    }
}
<commit_msg>Auto merge of #24387 - servo:jdm-patch-31, r=jdm<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at https://mozilla.org/MPL/2.0/. */

use app_units::Au;
use core_foundation::array::CFArray;
use core_foundation::base::{CFType, TCFType};
use core_foundation::dictionary::CFDictionary;
use core_foundation::string::CFString;
use core_graphics::data_provider::CGDataProvider;
use core_graphics::font::CGFont;
use core_text::font::CTFont;
use core_text::font_collection;
use core_text::font_descriptor;
use serde::de::{Error, Visitor};
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use servo_atoms::Atom;
use servo_url::ServoUrl;
use std::borrow::ToOwned;
use std::collections::HashMap;
use std::fmt;
use std::fs::{self, File};
use std::io::{Error as IoError, Read};
use std::ops::Deref;
use std::path::Path;
use std::sync::{Arc, Mutex};
use webrender_api::NativeFontHandle;

/// Platform specific font representation for mac.
/// The identifier is a PostScript font name. The
/// CTFont object is cached here for use by the
/// paint functions that create CGFont references.
#[derive(Deserialize, Serialize)]
pub struct FontTemplateData {
    // If you add members here, review the Debug impl below
    /// The `CTFont` object, if present. This is cached here so that we don't have to keep creating
    /// `CTFont` instances over and over. It can always be recreated from the `identifier` and/or
    /// `font_data` fields.
    ///
    /// When sending a `FontTemplateData` instance across processes, this will be cleared out on
    /// the other side, because `CTFont` instances cannot be sent across processes. This is
    /// harmless, however, because it can always be recreated.
    ctfont: CachedCTFont,

    pub identifier: Atom,
    pub font_data: Option<Arc<Vec<u8>>>,
}

impl fmt::Debug for FontTemplateData {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        fmt.debug_struct("FontTemplateData")
            .field("ctfont", &self.ctfont)
            .field("identifier", &self.identifier)
            .field(
                "font_data",
                &self
                    .font_data
                    .as_ref()
                    .map(|bytes| format!("[{} bytes]", bytes.len())),
            )
            .finish()
    }
}

unsafe impl Send for FontTemplateData {}
unsafe impl Sync for FontTemplateData {}

impl FontTemplateData {
    pub fn new(identifier: Atom, font_data: Option<Vec<u8>>) -> Result<FontTemplateData, IoError> {
        Ok(FontTemplateData {
            ctfont: CachedCTFont(Mutex::new(HashMap::new())),
            identifier: identifier.to_owned(),
            font_data: font_data.map(Arc::new),
        })
    }

    /// Retrieves the Core Text font instance, instantiating it if necessary.
    pub fn ctfont(&self, pt_size: f64) -> Option<CTFont> {
        let mut ctfonts = self.ctfont.lock().unwrap();
        let pt_size_key = Au::from_f64_px(pt_size);
        if !ctfonts.contains_key(&pt_size_key) {
            // If you pass a zero font size to one of the Core Text APIs, it'll replace it with
            // 12.0. We don't want that! (Issue #10492.)
            let clamped_pt_size = pt_size.max(0.01);
            let ctfont = match self.font_data {
                Some(ref bytes) => {
                    let fontprov = CGDataProvider::from_buffer(bytes.clone());
                    let cgfont_result = CGFont::from_data_provider(fontprov);
                    match cgfont_result {
                        Ok(cgfont) => {
                            Some(core_text::font::new_from_CGFont(&cgfont, clamped_pt_size))
                        },
                        Err(_) => None,
                    }
                },
                None => {
                    // We can't rely on Core Text to load a font for us by postscript
                    // name here, due to https://github.com/servo/servo/issues/23290.
                    // The APIs will randomly load the wrong font, forcing us to use
                    // the roundabout route of creating a Core Graphics font from a
                    // a set of descriptors and then creating a Core Text font from
                    // that one.

                    let attributes: CFDictionary<CFString, CFType> =
                        CFDictionary::from_CFType_pairs(&[(
                            CFString::new("NSFontNameAttribute"),
                            CFString::new(&*self.identifier).as_CFType(),
                        )]);

                    let descriptor = font_descriptor::new_from_attributes(&attributes);
                    let descriptors = CFArray::from_CFTypes(&[descriptor]);
                    let collection = font_collection::new_from_descriptors(&descriptors);
                    collection.get_descriptors().and_then(|descriptors| {
                        let descriptor = descriptors.get(0).unwrap();
                        let font_path = Path::new(&descriptor.font_path().unwrap()).to_owned();
                        fs::read(&font_path).ok().and_then(|bytes| {
                            let fontprov = CGDataProvider::from_buffer(Arc::new(bytes));
                            CGFont::from_data_provider(fontprov).ok().map(|cgfont| {
                                core_text::font::new_from_CGFont(&cgfont, clamped_pt_size)
                            })
                        })
                    })
                },
            };
            if let Some(ctfont) = ctfont {
                ctfonts.insert(pt_size_key, ctfont);
            }
        }
        ctfonts.get(&pt_size_key).map(|ctfont| (*ctfont).clone())
    }

    /// Returns a clone of the data in this font. This may be a hugely expensive
    /// operation (depending on the platform) which performs synchronous disk I/O
    /// and should never be done lightly.
    pub fn bytes(&self) -> Vec<u8> {
        if let Some(font_data) = self.bytes_if_in_memory() {
            return font_data;
        }

        let path = ServoUrl::parse(
            &*self
                .ctfont(0.0)
                .expect("No Core Text font available!")
                .url()
                .expect("No URL for Core Text font!")
                .get_string()
                .to_string(),
        )
        .expect("Couldn't parse Core Text font URL!")
        .as_url()
        .to_file_path()
        .expect("Core Text font didn't name a path!");
        let mut bytes = Vec::new();
        File::open(path)
            .expect("Couldn't open font file!")
            .read_to_end(&mut bytes)
            .unwrap();
        bytes
    }

    /// Returns a clone of the bytes in this font if they are in memory. This function never
    /// performs disk I/O.
    pub fn bytes_if_in_memory(&self) -> Option<Vec<u8>> {
        self.font_data.as_ref().map(|bytes| (**bytes).clone())
    }

    /// Returns the native font that underlies this font template, if applicable.
    pub fn native_font(&self) -> Option<NativeFontHandle> {
        self.ctfont(0.0)
            .map(|ctfont| NativeFontHandle(ctfont.copy_to_CGFont()))
    }
}

#[derive(Debug)]
pub struct CachedCTFont(Mutex<HashMap<Au, CTFont>>);

impl Deref for CachedCTFont {
    type Target = Mutex<HashMap<Au, CTFont>>;
    fn deref(&self) -> &Mutex<HashMap<Au, CTFont>> {
        &self.0
    }
}

impl Serialize for CachedCTFont {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        serializer.serialize_none()
    }
}

impl<'de> Deserialize<'de> for CachedCTFont {
    fn deserialize<D>(deserializer: D) -> Result<CachedCTFont, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct NoneOptionVisitor;

        impl<'de> Visitor<'de> for NoneOptionVisitor {
            type Value = CachedCTFont;

            fn expecting(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
                write!(fmt, "none")
            }

            #[inline]
            fn visit_none<E>(self) -> Result<CachedCTFont, E>
            where
                E: Error,
            {
                Ok(CachedCTFont(Mutex::new(HashMap::new())))
            }
        }

        deserializer.deserialize_option(NoneOptionVisitor)
    }
}
<|endoftext|>


<commit_before><commit_msg>cond_var: Use wfi() instead of asm!("wfi")<commit_after><|endoftext|>


<commit_before>extern crate discord;
extern crate time;
extern crate serde_json;

use std::env;
use discord::{Discord, State};
use discord::voice::VoiceConnection;
use discord::model::Event;

// A simple DJ bot example.
// Use by issuing the command "!dj <youtube-link>" in PM or a visible text channel.
// The bot will join the voice channel of the person issuing the command.
// "!dj stop" will stop playing, and "!dj quit" will quit the voice channel.
// The bot will quit any voice channel it is the last user in.

pub fn main() {
	// log in to the API
	let args: Vec<_> = env::args().collect();
	let discord = Discord::new_cache(
		"tokens.txt",
		args.get(1).expect("No email specified"),
		args.get(2).map(|x| &**x),
	).expect("Login failed");

	// establish websocket and voice connection
	let (mut connection, ready) = discord.connect().expect("connect failed");
	println!("[Ready] {} is serving {} servers", ready.user.username, ready.servers.len());
	let mut voice = VoiceConnection::new(ready.user.id.clone());
	let mut state = State::new(ready);
	let mut current_channel = None;

	// receive events forever
	loop {
		let event = match connection.recv_event() {
			Ok(event) => event,
			Err(err) => {
				println!("[Warning] Receive error: {:?}", err);
				if let discord::Error::WebSocket(..) = err {
					// Handle the websocket connection being dropped
					let (new_connection, ready) = discord.connect().expect("connect failed");
					connection = new_connection;
					state = State::new(ready);
					println!("[Ready] Reconnected successfully.");
				}
				continue
			},
		};
		state.update(&event);
		voice.update(&event);

		match event {
			Event::Closed(n) => {
				println!("[Error] Connection closed with status: {}", n);
				break
			},
			Event::MessageCreate(message) => {
				use std::ascii::AsciiExt;
				// safeguard: stop if the message is from us
				if message.author.id == state.user().id {
					continue
				}

				// reply to a command if there was one
				let mut split = message.content.split(" ");
				let first_word = split.next().unwrap_or("");
				let argument = split.next().unwrap_or("");

				if first_word.eq_ignore_ascii_case("!dj") {
					if argument.eq_ignore_ascii_case("stop") {
						voice.stop();
					} else if argument.eq_ignore_ascii_case("quit") {
						connection.voice_disconnect();
					} else {
						let output = (|| {
							for server in state.servers() {
								for vstate in &server.voice_states {
									if vstate.user_id == message.author.id {
										if let Some(ref chan) = vstate.channel_id {
											let stream = match discord::voice::open_ytdl_stream(&argument) {
												Ok(stream) => stream,
												Err(error) => return format!("Error: {}", error),
											};
											voice.stop();
											connection.voice_connect(&server.id, chan);
											voice.play(stream);
											return String::new()
										}
									}
								}
							}
							"You must be in a voice channel to DJ".into()
						})();
						if output.len() > 0 {
							warn(discord.send_message(&message.channel_id, &output, "", false));
						}
					}
				}
			}
			Event::VoiceStateUpdate(server_id, voice_state) => {
				if voice_state.user_id == state.user().id {
					current_channel = voice_state.channel_id.map(|c| (server_id, c));
				} else if let Some((ref cur_server, ref cur_channel)) = current_channel {
					// If we are in a voice channel, && someone on our server moves/hangs up,
					if *cur_server == server_id {
						// && our current voice channel is empty, disconnect from voice
						if let Some(srv) = state.servers().iter().find(|srv| srv.id == server_id) {
							if srv.voice_states.iter().filter(|vs| vs.channel_id.as_ref() == Some(cur_channel)).count() <= 1 {
								connection.voice_disconnect();
							}
						}
					}
				}
			}
			_ => {}, // discard other events
		}
	}
}

fn warn<T, E: ::std::fmt::Debug>(result: Result<T, E>) {
	match result {
		Ok(_) => {},
		Err(err) => println!("[Warning] {:?}", err)
	}
}
<commit_msg>Remove unused extern crates from dj example<commit_after>extern crate discord;

use std::env;
use discord::{Discord, State};
use discord::voice::VoiceConnection;
use discord::model::Event;

// A simple DJ bot example.
// Use by issuing the command "!dj <youtube-link>" in PM or a visible text channel.
// The bot will join the voice channel of the person issuing the command.
// "!dj stop" will stop playing, and "!dj quit" will quit the voice channel.
// The bot will quit any voice channel it is the last user in.

pub fn main() {
	// log in to the API
	let args: Vec<_> = env::args().collect();
	let discord = Discord::new_cache(
		"tokens.txt",
		args.get(1).expect("No email specified"),
		args.get(2).map(|x| &**x),
	).expect("Login failed");

	// establish websocket and voice connection
	let (mut connection, ready) = discord.connect().expect("connect failed");
	println!("[Ready] {} is serving {} servers", ready.user.username, ready.servers.len());
	let mut voice = VoiceConnection::new(ready.user.id.clone());
	let mut state = State::new(ready);
	let mut current_channel = None;

	// receive events forever
	loop {
		let event = match connection.recv_event() {
			Ok(event) => event,
			Err(err) => {
				println!("[Warning] Receive error: {:?}", err);
				if let discord::Error::WebSocket(..) = err {
					// Handle the websocket connection being dropped
					let (new_connection, ready) = discord.connect().expect("connect failed");
					connection = new_connection;
					state = State::new(ready);
					println!("[Ready] Reconnected successfully.");
				}
				continue
			},
		};
		state.update(&event);
		voice.update(&event);

		match event {
			Event::Closed(n) => {
				println!("[Error] Connection closed with status: {}", n);
				break
			},
			Event::MessageCreate(message) => {
				use std::ascii::AsciiExt;
				// safeguard: stop if the message is from us
				if message.author.id == state.user().id {
					continue
				}

				// reply to a command if there was one
				let mut split = message.content.split(" ");
				let first_word = split.next().unwrap_or("");
				let argument = split.next().unwrap_or("");

				if first_word.eq_ignore_ascii_case("!dj") {
					if argument.eq_ignore_ascii_case("stop") {
						voice.stop();
					} else if argument.eq_ignore_ascii_case("quit") {
						connection.voice_disconnect();
					} else {
						let output = (|| {
							for server in state.servers() {
								for vstate in &server.voice_states {
									if vstate.user_id == message.author.id {
										if let Some(ref chan) = vstate.channel_id {
											let stream = match discord::voice::open_ytdl_stream(&argument) {
												Ok(stream) => stream,
												Err(error) => return format!("Error: {}", error),
											};
											voice.stop();
											connection.voice_connect(&server.id, chan);
											voice.play(stream);
											return String::new()
										}
									}
								}
							}
							"You must be in a voice channel to DJ".into()
						})();
						if output.len() > 0 {
							warn(discord.send_message(&message.channel_id, &output, "", false));
						}
					}
				}
			}
			Event::VoiceStateUpdate(server_id, voice_state) => {
				if voice_state.user_id == state.user().id {
					current_channel = voice_state.channel_id.map(|c| (server_id, c));
				} else if let Some((ref cur_server, ref cur_channel)) = current_channel {
					// If we are in a voice channel, && someone on our server moves/hangs up,
					if *cur_server == server_id {
						// && our current voice channel is empty, disconnect from voice
						if let Some(srv) = state.servers().iter().find(|srv| srv.id == server_id) {
							if srv.voice_states.iter().filter(|vs| vs.channel_id.as_ref() == Some(cur_channel)).count() <= 1 {
								connection.voice_disconnect();
							}
						}
					}
				}
			}
			_ => {}, // discard other events
		}
	}
}

fn warn<T, E: ::std::fmt::Debug>(result: Result<T, E>) {
	match result {
		Ok(_) => {},
		Err(err) => println!("[Warning] {:?}", err)
	}
}
<|endoftext|>


<commit_before><commit_msg>Update comment<commit_after><|endoftext|>


<commit_before><commit_msg>copy logger<commit_after>//! Request logging middleware
use std::collections::HashSet;
use std::env;
use std::fmt::{self, Display, Formatter};

use regex::Regex;
use time;

use error::Result;
use httpmessage::HttpMessage;
use httprequest::HttpRequest;
use httpresponse::HttpResponse;
use middleware::{Finished, Middleware, Started};

/// `Middleware` for logging request and response info to the terminal.
///
/// `Logger` middleware uses standard log crate to log information. You should
/// enable logger for `actix_web` package to see access log.
/// ([`env_logger`](https://docs.rs/env_logger/*/env_logger/) or similar)
///
/// ## Usage
///
/// Create `Logger` middleware with the specified `format`.
/// Default `Logger` could be created with `default` method, it uses the
/// default format:
///
/// ```ignore
///  %a "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T
/// ```
/// ```rust
/// # extern crate actix_web;
/// extern crate env_logger;
/// use actix_web::middleware::Logger;
/// use actix_web::App;
///
/// fn main() {
///     std::env::set_var("RUST_LOG", "actix_web=info");
///     env_logger::init();
///
///     let app = App::new()
///         .middleware(Logger::default())
///         .middleware(Logger::new("%a %{User-Agent}i"))
///         .finish();
/// }
/// ```
///
/// ## Format
///
/// `%%`  The percent sign
///
/// `%a`  Remote IP-address (IP-address of proxy if using reverse proxy)
///
/// `%t`  Time when the request was started to process
///
/// `%r`  First line of request
///
/// `%s`  Response status code
///
/// `%b`  Size of response in bytes, including HTTP headers
///
/// `%T` Time taken to serve the request, in seconds with floating fraction in
/// .06f format
///
/// `%D`  Time taken to serve the request, in milliseconds
///
/// `%{FOO}i`  request.headers['FOO']
///
/// `%{FOO}o`  response.headers['FOO']
///
/// `%{FOO}e`  os.environ['FOO']
///
pub struct Logger {
    format: Format,
    exclude: HashSet<String>,
}

impl Logger {
    /// Create `Logger` middleware with the specified `format`.
    pub fn new(format: &str) -> Logger {
        Logger {
            format: Format::new(format),
            exclude: HashSet::new(),
        }
    }

    /// Ignore and do not log access info for specified path.
    pub fn exclude<T: Into<String>>(mut self, path: T) -> Self {
        self.exclude.insert(path.into());
        self
    }
}

impl Default for Logger {
    /// Create `Logger` middleware with format:
    ///
    /// ```ignore
    /// %a "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T
    /// ```
    fn default() -> Logger {
        Logger {
            format: Format::default(),
            exclude: HashSet::new(),
        }
    }
}

struct StartTime(time::Tm);

impl Logger {
    fn log<S>(&self, req: &HttpRequest<S>, resp: &HttpResponse) {
        if let Some(entry_time) = req.extensions().get::<StartTime>() {
            let render = |fmt: &mut Formatter| {
                for unit in &self.format.0 {
                    unit.render(fmt, req, resp, entry_time.0)?;
                }
                Ok(())
            };
            info!("{}", FormatDisplay(&render));
        }
    }
}

impl<S> Middleware<S> for Logger {
    fn start(&self, req: &HttpRequest<S>) -> Result<Started> {
        if !self.exclude.contains(req.path()) {
            req.extensions_mut().insert(StartTime(time::now()));
        }
        Ok(Started::Done)
    }

    fn finish(&self, req: &HttpRequest<S>, resp: &HttpResponse) -> Finished {
        self.log(req, resp);
        Finished::Done
    }
}

/// A formatting style for the `Logger`, consisting of multiple
/// `FormatText`s concatenated into one line.
#[derive(Clone)]
#[doc(hidden)]
struct Format(Vec<FormatText>);

impl Default for Format {
    /// Return the default formatting style for the `Logger`:
    fn default() -> Format {
        Format::new(r#"%a "%r" %s %b "%{Referer}i" "%{User-Agent}i" %T"#)
    }
}

impl Format {
    /// Create a `Format` from a format string.
    ///
    /// Returns `None` if the format string syntax is incorrect.
    pub fn new(s: &str) -> Format {
        trace!("Access log format: {}", s);
        let fmt = Regex::new(r"%(\{([A-Za-z0-9\-_]+)\}([ioe])|[atPrsbTD]?)").unwrap();

        let mut idx = 0;
        let mut results = Vec::new();
        for cap in fmt.captures_iter(s) {
            let m = cap.get(0).unwrap();
            let pos = m.start();
            if idx != pos {
                results.push(FormatText::Str(s[idx..pos].to_owned()));
            }
            idx = m.end();

            if let Some(key) = cap.get(2) {
                results.push(match cap.get(3).unwrap().as_str() {
                    "i" => FormatText::RequestHeader(key.as_str().to_owned()),
                    "o" => FormatText::ResponseHeader(key.as_str().to_owned()),
                    "e" => FormatText::EnvironHeader(key.as_str().to_owned()),
                    _ => unreachable!(),
                })
            } else {
                let m = cap.get(1).unwrap();
                results.push(match m.as_str() {
                    "%" => FormatText::Percent,
                    "a" => FormatText::RemoteAddr,
                    "t" => FormatText::RequestTime,
                    "r" => FormatText::RequestLine,
                    "s" => FormatText::ResponseStatus,
                    "b" => FormatText::ResponseSize,
                    "T" => FormatText::Time,
                    "D" => FormatText::TimeMillis,
                    _ => FormatText::Str(m.as_str().to_owned()),
                });
            }
        }
        if idx != s.len() {
            results.push(FormatText::Str(s[idx..].to_owned()));
        }

        Format(results)
    }
}

/// A string of text to be logged. This is either one of the data
/// fields supported by the `Logger`, or a custom `String`.
#[doc(hidden)]
#[derive(Debug, Clone)]
pub enum FormatText {
    Str(String),
    Percent,
    RequestLine,
    RequestTime,
    ResponseStatus,
    ResponseSize,
    Time,
    TimeMillis,
    RemoteAddr,
    RequestHeader(String),
    ResponseHeader(String),
    EnvironHeader(String),
}

impl FormatText {
    fn render<S>(
        &self, fmt: &mut Formatter, req: &HttpRequest<S>, resp: &HttpResponse,
        entry_time: time::Tm,
    ) -> Result<(), fmt::Error> {
        match *self {
            FormatText::Str(ref string) => fmt.write_str(string),
            FormatText::Percent => "%".fmt(fmt),
            FormatText::RequestLine => {
                if req.query_string().is_empty() {
                    fmt.write_fmt(format_args!(
                        "{} {} {:?}",
                        req.method(),
                        req.path(),
                        req.version()
                    ))
                } else {
                    fmt.write_fmt(format_args!(
                        "{} {}?{} {:?}",
                        req.method(),
                        req.path(),
                        req.query_string(),
                        req.version()
                    ))
                }
            }
            FormatText::ResponseStatus => resp.status().as_u16().fmt(fmt),
            FormatText::ResponseSize => resp.response_size().fmt(fmt),
            FormatText::Time => {
                let rt = time::now() - entry_time;
                let rt = (rt.num_nanoseconds().unwrap_or(0) as f64) / 1_000_000_000.0;
                fmt.write_fmt(format_args!("{:.6}", rt))
            }
            FormatText::TimeMillis => {
                let rt = time::now() - entry_time;
                let rt = (rt.num_nanoseconds().unwrap_or(0) as f64) / 1_000_000.0;
                fmt.write_fmt(format_args!("{:.6}", rt))
            }
            FormatText::RemoteAddr => {
                if let Some(remote) = req.connection_info().remote() {
                    return remote.fmt(fmt);
                } else {
                    "-".fmt(fmt)
                }
            }
            FormatText::RequestTime => entry_time
                .strftime("[%d/%b/%Y:%H:%M:%S %z]")
                .unwrap()
                .fmt(fmt),
            FormatText::RequestHeader(ref name) => {
                let s = if let Some(val) = req.headers().get(name) {
                    if let Ok(s) = val.to_str() {
                        s
                    } else {
                        "-"
                    }
                } else {
                    "-"
                };
                fmt.write_fmt(format_args!("{}", s))
            }
            FormatText::ResponseHeader(ref name) => {
                let s = if let Some(val) = resp.headers().get(name) {
                    if let Ok(s) = val.to_str() {
                        s
                    } else {
                        "-"
                    }
                } else {
                    "-"
                };
                fmt.write_fmt(format_args!("{}", s))
            }
            FormatText::EnvironHeader(ref name) => {
                if let Ok(val) = env::var(name) {
                    fmt.write_fmt(format_args!("{}", val))
                } else {
                    "-".fmt(fmt)
                }
            }
        }
    }
}

pub(crate) struct FormatDisplay<'a>(&'a Fn(&mut Formatter) -> Result<(), fmt::Error>);

impl<'a> fmt::Display for FormatDisplay<'a> {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
        (self.0)(fmt)
    }
}

#[cfg(test)]
mod tests {
    use time;

    use super::*;
    use http::{header, StatusCode};
    use test::TestRequest;

    #[test]
    fn test_logger() {
        let logger = Logger::new("%% %{User-Agent}i %{X-Test}o %{HOME}e %D test");

        let req = TestRequest::with_header(
            header::USER_AGENT,
            header::HeaderValue::from_static("ACTIX-WEB"),
        ).finish();
        let resp = HttpResponse::build(StatusCode::OK)
            .header("X-Test", "ttt")
            .force_close()
            .finish();

        match logger.start(&req) {
            Ok(Started::Done) => (),
            _ => panic!(),
        };
        match logger.finish(&req, &resp) {
            Finished::Done => (),
            _ => panic!(),
        }
        let entry_time = time::now();
        let render = |fmt: &mut Formatter| {
            for unit in &logger.format.0 {
                unit.render(fmt, &req, &resp, entry_time)?;
            }
            Ok(())
        };
        let s = format!("{}", FormatDisplay(&render));
        assert!(s.contains("ACTIX-WEB ttt"));
    }

    #[test]
    fn test_default_format() {
        let format = Format::default();

        let req = TestRequest::with_header(
            header::USER_AGENT,
            header::HeaderValue::from_static("ACTIX-WEB"),
        ).finish();
        let resp = HttpResponse::build(StatusCode::OK).force_close().finish();
        let entry_time = time::now();

        let render = |fmt: &mut Formatter| {
            for unit in &format.0 {
                unit.render(fmt, &req, &resp, entry_time)?;
            }
            Ok(())
        };
        let s = format!("{}", FormatDisplay(&render));
        assert!(s.contains("GET / HTTP/1.1"));
        assert!(s.contains("200 0"));
        assert!(s.contains("ACTIX-WEB"));

        let req = TestRequest::with_uri("/?test").finish();
        let resp = HttpResponse::build(StatusCode::OK).force_close().finish();
        let entry_time = time::now();

        let render = |fmt: &mut Formatter| {
            for unit in &format.0 {
                unit.render(fmt, &req, &resp, entry_time)?;
            }
            Ok(())
        };
        let s = format!("{}", FormatDisplay(&render));
        assert!(s.contains("GET /?test HTTP/1.1"));
    }
}
<|endoftext|>


<commit_before>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

extern crate clap;
#[macro_use] extern crate version;
#[macro_use] extern crate log;
extern crate walkdir;
extern crate toml;
extern crate toml_query;

extern crate libimagrt;
extern crate libimagerror;

use std::env;
use std::process::exit;
use std::process::Command;
use std::process::Stdio;
use std::io::ErrorKind;
use std::collections::BTreeMap;

use walkdir::WalkDir;
use clap::{Arg, ArgMatches, AppSettings, SubCommand};
use toml::Value;
use toml_query::read::TomlValueReadExt;

use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error;

/// Returns the helptext, putting the Strings in cmds as possible
/// subcommands into it
fn help_text(cmds: Vec<String>) -> String {
    format!(r#"

     _
    (_)_ __ ___   __ _  __ _
    | | '_ \` _ \/ _\`|/ _\`|
    | | | | | | | (_| | (_| |
    |_|_| |_| |_|\__,_|\__, |
                       |___/
    -------------------------

    Usage: imag [--version | --versions | -h | --help] <command> <args...>

    imag - the personal information management suite for the commandline

    imag is a PIM suite for the commandline. It consists of several commands,
    called "modules". Each module implements one PIM aspect and all of these
    modules can be used independently.

    Available commands:

    {imagbins}

    Call a command with 'imag <command> <args>'
    Each command can be called with "--help" to get the respective helptext.

    Please visit https://github.com/matthiasbeyer/imag to view the source code,
    follow the development of imag or maybe even contribute to imag.

    imag is free software. It is released under the terms of LGPLv2.1

    (c) 2016 Matthias Beyer and contributors"#,
        imagbins = cmds
            .into_iter()
            .map(|cmd| format!("\t{}\n", cmd))
            .fold(String::new(), |s, c| {
                let s = s + c.as_str();
                s
            }))
}

/// Returns the list of imag-* executables found in $PATH
fn get_commands() -> Vec<String> {
    match env::var("PATH") {
        Err(e) => {
            println!("PATH error: {:?}", e);
            exit(1);
        },

        Ok(path) => path
            .split(":")
            .flat_map(|elem| {
                WalkDir::new(elem)
                    .max_depth(1)
                    .into_iter()
                    .filter(|path| match *path {
                        Ok(ref p) => p.file_name().to_str().map_or(false, |f| f.starts_with("imag-")),
                        Err(_)    => false,
                    })
                    .filter_map(Result::ok)
                    .filter_map(|path| path
                        .file_name()
                       .to_str()
                       .and_then(|s| s.splitn(2, "-").nth(1).map(String::from))
                    )
            })
            .collect()
    }
}

fn main() {
    // Initialize the Runtime and build the CLI
    let appname  = "imag";
    let version  = &version!();
    let about    = "imag - the PIM suite for the commandline";
    let commands = get_commands();
    let helptext = help_text(commands.clone());
    let app      = Runtime::get_default_cli_builder(appname, version, about)
        .settings(&[AppSettings::AllowExternalSubcommands, AppSettings::ArgRequiredElseHelp])
        .arg(Arg::with_name("version")
             .long("version")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the version of imag"))
        .arg(Arg::with_name("versions")
             .long("versions")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the versions of the imag commands"))
        .subcommand(SubCommand::with_name("help").help("Show help"))
        .help(helptext.as_str());
    let rt = Runtime::new(app)
        .unwrap_or_else(|e| {
            println!("Runtime couldn't be setup. Exiting");
            trace_error(&e);
            exit(1);
        });
    let matches = rt.cli();

    debug!("matches: {:?}", matches);

    // Begin checking for arguments

    if matches.is_present("version") {
        debug!("Showing version");
        println!("imag {}", &version!()[..]);
        exit(0);
    }

    if matches.is_present("versions") {
        debug!("Showing versions");
        commands
            .iter()
            .map(|command| {
                match Command::new(format!("imag-{}", command))
                    .arg("--version")
                    .output()
                    .map(|v| v.stdout)
                {
                    Ok(s) => match String::from_utf8(s) {
                        Ok(s) => format!("{:10} -> {}", command, s),
                        Err(e) => format!("UTF8 Error while working with output of imag{}: {:?}", command, e),
                    },
                    Err(e) => format!("Failed calling imag-{} -> {:?}", command, e),
                }
            })
            .fold((), |_, line| {
                // The amount of newlines may differ depending on the subprocess
                println!("{}", line.trim());
            });

        exit(0);
    }

    let aliases = match fetch_aliases(&rt) {
        Ok(aliases) => aliases,
        Err(e)      => {
            println!("Error while fetching aliases from configuration file");
            debug!("Error = {:?}", e);
            println!("Aborting");
            exit(1);
        }
    };

    // Matches any subcommand given
    match matches.subcommand() {
        (subcommand, Some(scmd)) => {
            // Get all given arguments and further subcommands to pass to
            // the imag-<> binary
            // Providing no arguments is OK, and is therefore ignored here
            let mut subcommand_args : Vec<String> = match scmd.values_of("") {
                Some(values) => values.map(String::from).collect(),
                None => Vec::new()
            };

            forward_commandline_arguments(&matches, &mut subcommand_args);

            let subcommand = String::from(subcommand);
            let subcommand = aliases.get(&subcommand).cloned().unwrap_or(subcommand);

            debug!("Calling 'imag-{}' with args: {:?}", subcommand, subcommand_args);

            // Create a Command, and pass it the gathered arguments
            match Command::new(format!("imag-{}", subcommand))
                .stdin(Stdio::inherit())
                .stdout(Stdio::inherit())
                .stderr(Stdio::inherit())
                .args(&subcommand_args[..])
                .spawn()
                .and_then(|mut c| c.wait())
            {
                Ok(exit_status) => {
                    if !exit_status.success() {
                        debug!("{} exited with non-zero exit code: {:?}", subcommand, exit_status);
                        println!("{} exited with non-zero exit code", subcommand);
                        exit(exit_status.code().unwrap_or(1));
                    }
                    debug!("Successful exit!");
                },

                Err(e) => {
                    debug!("Error calling the subcommand");
                    match e.kind() {
                        ErrorKind::NotFound => {
                            println!("No such command: 'imag-{}'", subcommand);
                            println!("See 'imag --help' for available subcommands");
                            exit(1);
                        },
                        ErrorKind::PermissionDenied => {
                            println!("No permission to execute: 'imag-{}'", subcommand);
                            exit(1);
                        },
                        _ => {
                            println!("Error spawning: {:?}", e);
                            exit(1);
                        }
                    }
                }
            }
        },
        // Calling for example 'imag --versions' will lead here, as this option does not exit.
        // There's nothing to do in such a case
        _ => {},
    }
}

fn fetch_aliases(rt: &Runtime) -> Result<BTreeMap<String, String>, String> {
    let cfg   = try!(rt.config().ok_or_else(|| String::from("No configuration found")));
    let value = cfg
        .read("imag.aliases")
        .map_err(|_| String::from("Reading from config failed"));

    match try!(value) {
        None                         => Ok(BTreeMap::new()),
        Some(&Value::Table(ref tbl)) => {
            let mut alias_mappings = BTreeMap::new();

            for (k, v) in tbl {
                match v {
                    &Value::String(ref alias)      => {
                        alias_mappings.insert(alias.clone(), k.clone());
                    },
                    &Value::Array(ref aliases) => {
                        for alias in aliases {
                            match alias {
                                &Value::String(ref s) => {
                                    alias_mappings.insert(s.clone(), k.clone());
                                },
                                _ => {
                                    let e = format!("Not all values are a String in 'imag.aliases.{}'", k);
                                    return Err(e);
                                }
                            }
                        }
                    },

                    _ => {
                        let msg = format!("Type Error: 'imag.aliases.{}' is not a table or string", k);
                        return Err(msg);
                    },
                }
            }

            Ok(alias_mappings)
        },

        Some(_) => Err(String::from("Type Error: 'imag.aliases' is not a table")),
    }
}

fn forward_commandline_arguments(m: &ArgMatches, scmd: &mut Vec<String>) {
    let push = |flag: Option<&str>, val_name: &str, m: &ArgMatches, v: &mut Vec<String>| {
        let _ = m
            .value_of(val_name)
            .map(|val| {
                let flag = format!("--{}", flag.unwrap_or(val_name));
                v.insert(0, String::from(val));
                v.insert(0, flag);
            });
    };

    push(Some("verbose"),
         Runtime::arg_verbosity_name(), m , scmd);

    push(Some("debug"),
         Runtime::arg_debugging_name(), m , scmd);

    push(Some("no-color"),
         Runtime::arg_no_color_output_name(), m , scmd);

    push(Some("config"),
         Runtime::arg_config_name(), m , scmd);

    push(Some("override-config"),
         Runtime::arg_config_override_name(), m , scmd);

    push(Some("rtp"),
         Runtime::arg_runtimepath_name(), m , scmd);

    push(Some("store"),
         Runtime::arg_storepath_name(), m , scmd);

    push(Some("editor"),
         Runtime::arg_editor_name(), m , scmd);

    push(Some("generate-commandline-completion"),
         Runtime::arg_generate_compl(), m , scmd);

    push(None , Runtime::arg_logdest_name()                         , m , scmd);

}

<commit_msg>Replace uses of try!() macro with "?" operator<commit_after>//
// imag - the personal information management suite for the commandline
// Copyright (C) 2015, 2016 Matthias Beyer <mail@beyermatthias.de> and contributors
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; version
// 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
//

extern crate clap;
#[macro_use] extern crate version;
#[macro_use] extern crate log;
extern crate walkdir;
extern crate toml;
extern crate toml_query;

extern crate libimagrt;
extern crate libimagerror;

use std::env;
use std::process::exit;
use std::process::Command;
use std::process::Stdio;
use std::io::ErrorKind;
use std::collections::BTreeMap;

use walkdir::WalkDir;
use clap::{Arg, ArgMatches, AppSettings, SubCommand};
use toml::Value;
use toml_query::read::TomlValueReadExt;

use libimagrt::runtime::Runtime;
use libimagerror::trace::trace_error;

/// Returns the helptext, putting the Strings in cmds as possible
/// subcommands into it
fn help_text(cmds: Vec<String>) -> String {
    format!(r#"

     _
    (_)_ __ ___   __ _  __ _
    | | '_ \` _ \/ _\`|/ _\`|
    | | | | | | | (_| | (_| |
    |_|_| |_| |_|\__,_|\__, |
                       |___/
    -------------------------

    Usage: imag [--version | --versions | -h | --help] <command> <args...>

    imag - the personal information management suite for the commandline

    imag is a PIM suite for the commandline. It consists of several commands,
    called "modules". Each module implements one PIM aspect and all of these
    modules can be used independently.

    Available commands:

    {imagbins}

    Call a command with 'imag <command> <args>'
    Each command can be called with "--help" to get the respective helptext.

    Please visit https://github.com/matthiasbeyer/imag to view the source code,
    follow the development of imag or maybe even contribute to imag.

    imag is free software. It is released under the terms of LGPLv2.1

    (c) 2016 Matthias Beyer and contributors"#,
        imagbins = cmds
            .into_iter()
            .map(|cmd| format!("\t{}\n", cmd))
            .fold(String::new(), |s, c| {
                let s = s + c.as_str();
                s
            }))
}

/// Returns the list of imag-* executables found in $PATH
fn get_commands() -> Vec<String> {
    match env::var("PATH") {
        Err(e) => {
            println!("PATH error: {:?}", e);
            exit(1);
        },

        Ok(path) => path
            .split(":")
            .flat_map(|elem| {
                WalkDir::new(elem)
                    .max_depth(1)
                    .into_iter()
                    .filter(|path| match *path {
                        Ok(ref p) => p.file_name().to_str().map_or(false, |f| f.starts_with("imag-")),
                        Err(_)    => false,
                    })
                    .filter_map(Result::ok)
                    .filter_map(|path| path
                        .file_name()
                       .to_str()
                       .and_then(|s| s.splitn(2, "-").nth(1).map(String::from))
                    )
            })
            .collect()
    }
}

fn main() {
    // Initialize the Runtime and build the CLI
    let appname  = "imag";
    let version  = &version!();
    let about    = "imag - the PIM suite for the commandline";
    let commands = get_commands();
    let helptext = help_text(commands.clone());
    let app      = Runtime::get_default_cli_builder(appname, version, about)
        .settings(&[AppSettings::AllowExternalSubcommands, AppSettings::ArgRequiredElseHelp])
        .arg(Arg::with_name("version")
             .long("version")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the version of imag"))
        .arg(Arg::with_name("versions")
             .long("versions")
             .takes_value(false)
             .required(false)
             .multiple(false)
             .help("Get the versions of the imag commands"))
        .subcommand(SubCommand::with_name("help").help("Show help"))
        .help(helptext.as_str());
    let rt = Runtime::new(app)
        .unwrap_or_else(|e| {
            println!("Runtime couldn't be setup. Exiting");
            trace_error(&e);
            exit(1);
        });
    let matches = rt.cli();

    debug!("matches: {:?}", matches);

    // Begin checking for arguments

    if matches.is_present("version") {
        debug!("Showing version");
        println!("imag {}", &version!()[..]);
        exit(0);
    }

    if matches.is_present("versions") {
        debug!("Showing versions");
        commands
            .iter()
            .map(|command| {
                match Command::new(format!("imag-{}", command))
                    .arg("--version")
                    .output()
                    .map(|v| v.stdout)
                {
                    Ok(s) => match String::from_utf8(s) {
                        Ok(s) => format!("{:10} -> {}", command, s),
                        Err(e) => format!("UTF8 Error while working with output of imag{}: {:?}", command, e),
                    },
                    Err(e) => format!("Failed calling imag-{} -> {:?}", command, e),
                }
            })
            .fold((), |_, line| {
                // The amount of newlines may differ depending on the subprocess
                println!("{}", line.trim());
            });

        exit(0);
    }

    let aliases = match fetch_aliases(&rt) {
        Ok(aliases) => aliases,
        Err(e)      => {
            println!("Error while fetching aliases from configuration file");
            debug!("Error = {:?}", e);
            println!("Aborting");
            exit(1);
        }
    };

    // Matches any subcommand given
    match matches.subcommand() {
        (subcommand, Some(scmd)) => {
            // Get all given arguments and further subcommands to pass to
            // the imag-<> binary
            // Providing no arguments is OK, and is therefore ignored here
            let mut subcommand_args : Vec<String> = match scmd.values_of("") {
                Some(values) => values.map(String::from).collect(),
                None => Vec::new()
            };

            forward_commandline_arguments(&matches, &mut subcommand_args);

            let subcommand = String::from(subcommand);
            let subcommand = aliases.get(&subcommand).cloned().unwrap_or(subcommand);

            debug!("Calling 'imag-{}' with args: {:?}", subcommand, subcommand_args);

            // Create a Command, and pass it the gathered arguments
            match Command::new(format!("imag-{}", subcommand))
                .stdin(Stdio::inherit())
                .stdout(Stdio::inherit())
                .stderr(Stdio::inherit())
                .args(&subcommand_args[..])
                .spawn()
                .and_then(|mut c| c.wait())
            {
                Ok(exit_status) => {
                    if !exit_status.success() {
                        debug!("{} exited with non-zero exit code: {:?}", subcommand, exit_status);
                        println!("{} exited with non-zero exit code", subcommand);
                        exit(exit_status.code().unwrap_or(1));
                    }
                    debug!("Successful exit!");
                },

                Err(e) => {
                    debug!("Error calling the subcommand");
                    match e.kind() {
                        ErrorKind::NotFound => {
                            println!("No such command: 'imag-{}'", subcommand);
                            println!("See 'imag --help' for available subcommands");
                            exit(1);
                        },
                        ErrorKind::PermissionDenied => {
                            println!("No permission to execute: 'imag-{}'", subcommand);
                            exit(1);
                        },
                        _ => {
                            println!("Error spawning: {:?}", e);
                            exit(1);
                        }
                    }
                }
            }
        },
        // Calling for example 'imag --versions' will lead here, as this option does not exit.
        // There's nothing to do in such a case
        _ => {},
    }
}

fn fetch_aliases(rt: &Runtime) -> Result<BTreeMap<String, String>, String> {
    let cfg   = rt.config().ok_or_else(|| String::from("No configuration found"))?;
    let value = cfg
        .read("imag.aliases")
        .map_err(|_| String::from("Reading from config failed"));

    match value? {
        None                         => Ok(BTreeMap::new()),
        Some(&Value::Table(ref tbl)) => {
            let mut alias_mappings = BTreeMap::new();

            for (k, v) in tbl {
                match v {
                    &Value::String(ref alias)      => {
                        alias_mappings.insert(alias.clone(), k.clone());
                    },
                    &Value::Array(ref aliases) => {
                        for alias in aliases {
                            match alias {
                                &Value::String(ref s) => {
                                    alias_mappings.insert(s.clone(), k.clone());
                                },
                                _ => {
                                    let e = format!("Not all values are a String in 'imag.aliases.{}'", k);
                                    return Err(e);
                                }
                            }
                        }
                    },

                    _ => {
                        let msg = format!("Type Error: 'imag.aliases.{}' is not a table or string", k);
                        return Err(msg);
                    },
                }
            }

            Ok(alias_mappings)
        },

        Some(_) => Err(String::from("Type Error: 'imag.aliases' is not a table")),
    }
}

fn forward_commandline_arguments(m: &ArgMatches, scmd: &mut Vec<String>) {
    let push = |flag: Option<&str>, val_name: &str, m: &ArgMatches, v: &mut Vec<String>| {
        let _ = m
            .value_of(val_name)
            .map(|val| {
                let flag = format!("--{}", flag.unwrap_or(val_name));
                v.insert(0, String::from(val));
                v.insert(0, flag);
            });
    };

    push(Some("verbose"),
         Runtime::arg_verbosity_name(), m , scmd);

    push(Some("debug"),
         Runtime::arg_debugging_name(), m , scmd);

    push(Some("no-color"),
         Runtime::arg_no_color_output_name(), m , scmd);

    push(Some("config"),
         Runtime::arg_config_name(), m , scmd);

    push(Some("override-config"),
         Runtime::arg_config_override_name(), m , scmd);

    push(Some("rtp"),
         Runtime::arg_runtimepath_name(), m , scmd);

    push(Some("store"),
         Runtime::arg_storepath_name(), m , scmd);

    push(Some("editor"),
         Runtime::arg_editor_name(), m , scmd);

    push(Some("generate-commandline-completion"),
         Runtime::arg_generate_compl(), m , scmd);

    push(None , Runtime::arg_logdest_name()                         , m , scmd);

}

<|endoftext|>


<commit_before><commit_msg>Added an example solution that uses `gcj-helper`<commit_after>// Copyright (c) 2017 FaultyRAM
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT
// or http://opensource.org/licenses/MIT>, at your option. This file may not be
// copied, modified, or distributed except according to those terms.

//! An example Google Code Jam solution using `gcj-helper`.
//!
//! This is a naive solution for *Counting Sheep*, a.k.a. Problem A from the Qualification Round
//! of Google Code Jam 2016.

extern crate gcj_helper;

use gcj_helper::{TestCaseIo, TestCases};
use std::io::Write;

fn insomnia(tc_io: &mut TestCaseIo) {
    writeln!(tc_io, " INSOMNIA").expect("could not write to output file");
}

fn result(tc_io: &mut TestCaseIo, number: &str) {
    writeln!(tc_io, " {}", number).expect("could not write to output file");
}

fn main() {
    let tc = TestCases::new();
    tc.run(|tc_io| {
        let mut digits_found = [false; 10];
        let mut digits_count = 0;
        let mut step = tc_io.read_line();
        let mut step_mul = 2;
        let number = u32::from_str_radix(&step, 10).expect("could not parse test case");
        if step == "0" {
            insomnia(tc_io);
            return;
        }
        loop {
            for digit in step.bytes() {
                match digit {
                    0x30...0x39 => {
                        let i = (digit - 0x30) as usize;
                        if !digits_found[i] {
                            digits_found[i] = true;
                            digits_count += 1;
                            if digits_count >= digits_found.len() {
                                result(tc_io, &step);
                                return;
                            }
                        }
                    }
                    _ => unreachable!(),
                }
            }
            step = (number * step_mul).to_string();
            step_mul += 1;
        }
    });
}
<|endoftext|>


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

#![feature(core)]
use std::boxed::FnBox;

struct FuncContainer {
    f1: fn(data: u8),
    f2: extern "C" fn(data: u8),
    f3: unsafe fn(data: u8),
}

struct FuncContainerOuter {
    container: Box<FuncContainer>
}

struct Obj<F> where F: FnOnce() -> u32 {
    closure: F,
    not_closure: usize,
}

struct BoxedObj {
    boxed_closure: Box<FnBox() -> u32>,
}

struct Wrapper<F> where F: FnMut() -> u32 {
    wrap: Obj<F>,
}

fn func() -> u32 {
    0
}

fn check_expression() -> Obj<Box<FnBox() -> u32>> {
    Obj { closure: Box::new(|| 42_u32) as Box<FnBox() -> u32>, not_closure: 42 }
}

fn main() {
    // test variations of function

    let o_closure = Obj { closure: || 42, not_closure: 42 };
    o_closure.closure(); //~ ERROR no method named `closure` found
    //~^ NOTE use `(o_closure.closure)(...)` if you meant to call the function stored

    o_closure.not_closure(); //~ ERROR no method named `not_closure` found
    //~^ NOTE did you mean to write `o_closure.not_closure`?

    let o_func = Obj { closure: func, not_closure: 5 };
    o_func.closure(); //~ ERROR no method named `closure` found
    //~^ NOTE use `(o_func.closure)(...)` if you meant to call the function stored

    let boxed_fn = BoxedObj { boxed_closure: Box::new(func) };
    boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found
    //~^ NOTE use `(boxed_fn.boxed_closure)(...)` if you meant to call the function stored

    let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnBox() -> u32> };
    boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found
    //~^ NOTE use `(boxed_closure.boxed_closure)(...)` if you meant to call the function stored

    // test expression writing in the notes

    let w = Wrapper { wrap: o_func };
    w.wrap.closure();//~ ERROR no method named `closure` found
    //~^ NOTE use `(w.wrap.closure)(...)` if you meant to call the function stored

    w.wrap.not_closure();//~ ERROR no method named `not_closure` found
    //~^ NOTE did you mean to write `w.wrap.not_closure`?

    check_expression().closure();//~ ERROR no method named `closure` found
    //~^ NOTE use `(check_expression().closure)(...)` if you meant to call the function stored
}

impl FuncContainerOuter {
    fn run(&self) {
        unsafe {
            (*self.container).f1(1); //~ ERROR no method named `f1` found
            //~^ NOTE use `(*self.container.f1)(...)`
            (*self.container).f2(1); //~ ERROR no method named `f2` found
            //~^ NOTE use `(*self.container.f2)(...)`
            (*self.container).f3(1); //~ ERROR no method named `f3` found
            //~^ NOTE use `(*self.container.f3)(...)`
        }
    }
}
<commit_msg>Fix code suggestion in test<commit_after>// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(core)]
use std::boxed::FnBox;

struct FuncContainer {
    f1: fn(data: u8),
    f2: extern "C" fn(data: u8),
    f3: unsafe fn(data: u8),
}

struct FuncContainerOuter {
    container: Box<FuncContainer>
}

struct Obj<F> where F: FnOnce() -> u32 {
    closure: F,
    not_closure: usize,
}

struct BoxedObj {
    boxed_closure: Box<FnBox() -> u32>,
}

struct Wrapper<F> where F: FnMut() -> u32 {
    wrap: Obj<F>,
}

fn func() -> u32 {
    0
}

fn check_expression() -> Obj<Box<FnBox() -> u32>> {
    Obj { closure: Box::new(|| 42_u32) as Box<FnBox() -> u32>, not_closure: 42 }
}

fn main() {
    // test variations of function

    let o_closure = Obj { closure: || 42, not_closure: 42 };
    o_closure.closure(); //~ ERROR no method named `closure` found
    //~^ NOTE use `(o_closure.closure)(...)` if you meant to call the function stored

    o_closure.not_closure(); //~ ERROR no method named `not_closure` found
    //~^ NOTE did you mean to write `o_closure.not_closure`?

    let o_func = Obj { closure: func, not_closure: 5 };
    o_func.closure(); //~ ERROR no method named `closure` found
    //~^ NOTE use `(o_func.closure)(...)` if you meant to call the function stored

    let boxed_fn = BoxedObj { boxed_closure: Box::new(func) };
    boxed_fn.boxed_closure();//~ ERROR no method named `boxed_closure` found
    //~^ NOTE use `(boxed_fn.boxed_closure)(...)` if you meant to call the function stored

    let boxed_closure = BoxedObj { boxed_closure: Box::new(|| 42_u32) as Box<FnBox() -> u32> };
    boxed_closure.boxed_closure();//~ ERROR no method named `boxed_closure` found
    //~^ NOTE use `(boxed_closure.boxed_closure)(...)` if you meant to call the function stored

    // test expression writing in the notes

    let w = Wrapper { wrap: o_func };
    w.wrap.closure();//~ ERROR no method named `closure` found
    //~^ NOTE use `(w.wrap.closure)(...)` if you meant to call the function stored

    w.wrap.not_closure();//~ ERROR no method named `not_closure` found
    //~^ NOTE did you mean to write `w.wrap.not_closure`?

    check_expression().closure();//~ ERROR no method named `closure` found
    //~^ NOTE use `(check_expression().closure)(...)` if you meant to call the function stored
}

impl FuncContainerOuter {
    fn run(&self) {
        unsafe {
            (*self.container).f1(1); //~ ERROR no method named `f1` found
            //~^ NOTE use `((*self.container).f1)(...)`
            (*self.container).f2(1); //~ ERROR no method named `f2` found
            //~^ NOTE use `((*self.container).f2)(...)`
            (*self.container).f3(1); //~ ERROR no method named `f3` found
            //~^ NOTE use `((*self.container).f3)(...)`
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Write a redis parser<commit_after>
  fn take_n(v: &r/[u8], n: uint) -> (&r/[u8], &r/[u8]) {
    (vec::view(v, 0, n), vec::view(v, n, v.len()))
  }

  fn take_atmost_n(v: &r/[u8], n: uint) -> (&r/[u8], &r/[u8]) {
    take_n(v, uint::min(n, v.len()))
  }

  fn take_head(v: &r/[u8]) -> (u8, &r/[u8]) {
    assert v.is_not_empty();
    (v.head(), vec::view(v, 1, v.len()))
  }

  // in_integer
  enum RedisType {
    TyNone,
    TyList,
    TyData,
    TyInt
  }

  enum Inside {
    in_nothing,
    in_number,
    in_number_done,
    in_number_need_newline,
    in_data,
    //in_data_need_newline
  }

  //in_number(TYPE),
  //in_number_done(TYPE),
  //in_number_need_newline(TYPE)

  struct RedisState {
    mut in: Inside,
    mut typ: RedisType,
    mut data_size: uint,
    mut data_have: uint,
    mut number: uint,
    mut stack: ~[(uint, uint)] // (len, idx)
  }

  enum RedisResult {
    Finished,
    NeedMore,
    Error
  }

  // returns true if we are finished parsing a redis request
  fn element_done(st: &mut RedisState) -> bool {
    if st.stack.is_empty() {
      true
    }
    else {
      let (len, idx) = st.stack.last();
      assert idx+1 <= len;
      st.stack[st.stack.len()-1] = (len, idx+1);
      if idx + 1 == len {
        error!("Finsihed list");
        let _ = vec::pop(&mut st.stack);
        element_done(st)
      }
      else {
        false
      }
    }
  }

  fn parse_redis(st: &mut RedisState, buf: &r/[u8]) -> (RedisResult, &r/[u8]) {
    let mut buf = buf;

    loop {
      match st.in {
        in_nothing => {
          if (buf.is_empty()) {break}
          error!("in_nothing");

          let (c, b) = take_head(buf);
          buf = b;

          match c as char {
            '\r' | '\n' | ' ' =>  {
                error!("ignoring carriage return/new/whitespace line")
              }
            '*' => {
                st.typ = TyList;
                st.in = in_number;
                st.number = 0;
              }
            '$' => {
                st.typ = TyData;
                st.in = in_number;
                st.number = 0;
             }
            ':' => {
                st.typ = TyInt;
                st.in = in_number;
                st.number = 0;
             }

             _ => {
                return (Error, buf) // XXX: return a slice including the character that failed
             }
          }

        }

        in_data => {
          if (buf.is_empty()) {break}
          let (data, b) = take_atmost_n(buf, st.data_size - st.data_have);
          buf = b;
          error!("GOT data: %?", data);
          st.data_have += data.len();
          assert st.data_have <= st.data_size;
          if st.data_have == st.data_size {
            error!("GOT DATA COMPLETE");
            //st.in = in_data_need_newline;
            st.in = in_nothing;
            if element_done(st) {
              return (Finished, buf)
            }
          }
        }

        // we could treat the newline after data differently.
/*
        in_data_need_newline => {
          if (buf.is_empty()) {break}
          let (c, b) = take_head(buf);
          buf = b;
          if c == ('\n' as u8) {
            st.in = in_nothing;
          }
          else if c == ('\r' as u8) || c == (' ' as u8) {
            error("Consume whitespace");
          }
          else {
            return (Error, buf)
          }
        }
*/

        in_number_need_newline => {
          if (buf.is_empty()) {break}
          error!("in_number_need_newline");
          let (c, b) = take_head(buf);
          buf = b;
          if c == ('\n' as u8) {
            st.in = in_number_done;
          }
          else {
            return (Error, buf)
          }
        }
        // XXX: Negative numbers

        // XXX: make a function instead of a STATE
        in_number_done => {
          error!("in_number_done");
          match st.typ {
            TyData => {
              st.data_size = st.number;
              st.data_have = 0;
              st.in = in_data;
            }
            TyList => {
              // XXX:
              // push current recursion level and index on stack
              st.in = in_nothing;
              if st.number > 0 {
                vec::push(&mut st.stack, (st.number, 0));
              }
              else if st.number == 0 {
                if element_done(st) {
                  return (Finished, buf)
                }
              } else if (st.number == -1) {
                // NIL
                if element_done(st) {
                  return (Finished, buf)
                }
              }
              else {
                return (Error, buf)
              }

            }
            TyInt => {
              error!("GOT INTEGER: %?", st.number);
              st.in = in_nothing;
              if element_done(st) {
                return (Finished, buf)
              }
            }
            _ => {
              fail ~"THIS SHOULD NEVER HAPPEN"
            }
          }
        }

        in_number => {
          if (buf.is_empty()) {break}
          error!("in_number");
          let (c, b) = take_head(buf);
          buf = b;

          if c >= ('0' as u8) && c <= ('9' as u8) {
            st.number *= 10;
            st.number += (c - ('0' as u8)) as uint;
            error!("number: %?", st.number);
          }
          else if c as char == '\r' || c as char == ' ' {
            error!("number need newline");
            st.in = in_number_need_newline;
          }
          else if c as char == '\n' {
            error!("number finsihed");
            st.in = in_number_done;
          }
          else {
            return (Error, buf)
          }

        }
      }
    }
    (NeedMore, buf)
  }

fn main() {

  let mut st = RedisState {
    in: in_nothing,
    typ: TyNone,
    data_size: 0,
    data_have: 0,
    number: 0,
    stack: ~[]
  };

  error!("%?", st);

  let s = ~"*3\r\n$3\r\nabc\r\n:123\n:1\n";
  do str::as_bytes(&s) |v| {
    let x = parse_redis(&mut st, vec::view(*v, 0, (*v).len() - 1));
    error!("%?", st);
    error!("%?", x);
  }

}
<|endoftext|>


<commit_before><commit_msg>Initial commit<commit_after>// WARNING: Not utf-8 safe. But (hopefully) you get the idea.  To make
// it utf-8 safe, you'd want to rewrite to extract out characters
// rather than just indexing `str[pos]`.

extern mod std;

#[deriving(Eq)]
enum Re {
    ReChar(char),
    ReDot,
    ReStar(~Re),
    RePlus(~Re),
    ReSeq(~[Re]),
    ReGroup(~Re)
}

enum IntermediateResult {
    ParseOk(Re, uint),
    ParseErr(uint, ~str)
}

fn parse_regex(str: &str) -> Result<Re, ~str> {
    return match seq(str, 0) {
        ParseErr(pos, msg) => {
            Err(fmt!("at position %u, %s", pos, msg))
        }
        ParseOk(_, pos) if pos < str.len() => {
            // did not consume entire string
            Err(fmt!("at position %u, unexpected character '%c'", pos, str[pos] as char))
        }
        ParseOk(re, _) => {
            Ok(re)
        }
    };

    fn expect(str: &str, pos: uint, expect: char, ok: Re) -> IntermediateResult {
        if pos < str.len() && str[pos] as char == expect {
            ParseOk(ok, pos+1)
        } else if pos < str.len() {
            ParseErr(pos, fmt!("expected '%c', found '%c'", expect, str[pos] as char))
        } else {
            ParseErr(pos, fmt!("expected '%c', found EOF", expect))
        }
    }

    fn seq(str: &str, mut pos: uint) -> IntermediateResult {
        let mut vec = ~[];
        while pos < str.len() {
            match str[pos] as char {
                ')' => {
                    break;
                }
                _ => {
                    match rep(str, pos) {
                        ParseErr(pos, msg) => {
                            return ParseErr(pos, msg);
                        }
                        ParseOk(r, pos1) => {
                            vec.push(r);
                            pos = pos1;
                        }
                    }
                }
            }
        }
        ParseOk(ReSeq(vec), pos)
    }

    fn rep(str: &str, pos: uint) -> IntermediateResult {
        match base(str, pos) {
            ParseErr(pos, msg) => ParseErr(pos, msg),
            ParseOk(r, pos) => {
                match str[pos] as char {
                    '*' => {
                        ParseOk(ReStar(~r), pos+1)
                    }
                    '+' => {
                        ParseOk(RePlus(~r), pos+1)
                    }
                    _ => {
                        ParseOk(r, pos)
                    }
                }
            }
        }
    }

    fn base(str: &str, pos: uint) -> IntermediateResult {
        match str[pos] as char {
            '.' => {
                ParseOk(ReDot, pos+1)
            }
            '\\' => {
                if pos + 1 == str.len() {
                    ParseErr(pos+1, ~"EOF in escape")
                } else {
                    ParseOk(ReChar(str[pos+1] as char), pos + 2)
                }
            }
            '(' => {
                match seq(str, pos+1) {
                    ParseErr(pos, msg) => ParseErr(pos, msg),
                    ParseOk(r, pos) => {
                        expect(str, pos, ')', ReGroup(~r))
                    }
                }
            }
            ')' => {
                ParseErr(pos, ~"Unbalanced close paren")
            }
            c => {
                ParseOk(ReChar(c), pos+1)
            }
        }
    }
}

#[test]
fn parse_abc() {
    assert_eq!(
        parse_regex("abc*"),
        Ok(ReSeq(~[ReChar('a'), ReChar('b'), ReStar(~ReChar('c'))])));
}

#[test]
fn parse_group() {
    assert_eq!(
        parse_regex("a(bc)*"),
        Ok(ReSeq(~[ReChar('a'),
                   ReStar(~ReGroup(~ReSeq(~[ReChar('b'), ReChar('c')])))])));
}
<|endoftext|>


<commit_before><commit_msg>Add Linkable::is_linked_to()<commit_after><|endoftext|>


<commit_before><commit_msg>Push request processing down into AccessCodec.decode()<commit_after><|endoftext|>


<commit_before><commit_msg>Implement encrypt for ElGamal<commit_after><|endoftext|>


<commit_before>use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

use {Future, Poll, Async};
use slot::{Slot, Token};
use lock::Lock;
use task::{self, Task};

/// A future representing the completion of a computation happening elsewhere in
/// memory.
///
/// This is created by the `oneshot` function.
#[must_use = "futures do nothing unless polled"]
pub struct Oneshot<T> {
    inner: Arc<Inner<T>>,
    cancel_token: Option<Token>,
}

/// Represents the completion half of a oneshot through which the result of a
/// computation is signaled.
///
/// This is created by the `oneshot` function.
pub struct Complete<T> {
    inner: Arc<Inner<T>>,
    completed: bool,
}

struct Inner<T> {
    slot: Slot<Option<T>>,
    oneshot_gone: AtomicBool,
    notify_cancel: Lock<Option<Task>>,
}

/// Creates a new in-memory oneshot used to represent completing a computation.
///
/// A oneshot in this library is a concrete implementation of the `Future` trait
/// used to complete a computation from one location with a future representing
/// what to do in another.
///
/// This function is similar to Rust's channels found in the standard library.
/// Two halves are returned, the first of which is a `Oneshot` which implements
/// the `Future` trait. The second half is a `Complete` handle which is used to
/// signal the end of a computation.
///
/// Each half can be separately owned and sent across threads.
///
/// # Examples
///
/// ```
/// use std::thread;
/// use futures::*;
///
/// let (c, p) = oneshot::<i32>();
///
/// thread::spawn(|| {
///     p.map(|i| {
///         println!("got: {}", i);
///     }).wait();
/// });
///
/// c.complete(3);
/// ```
pub fn oneshot<T>() -> (Complete<T>, Oneshot<T>) {
    let inner = Arc::new(Inner {
        slot: Slot::new(None),
        oneshot_gone: AtomicBool::new(false),
        notify_cancel: Lock::new(None),
    });
    let oneshot = Oneshot {
        inner: inner.clone(),
        cancel_token: None,
    };
    let complete = Complete {
        inner: inner,
        completed: false,
    };
    (complete, oneshot)
}

impl<T> Complete<T> {
    /// Completes this oneshot with a successful result.
    ///
    /// This function will consume `self` and indicate to the other end, the
    /// `Oneshot`, that the error provided is the result of the computation this
    /// represents.
    pub fn complete(mut self, t: T) {
        self.completed = true;
        self.send(Some(t))
    }

    /// Polls this `Complete` half to detect whether the `Oneshot` this has
    /// paired with has gone away.
    ///
    /// This function can be used to learn about when the `Oneshot` (consumer)
    /// half has gone away and nothing will be able to receive a message sent
    /// from `complete`.
    ///
    /// Like `Future::poll`, this function will panic if it's not called from
    /// within the context of a task. In otherwords, this should only ever be
    /// called from inside another future.
    ///
    /// If `Ready` is returned then it means that the `Oneshot` has disappeared
    /// and the result this `Complete` would otherwise produce should no longer
    /// be produced.
    ///
    /// If `NotReady` is returned then the `Oneshot` is still alive and may be
    /// able to receive a message if sent. The current task, however, is
    /// scheduled to receive a notification if the corresponding `Oneshot` goes
    /// away.
    pub fn poll_cancel(&mut self) -> Poll<(), ()> {
        // Fast path up first, just read the flag and see if our other half is
        // gone.
        if self.inner.oneshot_gone.load(Ordering::SeqCst) {
            return Ok(Async::Ready(()))
        }

        // If our other half is not gone then we need to park our current task
        // and move it into the `notify_cancel` slot to get notified when it's
        // actually gone.
        //
        // If `try_lock` fails, then the `Oneshot` is in the process of using
        // it, so we can deduce that it's now in the process of going away and
        // hence we're canceled. If it succeeds then we just store our handle.
        //
        // Crucially we then check `oneshot_gone` *again* before we return.
        // While we were storing our handle inside `notify_cancel` the `Oneshot`
        // may have been dropped. The first thing it does is set the flag, and
        // if it fails to acquire the lock it assumes that we'll see the flag
        // later on. So... we then try to see the flag later on!
        let handle = task::park();
        match self.inner.notify_cancel.try_lock() {
            Some(mut p) => *p = Some(handle),
            None => return Ok(Async::Ready(())),
        }
        if self.inner.oneshot_gone.load(Ordering::SeqCst) {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::NotReady)
        }
    }

    fn send(&mut self, t: Option<T>) {
        if let Err(e) = self.inner.slot.try_produce(t) {
            self.inner.slot.on_empty(Some(e.into_inner()), |slot, item| {
                slot.try_produce(item.unwrap()).ok()
                    .expect("advertised as empty but wasn't");
            });
        }
    }
}

impl<T> Drop for Complete<T> {
    fn drop(&mut self) {
        if !self.completed {
            self.send(None);
        }
    }
}

/// Error returned from a `Oneshot<T>` whenever the correponding `Complete<T>`
/// is dropped.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Canceled;

impl<T> Future for Oneshot<T> {
    type Item = T;
    type Error = Canceled;

    fn poll(&mut self) -> Poll<T, Canceled> {
        if let Some(cancel_token) = self.cancel_token.take() {
            self.inner.slot.cancel(cancel_token);
        }
        match self.inner.slot.try_consume() {
            Ok(Some(e)) => Ok(Async::Ready(e)),
            Ok(None) => Err(Canceled),
            Err(_) => {
                let task = task::park();
                self.cancel_token = Some(self.inner.slot.on_full(move |_| {
                    task.unpark();
                }));
                Ok(Async::NotReady)
            }
        }
    }
}

impl<T> Drop for Oneshot<T> {
    fn drop(&mut self) {
        // First up, if we squirreled away a task to get notified once the
        // oneshot was filled in, we cancel that notification. We'll never end
        // up actually receiving data (as we're being dropped) so no need to
        // hold onto the task.
        if let Some(cancel_token) = self.cancel_token.take() {
            self.inner.slot.cancel(cancel_token)
        }

        // Next up, inform the `Complete` half that we're going away. First up
        // we flag ourselves as gone, and next we'll attempt to wake up any
        // handle that was stored.
        //
        // If we fail to acquire the lock on the handle, that means that a
        // `Complete` is in the process of storing one, and it'll check
        // `oneshot_gone` on its way out to see our write here.
        self.inner.oneshot_gone.store(true, Ordering::SeqCst);
        if let Some(mut handle) = self.inner.notify_cancel.try_lock() {
            if let Some(task) = handle.take() {
                drop(handle);
                task.unpark()
            }
        }
    }
}
<commit_msg>Describe oneshot return values in the right order.<commit_after>use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};

use {Future, Poll, Async};
use slot::{Slot, Token};
use lock::Lock;
use task::{self, Task};

/// A future representing the completion of a computation happening elsewhere in
/// memory.
///
/// This is created by the `oneshot` function.
#[must_use = "futures do nothing unless polled"]
pub struct Oneshot<T> {
    inner: Arc<Inner<T>>,
    cancel_token: Option<Token>,
}

/// Represents the completion half of a oneshot through which the result of a
/// computation is signaled.
///
/// This is created by the `oneshot` function.
pub struct Complete<T> {
    inner: Arc<Inner<T>>,
    completed: bool,
}

struct Inner<T> {
    slot: Slot<Option<T>>,
    oneshot_gone: AtomicBool,
    notify_cancel: Lock<Option<Task>>,
}

/// Creates a new in-memory oneshot used to represent completing a computation.
///
/// A oneshot in this library is a concrete implementation of the `Future` trait
/// used to complete a computation from one location with a future representing
/// what to do in another.
///
/// This function is similar to Rust's channels found in the standard library.
/// Two halves are returned, the first of which is a `Complete` handle, used to
/// signal the end of a computation and provide its value. The second half is a
/// `Oneshot` which implements the `Future` trait, resolving to the value that
/// was given to the `Complete` handle.
///
/// Each half can be separately owned and sent across threads.
///
/// # Examples
///
/// ```
/// use std::thread;
/// use futures::*;
///
/// let (c, p) = oneshot::<i32>();
///
/// thread::spawn(|| {
///     p.map(|i| {
///         println!("got: {}", i);
///     }).wait();
/// });
///
/// c.complete(3);
/// ```
pub fn oneshot<T>() -> (Complete<T>, Oneshot<T>) {
    let inner = Arc::new(Inner {
        slot: Slot::new(None),
        oneshot_gone: AtomicBool::new(false),
        notify_cancel: Lock::new(None),
    });
    let oneshot = Oneshot {
        inner: inner.clone(),
        cancel_token: None,
    };
    let complete = Complete {
        inner: inner,
        completed: false,
    };
    (complete, oneshot)
}

impl<T> Complete<T> {
    /// Completes this oneshot with a successful result.
    ///
    /// This function will consume `self` and indicate to the other end, the
    /// `Oneshot`, that the error provided is the result of the computation this
    /// represents.
    pub fn complete(mut self, t: T) {
        self.completed = true;
        self.send(Some(t))
    }

    /// Polls this `Complete` half to detect whether the `Oneshot` this has
    /// paired with has gone away.
    ///
    /// This function can be used to learn about when the `Oneshot` (consumer)
    /// half has gone away and nothing will be able to receive a message sent
    /// from `complete`.
    ///
    /// Like `Future::poll`, this function will panic if it's not called from
    /// within the context of a task. In otherwords, this should only ever be
    /// called from inside another future.
    ///
    /// If `Ready` is returned then it means that the `Oneshot` has disappeared
    /// and the result this `Complete` would otherwise produce should no longer
    /// be produced.
    ///
    /// If `NotReady` is returned then the `Oneshot` is still alive and may be
    /// able to receive a message if sent. The current task, however, is
    /// scheduled to receive a notification if the corresponding `Oneshot` goes
    /// away.
    pub fn poll_cancel(&mut self) -> Poll<(), ()> {
        // Fast path up first, just read the flag and see if our other half is
        // gone.
        if self.inner.oneshot_gone.load(Ordering::SeqCst) {
            return Ok(Async::Ready(()))
        }

        // If our other half is not gone then we need to park our current task
        // and move it into the `notify_cancel` slot to get notified when it's
        // actually gone.
        //
        // If `try_lock` fails, then the `Oneshot` is in the process of using
        // it, so we can deduce that it's now in the process of going away and
        // hence we're canceled. If it succeeds then we just store our handle.
        //
        // Crucially we then check `oneshot_gone` *again* before we return.
        // While we were storing our handle inside `notify_cancel` the `Oneshot`
        // may have been dropped. The first thing it does is set the flag, and
        // if it fails to acquire the lock it assumes that we'll see the flag
        // later on. So... we then try to see the flag later on!
        let handle = task::park();
        match self.inner.notify_cancel.try_lock() {
            Some(mut p) => *p = Some(handle),
            None => return Ok(Async::Ready(())),
        }
        if self.inner.oneshot_gone.load(Ordering::SeqCst) {
            Ok(Async::Ready(()))
        } else {
            Ok(Async::NotReady)
        }
    }

    fn send(&mut self, t: Option<T>) {
        if let Err(e) = self.inner.slot.try_produce(t) {
            self.inner.slot.on_empty(Some(e.into_inner()), |slot, item| {
                slot.try_produce(item.unwrap()).ok()
                    .expect("advertised as empty but wasn't");
            });
        }
    }
}

impl<T> Drop for Complete<T> {
    fn drop(&mut self) {
        if !self.completed {
            self.send(None);
        }
    }
}

/// Error returned from a `Oneshot<T>` whenever the correponding `Complete<T>`
/// is dropped.
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct Canceled;

impl<T> Future for Oneshot<T> {
    type Item = T;
    type Error = Canceled;

    fn poll(&mut self) -> Poll<T, Canceled> {
        if let Some(cancel_token) = self.cancel_token.take() {
            self.inner.slot.cancel(cancel_token);
        }
        match self.inner.slot.try_consume() {
            Ok(Some(e)) => Ok(Async::Ready(e)),
            Ok(None) => Err(Canceled),
            Err(_) => {
                let task = task::park();
                self.cancel_token = Some(self.inner.slot.on_full(move |_| {
                    task.unpark();
                }));
                Ok(Async::NotReady)
            }
        }
    }
}

impl<T> Drop for Oneshot<T> {
    fn drop(&mut self) {
        // First up, if we squirreled away a task to get notified once the
        // oneshot was filled in, we cancel that notification. We'll never end
        // up actually receiving data (as we're being dropped) so no need to
        // hold onto the task.
        if let Some(cancel_token) = self.cancel_token.take() {
            self.inner.slot.cancel(cancel_token)
        }

        // Next up, inform the `Complete` half that we're going away. First up
        // we flag ourselves as gone, and next we'll attempt to wake up any
        // handle that was stored.
        //
        // If we fail to acquire the lock on the handle, that means that a
        // `Complete` is in the process of storing one, and it'll check
        // `oneshot_gone` on its way out to see our write here.
        self.inner.oneshot_gone.store(true, Ordering::SeqCst);
        if let Some(mut handle) = self.inner.notify_cancel.try_lock() {
            if let Some(task) = handle.take() {
                drop(handle);
                task.unpark()
            }
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>coap work<commit_after><|endoftext|>


<commit_before><commit_msg>99 bottles of beer written in Rust<commit_after>fn main() {
    for n in ::std::iter::range_step(99,0,-1) {
        if n > 1 {
            println!("{} bottles of beer on the wall, {} bottles of beer.", n, n);
            if n > 2 {
                println!("Take on down and pass it around, {} bottles of beer on the wall.", n-1);
            } else {
                println!("Take on down and pass it around, 1 bottle of beer on the wall.");
            }
        } else {
            println!("1 bottle of beer on the wall, 1 bottle of beer.");
            println!("Take one down and pass it around, no more bottles of beer on the wall.");
        }
        println!("");
    }
    println!("No more bottles of beer on the wall, no more bottles of beer.");
    println!("Go to the store and buy some more, 99 bottles of beer on the wall.\n");
}
<|endoftext|>


<commit_before><commit_msg>an empy message<commit_after><|endoftext|>


<commit_before><commit_msg>Add another example for verifying message deserialization<commit_after>extern crate slack_api as slack;
extern crate reqwest;

use std::env;

fn main() {
    let token = env::var("SLACK_API_TOKEN").expect("SLACK_API_TOKEN not set.");
    let client = reqwest::Client::new().unwrap();

    let response = slack::channels::history(&client,
                                            &token,
                                            &slack::channels::HistoryRequest {
                                                channel: &env::args().nth(1).unwrap(),
                                                ..slack::channels::HistoryRequest::default()
                                            });

    if let Ok(response) = response {
        if let Some(messages) = response.messages {
            println!("Got {} messages:", messages.len());
            for message in messages {
                println!("{:?}", message);
            }
        }
    } else {
        println!("{:?}", response);
    }
}
<|endoftext|>