<commit_before>//! Just a dumping ground for cli stuff

use multirust::{Cfg, Result, Notification, Toolchain, Error};
use multirust_utils::{self, utils};
use multirust_utils::notify::NotificationLevel;
use std::ffi::OsStr;
use std::io::{Write, Read, BufRead};
use std::process::{self, Command};
use std;
use tty;
use term;

pub fn confirm(question: &str, default: bool) -> Result<bool> {
    print!("{} ", question);
    let _ = std::io::stdout().flush();
    let input = try!(read_line());

    let r = match &*input {
        "y" | "Y" => true,
        "n" | "N" => false,
        "" => default,
        _ => false,
    };

    println!("");

    Ok(r)
}

fn read_line() -> Result<String> {
    let stdin = std::io::stdin();
    let stdin = stdin.lock();
    let mut lines = stdin.lines();
    lines.next().and_then(|l| l.ok()).ok_or(Error::ReadStdin)
}

pub fn wait_for_keypress() -> Result<()> {
    let stdin = std::io::stdin();
    if stdin.bytes().next().is_some() {
        Ok(())
    } else {
        Err(Error::ReadStdin)
    }
}

pub fn set_globals(verbose: bool) -> Result<Cfg> {
    use download_tracker::DownloadTracker;
    use std::cell::RefCell;

    let download_tracker = RefCell::new(DownloadTracker::new());

    Cfg::from_env(shared_ntfy!(move |n: Notification| {
        if download_tracker.borrow_mut().handle_notification(&n) {
            return;
        }

        match n.level() {
            NotificationLevel::Verbose => {
                if verbose {
                    verbose!("{}", n);
                }
            }
            NotificationLevel::Info => {
                info!("{}", n);
            }
            NotificationLevel::Warn => {
                warn!("{}", n);
            }
            NotificationLevel::Error => {
                err!("{}", n);
            }
        }
    }))

}

pub fn run_inner<S: AsRef<OsStr>>(mut command: Command,
                                  args: &[S]) -> Result<()> {
    command.args(&args[1..]);
    // FIXME rust-lang/rust#32254. It's not clear to me
    // when and why this is needed.
    command.stdin(process::Stdio::inherit());

    let status = command.status();

    match status {
        Ok(status) => {
            // Ensure correct exit code is returned
            let code = status.code().unwrap_or(1);
            process::exit(code);
        }
        Err(e) => {
            Err(multirust_utils::Error::RunningCommand {
                name: args[0].as_ref().to_owned(),
                error: multirust_utils::raw::CommandError::Io(e),
            }.into())
        }
    }
}

pub fn show_channel_version(cfg: &Cfg, name: &str) -> Result<()> {
    println!("");
    let mut t = term::stdout().unwrap();
    if tty::stdout_isatty() { let _ = t.fg(term::color::BRIGHT_WHITE); }
    if tty::stdout_isatty() { let _ = t.bg(term::color::BLACK); }
    let _ = write!(t, "{}", name);
    if tty::stdout_isatty() { let _ = t.reset(); }
    let _ = writeln!(t, " revision:");
    println!("");
    try!(show_tool_versions(&try!(cfg.get_toolchain(&name, false))));
    println!("");
    Ok(())
}

pub fn show_tool_versions(toolchain: &Toolchain) -> Result<()> {
    if toolchain.exists() {
        let rustc_path = toolchain.binary_file("rustc");
        let cargo_path = toolchain.binary_file("cargo");

        if utils::is_file(&rustc_path) {
            let mut cmd = Command::new(&rustc_path);
            cmd.arg("--version");
            toolchain.set_ldpath(&mut cmd);

            if utils::cmd_status("rustc", &mut cmd).is_err() {
                println!("(failed to run rustc)");
            }
        } else {
            println!("(no rustc command in toolchain?)");
        }
        if utils::is_file(&cargo_path) {
            let mut cmd = Command::new(&cargo_path);
            cmd.arg("--version");
            toolchain.set_ldpath(&mut cmd);

            if utils::cmd_status("cargo", &mut cmd).is_err() {
                println!("(failed to run cargo)");
            }
        } else {
            println!("(no cargo command in toolchain?)");
        }
    } else {
        println!("(toolchain not installed)");
    }
    Ok(())
}

<commit_msg>Tell cargo where rustc is when printing the version info<commit_after>//! Just a dumping ground for cli stuff

use multirust::{Cfg, Result, Notification, Toolchain, Error};
use multirust_utils::{self, utils};
use multirust_utils::notify::NotificationLevel;
use std::ffi::OsStr;
use std::io::{Write, Read, BufRead};
use std::process::{self, Command};
use std;
use tty;
use term;

pub fn confirm(question: &str, default: bool) -> Result<bool> {
    print!("{} ", question);
    let _ = std::io::stdout().flush();
    let input = try!(read_line());

    let r = match &*input {
        "y" | "Y" => true,
        "n" | "N" => false,
        "" => default,
        _ => false,
    };

    println!("");

    Ok(r)
}

fn read_line() -> Result<String> {
    let stdin = std::io::stdin();
    let stdin = stdin.lock();
    let mut lines = stdin.lines();
    lines.next().and_then(|l| l.ok()).ok_or(Error::ReadStdin)
}

pub fn wait_for_keypress() -> Result<()> {
    let stdin = std::io::stdin();
    if stdin.bytes().next().is_some() {
        Ok(())
    } else {
        Err(Error::ReadStdin)
    }
}

pub fn set_globals(verbose: bool) -> Result<Cfg> {
    use download_tracker::DownloadTracker;
    use std::cell::RefCell;

    let download_tracker = RefCell::new(DownloadTracker::new());

    Cfg::from_env(shared_ntfy!(move |n: Notification| {
        if download_tracker.borrow_mut().handle_notification(&n) {
            return;
        }

        match n.level() {
            NotificationLevel::Verbose => {
                if verbose {
                    verbose!("{}", n);
                }
            }
            NotificationLevel::Info => {
                info!("{}", n);
            }
            NotificationLevel::Warn => {
                warn!("{}", n);
            }
            NotificationLevel::Error => {
                err!("{}", n);
            }
        }
    }))

}

pub fn run_inner<S: AsRef<OsStr>>(mut command: Command,
                                  args: &[S]) -> Result<()> {
    command.args(&args[1..]);
    // FIXME rust-lang/rust#32254. It's not clear to me
    // when and why this is needed.
    command.stdin(process::Stdio::inherit());

    let status = command.status();

    match status {
        Ok(status) => {
            // Ensure correct exit code is returned
            let code = status.code().unwrap_or(1);
            process::exit(code);
        }
        Err(e) => {
            Err(multirust_utils::Error::RunningCommand {
                name: args[0].as_ref().to_owned(),
                error: multirust_utils::raw::CommandError::Io(e),
            }.into())
        }
    }
}

pub fn show_channel_version(cfg: &Cfg, name: &str) -> Result<()> {
    println!("");
    let mut t = term::stdout().unwrap();
    if tty::stdout_isatty() { let _ = t.fg(term::color::BRIGHT_WHITE); }
    if tty::stdout_isatty() { let _ = t.bg(term::color::BLACK); }
    let _ = write!(t, "{}", name);
    if tty::stdout_isatty() { let _ = t.reset(); }
    let _ = writeln!(t, " revision:");
    println!("");
    try!(show_tool_versions(&try!(cfg.get_toolchain(&name, false))));
    println!("");
    Ok(())
}

pub fn show_tool_versions(toolchain: &Toolchain) -> Result<()> {
    if toolchain.exists() {
        let rustc_path = toolchain.binary_file("rustc");
        let cargo_path = toolchain.binary_file("cargo");

        if utils::is_file(&rustc_path) {
            let mut cmd = Command::new(&rustc_path);
            cmd.arg("--version");
            toolchain.set_ldpath(&mut cmd);

            if utils::cmd_status("rustc", &mut cmd).is_err() {
                println!("(failed to run rustc)");
            }
        } else {
            println!("(no rustc command in toolchain?)");
        }
        if utils::is_file(&cargo_path) {
            let mut cmd = Command::new(&cargo_path);
            cmd.arg("--version");
            // cargo invokes rustc during --version, this
            // makes sure it can find it since it may not
            // be on the `PATH` and multirust does not
            // manipulate `PATH`.
            cmd.env("RUSTC", rustc_path);
            toolchain.set_ldpath(&mut cmd);

            if utils::cmd_status("cargo", &mut cmd).is_err() {
                println!("(failed to run cargo)");
            }
        } else {
            println!("(no cargo command in toolchain?)");
        }
    } else {
        println!("(toolchain not installed)");
    }
    Ok(())
}

<|endoftext|>


<commit_before>// run-pass

#![feature(untagged_unions)]

#![allow(dead_code)]

use std::mem::needs_drop;
use std::mem::ManuallyDrop;

struct NeedDrop;

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

// Constant expressios allow `NoDrop` to go out of scope,
// unlike a value of the interior type implementing `Drop`.
static X: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1;

// A union that scrubs the drop glue from its inner type
union NoDrop<T> { inner: ManuallyDrop<T> }

// Copy currently can't be implemented on drop-containing unions,
// this may change later
// https://github.com/rust-lang/rust/pull/38934#issuecomment-271219289

// // We should be able to implement Copy for NoDrop
// impl<T> Copy for NoDrop<T> {}
// impl<T> Clone for NoDrop<T> {fn clone(&self) -> Self { *self }}

// // We should be able to implement Copy for things using NoDrop
// #[derive(Copy, Clone)]
struct Foo {
    x: NoDrop<Box<u8>>
}

struct Baz {
    x: NoDrop<Box<u8>>,
    y: Box<u8>,
}

union ActuallyDrop<T> { inner: ManuallyDrop<T> }

impl<T> Drop for ActuallyDrop<T> {
    fn drop(&mut self) {}
}

fn main() {
    // NoDrop should not make needs_drop true
    assert!(!needs_drop::<Foo>());
    assert!(!needs_drop::<NoDrop<u8>>());
    assert!(!needs_drop::<NoDrop<Box<u8>>>());
    // presence of other drop types should still work
    assert!(needs_drop::<Baz>());
    // drop impl on union itself should work
    assert!(needs_drop::<ActuallyDrop<u8>>());
    assert!(needs_drop::<ActuallyDrop<Box<u8>>>());
}
<commit_msg>Update src/test/run-pass/union/union-nodrop.rs<commit_after>// run-pass

#![feature(untagged_unions)]

#![allow(dead_code)]

use std::mem::needs_drop;
use std::mem::ManuallyDrop;

struct NeedDrop;

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

// Constant expressions allow `NoDrop` to go out of scope,
// unlike a value of the interior type implementing `Drop`.
static X: () = (NoDrop { inner: ManuallyDrop::new(NeedDrop) }, ()).1;

// A union that scrubs the drop glue from its inner type
union NoDrop<T> { inner: ManuallyDrop<T> }

// Copy currently can't be implemented on drop-containing unions,
// this may change later
// https://github.com/rust-lang/rust/pull/38934#issuecomment-271219289

// // We should be able to implement Copy for NoDrop
// impl<T> Copy for NoDrop<T> {}
// impl<T> Clone for NoDrop<T> {fn clone(&self) -> Self { *self }}

// // We should be able to implement Copy for things using NoDrop
// #[derive(Copy, Clone)]
struct Foo {
    x: NoDrop<Box<u8>>
}

struct Baz {
    x: NoDrop<Box<u8>>,
    y: Box<u8>,
}

union ActuallyDrop<T> { inner: ManuallyDrop<T> }

impl<T> Drop for ActuallyDrop<T> {
    fn drop(&mut self) {}
}

fn main() {
    // NoDrop should not make needs_drop true
    assert!(!needs_drop::<Foo>());
    assert!(!needs_drop::<NoDrop<u8>>());
    assert!(!needs_drop::<NoDrop<Box<u8>>>());
    // presence of other drop types should still work
    assert!(needs_drop::<Baz>());
    // drop impl on union itself should work
    assert!(needs_drop::<ActuallyDrop<u8>>());
    assert!(needs_drop::<ActuallyDrop<Box<u8>>>());
}
<|endoftext|>


<commit_before>//! Developer note:
//!
//! This is a set of embed builders for rich embeds.
//!
//! These are used in the [`Context::send_message`] and
//! [`ExecuteWebhook::embeds`] methods, both as part of builders.
//!
//! The only builder that should be exposed is [`CreateEmbed`]. The rest of
//! these have no real reason for being exposed, but are for completeness' sake.
//!
//! Documentation for embeds can be found [here].
//!
//! [`Context::send_message`]: ../../client/struct.Context.html#method.send_message
//! [`CreateEmbed`]: struct.CreateEmbed.html
//! [`ExecuteWebhook::embeds`]: struct.ExecuteWebhook.html#method.embeds
//! [here]: https://discordapp.com/developers/docs/resources/channel#embed-object

use serde_json::builder::ObjectBuilder;
use serde_json::Value;
use std::collections::BTreeMap;
use std::default::Default;
use ::utils::Colour;

/// A builder to create a fake [`Embed`] object, for use with the
/// [`Context::send_message`] and [`ExecuteWebhook::embeds`] methods.
///
/// # Examples
///
/// Refer to the documentation for [`Context::send_message`] for a very in-depth
/// example on how to use this.
///
/// [`Context::send_message`]: ../../client/struct.Context.html#method.send_message
/// [`Embed`]: ../../model/struct.Embed.html
/// [`ExecuteWebhook::embeds`]: struct.ExecuteWebhook.html#method.embeds
pub struct CreateEmbed(pub BTreeMap<String, Value>);

impl CreateEmbed {
    /// Set the author of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedAuthor`] for more
    /// information.
    ///
    /// [`CreateEmbedAuthor`]: struct.CreateEmbedAuthor.html
    pub fn author<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedAuthor) -> CreateEmbedAuthor {
        let author = f(CreateEmbedAuthor::default()).0.build();

        self.0.insert("author".to_owned(), author);

        CreateEmbed(self.0)
    }

    /// Set the colour of the left-hand side of the embed.
    ///
    /// This is an alias of [`colour`].
    ///
    /// [`colour`]: #method.colour
    pub fn color<C: Into<Colour>>(self, colour: C) -> Self {
        self.colour(colour.into())
    }

    /// Set the colour of the left-hand side of the embed.
    pub fn colour<C: Into<Colour>>(mut self, colour: C) -> Self {
        self.0.insert("color".to_owned(), Value::U64(colour.into().value as u64));

        CreateEmbed(self.0)
    }

    /// Set the description of the embed.
    pub fn description(mut self, description: &str) -> Self {
        self.0.insert("description".to_owned(), Value::String(description.to_owned()));

        CreateEmbed(self.0)
    }

    /// Set a field. Note that this will not overwrite other fields, and will
    /// add to them.
    ///
    /// Refer to the documentation for [`CreateEmbedField`] for more
    /// information.
    ///
    /// [`CreateEmbedField`]: struct.CreateEmbedField.html
    pub fn field<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedField) -> CreateEmbedField {
        let field = f(CreateEmbedField::default()).0.build();

        {
            let key = "fields".to_owned();

            let entry = self.0.remove(&key).unwrap_or_else(|| Value::Array(vec![]));
            let mut arr = match entry {
                Value::Array(inner) => inner,
                _ => {
                    // The type of `entry` should always be a `Value::Array`.
                    //
                    // Theoretically this never happens, but you never know.
                    //
                    // In the event that it does, just return the current value.
                    return CreateEmbed(self.0);
                },
            };
            arr.push(field);

            self.0.insert("fields".to_owned(), Value::Array(arr));
        }

        CreateEmbed(self.0)
    }

    /// Set the footer of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedFooter`] for more
    /// information.
    ///
    /// [`CreateEmbedFooter`]: struct.CreateEmbedFooter.html
    pub fn footer<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedFooter) -> CreateEmbedFooter {
        let footer = f(CreateEmbedFooter::default()).0.build();

        self.0.insert("footer".to_owned(), footer);

        CreateEmbed(self.0)
    }

    /// Set the image associated with the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedImage`] for more
    /// information.
    ///
    /// [`CreateEmbedImage`]: struct.CreateEmbedImage.html
    pub fn image<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedImage) -> CreateEmbedImage {
        let image = f(CreateEmbedImage::default()).0.build();

        self.0.insert("image".to_owned(), image);

        CreateEmbed(self.0)
    }

    /// Set the thumbnail of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedThumbnail`] for more
    /// information.
    ///
    /// [`CreateEmbedThumbnail`]: struct.CreateEmbedThumbnail.html
    pub fn thumbnail<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedThumbnail) -> CreateEmbedThumbnail {
        let thumbnail = f(CreateEmbedThumbnail::default()).0.build();

        self.0.insert("thumbnail".to_owned(), thumbnail);

        CreateEmbed(self.0)
    }

    /// Set the timestamp.
    pub fn timestamp(mut self, timestamp: &str) -> Self {
        self.0.insert("timestamp".to_owned(), Value::String(timestamp.to_owned()));

        CreateEmbed(self.0)
    }

    /// Set the title of the embed.
    pub fn title(mut self, title: &str) -> Self {
        self.0.insert("title".to_owned(), Value::String(title.to_owned()));

        CreateEmbed(self.0)
    }

    /// Set the URL to direct to when clicking on the title.
    pub fn url(mut self, url: &str) -> Self {
        self.0.insert("url".to_owned(), Value::String(url.to_owned()));

        CreateEmbed(self.0)
    }
}

impl Default for CreateEmbed {
    /// Creates a builder with default values, setting the `type` to `rich`.
    fn default() -> CreateEmbed {
        let mut map = BTreeMap::new();
        map.insert("type".to_owned(), Value::String("rich".to_owned()));

        CreateEmbed(map)
    }
}

/// A builder to create a fake [`Embed`] object's author, for use with the
/// [`CreateEmbed::author`] method.
///
/// Requires that you specify a [`name`].
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::author`]: struct.CreateEmbed.html#method.author
/// [`name`]: #method.name
pub struct CreateEmbedAuthor(pub ObjectBuilder);

impl CreateEmbedAuthor {
    /// Set the URL of the author's icon.
    pub fn icon_url(self, icon_url: &str) -> Self {
        CreateEmbedAuthor(self.0.insert("icon_url", icon_url))
    }

    /// Set the author's name.
    pub fn name(self, name: &str) -> Self {
        CreateEmbedAuthor(self.0.insert("name", name))
    }

    /// Set the author's URL.
    pub fn url(self, url: &str) -> Self {
        CreateEmbedAuthor(self.0.insert("url", url))
    }
}

impl Default for CreateEmbedAuthor {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedAuthor {
        CreateEmbedAuthor(ObjectBuilder::new())
    }
}

/// A builder to create a fake [`Embed`] object's field, for use with the
/// [`CreateEmbed::field`] method.
///
/// This does not require any field be set. `inline` is set to `true` by
/// default.
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::field`]: struct.CreateEmbed.html#method.field
pub struct CreateEmbedField(pub ObjectBuilder);

impl CreateEmbedField {
    /// Set whether the field is inlined.
    pub fn inline(self, inline: bool) -> Self {
        CreateEmbedField(self.0.insert("inline", inline))
    }

    /// Set the field's name.
    pub fn name(self, name: &str) -> Self {
        CreateEmbedField(self.0.insert("name", name))
    }

    /// Set the field's value.
    pub fn value(self, value: &str) -> Self {
        CreateEmbedField(self.0.insert("value", value))
    }
}

impl Default for CreateEmbedField {
    /// Creates a builder with default values, setting the value of `inline` to
    /// `true`.
    fn default() -> CreateEmbedField {
        CreateEmbedField(ObjectBuilder::new())
    }
}

/// A builder to create a fake [`Embed`] object's footer, for use with the
/// [`CreateEmbed::footer`] method.
///
/// This does not require any field be set.
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::footer`]: struct.CreateEmbed.html#method.footer
pub struct CreateEmbedFooter(pub ObjectBuilder);

impl CreateEmbedFooter {
    /// Set the icon URL's value. This only supports HTTP(S).
    pub fn icon_url(self, icon_url: &str) -> Self {
        CreateEmbedFooter(self.0.insert("icon_url", icon_url))
    }

    /// Set the footer's text.
    pub fn text(self, text: &str) -> Self {
        CreateEmbedFooter(self.0.insert("text", text))
    }
}

impl Default for CreateEmbedFooter {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedFooter {
        CreateEmbedFooter(ObjectBuilder::new())
    }
}

/// A builder to create a fake [`Embed`] object's image, for use with the
/// [`CreateEmbed::image`] method.
///
/// This does not require any field be set.
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::image`]: struct.CreateEmbed.html#method.image
pub struct CreateEmbedImage(pub ObjectBuilder);

impl CreateEmbedImage {
    /// Set the display height of the image.
    pub fn height(self, height: u64) -> Self {
        CreateEmbedImage(self.0.insert("height", height))
    }

    /// Set the image's URL. This only supports HTTP(S).
    pub fn url(self, url: &str) -> Self {
        CreateEmbedImage(self.0.insert("url", url))
    }

    /// Set the display width of the image.
    pub fn width(self, width: u64) -> Self {
        CreateEmbedImage(self.0.insert("widht", width))
    }
}

impl Default for CreateEmbedImage {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedImage {
        CreateEmbedImage(ObjectBuilder::new())
    }
}

/// A builder to create a fake [`Embed`] object's thumbnail, for use with the
/// [`CreateEmbed::thumbnail`] method.
///
/// Requires that you specify a [`url`].
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::thumbnail`]: struct.CreateEmbed.html#method.thumbnail
/// [`url`]: #method.url
pub struct CreateEmbedThumbnail(pub ObjectBuilder);

impl CreateEmbedThumbnail {
    /// Set the height of the thumbnail, in pixels.
    pub fn height(self, height: u64) -> Self {
        CreateEmbedThumbnail(self.0.insert("height", height))
    }

    /// Set the URL of the thumbnail. This only supports HTTP(S).
    ///
    /// _Must_ be specified.
    pub fn url(self, url: &str) -> Self {
        CreateEmbedThumbnail(self.0.insert("url", url))
    }

    /// Set the width of the thumbnail, in pixels.
    pub fn width(self, width: u64) -> Self {
        CreateEmbedThumbnail(self.0.insert("width", width))
    }
}

impl Default for CreateEmbedThumbnail {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedThumbnail {
        CreateEmbedThumbnail(ObjectBuilder::new())
    }
}

/// A builder to create a fake [`Embed`] object's video, for use with the
/// [`CreateEmbed::video`] method.
///
/// Requires that you specify a [`url`].
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::video`]: struct.CreateEmbed.html#method.video
/// [`url`]: #method.url
pub struct CreateEmbedVideo(pub ObjectBuilder);

impl CreateEmbedVideo {
    /// Set the height of the video, in pixels.
    pub fn height(self, height: u64) -> Self {
        CreateEmbedVideo(self.0.insert("height", height))
    }

    /// Set the source URL of the video.
    ///
    /// _Must_ be specified.
    pub fn url(self, url: &str) -> Self {
        CreateEmbedVideo(self.0.insert("url", url))
    }

    /// Set the width of the video, in pixels.
    pub fn width(self, width: &str) -> Self {
        CreateEmbedVideo(self.0.insert("width", width))
    }
}

impl Default for CreateEmbedVideo {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedVideo {
        CreateEmbedVideo(ObjectBuilder::new())
    }
}
<commit_msg>Ensure embed fields are inline by default<commit_after>//! Developer note:
//!
//! This is a set of embed builders for rich embeds.
//!
//! These are used in the [`Context::send_message`] and
//! [`ExecuteWebhook::embeds`] methods, both as part of builders.
//!
//! The only builder that should be exposed is [`CreateEmbed`]. The rest of
//! these have no real reason for being exposed, but are for completeness' sake.
//!
//! Documentation for embeds can be found [here].
//!
//! [`Context::send_message`]: ../../client/struct.Context.html#method.send_message
//! [`CreateEmbed`]: struct.CreateEmbed.html
//! [`ExecuteWebhook::embeds`]: struct.ExecuteWebhook.html#method.embeds
//! [here]: https://discordapp.com/developers/docs/resources/channel#embed-object

use serde_json::builder::ObjectBuilder;
use serde_json::Value;
use std::collections::BTreeMap;
use std::default::Default;
use ::utils::Colour;

/// A builder to create a fake [`Embed`] object, for use with the
/// [`Context::send_message`] and [`ExecuteWebhook::embeds`] methods.
///
/// # Examples
///
/// Refer to the documentation for [`Context::send_message`] for a very in-depth
/// example on how to use this.
///
/// [`Context::send_message`]: ../../client/struct.Context.html#method.send_message
/// [`Embed`]: ../../model/struct.Embed.html
/// [`ExecuteWebhook::embeds`]: struct.ExecuteWebhook.html#method.embeds
pub struct CreateEmbed(pub BTreeMap<String, Value>);

impl CreateEmbed {
    /// Set the author of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedAuthor`] for more
    /// information.
    ///
    /// [`CreateEmbedAuthor`]: struct.CreateEmbedAuthor.html
    pub fn author<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedAuthor) -> CreateEmbedAuthor {
        let author = f(CreateEmbedAuthor::default()).0.build();

        self.0.insert("author".to_owned(), author);

        CreateEmbed(self.0)
    }

    /// Set the colour of the left-hand side of the embed.
    ///
    /// This is an alias of [`colour`].
    ///
    /// [`colour`]: #method.colour
    pub fn color<C: Into<Colour>>(self, colour: C) -> Self {
        self.colour(colour.into())
    }

    /// Set the colour of the left-hand side of the embed.
    pub fn colour<C: Into<Colour>>(mut self, colour: C) -> Self {
        self.0.insert("color".to_owned(), Value::U64(colour.into().value as u64));

        CreateEmbed(self.0)
    }

    /// Set the description of the embed.
    pub fn description(mut self, description: &str) -> Self {
        self.0.insert("description".to_owned(), Value::String(description.to_owned()));

        CreateEmbed(self.0)
    }

    /// Set a field. Note that this will not overwrite other fields, and will
    /// add to them.
    ///
    /// Refer to the documentation for [`CreateEmbedField`] for more
    /// information.
    ///
    /// [`CreateEmbedField`]: struct.CreateEmbedField.html
    pub fn field<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedField) -> CreateEmbedField {
        let field = f(CreateEmbedField::default()).0.build();

        {
            let key = "fields".to_owned();

            let entry = self.0.remove(&key).unwrap_or_else(|| Value::Array(vec![]));
            let mut arr = match entry {
                Value::Array(inner) => inner,
                _ => {
                    // The type of `entry` should always be a `Value::Array`.
                    //
                    // Theoretically this never happens, but you never know.
                    //
                    // In the event that it does, just return the current value.
                    return CreateEmbed(self.0);
                },
            };
            arr.push(field);

            self.0.insert("fields".to_owned(), Value::Array(arr));
        }

        CreateEmbed(self.0)
    }

    /// Set the footer of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedFooter`] for more
    /// information.
    ///
    /// [`CreateEmbedFooter`]: struct.CreateEmbedFooter.html
    pub fn footer<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedFooter) -> CreateEmbedFooter {
        let footer = f(CreateEmbedFooter::default()).0.build();

        self.0.insert("footer".to_owned(), footer);

        CreateEmbed(self.0)
    }

    /// Set the image associated with the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedImage`] for more
    /// information.
    ///
    /// [`CreateEmbedImage`]: struct.CreateEmbedImage.html
    pub fn image<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedImage) -> CreateEmbedImage {
        let image = f(CreateEmbedImage::default()).0.build();

        self.0.insert("image".to_owned(), image);

        CreateEmbed(self.0)
    }

    /// Set the thumbnail of the embed.
    ///
    /// Refer to the documentation for [`CreateEmbedThumbnail`] for more
    /// information.
    ///
    /// [`CreateEmbedThumbnail`]: struct.CreateEmbedThumbnail.html
    pub fn thumbnail<F>(mut self, f: F) -> Self
        where F: FnOnce(CreateEmbedThumbnail) -> CreateEmbedThumbnail {
        let thumbnail = f(CreateEmbedThumbnail::default()).0.build();

        self.0.insert("thumbnail".to_owned(), thumbnail);

        CreateEmbed(self.0)
    }

    /// Set the timestamp.
    pub fn timestamp(mut self, timestamp: &str) -> Self {
        self.0.insert("timestamp".to_owned(), Value::String(timestamp.to_owned()));

        CreateEmbed(self.0)
    }

    /// Set the title of the embed.
    pub fn title(mut self, title: &str) -> Self {
        self.0.insert("title".to_owned(), Value::String(title.to_owned()));

        CreateEmbed(self.0)
    }

    /// Set the URL to direct to when clicking on the title.
    pub fn url(mut self, url: &str) -> Self {
        self.0.insert("url".to_owned(), Value::String(url.to_owned()));

        CreateEmbed(self.0)
    }
}

impl Default for CreateEmbed {
    /// Creates a builder with default values, setting the `type` to `rich`.
    fn default() -> CreateEmbed {
        let mut map = BTreeMap::new();
        map.insert("type".to_owned(), Value::String("rich".to_owned()));

        CreateEmbed(map)
    }
}

/// A builder to create a fake [`Embed`] object's author, for use with the
/// [`CreateEmbed::author`] method.
///
/// Requires that you specify a [`name`].
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::author`]: struct.CreateEmbed.html#method.author
/// [`name`]: #method.name
pub struct CreateEmbedAuthor(pub ObjectBuilder);

impl CreateEmbedAuthor {
    /// Set the URL of the author's icon.
    pub fn icon_url(self, icon_url: &str) -> Self {
        CreateEmbedAuthor(self.0.insert("icon_url", icon_url))
    }

    /// Set the author's name.
    pub fn name(self, name: &str) -> Self {
        CreateEmbedAuthor(self.0.insert("name", name))
    }

    /// Set the author's URL.
    pub fn url(self, url: &str) -> Self {
        CreateEmbedAuthor(self.0.insert("url", url))
    }
}

impl Default for CreateEmbedAuthor {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedAuthor {
        CreateEmbedAuthor(ObjectBuilder::new())
    }
}

/// A builder to create a fake [`Embed`] object's field, for use with the
/// [`CreateEmbed::field`] method.
///
/// This does not require any field be set. `inline` is set to `true` by
/// default.
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::field`]: struct.CreateEmbed.html#method.field
pub struct CreateEmbedField(pub ObjectBuilder);

impl CreateEmbedField {
    /// Set whether the field is inlined.
    pub fn inline(self, inline: bool) -> Self {
        CreateEmbedField(self.0.insert("inline", inline))
    }

    /// Set the field's name.
    pub fn name(self, name: &str) -> Self {
        CreateEmbedField(self.0.insert("name", name))
    }

    /// Set the field's value.
    pub fn value(self, value: &str) -> Self {
        CreateEmbedField(self.0.insert("value", value))
    }
}

impl Default for CreateEmbedField {
    /// Creates a builder with default values, setting the value of `inline` to
    /// `true`.
    fn default() -> CreateEmbedField {
        CreateEmbedField(ObjectBuilder::new().insert("inline", true))
    }
}

/// A builder to create a fake [`Embed`] object's footer, for use with the
/// [`CreateEmbed::footer`] method.
///
/// This does not require any field be set.
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::footer`]: struct.CreateEmbed.html#method.footer
pub struct CreateEmbedFooter(pub ObjectBuilder);

impl CreateEmbedFooter {
    /// Set the icon URL's value. This only supports HTTP(S).
    pub fn icon_url(self, icon_url: &str) -> Self {
        CreateEmbedFooter(self.0.insert("icon_url", icon_url))
    }

    /// Set the footer's text.
    pub fn text(self, text: &str) -> Self {
        CreateEmbedFooter(self.0.insert("text", text))
    }
}

impl Default for CreateEmbedFooter {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedFooter {
        CreateEmbedFooter(ObjectBuilder::new())
    }
}

/// A builder to create a fake [`Embed`] object's image, for use with the
/// [`CreateEmbed::image`] method.
///
/// This does not require any field be set.
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::image`]: struct.CreateEmbed.html#method.image
pub struct CreateEmbedImage(pub ObjectBuilder);

impl CreateEmbedImage {
    /// Set the display height of the image.
    pub fn height(self, height: u64) -> Self {
        CreateEmbedImage(self.0.insert("height", height))
    }

    /// Set the image's URL. This only supports HTTP(S).
    pub fn url(self, url: &str) -> Self {
        CreateEmbedImage(self.0.insert("url", url))
    }

    /// Set the display width of the image.
    pub fn width(self, width: u64) -> Self {
        CreateEmbedImage(self.0.insert("widht", width))
    }
}

impl Default for CreateEmbedImage {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedImage {
        CreateEmbedImage(ObjectBuilder::new())
    }
}

/// A builder to create a fake [`Embed`] object's thumbnail, for use with the
/// [`CreateEmbed::thumbnail`] method.
///
/// Requires that you specify a [`url`].
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::thumbnail`]: struct.CreateEmbed.html#method.thumbnail
/// [`url`]: #method.url
pub struct CreateEmbedThumbnail(pub ObjectBuilder);

impl CreateEmbedThumbnail {
    /// Set the height of the thumbnail, in pixels.
    pub fn height(self, height: u64) -> Self {
        CreateEmbedThumbnail(self.0.insert("height", height))
    }

    /// Set the URL of the thumbnail. This only supports HTTP(S).
    ///
    /// _Must_ be specified.
    pub fn url(self, url: &str) -> Self {
        CreateEmbedThumbnail(self.0.insert("url", url))
    }

    /// Set the width of the thumbnail, in pixels.
    pub fn width(self, width: u64) -> Self {
        CreateEmbedThumbnail(self.0.insert("width", width))
    }
}

impl Default for CreateEmbedThumbnail {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedThumbnail {
        CreateEmbedThumbnail(ObjectBuilder::new())
    }
}

/// A builder to create a fake [`Embed`] object's video, for use with the
/// [`CreateEmbed::video`] method.
///
/// Requires that you specify a [`url`].
///
/// [`Embed`]: ../../model/struct.Embed.html
/// [`CreateEmbed::video`]: struct.CreateEmbed.html#method.video
/// [`url`]: #method.url
pub struct CreateEmbedVideo(pub ObjectBuilder);

impl CreateEmbedVideo {
    /// Set the height of the video, in pixels.
    pub fn height(self, height: u64) -> Self {
        CreateEmbedVideo(self.0.insert("height", height))
    }

    /// Set the source URL of the video.
    ///
    /// _Must_ be specified.
    pub fn url(self, url: &str) -> Self {
        CreateEmbedVideo(self.0.insert("url", url))
    }

    /// Set the width of the video, in pixels.
    pub fn width(self, width: &str) -> Self {
        CreateEmbedVideo(self.0.insert("width", width))
    }
}

impl Default for CreateEmbedVideo {
    /// Creates a builder with no default values.
    fn default() -> CreateEmbedVideo {
        CreateEmbedVideo(ObjectBuilder::new())
    }
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar, rustc_private)]

extern crate serde_codegen;
extern crate rustc;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut rustc::plugin::Registry) {
    serde_codegen::register(reg);
}
<commit_msg>fix(rustup): Update serde_codegen to reflect Registry move<commit_after>#![feature(plugin_registrar, rustc_private)]

extern crate serde_codegen;
extern crate rustc_plugin;

#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut rustc_plugin::Registry) {
    serde_codegen::register(reg);
}
<|endoftext|>


<commit_before>#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Token {
    /// A serialized `bool`.
    Bool(bool),

    /// A serialized `i8`.
    I8(i8),

    /// A serialized `i16`.
    I16(i16),

    /// A serialized `i32`.
    I32(i32),

    /// A serialized `i64`.
    I64(i64),

    /// A serialized `u8`.
    U8(u8),

    /// A serialized `u16`.
    U16(u16),

    /// A serialized `u32`.
    U32(u32),

    /// A serialized `u64`.
    U64(u64),

    /// A serialized `f32`.
    F32(f32),

    /// A serialized `f64`.
    F64(f64),

    /// A serialized `char`.
    Char(char),

    /// A serialized `str`.
    Str(&'static str),

    /// A borrowed `str`.
    BorrowedStr(&'static str),

    /// A serialized `String`.
    String(&'static str),

    /// A serialized `[u8]`
    Bytes(&'static [u8]),

    /// A borrowed `[u8]`.
    BorrowedBytes(&'static [u8]),

    /// A serialized `ByteBuf`
    ByteBuf(&'static [u8]),

    /// The header to a serialized `Option<T>`.
    ///
    /// `None` is serialized as `Option(false)`, while `Some` is serialized as `Option(true)`, then
    /// the value contained in the option.
    Option(bool),

    /// A serialized `()`.
    Unit,

    /// A serialized unit struct of the given name.
    UnitStruct(&'static str),

    /// The header to a serialized newtype struct of the given name.
    ///
    /// Newtype structs are serialized with this header, followed by the value contained in the
    /// newtype struct.
    StructNewType(&'static str),

    /// The header to an enum of the given name.
    ///
    /// This token is only used for deserializers, and ensures that the following tokens are read as
    /// an enum. Because this is never emitted by serializers, calling `assert_ser_tokens` or
    /// `assert_tokens` will fail if this token is used.
    ///
    /// TODO: Trash this.
    EnumStart(&'static str),

    /// A unit variant of an enum of the given name, of the given name.
    ///
    /// The first string represents the name of the enum, and the second represents the name of the
    /// variant.
    EnumUnit(&'static str, &'static str),

    /// The header to a newtype variant of an enum of the given name, of the given name.
    ///
    /// The first string represents the name of the enum, and the second represents the name of the
    /// variant. The value contained within this enum works the same as `StructNewType`.
    EnumNewType(&'static str, &'static str),

    /// The header to a sequence of the given length.
    ///
    /// These are serialized via `serialize_seq`, which takes an optional length. After this
    /// header is a list of elements, followed by `SeqEnd`.
    SeqStart(Option<usize>),

    /// The header to an array of the given length.
    ///
    /// These are serialized via `serialize_seq_fized_size`, which requires a length. After this
    /// header is a list of elements, followed by `SeqEnd`.
    SeqArrayStart(usize),

    /// An indicator of the end of a sequence.
    SeqEnd,

    /// The header to a tuple of the given length, similar to `SeqArrayStart`.
    TupleStart(usize),

    /// An indicator of the end of a tuple, similar to `SeqEnd`.
    TupleEnd,

    /// The header to a tuple struct of the given name and length.
    TupleStructStart(&'static str, usize),

    /// An indicator of the end of a tuple struct, similar to `TupleEnd`.
    TupleStructEnd,

    /// The header to a map of the given length.
    ///
    /// These are serialized via `serialize_map`, which takes an optional length. After this header
    /// is a list of key-value pairs, followed by `MapEnd`.
    MapStart(Option<usize>),

    /// An indicator of the end of a map.
    MapEnd,

    /// The header of a struct of the given name and length, similar to `MapStart`.
    StructStart(&'static str, usize),

    /// An indicator of the end of a struct, similar to `MapEnd`.
    StructEnd,

    /// The header to a tuple variant of an enum of the given name, of the given name and length.
    EnumSeqStart(&'static str, &'static str, usize),

    /// An indicator of the end of a tuple variant, similar to `TupleEnd`.
    EnumSeqEnd,

    /// The header of a struct variant of an enum of the given name, of the given name and length,
    /// similar to `StructStart`.
    EnumMapStart(&'static str, &'static str, usize),

    /// An indicator of the end of a struct, similar to `StructEnd`.
    EnumMapEnd,
}
<commit_msg>Modernize serde_test Token names<commit_after>#[derive(Copy, Clone, PartialEq, Debug)]
pub enum Token {
    /// A serialized `bool`.
    Bool(bool),

    /// A serialized `i8`.
    I8(i8),

    /// A serialized `i16`.
    I16(i16),

    /// A serialized `i32`.
    I32(i32),

    /// A serialized `i64`.
    I64(i64),

    /// A serialized `u8`.
    U8(u8),

    /// A serialized `u16`.
    U16(u16),

    /// A serialized `u32`.
    U32(u32),

    /// A serialized `u64`.
    U64(u64),

    /// A serialized `f32`.
    F32(f32),

    /// A serialized `f64`.
    F64(f64),

    /// A serialized `char`.
    Char(char),

    /// A serialized `str`.
    Str(&'static str),

    /// A borrowed `str`.
    BorrowedStr(&'static str),

    /// A serialized `String`.
    String(&'static str),

    /// A serialized `[u8]`
    Bytes(&'static [u8]),

    /// A borrowed `[u8]`.
    BorrowedBytes(&'static [u8]),

    /// A serialized `ByteBuf`
    ByteBuf(&'static [u8]),

    /// The header to a serialized `Option<T>` containing some value.
    ///
    /// The tokens of the value follow after this header.
    Some,

    /// A serialized `Option<T>` containing none.
    None,

    /// A serialized `()`.
    Unit,

    /// A serialized unit struct of the given name.
    UnitStruct(&'static str),

    /// The header to a serialized newtype struct of the given name.
    ///
    /// Newtype structs are serialized with this header, followed by the value contained in the
    /// newtype struct.
    NewtypeStruct(&'static str),

    /// The header to an enum of the given name.
    Enum(&'static str),

    /// A unit variant of an enum of the given name, of the given name.
    ///
    /// The first string represents the name of the enum, and the second represents the name of the
    /// variant.
    UnitVariant(&'static str, &'static str),

    /// The header to a newtype variant of an enum of the given name, of the given name.
    ///
    /// The first string represents the name of the enum, and the second represents the name of the
    /// variant. The value contained within this enum works the same as `StructNewType`.
    NewtypeVariant(&'static str, &'static str),

    /// The header to a sequence of the given length.
    ///
    /// These are serialized via `serialize_seq`, which takes an optional length. After this
    /// header is a list of elements, followed by `SeqEnd`.
    Seq(Option<usize>),

    /// The header to an array of the given length.
    ///
    /// These are serialized via `serialize_seq_fized_size`, which requires a length. After this
    /// header is a list of elements, followed by `SeqEnd`.
    SeqFixedSize(usize),

    /// An indicator of the end of a sequence.
    SeqEnd,

    /// The header to a tuple of the given length, similar to `SeqFixedSize`.
    Tuple(usize),

    /// An indicator of the end of a tuple, similar to `SeqEnd`.
    TupleEnd,

    /// The header to a tuple struct of the given name and length.
    TupleStruct(&'static str, usize),

    /// An indicator of the end of a tuple struct, similar to `TupleEnd`.
    TupleStructEnd,

    /// The header to a map of the given length.
    ///
    /// These are serialized via `serialize_map`, which takes an optional length. After this header
    /// is a list of key-value pairs, followed by `MapEnd`.
    Map(Option<usize>),

    /// An indicator of the end of a map.
    MapEnd,

    /// The header of a struct of the given name and length, similar to `Map`.
    Struct(&'static str, usize),

    /// An indicator of the end of a struct, similar to `MapEnd`.
    StructEnd,

    /// The header to a tuple variant of an enum of the given name, of the given name and length.
    TupleVariant(&'static str, &'static str, usize),

    /// An indicator of the end of a tuple variant, similar to `TupleEnd`.
    TupleVariantEnd,

    /// The header of a struct variant of an enum of the given name, of the given name and length,
    /// similar to `Struct`.
    StructVariant(&'static str, &'static str, usize),

    /// An indicator of the end of a struct, similar to `StructEnd`.
    StructVariantEnd,
}
<|endoftext|>


<commit_before>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::collections::btree_map::Entry;
use std::collections::BTreeMap;
use std::fs::File;

use libvda::encode::{EncodeCapabilities, VeaImplType, VeaInstance};

use base::{error, warn, AsRawDescriptor, IntoRawDescriptor};

use super::*;
use crate::virtio::video::format::{
    Bitrate, Format, FormatDesc, FormatRange, FrameFormat, FramePlane, Level, Profile,
};
use crate::virtio::video::{
    encoder::{encoder::*, EncoderDevice},
    error::{VideoError, VideoResult},
    Tube,
};

impl From<Bitrate> for libvda::encode::Bitrate {
    fn from(bitrate: Bitrate) -> Self {
        libvda::encode::Bitrate {
            mode: match bitrate {
                Bitrate::VBR { .. } => libvda::encode::BitrateMode::VBR,
                Bitrate::CBR { .. } => libvda::encode::BitrateMode::CBR,
            },
            target: bitrate.target(),
            peak: match &bitrate {
                // No need to specify peak if mode is CBR.
                Bitrate::CBR { .. } => 0,
                Bitrate::VBR { peak, .. } => *peak,
            },
        }
    }
}

pub struct LibvdaEncoder {
    instance: VeaInstance,
    capabilities: EncoderCapabilities,
}

impl LibvdaEncoder {
    fn new() -> VideoResult<Self> {
        let instance = VeaInstance::new(VeaImplType::Gavea)?;

        let EncodeCapabilities {
            input_formats,
            output_formats,
        } = instance.get_capabilities();

        if input_formats.len() == 0 || output_formats.len() == 0 {
            error!("No input or output formats.");
            return Err(VideoError::InvalidFormat);
        }

        let input_format_descs: Vec<FormatDesc> = input_formats
            .iter()
            .map(|input_format| {
                let format = match input_format {
                    libvda::PixelFormat::NV12 => Format::NV12,
                    libvda::PixelFormat::YV12 => Format::YUV420,
                };

                // VEA's GetSupportedProfiles does not return resolution information.
                // The input formats are retrieved by querying minigbm.
                // TODO(alexlau): Populate this with real information.

                FormatDesc {
                    mask: !(u64::MAX << output_formats.len()),
                    format,
                    frame_formats: vec![FrameFormat {
                        width: FormatRange {
                            min: 2,
                            max: 4096,
                            step: 1,
                        },
                        height: FormatRange {
                            min: 2,
                            max: 4096,
                            step: 1,
                        },
                        bitrates: vec![FormatRange {
                            min: 0,
                            max: 8000,
                            step: 1,
                        }],
                    }],
                }
            })
            .collect();

        if input_format_descs
            .iter()
            .find(|fd| fd.format == Format::NV12)
            .is_none()
        {
            // NV12 is currently the only supported pixel format for libvda.
            error!("libvda encoder does not support NV12.");
            return Err(VideoError::InvalidFormat);
        }

        struct ParsedFormat {
            profiles: Vec<Profile>,
            max_width: u32,
            max_height: u32,
        }
        let mut parsed_formats: BTreeMap<Format, ParsedFormat> = BTreeMap::new();

        for output_format in output_formats.iter() {
            // TODO(alexlau): Consider using `max_framerate_numerator` and `max_framerate_denominator`.
            let libvda::encode::OutputProfile {
                profile: libvda_profile,
                max_width,
                max_height,
                ..
            } = output_format;

            let profile = match Profile::from_libvda_profile(*libvda_profile) {
                Some(p) => p,
                None => {
                    warn!("Skipping unsupported libvda profile: {:?}", libvda_profile);
                    continue;
                }
            };

            match parsed_formats.entry(profile.to_format()) {
                Entry::Occupied(mut occupied_entry) => {
                    let parsed_format = occupied_entry.get_mut();
                    parsed_format.profiles.push(profile);
                    // If we get different libvda profiles of the same VIRTIO_VIDEO_FORMAT
                    // (Format) that have different max resolutions or bitrates, take the
                    // minimum between all of the different profiles.
                    parsed_format.max_width = std::cmp::min(*max_width, parsed_format.max_width);
                    parsed_format.max_height = std::cmp::min(*max_height, parsed_format.max_height);
                }
                Entry::Vacant(vacant_entry) => {
                    vacant_entry.insert(ParsedFormat {
                        profiles: vec![profile],
                        max_width: *max_width,
                        max_height: *max_height,
                    });
                }
            }
        }

        let mut output_format_descs = vec![];
        let mut coded_format_profiles = BTreeMap::new();
        for (format, parsed_format) in parsed_formats.into_iter() {
            let ParsedFormat {
                mut profiles,
                max_width,
                max_height,
            } = parsed_format;

            output_format_descs.push(FormatDesc {
                mask: !(u64::MAX << output_formats.len()),
                format,
                frame_formats: vec![FrameFormat {
                    width: FormatRange {
                        min: 2,
                        max: max_width,
                        step: 1,
                    },
                    height: FormatRange {
                        min: 2,
                        max: max_height,
                        step: 1,
                    },
                    bitrates: vec![FormatRange {
                        min: 0,
                        max: 8000,
                        step: 1,
                    }],
                }],
            });

            profiles.sort_unstable();
            coded_format_profiles.insert(format, profiles);
        }

        Ok(LibvdaEncoder {
            instance,
            capabilities: EncoderCapabilities {
                input_format_descs,
                output_format_descs,
                coded_format_profiles,
            },
        })
    }
}

impl Encoder for LibvdaEncoder {
    type Session = LibvdaEncoderSession;

    fn query_capabilities(&self) -> VideoResult<EncoderCapabilities> {
        Ok(self.capabilities.clone())
    }

    fn start_session(&mut self, config: SessionConfig) -> VideoResult<LibvdaEncoderSession> {
        if config.dst_params.format.is_none() {
            return Err(VideoError::InvalidArgument);
        }

        let input_format = match config
            .src_params
            .format
            .ok_or(VideoError::InvalidArgument)?
        {
            Format::NV12 => libvda::PixelFormat::NV12,
            Format::YUV420 => libvda::PixelFormat::YV12,
            unsupported_format => {
                error!("Unsupported libvda format: {}", unsupported_format);
                return Err(VideoError::InvalidArgument);
            }
        };

        let output_profile = match config.dst_profile.to_libvda_profile() {
            Some(p) => p,
            None => {
                error!("Unsupported libvda profile");
                return Err(VideoError::InvalidArgument);
            }
        };

        let config = libvda::encode::Config {
            input_format,
            input_visible_width: config.src_params.frame_width,
            input_visible_height: config.src_params.frame_height,
            output_profile,
            bitrate: config.dst_bitrate.into(),
            initial_framerate: if config.frame_rate == 0 {
                None
            } else {
                Some(config.frame_rate)
            },
            h264_output_level: config.dst_h264_level.map(|level| {
                // This value is aligned to the H264 standard definition of SPS.level_idc.
                match level {
                    Level::H264_1_0 => 10,
                    Level::H264_1_1 => 11,
                    Level::H264_1_2 => 12,
                    Level::H264_1_3 => 13,
                    Level::H264_2_0 => 20,
                    Level::H264_2_1 => 21,
                    Level::H264_2_2 => 22,
                    Level::H264_3_0 => 30,
                    Level::H264_3_1 => 31,
                    Level::H264_3_2 => 32,
                    Level::H264_4_0 => 40,
                    Level::H264_4_1 => 41,
                    Level::H264_4_2 => 42,
                    Level::H264_5_0 => 50,
                    Level::H264_5_1 => 51,
                }
            }),
        };

        let session = self.instance.open_session(config)?;

        Ok(LibvdaEncoderSession {
            session,
            next_input_buffer_id: 1,
            next_output_buffer_id: 1,
        })
    }

    fn stop_session(&mut self, _session: LibvdaEncoderSession) -> VideoResult<()> {
        // Resources will be freed when `_session` is dropped.
        Ok(())
    }
}

pub struct LibvdaEncoderSession {
    session: libvda::encode::Session,
    next_input_buffer_id: InputBufferId,
    next_output_buffer_id: OutputBufferId,
}

impl EncoderSession for LibvdaEncoderSession {
    fn encode(
        &mut self,
        resource: File,
        planes: &[FramePlane],
        timestamp: u64,
        force_keyframe: bool,
    ) -> VideoResult<InputBufferId> {
        let input_buffer_id = self.next_input_buffer_id;

        let libvda_planes = planes
            .iter()
            .map(|plane| libvda::FramePlane {
                offset: plane.offset as i32,
                stride: plane.stride as i32,
            })
            .collect::<Vec<_>>();

        self.session.encode(
            input_buffer_id as i32,
            resource.into_raw_descriptor(),
            &libvda_planes,
            timestamp as i64,
            force_keyframe,
        )?;

        self.next_input_buffer_id = self.next_input_buffer_id.wrapping_add(1);

        Ok(input_buffer_id)
    }

    fn use_output_buffer(
        &mut self,
        file: File,
        offset: u32,
        size: u32,
    ) -> VideoResult<OutputBufferId> {
        let output_buffer_id = self.next_output_buffer_id;

        self.session.use_output_buffer(
            output_buffer_id as i32,
            file.into_raw_descriptor(),
            offset,
            size,
        )?;

        self.next_output_buffer_id = self.next_output_buffer_id.wrapping_add(1);

        Ok(output_buffer_id)
    }

    fn flush(&mut self) -> VideoResult<()> {
        self.session.flush().map_err(VideoError::from)
    }

    fn request_encoding_params_change(
        &mut self,
        bitrate: Bitrate,
        framerate: u32,
    ) -> VideoResult<()> {
        self.session
            .request_encoding_params_change(bitrate.into(), framerate)
            .map_err(VideoError::from)
    }

    fn event_pipe(&self) -> &dyn AsRawDescriptor {
        self.session.pipe()
    }

    fn read_event(&mut self) -> VideoResult<EncoderEvent> {
        let event = self.session.read_event()?;

        use libvda::encode::Event::*;
        let encoder_event = match event {
            RequireInputBuffers {
                input_count,
                input_frame_width,
                input_frame_height,
                output_buffer_size,
            } => EncoderEvent::RequireInputBuffers {
                input_count,
                input_frame_width,
                input_frame_height,
                output_buffer_size,
            },
            ProcessedInputBuffer(id) => EncoderEvent::ProcessedInputBuffer { id: id as u32 },
            ProcessedOutputBuffer {
                output_buffer_id,
                payload_size,
                key_frame,
                timestamp,
                ..
            } => EncoderEvent::ProcessedOutputBuffer {
                id: output_buffer_id as u32,
                bytesused: payload_size,
                keyframe: key_frame,
                timestamp: timestamp as u64,
            },
            FlushResponse { flush_done } => EncoderEvent::FlushResponse { flush_done },
            NotifyError(err) => EncoderEvent::NotifyError {
                error: VideoError::BackendFailure(Box::new(err)),
            },
        };

        Ok(encoder_event)
    }
}

/// Create a new encoder instance using a Libvda encoder instance to perform
/// the encoding.
impl EncoderDevice<LibvdaEncoder> {
    pub fn new(resource_bridge: Tube) -> VideoResult<Self> {
        let vea = LibvdaEncoder::new()?;
        EncoderDevice::from_backend(vea, resource_bridge)
    }
}
<commit_msg>virtio: video: use iter .any() to check presence<commit_after>// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::collections::btree_map::Entry;
use std::collections::BTreeMap;
use std::fs::File;

use libvda::encode::{EncodeCapabilities, VeaImplType, VeaInstance};

use base::{error, warn, AsRawDescriptor, IntoRawDescriptor};

use super::*;
use crate::virtio::video::format::{
    Bitrate, Format, FormatDesc, FormatRange, FrameFormat, FramePlane, Level, Profile,
};
use crate::virtio::video::{
    encoder::{encoder::*, EncoderDevice},
    error::{VideoError, VideoResult},
    Tube,
};

impl From<Bitrate> for libvda::encode::Bitrate {
    fn from(bitrate: Bitrate) -> Self {
        libvda::encode::Bitrate {
            mode: match bitrate {
                Bitrate::VBR { .. } => libvda::encode::BitrateMode::VBR,
                Bitrate::CBR { .. } => libvda::encode::BitrateMode::CBR,
            },
            target: bitrate.target(),
            peak: match &bitrate {
                // No need to specify peak if mode is CBR.
                Bitrate::CBR { .. } => 0,
                Bitrate::VBR { peak, .. } => *peak,
            },
        }
    }
}

pub struct LibvdaEncoder {
    instance: VeaInstance,
    capabilities: EncoderCapabilities,
}

impl LibvdaEncoder {
    fn new() -> VideoResult<Self> {
        let instance = VeaInstance::new(VeaImplType::Gavea)?;

        let EncodeCapabilities {
            input_formats,
            output_formats,
        } = instance.get_capabilities();

        if input_formats.len() == 0 || output_formats.len() == 0 {
            error!("No input or output formats.");
            return Err(VideoError::InvalidFormat);
        }

        let input_format_descs: Vec<FormatDesc> = input_formats
            .iter()
            .map(|input_format| {
                let format = match input_format {
                    libvda::PixelFormat::NV12 => Format::NV12,
                    libvda::PixelFormat::YV12 => Format::YUV420,
                };

                // VEA's GetSupportedProfiles does not return resolution information.
                // The input formats are retrieved by querying minigbm.
                // TODO(alexlau): Populate this with real information.

                FormatDesc {
                    mask: !(u64::MAX << output_formats.len()),
                    format,
                    frame_formats: vec![FrameFormat {
                        width: FormatRange {
                            min: 2,
                            max: 4096,
                            step: 1,
                        },
                        height: FormatRange {
                            min: 2,
                            max: 4096,
                            step: 1,
                        },
                        bitrates: vec![FormatRange {
                            min: 0,
                            max: 8000,
                            step: 1,
                        }],
                    }],
                }
            })
            .collect();

        if !input_format_descs
            .iter()
            .any(|fd| fd.format == Format::NV12)
        {
            // NV12 is currently the only supported pixel format for libvda.
            error!("libvda encoder does not support NV12.");
            return Err(VideoError::InvalidFormat);
        }

        struct ParsedFormat {
            profiles: Vec<Profile>,
            max_width: u32,
            max_height: u32,
        }
        let mut parsed_formats: BTreeMap<Format, ParsedFormat> = BTreeMap::new();

        for output_format in output_formats.iter() {
            // TODO(alexlau): Consider using `max_framerate_numerator` and `max_framerate_denominator`.
            let libvda::encode::OutputProfile {
                profile: libvda_profile,
                max_width,
                max_height,
                ..
            } = output_format;

            let profile = match Profile::from_libvda_profile(*libvda_profile) {
                Some(p) => p,
                None => {
                    warn!("Skipping unsupported libvda profile: {:?}", libvda_profile);
                    continue;
                }
            };

            match parsed_formats.entry(profile.to_format()) {
                Entry::Occupied(mut occupied_entry) => {
                    let parsed_format = occupied_entry.get_mut();
                    parsed_format.profiles.push(profile);
                    // If we get different libvda profiles of the same VIRTIO_VIDEO_FORMAT
                    // (Format) that have different max resolutions or bitrates, take the
                    // minimum between all of the different profiles.
                    parsed_format.max_width = std::cmp::min(*max_width, parsed_format.max_width);
                    parsed_format.max_height = std::cmp::min(*max_height, parsed_format.max_height);
                }
                Entry::Vacant(vacant_entry) => {
                    vacant_entry.insert(ParsedFormat {
                        profiles: vec![profile],
                        max_width: *max_width,
                        max_height: *max_height,
                    });
                }
            }
        }

        let mut output_format_descs = vec![];
        let mut coded_format_profiles = BTreeMap::new();
        for (format, parsed_format) in parsed_formats.into_iter() {
            let ParsedFormat {
                mut profiles,
                max_width,
                max_height,
            } = parsed_format;

            output_format_descs.push(FormatDesc {
                mask: !(u64::MAX << output_formats.len()),
                format,
                frame_formats: vec![FrameFormat {
                    width: FormatRange {
                        min: 2,
                        max: max_width,
                        step: 1,
                    },
                    height: FormatRange {
                        min: 2,
                        max: max_height,
                        step: 1,
                    },
                    bitrates: vec![FormatRange {
                        min: 0,
                        max: 8000,
                        step: 1,
                    }],
                }],
            });

            profiles.sort_unstable();
            coded_format_profiles.insert(format, profiles);
        }

        Ok(LibvdaEncoder {
            instance,
            capabilities: EncoderCapabilities {
                input_format_descs,
                output_format_descs,
                coded_format_profiles,
            },
        })
    }
}

impl Encoder for LibvdaEncoder {
    type Session = LibvdaEncoderSession;

    fn query_capabilities(&self) -> VideoResult<EncoderCapabilities> {
        Ok(self.capabilities.clone())
    }

    fn start_session(&mut self, config: SessionConfig) -> VideoResult<LibvdaEncoderSession> {
        if config.dst_params.format.is_none() {
            return Err(VideoError::InvalidArgument);
        }

        let input_format = match config
            .src_params
            .format
            .ok_or(VideoError::InvalidArgument)?
        {
            Format::NV12 => libvda::PixelFormat::NV12,
            Format::YUV420 => libvda::PixelFormat::YV12,
            unsupported_format => {
                error!("Unsupported libvda format: {}", unsupported_format);
                return Err(VideoError::InvalidArgument);
            }
        };

        let output_profile = match config.dst_profile.to_libvda_profile() {
            Some(p) => p,
            None => {
                error!("Unsupported libvda profile");
                return Err(VideoError::InvalidArgument);
            }
        };

        let config = libvda::encode::Config {
            input_format,
            input_visible_width: config.src_params.frame_width,
            input_visible_height: config.src_params.frame_height,
            output_profile,
            bitrate: config.dst_bitrate.into(),
            initial_framerate: if config.frame_rate == 0 {
                None
            } else {
                Some(config.frame_rate)
            },
            h264_output_level: config.dst_h264_level.map(|level| {
                // This value is aligned to the H264 standard definition of SPS.level_idc.
                match level {
                    Level::H264_1_0 => 10,
                    Level::H264_1_1 => 11,
                    Level::H264_1_2 => 12,
                    Level::H264_1_3 => 13,
                    Level::H264_2_0 => 20,
                    Level::H264_2_1 => 21,
                    Level::H264_2_2 => 22,
                    Level::H264_3_0 => 30,
                    Level::H264_3_1 => 31,
                    Level::H264_3_2 => 32,
                    Level::H264_4_0 => 40,
                    Level::H264_4_1 => 41,
                    Level::H264_4_2 => 42,
                    Level::H264_5_0 => 50,
                    Level::H264_5_1 => 51,
                }
            }),
        };

        let session = self.instance.open_session(config)?;

        Ok(LibvdaEncoderSession {
            session,
            next_input_buffer_id: 1,
            next_output_buffer_id: 1,
        })
    }

    fn stop_session(&mut self, _session: LibvdaEncoderSession) -> VideoResult<()> {
        // Resources will be freed when `_session` is dropped.
        Ok(())
    }
}

pub struct LibvdaEncoderSession {
    session: libvda::encode::Session,
    next_input_buffer_id: InputBufferId,
    next_output_buffer_id: OutputBufferId,
}

impl EncoderSession for LibvdaEncoderSession {
    fn encode(
        &mut self,
        resource: File,
        planes: &[FramePlane],
        timestamp: u64,
        force_keyframe: bool,
    ) -> VideoResult<InputBufferId> {
        let input_buffer_id = self.next_input_buffer_id;

        let libvda_planes = planes
            .iter()
            .map(|plane| libvda::FramePlane {
                offset: plane.offset as i32,
                stride: plane.stride as i32,
            })
            .collect::<Vec<_>>();

        self.session.encode(
            input_buffer_id as i32,
            resource.into_raw_descriptor(),
            &libvda_planes,
            timestamp as i64,
            force_keyframe,
        )?;

        self.next_input_buffer_id = self.next_input_buffer_id.wrapping_add(1);

        Ok(input_buffer_id)
    }

    fn use_output_buffer(
        &mut self,
        file: File,
        offset: u32,
        size: u32,
    ) -> VideoResult<OutputBufferId> {
        let output_buffer_id = self.next_output_buffer_id;

        self.session.use_output_buffer(
            output_buffer_id as i32,
            file.into_raw_descriptor(),
            offset,
            size,
        )?;

        self.next_output_buffer_id = self.next_output_buffer_id.wrapping_add(1);

        Ok(output_buffer_id)
    }

    fn flush(&mut self) -> VideoResult<()> {
        self.session.flush().map_err(VideoError::from)
    }

    fn request_encoding_params_change(
        &mut self,
        bitrate: Bitrate,
        framerate: u32,
    ) -> VideoResult<()> {
        self.session
            .request_encoding_params_change(bitrate.into(), framerate)
            .map_err(VideoError::from)
    }

    fn event_pipe(&self) -> &dyn AsRawDescriptor {
        self.session.pipe()
    }

    fn read_event(&mut self) -> VideoResult<EncoderEvent> {
        let event = self.session.read_event()?;

        use libvda::encode::Event::*;
        let encoder_event = match event {
            RequireInputBuffers {
                input_count,
                input_frame_width,
                input_frame_height,
                output_buffer_size,
            } => EncoderEvent::RequireInputBuffers {
                input_count,
                input_frame_width,
                input_frame_height,
                output_buffer_size,
            },
            ProcessedInputBuffer(id) => EncoderEvent::ProcessedInputBuffer { id: id as u32 },
            ProcessedOutputBuffer {
                output_buffer_id,
                payload_size,
                key_frame,
                timestamp,
                ..
            } => EncoderEvent::ProcessedOutputBuffer {
                id: output_buffer_id as u32,
                bytesused: payload_size,
                keyframe: key_frame,
                timestamp: timestamp as u64,
            },
            FlushResponse { flush_done } => EncoderEvent::FlushResponse { flush_done },
            NotifyError(err) => EncoderEvent::NotifyError {
                error: VideoError::BackendFailure(Box::new(err)),
            },
        };

        Ok(encoder_event)
    }
}

/// Create a new encoder instance using a Libvda encoder instance to perform
/// the encoding.
impl EncoderDevice<LibvdaEncoder> {
    pub fn new(resource_bridge: Tube) -> VideoResult<Self> {
        let vea = LibvdaEncoder::new()?;
        EncoderDevice::from_backend(vea, resource_bridge)
    }
}
<|endoftext|>


<commit_before>extern crate rustc_serialize;
extern crate clap;
extern crate shadowsocks;
extern crate qrcode;

use std::str;

use rustc_serialize::base64::{FromBase64, ToBase64, URL_SAFE};
use rustc_serialize::json::{ToJson, as_pretty_json};

use clap::{App, Arg};

use qrcode::QrCode;

use shadowsocks::config::{Config, ConfigType, ServerConfig};

const BLACK: &'static str = "\x1b[40m  \x1b[0m";
const WHITE: &'static str = "\x1b[47m  \x1b[0m";

fn encode_url(svr: &ServerConfig) -> String {
    let url = format!("{}:{}@{}:{}", svr.method.to_string(), svr.password, svr.addr, svr.port);
    format!("ss://{}", url.as_bytes().to_base64(URL_SAFE))
}

fn print_qrcode(encoded: &str) {
    let qrcode = QrCode::new(encoded.as_bytes()).unwrap();

    for _ in 0..qrcode.width()+2 {
        print!("{}", WHITE);
    }
    println!("");

    for y in 0..qrcode.width() {
        print!("{}", WHITE);
        for x in 0..qrcode.width() {
            let color = if qrcode[(x, y)] {
                BLACK
            } else {
                WHITE
            };

            print!("{}", color);
        }
        println!("{}", WHITE);
    }

    for _ in 0..qrcode.width()+2 {
        print!("{}", WHITE);
    }
    println!("");
}

fn encode(filename: &str, need_qrcode: bool) {
    let config = Config::load_from_file(filename, ConfigType::Server).unwrap();

    for svr in config.server {
        let encoded = encode_url(&svr);

        println!("{}", encoded);

        if need_qrcode {
            print_qrcode(&encoded);
        }
    }
}

fn decode(encoded: &str, need_qrcode: bool) {
    if !encoded.starts_with("ss://") {
        panic!("Malformed input: {:?}", encoded);
    }

    let decoded = encoded[5..].from_base64().unwrap();
    let decoded = str::from_utf8(&decoded).unwrap();

    let mut sp1 = decoded.split('@');
    let (account, addr) = match (sp1.next(), sp1.next()) {
        (Some(account), Some(addr)) => {
            (account, addr)
        },
        _ => panic!("Malformed input"),
    };

    let mut sp2 = account.split(':');
    let (method, pwd) = match (sp2.next(), sp2.next()) {
        (Some(m), Some(p)) => (m, p),
        _ => panic!("Malformed input"),
    };

    let mut sp3 = addr.split(':');
    let (addr, port) = match (sp3.next(), sp3.next()) {
        (Some(a), Some(p)) => (a, p),
        _ => panic!("Malformed input"),
    };

    let svrconfig = ServerConfig::basic(addr.to_owned(), port.parse().unwrap(),
                                        pwd.to_owned(), method.parse().unwrap());

    let svrconfig_json = svrconfig.to_json();
    println!("{}", as_pretty_json(&svrconfig_json));

    if need_qrcode {
        print_qrcode(encoded);
    }
}

fn main() {
    let app = App::new("ssurl")
                    .author("Y. T. Chung <zonyitoo@gmail.com>")
                    .about("Encode and decode ShadowSocks URL")
                    .arg(Arg::with_name("ENCODE").short("e").long("encode")
                            .takes_value(true)
                            .help("Encode the server configuration in the provided JSON file"))
                    .arg(Arg::with_name("DECODE").short("d").long("decode")
                            .takes_value(true)
                            .help("Decode the server configuration from the provide ShadowSocks URL"))
                    .arg(Arg::with_name("QRCODE").short("c").long("qrcode")
                            .takes_value(false)
                            .help("Generate the QRCode with the provided configuration"));
    let matches = app.get_matches();

    let need_qrcode = matches.is_present("QRCODE");

    if let Some(file) = matches.value_of("ENCODE") {
        encode(file, need_qrcode);
    } else if let Some(encoded) = matches.value_of("DECODE") {
        decode(encoded, need_qrcode);
    } else {
        println!("Use -h for more detail");
    }
}
<commit_msg>use standard base64 encode<commit_after>extern crate rustc_serialize;
extern crate clap;
extern crate shadowsocks;
extern crate qrcode;

use std::str;

use rustc_serialize::base64::{FromBase64, ToBase64, STANDARD};
use rustc_serialize::json::{ToJson, as_pretty_json};

use clap::{App, Arg};

use qrcode::QrCode;

use shadowsocks::config::{Config, ConfigType, ServerConfig};

const BLACK: &'static str = "\x1b[40m  \x1b[0m";
const WHITE: &'static str = "\x1b[47m  \x1b[0m";

fn encode_url(svr: &ServerConfig) -> String {
    let url = format!("{}:{}@{}:{}", svr.method.to_string(), svr.password, svr.addr, svr.port);
    format!("ss://{}", url.as_bytes().to_base64(STANDARD))
}

fn print_qrcode(encoded: &str) {
    let qrcode = QrCode::new(encoded.as_bytes()).unwrap();

    for _ in 0..qrcode.width()+2 {
        print!("{}", WHITE);
    }
    println!("");

    for y in 0..qrcode.width() {
        print!("{}", WHITE);
        for x in 0..qrcode.width() {
            let color = if qrcode[(x, y)] {
                BLACK
            } else {
                WHITE
            };

            print!("{}", color);
        }
        println!("{}", WHITE);
    }

    for _ in 0..qrcode.width()+2 {
        print!("{}", WHITE);
    }
    println!("");
}

fn encode(filename: &str, need_qrcode: bool) {
    let config = Config::load_from_file(filename, ConfigType::Server).unwrap();

    for svr in config.server {
        let encoded = encode_url(&svr);

        println!("{}", encoded);

        if need_qrcode {
            print_qrcode(&encoded);
        }
    }
}

fn decode(encoded: &str, need_qrcode: bool) {
    if !encoded.starts_with("ss://") {
        panic!("Malformed input: {:?}", encoded);
    }

    let decoded = encoded[5..].from_base64().unwrap();
    let decoded = str::from_utf8(&decoded).unwrap();

    let mut sp1 = decoded.split('@');
    let (account, addr) = match (sp1.next(), sp1.next()) {
        (Some(account), Some(addr)) => {
            (account, addr)
        },
        _ => panic!("Malformed input"),
    };

    let mut sp2 = account.split(':');
    let (method, pwd) = match (sp2.next(), sp2.next()) {
        (Some(m), Some(p)) => (m, p),
        _ => panic!("Malformed input"),
    };

    let mut sp3 = addr.split(':');
    let (addr, port) = match (sp3.next(), sp3.next()) {
        (Some(a), Some(p)) => (a, p),
        _ => panic!("Malformed input"),
    };

    let svrconfig = ServerConfig::basic(addr.to_owned(), port.parse().unwrap(),
                                        pwd.to_owned(), method.parse().unwrap());

    let svrconfig_json = svrconfig.to_json();
    println!("{}", as_pretty_json(&svrconfig_json));

    if need_qrcode {
        print_qrcode(encoded);
    }
}

fn main() {
    let app = App::new("ssurl")
                    .author("Y. T. Chung <zonyitoo@gmail.com>")
                    .about("Encode and decode ShadowSocks URL")
                    .arg(Arg::with_name("ENCODE").short("e").long("encode")
                            .takes_value(true)
                            .help("Encode the server configuration in the provided JSON file"))
                    .arg(Arg::with_name("DECODE").short("d").long("decode")
                            .takes_value(true)
                            .help("Decode the server configuration from the provide ShadowSocks URL"))
                    .arg(Arg::with_name("QRCODE").short("c").long("qrcode")
                            .takes_value(false)
                            .help("Generate the QRCode with the provided configuration"));
    let matches = app.get_matches();

    let need_qrcode = matches.is_present("QRCODE");

    if let Some(file) = matches.value_of("ENCODE") {
        encode(file, need_qrcode);
    } else if let Some(encoded) = matches.value_of("DECODE") {
        decode(encoded, need_qrcode);
    } else {
        println!("Use -h for more detail");
    }
}
<|endoftext|>


<commit_before>#![allow(deprecated)] // keysyms

//! Callback methods for rustwlc
use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::*;
use rustwlc::input::{pointer, keyboard};

use rustc_serialize::json::Json;
use std::sync::Arc;
use std::thread;

use registry::{self, RegistryGetData};
use super::keys::{self, KeyPress, KeyEvent};
use super::layout::{Action, try_lock_tree, try_lock_action, ContainerType, MovementError, TreeError};
use super::layout::commands::set_performing_action;
use super::lua::{self, LuaQuery};
use super::background;

/// If the event is handled by way-cooler
const EVENT_HANDLED: bool = true;

/// If the event should be passed through to clients
const EVENT_PASS_THROUGH: bool = false;

// wlc callbacks

pub extern fn output_created(output: WlcOutput) -> bool {
    trace!("output_created: {:?}: {}", output, output.get_name());
    if let Ok(mut tree) = try_lock_tree() {
        tree.add_output(output).and_then(|_|{
            tree.switch_to_workspace(&"1")
        }).is_ok()
    } else {
        false
    }
}

pub extern fn output_destroyed(output: WlcOutput) {
    trace!("output_destroyed: {:?}", output);
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    trace!("output_focus: {:?} focus={}", output, focused);
}

pub extern fn output_resolution(output: WlcOutput,
                            old_size_ptr: &Size, new_size_ptr: &Size) {
    trace!("output_resolution: {:?} from  {:?} to {:?}",
           output, *old_size_ptr, *new_size_ptr);
    // Update the resolution of the output and its children
    output.set_resolution(*new_size_ptr, 1);
    if let Ok(mut tree) = try_lock_tree() {
        tree.layout_active_of(ContainerType::Output)
            .expect("Could not layout active output");
    }
}

pub extern fn view_created(view: WlcView) -> bool {
    trace!("view_created: {:?}: \"{}\"", view, view.get_title());
    if let Ok(mut tree) = try_lock_tree() {
        tree.add_view(view.clone()).and_then(|_| {
            tree.set_active_view(view)
        }).is_ok()
    } else {
        false
    }
}

pub extern fn view_destroyed(view: WlcView) {
    trace!("view_destroyed: {:?}", view);
    if let Ok(mut tree) = try_lock_tree() {
        tree.remove_view(view.clone()).and_then(|_| {
            tree.layout_active_of(ContainerType::Workspace)
        }).unwrap_or_else(|err| {
            match err {
                TreeError::ViewNotFound(_) => {},
                _ => {
                    error!("Error in view_destroyed: {:?}", err);
                }
            }
        });
    } else {
        error!("Could not delete view {:?}", view);
    }
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    trace!("view_focus: {:?} {}", current, focused);
    current.set_state(VIEW_ACTIVATED, focused);
    // set the focus view in the tree
    // If tree is already grabbed,
    // it should have the active container all set
    if let Ok(mut tree) = try_lock_tree() {
        if tree.set_active_view(current.clone()).is_err() {
            error!("Could not layout {:?}", current);
        }
    }
}

pub extern fn view_move_to_output(current: WlcView,
                                  o1: WlcOutput, o2: WlcOutput) {
    trace!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
}

pub extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    view.set_state(state, handled);
}

pub extern fn view_request_move(view: WlcView, _dest: &Point) {
    if let Ok(mut tree) = try_lock_tree() {
        if let Err(err) = tree.set_active_view(view) {
            error!("view_request_move error: {:?}", err);
        }
    }
}

pub extern fn view_request_resize(_view: WlcView, _edge: ResizeEdge, _location: &Point) {

}

#[allow(non_snake_case)] // EMPTY_MODS will be a static once we have KEY_LED_NONE
pub extern fn keyboard_key(_view: WlcView, _time: u32, mods: &KeyboardModifiers,
                           key: u32, state: KeyState) -> bool {
    let EMPTY_MODS: KeyboardModifiers = KeyboardModifiers {
            mods: MOD_NONE,
            leds: KeyboardLed::empty()
    };
    let sym = keyboard::get_keysym_for_key(key, EMPTY_MODS);
    let press = KeyPress::new(mods.mods, sym);

    if state == KeyState::Pressed {
        if let Some(action) = keys::get(&press) {
            debug!("[key] Found an action for {}", press);
            match action {
                KeyEvent::Command(func) => {
                    func();
                },
                KeyEvent::Lua => {
                    match lua::send(LuaQuery::HandleKey(press)) {
                        Ok(_) => {},
                        Err(err) => {
                            // We may want to wait for Lua's reply from
                            // keypresses; for example if the table is tampered
                            // with or Lua is restarted or Lua has an error.
                            // ATM Lua asynchronously logs this but in the future
                            // an error popup/etc is a good idea.
                            error!("Error sending keypress: {:?}", err);
                        }
                    }
                }
            }
            return EVENT_HANDLED
        }
    }

    return EVENT_PASS_THROUGH
}

pub extern fn view_request_geometry(_view: WlcView, _geometry: &Geometry) {
}

pub extern fn pointer_button(view: WlcView, _time: u32,
                         mods: &KeyboardModifiers, _button: u32,
                             state: ButtonState, point: &Point) -> bool {
    if state == ButtonState::Pressed && !view.is_root() {
        if let Ok(mut tree) = try_lock_tree() {
            tree.set_active_view(view)
                .unwrap_or_else(|err| {
                    error!("Could not set active container {:?}", err);
                });
            if mods.mods.contains(MOD_CTRL) {
                let action = Action {
                    view: view,
                    grab: *point,
                    edges: ResizeEdge::empty()
                };
                if let Err(err) = set_performing_action(Some(action)) {
                    warn!("{:#?}", err);
                }
            }
        }
    } else {
        if let Err(err) = set_performing_action(None) {
            warn!("{:#?}", err);
        }
    }
    false
}

pub extern fn pointer_scroll(_view: WlcView, _time: u32,
                         _mods_ptr: &KeyboardModifiers, _axis: ScrollAxis,
                         _heights: [f64; 2]) -> bool {
    false
}

pub extern fn pointer_motion(_view: WlcView, _time: u32, point: &Point) -> bool {
    pointer::set_position(*point);
    if let Ok(action) = try_lock_action() {
        match *action {
            None => return false,
            _ => {}
        }
    } else {
        warn!("Could not lock action");
        return false;
    }
    if let Ok(mut tree) = try_lock_tree() {
        match tree.try_drag_active(*point) {
            Ok(_) => return true,
            Err(TreeError::PerformingAction(_)) => {},
            Err(TreeError::Movement(MovementError::NotFloating(_))) => {},
            Err(err) => error!("Error: {:#?}", err)
        }
    }
    false
}

pub extern fn compositor_ready() {
    info!("Preparing compositor!");
    info!("Initializing Lua...");
    lua::init();
    info!("Loading background...");
    let maybe_color: Result<Arc<Json>, ()> = registry::get_data("background")
        .map(RegistryGetData::resolve).and_then(|(_, data)| {
            Ok(data)
        }).map_err(|_| ());
    if let Ok(color) = maybe_color {
        match *color {
            Json::F64(hex_color) => {
                for output in WlcOutput::list() {
                    let color = background::Color::from_u32(hex_color as u32);
                    // different thread for each output.
                    thread::spawn(move || {background::generate_solid_background(color, output.clone());});
                }
            }
            _ => {
                error!("Non-solid color backgrounds not yet supported, {:?}", color);
            }
        }
    } else {
        warn!("Couldn't read background value");
    }
}

pub extern fn compositor_terminating() {
    info!("Compositor terminating!");
    lua::send(lua::LuaQuery::Terminate).ok();
    if let Ok(mut tree) = try_lock_tree() {
        if tree.destroy_tree().is_err() {
            error!("Could not destroy tree");
        }
    }

}

pub fn init() {
    use rustwlc::callback;

    callback::output_created(output_created);
    callback::output_destroyed(output_destroyed);
    callback::output_focus(output_focus);
    callback::output_resolution(output_resolution);
    callback::view_created(view_created);
    callback::view_destroyed(view_destroyed);
    callback::view_focus(view_focus);
    callback::view_move_to_output(view_move_to_output);
    callback::view_request_geometry(view_request_geometry);
    callback::view_request_state(view_request_state);
    callback::view_request_move(view_request_move);
    callback::view_request_resize(view_request_resize);
    callback::keyboard_key(keyboard_key);
    callback::pointer_button(pointer_button);
    callback::pointer_scroll(pointer_scroll);
    callback::pointer_motion(pointer_motion);
    callback::compositor_ready(compositor_ready);
    callback::compositor_terminate(compositor_terminating);
    trace!("Registered wlc callbacks");
}
<commit_msg>Background Hotfix. Should help issues in #115<commit_after>#![allow(deprecated)] // keysyms

//! Callback methods for rustwlc
use rustwlc::handle::{WlcOutput, WlcView};
use rustwlc::types::*;
use rustwlc::input::{pointer, keyboard};

use rustc_serialize::json::Json;
use std::sync::Arc;
use std::thread;

use registry::{self, RegistryGetData};
use super::keys::{self, KeyPress, KeyEvent};
use super::layout::{Action, try_lock_tree, try_lock_action, ContainerType, MovementError, TreeError};
use super::layout::commands::set_performing_action;
use super::lua::{self, LuaQuery};
use super::background;

/// If the event is handled by way-cooler
const EVENT_HANDLED: bool = true;

/// If the event should be passed through to clients
const EVENT_PASS_THROUGH: bool = false;

// wlc callbacks

pub extern fn output_created(output: WlcOutput) -> bool {
    trace!("output_created: {:?}: {}", output, output.get_name());
    if let Ok(mut tree) = try_lock_tree() {
        tree.add_output(output).and_then(|_|{
            tree.switch_to_workspace(&"1")
        }).is_ok()
    } else {
        false
    }
}

pub extern fn output_destroyed(output: WlcOutput) {
    trace!("output_destroyed: {:?}", output);
}

pub extern fn output_focus(output: WlcOutput, focused: bool) {
    trace!("output_focus: {:?} focus={}", output, focused);
}

pub extern fn output_resolution(output: WlcOutput,
                            old_size_ptr: &Size, new_size_ptr: &Size) {
    trace!("output_resolution: {:?} from  {:?} to {:?}",
           output, *old_size_ptr, *new_size_ptr);
    // Update the resolution of the output and its children
    output.set_resolution(*new_size_ptr, 1);
    if let Ok(mut tree) = try_lock_tree() {
        tree.layout_active_of(ContainerType::Output)
            .expect("Could not layout active output");
    }
}

pub extern fn view_created(view: WlcView) -> bool {
    trace!("view_created: {:?}: \"{}\"", view, view.get_title());
    if let Ok(mut tree) = try_lock_tree() {
        tree.add_view(view.clone()).and_then(|_| {
            if view.get_class() == "Background" {
                return Ok(())
            }
            tree.set_active_view(view)
        }).is_ok()
    } else {
        false
    }
}

pub extern fn view_destroyed(view: WlcView) {
    trace!("view_destroyed: {:?}", view);
    if let Ok(mut tree) = try_lock_tree() {
        tree.remove_view(view.clone()).and_then(|_| {
            tree.layout_active_of(ContainerType::Workspace)
        }).unwrap_or_else(|err| {
            match err {
                TreeError::ViewNotFound(_) => {},
                _ => {
                    error!("Error in view_destroyed: {:?}", err);
                }
            }
        });
    } else {
        error!("Could not delete view {:?}", view);
    }
}

pub extern fn view_focus(current: WlcView, focused: bool) {
    trace!("view_focus: {:?} {}", current, focused);
    current.set_state(VIEW_ACTIVATED, focused);
    // set the focus view in the tree
    // If tree is already grabbed,
    // it should have the active container all set
    if let Ok(mut tree) = try_lock_tree() {
        if tree.set_active_view(current.clone()).is_err() {
            error!("Could not layout {:?}", current);
        }
    }
}

pub extern fn view_move_to_output(current: WlcView,
                                  o1: WlcOutput, o2: WlcOutput) {
    trace!("view_move_to_output: {:?}, {:?}, {:?}", current, o1, o2);
}

pub extern fn view_request_state(view: WlcView, state: ViewState, handled: bool) {
    view.set_state(state, handled);
}

pub extern fn view_request_move(view: WlcView, _dest: &Point) {
    if let Ok(mut tree) = try_lock_tree() {
        if let Err(err) = tree.set_active_view(view) {
            error!("view_request_move error: {:?}", err);
        }
    }
}

pub extern fn view_request_resize(_view: WlcView, _edge: ResizeEdge, _location: &Point) {

}

#[allow(non_snake_case)] // EMPTY_MODS will be a static once we have KEY_LED_NONE
pub extern fn keyboard_key(_view: WlcView, _time: u32, mods: &KeyboardModifiers,
                           key: u32, state: KeyState) -> bool {
    let EMPTY_MODS: KeyboardModifiers = KeyboardModifiers {
            mods: MOD_NONE,
            leds: KeyboardLed::empty()
    };
    let sym = keyboard::get_keysym_for_key(key, EMPTY_MODS);
    let press = KeyPress::new(mods.mods, sym);

    if state == KeyState::Pressed {
        if let Some(action) = keys::get(&press) {
            debug!("[key] Found an action for {}", press);
            match action {
                KeyEvent::Command(func) => {
                    func();
                },
                KeyEvent::Lua => {
                    match lua::send(LuaQuery::HandleKey(press)) {
                        Ok(_) => {},
                        Err(err) => {
                            // We may want to wait for Lua's reply from
                            // keypresses; for example if the table is tampered
                            // with or Lua is restarted or Lua has an error.
                            // ATM Lua asynchronously logs this but in the future
                            // an error popup/etc is a good idea.
                            error!("Error sending keypress: {:?}", err);
                        }
                    }
                }
            }
            return EVENT_HANDLED
        }
    }

    return EVENT_PASS_THROUGH
}

pub extern fn view_request_geometry(_view: WlcView, _geometry: &Geometry) {
}

pub extern fn pointer_button(view: WlcView, _time: u32,
                         mods: &KeyboardModifiers, _button: u32,
                             state: ButtonState, point: &Point) -> bool {
    if state == ButtonState::Pressed && !view.is_root() {
        if let Ok(mut tree) = try_lock_tree() {
            tree.set_active_view(view)
                .unwrap_or_else(|err| {
                    error!("Could not set active container {:?}", err);
                });
            if mods.mods.contains(MOD_CTRL) {
                let action = Action {
                    view: view,
                    grab: *point,
                    edges: ResizeEdge::empty()
                };
                if let Err(err) = set_performing_action(Some(action)) {
                    warn!("{:#?}", err);
                }
            }
        }
    } else {
        if let Err(err) = set_performing_action(None) {
            warn!("{:#?}", err);
        }
    }
    false
}

pub extern fn pointer_scroll(_view: WlcView, _time: u32,
                         _mods_ptr: &KeyboardModifiers, _axis: ScrollAxis,
                         _heights: [f64; 2]) -> bool {
    false
}

pub extern fn pointer_motion(_view: WlcView, _time: u32, point: &Point) -> bool {
    pointer::set_position(*point);
    if let Ok(action) = try_lock_action() {
        match *action {
            None => return false,
            _ => {}
        }
    } else {
        warn!("Could not lock action");
        return false;
    }
    if let Ok(mut tree) = try_lock_tree() {
        match tree.try_drag_active(*point) {
            Ok(_) => return true,
            Err(TreeError::PerformingAction(_)) => {},
            Err(TreeError::Movement(MovementError::NotFloating(_))) => {},
            Err(err) => error!("Error: {:#?}", err)
        }
    }
    false
}

pub extern fn compositor_ready() {
    info!("Preparing compositor!");
    info!("Initializing Lua...");
    lua::init();
    info!("Loading background...");
    let maybe_color: Result<Arc<Json>, ()> = registry::get_data("background")
        .map(RegistryGetData::resolve).and_then(|(_, data)| {
            Ok(data)
        }).map_err(|_| ());
    if let Ok(color) = maybe_color {
        match *color {
            Json::F64(hex_color) => {
                for output in WlcOutput::list() {
                    let color = background::Color::from_u32(hex_color as u32);
                    // different thread for each output.
                    thread::spawn(move || {background::generate_solid_background(color, output.clone());});
                }
            }
            _ => {
                error!("Non-solid color backgrounds not yet supported, {:?}", color);
            }
        }
    } else {
        warn!("Couldn't read background value");
    }
}

pub extern fn compositor_terminating() {
    info!("Compositor terminating!");
    lua::send(lua::LuaQuery::Terminate).ok();
    if let Ok(mut tree) = try_lock_tree() {
        if tree.destroy_tree().is_err() {
            error!("Could not destroy tree");
        }
    }

}

pub fn init() {
    use rustwlc::callback;

    callback::output_created(output_created);
    callback::output_destroyed(output_destroyed);
    callback::output_focus(output_focus);
    callback::output_resolution(output_resolution);
    callback::view_created(view_created);
    callback::view_destroyed(view_destroyed);
    callback::view_focus(view_focus);
    callback::view_move_to_output(view_move_to_output);
    callback::view_request_geometry(view_request_geometry);
    callback::view_request_state(view_request_state);
    callback::view_request_move(view_request_move);
    callback::view_request_resize(view_request_resize);
    callback::keyboard_key(keyboard_key);
    callback::pointer_button(pointer_button);
    callback::pointer_scroll(pointer_scroll);
    callback::pointer_motion(pointer_motion);
    callback::compositor_ready(compositor_ready);
    callback::compositor_terminate(compositor_terminating);
    trace!("Registered wlc callbacks");
}
<|endoftext|>