<commit_before>// DOCS

#![allow(unstable)]
#![feature(plugin)]
#[plugin] extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

pub struct Property {
    /// Parameters.
    pub params: HashMap<String, String>,

    /// Value as unparsed string.
    pub raw_value: String,

    /// Property group. E.g. a contentline like `foo.FN:Markus` would result in the group being
    /// `"foo"`.
    pub prop_group: Option<String>
}

impl Property {
    pub fn new(params: HashMap<String, String>, raw_value: String, prop_group: Option<String>) -> Property {
        Property {
            params: params,
            raw_value: raw_value,
            prop_group: prop_group
        }
    }

    /// Create property from unescaped string.
    pub fn new_from_string(s: &str) -> Property {
        Property::new(HashMap::new(), escape_chars(s), None)
    }

    /// Get value as unescaped string.
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.raw_value.as_slice())
    }
}

pub struct Component {
    /// The name of the component, such as `VCARD` or `VEVENT`.
    pub name: String,

    /// The component's properties.
    pub props: HashMap<String, Vec<Property>>,

    /// The component's child- or sub-components.
    pub subcomponents: Vec<Component>
}

impl Component {
    pub fn new(name: String) -> Component {
        Component {
            name: name,
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    /// Retrieve one property (from many) by key. Returns `None` if nothing is found.
    pub fn single_prop(&self, key: &str) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    /// Retrieve a mutable vector of properties for this key. Creates one (and inserts it into the
    /// component) if none exists.
    pub fn all_props_mut(&mut self, key: &str) -> &mut Vec<Property> {
        match self.props.entry(String::from_str(key)) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.insert(vec![])
        }
    }

    /// Retrieve properties by key. Returns an empty slice if key doesn't exist.
    pub fn all_props(&self, key: &str) -> &[Property] {
        static EMPTY: &'static [Property] = &[];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

#[pub]
component -> Component
    = name:component_begin
      ps:props
      cs:components?
      component_end {
        let mut rv = Component::new(name);

        match cs {
            Some(components) => { rv.subcomponents = components; },
            None => ()
        };

        for (k, v) in ps.into_iter() {
            rv.all_props_mut(k).push(v);
        };

        rv
    }

component_begin -> String
    = "BEGIN:" v:value __ { v.to_string() }

component_end -> String
    = "END:" v:value __ { v.to_string() }

components -> Vec<Component>
    = cs:component ++ eols __ { cs }

props -> Vec<(&'input str, Property)>
    = ps:prop ++ eols __ { ps }

prop -> (&'input str, Property)
    = !"BEGIN:" !"END:" g:group? k:name p:params ":" v:value {
        (k, Property::new(p, v, g))
    }

group -> String
    = g:group_name "." { g }

group_name -> String
    = group_char+ { match_str.to_string() }

name -> &'input str
    = iana_token+ { match_str }

params -> HashMap<String, String>
    = ps:(";" p:param {p})* {
        let mut rv: HashMap<String, String> = HashMap::with_capacity(ps.len());
        rv.extend(ps.into_iter().map(|(k, v)| (k.to_string(), v.to_string())));
        rv
    }

param -> (&'input str, &'input str)
    // FIXME: Doesn't handle comma-separated values
    = k:param_name v:("=" v:param_value { v })? {
        (k, match v {
            Some(x) => x,
            None => ""
        })
    }

param_name -> &'input str
    = iana_token+ { match_str }

param_value -> &'input str
    = x:(quoted_string / param_text) { x }

param_text -> &'input str
    = safe_char* { match_str }

value -> String
    = value_char+ { match_str.to_string() }

quoted_string -> &'input str
    = dquote x:quoted_content dquote { x }

quoted_content -> &'input str
    = qsafe_char* { match_str }

iana_token = ([a-zA-Z0-9] / "-")+
group_char = ([a-zA-Z0-9] / "-")
qsafe_char = !dquote !ctl value_char
safe_char = !";" !":" qsafe_char

value_char = !eol .

eol = "\r\n" / "\n" / "\r"
dquote = "\""
eols = eol+

// Taken from vCard. vCalendar's is a subset. Together with the definition of "qsafe_char" this
// might reject a bunch of valid iCalendars, but I can't imagine one.
ctl = [\u{00}-\u{1F}] / "\u{7F}"

whitespace = " " / "\t"
__ = (eol / whitespace)*

"#);

/// Parse a component. The error value is a human-readable message.
pub fn parse_component(s: &str) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = unfold_lines(s);
    parser::component(unfolded.as_slice())
}

/// Write a component. The error value is a human-readable message.
pub fn write_component(c: &Component) -> String {
    fn inner(buf: &mut String, c: &Component) {
        buf.push_str("BEGIN:");
        buf.push_str(c.name.as_slice());
        buf.push_str("\r\n");

        for (prop_name, props) in c.props.iter() {
            for prop in props.iter() {
                match prop.prop_group {
                    Some(ref x) => { buf.push_str(x.as_slice()); buf.push('.'); },
                    None => ()
                };
                buf.push_str(prop_name.as_slice());
                for (param_key, param_value) in prop.params.iter() {
                    buf.push(';');
                    buf.push_str(param_key.as_slice());
                    buf.push('=');
                    buf.push_str(param_value.as_slice());
                };
                buf.push(':');
                buf.push_str(fold_line(prop.raw_value.as_slice()).as_slice());
                buf.push_str("\r\n");
            };
        };

        for subcomponent in c.subcomponents.iter() {
            inner(buf, subcomponent);
        };

        buf.push_str("END:");
        buf.push_str(c.name.as_slice());
        buf.push_str("\r\n");
    }

    let mut buf = String::new();
    inner(&mut buf, c);
    buf
}

/// Escape text for a VObject property value.
pub fn escape_chars(s: &str) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

/// Unescape text from a VObject property value.
pub fn unescape_chars(s: &str) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}

/// Unfold contentline.
pub fn unfold_lines(s: &str) -> String {
    s
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r ", "").replace("\r\t", "")
}

/// Fold contentline to 75 chars. This function assumes the input to be unfolded, which means no
/// '\n' or '\r' in it.
pub fn fold_line(s: &str) -> String {
    let mut rv = String::new();
    for (i, c) in s.chars().enumerate() {
        rv.push(c);
        if i != 0 && i % 75 == 0 {
            rv.push_str("\r\n ");
        };
    };
    rv
}
<commit_msg>Property::new is consistent with Component::new<commit_after>// DOCS

#![allow(unstable)]
#![feature(plugin)]
#[plugin] extern crate peg_syntax_ext;

use std::collections::HashMap;
use std::collections::hash_map::Entry::{Occupied, Vacant};

pub struct Property {
    /// Parameters.
    pub params: HashMap<String, String>,

    /// Value as unparsed string.
    pub raw_value: String,

    /// Property group. E.g. a contentline like `foo.FN:Markus` would result in the group being
    /// `"foo"`.
    pub prop_group: Option<String>
}

impl Property {
    /// Create property from unescaped string.
    pub fn new(value: &str) -> Property {
        Property {
            params: HashMap::new(),
            raw_value: escape_chars(value),
            prop_group: None
        }
    }

    /// Get value as unescaped string.
    pub fn value_as_string(&self) -> String {
        unescape_chars(self.raw_value.as_slice())
    }
}

pub struct Component {
    /// The name of the component, such as `VCARD` or `VEVENT`.
    pub name: String,

    /// The component's properties.
    pub props: HashMap<String, Vec<Property>>,

    /// The component's child- or sub-components.
    pub subcomponents: Vec<Component>
}

impl Component {
    pub fn new(name: String) -> Component {
        Component {
            name: name,
            props: HashMap::new(),
            subcomponents: vec![]
        }
    }

    /// Retrieve one property (from many) by key. Returns `None` if nothing is found.
    pub fn single_prop(&self, key: &str) -> Option<&Property> {
        match self.props.get(key) {
            Some(x) => {
                match x.len() {
                    1 => Some(&x[0]),
                    _ => None
                }
            },
            None => None
        }
    }

    /// Retrieve a mutable vector of properties for this key. Creates one (and inserts it into the
    /// component) if none exists.
    pub fn all_props_mut(&mut self, key: &str) -> &mut Vec<Property> {
        match self.props.entry(String::from_str(key)) {
            Occupied(values) => values.into_mut(),
            Vacant(values) => values.insert(vec![])
        }
    }

    /// Retrieve properties by key. Returns an empty slice if key doesn't exist.
    pub fn all_props(&self, key: &str) -> &[Property] {
        static EMPTY: &'static [Property] = &[];
        match self.props.get(key) {
            Some(values) => values.as_slice(),
            None => EMPTY
        }
    }
}

peg! parser(r#"
use super::{Component,Property};
use std::collections::HashMap;

#[pub]
component -> Component
    = name:component_begin
      ps:props
      cs:components
      component_end {
        let mut rv = Component::new(name);
        rv.subcomponents = cs;

        for (k, v) in ps.into_iter() {
            rv.all_props_mut(k).push(v);
        };

        rv
    }

component_begin -> String
    = "BEGIN:" v:value __ { v.to_string() }

component_end -> String
    = "END:" v:value __ { v.to_string() }

components -> Vec<Component>
    = cs:component ** eols __ { cs }

props -> Vec<(&'input str, Property)>
    = ps:prop ++ eols __ { ps }

prop -> (&'input str, Property)
    = !"BEGIN:" !"END:" g:group? k:name p:params ":" v:value {
        (k, Property { params: p, raw_value: v, prop_group: g })
    }

group -> String
    = g:group_name "." { g }

group_name -> String
    = group_char+ { match_str.to_string() }

name -> &'input str
    = iana_token+ { match_str }

params -> HashMap<String, String>
    = ps:(";" p:param {p})* {
        let mut rv: HashMap<String, String> = HashMap::with_capacity(ps.len());
        rv.extend(ps.into_iter().map(|(k, v)| (k.to_string(), v.to_string())));
        rv
    }

param -> (&'input str, &'input str)
    // FIXME: Doesn't handle comma-separated values
    = k:param_name v:("=" v:param_value { v })? {
        (k, match v {
            Some(x) => x,
            None => ""
        })
    }

param_name -> &'input str
    = iana_token+ { match_str }

param_value -> &'input str
    = x:(quoted_string / param_text) { x }

param_text -> &'input str
    = safe_char* { match_str }

value -> String
    = value_char+ { match_str.to_string() }

quoted_string -> &'input str
    = dquote x:quoted_content dquote { x }

quoted_content -> &'input str
    = qsafe_char* { match_str }

iana_token = ([a-zA-Z0-9] / "-")+
group_char = ([a-zA-Z0-9] / "-")
qsafe_char = !dquote !ctl value_char
safe_char = !";" !":" qsafe_char

value_char = !eol .

eol = "\r\n" / "\n" / "\r"
dquote = "\""
eols = eol+

// Taken from vCard. vCalendar's is a subset. Together with the definition of "qsafe_char" this
// might reject a bunch of valid iCalendars, but I can't imagine one.
ctl = [\u{00}-\u{1F}] / "\u{7F}"

whitespace = " " / "\t"
__ = (eol / whitespace)*

"#);

/// Parse a component. The error value is a human-readable message.
pub fn parse_component(s: &str) -> Result<Component, String> {
    // XXX: The unfolding should be worked into the PEG
    // See feature request: https://github.com/kevinmehall/rust-peg/issues/26
    let unfolded = unfold_lines(s);
    parser::component(unfolded.as_slice())
}

/// Write a component. The error value is a human-readable message.
pub fn write_component(c: &Component) -> String {
    fn inner(buf: &mut String, c: &Component) {
        buf.push_str("BEGIN:");
        buf.push_str(c.name.as_slice());
        buf.push_str("\r\n");

        for (prop_name, props) in c.props.iter() {
            for prop in props.iter() {
                match prop.prop_group {
                    Some(ref x) => { buf.push_str(x.as_slice()); buf.push('.'); },
                    None => ()
                };
                buf.push_str(prop_name.as_slice());
                for (param_key, param_value) in prop.params.iter() {
                    buf.push(';');
                    buf.push_str(param_key.as_slice());
                    buf.push('=');
                    buf.push_str(param_value.as_slice());
                };
                buf.push(':');
                buf.push_str(fold_line(prop.raw_value.as_slice()).as_slice());
                buf.push_str("\r\n");
            };
        };

        for subcomponent in c.subcomponents.iter() {
            inner(buf, subcomponent);
        };

        buf.push_str("END:");
        buf.push_str(c.name.as_slice());
        buf.push_str("\r\n");
    }

    let mut buf = String::new();
    inner(&mut buf, c);
    buf
}

/// Escape text for a VObject property value.
pub fn escape_chars(s: &str) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\n")
        .replace("\\", "\\\\")
        .replace(";", "\\;")
        .replace(",", "\\,")
        .replace("\r\n", "\\n")
        .replace("\n", "\\n")
}

/// Unescape text from a VObject property value.
pub fn unescape_chars(s: &str) -> String {
    // Order matters! Lifted from icalendar.parser
    // https://github.com/collective/icalendar/
    s
        .replace("\\N", "\\n")
        .replace("\r\n", "\n")
        .replace("\\n", "\n")
        .replace("\\,", ",")
        .replace("\\;", ";")
        .replace("\\\\", "\\")
}

/// Unfold contentline.
pub fn unfold_lines(s: &str) -> String {
    s
        .replace("\r\n ", "").replace("\r\n\t", "")
        .replace("\n ", "").replace("\n\t", "")
        .replace("\r ", "").replace("\r\t", "")
}

/// Fold contentline to 75 chars. This function assumes the input to be unfolded, which means no
/// '\n' or '\r' in it.
pub fn fold_line(s: &str) -> String {
    let mut rv = String::new();
    for (i, c) in s.chars().enumerate() {
        rv.push(c);
        if i != 0 && i % 75 == 0 {
            rv.push_str("\r\n ");
        };
    };
    rv
}
<|endoftext|>


<commit_before>use rand::{Rng, Closed01};

/// Represents a connection weight.
pub struct Weight(pub f64);

/// Represents the range within a connection weight can be.
pub enum WeightRange {
    /// Bipolar weight range is within [-magnitude, +magnitude].
    Bipolar {magnitude: f64},
    /// Unipolar weight range is within [0, +magnitude].
    Unipolar {magnitude: f64}
}

impl WeightRange {
    pub fn random_weight<R: Rng>(&self, rng: &mut R) -> Weight {
       let w: Closed01<f64> = rng.gen(); // f64 in the range [0, 1]
       match *self {
           WeightRange::Bipolar {magnitude} => {
               let w = Weight((2.0 * magnitude * w.0) - magnitude);
               debug_assert!(w.0 >= -(magnitude.abs()) && w.0 <= magnitude.abs());
               w
           }
           WeightRange::Unipolar {magnitude} => {
               let w = Weight(magnitude * w.0);
               if magnitude > 0.0 {
                   debug_assert!(w.0 >= 0.0 && w.0 <= magnitude);
               } else {
                   debug_assert!(w.0 >= magnitude && w.0 <= 0.0);
               }
               w
           }
       }
    }

    pub fn clip_weight(&self, weight: Weight) -> Weight {
        match *self {
            WeightRange::Bipolar {magnitude} => {
            }
            WeightRange::Unipolar {magnitude} => {
            }
        }
    }
}

/// Defines a perturbance method.
pub enum WeightPerturbanceMethod {
    JiggleUniform  {magnitude: f64},
    JiggleGaussian {sigma: f64},
    Random,
}

impl WeightPerturbanceMethod {
    pub fn perturb<R: Rng>(&self, weight: Weight, range: &WeightRange, rng: &mut R) -> Weight {
        match *self {
            WeightPerturbanceMethod::Random => {
                range.random_weight(rng)
            }
            WeightPerturbanceMethod::JiggleUniform { magnitude } => {
                unimplemented!()
            }
            WeightPerturbanceMethod::JiggleGaussian {sigma} => {
                unimplemented!()
            }
        }
    }
}
<commit_msg>Refactor the weight<commit_after>use rand::{Rng, Closed01};

/// Represents a connection weight.
#[derive(Debug, Clone, Copy)]
pub struct Weight(pub f64);

/// Represents the range of a connection weight. The range is closed,
/// i.e. including both endpoints [low, high].
#[derive(Debug, Clone, Copy)]
pub struct WeightRange {
    high: f64,
    low: f64,
}

impl WeightRange {
    pub fn new(high: f64, low: f64) -> WeightRange {
        assert!(high >= low);
        WeightRange {
            high: high,
            low: low,
        }
    }

    pub fn unipolar(magnitude: f64) -> WeightRange {
        if magnitude >= 0.0 {
            WeightRange {
                high: magnitude,
                low: 0.0,
            }
        } else {
            WeightRange {
                high: 0.0,
                low: magnitude,
            }
        }
    }

    pub fn bipolar(magnitude: f64) -> WeightRange {
        assert!(magnitude >= 0.0);
        WeightRange {
            high: magnitude,
            low: -magnitude,
        }
    }

    pub fn in_range(&self, weight: Weight) -> bool {
        weight.0 >= self.low && weight.0 <= self.high
    }

    pub fn random_weight<R: Rng>(&self, rng: &mut R) -> Weight {
        let w = rng.gen::<Closed01<f64>>().0;
        debug_assert!(w >= 0.0 && w <= 1.0);

        let weight = Weight(((self.high - self.low) * w) + self.low);

        debug_assert!(self.in_range(weight));

        weight
    }

    pub fn clip_weight(&self, weight: Weight) -> Weight {
        let clipped = if weight.0 >= self.high {
            Weight(self.high)
        } else if weight.0 <= self.low {
            Weight(self.low)
        } else {
            weight
        };

        debug_assert!(self.in_range(clipped));

        clipped
    }
}

/// Defines a perturbance method.
pub enum WeightPerturbanceMethod {
    JiggleUniform {
        range: WeightRange,
    },
    JiggleGaussian {
        sigma: f64,
    },
    Random,
}

impl WeightPerturbanceMethod {
    pub fn perturb<R: Rng>(&self,
                           weight: Weight,
                           weight_range: &WeightRange,
                           rng: &mut R)
                           -> Weight {
        match *self {
            WeightPerturbanceMethod::Random => weight_range.random_weight(rng),
            WeightPerturbanceMethod::JiggleUniform { range } => {
                weight_range.clip_weight(Weight(weight.0 + range.random_weight(rng).0))
            }
            WeightPerturbanceMethod::JiggleGaussian {..} => unimplemented!(),
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::convert::From;
use std::fmt::{self, Display};
use std::ops::Deref;

use gl;
use glutin::{self, ContextBuilder, ControlFlow, CursorState, Event, EventsLoop,
             MouseCursor as GlutinMouseCursor, WindowBuilder};
use glutin::GlContext;

use MouseCursor;

use config::WindowConfig;

/// Window errors
#[derive(Debug)]
pub enum Error {
    /// Error creating the window
    ContextCreation(glutin::CreationError),

    /// Error manipulating the rendering context
    Context(glutin::ContextError),
}

/// Result of fallible operations concerning a Window.
type Result<T> = ::std::result::Result<T, Error>;

/// A window which can be used for displaying the terminal
///
/// Wraps the underlying windowing library to provide a stable API in Alacritty
pub struct Window {
    event_loop: EventsLoop,
    window: glutin::GlWindow,
    cursor_visible: bool,

    /// Whether or not the window is the focused window.
    pub is_focused: bool,
}

/// Threadsafe APIs for the window
pub struct Proxy {
    inner: glutin::EventsLoopProxy,
}

/// Information about where the window is being displayed
///
/// Useful for subsystems like the font rasterized which depend on DPI and scale
/// factor.
pub struct DeviceProperties {
    /// Scale factor for pixels <-> points.
    ///
    /// This will be 1. on standard displays and may have a different value on
    /// hidpi displays.
    pub scale_factor: f32,
}

/// Size of the window
#[derive(Debug, Copy, Clone)]
pub struct Size<T> {
    pub width: T,
    pub height: T,
}

/// Strongly typed Pixels unit
#[derive(Debug, Copy, Clone)]
pub struct Pixels<T>(pub T);

/// Strongly typed Points unit
///
/// Points are like pixels but adjusted for DPI.
#[derive(Debug, Copy, Clone)]
pub struct Points<T>(pub T);

pub trait ToPoints {
    fn to_points(&self, scale: f32) -> Size<Points<u32>>;
}

impl ToPoints for Size<Points<u32>> {
    #[inline]
    fn to_points(&self, _scale: f32) -> Size<Points<u32>> {
        *self
    }
}

impl ToPoints for Size<Pixels<u32>> {
    fn to_points(&self, scale: f32) -> Size<Points<u32>> {
        let width_pts = (*self.width as f32 / scale) as u32;
        let height_pts = (*self.height as f32 / scale) as u32;

        Size {
            width: Points(width_pts),
            height: Points(height_pts)
        }
    }
}

impl<T: Display> Display for Size<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} × {}", self.width, self.height)
    }
}

macro_rules! deref_newtype {
    ($($src:ty),+) => {
        $(
        impl<T> Deref for $src {
            type Target = T;

            #[inline]
            fn deref(&self) -> &Self::Target {
                &self.0
            }
        }
        )+
    }
}

deref_newtype! { Points<T>, Pixels<T> }

impl<T: Display> Display for Pixels<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}px", self.0)
    }
}

impl<T: Display> Display for Points<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}pts", self.0)
    }
}

impl ::std::error::Error for Error {
    fn cause(&self) -> Option<&::std::error::Error> {
        match *self {
            Error::ContextCreation(ref err) => Some(err),
            Error::Context(ref err) => Some(err),
        }
    }

    fn description(&self) -> &str {
        match *self {
            Error::ContextCreation(ref _err) => "Error creating gl context",
            Error::Context(ref _err) => "Error operating on render context",
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Error::ContextCreation(ref err) => {
                write!(f, "Error creating GL context; {}", err)
            },
            Error::Context(ref err) => {
                write!(f, "Error operating on render context; {}", err)
            },
        }
    }
}

impl From<glutin::CreationError> for Error {
    fn from(val: glutin::CreationError) -> Error {
        Error::ContextCreation(val)
    }
}

impl From<glutin::ContextError> for Error {
    fn from(val: glutin::ContextError) -> Error {
        Error::Context(val)
    }
}

impl Window {
    /// Create a new window
    ///
    /// This creates a window and fully initializes a window.
    pub fn new(
        title: &str,
        window_config: &WindowConfig,
    ) -> Result<Window> {
        let event_loop = EventsLoop::new();

        Window::platform_window_init();
        let window = WindowBuilder::new()
            .with_title(title)
            .with_visibility(false)
            .with_transparency(true)
            .with_decorations(window_config.decorations());
        let context = ContextBuilder::new()
            .with_srgb(true)
            .with_vsync(true);
        let window = ::glutin::GlWindow::new(window, context, &event_loop)?;
        window.show();

        // Text cursor
        window.set_cursor(GlutinMouseCursor::Text);

        // Set OpenGL symbol loader
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

        // Make the context current so OpenGL operations can run
        unsafe {
            window.make_current()?;
        }

        let window = Window {
            event_loop,
            window,
            cursor_visible: true,
            is_focused: true,
        };

        window.run_os_extensions();

        Ok(window)
    }

    /// Get some properties about the device
    ///
    /// Some window properties are provided since subsystems like font
    /// rasterization depend on DPI and scale factor.
    pub fn device_properties(&self) -> DeviceProperties {
        DeviceProperties {
            scale_factor: self.window.hidpi_factor(),
        }
    }

    pub fn inner_size_pixels(&self) -> Option<Size<Pixels<u32>>> {
        self.window
            .get_inner_size()
            .map(|(w, h)| Size { width: Pixels(w), height: Pixels(h) })
    }

    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
        self.window.hidpi_factor()
    }

    #[inline]
    pub fn create_window_proxy(&self) -> Proxy {
        Proxy {
            inner: self.event_loop.create_proxy(),
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<()> {
        self.window
            .swap_buffers()
            .map_err(From::from)
    }

    /// Poll for any available events
    #[inline]
    pub fn poll_events<F>(&mut self, func: F)
        where F: FnMut(Event)
    {
        self.event_loop.poll_events(func);
    }

    #[inline]
    pub fn resize(&self, width: u32, height: u32) {
        self.window.resize(width, height);
    }

    /// Block waiting for events
    #[inline]
    pub fn wait_events<F>(&mut self, func: F)
        where F: FnMut(Event) -> ControlFlow
    {
        self.event_loop.run_forever(func);
    }

    /// Set the window title
    #[inline]
    pub fn set_title(&self, title: &str) {
        self.window.set_title(title);
    }

    #[inline]
    pub fn set_mouse_cursor(&self, cursor: MouseCursor) {
        self.window.set_cursor(match cursor {
            MouseCursor::Arrow => GlutinMouseCursor::Arrow,
            MouseCursor::Text => GlutinMouseCursor::Text,
        });
    }

    /// Set cursor visible
    pub fn set_cursor_visible(&mut self, visible: bool) {
        if visible != self.cursor_visible {
            self.cursor_visible = visible;
            if let Err(err) = self.window.set_cursor_state(if visible {
                CursorState::Normal
            } else {
                CursorState::Hide
            }) {
                warn!("Failed to set cursor visibility: {}", err);
            }
        }
    }

    #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
    pub fn platform_window_init() {
        /// Set up env to make XIM work correctly
        use x11_dl::xlib;
        use libc::{setlocale, LC_CTYPE};
        let xlib = xlib::Xlib::open().expect("get xlib");
        unsafe {
            // Use empty c string to fallback to LC_CTYPE in environment variables
            setlocale(LC_CTYPE, b"\0".as_ptr() as *const _);
            // Use empty c string for implementation dependent behavior,
            // which might be the XMODIFIERS set in env
            (xlib.XSetLocaleModifiers)(b"\0".as_ptr() as *const _);
        }
    }

    /// TODO: change this directive when adding functions for other platforms
    #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))]
    pub fn platform_window_init() {
    }

    #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
    pub fn set_urgent(&self, is_urgent: bool) {
        use glutin::os::unix::WindowExt;
        use std::os::raw;
        use x11_dl::xlib::{self, XUrgencyHint};

        let xlib_display = self.window.get_xlib_display();
        let xlib_window = self.window.get_xlib_window();

        if let (Some(xlib_window), Some(xlib_display)) = (xlib_window, xlib_display) {
            let xlib = xlib::Xlib::open().expect("get xlib");

            unsafe {
                let mut hints = (xlib.XGetWMHints)(xlib_display as _, xlib_window as _);

                if hints.is_null() {
                    hints = (xlib.XAllocWMHints)();
                }

                if is_urgent {
                    (*hints).flags |= XUrgencyHint;
                } else {
                    (*hints).flags &= !XUrgencyHint;
                 }

                (xlib.XSetWMHints)(xlib_display as _, xlib_window as _, hints);

                (xlib.XFree)(hints as *mut raw::c_void);
            }
        }

    }

    #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))]
    pub fn set_urgent(&self, _: bool) {
    }

    #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
    pub fn send_xim_spot(&self, x: i16, y: i16) {
        use glutin::os::unix::WindowExt;
        self.window.send_xim_spot(x, y);
    }

    #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))]
    pub fn send_xim_spot(&self, _x: i16, _y: i16) {
    }

    #[cfg(not(target_os = "macos"))]
    pub fn get_window_id(&self) -> Option<usize> {
        use glutin::os::unix::WindowExt;

        match self.window.get_xlib_window() {
            Some(xlib_window) => Some(xlib_window as usize),
            None => None
        }
    }

    #[cfg(target_os = "macos")]
    pub fn get_window_id(&self) -> Option<usize> {
        None
    }
}

pub trait OsExtensions {
    fn run_os_extensions(&self) {}
}

#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd")))]
impl OsExtensions for Window { }

#[cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))]
impl OsExtensions for Window {
    fn run_os_extensions(&self) {
        use glutin::os::unix::WindowExt;
        use x11_dl::xlib::{self, XA_CARDINAL, PropModeReplace};
        use std::ffi::{CStr};
        use std::ptr;
        use libc::getpid;

        let xlib_display = self.window.get_xlib_display();
        let xlib_window = self.window.get_xlib_window();

        if let (Some(xlib_window), Some(xlib_display)) = (xlib_window, xlib_display) {
            let xlib = xlib::Xlib::open().expect("get xlib");

            // Set _NET_WM_PID to process pid
            unsafe {
                let _net_wm_pid = CStr::from_ptr(b"_NET_WM_PID\0".as_ptr() as *const _);
                let atom = (xlib.XInternAtom)(xlib_display as *mut _, _net_wm_pid.as_ptr(), 0);
                let pid = getpid();

                (xlib.XChangeProperty)(xlib_display as _, xlib_window as _, atom,
                    XA_CARDINAL, 32, PropModeReplace, &pid as *const i32 as *const u8, 1);

            }
            // Although this call doesn't actually pass any data, it does cause
            // WM_CLIENT_MACHINE to be set. WM_CLIENT_MACHINE MUST be set if _NET_WM_PID is set
            // (which we do above).
            unsafe {
                (xlib.XSetWMProperties)(xlib_display as _, xlib_window as _, ptr::null_mut(),
                    ptr::null_mut(), ptr::null_mut(), 0, ptr::null_mut(), ptr::null_mut(),
                    ptr::null_mut());
            }
        }
    }
}

impl Proxy {
    /// Wakes up the event loop of the window
    ///
    /// This is useful for triggering a draw when the renderer would otherwise
    /// be waiting on user input.
    pub fn wakeup_event_loop(&self) {
        self.inner.wakeup().unwrap();
    }
}

pub trait SetInnerSize<T> {
    fn set_inner_size<S: ToPoints>(&mut self, size: &S);
}

impl SetInnerSize<Pixels<u32>> for Window {
    fn set_inner_size<T: ToPoints>(&mut self, size: &T) {
        let size = size.to_points(self.hidpi_factor());
        self.window.set_inner_size(*size.width as _, *size.height as _);
    }
}
<commit_msg>Try to create window with different SRGB config when failed<commit_after>// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
use std::convert::From;
use std::fmt::{self, Display};
use std::ops::Deref;

use gl;
use glutin::{self, ContextBuilder, ControlFlow, CursorState, Event, EventsLoop,
             MouseCursor as GlutinMouseCursor, WindowBuilder};
use glutin::GlContext;

use MouseCursor;

use config::WindowConfig;

/// Window errors
#[derive(Debug)]
pub enum Error {
    /// Error creating the window
    ContextCreation(glutin::CreationError),

    /// Error manipulating the rendering context
    Context(glutin::ContextError),
}

/// Result of fallible operations concerning a Window.
type Result<T> = ::std::result::Result<T, Error>;

/// A window which can be used for displaying the terminal
///
/// Wraps the underlying windowing library to provide a stable API in Alacritty
pub struct Window {
    event_loop: EventsLoop,
    window: glutin::GlWindow,
    cursor_visible: bool,

    /// Whether or not the window is the focused window.
    pub is_focused: bool,
}

/// Threadsafe APIs for the window
pub struct Proxy {
    inner: glutin::EventsLoopProxy,
}

/// Information about where the window is being displayed
///
/// Useful for subsystems like the font rasterized which depend on DPI and scale
/// factor.
pub struct DeviceProperties {
    /// Scale factor for pixels <-> points.
    ///
    /// This will be 1. on standard displays and may have a different value on
    /// hidpi displays.
    pub scale_factor: f32,
}

/// Size of the window
#[derive(Debug, Copy, Clone)]
pub struct Size<T> {
    pub width: T,
    pub height: T,
}

/// Strongly typed Pixels unit
#[derive(Debug, Copy, Clone)]
pub struct Pixels<T>(pub T);

/// Strongly typed Points unit
///
/// Points are like pixels but adjusted for DPI.
#[derive(Debug, Copy, Clone)]
pub struct Points<T>(pub T);

pub trait ToPoints {
    fn to_points(&self, scale: f32) -> Size<Points<u32>>;
}

impl ToPoints for Size<Points<u32>> {
    #[inline]
    fn to_points(&self, _scale: f32) -> Size<Points<u32>> {
        *self
    }
}

impl ToPoints for Size<Pixels<u32>> {
    fn to_points(&self, scale: f32) -> Size<Points<u32>> {
        let width_pts = (*self.width as f32 / scale) as u32;
        let height_pts = (*self.height as f32 / scale) as u32;

        Size {
            width: Points(width_pts),
            height: Points(height_pts)
        }
    }
}

impl<T: Display> Display for Size<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{} × {}", self.width, self.height)
    }
}

macro_rules! deref_newtype {
    ($($src:ty),+) => {
        $(
        impl<T> Deref for $src {
            type Target = T;

            #[inline]
            fn deref(&self) -> &Self::Target {
                &self.0
            }
        }
        )+
    }
}

deref_newtype! { Points<T>, Pixels<T> }

impl<T: Display> Display for Pixels<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}px", self.0)
    }
}

impl<T: Display> Display for Points<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}pts", self.0)
    }
}

impl ::std::error::Error for Error {
    fn cause(&self) -> Option<&::std::error::Error> {
        match *self {
            Error::ContextCreation(ref err) => Some(err),
            Error::Context(ref err) => Some(err),
        }
    }

    fn description(&self) -> &str {
        match *self {
            Error::ContextCreation(ref _err) => "Error creating gl context",
            Error::Context(ref _err) => "Error operating on render context",
        }
    }
}

impl Display for Error {
    fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        match *self {
            Error::ContextCreation(ref err) => {
                write!(f, "Error creating GL context; {}", err)
            },
            Error::Context(ref err) => {
                write!(f, "Error operating on render context; {}", err)
            },
        }
    }
}

impl From<glutin::CreationError> for Error {
    fn from(val: glutin::CreationError) -> Error {
        Error::ContextCreation(val)
    }
}

impl From<glutin::ContextError> for Error {
    fn from(val: glutin::ContextError) -> Error {
        Error::Context(val)
    }
}

fn create_gl_window(
    window: WindowBuilder,
    event_loop: &EventsLoop,
    srgb: bool,
) -> ::std::result::Result<glutin::GlWindow, glutin::CreationError> {
    let context = ContextBuilder::new()
        .with_srgb(srgb)
        .with_vsync(true);
    ::glutin::GlWindow::new(window, context, event_loop)
}

impl Window {
    /// Create a new window
    ///
    /// This creates a window and fully initializes a window.
    pub fn new(
        title: &str,
        window_config: &WindowConfig,
    ) -> Result<Window> {
        let event_loop = EventsLoop::new();

        Window::platform_window_init();
        let window = WindowBuilder::new()
            .with_title(title)
            .with_visibility(false)
            .with_transparency(true)
            .with_decorations(window_config.decorations());
        let window = create_gl_window(window.clone(), &event_loop, false)
            .or_else(|_| create_gl_window(window, &event_loop, true))?;
        window.show();

        // Text cursor
        window.set_cursor(GlutinMouseCursor::Text);

        // Set OpenGL symbol loader
        gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

        // Make the context current so OpenGL operations can run
        unsafe {
            window.make_current()?;
        }

        let window = Window {
            event_loop,
            window,
            cursor_visible: true,
            is_focused: true,
        };

        window.run_os_extensions();

        Ok(window)
    }

    /// Get some properties about the device
    ///
    /// Some window properties are provided since subsystems like font
    /// rasterization depend on DPI and scale factor.
    pub fn device_properties(&self) -> DeviceProperties {
        DeviceProperties {
            scale_factor: self.window.hidpi_factor(),
        }
    }

    pub fn inner_size_pixels(&self) -> Option<Size<Pixels<u32>>> {
        self.window
            .get_inner_size()
            .map(|(w, h)| Size { width: Pixels(w), height: Pixels(h) })
    }

    #[inline]
    pub fn hidpi_factor(&self) -> f32 {
        self.window.hidpi_factor()
    }

    #[inline]
    pub fn create_window_proxy(&self) -> Proxy {
        Proxy {
            inner: self.event_loop.create_proxy(),
        }
    }

    #[inline]
    pub fn swap_buffers(&self) -> Result<()> {
        self.window
            .swap_buffers()
            .map_err(From::from)
    }

    /// Poll for any available events
    #[inline]
    pub fn poll_events<F>(&mut self, func: F)
        where F: FnMut(Event)
    {
        self.event_loop.poll_events(func);
    }

    #[inline]
    pub fn resize(&self, width: u32, height: u32) {
        self.window.resize(width, height);
    }

    /// Block waiting for events
    #[inline]
    pub fn wait_events<F>(&mut self, func: F)
        where F: FnMut(Event) -> ControlFlow
    {
        self.event_loop.run_forever(func);
    }

    /// Set the window title
    #[inline]
    pub fn set_title(&self, title: &str) {
        self.window.set_title(title);
    }

    #[inline]
    pub fn set_mouse_cursor(&self, cursor: MouseCursor) {
        self.window.set_cursor(match cursor {
            MouseCursor::Arrow => GlutinMouseCursor::Arrow,
            MouseCursor::Text => GlutinMouseCursor::Text,
        });
    }

    /// Set cursor visible
    pub fn set_cursor_visible(&mut self, visible: bool) {
        if visible != self.cursor_visible {
            self.cursor_visible = visible;
            if let Err(err) = self.window.set_cursor_state(if visible {
                CursorState::Normal
            } else {
                CursorState::Hide
            }) {
                warn!("Failed to set cursor visibility: {}", err);
            }
        }
    }

    #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
    pub fn platform_window_init() {
        /// Set up env to make XIM work correctly
        use x11_dl::xlib;
        use libc::{setlocale, LC_CTYPE};
        let xlib = xlib::Xlib::open().expect("get xlib");
        unsafe {
            // Use empty c string to fallback to LC_CTYPE in environment variables
            setlocale(LC_CTYPE, b"\0".as_ptr() as *const _);
            // Use empty c string for implementation dependent behavior,
            // which might be the XMODIFIERS set in env
            (xlib.XSetLocaleModifiers)(b"\0".as_ptr() as *const _);
        }
    }

    /// TODO: change this directive when adding functions for other platforms
    #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))]
    pub fn platform_window_init() {
    }

    #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
    pub fn set_urgent(&self, is_urgent: bool) {
        use glutin::os::unix::WindowExt;
        use std::os::raw;
        use x11_dl::xlib::{self, XUrgencyHint};

        let xlib_display = self.window.get_xlib_display();
        let xlib_window = self.window.get_xlib_window();

        if let (Some(xlib_window), Some(xlib_display)) = (xlib_window, xlib_display) {
            let xlib = xlib::Xlib::open().expect("get xlib");

            unsafe {
                let mut hints = (xlib.XGetWMHints)(xlib_display as _, xlib_window as _);

                if hints.is_null() {
                    hints = (xlib.XAllocWMHints)();
                }

                if is_urgent {
                    (*hints).flags |= XUrgencyHint;
                } else {
                    (*hints).flags &= !XUrgencyHint;
                 }

                (xlib.XSetWMHints)(xlib_display as _, xlib_window as _, hints);

                (xlib.XFree)(hints as *mut raw::c_void);
            }
        }

    }

    #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))]
    pub fn set_urgent(&self, _: bool) {
    }

    #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd"))]
    pub fn send_xim_spot(&self, x: i16, y: i16) {
        use glutin::os::unix::WindowExt;
        self.window.send_xim_spot(x, y);
    }

    #[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os = "dragonfly", target_os = "openbsd")))]
    pub fn send_xim_spot(&self, _x: i16, _y: i16) {
    }

    #[cfg(not(target_os = "macos"))]
    pub fn get_window_id(&self) -> Option<usize> {
        use glutin::os::unix::WindowExt;

        match self.window.get_xlib_window() {
            Some(xlib_window) => Some(xlib_window as usize),
            None => None
        }
    }

    #[cfg(target_os = "macos")]
    pub fn get_window_id(&self) -> Option<usize> {
        None
    }
}

pub trait OsExtensions {
    fn run_os_extensions(&self) {}
}

#[cfg(not(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd")))]
impl OsExtensions for Window { }

#[cfg(any(target_os = "linux", target_os = "freebsd", target_os="dragonfly", target_os="openbsd"))]
impl OsExtensions for Window {
    fn run_os_extensions(&self) {
        use glutin::os::unix::WindowExt;
        use x11_dl::xlib::{self, XA_CARDINAL, PropModeReplace};
        use std::ffi::{CStr};
        use std::ptr;
        use libc::getpid;

        let xlib_display = self.window.get_xlib_display();
        let xlib_window = self.window.get_xlib_window();

        if let (Some(xlib_window), Some(xlib_display)) = (xlib_window, xlib_display) {
            let xlib = xlib::Xlib::open().expect("get xlib");

            // Set _NET_WM_PID to process pid
            unsafe {
                let _net_wm_pid = CStr::from_ptr(b"_NET_WM_PID\0".as_ptr() as *const _);
                let atom = (xlib.XInternAtom)(xlib_display as *mut _, _net_wm_pid.as_ptr(), 0);
                let pid = getpid();

                (xlib.XChangeProperty)(xlib_display as _, xlib_window as _, atom,
                    XA_CARDINAL, 32, PropModeReplace, &pid as *const i32 as *const u8, 1);

            }
            // Although this call doesn't actually pass any data, it does cause
            // WM_CLIENT_MACHINE to be set. WM_CLIENT_MACHINE MUST be set if _NET_WM_PID is set
            // (which we do above).
            unsafe {
                (xlib.XSetWMProperties)(xlib_display as _, xlib_window as _, ptr::null_mut(),
                    ptr::null_mut(), ptr::null_mut(), 0, ptr::null_mut(), ptr::null_mut(),
                    ptr::null_mut());
            }
        }
    }
}

impl Proxy {
    /// Wakes up the event loop of the window
    ///
    /// This is useful for triggering a draw when the renderer would otherwise
    /// be waiting on user input.
    pub fn wakeup_event_loop(&self) {
        self.inner.wakeup().unwrap();
    }
}

pub trait SetInnerSize<T> {
    fn set_inner_size<S: ToPoints>(&mut self, size: &S);
}

impl SetInnerSize<Pixels<u32>> for Window {
    fn set_inner_size<T: ToPoints>(&mut self, size: &T) {
        let size = size.to_points(self.hidpi_factor());
        self.window.set_inner_size(*size.width as _, *size.height as _);
    }
}
<|endoftext|>


<commit_before>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Serializable HTTP interfaces.
//! # Convertion
//! For interoperability with other Rust libraries, all structs can be coverted to and from the
//! corresponding types in [`http`] crate.

use anyhow::{anyhow, Error, Result};
use serde::{Deserialize, Serialize};
use std::convert::{Infallible, TryFrom, TryInto};

#[derive(Debug, Eq, PartialEq, Serialize)]
pub struct HttpRequest {
    pub body: Vec<u8>,
    pub headers: HeaderFields,
    pub method: Method,
    pub url: String,
}

impl TryFrom<::http::request::Request<Vec<u8>>> for HttpRequest {
    type Error = Error;
    fn try_from(input: ::http::request::Request<Vec<u8>>) -> Result<Self> {
        let (parts, body) = input.into_parts();
        Ok(HttpRequest {
            body,
            headers: try_from_header_map(parts.headers)?,
            method: parts.method.try_into()?,
            url: parts.uri.to_string(),
        })
    }
}

impl TryInto<::http::request::Request<Vec<u8>>> for HttpRequest {
    type Error = Error;
    fn try_into(self) -> Result<::http::request::Request<Vec<u8>>> {
        let mut output = ::http::request::Request::new(self.body);
        *output.headers_mut() = try_into_header_map(self.headers)?;
        *output.method_mut() = self.method.try_into()?;
        *output.uri_mut() = self.url.try_into()?;
        Ok(output)
    }
}

#[derive(Serialize, Deserialize, Debug, PartialEq, Clone)]
pub struct HttpResponse {
    pub body: Vec<u8>,
    pub headers: HeaderFields,
    pub status: u16,
}

impl TryFrom<::http::response::Response<Vec<u8>>> for HttpResponse {
    type Error = Error;
    fn try_from(input: ::http::response::Response<Vec<u8>>) -> Result<Self> {
        let (parts, body) = input.into_parts();
        Ok(HttpResponse {
            body,
            headers: try_from_header_map(parts.headers)?,
            status: parts.status.as_u16(),
        })
    }
}

impl TryInto<::http::response::Response<Vec<u8>>> for HttpResponse {
    type Error = Error;
    fn try_into(self) -> Result<::http::response::Response<Vec<u8>>> {
        let mut output = ::http::response::Response::new(self.body);
        *output.headers_mut() = try_into_header_map(self.headers)?;
        *output.status_mut() = self.status.try_into()?;
        Ok(output)
    }
}

pub type HeaderFields = Vec<(String, String)>;

// The more readable way is to write
// ```
// impl TryFrom<::http::header::HeaderMap> for HeaderFields { ... }
// ```
// But compiler will throw error E0117 if do that.
// Because `HeaderFields` is a type alias, and we are not the author of `Vec<(String, String)>`.
fn try_from_header_map(input: ::http::header::HeaderMap) -> Result<HeaderFields> {
    let mut output = vec![];
    for (name, value) in input.iter() {
        let value = value.to_str().map_err(|e| {
            Error::new(e).context(format!("Header {} contains non-ASCII value", name))
        })?;
        output.push((name.to_string(), value.to_string()));
    }
    Ok(output)
}

// The more readable way is to write
// ```
// impl TryInto<::http::header::HeaderMap> for HeaderFields { ... }
// ```
// But compiler will throw error E0117 if do that.
// Because `HeaderFields` is a type alias, and we are not the author of `Vec<(String, String)>`.
fn try_into_header_map(input: HeaderFields) -> Result<::http::header::HeaderMap> {
    input
        .iter()
        .map(|(name, value)| -> Result<_> {
            let name =
                ::http::header::HeaderName::from_bytes(name.as_bytes()).map_err(Error::new)?;
            let value = ::http::header::HeaderValue::from_str(value).map_err(Error::new)?;
            Ok((name, value))
        })
        .collect()
}

#[derive(Debug, Eq, PartialEq, Serialize)]
pub enum Method {
    Get,
    Post,
}

impl TryFrom<::http::Method> for Method {
    type Error = Error;
    fn try_from(method: ::http::Method) -> Result<Self> {
        match method {
            ::http::Method::GET => Ok(Method::Get),
            ::http::Method::POST => Ok(Method::Post),
            x => Err(anyhow!("Method {} is not supported", x)),
        }
    }
}

impl TryInto<::http::Method> for Method {
    type Error = Infallible;
    fn try_into(self) -> Result<::http::Method, Self::Error> {
        match self {
            Method::Get => Ok(::http::Method::GET),
            Method::Post => Ok(::http::Method::POST),
        }
    }
}
<commit_msg>Use base64 for response body in debug trait (#205)<commit_after>// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

//! Serializable HTTP interfaces.
//! # Convertion
//! For interoperability with other Rust libraries, all structs can be coverted to and from the
//! corresponding types in [`http`] crate.

use anyhow::{anyhow, Error, Result};
use serde::{Deserialize, Serialize};
use std::convert::{Infallible, TryFrom, TryInto};

#[derive(Debug, Eq, PartialEq, Serialize)]
pub struct HttpRequest {
    pub body: Vec<u8>,
    pub headers: HeaderFields,
    pub method: Method,
    pub url: String,
}

impl TryFrom<::http::request::Request<Vec<u8>>> for HttpRequest {
    type Error = Error;
    fn try_from(input: ::http::request::Request<Vec<u8>>) -> Result<Self> {
        let (parts, body) = input.into_parts();
        Ok(HttpRequest {
            body,
            headers: try_from_header_map(parts.headers)?,
            method: parts.method.try_into()?,
            url: parts.uri.to_string(),
        })
    }
}

impl TryInto<::http::request::Request<Vec<u8>>> for HttpRequest {
    type Error = Error;
    fn try_into(self) -> Result<::http::request::Request<Vec<u8>>> {
        let mut output = ::http::request::Request::new(self.body);
        *output.headers_mut() = try_into_header_map(self.headers)?;
        *output.method_mut() = self.method.try_into()?;
        *output.uri_mut() = self.url.try_into()?;
        Ok(output)
    }
}

#[derive(Serialize, Deserialize, PartialEq, Clone)]
pub struct HttpResponse {
    pub body: Vec<u8>,
    pub headers: HeaderFields,
    pub status: u16,
}

impl TryFrom<::http::response::Response<Vec<u8>>> for HttpResponse {
    type Error = Error;
    fn try_from(input: ::http::response::Response<Vec<u8>>) -> Result<Self> {
        let (parts, body) = input.into_parts();
        Ok(HttpResponse {
            body,
            headers: try_from_header_map(parts.headers)?,
            status: parts.status.as_u16(),
        })
    }
}

impl TryInto<::http::response::Response<Vec<u8>>> for HttpResponse {
    type Error = Error;
    fn try_into(self) -> Result<::http::response::Response<Vec<u8>>> {
        let mut output = ::http::response::Response::new(self.body);
        *output.headers_mut() = try_into_header_map(self.headers)?;
        *output.status_mut() = self.status.try_into()?;
        Ok(output)
    }
}

pub type HeaderFields = Vec<(String, String)>;

// The more readable way is to write
// ```
// impl TryFrom<::http::header::HeaderMap> for HeaderFields { ... }
// ```
// But compiler will throw error E0117 if do that.
// Because `HeaderFields` is a type alias, and we are not the author of `Vec<(String, String)>`.
fn try_from_header_map(input: ::http::header::HeaderMap) -> Result<HeaderFields> {
    let mut output = vec![];
    for (name, value) in input.iter() {
        let value = value.to_str().map_err(|e| {
            Error::new(e).context(format!("Header {} contains non-ASCII value", name))
        })?;
        output.push((name.to_string(), value.to_string()));
    }
    Ok(output)
}

// The more readable way is to write
// ```
// impl TryInto<::http::header::HeaderMap> for HeaderFields { ... }
// ```
// But compiler will throw error E0117 if do that.
// Because `HeaderFields` is a type alias, and we are not the author of `Vec<(String, String)>`.
fn try_into_header_map(input: HeaderFields) -> Result<::http::header::HeaderMap> {
    input
        .iter()
        .map(|(name, value)| -> Result<_> {
            let name =
                ::http::header::HeaderName::from_bytes(name.as_bytes()).map_err(Error::new)?;
            let value = ::http::header::HeaderValue::from_str(value).map_err(Error::new)?;
            Ok((name, value))
        })
        .collect()
}

#[derive(Debug, Eq, PartialEq, Serialize)]
pub enum Method {
    Get,
    Post,
}

impl TryFrom<::http::Method> for Method {
    type Error = Error;
    fn try_from(method: ::http::Method) -> Result<Self> {
        match method {
            ::http::Method::GET => Ok(Method::Get),
            ::http::Method::POST => Ok(Method::Post),
            x => Err(anyhow!("Method {} is not supported", x)),
        }
    }
}

impl TryInto<::http::Method> for Method {
    type Error = Infallible;
    fn try_into(self) -> Result<::http::Method, Self::Error> {
        match self {
            Method::Get => Ok(::http::Method::GET),
            Method::Post => Ok(::http::Method::POST),
        }
    }
}

impl std::fmt::Debug for HttpResponse {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("HttpResponse")
            .field("status", &self.status)
            .field("headers", &self.headers)
            .field("body", &base64::encode(&self.body))
            .finish()
    }
}
<|endoftext|>


<commit_before>#![feature(proc_macro, conservative_impl_trait, generators, underscore_lifetimes)]

extern crate futures_await as futures;

use futures::stable::PinnedFuture;
use futures::executor;
use futures::prelude::*;

struct Ref<'a, T: 'a>(&'a T);

#[async]
fn references(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async]
fn new_types(x: Ref<'_, i32>) -> Result<i32, i32> {
    Ok(*x.0)
}

#[async_move]
fn references_move(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async_stream(item = i32)]
fn _streams(x: &i32) -> Result<(), i32> {
    stream_yield!(*x);
    Ok(())
}

#[test]
fn main() {
    let x = 0;
    assert_eq!(executor::block_on(references(&x).anchor()), Ok(0));
    assert_eq!(executor::block_on(new_types(Ref(&x)).anchor()), Ok(0));
    assert_eq!(executor::block_on(references_move(&x)), Ok(0));
}
<commit_msg>Test return type elision.<commit_after>#![feature(proc_macro, conservative_impl_trait, generators, underscore_lifetimes)]

extern crate futures_await as futures;

use futures::stable::PinnedFuture;
use futures::executor;
use futures::prelude::*;

struct Ref<'a, T: 'a>(&'a T);

#[async]
fn references(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async]
fn new_types(x: Ref<'_, i32>) -> Result<i32, i32> {
    Ok(*x.0)
}

#[async_move]
fn references_move(x: &i32) -> Result<i32, i32> {
    Ok(*x)
}

#[async_stream(item = i32)]
fn _streams(x: &i32) -> Result<(), i32> {
    stream_yield!(*x);
    Ok(())
}

struct Foo(i32);

impl Foo {
    #[async]
    fn foo(&self) -> Result<&i32, i32> {
        Ok(&self.0)
    }
}

#[async]
fn single_ref(x: &i32) -> Result<&i32, i32> {
    Ok(x)
}

#[test]
fn main() {
    let x = 0;
    let foo = Foo(x);
    assert_eq!(executor::block_on(references(&x).anchor()), Ok(x));
    assert_eq!(executor::block_on(new_types(Ref(&x)).anchor()), Ok(x));
    assert_eq!(executor::block_on(references_move(&x)), Ok(x));
    assert_eq!(executor::block_on(single_ref(&x).anchor()), Ok(&x));
    assert_eq!(executor::block_on(foo.foo().anchor()), Ok(&x));
}
<|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/. */

use devtools_traits::{ConsoleMessage, LogLevel, ScriptToDevtoolsControlMsg};
use dom::bindings::codegen::Bindings::ConsoleBinding;
use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
use dom::bindings::global::{GlobalRef, global_root_from_reflector};
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use util::str::DOMString;

// https://developer.mozilla.org/en-US/docs/Web/API/Console
#[dom_struct]
pub struct Console {
    reflector_: Reflector,
}

impl Console {
    fn new_inherited() -> Console {
        Console {
            reflector_: Reflector::new(),
        }
    }

    pub fn new(global: GlobalRef) -> Root<Console> {
        reflect_dom_object(box Console::new_inherited(),
                           global,
                           ConsoleBinding::Wrap)
    }
}

impl ConsoleMethods for Console {
    // https://developer.mozilla.org/en-US/docs/Web/API/Console/log
    fn Log(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Log, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console
    fn Debug(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Debug, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/info
    fn Info(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Info, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/warn
    fn Warn(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Warn, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/error
    fn Error(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Error, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/assert
    fn Assert(&self, condition: bool, message: Option<DOMString>) {
        if !condition {
            let message = message.unwrap_or_else(|| DOMString::from("no message"));
            println!("Assertion failed: {}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Error, message));
        }
    }
}

fn prepare_message(logLevel: LogLevel, message: DOMString) -> ConsoleMessage {
    // TODO: Sending fake values for filename, lineNumber and columnNumber in LogMessage; adjust later
    ConsoleMessage {
        message: String::from(message),
        logLevel: logLevel,
        filename: "test".to_owned(),
        lineNumber: 1,
        columnNumber: 1,
    }
}

fn propagate_console_msg(console: &&Console, console_message: ConsoleMessage) {
    let global = global_root_from_reflector(*console);
    let pipelineId = global.r().pipeline();
    global.r().devtools_chan().as_ref().map(|chan| {
        chan.send(ScriptToDevtoolsControlMsg::ConsoleAPI(pipelineId,
                                                         console_message.clone(),
                                                         global.r().get_worker_id()))
            .unwrap();
    });
}
<commit_msg>Introduce Console::send_to_devtools<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/. */

use devtools_traits::{ConsoleMessage, LogLevel, ScriptToDevtoolsControlMsg};
use dom::bindings::codegen::Bindings::ConsoleBinding;
use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
use dom::bindings::global::{GlobalRef, global_root_from_reflector};
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use util::str::DOMString;

// https://developer.mozilla.org/en-US/docs/Web/API/Console
#[dom_struct]
pub struct Console {
    reflector_: Reflector,
}

impl Console {
    fn new_inherited() -> Console {
        Console {
            reflector_: Reflector::new(),
        }
    }

    pub fn new(global: GlobalRef) -> Root<Console> {
        reflect_dom_object(box Console::new_inherited(),
                           global,
                           ConsoleBinding::Wrap)
    }

    fn send_to_devtools(&self, level: LogLevel, message: DOMString) {
        let global = global_root_from_reflector(self);
        let global = global.r();
        if let Some(chan) = global.devtools_chan() {
            let console_message = prepare_message(level, message);
            let devtools_message = ScriptToDevtoolsControlMsg::ConsoleAPI(
                global.pipeline(),
                console_message,
                global.get_worker_id());
            chan.send(devtools_message).unwrap();
        }
    }
}

impl ConsoleMethods for Console {
    // https://developer.mozilla.org/en-US/docs/Web/API/Console/log
    fn Log(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            self.send_to_devtools(LogLevel::Log, message);
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console
    fn Debug(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            self.send_to_devtools(LogLevel::Debug, message);
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/info
    fn Info(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            self.send_to_devtools(LogLevel::Info, message);
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/warn
    fn Warn(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            self.send_to_devtools(LogLevel::Warn, message);
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/error
    fn Error(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            self.send_to_devtools(LogLevel::Error, message);
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/assert
    fn Assert(&self, condition: bool, message: Option<DOMString>) {
        if !condition {
            let message = message.unwrap_or_else(|| DOMString::from("no message"));
            println!("Assertion failed: {}", message);
            self.send_to_devtools(LogLevel::Error, message);
        }
    }
}

fn prepare_message(logLevel: LogLevel, message: DOMString) -> ConsoleMessage {
    // TODO: Sending fake values for filename, lineNumber and columnNumber in LogMessage; adjust later
    ConsoleMessage {
        message: String::from(message),
        logLevel: logLevel,
        filename: "test".to_owned(),
        lineNumber: 1,
        columnNumber: 1,
    }
}
<|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/. */

use devtools_traits::{ConsoleMessage, LogLevel, ScriptToDevtoolsControlMsg};
use dom::bindings::codegen::Bindings::ConsoleBinding;
use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
use dom::bindings::global::{GlobalField, GlobalRef};
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use util::str::DOMString;

// https://developer.mozilla.org/en-US/docs/Web/API/Console
#[dom_struct]
pub struct Console {
    reflector_: Reflector,
    global: GlobalField,
}

impl Console {
    fn new_inherited(global: GlobalRef) -> Console {
        Console {
            reflector_: Reflector::new(),
            global: GlobalField::from_rooted(&global),
        }
    }

    pub fn new(global: GlobalRef) -> Root<Console> {
        reflect_dom_object(box Console::new_inherited(global),
                           global,
                           ConsoleBinding::Wrap)
    }
}

impl ConsoleMethods for Console {
    // https://developer.mozilla.org/en-US/docs/Web/API/Console/log
    fn Log(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Log, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console
    fn Debug(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Debug, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/info
    fn Info(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Info, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/warn
    fn Warn(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Warn, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/error
    fn Error(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Error, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/assert
    fn Assert(&self, condition: bool, message: Option<DOMString>) {
        if !condition {
            let message = message.unwrap_or_else(|| DOMString::from("no message"));
            println!("Assertion failed: {}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Error, message));
        }
    }
}

fn prepare_message(logLevel: LogLevel, message: DOMString) -> ConsoleMessage {
    // TODO: Sending fake values for filename, lineNumber and columnNumber in LogMessage; adjust later
    ConsoleMessage {
        message: String::from(message),
        logLevel: logLevel,
        filename: "test".to_owned(),
        lineNumber: 1,
        columnNumber: 1,
    }
}

fn propagate_console_msg(console: &&Console, console_message: ConsoleMessage) {
    let global = console.global.root();
    let pipelineId = global.r().pipeline();
    global.r().devtools_chan().as_ref().map(|chan| {
        chan.send(ScriptToDevtoolsControlMsg::ConsoleAPI(pipelineId,
                                                         console_message.clone(),
                                                         global.r().get_worker_id()))
            .unwrap();
    });
}
<commit_msg>Remove the global field from Console<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/. */

use devtools_traits::{ConsoleMessage, LogLevel, ScriptToDevtoolsControlMsg};
use dom::bindings::codegen::Bindings::ConsoleBinding;
use dom::bindings::codegen::Bindings::ConsoleBinding::ConsoleMethods;
use dom::bindings::global::{GlobalRef, global_root_from_reflector};
use dom::bindings::js::Root;
use dom::bindings::reflector::{Reflector, reflect_dom_object};
use util::str::DOMString;

// https://developer.mozilla.org/en-US/docs/Web/API/Console
#[dom_struct]
pub struct Console {
    reflector_: Reflector,
}

impl Console {
    fn new_inherited() -> Console {
        Console {
            reflector_: Reflector::new(),
        }
    }

    pub fn new(global: GlobalRef) -> Root<Console> {
        reflect_dom_object(box Console::new_inherited(),
                           global,
                           ConsoleBinding::Wrap)
    }
}

impl ConsoleMethods for Console {
    // https://developer.mozilla.org/en-US/docs/Web/API/Console/log
    fn Log(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Log, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console
    fn Debug(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Debug, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/info
    fn Info(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Info, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/warn
    fn Warn(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Warn, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/error
    fn Error(&self, messages: Vec<DOMString>) {
        for message in messages {
            println!("{}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Error, message));
        }
    }

    // https://developer.mozilla.org/en-US/docs/Web/API/Console/assert
    fn Assert(&self, condition: bool, message: Option<DOMString>) {
        if !condition {
            let message = message.unwrap_or_else(|| DOMString::from("no message"));
            println!("Assertion failed: {}", message);
            propagate_console_msg(&self, prepare_message(LogLevel::Error, message));
        }
    }
}

fn prepare_message(logLevel: LogLevel, message: DOMString) -> ConsoleMessage {
    // TODO: Sending fake values for filename, lineNumber and columnNumber in LogMessage; adjust later
    ConsoleMessage {
        message: String::from(message),
        logLevel: logLevel,
        filename: "test".to_owned(),
        lineNumber: 1,
        columnNumber: 1,
    }
}

fn propagate_console_msg(console: &&Console, console_message: ConsoleMessage) {
    let global = global_root_from_reflector(*console);
    let pipelineId = global.r().pipeline();
    global.r().devtools_chan().as_ref().map(|chan| {
        chan.send(ScriptToDevtoolsControlMsg::ConsoleAPI(pipelineId,
                                                         console_message.clone(),
                                                         global.r().get_worker_id()))
            .unwrap();
    });
}
<|endoftext|>


<commit_before>mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "72da5a9d85a522b11e80d0fdd1fd95247d442604";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/closing-args-token.rs",
    "src/test/ui/const-generics/const-expression-parameter.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/include-single-expr-helper.rs",
    "src/test/ui/include-single-expr-helper-1.rs",
    "src/test/ui/issues/auxiliary/issue-21146-inc.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
        return false;
    }

    if path.starts_with("src/test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<commit_msg>Update test suite to nightly-2021-02-04<commit_after>mod progress;

use self::progress::Progress;
use anyhow::Result;
use flate2::read::GzDecoder;
use std::fs;
use std::path::Path;
use tar::Archive;
use walkdir::DirEntry;

const REVISION: &str = "e708cbd91c9cae4426d69270248362b423324556";

#[rustfmt::skip]
static EXCLUDE: &[&str] = &[
    // Compile-fail expr parameter in const generic position: f::<1 + 2>()
    "src/test/ui/const-generics/closing-args-token.rs",
    "src/test/ui/const-generics/const-expression-parameter.rs",

    // Deprecated anonymous parameter syntax in traits
    "src/test/ui/issues/issue-13105.rs",
    "src/test/ui/issues/issue-13775.rs",
    "src/test/ui/issues/issue-34074.rs",
    "src/test/ui/proc-macro/trait-fn-args-2015.rs",

    // Not actually test cases
    "src/test/rustdoc-ui/test-compile-fail2.rs",
    "src/test/rustdoc-ui/test-compile-fail3.rs",
    "src/test/ui/include-single-expr-helper.rs",
    "src/test/ui/include-single-expr-helper-1.rs",
    "src/test/ui/json-bom-plus-crlf-multifile-aux.rs",
    "src/test/ui/lint/expansion-time-include.rs",
    "src/test/ui/macros/auxiliary/macro-comma-support.rs",
    "src/test/ui/macros/auxiliary/macro-include-items-expr.rs",
    "src/test/ui/parser/auxiliary/issue-21146-inc.rs",
];

pub fn base_dir_filter(entry: &DirEntry) -> bool {
    let path = entry.path();
    if path.is_dir() {
        return true; // otherwise walkdir does not visit the files
    }
    if path.extension().map(|e| e != "rs").unwrap_or(true) {
        return false;
    }

    let mut path_string = path.to_string_lossy();
    if cfg!(windows) {
        path_string = path_string.replace('\\', "/").into();
    }
    let path = if let Some(path) = path_string.strip_prefix("tests/rust/") {
        path
    } else {
        panic!("unexpected path in Rust dist: {}", path_string);
    };

    if path.starts_with("src/test/compile-fail") || path.starts_with("src/test/rustfix") {
        return false;
    }

    if path.starts_with("src/test/ui") {
        let stderr_path = entry.path().with_extension("stderr");
        if stderr_path.exists() {
            // Expected to fail in some way
            return false;
        }
    }

    !EXCLUDE.contains(&path)
}

#[allow(dead_code)]
pub fn edition(path: &Path) -> &'static str {
    if path.ends_with("dyn-2015-no-warnings-without-lints.rs") {
        "2015"
    } else {
        "2018"
    }
}

pub fn clone_rust() {
    let needs_clone = match fs::read_to_string("tests/rust/COMMIT") {
        Err(_) => true,
        Ok(contents) => contents.trim() != REVISION,
    };
    if needs_clone {
        download_and_unpack().unwrap();
    }
    let mut missing = String::new();
    let test_src = Path::new("tests/rust");
    for exclude in EXCLUDE {
        if !test_src.join(exclude).exists() {
            missing += "\ntests/rust/";
            missing += exclude;
        }
    }
    if !missing.is_empty() {
        panic!("excluded test file does not exist:{}\n", missing);
    }
}

fn download_and_unpack() -> Result<()> {
    let url = format!(
        "https://github.com/rust-lang/rust/archive/{}.tar.gz",
        REVISION
    );
    let response = reqwest::blocking::get(&url)?.error_for_status()?;
    let progress = Progress::new(response);
    let decoder = GzDecoder::new(progress);
    let mut archive = Archive::new(decoder);
    let prefix = format!("rust-{}", REVISION);

    let tests_rust = Path::new("tests/rust");
    if tests_rust.exists() {
        fs::remove_dir_all(tests_rust)?;
    }

    for entry in archive.entries()? {
        let mut entry = entry?;
        let path = entry.path()?;
        if path == Path::new("pax_global_header") {
            continue;
        }
        let relative = path.strip_prefix(&prefix)?;
        let out = tests_rust.join(relative);
        entry.unpack(&out)?;
    }

    fs::write("tests/rust/COMMIT", REVISION)?;
    Ok(())
}
<|endoftext|>


<commit_before>use mio::net::{TcpListener, TcpStream};
use mio::*;
use std::sync::{Arc, Barrier};
use std::thread;
use std::time::Duration;

mod util;

use util::{init, localhost};

#[test]
fn test_poll_closes_fd() {
    init();

    for _ in 0..2000 {
        let mut poll = Poll::new().unwrap();
        let mut events = Events::with_capacity(4);

        poll.poll(&mut events, Some(Duration::from_millis(0)))
            .unwrap();

        drop(poll);
    }
}

#[test]
fn test_drop_cancels_interest_and_shuts_down() {
    init();

    use mio::net::TcpStream;
    use std::io;
    use std::io::Read;
    use std::net::TcpListener;
    use std::thread;

    let l = TcpListener::bind("127.0.0.1:0").unwrap();
    let addr = l.local_addr().unwrap();

    let t = thread::spawn(move || {
        let mut s = l.incoming().next().unwrap().unwrap();
        s.set_read_timeout(Some(Duration::from_secs(5)))
            .expect("set_read_timeout");
        let r = s.read(&mut [0; 16]);
        match r {
            Ok(_) => (),
            Err(e) => {
                if e.kind() != io::ErrorKind::UnexpectedEof {
                    panic!(e);
                }
            }
        }
    });

    let mut poll = Poll::new().unwrap();
    let mut s = TcpStream::connect(addr).unwrap();

    poll.registry()
        .register(&s, Token(1), Interests::READABLE | Interests::WRITABLE)
        .unwrap();
    let mut events = Events::with_capacity(16);
    'outer: loop {
        poll.poll(&mut events, None).unwrap();
        for event in &events {
            if event.token() == Token(1) {
                // connected
                break 'outer;
            }
        }
    }

    let mut b = [0; 1024];
    match s.read(&mut b) {
        Ok(_) => panic!("unexpected ok"),
        Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => (),
        Err(e) => panic!("unexpected error: {:?}", e),
    }

    drop(s);
    t.join().unwrap();
}

#[test]
fn test_registry_behind_arc() {
    // `Registry` should work behind an `Arc`, being `Sync` and `Send`.
    init();

    let mut poll = Poll::new().unwrap();
    let registry = Arc::new(poll.registry().try_clone().unwrap());
    let mut events = Events::with_capacity(128);

    let addr = localhost();
    let barrier = Arc::new(Barrier::new(3));

    let registry2 = Arc::clone(&registry);
    let registry3 = Arc::clone(&registry);
    let barrier2 = Arc::clone(&barrier);
    let barrier3 = Arc::clone(&barrier);

    let handle1 = thread::spawn(move || {
        let listener = TcpListener::bind(addr).unwrap();
        registry2
            .register(&listener, Token(0), Interests::READABLE)
            .unwrap();
        barrier2.wait();
    });
    let handle2 = thread::spawn(move || {
        let stream = TcpStream::connect(addr).unwrap();
        registry3
            .register(&stream, Token(1), Interests::READABLE | Interests::WRITABLE)
            .unwrap();
        barrier3.wait();
    });

    poll.poll(&mut events, Some(Duration::from_millis(100)))
        .unwrap();
    assert!(events.iter().count() >= 1);

    // Let the threads return.
    barrier.wait();

    handle1.join().unwrap();
    handle2.join().unwrap();
}

#[test]
fn assertions() {
    fn assert_sync<T: Sync>() {}
    fn assert_send<T: Send>() {}

    assert_sync::<Poll>();
    assert_send::<Poll>();
    assert_sync::<Registry>();
    assert_send::<Registry>();
}
<commit_msg>Disable test_registry_behind_arc on Windows<commit_after>use mio::net::{TcpListener, TcpStream};
use mio::*;
use std::sync::{Arc, Barrier};
use std::thread;
use std::time::Duration;

mod util;

use util::{init, localhost};

#[test]
fn test_poll_closes_fd() {
    init();

    for _ in 0..2000 {
        let mut poll = Poll::new().unwrap();
        let mut events = Events::with_capacity(4);

        poll.poll(&mut events, Some(Duration::from_millis(0)))
            .unwrap();

        drop(poll);
    }
}

#[test]
fn test_drop_cancels_interest_and_shuts_down() {
    init();

    use mio::net::TcpStream;
    use std::io;
    use std::io::Read;
    use std::net::TcpListener;
    use std::thread;

    let l = TcpListener::bind("127.0.0.1:0").unwrap();
    let addr = l.local_addr().unwrap();

    let t = thread::spawn(move || {
        let mut s = l.incoming().next().unwrap().unwrap();
        s.set_read_timeout(Some(Duration::from_secs(5)))
            .expect("set_read_timeout");
        let r = s.read(&mut [0; 16]);
        match r {
            Ok(_) => (),
            Err(e) => {
                if e.kind() != io::ErrorKind::UnexpectedEof {
                    panic!(e);
                }
            }
        }
    });

    let mut poll = Poll::new().unwrap();
    let mut s = TcpStream::connect(addr).unwrap();

    poll.registry()
        .register(&s, Token(1), Interests::READABLE | Interests::WRITABLE)
        .unwrap();
    let mut events = Events::with_capacity(16);
    'outer: loop {
        poll.poll(&mut events, None).unwrap();
        for event in &events {
            if event.token() == Token(1) {
                // connected
                break 'outer;
            }
        }
    }

    let mut b = [0; 1024];
    match s.read(&mut b) {
        Ok(_) => panic!("unexpected ok"),
        Err(ref e) if e.kind() == io::ErrorKind::WouldBlock => (),
        Err(e) => panic!("unexpected error: {:?}", e),
    }

    drop(s);
    t.join().unwrap();
}

#[test]
#[cfg_attr(windows, ignore = "can't concurrently poll and register on Windows")]
fn test_registry_behind_arc() {
    // `Registry` should work behind an `Arc`, being `Sync` and `Send`.
    init();

    let mut poll = Poll::new().unwrap();
    let registry = Arc::new(poll.registry().try_clone().unwrap());
    let mut events = Events::with_capacity(128);

    let addr = localhost();
    let barrier = Arc::new(Barrier::new(3));

    let registry2 = Arc::clone(&registry);
    let registry3 = Arc::clone(&registry);
    let barrier2 = Arc::clone(&barrier);
    let barrier3 = Arc::clone(&barrier);

    let handle1 = thread::spawn(move || {
        let listener = TcpListener::bind(addr).unwrap();
        registry2
            .register(&listener, Token(0), Interests::READABLE)
            .unwrap();
        barrier2.wait();
    });
    let handle2 = thread::spawn(move || {
        let stream = TcpStream::connect(addr).unwrap();
        registry3
            .register(&stream, Token(1), Interests::READABLE | Interests::WRITABLE)
            .unwrap();
        barrier3.wait();
    });

    poll.poll(&mut events, Some(Duration::from_millis(100)))
        .unwrap();
    assert!(events.iter().count() >= 1);

    // Let the threads return.
    barrier.wait();

    handle1.join().unwrap();
    handle2.join().unwrap();
}

#[test]
fn assertions() {
    fn assert_sync<T: Sync>() {}
    fn assert_send<T: Send>() {}

    assert_sync::<Poll>();
    assert_send::<Poll>();
    assert_sync::<Registry>();
    assert_send::<Registry>();
}
<|endoftext|>


<commit_before>use cxx_test_suite::ffi;
use std::cell::Cell;
use std::ffi::CStr;

thread_local! {
    static CORRECT: Cell<bool> = Cell::new(false);
}

#[no_mangle]
extern "C" fn cxx_test_suite_set_correct() {
    CORRECT.with(|correct| correct.set(true));
}

macro_rules! check {
    ($run:expr) => {{
        CORRECT.with(|correct| correct.set(false));
        $run;
        assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
    }};
}

#[test]
fn test_c_return() {
    let shared = ffi::Shared { z: 2020 };

    assert_eq!(2020, ffi::c_return_primitive());
    assert_eq!(2020, ffi::c_return_shared().z);
    assert_eq!(2020, *ffi::c_return_box());
    ffi::c_return_unique_ptr();
    assert_eq!(2020, *ffi::c_return_ref(&shared));
    assert_eq!("2020", ffi::c_return_str(&shared));
    assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
    assert_eq!("2020", ffi::c_return_rust_string());
    assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
    assert_eq!(
        4,
        ffi::c_return_unique_ptr_vector_u8()
            .as_ref()
            .unwrap()
            .size()
    );
    assert_eq!(
        200_u8,
        ffi::c_return_unique_ptr_vector_u8()
            .as_ref()
            .unwrap()
            .into_iter()
            .sum()
    );
    assert_eq!(
        200.5_f64,
        ffi::c_return_unique_ptr_vector_f64()
            .as_ref()
            .unwrap()
            .into_iter()
            .sum()
    );
    assert_eq!(
        2,
        ffi::c_return_unique_ptr_vector_shared()
            .as_ref()
            .unwrap()
            .size()
    );
    assert_eq!(
        2021_usize,
        ffi::c_return_unique_ptr_vector_shared()
            .as_ref()
            .unwrap()
            .into_iter()
            .map(|o| o.z)
            .sum()
    );
}

#[test]
fn test_c_try_return() {
    assert_eq!((), ffi::c_try_return_void().unwrap());
    assert_eq!(2020, ffi::c_try_return_primitive().unwrap());
    assert_eq!(
        "logic error",
        ffi::c_fail_return_primitive().unwrap_err().what(),
    );
    assert_eq!(2020, *ffi::c_try_return_box().unwrap());
    assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap());
    assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
    assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap());
    assert_eq!("2020", ffi::c_try_return_rust_string().unwrap());
    assert_eq!("2020", &*ffi::c_try_return_unique_ptr_string().unwrap());
}

#[test]
fn test_c_take() {
    let unique_ptr = ffi::c_return_unique_ptr();

    check!(ffi::c_take_primitive(2020));
    check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
    check!(ffi::c_take_box(Box::new(2020)));
    check!(ffi::c_take_ref_c(&unique_ptr));
    check!(ffi::c_take_unique_ptr(unique_ptr));
    check!(ffi::c_take_str("2020"));
    check!(ffi::c_take_sliceu8(b"2020"));
    check!(ffi::c_take_rust_string("2020".to_owned()));
    check!(ffi::c_take_unique_ptr_string(
        ffi::c_return_unique_ptr_string()
    ));
    check!(ffi::c_take_unique_ptr_vector_u8(
        ffi::c_return_unique_ptr_vector_u8()
    ));
    check!(ffi::c_take_unique_ptr_vector_f64(
        ffi::c_return_unique_ptr_vector_f64()
    ));
    check!(ffi::c_take_unique_ptr_vector_shared(
        ffi::c_return_unique_ptr_vector_shared()
    ));
    check!(ffi::c_take_vec_u8(&[86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
    check!(ffi::c_take_vec_shared(&vec![
        ffi::Shared { z: 1010 },
        ffi::Shared { z: 1011 }
    ]));
}

#[test]
fn test_c_callback() {
    fn callback(s: String) -> usize {
        if s == "2020" {
            cxx_test_suite_set_correct();
        }
        0
    }

    check!(ffi::c_take_callback(callback));
}

#[test]
fn test_c_call_r() {
    fn cxx_run_test() {
        extern "C" {
            fn cxx_run_test() -> *const i8;
        }
        let failure = unsafe { cxx_run_test() };
        if !failure.is_null() {
            let msg = unsafe { CStr::from_ptr(failure) };
            eprintln!("{}", msg.to_string_lossy());
        }
    }
    check!(cxx_run_test());
}

#[test]
fn test_c_method_calls() {
    let mut unique_ptr = ffi::c_return_unique_ptr();

    let old_value = unique_ptr.get();
    assert_eq!(2020, old_value);
    assert_eq!(2021, unique_ptr.set(2021));
    assert_eq!(2021, unique_ptr.get());
    assert_eq!(old_value, unique_ptr.set2(old_value));
    assert_eq!(old_value, unique_ptr.get2())
}

#[no_mangle]
extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
    Box::into_raw(Box::new(2020usize))
}

#[no_mangle]
unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const cxx_test_suite::R) -> bool {
    *r == 2020
}
<commit_msg>Simplify vector tests using UniquePtr deref<commit_after>use cxx_test_suite::ffi;
use std::cell::Cell;
use std::ffi::CStr;

thread_local! {
    static CORRECT: Cell<bool> = Cell::new(false);
}

#[no_mangle]
extern "C" fn cxx_test_suite_set_correct() {
    CORRECT.with(|correct| correct.set(true));
}

macro_rules! check {
    ($run:expr) => {{
        CORRECT.with(|correct| correct.set(false));
        $run;
        assert!(CORRECT.with(|correct| correct.get()), stringify!($run));
    }};
}

#[test]
fn test_c_return() {
    let shared = ffi::Shared { z: 2020 };

    assert_eq!(2020, ffi::c_return_primitive());
    assert_eq!(2020, ffi::c_return_shared().z);
    assert_eq!(2020, *ffi::c_return_box());
    ffi::c_return_unique_ptr();
    assert_eq!(2020, *ffi::c_return_ref(&shared));
    assert_eq!("2020", ffi::c_return_str(&shared));
    assert_eq!(b"2020\0", ffi::c_return_sliceu8(&shared));
    assert_eq!("2020", ffi::c_return_rust_string());
    assert_eq!("2020", ffi::c_return_unique_ptr_string().to_str().unwrap());
    assert_eq!(4, ffi::c_return_unique_ptr_vector_u8().size());
    assert_eq!(
        200_u8,
        ffi::c_return_unique_ptr_vector_u8().into_iter().sum(),
    );
    assert_eq!(
        200.5_f64,
        ffi::c_return_unique_ptr_vector_f64().into_iter().sum(),
    );
    assert_eq!(2, ffi::c_return_unique_ptr_vector_shared().size());
    assert_eq!(
        2021_usize,
        ffi::c_return_unique_ptr_vector_shared()
            .into_iter()
            .map(|o| o.z)
            .sum(),
    );
}

#[test]
fn test_c_try_return() {
    assert_eq!((), ffi::c_try_return_void().unwrap());
    assert_eq!(2020, ffi::c_try_return_primitive().unwrap());
    assert_eq!(
        "logic error",
        ffi::c_fail_return_primitive().unwrap_err().what(),
    );
    assert_eq!(2020, *ffi::c_try_return_box().unwrap());
    assert_eq!("2020", *ffi::c_try_return_ref(&"2020".to_owned()).unwrap());
    assert_eq!("2020", ffi::c_try_return_str("2020").unwrap());
    assert_eq!(b"2020", ffi::c_try_return_sliceu8(b"2020").unwrap());
    assert_eq!("2020", ffi::c_try_return_rust_string().unwrap());
    assert_eq!("2020", &*ffi::c_try_return_unique_ptr_string().unwrap());
}

#[test]
fn test_c_take() {
    let unique_ptr = ffi::c_return_unique_ptr();

    check!(ffi::c_take_primitive(2020));
    check!(ffi::c_take_shared(ffi::Shared { z: 2020 }));
    check!(ffi::c_take_box(Box::new(2020)));
    check!(ffi::c_take_ref_c(&unique_ptr));
    check!(ffi::c_take_unique_ptr(unique_ptr));
    check!(ffi::c_take_str("2020"));
    check!(ffi::c_take_sliceu8(b"2020"));
    check!(ffi::c_take_rust_string("2020".to_owned()));
    check!(ffi::c_take_unique_ptr_string(
        ffi::c_return_unique_ptr_string()
    ));
    check!(ffi::c_take_unique_ptr_vector_u8(
        ffi::c_return_unique_ptr_vector_u8()
    ));
    check!(ffi::c_take_unique_ptr_vector_f64(
        ffi::c_return_unique_ptr_vector_f64()
    ));
    check!(ffi::c_take_unique_ptr_vector_shared(
        ffi::c_return_unique_ptr_vector_shared()
    ));
    check!(ffi::c_take_vec_u8(&[86_u8, 75_u8, 30_u8, 9_u8].to_vec()));
    check!(ffi::c_take_vec_shared(&vec![
        ffi::Shared { z: 1010 },
        ffi::Shared { z: 1011 }
    ]));
}

#[test]
fn test_c_callback() {
    fn callback(s: String) -> usize {
        if s == "2020" {
            cxx_test_suite_set_correct();
        }
        0
    }

    check!(ffi::c_take_callback(callback));
}

#[test]
fn test_c_call_r() {
    fn cxx_run_test() {
        extern "C" {
            fn cxx_run_test() -> *const i8;
        }
        let failure = unsafe { cxx_run_test() };
        if !failure.is_null() {
            let msg = unsafe { CStr::from_ptr(failure) };
            eprintln!("{}", msg.to_string_lossy());
        }
    }
    check!(cxx_run_test());
}

#[test]
fn test_c_method_calls() {
    let mut unique_ptr = ffi::c_return_unique_ptr();

    let old_value = unique_ptr.get();
    assert_eq!(2020, old_value);
    assert_eq!(2021, unique_ptr.set(2021));
    assert_eq!(2021, unique_ptr.get());
    assert_eq!(old_value, unique_ptr.set2(old_value));
    assert_eq!(old_value, unique_ptr.get2())
}

#[no_mangle]
extern "C" fn cxx_test_suite_get_box() -> *mut cxx_test_suite::R {
    Box::into_raw(Box::new(2020usize))
}

#[no_mangle]
unsafe extern "C" fn cxx_test_suite_r_is_correct(r: *const cxx_test_suite::R) -> bool {
    *r == 2020
}
<|endoftext|>