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

//! Animated types for CSS values related to effects.

use properties::animated_properties::Animatable;
use properties::longhands::box_shadow::computed_value::T as ComputedBoxShadowList;
use properties::longhands::filter::computed_value::T as ComputedFilterList;
use properties::longhands::text_shadow::computed_value::T as ComputedTextShadowList;
use std::cmp;
#[cfg(not(feature = "gecko"))]
use values::Impossible;
use values::animated::{ToAnimatedValue, ToAnimatedZero};
use values::animated::color::Color;
use values::computed::{Angle, NonNegativeNumber};
use values::computed::length::{Length, NonNegativeLength};
use values::distance::{ComputeSquaredDistance, SquaredDistance};
use values::generics::effects::BoxShadow as GenericBoxShadow;
use values::generics::effects::Filter as GenericFilter;
use values::generics::effects::SimpleShadow as GenericSimpleShadow;

/// An animated value for the `box-shadow` property.
pub type BoxShadowList = ShadowList<BoxShadow>;

/// An animated value for the `text-shadow` property.
pub type TextShadowList = ShadowList<SimpleShadow>;

/// An animated value for shadow lists.
///
/// https://drafts.csswg.org/css-transitions/#animtype-shadow-list
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq)]
pub struct ShadowList<Shadow>(Vec<Shadow>);

/// An animated value for a single `box-shadow`.
pub type BoxShadow = GenericBoxShadow<Color, Length, NonNegativeLength, Length>;

/// An animated value for the `filter` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq)]
pub struct FilterList(pub Vec<Filter>);

/// An animated value for a single `filter`.
#[cfg(feature = "gecko")]
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow>;

/// An animated value for a single `filter`.
#[cfg(not(feature = "gecko"))]
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible>;

/// An animated value for the `drop-shadow()` filter.
pub type SimpleShadow = GenericSimpleShadow<Color, Length, NonNegativeLength>;

impl ToAnimatedValue for ComputedBoxShadowList {
    type AnimatedValue = BoxShadowList;

    #[inline]
    fn to_animated_value(self) -> Self::AnimatedValue {
        ShadowList(self.0.to_animated_value())
    }

    #[inline]
    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
        ComputedBoxShadowList(ToAnimatedValue::from_animated_value(animated.0))
    }
}

impl<S> Animatable for ShadowList<S>
where
    S: Animatable + Clone + ToAnimatedZero,
{
    #[inline]
    fn add_weighted(
        &self,
        other: &Self,
        self_portion: f64,
        other_portion: f64,
    ) -> Result<Self, ()> {
        let max_len = cmp::max(self.0.len(), other.0.len());
        let mut shadows = Vec::with_capacity(max_len);
        for i in 0..max_len {
            shadows.push(match (self.0.get(i), other.0.get(i)) {
                (Some(shadow), Some(other)) => {
                    shadow.add_weighted(other, self_portion, other_portion)?
                },
                (Some(shadow), None) => {
                    shadow.add_weighted(&shadow.to_animated_zero()?, self_portion, other_portion)?
                },
                (None, Some(shadow)) => {
                    shadow.to_animated_zero()?.add_weighted(&shadow, self_portion, other_portion)?
                },
                (None, None) => unreachable!(),
            });
        }
        Ok(ShadowList(shadows))
    }

    #[inline]
    fn add(&self, other: &Self) -> Result<Self, ()> {
        Ok(ShadowList(
            self.0.iter().cloned().chain(other.0.iter().cloned()).collect(),
        ))
    }
}

impl<S> ComputeSquaredDistance for ShadowList<S> {
    #[inline]
    fn compute_squared_distance(&self, _other: &Self) -> Result<SquaredDistance, ()> {
        // FIXME: This should be implemented.
        Err(())
    }
}

impl<S> ToAnimatedZero for ShadowList<S> {
    #[inline]
    fn to_animated_zero(&self) -> Result<Self, ()> {
        Ok(ShadowList(vec![]))
    }
}

impl ToAnimatedValue for ComputedTextShadowList {
    type AnimatedValue = TextShadowList;

    #[inline]
    fn to_animated_value(self) -> Self::AnimatedValue {
        ShadowList(self.0.to_animated_value())
    }

    #[inline]
    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
        ComputedTextShadowList(ToAnimatedValue::from_animated_value(animated.0))
    }
}

impl Animatable for BoxShadow {
    #[inline]
    fn add_weighted(
        &self,
        other: &Self,
        self_portion: f64,
        other_portion: f64,
    ) -> Result<Self, ()> {
        if self.inset != other.inset {
            return Err(());
        }
        Ok(BoxShadow {
            base: self.base.add_weighted(&other.base, self_portion, other_portion)?,
            spread: self.spread.add_weighted(&other.spread, self_portion, other_portion)?,
            inset: self.inset,
        })
    }
}

impl ComputeSquaredDistance for BoxShadow {
    #[inline]
    fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
        if self.inset != other.inset {
            return Err(());
        }
        Ok(
            self.base.compute_squared_distance(&other.base)? +
            self.spread.compute_squared_distance(&other.spread)?,
        )
    }
}

impl ToAnimatedZero for BoxShadow {
    #[inline]
    fn to_animated_zero(&self) -> Result<Self, ()> {
        Ok(BoxShadow {
            base: self.base.to_animated_zero()?,
            spread: self.spread.to_animated_zero()?,
            inset: self.inset,
        })
    }
}

impl ToAnimatedValue for ComputedFilterList {
    type AnimatedValue = FilterList;

    #[cfg(not(feature = "gecko"))]
    #[inline]
    fn to_animated_value(self) -> Self::AnimatedValue {
        FilterList(self.0)
    }

    #[cfg(feature = "gecko")]
    #[inline]
    fn to_animated_value(self) -> Self::AnimatedValue {
        FilterList(self.0.to_animated_value())
    }

    #[cfg(not(feature = "gecko"))]
    #[inline]
    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
        ComputedFilterList(animated.0)
    }

    #[cfg(feature = "gecko")]
    #[inline]
    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
        ComputedFilterList(ToAnimatedValue::from_animated_value(animated.0))
    }
}

impl ToAnimatedZero for FilterList {
    #[inline]
    fn to_animated_zero(&self) -> Result<Self, ()> {
        Ok(FilterList(vec![]))
    }
}

impl Animatable for SimpleShadow {
    #[inline]
    fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
        let color = self.color.add_weighted(&other.color, self_portion, other_portion)?;
        let horizontal = self.horizontal.add_weighted(&other.horizontal, self_portion, other_portion)?;
        let vertical = self.vertical.add_weighted(&other.vertical, self_portion, other_portion)?;
        let blur = self.blur.add_weighted(&other.blur, self_portion, other_portion)?;

        Ok(SimpleShadow {
            color: color,
            horizontal: horizontal,
            vertical: vertical,
            blur: blur,
        })
    }
}

impl ToAnimatedZero for SimpleShadow {
    #[inline]
    fn to_animated_zero(&self) -> Result<Self, ()> {
        Ok(SimpleShadow {
            color: Color::transparent(),
            horizontal: self.horizontal.to_animated_zero()?,
            vertical: self.vertical.to_animated_zero()?,
            blur: self.blur.to_animated_zero()?,
        })
    }
}
<commit_msg>Implement distance for shadow list.<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

//! Animated types for CSS values related to effects.

use properties::animated_properties::Animatable;
use properties::longhands::box_shadow::computed_value::T as ComputedBoxShadowList;
use properties::longhands::filter::computed_value::T as ComputedFilterList;
use properties::longhands::text_shadow::computed_value::T as ComputedTextShadowList;
use std::cmp;
#[cfg(not(feature = "gecko"))]
use values::Impossible;
use values::animated::{ToAnimatedValue, ToAnimatedZero};
use values::animated::color::Color;
use values::computed::{Angle, NonNegativeNumber};
use values::computed::length::{Length, NonNegativeLength};
use values::distance::{ComputeSquaredDistance, SquaredDistance};
use values::generics::effects::BoxShadow as GenericBoxShadow;
use values::generics::effects::Filter as GenericFilter;
use values::generics::effects::SimpleShadow as GenericSimpleShadow;

/// An animated value for the `box-shadow` property.
pub type BoxShadowList = ShadowList<BoxShadow>;

/// An animated value for the `text-shadow` property.
pub type TextShadowList = ShadowList<SimpleShadow>;

/// An animated value for shadow lists.
///
/// https://drafts.csswg.org/css-transitions/#animtype-shadow-list
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq)]
pub struct ShadowList<Shadow>(Vec<Shadow>);

/// An animated value for a single `box-shadow`.
pub type BoxShadow = GenericBoxShadow<Color, Length, NonNegativeLength, Length>;

/// An animated value for the `filter` property.
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Clone, Debug, PartialEq)]
pub struct FilterList(pub Vec<Filter>);

/// An animated value for a single `filter`.
#[cfg(feature = "gecko")]
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow>;

/// An animated value for a single `filter`.
#[cfg(not(feature = "gecko"))]
pub type Filter = GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible>;

/// An animated value for the `drop-shadow()` filter.
pub type SimpleShadow = GenericSimpleShadow<Color, Length, NonNegativeLength>;

impl ToAnimatedValue for ComputedBoxShadowList {
    type AnimatedValue = BoxShadowList;

    #[inline]
    fn to_animated_value(self) -> Self::AnimatedValue {
        ShadowList(self.0.to_animated_value())
    }

    #[inline]
    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
        ComputedBoxShadowList(ToAnimatedValue::from_animated_value(animated.0))
    }
}

impl<S> Animatable for ShadowList<S>
where
    S: Animatable + Clone + ToAnimatedZero,
{
    #[inline]
    fn add_weighted(
        &self,
        other: &Self,
        self_portion: f64,
        other_portion: f64,
    ) -> Result<Self, ()> {
        let max_len = cmp::max(self.0.len(), other.0.len());
        let mut shadows = Vec::with_capacity(max_len);
        for i in 0..max_len {
            shadows.push(match (self.0.get(i), other.0.get(i)) {
                (Some(shadow), Some(other)) => {
                    shadow.add_weighted(other, self_portion, other_portion)?
                },
                (Some(shadow), None) => {
                    shadow.add_weighted(&shadow.to_animated_zero()?, self_portion, other_portion)?
                },
                (None, Some(shadow)) => {
                    shadow.to_animated_zero()?.add_weighted(&shadow, self_portion, other_portion)?
                },
                (None, None) => unreachable!(),
            });
        }
        Ok(ShadowList(shadows))
    }

    #[inline]
    fn add(&self, other: &Self) -> Result<Self, ()> {
        Ok(ShadowList(
            self.0.iter().cloned().chain(other.0.iter().cloned()).collect(),
        ))
    }
}

impl<S> ComputeSquaredDistance for ShadowList<S>
where
    S: ComputeSquaredDistance + ToAnimatedZero,
{
    #[inline]
    fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
        use itertools::{EitherOrBoth, Itertools};

        self.0.iter().zip_longest(other.0.iter()).map(|it| {
            match it {
                EitherOrBoth::Both(from, to) => {
                    from.compute_squared_distance(to)
                },
                EitherOrBoth::Left(list) | EitherOrBoth::Right(list) => {
                    list.compute_squared_distance(&list.to_animated_zero()?)
                },
            }
        }).sum()
    }
}

impl<S> ToAnimatedZero for ShadowList<S> {
    #[inline]
    fn to_animated_zero(&self) -> Result<Self, ()> {
        Ok(ShadowList(vec![]))
    }
}

impl ToAnimatedValue for ComputedTextShadowList {
    type AnimatedValue = TextShadowList;

    #[inline]
    fn to_animated_value(self) -> Self::AnimatedValue {
        ShadowList(self.0.to_animated_value())
    }

    #[inline]
    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
        ComputedTextShadowList(ToAnimatedValue::from_animated_value(animated.0))
    }
}

impl Animatable for BoxShadow {
    #[inline]
    fn add_weighted(
        &self,
        other: &Self,
        self_portion: f64,
        other_portion: f64,
    ) -> Result<Self, ()> {
        if self.inset != other.inset {
            return Err(());
        }
        Ok(BoxShadow {
            base: self.base.add_weighted(&other.base, self_portion, other_portion)?,
            spread: self.spread.add_weighted(&other.spread, self_portion, other_portion)?,
            inset: self.inset,
        })
    }
}

impl ComputeSquaredDistance for BoxShadow {
    #[inline]
    fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
        if self.inset != other.inset {
            return Err(());
        }
        Ok(
            self.base.compute_squared_distance(&other.base)? +
            self.spread.compute_squared_distance(&other.spread)?,
        )
    }
}

impl ToAnimatedZero for BoxShadow {
    #[inline]
    fn to_animated_zero(&self) -> Result<Self, ()> {
        Ok(BoxShadow {
            base: self.base.to_animated_zero()?,
            spread: self.spread.to_animated_zero()?,
            inset: self.inset,
        })
    }
}

impl ToAnimatedValue for ComputedFilterList {
    type AnimatedValue = FilterList;

    #[cfg(not(feature = "gecko"))]
    #[inline]
    fn to_animated_value(self) -> Self::AnimatedValue {
        FilterList(self.0)
    }

    #[cfg(feature = "gecko")]
    #[inline]
    fn to_animated_value(self) -> Self::AnimatedValue {
        FilterList(self.0.to_animated_value())
    }

    #[cfg(not(feature = "gecko"))]
    #[inline]
    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
        ComputedFilterList(animated.0)
    }

    #[cfg(feature = "gecko")]
    #[inline]
    fn from_animated_value(animated: Self::AnimatedValue) -> Self {
        ComputedFilterList(ToAnimatedValue::from_animated_value(animated.0))
    }
}

impl ToAnimatedZero for FilterList {
    #[inline]
    fn to_animated_zero(&self) -> Result<Self, ()> {
        Ok(FilterList(vec![]))
    }
}

impl Animatable for SimpleShadow {
    #[inline]
    fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) -> Result<Self, ()> {
        let color = self.color.add_weighted(&other.color, self_portion, other_portion)?;
        let horizontal = self.horizontal.add_weighted(&other.horizontal, self_portion, other_portion)?;
        let vertical = self.vertical.add_weighted(&other.vertical, self_portion, other_portion)?;
        let blur = self.blur.add_weighted(&other.blur, self_portion, other_portion)?;

        Ok(SimpleShadow {
            color: color,
            horizontal: horizontal,
            vertical: vertical,
            blur: blur,
        })
    }
}

impl ToAnimatedZero for SimpleShadow {
    #[inline]
    fn to_animated_zero(&self) -> Result<Self, ()> {
        Ok(SimpleShadow {
            color: Color::transparent(),
            horizontal: self.horizontal.to_animated_zero()?,
            vertical: self.vertical.to_animated_zero()?,
            blur: self.blur.to_animated_zero()?,
        })
    }
}
<|endoftext|>


<commit_before>//! A small TCP server to handle collection of diagnostics information in a
//! cross-platform way for the `cargo fix` command.

use std::collections::HashSet;
use std::env;
use std::io::{BufReader, Read, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, JoinHandle};

use failure::{Error, ResultExt};
use serde_json;

use util::{Config, ProcessBuilder};
use util::errors::CargoResult;

const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
const PLEASE_REPORT_THIS_BUG: &str =
    "\
     This likely indicates a bug in either rustc or cargo itself,\n\
     and we would appreciate a bug report! You're likely to see \n\
     a number of compiler warnings after this message which cargo\n\
     attempted to fix but failed. If you could open an issue at\n\
     https://github.com/rust-lang/cargo/issues\n\
     quoting the full output of this command we'd be very appreciative!\n\n\
     ";

#[derive(Deserialize, Serialize)]
pub enum Message {
    Fixing {
        file: String,
        fixes: u32,
    },
    FixFailed {
        files: Vec<String>,
        krate: Option<String>,
    },
    ReplaceFailed {
        file: String,
        message: String,
    },
    PreviewNotFound {
        file: String,
        edition: String,
    },
    EditionAlreadyEnabled {
        file: String,
        edition: String,
    },
    IdiomEditionMismatch {
        file: String,
        idioms: String,
        edition: Option<String>,
    },
}

impl Message {
    pub fn post(&self) -> Result<(), Error> {
        let addr = env::var(DIAGNOSICS_SERVER_VAR)
            .context("diagnostics collector misconfigured")?;
        let mut client =
            TcpStream::connect(&addr).context("failed to connect to parent diagnostics target")?;

        let s = serde_json::to_string(self).context("failed to serialize message")?;
        client
            .write_all(s.as_bytes())
            .context("failed to write message to diagnostics target")?;
        client
            .shutdown(Shutdown::Write)
            .context("failed to shutdown")?;

        let mut tmp = Vec::new();
        client
            .read_to_end(&mut tmp)
            .context("failed to receive a disconnect")?;

        Ok(())
    }
}

pub struct DiagnosticPrinter<'a> {
    config: &'a Config,
    preview_not_found: HashSet<String>,
    edition_already_enabled: HashSet<String>,
    idiom_mismatch: HashSet<String>,
}

impl<'a> DiagnosticPrinter<'a> {
    pub fn new(config: &'a Config) -> DiagnosticPrinter<'a> {
        DiagnosticPrinter {
            config,
            preview_not_found: HashSet::new(),
            edition_already_enabled: HashSet::new(),
            idiom_mismatch: HashSet::new(),
        }
    }

    pub fn print(&mut self, msg: &Message) -> CargoResult<()> {
        match msg {
            Message::Fixing { file, fixes } => {
                let msg = if *fixes == 1 { "fix" } else { "fixes" };
                let msg = format!("{} ({} {})", file, fixes, msg);
                self.config.shell().status("Fixing", msg)
            }
            Message::ReplaceFailed { file, message } => {
                let msg = format!("error applying suggestions to `{}`\n", file);
                self.config.shell().warn(&msg)?;
                write!(
                    self.config.shell().err(),
                    "The full error message was:\n\n> {}\n\n",
                    message,
                )?;
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::FixFailed { files, krate } => {
                if let Some(ref krate) = *krate {
                    self.config.shell().warn(&format!(
                        "failed to automatically apply fixes suggested by rustc \
                         to crate `{}`",
                        krate,
                    ))?;
                } else {
                    self.config.shell().warn(
                        "failed to automatically apply fixes suggested by rustc"
                    )?;
                }
                if !files.is_empty() {
                    writeln!(
                        self.config.shell().err(),
                        "\nafter fixes were automatically applied the compiler \
                         reported errors within these files:\n"
                    )?;
                    for file in files {
                        writeln!(self.config.shell().err(), "  * {}", file)?;
                    }
                    writeln!(self.config.shell().err())?;
                }
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::PreviewNotFound { file, edition } => {
                // By default we're fixing a lot of things concurrently, don't
                // warn about the same file multiple times.
                if !self.preview_not_found.insert(file.clone()) {
                    return Ok(())
                }
                self.config.shell().warn(&format!(
                    "failed to find `#![feature(rust_{}_preview)]` in `{}`\n\
                     this may cause `cargo fix` to not be able to fix all\n\
                     issues in preparation for the {0} edition",
                    edition,
                    file,
                ))?;
                Ok(())
            }
            Message::EditionAlreadyEnabled { file, edition } => {
                // Like above, only warn once per file
                if !self.edition_already_enabled.insert(file.clone()) {
                    return Ok(())
                }

                let msg = format!(
                    "\
cannot prepare for the {} edition when it is enabled, so cargo cannot
automatically fix errors in `{}`

To prepare for the {0} edition you should first remove `edition = '{0}'` from
your `Cargo.toml` and then rerun this command. Once all warnings have been fixed
then you can re-enable the `edition` key in `Cargo.toml`. For some more
information about transitioning to the {0} edition see:

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-your-code-to-a-new-edition.html
",
                    edition,
                    file,
                );
                self.config.shell().error(&msg)?;
                Ok(())
            }
            Message::IdiomEditionMismatch { file, idioms, edition } => {
                // Same as above
                if !self.idiom_mismatch.insert(file.clone()) {
                    return Ok(())
                }
                self.config.shell().error(&format!(
                    "\
cannot migrate to the idioms of the {} edition for `{}`
because it is compiled {}, which doesn't match {0}

consider migrating to the {0} edition by adding `edition = '{0}'` to
`Cargo.toml` and then rerunning this command; a more detailed transition
guide can be found at

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-your-code-to-a-new-edition.html
",
                    idioms,
                    file,
                    match edition {
                        Some(s) => format!("with the {} edition", s),
                        None => "without an edition".to_string(),
                    },
                ))?;
                Ok(())
            }
        }
    }
}

#[derive(Debug)]
pub struct RustfixDiagnosticServer {
    listener: TcpListener,
    addr: SocketAddr,
}

pub struct StartedServer {
    addr: SocketAddr,
    done: Arc<AtomicBool>,
    thread: Option<JoinHandle<()>>,
}

impl RustfixDiagnosticServer {
    pub fn new() -> Result<Self, Error> {
        let listener = TcpListener::bind("127.0.0.1:0")
            .with_context(|_| "failed to bind TCP listener to manage locking")?;
        let addr = listener.local_addr()?;

        Ok(RustfixDiagnosticServer { listener, addr })
    }

    pub fn configure(&self, process: &mut ProcessBuilder) {
        process.env(DIAGNOSICS_SERVER_VAR, self.addr.to_string());
    }

    pub fn start<F>(self, on_message: F) -> Result<StartedServer, Error>
    where
        F: Fn(Message) + Send + 'static,
    {
        let addr = self.addr;
        let done = Arc::new(AtomicBool::new(false));
        let done2 = done.clone();
        let thread = thread::spawn(move || {
            self.run(&on_message, &done2);
        });

        Ok(StartedServer {
            addr,
            thread: Some(thread),
            done,
        })
    }

    fn run(self, on_message: &Fn(Message), done: &AtomicBool) {
        while let Ok((client, _)) = self.listener.accept() {
            let client = BufReader::new(client);
            match serde_json::from_reader(client) {
                Ok(message) => on_message(message),
                Err(e) => warn!("invalid diagnostics message: {}", e),
            }
            if done.load(Ordering::SeqCst) {
                break
            }
        }
    }
}

impl Drop for StartedServer {
    fn drop(&mut self) {
        self.done.store(true, Ordering::SeqCst);
        // Ignore errors here as this is largely best-effort
        if TcpStream::connect(&self.addr).is_err() {
            return;
        }
        drop(self.thread.take().unwrap().join());
    }
}
<commit_msg>Finish removing PreviewNotFound<commit_after>//! A small TCP server to handle collection of diagnostics information in a
//! cross-platform way for the `cargo fix` command.

use std::collections::HashSet;
use std::env;
use std::io::{BufReader, Read, Write};
use std::net::{Shutdown, SocketAddr, TcpListener, TcpStream};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::{self, JoinHandle};

use failure::{Error, ResultExt};
use serde_json;

use util::{Config, ProcessBuilder};
use util::errors::CargoResult;

const DIAGNOSICS_SERVER_VAR: &str = "__CARGO_FIX_DIAGNOSTICS_SERVER";
const PLEASE_REPORT_THIS_BUG: &str =
    "\
     This likely indicates a bug in either rustc or cargo itself,\n\
     and we would appreciate a bug report! You're likely to see \n\
     a number of compiler warnings after this message which cargo\n\
     attempted to fix but failed. If you could open an issue at\n\
     https://github.com/rust-lang/cargo/issues\n\
     quoting the full output of this command we'd be very appreciative!\n\n\
     ";

#[derive(Deserialize, Serialize)]
pub enum Message {
    Fixing {
        file: String,
        fixes: u32,
    },
    FixFailed {
        files: Vec<String>,
        krate: Option<String>,
    },
    ReplaceFailed {
        file: String,
        message: String,
    },
    EditionAlreadyEnabled {
        file: String,
        edition: String,
    },
    IdiomEditionMismatch {
        file: String,
        idioms: String,
        edition: Option<String>,
    },
}

impl Message {
    pub fn post(&self) -> Result<(), Error> {
        let addr = env::var(DIAGNOSICS_SERVER_VAR)
            .context("diagnostics collector misconfigured")?;
        let mut client =
            TcpStream::connect(&addr).context("failed to connect to parent diagnostics target")?;

        let s = serde_json::to_string(self).context("failed to serialize message")?;
        client
            .write_all(s.as_bytes())
            .context("failed to write message to diagnostics target")?;
        client
            .shutdown(Shutdown::Write)
            .context("failed to shutdown")?;

        let mut tmp = Vec::new();
        client
            .read_to_end(&mut tmp)
            .context("failed to receive a disconnect")?;

        Ok(())
    }
}

pub struct DiagnosticPrinter<'a> {
    config: &'a Config,
    edition_already_enabled: HashSet<String>,
    idiom_mismatch: HashSet<String>,
}

impl<'a> DiagnosticPrinter<'a> {
    pub fn new(config: &'a Config) -> DiagnosticPrinter<'a> {
        DiagnosticPrinter {
            config,
            edition_already_enabled: HashSet::new(),
            idiom_mismatch: HashSet::new(),
        }
    }

    pub fn print(&mut self, msg: &Message) -> CargoResult<()> {
        match msg {
            Message::Fixing { file, fixes } => {
                let msg = if *fixes == 1 { "fix" } else { "fixes" };
                let msg = format!("{} ({} {})", file, fixes, msg);
                self.config.shell().status("Fixing", msg)
            }
            Message::ReplaceFailed { file, message } => {
                let msg = format!("error applying suggestions to `{}`\n", file);
                self.config.shell().warn(&msg)?;
                write!(
                    self.config.shell().err(),
                    "The full error message was:\n\n> {}\n\n",
                    message,
                )?;
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::FixFailed { files, krate } => {
                if let Some(ref krate) = *krate {
                    self.config.shell().warn(&format!(
                        "failed to automatically apply fixes suggested by rustc \
                         to crate `{}`",
                        krate,
                    ))?;
                } else {
                    self.config.shell().warn(
                        "failed to automatically apply fixes suggested by rustc"
                    )?;
                }
                if !files.is_empty() {
                    writeln!(
                        self.config.shell().err(),
                        "\nafter fixes were automatically applied the compiler \
                         reported errors within these files:\n"
                    )?;
                    for file in files {
                        writeln!(self.config.shell().err(), "  * {}", file)?;
                    }
                    writeln!(self.config.shell().err())?;
                }
                write!(self.config.shell().err(), "{}", PLEASE_REPORT_THIS_BUG)?;
                Ok(())
            }
            Message::EditionAlreadyEnabled { file, edition } => {
                // Like above, only warn once per file
                if !self.edition_already_enabled.insert(file.clone()) {
                    return Ok(())
                }

                let msg = format!(
                    "\
cannot prepare for the {} edition when it is enabled, so cargo cannot
automatically fix errors in `{}`

To prepare for the {0} edition you should first remove `edition = '{0}'` from
your `Cargo.toml` and then rerun this command. Once all warnings have been fixed
then you can re-enable the `edition` key in `Cargo.toml`. For some more
information about transitioning to the {0} edition see:

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-your-code-to-a-new-edition.html
",
                    edition,
                    file,
                );
                self.config.shell().error(&msg)?;
                Ok(())
            }
            Message::IdiomEditionMismatch { file, idioms, edition } => {
                // Same as above
                if !self.idiom_mismatch.insert(file.clone()) {
                    return Ok(())
                }
                self.config.shell().error(&format!(
                    "\
cannot migrate to the idioms of the {} edition for `{}`
because it is compiled {}, which doesn't match {0}

consider migrating to the {0} edition by adding `edition = '{0}'` to
`Cargo.toml` and then rerunning this command; a more detailed transition
guide can be found at

  https://rust-lang-nursery.github.io/edition-guide/editions/transitioning-your-code-to-a-new-edition.html
",
                    idioms,
                    file,
                    match edition {
                        Some(s) => format!("with the {} edition", s),
                        None => "without an edition".to_string(),
                    },
                ))?;
                Ok(())
            }
        }
    }
}

#[derive(Debug)]
pub struct RustfixDiagnosticServer {
    listener: TcpListener,
    addr: SocketAddr,
}

pub struct StartedServer {
    addr: SocketAddr,
    done: Arc<AtomicBool>,
    thread: Option<JoinHandle<()>>,
}

impl RustfixDiagnosticServer {
    pub fn new() -> Result<Self, Error> {
        let listener = TcpListener::bind("127.0.0.1:0")
            .with_context(|_| "failed to bind TCP listener to manage locking")?;
        let addr = listener.local_addr()?;

        Ok(RustfixDiagnosticServer { listener, addr })
    }

    pub fn configure(&self, process: &mut ProcessBuilder) {
        process.env(DIAGNOSICS_SERVER_VAR, self.addr.to_string());
    }

    pub fn start<F>(self, on_message: F) -> Result<StartedServer, Error>
    where
        F: Fn(Message) + Send + 'static,
    {
        let addr = self.addr;
        let done = Arc::new(AtomicBool::new(false));
        let done2 = done.clone();
        let thread = thread::spawn(move || {
            self.run(&on_message, &done2);
        });

        Ok(StartedServer {
            addr,
            thread: Some(thread),
            done,
        })
    }

    fn run(self, on_message: &Fn(Message), done: &AtomicBool) {
        while let Ok((client, _)) = self.listener.accept() {
            let client = BufReader::new(client);
            match serde_json::from_reader(client) {
                Ok(message) => on_message(message),
                Err(e) => warn!("invalid diagnostics message: {}", e),
            }
            if done.load(Ordering::SeqCst) {
                break
            }
        }
    }
}

impl Drop for StartedServer {
    fn drop(&mut self) {
        self.done.store(true, Ordering::SeqCst);
        // Ignore errors here as this is largely best-effort
        if TcpStream::connect(&self.addr).is_err() {
            return;
        }
        drop(self.thread.take().unwrap().join());
    }
}
<|endoftext|>


<commit_before>//! Utility code, that allow writing more ituitive and shorter code,
//! moving Extensions or complex Error Handling out of the core modules (frontend/backend).
//!
//! For actual usage take a look at the corresponding submodule
pub mod extensions;
#[macro_use] pub mod error;
<commit_msg>Update mod.rs to match Docstring RFC<commit_after>//! Utility code for more ituitive and shorter code.
//!
//! The submodules move moving Extensions or complex Error Handling out of the core modules (frontend/backend).
//! For actual usage take a look at the corresponding submodule.
pub mod extensions;
#[macro_use] pub mod error;
<|endoftext|>


<commit_before>use std::io::{Read, Cursor, Error, ErrorKind};
use tokio_codec::{Encoder, Decoder};
use bytes::{BufMut, BytesMut};
use serializer::*;

use blockchain::Properties;
use tx::TxVariant;
use net::rpc::*;

// 5 MiB limit
const MAX_PAYLOAD_LEN: u32 = 5_242_880;

#[derive(Default)]
pub struct RpcCodec {
    msg_len: u32
}

impl RpcCodec {
    pub fn new() -> RpcCodec {
        RpcCodec::default()
    }
}

impl Encoder for RpcCodec {
    type Item = RpcPayload;
    type Error = Error;

    fn encode(&mut self, pl: Self::Item, buf: &mut BytesMut) -> Result<(), Error> {
        let mut payload = Vec::<u8>::with_capacity(10240);
        payload.push_u32(pl.id);
        if let Some(msg) = pl.msg {
            match msg {
                RpcMsg::Error(err) => {
                    payload.push_u32(err.len() as u32);
                    payload.push_bytes(err.as_bytes());
                },
                RpcMsg::Event(evt) => {
                    payload.push(RpcMsgType::Event as u8);
                    match evt {
                        RpcEvent::Tx(tx) => {
                            payload.push(RpcEventType::TX as u8);
                            tx.encode_with_sigs(&mut payload);
                        },
                        RpcEvent::Block(block) => {
                            payload.push(RpcEventType::BLOCK as u8);
                            block.encode_with_tx(&mut payload);
                        }
                    }
                },
                RpcMsg::Handshake(peer_type) => {
                    payload.push(RpcMsgType::Handshake as u8);
                    payload.push(peer_type as u8);
                },
                RpcMsg::Broadcast(tx) => {
                    payload.push(RpcMsgType::Broadcast as u8);
                    tx.encode_with_sigs(&mut payload);
                },
                RpcMsg::Properties(rpc) => {
                    payload.push(RpcMsgType::Properties as u8);
                    if let Some(props) = rpc.response() {
                        payload.push(RpcVariantType::Res as u8);
                        payload.push_u64(props.height);
                        payload.push_asset(&props.token_supply.gold);
                        payload.push_asset(&props.token_supply.silver);
                    } else {
                        payload.push(RpcVariantType::Req as u8);
                    }
                },
                RpcMsg::Block(rpc) => {
                    payload.push(RpcMsgType::Block as u8);
                    match rpc {
                        RpcVariant::Req(height) => {
                            payload.push(RpcVariantType::Req as u8);
                            payload.push_u64(height);
                        },
                        RpcVariant::Res(block) => {
                            payload.push(RpcVariantType::Res as u8);
                            if let Some(block) = block {
                                block.encode_with_tx(&mut payload);
                            }
                        }
                    }
                },
                RpcMsg::Balance(rpc) => {
                    payload.push(RpcMsgType::Balance as u8);
                    match rpc {
                        RpcVariant::Req(addr) => {
                            payload.push(RpcVariantType::Req as u8);
                            payload.push_pub_key(&addr);
                        },
                        RpcVariant::Res(bal) => {
                            payload.push(RpcVariantType::Res as u8);
                            payload.push_asset(&bal.gold);
                            payload.push_asset(&bal.silver);
                        }
                    }
                },
                RpcMsg::TotalFee(rpc) => {
                    payload.push(RpcMsgType::Balance as u8);
                    match rpc {
                        RpcVariant::Req(addr) => {
                            payload.push(RpcVariantType::Req as u8);
                            payload.push_pub_key(&addr);
                        },
                        RpcVariant::Res(bal) => {
                            payload.push(RpcVariantType::Res as u8);
                            payload.push_asset(&bal.gold);
                            payload.push_asset(&bal.silver);
                        }
                    }
                }
            }
        }

        buf.reserve(4 + payload.len());
        buf.put_u32_be(4 + (payload.len() as u32));
        buf.put_slice(&payload);
        debug_assert!((buf.capacity() as u32) < MAX_PAYLOAD_LEN);
        let mut v = Vec::<u8>::with_capacity(buf.len());
        v.extend_from_slice(buf);
        Ok(())
    }
}

impl Decoder for RpcCodec {
    type Item = RpcPayload;
    type Error = Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
        if self.msg_len == 0 && buf.len() >= 4 {
            let buf = buf.split_to(4);
            self.msg_len = u32_from_buf!(buf);
            if self.msg_len <= 4 {
                return Err(Error::new(ErrorKind::Other, "payload must be >4 bytes"))
            } else if self.msg_len > MAX_PAYLOAD_LEN {
                return Err(Error::new(ErrorKind::Other, format!("payload must be <={} bytes", MAX_PAYLOAD_LEN)))
            }
            self.msg_len -= 4;
        }
        if self.msg_len != 0 && buf.len() >= self.msg_len as usize {
            let msg_len = self.msg_len;
            let split = buf.split_to(msg_len as usize);
            let mut cur = Cursor::new(split.as_ref());
            self.msg_len = 0;

            let id = cur.take_u32()?;
            if msg_len == 4 {
                return Ok(Some(RpcPayload {
                    id,
                    msg: None
                }))
            }

            let msg = match cur.take_u8()? {
                t if t == RpcMsgType::Error as u8 => {
                    let len = cur.take_u32()?;
                    if len > MAX_PAYLOAD_LEN {
                        return Err(Error::new(ErrorKind::Other, "error string too large"))
                    }
                    let mut buf = Vec::with_capacity(len as usize);
                    cur.read_exact(&mut buf).map_err(|_| {
                        Error::new(ErrorKind::Other, "failed to read error string")
                    })?;
                    RpcMsg::Error(String::from_utf8_lossy(&buf).into_owned())
                },
                t if t == RpcMsgType::Event as u8 => {
                    let event_type = cur.take_u8()?;
                    match event_type {
                        t if t == RpcEventType::TX as u8 => {
                            let tx = TxVariant::decode_with_sigs(&mut cur).ok_or_else(|| {
                                Error::new(ErrorKind::Other, "failed to decode tx")
                            })?;
                            RpcMsg::Event(RpcEvent::Tx(tx))
                        },
                        t if t == RpcEventType::BLOCK as u8 => {
                            let block = SignedBlock::decode_with_tx(&mut cur).ok_or_else(|| {
                                Error::new(ErrorKind::Other, "failed to decode signed block")
                            })?;
                            RpcMsg::Event(RpcEvent::Block(block))
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid event type"))
                    }
                },
                t if t == RpcMsgType::Handshake as u8 => {
                    let peer_type = match cur.take_u8()? {
                        t if t == PeerType::NODE as u8 => PeerType::NODE,
                        t if t == PeerType::WALLET as u8 => PeerType::WALLET,
                        _ => return Err(Error::new(ErrorKind::Other, "invalid peer type"))
                    };
                    RpcMsg::Handshake(peer_type)
                },
                t if t == RpcMsgType::Broadcast as u8 => {
                    let tx = TxVariant::decode_with_sigs(&mut cur).ok_or_else(|| {
                        Error::new(ErrorKind::Other, "failed to decode broadcast tx")
                    })?;
                    RpcMsg::Broadcast(tx)
                },
                t if t == RpcMsgType::Properties as u8 => {
                    let rpc = cur.take_u8()?;
                    match rpc {
                        t if t == RpcVariantType::Req as u8 => {
                            RpcMsg::Properties(RpcVariant::Req(()))
                        },
                        t if t == RpcVariantType::Res as u8 => {
                            let height = cur.take_u64()?;
                            let gold = cur.take_asset()?;
                            let silver = cur.take_asset()?;
                            RpcMsg::Properties(RpcVariant::Res(Properties {
                                height,
                                token_supply: Balance { gold, silver }
                            }))
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid rpc type"))
                    }
                },
                t if t == RpcMsgType::Block as u8 => {
                    let rpc = cur.take_u8()?;
                    match rpc {
                        t if t == RpcVariantType::Req as u8 => {
                            let height = cur.take_u64()?;
                            RpcMsg::Block(RpcVariant::Req(height))
                        },
                        t if t == RpcVariantType::Res as u8 => {
                            if u64::from(msg_len).saturating_sub(cur.position()) > 0 {
                                let block = SignedBlock::decode_with_tx(&mut cur).ok_or_else(|| {
                                    Error::new(ErrorKind::Other, "failed to decode block")
                                })?;
                                RpcMsg::Block(RpcVariant::Res(Some(block)))
                            } else {
                                RpcMsg::Block(RpcVariant::Res(None))
                            }
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid rpc type"))
                    }
                },
                t if t == RpcMsgType::Balance as u8 => {
                    let rpc = cur.take_u8()?;
                    match rpc {
                        t if t == RpcVariantType::Req as u8 => {
                            let addr = cur.take_pub_key()?;
                            RpcMsg::Balance(RpcVariant::Req(addr))
                        },
                        t if t == RpcVariantType::Res as u8 => {
                            let gold = cur.take_asset()?;
                            let silver = cur.take_asset()?;
                            RpcMsg::Balance(RpcVariant::Res(Balance { gold, silver }))
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid rpc type"))
                    }
                },
                t if t == RpcMsgType::TotalFee as u8 => {
                    let rpc = cur.take_u8()?;
                    match rpc {
                        t if t == RpcVariantType::Req as u8 => {
                            let addr = cur.take_pub_key()?;
                            RpcMsg::TotalFee(RpcVariant::Req(addr))
                        },
                        t if t == RpcVariantType::Res as u8 => {
                            let gold = cur.take_asset()?;
                            let silver = cur.take_asset()?;
                            RpcMsg::TotalFee(RpcVariant::Res(Balance { gold, silver }))
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid rpc type"))
                    }
                },
                _ => return Err(Error::new(ErrorKind::Other, "invalid msg type"))
            };

            Ok(Some(RpcPayload {
                id,
                msg: Some(msg)
            }))
        } else {
            Ok(None)
        }
    }
}
<commit_msg>Push the error type byte and no longer use a message length for errors<commit_after>use std::io::{Read, Cursor, Error, ErrorKind};
use tokio_codec::{Encoder, Decoder};
use bytes::{BufMut, BytesMut};
use serializer::*;

use blockchain::Properties;
use tx::TxVariant;
use net::rpc::*;

// 5 MiB limit
const MAX_PAYLOAD_LEN: u32 = 5_242_880;

#[derive(Default)]
pub struct RpcCodec {
    msg_len: u32
}

impl RpcCodec {
    pub fn new() -> RpcCodec {
        RpcCodec::default()
    }
}

impl Encoder for RpcCodec {
    type Item = RpcPayload;
    type Error = Error;

    fn encode(&mut self, pl: Self::Item, buf: &mut BytesMut) -> Result<(), Error> {
        let mut payload = Vec::<u8>::with_capacity(10240);
        payload.push_u32(pl.id);
        if let Some(msg) = pl.msg {
            match msg {
                RpcMsg::Error(err) => {
                    payload.push(RpcMsgType::Error as u8);
                    payload.push_bytes(err.as_bytes());
                },
                RpcMsg::Event(evt) => {
                    payload.push(RpcMsgType::Event as u8);
                    match evt {
                        RpcEvent::Tx(tx) => {
                            payload.push(RpcEventType::TX as u8);
                            tx.encode_with_sigs(&mut payload);
                        },
                        RpcEvent::Block(block) => {
                            payload.push(RpcEventType::BLOCK as u8);
                            block.encode_with_tx(&mut payload);
                        }
                    }
                },
                RpcMsg::Handshake(peer_type) => {
                    payload.push(RpcMsgType::Handshake as u8);
                    payload.push(peer_type as u8);
                },
                RpcMsg::Broadcast(tx) => {
                    payload.push(RpcMsgType::Broadcast as u8);
                    tx.encode_with_sigs(&mut payload);
                },
                RpcMsg::Properties(rpc) => {
                    payload.push(RpcMsgType::Properties as u8);
                    if let Some(props) = rpc.response() {
                        payload.push(RpcVariantType::Res as u8);
                        payload.push_u64(props.height);
                        payload.push_asset(&props.token_supply.gold);
                        payload.push_asset(&props.token_supply.silver);
                    } else {
                        payload.push(RpcVariantType::Req as u8);
                    }
                },
                RpcMsg::Block(rpc) => {
                    payload.push(RpcMsgType::Block as u8);
                    match rpc {
                        RpcVariant::Req(height) => {
                            payload.push(RpcVariantType::Req as u8);
                            payload.push_u64(height);
                        },
                        RpcVariant::Res(block) => {
                            payload.push(RpcVariantType::Res as u8);
                            if let Some(block) = block {
                                block.encode_with_tx(&mut payload);
                            }
                        }
                    }
                },
                RpcMsg::Balance(rpc) => {
                    payload.push(RpcMsgType::Balance as u8);
                    match rpc {
                        RpcVariant::Req(addr) => {
                            payload.push(RpcVariantType::Req as u8);
                            payload.push_pub_key(&addr);
                        },
                        RpcVariant::Res(bal) => {
                            payload.push(RpcVariantType::Res as u8);
                            payload.push_asset(&bal.gold);
                            payload.push_asset(&bal.silver);
                        }
                    }
                },
                RpcMsg::TotalFee(rpc) => {
                    payload.push(RpcMsgType::Balance as u8);
                    match rpc {
                        RpcVariant::Req(addr) => {
                            payload.push(RpcVariantType::Req as u8);
                            payload.push_pub_key(&addr);
                        },
                        RpcVariant::Res(bal) => {
                            payload.push(RpcVariantType::Res as u8);
                            payload.push_asset(&bal.gold);
                            payload.push_asset(&bal.silver);
                        }
                    }
                }
            }
        }

        buf.reserve(4 + payload.len());
        buf.put_u32_be(4 + (payload.len() as u32));
        buf.put_slice(&payload);
        debug_assert!((buf.capacity() as u32) < MAX_PAYLOAD_LEN);
        let mut v = Vec::<u8>::with_capacity(buf.len());
        v.extend_from_slice(buf);
        Ok(())
    }
}

impl Decoder for RpcCodec {
    type Item = RpcPayload;
    type Error = Error;

    fn decode(&mut self, buf: &mut BytesMut) -> Result<Option<Self::Item>, Error> {
        if self.msg_len == 0 && buf.len() >= 4 {
            let buf = buf.split_to(4);
            self.msg_len = u32_from_buf!(buf);
            if self.msg_len <= 4 {
                return Err(Error::new(ErrorKind::Other, "payload must be >4 bytes"))
            } else if self.msg_len > MAX_PAYLOAD_LEN {
                return Err(Error::new(ErrorKind::Other, format!("payload must be <={} bytes", MAX_PAYLOAD_LEN)))
            }
            self.msg_len -= 4;
        }
        if self.msg_len != 0 && buf.len() >= self.msg_len as usize {
            let msg_len = self.msg_len;
            let split = buf.split_to(msg_len as usize);
            let mut cur = Cursor::new(split.as_ref());
            self.msg_len = 0;

            let id = cur.take_u32()?;
            if msg_len == 4 {
                return Ok(Some(RpcPayload {
                    id,
                    msg: None
                }))
            }

            let msg = match cur.take_u8()? {
                t if t == RpcMsgType::Error as u8 => {
                    let len = msg_len as u64 - cur.position();
                    let mut buf = Vec::with_capacity(len as usize);
                    cur.read_exact(&mut buf).map_err(|_| {
                        Error::new(ErrorKind::Other, "failed to read error string")
                    })?;
                    RpcMsg::Error(String::from_utf8_lossy(&buf).into_owned())
                },
                t if t == RpcMsgType::Event as u8 => {
                    let event_type = cur.take_u8()?;
                    match event_type {
                        t if t == RpcEventType::TX as u8 => {
                            let tx = TxVariant::decode_with_sigs(&mut cur).ok_or_else(|| {
                                Error::new(ErrorKind::Other, "failed to decode tx")
                            })?;
                            RpcMsg::Event(RpcEvent::Tx(tx))
                        },
                        t if t == RpcEventType::BLOCK as u8 => {
                            let block = SignedBlock::decode_with_tx(&mut cur).ok_or_else(|| {
                                Error::new(ErrorKind::Other, "failed to decode signed block")
                            })?;
                            RpcMsg::Event(RpcEvent::Block(block))
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid event type"))
                    }
                },
                t if t == RpcMsgType::Handshake as u8 => {
                    let peer_type = match cur.take_u8()? {
                        t if t == PeerType::NODE as u8 => PeerType::NODE,
                        t if t == PeerType::WALLET as u8 => PeerType::WALLET,
                        _ => return Err(Error::new(ErrorKind::Other, "invalid peer type"))
                    };
                    RpcMsg::Handshake(peer_type)
                },
                t if t == RpcMsgType::Broadcast as u8 => {
                    let tx = TxVariant::decode_with_sigs(&mut cur).ok_or_else(|| {
                        Error::new(ErrorKind::Other, "failed to decode broadcast tx")
                    })?;
                    RpcMsg::Broadcast(tx)
                },
                t if t == RpcMsgType::Properties as u8 => {
                    let rpc = cur.take_u8()?;
                    match rpc {
                        t if t == RpcVariantType::Req as u8 => {
                            RpcMsg::Properties(RpcVariant::Req(()))
                        },
                        t if t == RpcVariantType::Res as u8 => {
                            let height = cur.take_u64()?;
                            let gold = cur.take_asset()?;
                            let silver = cur.take_asset()?;
                            RpcMsg::Properties(RpcVariant::Res(Properties {
                                height,
                                token_supply: Balance { gold, silver }
                            }))
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid rpc type"))
                    }
                },
                t if t == RpcMsgType::Block as u8 => {
                    let rpc = cur.take_u8()?;
                    match rpc {
                        t if t == RpcVariantType::Req as u8 => {
                            let height = cur.take_u64()?;
                            RpcMsg::Block(RpcVariant::Req(height))
                        },
                        t if t == RpcVariantType::Res as u8 => {
                            if u64::from(msg_len).saturating_sub(cur.position()) > 0 {
                                let block = SignedBlock::decode_with_tx(&mut cur).ok_or_else(|| {
                                    Error::new(ErrorKind::Other, "failed to decode block")
                                })?;
                                RpcMsg::Block(RpcVariant::Res(Some(block)))
                            } else {
                                RpcMsg::Block(RpcVariant::Res(None))
                            }
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid rpc type"))
                    }
                },
                t if t == RpcMsgType::Balance as u8 => {
                    let rpc = cur.take_u8()?;
                    match rpc {
                        t if t == RpcVariantType::Req as u8 => {
                            let addr = cur.take_pub_key()?;
                            RpcMsg::Balance(RpcVariant::Req(addr))
                        },
                        t if t == RpcVariantType::Res as u8 => {
                            let gold = cur.take_asset()?;
                            let silver = cur.take_asset()?;
                            RpcMsg::Balance(RpcVariant::Res(Balance { gold, silver }))
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid rpc type"))
                    }
                },
                t if t == RpcMsgType::TotalFee as u8 => {
                    let rpc = cur.take_u8()?;
                    match rpc {
                        t if t == RpcVariantType::Req as u8 => {
                            let addr = cur.take_pub_key()?;
                            RpcMsg::TotalFee(RpcVariant::Req(addr))
                        },
                        t if t == RpcVariantType::Res as u8 => {
                            let gold = cur.take_asset()?;
                            let silver = cur.take_asset()?;
                            RpcMsg::TotalFee(RpcVariant::Res(Balance { gold, silver }))
                        },
                        _ => return Err(Error::new(ErrorKind::Other, "invalid rpc type"))
                    }
                },
                _ => return Err(Error::new(ErrorKind::Other, "invalid msg type"))
            };

            Ok(Some(RpcPayload {
                id,
                msg: Some(msg)
            }))
        } else {
            Ok(None)
        }
    }
}
<|endoftext|>


<commit_before>extern crate bindgen;
#[cfg(feature = "static")]
extern crate meson;
extern crate pkg_config;
extern crate wayland_scanner;

use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, fs, io};

fn main() {
    meson();
    let protocol_header_path =
        generate_protocol_headers().expect("Could not generate header files for wayland protocols");
    let target_dir = env::var("OUT_DIR").expect("$OUT_DIR not set!");
    let mut builder = bindgen::builder()
        .derive_debug(true)
        .derive_default(true)
        .generate_comments(true)
        .header("src/wlroots.h")
        .whitelisted_type(r"^wlr_.*$")
        .whitelisted_type(r"^xkb_.*$")
        .whitelisted_type(r"^XKB_.*$")
        .whitelisted_function(r"^_?pixman_.*$")
        .whitelisted_function(r"^_?wlr_.*$")
        .whitelisted_function(r"^xkb_.*$")
        .ctypes_prefix("libc")
        .clang_arg("-Iwlroots/include")
        .clang_arg("-Iwlroots/include/wlr")
        // NOTE Necessary because they use the out directory to put
        // pragma information on what features are available in a header file
        // titled "config.h"
        .clang_arg(format!("-I{}{}", target_dir, "/include/"))
        .clang_arg(format!("-I{}", protocol_header_path.to_str().unwrap()))
        .clang_arg("-Iwlroots/include/xcursor")
        .clang_arg("-I/usr/include/pixman-1")
        // Work around bug https://github.com/rust-lang-nursery/rust-bindgen/issues/687
        .hide_type("FP_NAN")
        .hide_type("FP_INFINITE")
        .hide_type("FP_ZERO")
        .hide_type("FP_SUBNORMAL")
        .hide_type("FP_NORMAL");
    if cfg!(feature = "unstable") {
        builder = builder.clang_arg("-DWLR_USE_UNSTABLE");
    }
    if !cfg!(feature = "static") {
        // config.h won't exist, so make a dummy file.
        // We don't need it because of the following -D defines.
        fs::create_dir_all(format!("{}{}", target_dir, "/include/wlr/"))
            .expect("Could not create <out>/include/wlr");
        fs::File::create(format!("{}{}", target_dir, "/include/wlr/config.h"))
            .expect("Could not create dummy config.h file");
        // meson automatically sets up variables, but if we are linking
        // dynamically bindgen will no longer have them.
        builder = builder.clang_args(
            [
                format!("-DWLR_HAS_LIBCAP={}", cfg!(feature = "libcap") as u8),
                format!("-DWLR_HAS_SYSTEMD={}", cfg!(feature = "systemd") as u8),
                format!("-DWLR_HAS_ELOGIND={}", cfg!(feature = "elogind") as u8),
                format!("-DWLR_HAS_X11_BACKEND={}", cfg!(feature = "x11_backend") as u8),
                format!("-DWLR_HAS_XWAYLAND={}", cfg!(feature = "xwayland") as u8),
                format!("-DWLR_HAS_XCB_ERRORS={}", cfg!(feature = "xcb_errors") as u8),
                format!("-DWLR_HAS_XCB_ICCCM={}", cfg!(feature = "xcb_icccm") as u8)
            ]
            .iter()
        )
    }
    let generated = builder.generate().unwrap();

    println!("cargo:rustc-link-lib=dylib=X11");
    println!("cargo:rustc-link-lib=dylib=X11-xcb");
    println!("cargo:rustc-link-lib=dylib=xkbcommon");
    println!("cargo:rustc-link-lib=dylib=xcb");
    println!("cargo:rustc-link-lib=dylib=xcb-composite");
    println!("cargo:rustc-link-lib=dylib=xcb-xfixes");
    println!("cargo:rustc-link-lib=dylib=xcb-image");
    println!("cargo:rustc-link-lib=dylib=xcb-render");
    println!("cargo:rustc-link-lib=dylib=xcb-shm");
    println!("cargo:rustc-link-lib=dylib=xcb-icccm");
    println!("cargo:rustc-link-lib=dylib=xcb-xkb");
    println!("cargo:rustc-link-lib=dylib=xcb-xinput");
    println!("cargo:rustc-link-lib=dylib=wayland-egl");
    println!("cargo:rustc-link-lib=dylib=wayland-client");
    println!("cargo:rustc-link-lib=dylib=wayland-server");
    println!("cargo:rustc-link-lib=dylib=EGL");
    println!("cargo:rustc-link-lib=dylib=GL");
    println!("cargo:rustc-link-lib=dylib=gbm");
    println!("cargo:rustc-link-lib=dylib=drm");
    println!("cargo:rustc-link-lib=dylib=input");
    println!("cargo:rustc-link-lib=dylib=udev");
    println!("cargo:rustc-link-lib=dylib=dbus-1");
    println!("cargo:rustc-link-lib=dylib=pixman-1");

    link_optional_libs();

    if !cfg!(feature = "static") {
        println!("cargo:rustc-link-lib=dylib=wlroots");
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    // generate the bindings
    println!("cargo:rerun-if-changed={}", "src/gen.rs");
    generated.write_to_file("src/gen.rs").unwrap();

    generate_protocols();
}

#[cfg(not(feature = "static"))]
fn meson() {}

#[cfg(feature = "static")]
fn meson() {
    let build_path = PathBuf::from(env::var("OUT_DIR").expect("Could not get OUT_DIR env variable"));
    build_path.join("build");
    let build_path_str = build_path
        .to_str()
        .expect("Could not turn build path into a string");
    println!("cargo:rustc-link-search=native=wlroots");
    println!("cargo:rustc-link-search=native={}/lib", build_path_str);
    println!("cargo:rustc-link-search=native={}/lib64", build_path_str);
    println!("cargo:rustc-link-search=native={}/build/", build_path_str);
    if cfg!(feature = "static") {
        println!("cargo:rustc-link-search=native={}/util/", build_path_str);
        println!("cargo:rustc-link-search=native={}/types/", build_path_str);
        println!("cargo:rustc-link-search=native={}/protocol/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xcursor/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xwayland/", build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/", build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/x11", build_path_str);
        println!("cargo:rustc-link-search=native={}/render/", build_path_str);

        println!("cargo:rustc-link-lib=static=wlr_util");
        println!("cargo:rustc-link-lib=static=wlr_types");
        println!("cargo:rustc-link-lib=static=wlr_xcursor");
        println!("cargo:rustc-link-lib=static=wlr_xwayland");
        println!("cargo:rustc-link-lib=static=wlr_backend");
        println!("cargo:rustc-link-lib=static=wlr_backend_x11");
        println!("cargo:rustc-link-lib=static=wlr_render");
        println!("cargo:rustc-link-lib=static=wl_protos");
    }

    if Path::new("wlroots").exists() {
        meson::build("wlroots", build_path_str);
    } else {
        panic!("The `wlroots` submodule does not exist");
    }
}

/// Gets the unstable and stable protocols in /usr/share-wayland-protocols and
/// generates server headers for them.
///
/// The path to the folder with the generated headers is returned. It will
/// have two directories, `stable`, and `unstable`.
fn generate_protocol_headers() -> io::Result<PathBuf> {
    let output_dir_str = env::var("OUT_DIR").unwrap();
    let out_path: PathBuf = format!("{}/wayland-protocols", output_dir_str).into();
    fs::create_dir(&out_path).ok();
    let protocols_prefix = pkg_config::get_variable("wayland-protocols", "prefix").unwrap();
    let protocols = fs::read_dir(format!("{}/share/wayland-protocols/stable", protocols_prefix))?.chain(
        fs::read_dir(format!("{}/share/wayland-protocols/unstable", protocols_prefix))?
    );
    for entry in protocols {
        let entry = entry?;
        for entry in fs::read_dir(entry.path())? {
            let entry = entry?;
            let path = entry.path();
            let mut filename = entry.file_name().into_string().unwrap();
            if filename.ends_with(".xml") {
                let new_length = filename.len() - 4;
                filename.truncate(new_length);
            }
            filename.push_str("-protocol");
            Command::new("wayland-scanner")
                .arg("server-header")
                .arg(path.clone())
                .arg(format!("{}/{}.h", out_path.to_str().unwrap(), filename))
                .status()
                .unwrap();
        }
    }
    Ok(out_path)
}

fn generate_protocols() {
    let output_dir_str = env::var("OUT_DIR").unwrap();

    let output_dir = Path::new(&output_dir_str);

    let protocols = &[
        ("./wlroots/protocol/server-decoration.xml", "server_decoration"),
        (
            "./wlroots/protocol/wlr-gamma-control-unstable-v1.xml",
            "gamma_control"
        ),
        ("./wlroots/protocol/wlr-screencopy-unstable-v1.xml", "screencopy"),
        ("./wlroots/protocol/screenshooter.xml", "screenshooter"),
        ("./wlroots/protocol/idle.xml", "idle")
    ];

    for protocol in protocols {
        wayland_scanner::generate_c_code(
            protocol.0,
            output_dir.join(format!("{}_server_api.rs", protocol.1)),
            wayland_scanner::Side::Server
        );
        wayland_scanner::generate_c_code(
            protocol.0,
            output_dir.join(format!("{}_client_api.rs", protocol.1)),
            wayland_scanner::Side::Client
        );
        wayland_scanner::generate_c_interfaces(
            protocol.0,
            output_dir.join(format!("{}_interfaces.rs", protocol.1))
        );
    }
}

fn link_optional_libs() {
    if cfg!(feature = "libcap") && pkg_config::probe_library("libcap").is_ok() {
        println!("cargo:rustc-link-lib=dylib=cap");
    }
    if cfg!(feature = "systemd") && pkg_config::probe_library("libsystemd").is_ok() {
        println!("cargo:rustc-link-lib=dylib=systemd");
    }
    if cfg!(feature = "elogind") && pkg_config::probe_library("elogind").is_ok() {
        println!("cargo:rustc-link-lib=dylib=elogind");
    }
    if pkg_config::probe_library("xcb-errors").is_ok() {
        println!("cargo:rustc-link-lib=dylib=xcb-errors");
    }
}
<commit_msg>Removed redundant linker flag<commit_after>extern crate bindgen;
#[cfg(feature = "static")]
extern crate meson;
extern crate pkg_config;
extern crate wayland_scanner;

use std::path::{Path, PathBuf};
use std::process::Command;
use std::{env, fs, io};

fn main() {
    meson();
    let protocol_header_path =
        generate_protocol_headers().expect("Could not generate header files for wayland protocols");
    let target_dir = env::var("OUT_DIR").expect("$OUT_DIR not set!");
    let mut builder = bindgen::builder()
        .derive_debug(true)
        .derive_default(true)
        .generate_comments(true)
        .header("src/wlroots.h")
        .whitelisted_type(r"^wlr_.*$")
        .whitelisted_type(r"^xkb_.*$")
        .whitelisted_type(r"^XKB_.*$")
        .whitelisted_function(r"^_?pixman_.*$")
        .whitelisted_function(r"^_?wlr_.*$")
        .whitelisted_function(r"^xkb_.*$")
        .ctypes_prefix("libc")
        .clang_arg("-Iwlroots/include")
        .clang_arg("-Iwlroots/include/wlr")
        // NOTE Necessary because they use the out directory to put
        // pragma information on what features are available in a header file
        // titled "config.h"
        .clang_arg(format!("-I{}{}", target_dir, "/include/"))
        .clang_arg(format!("-I{}", protocol_header_path.to_str().unwrap()))
        .clang_arg("-Iwlroots/include/xcursor")
        .clang_arg("-I/usr/include/pixman-1")
        // Work around bug https://github.com/rust-lang-nursery/rust-bindgen/issues/687
        .hide_type("FP_NAN")
        .hide_type("FP_INFINITE")
        .hide_type("FP_ZERO")
        .hide_type("FP_SUBNORMAL")
        .hide_type("FP_NORMAL");
    if cfg!(feature = "unstable") {
        builder = builder.clang_arg("-DWLR_USE_UNSTABLE");
    }
    if !cfg!(feature = "static") {
        // config.h won't exist, so make a dummy file.
        // We don't need it because of the following -D defines.
        fs::create_dir_all(format!("{}{}", target_dir, "/include/wlr/"))
            .expect("Could not create <out>/include/wlr");
        fs::File::create(format!("{}{}", target_dir, "/include/wlr/config.h"))
            .expect("Could not create dummy config.h file");
        // meson automatically sets up variables, but if we are linking
        // dynamically bindgen will no longer have them.
        builder = builder.clang_args(
            [
                format!("-DWLR_HAS_LIBCAP={}", cfg!(feature = "libcap") as u8),
                format!("-DWLR_HAS_SYSTEMD={}", cfg!(feature = "systemd") as u8),
                format!("-DWLR_HAS_ELOGIND={}", cfg!(feature = "elogind") as u8),
                format!("-DWLR_HAS_X11_BACKEND={}", cfg!(feature = "x11_backend") as u8),
                format!("-DWLR_HAS_XWAYLAND={}", cfg!(feature = "xwayland") as u8),
                format!("-DWLR_HAS_XCB_ERRORS={}", cfg!(feature = "xcb_errors") as u8),
                format!("-DWLR_HAS_XCB_ICCCM={}", cfg!(feature = "xcb_icccm") as u8)
            ]
            .iter()
        )
    }
    let generated = builder.generate().unwrap();

    println!("cargo:rustc-link-lib=dylib=X11");
    println!("cargo:rustc-link-lib=dylib=X11-xcb");
    println!("cargo:rustc-link-lib=dylib=xkbcommon");
    println!("cargo:rustc-link-lib=dylib=xcb-composite");
    println!("cargo:rustc-link-lib=dylib=xcb-xfixes");
    println!("cargo:rustc-link-lib=dylib=xcb-image");
    println!("cargo:rustc-link-lib=dylib=xcb-render");
    println!("cargo:rustc-link-lib=dylib=xcb-shm");
    println!("cargo:rustc-link-lib=dylib=xcb-icccm");
    println!("cargo:rustc-link-lib=dylib=xcb-xkb");
    println!("cargo:rustc-link-lib=dylib=xcb-xinput");
    println!("cargo:rustc-link-lib=dylib=wayland-egl");
    println!("cargo:rustc-link-lib=dylib=wayland-client");
    println!("cargo:rustc-link-lib=dylib=wayland-server");
    println!("cargo:rustc-link-lib=dylib=EGL");
    println!("cargo:rustc-link-lib=dylib=GL");
    println!("cargo:rustc-link-lib=dylib=gbm");
    println!("cargo:rustc-link-lib=dylib=drm");
    println!("cargo:rustc-link-lib=dylib=input");
    println!("cargo:rustc-link-lib=dylib=udev");
    println!("cargo:rustc-link-lib=dylib=dbus-1");
    println!("cargo:rustc-link-lib=dylib=pixman-1");

    link_optional_libs();

    if !cfg!(feature = "static") {
        println!("cargo:rustc-link-lib=dylib=wlroots");
        println!("cargo:rustc-link-search=native=/usr/local/lib");
    }

    // generate the bindings
    println!("cargo:rerun-if-changed={}", "src/gen.rs");
    generated.write_to_file("src/gen.rs").unwrap();

    generate_protocols();
}

#[cfg(not(feature = "static"))]
fn meson() {}

#[cfg(feature = "static")]
fn meson() {
    let build_path = PathBuf::from(env::var("OUT_DIR").expect("Could not get OUT_DIR env variable"));
    build_path.join("build");
    let build_path_str = build_path
        .to_str()
        .expect("Could not turn build path into a string");
    println!("cargo:rustc-link-search=native=wlroots");
    println!("cargo:rustc-link-search=native={}/lib", build_path_str);
    println!("cargo:rustc-link-search=native={}/lib64", build_path_str);
    println!("cargo:rustc-link-search=native={}/build/", build_path_str);
    if cfg!(feature = "static") {
        println!("cargo:rustc-link-search=native={}/util/", build_path_str);
        println!("cargo:rustc-link-search=native={}/types/", build_path_str);
        println!("cargo:rustc-link-search=native={}/protocol/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xcursor/", build_path_str);
        println!("cargo:rustc-link-search=native={}/xwayland/", build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/", build_path_str);
        println!("cargo:rustc-link-search=native={}/backend/x11", build_path_str);
        println!("cargo:rustc-link-search=native={}/render/", build_path_str);

        println!("cargo:rustc-link-lib=static=wlr_util");
        println!("cargo:rustc-link-lib=static=wlr_types");
        println!("cargo:rustc-link-lib=static=wlr_xcursor");
        println!("cargo:rustc-link-lib=static=wlr_xwayland");
        println!("cargo:rustc-link-lib=static=wlr_backend");
        println!("cargo:rustc-link-lib=static=wlr_backend_x11");
        println!("cargo:rustc-link-lib=static=wlr_render");
        println!("cargo:rustc-link-lib=static=wl_protos");
    }

    if Path::new("wlroots").exists() {
        meson::build("wlroots", build_path_str);
    } else {
        panic!("The `wlroots` submodule does not exist");
    }
}

/// Gets the unstable and stable protocols in /usr/share-wayland-protocols and
/// generates server headers for them.
///
/// The path to the folder with the generated headers is returned. It will
/// have two directories, `stable`, and `unstable`.
fn generate_protocol_headers() -> io::Result<PathBuf> {
    let output_dir_str = env::var("OUT_DIR").unwrap();
    let out_path: PathBuf = format!("{}/wayland-protocols", output_dir_str).into();
    fs::create_dir(&out_path).ok();
    let protocols_prefix = pkg_config::get_variable("wayland-protocols", "prefix").unwrap();
    let protocols = fs::read_dir(format!("{}/share/wayland-protocols/stable", protocols_prefix))?.chain(
        fs::read_dir(format!("{}/share/wayland-protocols/unstable", protocols_prefix))?
    );
    for entry in protocols {
        let entry = entry?;
        for entry in fs::read_dir(entry.path())? {
            let entry = entry?;
            let path = entry.path();
            let mut filename = entry.file_name().into_string().unwrap();
            if filename.ends_with(".xml") {
                let new_length = filename.len() - 4;
                filename.truncate(new_length);
            }
            filename.push_str("-protocol");
            Command::new("wayland-scanner")
                .arg("server-header")
                .arg(path.clone())
                .arg(format!("{}/{}.h", out_path.to_str().unwrap(), filename))
                .status()
                .unwrap();
        }
    }
    Ok(out_path)
}

fn generate_protocols() {
    let output_dir_str = env::var("OUT_DIR").unwrap();

    let output_dir = Path::new(&output_dir_str);

    let protocols = &[
        ("./wlroots/protocol/server-decoration.xml", "server_decoration"),
        (
            "./wlroots/protocol/wlr-gamma-control-unstable-v1.xml",
            "gamma_control"
        ),
        ("./wlroots/protocol/wlr-screencopy-unstable-v1.xml", "screencopy"),
        ("./wlroots/protocol/screenshooter.xml", "screenshooter"),
        ("./wlroots/protocol/idle.xml", "idle")
    ];

    for protocol in protocols {
        wayland_scanner::generate_c_code(
            protocol.0,
            output_dir.join(format!("{}_server_api.rs", protocol.1)),
            wayland_scanner::Side::Server
        );
        wayland_scanner::generate_c_code(
            protocol.0,
            output_dir.join(format!("{}_client_api.rs", protocol.1)),
            wayland_scanner::Side::Client
        );
        wayland_scanner::generate_c_interfaces(
            protocol.0,
            output_dir.join(format!("{}_interfaces.rs", protocol.1))
        );
    }
}

fn link_optional_libs() {
    if cfg!(feature = "libcap") && pkg_config::probe_library("libcap").is_ok() {
        println!("cargo:rustc-link-lib=dylib=cap");
    }
    if cfg!(feature = "systemd") && pkg_config::probe_library("libsystemd").is_ok() {
        println!("cargo:rustc-link-lib=dylib=systemd");
    }
    if cfg!(feature = "elogind") && pkg_config::probe_library("elogind").is_ok() {
        println!("cargo:rustc-link-lib=dylib=elogind");
    }
    if pkg_config::probe_library("xcb-errors").is_ok() {
        println!("cargo:rustc-link-lib=dylib=xcb-errors");
    }
}
<|endoftext|>


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

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("SVG", inherited=False, gecko_name="SVGReset") %>

// TODO: Which of these should be animatable properties?
${helpers.single_keyword("dominant-baseline",
                 """auto use-script no-change reset-size ideographic alphabetic hanging
                    mathematical central middle text-after-edge text-before-edge""",
                 products="gecko",
                 animatable=False)}

${helpers.single_keyword("vector-effect", "none non-scaling-stroke",
                         products="gecko", animatable=False)}

// Section 13 - Gradients and Patterns

${helpers.predefined_type(
    "stop-color", "CSSColor",
    "CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
    products="gecko",
    animatable=False)}

${helpers.predefined_type("stop-opacity", "Opacity", "1.0",
                          products="gecko",
                          animatable=False)}

// Section 15 - Filter Effects

${helpers.predefined_type(
    "flood-color", "CSSColor",
    "CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
    products="gecko",
    animatable=False)}

${helpers.predefined_type("flood-opacity", "Opacity",
                          "1.0", products="gecko", animatable=False)}

${helpers.predefined_type(
    "lighting-color", "CSSColor",
    "CSSParserColor::RGBA(RGBA { red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0 })",
    products="gecko",
    animatable=False)}

// CSS Masking Module Level 1
// https://www.w3.org/TR/css-masking-1/
${helpers.single_keyword("mask-type", "luminance alpha",
                         products="gecko", animatable=False)}
<commit_msg>Add clip-path<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

<%namespace name="helpers" file="/helpers.mako.rs" />

<% data.new_style_struct("SVG", inherited=False, gecko_name="SVGReset") %>

// TODO: Which of these should be animatable properties?
${helpers.single_keyword("dominant-baseline",
                 """auto use-script no-change reset-size ideographic alphabetic hanging
                    mathematical central middle text-after-edge text-before-edge""",
                 products="gecko",
                 animatable=False)}

${helpers.single_keyword("vector-effect", "none non-scaling-stroke",
                         products="gecko", animatable=False)}

// Section 13 - Gradients and Patterns

${helpers.predefined_type(
    "stop-color", "CSSColor",
    "CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
    products="gecko",
    animatable=False)}

${helpers.predefined_type("stop-opacity", "Opacity", "1.0",
                          products="gecko",
                          animatable=False)}

// Section 15 - Filter Effects

${helpers.predefined_type(
    "flood-color", "CSSColor",
    "CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
    products="gecko",
    animatable=False)}

${helpers.predefined_type("flood-opacity", "Opacity",
                          "1.0", products="gecko", animatable=False)}

${helpers.predefined_type(
    "lighting-color", "CSSColor",
    "CSSParserColor::RGBA(RGBA { red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0 })",
    products="gecko",
    animatable=False)}

// CSS Masking Module Level 1
// https://www.w3.org/TR/css-masking-1/
${helpers.single_keyword("mask-type", "luminance alpha",
                         products="gecko", animatable=False)}

<%helpers:longhand name="clip-path" animatable="False" products="gecko">
    use cssparser::ToCss;
    use std::fmt;
    use values::LocalToCss;
    use values::NoViewportPercentage;
    use values::specified::basic_shape::{ShapeSource, GeometryBox};

    pub mod computed_value {
        use app_units::Au;
        use values::computed::basic_shape::{ShapeSource, GeometryBox};

        pub type T = ShapeSource<GeometryBox>;
    }

    pub type SpecifiedValue = ShapeSource<GeometryBox>;

    #[inline]
    pub fn get_initial_value() -> computed_value::T {
        Default::default()
    }

    pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
        ShapeSource::parse(context, input)
    }

    impl NoViewportPercentage for SpecifiedValue {}
</%helpers:longhand>
<|endoftext|>


<commit_before>use command_line_parser::CommandLineParser;
use std::collections::vec_deque::VecDeque;
use std::str::FromStr;

impl CommandLineParser for bool {
    fn parse(args: &mut VecDeque<String>) -> Self {
        let arg = match args.pop_front() {
            Some(arg) => {
                arg
            },
            None => {
                panic!("Error popping arg queue in bool CommandLineParser. Queue is probably empty.");
            },
        };

        let result = match bool::from_str(arg.as_ref()) {
            Ok(result) => {
                result
            },
            Err(err) => {
                panic!("Error parsing arg in bool CommandLineParser: {}", err);
            },
        };

        result
    }
}

impl CommandLineParser for String {
    fn parse(args: &mut VecDeque<String>) -> Self {
        let arg = match args.pop_front() {
            Some(arg) => {
                arg
            },
            None => {
                panic!("Error popping arg queue in bool CommandLineParser. Queue is probably empty.");
            },
        };

        arg
    }
}

impl <T0, T1> CommandLineParser for (T0, T1)
    where T0: CommandLineParser,
          T1: CommandLineParser {
    fn parse(args: &mut VecDeque<String>) -> Self {
        (T0::parse(args), T1::parse(args))
    }
}
<commit_msg>Added command line parsers for usize and vec.<commit_after>use command_line_parser::CommandLineParser;
use std::collections::vec_deque::VecDeque;
use std::str::FromStr;

impl CommandLineParser for bool {
    fn parse(args: &mut VecDeque<String>) -> Self {
        let arg = match args.pop_front() {
            Some(arg) => {
                arg
            },
            None => {
                panic!("Error popping arg queue in bool CommandLineParser. Queue is probably empty.");
            },
        };

        let result = match bool::from_str(arg.as_ref()) {
            Ok(result) => {
                result
            },
            Err(err) => {
                panic!("Error parsing arg in bool CommandLineParser: {}", err);
            },
        };

        result
    }
}

impl CommandLineParser for usize {
    fn parse(args: &mut VecDeque<String>) -> Self {
        let arg = match args.pop_front() {
            Some(arg) => {
                arg
            },
            None => {
                panic!("Error popping arg queue in u8 CommandLineParser. Queue is probably empty.");
            },
        };

        let result = match usize::from_str(arg.as_ref()) {
            Ok(result) => {
                result
            },
            Err(err) => {
                panic!("Error parsing arg in u8 CommandLineParser: {}", err);
            },
        };

        result
    }
}

impl CommandLineParser for String {
    fn parse(args: &mut VecDeque<String>) -> Self {
        let arg = match args.pop_front() {
            Some(arg) => {
                arg
            },
            None => {
                panic!("Error popping arg queue in bool CommandLineParser. Queue is probably empty.");
            },
        };

        arg
    }
}

impl <T> CommandLineParser for Vec<T>
    where T: CommandLineParser {
    fn parse(args: &mut VecDeque<String>) -> Self {
        let len = usize::parse(args);
        [0..len].iter()
                .map(
                    |_| {
                        T::parse(args)
                    }
                )
                .collect()
    }
}

impl <T0, T1> CommandLineParser for (T0, T1)
    where T0: CommandLineParser,
          T1: CommandLineParser {
    fn parse(args: &mut VecDeque<String>) -> Self {
        (T0::parse(args), T1::parse(args))
    }
}
<|endoftext|>


<commit_before>use http::status::{ NotFound, BadRequest, InternalServerError };
use request::Request;
use response::Response;
use middleware::{Halt, ErrorHandler, MiddlewareResult};
use nickel_error::{ NickelError, ErrorWithStatusCode };

#[deriving(Clone)]
pub struct DefaultErrorHandler;

impl ErrorHandler for DefaultErrorHandler {
    fn invoke(&self, err: &NickelError, _req: &mut Request, res: &mut Response) -> MiddlewareResult {
        match err.kind {
            ErrorWithStatusCode(NotFound) => {
                res.origin.status = NotFound;
                res.send("Not Found");
                Ok(Halt)
            },
            ErrorWithStatusCode(BadRequest) => {
                res.origin.status = BadRequest;
                res.send("Bad Request");
                Ok(Halt)
            }
            _ => {
                res.origin.status = InternalServerError;
                res.send("Internal Server Error");
                Ok(Halt)
            }
        }
    }
}
<commit_msg>refactor(default_error): simplify default_error_handler<commit_after>use http::status::{NotFound, BadRequest, InternalServerError};
use request::Request;
use response::Response;
use ResponseFinalizer;
use middleware::{ErrorHandler, MiddlewareResult};
use nickel_error::{NickelError, ErrorWithStatusCode};

#[deriving(Clone)]
pub struct DefaultErrorHandler;

impl ErrorHandler for DefaultErrorHandler {
    fn invoke(&self, err: &NickelError, _req: &mut Request, res: &mut Response) -> MiddlewareResult {
        let r = match err.kind {
            ErrorWithStatusCode(NotFound) => (NotFound, "Not Found"),
            ErrorWithStatusCode(BadRequest) => (BadRequest, "Bad Request"),
            _ => (InternalServerError, "Internal Server Error")
        };

        r.respond(res)
    }
}
<|endoftext|>