<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/. */

//! Borders, padding, and margins.

use layout::display_list_builder::{ExtraDisplayListData, ToGfxColor};
use layout::box::RenderBox;

use core::cell::Cell;
use core::num::Zero;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use geom::side_offsets::SideOffsets2D;
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass, DisplayList};
use gfx::geometry::Au;
use newcss::complete::CompleteStyle;
use newcss::units::{Em, Pt, Px};
use newcss::values::{CSSBorderWidth, CSSBorderWidthLength, CSSBorderWidthMedium};
use newcss::values::{CSSBorderWidthThick, CSSBorderWidthThin};
use newcss::values::{CSSWidth, CSSWidthLength, CSSWidthPercentage, CSSWidthAuto};
use newcss::values::{CSSMargin, CSSMarginLength, CSSMarginPercentage, CSSMarginAuto};
use newcss::values::{CSSPadding, CSSPaddingLength, CSSPaddingPercentage};
/// Encapsulates the borders, padding, and margins, which we collectively call the "box model".
pub struct BoxModel {
    border: SideOffsets2D<Au>,
    padding: SideOffsets2D<Au>,
    margin: SideOffsets2D<Au>,
    /// The width of the content box.
    content_box_width: Au,
}

/// Useful helper data type when computing values for blocks and positioned elements.
pub enum MaybeAuto {
    Auto,
    Specified(Au),
}

impl MaybeAuto{
    pub fn from_margin(margin: CSSMargin, cb_width: Au) -> MaybeAuto{
        match margin {
            CSSMarginAuto => Auto,
            //FIXME(eatkinson): Compute percents properly
            CSSMarginPercentage(percent) => Specified(cb_width.scale_by(percent/100.0)),
            //FIXME(eatkinson): Compute pt and em values properly
            CSSMarginLength(Px(v)) |
            CSSMarginLength(Pt(v)) |
            CSSMarginLength(Em(v)) => Specified(Au::from_frac_px(v)),
        }
    }

    pub fn from_width(width: CSSWidth, cb_width: Au) -> MaybeAuto{
        match width{
            CSSWidthAuto => Auto,
            CSSWidthPercentage(percent) => Specified(cb_width.scale_by(percent/100.0)),
            //FIXME(eatkinson): Compute pt and em values properly
            CSSWidthLength(Px(v)) |
            CSSWidthLength(Pt(v)) |
            CSSWidthLength(Em(v)) => Specified(Au::from_frac_px(v)),
        }
    }

    pub fn spec_or_default(&self, default: Au) -> Au{
        match *self{
            Auto => default,
            Specified(value) => value
        }
    }
}

impl Zero for BoxModel {
    fn zero() -> BoxModel {
        BoxModel {
            border: Zero::zero(),
            padding: Zero::zero(),
            margin: Zero::zero(),
            content_box_width: Zero::zero(),
        }
    }

    fn is_zero(&self) -> bool {
        self.padding.is_zero() && self.border.is_zero() && self.margin.is_zero()
    }
}

impl BoxModel {
    /// Populates the box model parameters from the given computed style.
    pub fn compute_borders(&mut self, style: CompleteStyle) {
        // Compute the borders.
        self.border.top = self.compute_border_width(style.border_top_width());
        self.border.right = self.compute_border_width(style.border_right_width());
        self.border.bottom = self.compute_border_width(style.border_bottom_width());
        self.border.left = self.compute_border_width(style.border_left_width());
    }

    pub fn compute_padding(&mut self, style: CompleteStyle, cb_width: Au){
        self.padding.top = self.compute_padding_length(style.padding_top(), cb_width);
        self.padding.right = self.compute_padding_length(style.padding_right(), cb_width);
        self.padding.bottom = self.compute_padding_length(style.padding_bottom(), cb_width);
        self.padding.left = self.compute_padding_length(style.padding_left(), cb_width);
    }

    pub fn noncontent_width(&self) -> Au {
        let left = self.margin.left + self.border.left + self.padding.left;
        let right = self.margin.right + self.border.right + self.padding.right;
        left + right
    }

    pub fn offset(&self) -> Au {
        self.margin.left + self.border.left + self.padding.left
    }

    /// Helper function to compute the border width in app units from the CSS border width.
    priv fn compute_border_width(&self, width: CSSBorderWidth) -> Au {
        match width {
            CSSBorderWidthLength(Px(v)) |
            CSSBorderWidthLength(Em(v)) |
            CSSBorderWidthLength(Pt(v)) => {
                // FIXME(pcwalton): Handle `em` and `pt` correctly.
                Au::from_frac_px(v)
            }
            CSSBorderWidthThin => Au::from_px(1),
            CSSBorderWidthMedium => Au::from_px(5),
            CSSBorderWidthThick => Au::from_px(10),
        }
    }

    fn compute_padding_length(&self, padding: CSSPadding, content_box_width: Au) -> Au {
        match padding {
            CSSPaddingLength(Px(v)) |
            CSSPaddingLength(Pt(v)) |
            CSSPaddingLength(Em(v)) => {
                // FIXME(eatkinson): Handle 'em' and 'pt' correctly
                Au::from_frac_px(v)
            }
            CSSPaddingPercentage(p) => content_box_width.scale_by(p)
        }
    }
}

//
// Painting
//

impl RenderBox {
    /// Adds the display items necessary to paint the borders of this render box to a display list
    /// if necessary.
    pub fn paint_borders_if_applicable<E:ExtraDisplayListData>(&self,
                                                               list: &Cell<DisplayList<E>>,
                                                               abs_bounds: &Rect<Au>) {
        // Fast path.
        let border = do self.with_base |base| {
            base.model.border
        };
        if border.is_zero() {
            return
        }

        // Are all the widths equal?
        //
        // FIXME(pcwalton): Obviously this is wrong.
        if [ border.top, border.right, border.bottom ].all(|a| *a == border.left) {
            let border_width = border.top;
            let bounds = Rect {
                origin: Point2D {
                    x: abs_bounds.origin.x + border_width.scale_by(0.5),
                    y: abs_bounds.origin.y + border_width.scale_by(0.5),
                },
                size: Size2D {
                    width: abs_bounds.size.width - border_width,
                    height: abs_bounds.size.height - border_width
                }
            };

            let top_color = self.style().border_top_color();
            let color = top_color.to_gfx_color(); // FIXME

            // Append the border to the display list.
            do list.with_mut_ref |list| {
                let border_display_item = ~BorderDisplayItem {
                    base: BaseDisplayItem {
                        bounds: bounds,
                        extra: ExtraDisplayListData::new(*self),
                    },
                    width: border_width,
                    color: color,
                };

                list.append_item(BorderDisplayItemClass(border_display_item))
            }
        } else {
            warn!("ignoring unimplemented border widths");
        }
    }

}

<commit_msg>Fix padding<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/. */

//! Borders, padding, and margins.

use layout::display_list_builder::{ExtraDisplayListData, ToGfxColor};
use layout::box::RenderBox;

use core::cell::Cell;
use core::num::Zero;
use geom::point::Point2D;
use geom::rect::Rect;
use geom::size::Size2D;
use geom::side_offsets::SideOffsets2D;
use gfx::display_list::{BaseDisplayItem, BorderDisplayItem, BorderDisplayItemClass, DisplayList};
use gfx::geometry::Au;
use newcss::complete::CompleteStyle;
use newcss::units::{Em, Pt, Px};
use newcss::values::{CSSBorderWidth, CSSBorderWidthLength, CSSBorderWidthMedium};
use newcss::values::{CSSBorderWidthThick, CSSBorderWidthThin};
use newcss::values::{CSSWidth, CSSWidthLength, CSSWidthPercentage, CSSWidthAuto};
use newcss::values::{CSSMargin, CSSMarginLength, CSSMarginPercentage, CSSMarginAuto};
use newcss::values::{CSSPadding, CSSPaddingLength, CSSPaddingPercentage};
/// Encapsulates the borders, padding, and margins, which we collectively call the "box model".
pub struct BoxModel {
    border: SideOffsets2D<Au>,
    padding: SideOffsets2D<Au>,
    margin: SideOffsets2D<Au>,
    /// The width of the content box.
    content_box_width: Au,
}

/// Useful helper data type when computing values for blocks and positioned elements.
pub enum MaybeAuto {
    Auto,
    Specified(Au),
}

impl MaybeAuto{
    pub fn from_margin(margin: CSSMargin, cb_width: Au) -> MaybeAuto{
        match margin {
            CSSMarginAuto => Auto,
            //FIXME(eatkinson): Compute percents properly
            CSSMarginPercentage(percent) => Specified(cb_width.scale_by(percent/100.0)),
            //FIXME(eatkinson): Compute pt and em values properly
            CSSMarginLength(Px(v)) |
            CSSMarginLength(Pt(v)) |
            CSSMarginLength(Em(v)) => Specified(Au::from_frac_px(v)),
        }
    }

    pub fn from_width(width: CSSWidth, cb_width: Au) -> MaybeAuto{
        match width{
            CSSWidthAuto => Auto,
            CSSWidthPercentage(percent) => Specified(cb_width.scale_by(percent/100.0)),
            //FIXME(eatkinson): Compute pt and em values properly
            CSSWidthLength(Px(v)) |
            CSSWidthLength(Pt(v)) |
            CSSWidthLength(Em(v)) => Specified(Au::from_frac_px(v)),
        }
    }

    pub fn spec_or_default(&self, default: Au) -> Au{
        match *self{
            Auto => default,
            Specified(value) => value
        }
    }
}

impl Zero for BoxModel {
    fn zero() -> BoxModel {
        BoxModel {
            border: Zero::zero(),
            padding: Zero::zero(),
            margin: Zero::zero(),
            content_box_width: Zero::zero(),
        }
    }

    fn is_zero(&self) -> bool {
        self.padding.is_zero() && self.border.is_zero() && self.margin.is_zero()
    }
}

impl BoxModel {
    /// Populates the box model parameters from the given computed style.
    pub fn compute_borders(&mut self, style: CompleteStyle) {
        // Compute the borders.
        self.border.top = self.compute_border_width(style.border_top_width());
        self.border.right = self.compute_border_width(style.border_right_width());
        self.border.bottom = self.compute_border_width(style.border_bottom_width());
        self.border.left = self.compute_border_width(style.border_left_width());
    }

    pub fn compute_padding(&mut self, style: CompleteStyle, cb_width: Au){
        self.padding.top = self.compute_padding_length(style.padding_top(), cb_width);
        self.padding.right = self.compute_padding_length(style.padding_right(), cb_width);
        self.padding.bottom = self.compute_padding_length(style.padding_bottom(), cb_width);
        self.padding.left = self.compute_padding_length(style.padding_left(), cb_width);
    }

    pub fn noncontent_width(&self) -> Au {
        let left = self.margin.left + self.border.left + self.padding.left;
        let right = self.margin.right + self.border.right + self.padding.right;
        left + right
    }

    pub fn offset(&self) -> Au {
        self.margin.left + self.border.left + self.padding.left
    }

    /// Helper function to compute the border width in app units from the CSS border width.
    priv fn compute_border_width(&self, width: CSSBorderWidth) -> Au {
        match width {
            CSSBorderWidthLength(Px(v)) |
            CSSBorderWidthLength(Em(v)) |
            CSSBorderWidthLength(Pt(v)) => {
                // FIXME(pcwalton): Handle `em` and `pt` correctly.
                Au::from_frac_px(v)
            }
            CSSBorderWidthThin => Au::from_px(1),
            CSSBorderWidthMedium => Au::from_px(5),
            CSSBorderWidthThick => Au::from_px(10),
        }
    }

    fn compute_padding_length(&self, padding: CSSPadding, content_box_width: Au) -> Au {
        match padding {
            CSSPaddingLength(Px(v)) |
            CSSPaddingLength(Pt(v)) |
            CSSPaddingLength(Em(v)) => {
                // FIXME(eatkinson): Handle 'em' and 'pt' correctly
                Au::from_frac_px(v)
            }
            CSSPaddingPercentage(p) => content_box_width.scale_by(p/100.0)
        }
    }
}

//
// Painting
//

impl RenderBox {
    /// Adds the display items necessary to paint the borders of this render box to a display list
    /// if necessary.
    pub fn paint_borders_if_applicable<E:ExtraDisplayListData>(&self,
                                                               list: &Cell<DisplayList<E>>,
                                                               abs_bounds: &Rect<Au>) {
        // Fast path.
        let border = do self.with_base |base| {
            base.model.border
        };
        if border.is_zero() {
            return
        }

        // Are all the widths equal?
        //
        // FIXME(pcwalton): Obviously this is wrong.
        if [ border.top, border.right, border.bottom ].all(|a| *a == border.left) {
            let border_width = border.top;
            let bounds = Rect {
                origin: Point2D {
                    x: abs_bounds.origin.x + border_width.scale_by(0.5),
                    y: abs_bounds.origin.y + border_width.scale_by(0.5),
                },
                size: Size2D {
                    width: abs_bounds.size.width - border_width,
                    height: abs_bounds.size.height - border_width
                }
            };

            let top_color = self.style().border_top_color();
            let color = top_color.to_gfx_color(); // FIXME

            // Append the border to the display list.
            do list.with_mut_ref |list| {
                let border_display_item = ~BorderDisplayItem {
                    base: BaseDisplayItem {
                        bounds: bounds,
                        extra: ExtraDisplayListData::new(*self),
                    },
                    width: border_width,
                    color: color,
                };

                list.append_item(BorderDisplayItemClass(border_display_item))
            }
        } else {
            warn!("ignoring unimplemented border widths");
        }
    }

}

<|endoftext|>


<commit_before>#![cfg(feature = "integration")]

use git2::Repository;

use std::env;
use std::process::Command;

#[cfg_attr(feature = "integration", test)]
fn integration_test() {
    let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
    let repo_url = format!("https://github.com/{}", repo_name);
    let crate_name = repo_name
        .split('/')
        .nth(1)
        .expect("repo name should have format `<org>/<name>`");

    let repo_dir = tempfile::tempdir()
        .expect("couldn't create temp dir")
        .path()
        .join(crate_name);

    Repository::clone(&repo_url, &repo_dir).expect("clone of repo failed");

    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let target_dir = std::path::Path::new(&root_dir).join("target");
    let clippy_binary = target_dir.join(env!("PROFILE")).join("cargo-clippy");

    let output = Command::new(clippy_binary)
        .current_dir(repo_dir)
        .env("RUST_BACKTRACE", "full")
        .env("CARGO_TARGET_DIR", target_dir)
        .args(&[
            "clippy",
            "--all-targets",
            "--all-features",
            "--",
            "--cap-lints",
            "warn",
            "-Wclippy::pedantic",
            "-Wclippy::nursery",
        ])
        .output()
        .expect("unable to run clippy");

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr.contains("internal compiler error") {
        let backtrace_start = stderr
            .find("thread 'rustc' panicked at")
            .expect("start of backtrace not found");
        let backtrace_end = stderr
            .rfind("error: internal compiler error")
            .expect("end of backtrace not found");

        panic!(
            "internal compiler error\nBacktrace:\n\n{}",
            &stderr[backtrace_start..backtrace_end]
        );
    } else if stderr.contains("query stack during panic") {
        panic!("query stack during panic in the output");
    } else if stderr.contains("E0463") {
        panic!("error: E0463");
    }

    match output.status.code() {
        Some(code) => {
            if code == 0 {
                println!("Compilation successful");
            } else {
                eprintln!("Compilation failed. Exit code: {}", code);
            }
        },
        None => panic!("Process terminated by signal"),
    }
}
<commit_msg>Add two more error causes to integration test<commit_after>#![cfg(feature = "integration")]

use git2::Repository;

use std::env;
use std::process::Command;

#[cfg_attr(feature = "integration", test)]
fn integration_test() {
    let repo_name = env::var("INTEGRATION").expect("`INTEGRATION` var not set");
    let repo_url = format!("https://github.com/{}", repo_name);
    let crate_name = repo_name
        .split('/')
        .nth(1)
        .expect("repo name should have format `<org>/<name>`");

    let repo_dir = tempfile::tempdir()
        .expect("couldn't create temp dir")
        .path()
        .join(crate_name);

    Repository::clone(&repo_url, &repo_dir).expect("clone of repo failed");

    let root_dir = std::path::PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    let target_dir = std::path::Path::new(&root_dir).join("target");
    let clippy_binary = target_dir.join(env!("PROFILE")).join("cargo-clippy");

    let output = Command::new(clippy_binary)
        .current_dir(repo_dir)
        .env("RUST_BACKTRACE", "full")
        .env("CARGO_TARGET_DIR", target_dir)
        .args(&[
            "clippy",
            "--all-targets",
            "--all-features",
            "--",
            "--cap-lints",
            "warn",
            "-Wclippy::pedantic",
            "-Wclippy::nursery",
        ])
        .output()
        .expect("unable to run clippy");

    let stderr = String::from_utf8_lossy(&output.stderr);
    if stderr.contains("internal compiler error") {
        let backtrace_start = stderr
            .find("thread 'rustc' panicked at")
            .expect("start of backtrace not found");
        let backtrace_end = stderr
            .rfind("error: internal compiler error")
            .expect("end of backtrace not found");

        panic!(
            "internal compiler error\nBacktrace:\n\n{}",
            &stderr[backtrace_start..backtrace_end]
        );
    } else if stderr.contains("query stack during panic") {
        panic!("query stack during panic in the output");
    } else if stderr.contains("E0463") {
        panic!("error: E0463");
    } else if stderr.contains("E0514") {
        panic!("incompatible crate versions");
    } else if stderr.contains("failed to run `rustc` to learn about target-specific information") {
        panic!("couldn't find librustc_driver, consider setting `LD_LIBRARY_PATH`");
    }

    match output.status.code() {
        Some(code) => {
            if code == 0 {
                println!("Compilation successful");
            } else {
                eprintln!("Compilation failed. Exit code: {}", code);
            }
        },
        None => panic!("Process terminated by signal"),
    }
}
<|endoftext|>


<commit_before>/**
Create an input object

Input objects are used as data carriers for complex input values to
fields and mutations. Unlike the other helper macros,
`graphql_input_object!` actually *creates* the struct you define. It
does not add anything to the struct definition itself - what you type
is what will be generated:

```rust
# #[macro_use] extern crate juniper;
#
graphql_input_object!(
    description: "Coordinates for the user"

    struct Coordinates {
        longitude: f64 as "The X coordinate, from -180 to +180",
        latitude: f64 as "The Y coordinate, from -90 to +90",
    }
);

# fn main() { }
```

This macro creates the struct as specified and implements
`FromInputValue` to automatically parse values provided from variables
and arguments.

If you want to expose the struct under a different name than the Rust
type, you can write `struct Coordinates as "MyCoordinates" { ...`.

You can specify *default values* for input object fields; the syntax
is similar to argument default values:

```rust
# #[macro_use] extern crate juniper;
#
graphql_input_object!(
    struct SampleObject {
        foo = 123: i64 as "A sample field, defaults to 123 if omitted"
    }
);

# fn main() { }
```

*/
#[macro_export]
macro_rules! graphql_input_object {
    // Calls $val.$func($arg) if $arg is not None
    ( @maybe_apply, None, $func:ident, $val:expr ) => { $val };
    ( @maybe_apply, $arg:tt, $func:ident, $val:expr ) => { $val.$func($arg) };

    // Calls $val.description($descr) when $descr is not empty
    ( @apply_description, , $val:expr ) => { $val };
    ( @apply_description, $descr:tt , $val:expr ) => { $val.description($descr) };

    // Generate the FromInputValue::from method body, provided a
    // HashMap<&str, &InputValue> in $var
    (
        @generate_from_input_value,
        $name:tt, $var:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        Some($name {
            $( $field_name: {
                let n: String = $crate::to_camel_case(stringify!($field_name));
                let v: Option<&&$crate::InputValue> = $var.get(&n[..]);

                println!("Found variable for {:?}: {:?} in {:?}", n, v, $var);

                match v {
                    $( Some(&&InputValue::Null) | None if true => $default, )*
                        Some(v) => $crate::FromInputValue::from(v).unwrap(),
                        _ => $crate::FromInputValue::from(&$crate::InputValue::null()).unwrap()
                }
            } ),*
        })
    };

    // Generate the struct declaration, including (Rust) meta attributes
    (
        @generate_struct_fields,
        ( $($meta:tt)* ), ( $($pubmod:tt)* ), $name:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        $($meta)* $($pubmod)* struct $name {
            $( $field_name: $field_type, )*
        }
    };

    // Generate single field meta for field with default value
    (
        @generate_single_meta_field,
        $reg:tt,
        ( $field_name:ident = $default:tt : $field_type:ty $(as $descr:tt)* )
    ) => {
        graphql_input_object!(
            @apply_description,
            $($descr)*,
            $reg.arg_with_default::<$field_type>(
                &$crate::to_camel_case(stringify!($field_name)),
                &$default))
    };

    // Generate single field meta for field without default value
    (
        @generate_single_meta_field,
        $reg:tt,
        ( $field_name:ident : $field_type:ty $(as $descr:tt)* )
    ) => {
        graphql_input_object!(
            @apply_description,
            $($descr)*,
            $reg.arg::<$field_type>(
                &$crate::to_camel_case(stringify!($field_name))))
    };

    // Generate the input field meta list, i.e. &[Argument] for
    (
        @generate_meta_fields,
        $reg:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        &[
            $(
                graphql_input_object!(
                    @generate_single_meta_field,
                    $reg,
                    ( $field_name $(= $default)* : $field_type $(as $descr)* )
                )
            ),*
        ]
    };

    // #[...] struct $name { ... }
    // struct $name { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* struct $name:ident { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $(#[$meta])* ), ( ), $name, (stringify!($name)), ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] pub struct $name { ... }
    // pub struct $name { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* pub struct $name:ident { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $(#[$meta])* ), ( pub ), $name, (stringify!($name)), ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] struct $name as "GraphQLName" { ... }
    // struct $name as "GraphQLName" { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $($meta)* ), ( ), $name, $outname, ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] pub struct $name as "GraphQLName" { ... }
    // pub struct $name as "GraphQLName" { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* pub struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $($meta)* ), ( pub ), $name, $outname, ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // description: <description>
    (
        @parse,
        ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $_ignore:tt ),
        description: $descr:tt $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( $meta, $pubmod, $name, $outname, $fields, $descr ),
            $($rest)*
        );
    };

    // No more data to parse, generate the struct and impls
    (
        @parse,
        ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $descr:tt ),
    ) => {
        graphql_input_object!(@generate_struct_fields, $meta, $pubmod, $name, $fields);

        impl $crate::FromInputValue for $name {
            fn from(value: &$crate::InputValue) -> Option<$name> {
                if let Some(obj) = value.to_object_value() {
                    graphql_input_object!(@generate_from_input_value, $name, obj, $fields)
                }
                else {
                   None
                }
            }
        }

        impl $crate::GraphQLType for $name {
            type Context = ();

            fn name() -> Option<&'static str> {
                Some($outname)
            }

            fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> {
                let fields = graphql_input_object!(@generate_meta_fields, registry, $fields);
                graphql_input_object!(
                    @maybe_apply, $descr, description,
                    registry.build_input_object_type::<$name>(fields)).into_meta()
            }
        }
    };

    // Entry point: parse calls starting with a struct declaration
    ( $(#[$meta:meta])* struct $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            $(#[$meta])* struct $($items)*
        );
    };

    // Entry point: parse calls starting with a public struct declaration
    ( $(#[$meta:meta])* pub struct $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            $(#[$meta])* pub struct $($items)*
        );
    };

    // Entry point: parse calls starting with the description
    ( description: $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            description: $($items)*
        );
    };
}
<commit_msg>Fix bug in input object macro<commit_after>/**
Create an input object

Input objects are used as data carriers for complex input values to
fields and mutations. Unlike the other helper macros,
`graphql_input_object!` actually *creates* the struct you define. It
does not add anything to the struct definition itself - what you type
is what will be generated:

```rust
# #[macro_use] extern crate juniper;
#
graphql_input_object!(
    description: "Coordinates for the user"

    struct Coordinates {
        longitude: f64 as "The X coordinate, from -180 to +180",
        latitude: f64 as "The Y coordinate, from -90 to +90",
    }
);

# fn main() { }
```

This macro creates the struct as specified and implements
`FromInputValue` to automatically parse values provided from variables
and arguments.

If you want to expose the struct under a different name than the Rust
type, you can write `struct Coordinates as "MyCoordinates" { ...`.

You can specify *default values* for input object fields; the syntax
is similar to argument default values:

```rust
# #[macro_use] extern crate juniper;
#
graphql_input_object!(
    struct SampleObject {
        foo = 123: i64 as "A sample field, defaults to 123 if omitted"
    }
);

# fn main() { }
```

*/
#[macro_export]
macro_rules! graphql_input_object {
    // Calls $val.$func($arg) if $arg is not None
    ( @maybe_apply, None, $func:ident, $val:expr ) => { $val };
    ( @maybe_apply, $arg:tt, $func:ident, $val:expr ) => { $val.$func($arg) };

    // Calls $val.description($descr) when $descr is not empty
    ( @apply_description, , $val:expr ) => { $val };
    ( @apply_description, $descr:tt , $val:expr ) => { $val.description($descr) };

    // Generate the FromInputValue::from method body, provided a
    // HashMap<&str, &InputValue> in $var
    (
        @generate_from_input_value,
        $name:tt, $var:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        Some($name {
            $( $field_name: {
                let n: String = $crate::to_camel_case(stringify!($field_name));
                let v: Option<&&$crate::InputValue> = $var.get(&n[..]);

                println!("Found variable for {:?}: {:?} in {:?}", n, v, $var);

                match v {
                    $( Some(&&$crate::InputValue::Null) | None if true => $default, )*
                        Some(v) => $crate::FromInputValue::from(v).unwrap(),
                        _ => $crate::FromInputValue::from(&$crate::InputValue::null()).unwrap()
                }
            } ),*
        })
    };

    // Generate the struct declaration, including (Rust) meta attributes
    (
        @generate_struct_fields,
        ( $($meta:tt)* ), ( $($pubmod:tt)* ), $name:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        $($meta)* $($pubmod)* struct $name {
            $( $field_name: $field_type, )*
        }
    };

    // Generate single field meta for field with default value
    (
        @generate_single_meta_field,
        $reg:tt,
        ( $field_name:ident = $default:tt : $field_type:ty $(as $descr:tt)* )
    ) => {
        graphql_input_object!(
            @apply_description,
            $($descr)*,
            $reg.arg_with_default::<$field_type>(
                &$crate::to_camel_case(stringify!($field_name)),
                &$default))
    };

    // Generate single field meta for field without default value
    (
        @generate_single_meta_field,
        $reg:tt,
        ( $field_name:ident : $field_type:ty $(as $descr:tt)* )
    ) => {
        graphql_input_object!(
            @apply_description,
            $($descr)*,
            $reg.arg::<$field_type>(
                &$crate::to_camel_case(stringify!($field_name))))
    };

    // Generate the input field meta list, i.e. &[Argument] for
    (
        @generate_meta_fields,
        $reg:tt,
        ( $($field_name:ident $(= $default:tt)* : $field_type:ty $(as $descr:tt)* $(,)* ),* )
    ) => {
        &[
            $(
                graphql_input_object!(
                    @generate_single_meta_field,
                    $reg,
                    ( $field_name $(= $default)* : $field_type $(as $descr)* )
                )
            ),*
        ]
    };

    // #[...] struct $name { ... }
    // struct $name { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* struct $name:ident { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $(#[$meta])* ), ( ), $name, (stringify!($name)), ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] pub struct $name { ... }
    // pub struct $name { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* pub struct $name:ident { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $(#[$meta])* ), ( pub ), $name, (stringify!($name)), ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] struct $name as "GraphQLName" { ... }
    // struct $name as "GraphQLName" { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $($meta)* ), ( ), $name, $outname, ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // #[...] pub struct $name as "GraphQLName" { ... }
    // pub struct $name as "GraphQLName" { ... }
    (
        @parse,
        ( $_ignore1:tt, $_ignore2:tt, $_ignore3:tt, $_ignore4:tt, $_ignore5:tt, $descr:tt ),
        $(#[$meta:meta])* pub struct $name:ident as $outname:tt { $($fields:tt)* } $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( ( $($meta)* ), ( pub ), $name, $outname, ($($fields)*), $descr ),
            $($rest)*
        );
    };

    // description: <description>
    (
        @parse,
        ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $_ignore:tt ),
        description: $descr:tt $($rest:tt)*
    ) => {
        graphql_input_object!(
            @parse,
            ( $meta, $pubmod, $name, $outname, $fields, $descr ),
            $($rest)*
        );
    };

    // No more data to parse, generate the struct and impls
    (
        @parse,
        ( $meta:tt, $pubmod:tt, $name:tt, $outname:tt, $fields:tt, $descr:tt ),
    ) => {
        graphql_input_object!(@generate_struct_fields, $meta, $pubmod, $name, $fields);

        impl $crate::FromInputValue for $name {
            fn from(value: &$crate::InputValue) -> Option<$name> {
                if let Some(obj) = value.to_object_value() {
                    graphql_input_object!(@generate_from_input_value, $name, obj, $fields)
                }
                else {
                   None
                }
            }
        }

        impl $crate::GraphQLType for $name {
            type Context = ();

            fn name() -> Option<&'static str> {
                Some($outname)
            }

            fn meta<'r>(registry: &mut $crate::Registry<'r>) -> $crate::meta::MetaType<'r> {
                let fields = graphql_input_object!(@generate_meta_fields, registry, $fields);
                graphql_input_object!(
                    @maybe_apply, $descr, description,
                    registry.build_input_object_type::<$name>(fields)).into_meta()
            }
        }
    };

    // Entry point: parse calls starting with a struct declaration
    ( $(#[$meta:meta])* struct $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            $(#[$meta])* struct $($items)*
        );
    };

    // Entry point: parse calls starting with a public struct declaration
    ( $(#[$meta:meta])* pub struct $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            $(#[$meta])* pub struct $($items)*
        );
    };

    // Entry point: parse calls starting with the description
    ( description: $($items:tt)* ) => {
        graphql_input_object!(
            @parse,
            ( ( ), ( ), None, None, None, None ),
            description: $($items)*
        );
    };
}
<|endoftext|>


<commit_before>// http://rosettacode.org/wiki/Define_a_primitive_data_type
// Implements a custom type named CustomInt.
// This type only implements a subset of all traits within std::ops.

mod custom_int {
    use std::ops;

    #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)]
    pub struct CustomInt {
        value: u8,
    }

    // constructor function
    pub fn custom_int(v: u8) -> CustomInt {
        let rval = CustomInt { value: v };
        rval.in_bounds();
        rval
    }

    // custom trait to specify bounds
    trait Bounded {
        fn in_bounds(&self);
    }

    impl Bounded for CustomInt {
        fn in_bounds(&self) {
            if self.value < 1 || self.value > 10 {
                panic(self.value);
            }
            #[cold]
            #[inline(never)]
            fn panic(v: u8) -> ! {
                panic!("CustomInt is out of bounds! {} was value", v);
            }
        }
    }

    impl ops::Add for CustomInt {
        type Output = CustomInt;
        fn add(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value + rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::Sub for CustomInt {
        type Output = CustomInt;
        fn sub(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value - rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::Mul for CustomInt {
        type Output = CustomInt;
        fn mul(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value * rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::Div for CustomInt {
        type Output = CustomInt;
        fn div(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value / rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::BitAnd for CustomInt {
        type Output = CustomInt;
        fn bitand(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value & rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::BitOr for CustomInt {
        type Output = CustomInt;
        fn bitor(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value | rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::BitXor for CustomInt {
        type Output = CustomInt;
        fn bitxor(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value ^ rhs.value) };
            rval.in_bounds();
            rval
        }
    }
}

fn main() {
    use custom_int::*;
    let cint_2 = custom_int(2);
    let cint_3 = custom_int(3);
    let cint_4 = custom_int(4);
    cint_2 + cint_4; // CustomInt { value: 6 }
    cint_4 - cint_2; // CustomInt { value: 2 }
    cint_4 * cint_2; // CustomInt { value: 8 }
    cint_4 / cint_2; // CustomInt { value: 2 }
    cint_3 & cint_2; // CustomInt { value: 2 }
    cint_3 | cint_2; // CustomInt { value: 3 }
    cint_3 ^ cint_2; // CustomInt { value: 1 }
}
<commit_msg>add tests for define primitive data type<commit_after>// http://rosettacode.org/wiki/Define_a_primitive_data_type
// Implements a custom type named CustomInt.
// This type only implements a subset of all traits within std::ops.

mod custom_int {
    use std::ops;

    #[derive(Eq, PartialEq, Ord, PartialOrd, Debug, Copy, Clone)]
    pub struct CustomInt {
        value: u8,
    }

    // constructor function
    pub fn custom_int(v: u8) -> CustomInt {
        let rval = CustomInt { value: v };
        rval.in_bounds();
        rval
    }

    // custom trait to specify bounds
    trait Bounded {
        fn in_bounds(&self);
    }

    impl Bounded for CustomInt {
        fn in_bounds(&self) {
            if self.value < 1 || self.value > 10 {
                panic(self.value);
            }
            #[cold]
            #[inline(never)]
            fn panic(v: u8) -> ! {
                panic!("CustomInt is out of bounds! {} was value", v);
            }
        }
    }

    impl ops::Add for CustomInt {
        type Output = CustomInt;
        fn add(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value + rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::Sub for CustomInt {
        type Output = CustomInt;
        fn sub(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value - rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::Mul for CustomInt {
        type Output = CustomInt;
        fn mul(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value * rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::Div for CustomInt {
        type Output = CustomInt;
        fn div(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value / rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::BitAnd for CustomInt {
        type Output = CustomInt;
        fn bitand(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value & rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::BitOr for CustomInt {
        type Output = CustomInt;
        fn bitor(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value | rhs.value) };
            rval.in_bounds();
            rval
        }
    }

    impl ops::BitXor for CustomInt {
        type Output = CustomInt;
        fn bitxor(self, rhs: CustomInt) -> CustomInt {
            let rval = CustomInt { value: (self.value ^ rhs.value) };
            rval.in_bounds();
            rval
        }
    }
}

fn main() {
    use custom_int::*;
    let cint_2 = custom_int(2);
    let cint_3 = custom_int(3);
    let cint_4 = custom_int(4);
    cint_2 + cint_4; // CustomInt { value: 6 }
    cint_4 - cint_2; // CustomInt { value: 2 }
    cint_4 * cint_2; // CustomInt { value: 8 }
    cint_4 / cint_2; // CustomInt { value: 2 }
    cint_3 & cint_2; // CustomInt { value: 2 }
    cint_3 | cint_2; // CustomInt { value: 3 }
    cint_3 ^ cint_2; // CustomInt { value: 1 }
}

#[cfg(test)]
mod tests {
    use custom_int::*;

    #[test]
    fn add_test() {
        let cint_2 = custom_int(2);
        let cint_4 = custom_int(4);
        assert_eq!(custom_int(6), cint_2 + cint_4);
    }

    #[test]
    fn sub_test() {
        let cint_2 = custom_int(2);
        let cint_4 = custom_int(4);
        assert_eq!(custom_int(2), cint_4 - cint_2);
    }

    #[test]
    fn mul_test() {
        let cint_2 = custom_int(2);
        let cint_4 = custom_int(4);
        assert_eq!(custom_int(8), cint_4 * cint_2);
    }

    #[test]
    fn div_test() {
        let cint_2 = custom_int(2);
        let cint_4 = custom_int(4);
        assert_eq!(custom_int(2), cint_4 / cint_2);
    }

    #[test]
    fn and_test() {
        let cint_2 = custom_int(2);
        let cint_3 = custom_int(3);
        assert_eq!(custom_int(2), cint_3 & cint_2);
    }

    #[test]
    fn or_test() {
        let cint_2 = custom_int(2);
        let cint_3 = custom_int(3);
        assert_eq!(custom_int(3), cint_3 | cint_2);
    }

    #[test]
    fn xor_test() {
        let cint_2 = custom_int(2);
        let cint_3 = custom_int(3);
        assert_eq!(custom_int(1), cint_3 ^ cint_2);
    }
}
<|endoftext|>


<commit_before>use rustc::middle::lang_items::PanicLocationLangItem;
use rustc::ty::subst::Subst;
use rustc_span::{Span, Symbol};
use rustc_target::abi::LayoutOf;

use crate::interpret::{
    intrinsics::{InterpCx, Machine},
    MPlaceTy, MemoryKind, Scalar,
};

impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
    /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
    /// frame which is not `#[track_caller]`. If the first frame found lacks `#[track_caller]`, then
    /// `None` is returned and the callsite of the function invocation itself should be used.
    crate fn find_closest_untracked_caller_location(&self) -> Option<Span> {
        let mut caller_span = None;
        for next_caller in self.stack.iter().rev() {
            if !next_caller.instance.def.requires_caller_location(*self.tcx) {
                return caller_span;
            }
            caller_span = Some(next_caller.span);
        }

        caller_span
    }

    /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
    crate fn alloc_caller_location(
        &mut self,
        filename: Symbol,
        line: u32,
        col: u32,
    ) -> MPlaceTy<'tcx, M::PointerTag> {
        let file = self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation);
        let line = Scalar::from_u32(line);
        let col = Scalar::from_u32(col);

        // Allocate memory for `CallerLocation` struct.
        let loc_ty = self
            .tcx
            .type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
            .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter()));
        let loc_layout = self.layout_of(loc_ty).unwrap();
        let location = self.allocate(loc_layout, MemoryKind::CallerLocation);

        // Initialize fields.
        self.write_immediate(file.to_ref(), self.mplace_field(location, 0).unwrap().into())
            .expect("writing to memory we just allocated cannot fail");
        self.write_scalar(line, self.mplace_field(location, 1).unwrap().into())
            .expect("writing to memory we just allocated cannot fail");
        self.write_scalar(col, self.mplace_field(location, 2).unwrap().into())
            .expect("writing to memory we just allocated cannot fail");

        location
    }

    pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> {
        let (file, line, column) = self.location_triple_for_span(span);
        self.alloc_caller_location(file, line, column)
    }

    pub fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
        let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
        let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
        (
            Symbol::intern(&caller.file.name.to_string()),
            caller.line as u32,
            caller.col_display as u32 + 1,
        )
    }
}
<commit_msg>Restrict visibility of location_triple_for_span.<commit_after>use rustc::middle::lang_items::PanicLocationLangItem;
use rustc::ty::subst::Subst;
use rustc_span::{Span, Symbol};
use rustc_target::abi::LayoutOf;

use crate::interpret::{
    intrinsics::{InterpCx, Machine},
    MPlaceTy, MemoryKind, Scalar,
};

impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
    /// Walks up the callstack from the intrinsic's callsite, searching for the first callsite in a
    /// frame which is not `#[track_caller]`. If the first frame found lacks `#[track_caller]`, then
    /// `None` is returned and the callsite of the function invocation itself should be used.
    crate fn find_closest_untracked_caller_location(&self) -> Option<Span> {
        let mut caller_span = None;
        for next_caller in self.stack.iter().rev() {
            if !next_caller.instance.def.requires_caller_location(*self.tcx) {
                return caller_span;
            }
            caller_span = Some(next_caller.span);
        }

        caller_span
    }

    /// Allocate a `const core::panic::Location` with the provided filename and line/column numbers.
    crate fn alloc_caller_location(
        &mut self,
        filename: Symbol,
        line: u32,
        col: u32,
    ) -> MPlaceTy<'tcx, M::PointerTag> {
        let file = self.allocate_str(&filename.as_str(), MemoryKind::CallerLocation);
        let line = Scalar::from_u32(line);
        let col = Scalar::from_u32(col);

        // Allocate memory for `CallerLocation` struct.
        let loc_ty = self
            .tcx
            .type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
            .subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter()));
        let loc_layout = self.layout_of(loc_ty).unwrap();
        let location = self.allocate(loc_layout, MemoryKind::CallerLocation);

        // Initialize fields.
        self.write_immediate(file.to_ref(), self.mplace_field(location, 0).unwrap().into())
            .expect("writing to memory we just allocated cannot fail");
        self.write_scalar(line, self.mplace_field(location, 1).unwrap().into())
            .expect("writing to memory we just allocated cannot fail");
        self.write_scalar(col, self.mplace_field(location, 2).unwrap().into())
            .expect("writing to memory we just allocated cannot fail");

        location
    }

    pub fn alloc_caller_location_for_span(&mut self, span: Span) -> MPlaceTy<'tcx, M::PointerTag> {
        let (file, line, column) = self.location_triple_for_span(span);
        self.alloc_caller_location(file, line, column)
    }

    pub(super) fn location_triple_for_span(&self, span: Span) -> (Symbol, u32, u32) {
        let topmost = span.ctxt().outer_expn().expansion_cause().unwrap_or(span);
        let caller = self.tcx.sess.source_map().lookup_char_pos(topmost.lo());
        (
            Symbol::intern(&caller.file.name.to_string()),
            caller.line as u32,
            caller.col_display as u32 + 1,
        )
    }
}
<|endoftext|>


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

//! MSVC-specific logic for linkers and such.
//!
//! This module contains a cross-platform interface but has a blank unix
//! implementation. The Windows implementation builds on top of Windows native
//! libraries (reading registry keys), so it otherwise wouldn't link on unix.
//!
//! Note that we don't have much special logic for finding the system linker on
//! any other platforms, so it may seem a little odd to single out MSVC to have
//! a good deal of code just to find the linker. Unlike Unix systems, however,
//! the MSVC linker is not in the system PATH by default. It also additionally
//! needs a few environment variables or command line flags to be able to link
//! against system libraries.
//!
//! In order to have a nice smooth experience on Windows, the logic in this file
//! is here to find the MSVC linker and set it up in the default configuration
//! one would need to set up anyway. This means that the Rust compiler can be
//! run not only in the developer shells of MSVC but also the standard cmd.exe
//! shell or MSYS shells.
//!
//! As a high-level note, all logic in this module for looking up various
//! paths/files is copied over from Clang in its MSVCToolChain.cpp file, but
//! comments can also be found below leading through the various code paths.

use std::process::Command;
use session::Session;

#[cfg(windows)]
mod registry;

#[cfg(windows)]
pub fn link_exe_cmd(sess: &Session) -> Command {
    use std::env;
    use std::ffi::OsString;
    use std::fs;
    use std::path::PathBuf;
    use self::registry::{RegistryKey, LOCAL_MACHINE};

    // When finding the link.exe binary the 32-bit version is at the top level
    // but the versions to cross to other architectures are stored in
    // sub-folders. Unknown architectures also just bail out early to return the
    // standard `link.exe` command.
    let extra = match &sess.target.target.arch[..] {
        "x86" => "",
        "x86_64" => "amd64",
        "arm" => "arm",
        _ => return Command::new("link.exe"),
    };

    let vs_install_dir = get_vs_install_dir();

    // First up, we need to find the `link.exe` binary itself, and there's a few
    // locations that we can look. First up is the standard VCINSTALLDIR
    // environment variable which is normally set by the vcvarsall.bat file. If
    // an environment is set up manually by whomever's driving the compiler then
    // we shouldn't muck with that decision and should instead respect that.
    //
    // Next up is looking in PATH itself. Here we look for `cl.exe` and then
    // assume that `link.exe` is next to it if we find it. Note that we look for
    // `cl.exe` because MinGW ships /usr/bin/link.exe which is normally found in
    // PATH but we're not interested in finding that.
    //
    // Finally we read the Windows registry to discover the VS install root.
    // From here we probe for `link.exe` just to make sure that it exists.
    let mut cmd = env::var_os("VCINSTALLDIR").and_then(|dir| {
        let mut p = PathBuf::from(dir);
        p.push("bin");
        p.push(extra);
        p.push("link.exe");
        if fs::metadata(&p).is_ok() {Some(p)} else {None}
    }).or_else(|| {
        env::var_os("PATH").and_then(|path| {
            env::split_paths(&path).find(|path| {
                fs::metadata(&path.join("cl.exe")).is_ok()
            }).map(|p| {
                p.join("link.exe")
            })
        })
    }).or_else(|| {
        vs_install_dir.as_ref().and_then(|p| {
            let mut p = p.join("VC/bin");
            p.push(extra);
            p.push("link.exe");
            if fs::metadata(&p).is_ok() {Some(p)} else {None}
        })
    }).map(|linker| {
        Command::new(linker)
    }).unwrap_or_else(|| {
        Command::new("link.exe")
    });

    // The MSVC linker uses the LIB environment variable as the default lookup
    // path for libraries. This environment variable is normally set up by the
    // VS shells, so we only want to start adding our own pieces if it's not
    // set.
    //
    // If we're adding our own pieces, then we need to add two primary
    // directories to the default search path for the linker. The first is in
    // the VS install direcotry and the next is the Windows SDK directory.
    if env::var_os("LIB").is_none() {
        if let Some(mut vs_install_dir) = vs_install_dir {
            vs_install_dir.push("VC/lib");
            vs_install_dir.push(extra);
            let mut arg = OsString::from("/LIBPATH:");
            arg.push(&vs_install_dir);
            cmd.arg(arg);
        }
        if let Some(path) = get_windows_sdk_lib_path(sess) {
            let mut arg = OsString::from("/LIBPATH:");
            arg.push(&path);
            cmd.arg(arg);
        }
    }

    return cmd;

    // When looking for the Visual Studio installation directory we look in a
    // number of locations in varying degrees of precedence:
    //
    // 1. The Visual Studio registry keys
    // 2. The Visual Studio Express registry keys
    // 3. A number of somewhat standard environment variables
    //
    // If we find a hit from any of these keys then we strip off the IDE/Tools
    // folders which are typically found at the end.
    //
    // As a final note, when we take a look at the registry keys they're
    // typically found underneath the version of what's installed, but we don't
    // quite know what's installed. As a result we probe all sub-keys of the two
    // keys we're looking at to find out the maximum version of what's installed
    // and we use that root directory.
    fn get_vs_install_dir() -> Option<PathBuf> {
        LOCAL_MACHINE.open(r"SOFTWARE\Microsoft\VisualStudio".as_ref()).or_else(|_| {
            LOCAL_MACHINE.open(r"SOFTWARE\Microsoft\VCExpress".as_ref())
        }).ok().and_then(|key| {
            max_version(&key).and_then(|(_vers, key)| {
                key.query_str("InstallDir").ok()
            })
        }).or_else(|| {
            env::var_os("VS120COMNTOOLS")
        }).or_else(|| {
            env::var_os("VS100COMNTOOLS")
        }).or_else(|| {
            env::var_os("VS90COMNTOOLS")
        }).or_else(|| {
            env::var_os("VS80COMNTOOLS")
        }).map(PathBuf::from).and_then(|mut dir| {
            if dir.ends_with("Common7/IDE") || dir.ends_with("Common7/Tools") {
                dir.pop();
                dir.pop();
                Some(dir)
            } else {
                None
            }
        })
    }

    // Given a registry key, look at all the sub keys and find the one which has
    // the maximal numeric value.
    //
    // Returns the name of the maximal key as well as the opened maximal key.
    fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> {
        let mut max_vers = 0;
        let mut max_key = None;
        for subkey in key.iter().filter_map(|k| k.ok()) {
            let val = subkey.to_str().and_then(|s| {
                s.trim_left_matches("v").replace(".", "").parse().ok()
            });
            let val = match val {
                Some(s) => s,
                None => continue,
            };
            if val > max_vers {
                if let Ok(k) = key.open(&subkey) {
                    max_vers = val;
                    max_key = Some((subkey, k));
                }
            }
        }
        return max_key
    }

    fn get_windows_sdk_lib_path(sess: &Session) -> Option<PathBuf> {
        let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows";
        let key = LOCAL_MACHINE.open(key.as_ref());
        let (n, k) = match key.ok().as_ref().and_then(max_version) {
            Some(p) => p,
            None => return None,
        };
        let mut parts = n.to_str().unwrap().trim_left_matches("v").splitn(2, ".");
        let major = parts.next().unwrap().parse::<usize>().unwrap();
        let _minor = parts.next().unwrap().parse::<usize>().unwrap();
        let path = match k.query_str("InstallationFolder") {
            Ok(p) => PathBuf::from(p).join("Lib"),
            Err(..) => return None,
        };
        if major <= 7 {
            // In Windows SDK 7.x, x86 libraries are directly in the Lib folder,
            // x64 libraries are inside, and it's not necessary to link agains
            // the SDK 7.x when targeting ARM or other architectures.
            let x86 = match &sess.target.target.arch[..] {
                "x86" => true,
                "x86_64" => false,
                _ => return None,
            };
            Some(if x86 {path} else {path.join("x64")})
        } else {
            // Windows SDK 8.x installes libraries in a folder whose names
            // depend on the version of the OS you're targeting. By default
            // choose the newest, which usually corresponds to the version of
            // the OS you've installed the SDK on.
            let extra = match &sess.target.target.arch[..] {
                "x86" => "x86",
                "x86_64" => "x64",
                "arm" => "arm",
                _ => return None,
            };
            ["winv6.3", "win8", "win7"].iter().map(|p| path.join(p)).find(|part| {
                fs::metadata(part).is_ok()
            }).map(|path| {
                path.join("um").join(extra)
            })
        }
    }
}

#[cfg(not(windows))]
pub fn link_exe_cmd(_sess: &Session) -> Command {
    Command::new("link.exe")
}
<commit_msg>trans: Try to detect the Universal CRT on MSVC<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! MSVC-specific logic for linkers and such.
//!
//! This module contains a cross-platform interface but has a blank unix
//! implementation. The Windows implementation builds on top of Windows native
//! libraries (reading registry keys), so it otherwise wouldn't link on unix.
//!
//! Note that we don't have much special logic for finding the system linker on
//! any other platforms, so it may seem a little odd to single out MSVC to have
//! a good deal of code just to find the linker. Unlike Unix systems, however,
//! the MSVC linker is not in the system PATH by default. It also additionally
//! needs a few environment variables or command line flags to be able to link
//! against system libraries.
//!
//! In order to have a nice smooth experience on Windows, the logic in this file
//! is here to find the MSVC linker and set it up in the default configuration
//! one would need to set up anyway. This means that the Rust compiler can be
//! run not only in the developer shells of MSVC but also the standard cmd.exe
//! shell or MSYS shells.
//!
//! As a high-level note, all logic in this module for looking up various
//! paths/files is copied over from Clang in its MSVCToolChain.cpp file, but
//! comments can also be found below leading through the various code paths.

use std::process::Command;
use session::Session;

#[cfg(windows)]
mod registry;

#[cfg(windows)]
pub fn link_exe_cmd(sess: &Session) -> Command {
    use std::env;
    use std::ffi::OsString;
    use std::fs;
    use std::io;
    use std::path::{Path, PathBuf};
    use self::registry::{RegistryKey, LOCAL_MACHINE};

    // When finding the link.exe binary the 32-bit version is at the top level
    // but the versions to cross to other architectures are stored in
    // sub-folders. Unknown architectures also just bail out early to return the
    // standard `link.exe` command.
    let extra = match &sess.target.target.arch[..] {
        "x86" => "",
        "x86_64" => "amd64",
        "arm" => "arm",
        _ => return Command::new("link.exe"),
    };

    let vs_install_dir = get_vs_install_dir();

    // First up, we need to find the `link.exe` binary itself, and there's a few
    // locations that we can look. First up is the standard VCINSTALLDIR
    // environment variable which is normally set by the vcvarsall.bat file. If
    // an environment is set up manually by whomever's driving the compiler then
    // we shouldn't muck with that decision and should instead respect that.
    //
    // Next up is looking in PATH itself. Here we look for `cl.exe` and then
    // assume that `link.exe` is next to it if we find it. Note that we look for
    // `cl.exe` because MinGW ships /usr/bin/link.exe which is normally found in
    // PATH but we're not interested in finding that.
    //
    // Finally we read the Windows registry to discover the VS install root.
    // From here we probe for `link.exe` just to make sure that it exists.
    let mut cmd = env::var_os("VCINSTALLDIR").and_then(|dir| {
        let mut p = PathBuf::from(dir);
        p.push("bin");
        p.push(extra);
        p.push("link.exe");
        if fs::metadata(&p).is_ok() {Some(p)} else {None}
    }).or_else(|| {
        env::var_os("PATH").and_then(|path| {
            env::split_paths(&path).find(|path| {
                fs::metadata(&path.join("cl.exe")).is_ok()
            }).map(|p| {
                p.join("link.exe")
            })
        })
    }).or_else(|| {
        vs_install_dir.as_ref().and_then(|p| {
            let mut p = p.join("VC/bin");
            p.push(extra);
            p.push("link.exe");
            if fs::metadata(&p).is_ok() {Some(p)} else {None}
        })
    }).map(|linker| {
        Command::new(linker)
    }).unwrap_or_else(|| {
        Command::new("link.exe")
    });

    // The MSVC linker uses the LIB environment variable as the default lookup
    // path for libraries. This environment variable is normally set up by the
    // VS shells, so we only want to start adding our own pieces if it's not
    // set.
    //
    // If we're adding our own pieces, then we need to add a few primary
    // directories to the default search path for the linker. The first is in
    // the VS install direcotry, the next is the Windows SDK directory, and the
    // last is the possible UCRT installation directory.
    //
    // The UCRT is a recent addition to Visual Studio installs (2015 at the time
    // of this writing), and it's in the normal windows SDK folder, but there
    // apparently aren't registry keys pointing to it. As a result we detect the
    // installation and then add it manually. This logic will probably need to
    // be tweaked over time...
    if env::var_os("LIB").is_none() {
        if let Some(mut vs_install_dir) = vs_install_dir {
            vs_install_dir.push("VC/lib");
            vs_install_dir.push(extra);
            let mut arg = OsString::from("/LIBPATH:");
            arg.push(&vs_install_dir);
            cmd.arg(arg);

            if let Some((ucrt_root, vers)) = ucrt_install_dir(&vs_install_dir) {
                if let Some(arch) = windows_sdk_v8_subdir(sess) {
                    let mut arg = OsString::from("/LIBPATH:");
                    arg.push(ucrt_root.join("Lib").join(vers)
                                      .join("ucrt").join(arch));
                    cmd.arg(arg);
                }
            }
        }
        if let Some(path) = get_windows_sdk_lib_path(sess) {
            let mut arg = OsString::from("/LIBPATH:");
            arg.push(&path);
            cmd.arg(arg);
        }
    }

    return cmd;

    // When looking for the Visual Studio installation directory we look in a
    // number of locations in varying degrees of precedence:
    //
    // 1. The Visual Studio registry keys
    // 2. The Visual Studio Express registry keys
    // 3. A number of somewhat standard environment variables
    //
    // If we find a hit from any of these keys then we strip off the IDE/Tools
    // folders which are typically found at the end.
    //
    // As a final note, when we take a look at the registry keys they're
    // typically found underneath the version of what's installed, but we don't
    // quite know what's installed. As a result we probe all sub-keys of the two
    // keys we're looking at to find out the maximum version of what's installed
    // and we use that root directory.
    fn get_vs_install_dir() -> Option<PathBuf> {
        LOCAL_MACHINE.open(r"SOFTWARE\Microsoft\VisualStudio".as_ref()).or_else(|_| {
            LOCAL_MACHINE.open(r"SOFTWARE\Microsoft\VCExpress".as_ref())
        }).ok().and_then(|key| {
            max_version(&key).and_then(|(_vers, key)| {
                key.query_str("InstallDir").ok()
            })
        }).or_else(|| {
            env::var_os("VS120COMNTOOLS")
        }).or_else(|| {
            env::var_os("VS100COMNTOOLS")
        }).or_else(|| {
            env::var_os("VS90COMNTOOLS")
        }).or_else(|| {
            env::var_os("VS80COMNTOOLS")
        }).map(PathBuf::from).and_then(|mut dir| {
            if dir.ends_with("Common7/IDE") || dir.ends_with("Common7/Tools") {
                dir.pop();
                dir.pop();
                Some(dir)
            } else {
                None
            }
        })
    }

    // Given a registry key, look at all the sub keys and find the one which has
    // the maximal numeric value.
    //
    // Returns the name of the maximal key as well as the opened maximal key.
    fn max_version(key: &RegistryKey) -> Option<(OsString, RegistryKey)> {
        let mut max_vers = 0;
        let mut max_key = None;
        for subkey in key.iter().filter_map(|k| k.ok()) {
            let val = subkey.to_str().and_then(|s| {
                s.trim_left_matches("v").replace(".", "").parse().ok()
            });
            let val = match val {
                Some(s) => s,
                None => continue,
            };
            if val > max_vers {
                if let Ok(k) = key.open(&subkey) {
                    max_vers = val;
                    max_key = Some((subkey, k));
                }
            }
        }
        return max_key
    }

    fn get_windows_sdk_path() -> Option<(PathBuf, usize)> {
        let key = r"SOFTWARE\Microsoft\Microsoft SDKs\Windows";
        let key = LOCAL_MACHINE.open(key.as_ref());
        let (n, k) = match key.ok().as_ref().and_then(max_version) {
            Some(p) => p,
            None => return None,
        };
        let mut parts = n.to_str().unwrap().trim_left_matches("v").splitn(2, ".");
        let major = parts.next().unwrap().parse::<usize>().unwrap();
        let _minor = parts.next().unwrap().parse::<usize>().unwrap();
        k.query_str("InstallationFolder").ok().map(|folder| {
            (PathBuf::from(folder), major)
        })
    }

    fn get_windows_sdk_lib_path(sess: &Session) -> Option<PathBuf> {
        let (mut path, major) = match get_windows_sdk_path() {
            Some(p) => p,
            None => return None,
        };
        path.push("Lib");
        if major <= 7 {
            // In Windows SDK 7.x, x86 libraries are directly in the Lib folder,
            // x64 libraries are inside, and it's not necessary to link agains
            // the SDK 7.x when targeting ARM or other architectures.
            let x86 = match &sess.target.target.arch[..] {
                "x86" => true,
                "x86_64" => false,
                _ => return None,
            };
            Some(if x86 {path} else {path.join("x64")})
        } else {
            // Windows SDK 8.x installes libraries in a folder whose names
            // depend on the version of the OS you're targeting. By default
            // choose the newest, which usually corresponds to the version of
            // the OS you've installed the SDK on.
            let extra = match windows_sdk_v8_subdir(sess) {
                Some(e) => e,
                None => return None,
            };
            ["winv6.3", "win8", "win7"].iter().map(|p| path.join(p)).find(|part| {
                fs::metadata(part).is_ok()
            }).map(|path| {
                path.join("um").join(extra)
            })
        }
    }

    fn windows_sdk_v8_subdir(sess: &Session) -> Option<&'static str> {
        match &sess.target.target.arch[..] {
            "x86" => Some("x86"),
            "x86_64" => Some("x64"),
            "arm" => Some("arm"),
            _ => return None,
        }
    }

    fn ucrt_install_dir(vs_install_dir: &Path) -> Option<(PathBuf, String)> {
        let is_vs_14 = vs_install_dir.iter().filter_map(|p| p.to_str()).any(|s| {
            s == "Microsoft Visual Studio 14.0"
        });
        if !is_vs_14 {
            return None
        }
        let key = r"SOFTWARE\Microsoft\Windows Kits\Installed Roots";
        let sdk_dir = LOCAL_MACHINE.open(key.as_ref()).and_then(|p| {
            p.query_str("KitsRoot10")
        }).map(PathBuf::from);
        let sdk_dir = match sdk_dir {
            Ok(p) => p,
            Err(..) => return None,
        };
        (move || -> io::Result<_> {
            let mut max = None;
            let mut max_s = None;
            for entry in try!(fs::read_dir(&sdk_dir.join("Lib"))) {
                let entry = try!(entry);
                if let Ok(s) = entry.file_name().into_string() {
                    if let Ok(u) = s.replace(".", "").parse::<usize>() {
                        if Some(u) > max {
                            max = Some(u);
                            max_s = Some(s);
                        }
                    }
                }
            }
            Ok(max_s.map(|m| (sdk_dir, m)))
        })().ok().and_then(|x| x)
    }
}

#[cfg(not(windows))]
pub fn link_exe_cmd(_sess: &Session) -> Command {
    Command::new("link.exe")
}
<|endoftext|>


<commit_before>use error::Error;
use client::Client;
use params::{List, Metadata, Timestamp};
use resources::{Currency, Discount, Plan};
use serde_qs as query;

/// The set of parameters that can be used when creating or updating an invoice.
///
/// For more details see https://stripe.com/docs/api#create_invoice, https://stripe.com/docs/api#update_invoice.
#[derive(Default, Serialize)]
pub struct InvoiceParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub statement_descriptor: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub subscription: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub tax_percent: Option<f64>,

    #[serde(skip_serializing_if = "Option::is_none")] pub closed: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub forgiven: Option<bool>,
}

/*
#[derive(Serialize)]
pub struct InvoiceListLinesParams {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub ending_before: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")] pub starting_after: Option<String>,

    ..
}
*/

/// Period is a structure representing a start and end dates.
#[derive(Debug, Deserialize)]
pub struct Period {
    pub start: Timestamp,
    pub end: Timestamp,
}

/// The resource representing a Stripe invoice line item.
///
/// For more details see https://stripe.com/docs/api#invoice_line_item_object.
#[derive(Debug, Deserialize)]
pub struct InvoiceLine {
    pub id: String,
    pub amount: u64,
    pub currency: Currency,
    pub description: Option<String>,
    pub discountable: bool,
    pub livemode: bool,
    pub metadata: Metadata,
    pub period: Period,
    pub plan: Option<Plan>,
    pub proration: bool,
    pub quantity: Option<u64>,
    pub subscription: Option<String>,
    pub subscription_item: Option<String>,
    #[serde(rename = "type")] pub item_type: String, // (invoiceitem, subscription)
}

/// The resource representing a Stripe invoice.
///
/// For more details see https://stripe.com/docs/api#invoice_object.
#[derive(Debug, Deserialize)]
pub struct Invoice {
    pub id: String,
    pub amount_due: u64,
    pub application_fee: Option<u64>,
    pub attempt_count: u64,
    pub attempted: bool,
    pub charge: Option<String>,
    pub closed: bool,
    pub currency: Currency,
    pub customer: String,
    pub date: Timestamp,
    pub description: Option<String>,
    pub discount: Option<Discount>,
    pub ending_balance: Option<i64>,
    pub forgiven: bool,
    pub lines: List<InvoiceLine>,
    pub livemode: bool,
    pub metadata: Metadata,
    pub next_payment_attempt: Option<Timestamp>,
    pub paid: bool,
    pub period_end: Timestamp,
    pub period_start: Timestamp,
    pub receipt_number: Option<String>,
    pub starting_balance: i64,
    pub statment_descriptor: Option<String>,
    pub subscription: Option<String>,
    pub subscription_proration_date: Option<Timestamp>,
    pub subtotal: i64,
    pub tax: Option<i64>,
    pub tax_percent: Option<f64>,
    pub total: i64,
    pub webhooks_delivered_at: Option<Timestamp>,
}

#[derive(Default, Serialize)]
pub struct InvoiceListParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
}

impl Invoice {
    /// Creates a new invoice.
    ///
    /// For more details see https://stripe.com/docs/api#create_invoice.
    pub fn create(client: &Client, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post("/invoices", params)
    }

    /// Retrieves the details of an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#retrieve_invoice.
    pub fn retrieve(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.get(&format!("/invoices/{}", invoice_id))
    }

    // TODO: Implement InvoiceListLinesParams
    // pub fn get_lines(client: &Client, invoice_id: &str, params: InvoiceListLinesParams) -> Result<List<InvoiceLine>, Error> {
    //     client.get(&format!("/invoices/{}/lines", invoice_id))
    // }

    // TODO: Implement InvoiceUpcomingParams
    // pub fn get_upcoming(client: &Client, params: InvoiceUpcomingParams) -> Result<Invoice, Error> {
    //     client.get(&format!("/invoices/upcoming?customer={}", invoice_id))
    // }

    /// Pays an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#pay_invoice.
    pub fn pay(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.post_empty(&format!("/invoices/{}/pay", invoice_id))
    }

    /// Updates an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#update_invoice.
    pub fn update(client: &Client, invoice_id: &str, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post(&format!("/invoices/{}", invoice_id), &params)
    }

    /// Lists all invoices with optional customer_id and limit params
    ///
    /// For more details see https://stripe.com/docs/api#list_invoices.
    pub fn list(client: &Client, params: InvoiceListParams) -> Result<List<Invoice>, Error> {
        client.get(&format!("/invoices?{}", query::to_string(&params)?))
    }
}
<commit_msg>Add create invoice items<commit_after>use error::Error;
use client::Client;
use params::{List, Metadata, Timestamp};
use resources::{Currency, Discount, Plan};
use serde_qs as query;

/// The set of parameters that can be used when creating or updating an invoice.
///
/// For more details see https://stripe.com/docs/api#create_invoice, https://stripe.com/docs/api#update_invoice.
#[derive(Default, Serialize)]
pub struct InvoiceParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub application_fee: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub statement_descriptor: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub subscription: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub tax_percent: Option<f64>,

    #[serde(skip_serializing_if = "Option::is_none")] pub closed: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub forgiven: Option<bool>,
}

#[derive(Default, Serialize)]
pub struct InvoiceItemParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub amount: Option<i64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub currency: Option<Currency>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub description: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub discountable: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub invoice: Option<&'a str>,
    #[serde(skip_serializing_if = "Option::is_none")] pub metadata: Option<bool>,
    #[serde(skip_serializing_if = "Option::is_none")] pub subscription: Option<bool>,
}

/*
#[derive(Serialize)]
pub struct InvoiceListLinesParams {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub ending_before: Option<String>,
    #[serde(skip_serializing_if = "Option::is_none")] pub starting_after: Option<String>,

    ..
}
*/

/// Period is a structure representing a start and end dates.
#[derive(Debug, Deserialize)]
pub struct Period {
    pub start: Timestamp,
    pub end: Timestamp,
}

/// The resource representing a Stripe invoice line item.
///
/// For more details see https://stripe.com/docs/api#invoice_line_item_object.
#[derive(Debug, Deserialize)]
pub struct InvoiceLine {
    pub id: String,
    pub amount: u64,
    pub currency: Currency,
    pub description: Option<String>,
    pub discountable: bool,
    pub livemode: bool,
    pub metadata: Metadata,
    pub period: Period,
    pub plan: Option<Plan>,
    pub proration: bool,
    pub quantity: Option<u64>,
    pub subscription: Option<String>,
    pub subscription_item: Option<String>,
    #[serde(rename = "type")] pub item_type: String, // (invoiceitem, subscription)
}

/// The resource representing a Stripe invoice.
///
/// For more details see https://stripe.com/docs/api#invoice_object.
#[derive(Debug, Deserialize)]
pub struct Invoice {
    pub id: String,
    pub amount_due: u64,
    pub application_fee: Option<u64>,
    pub attempt_count: u64,
    pub attempted: bool,
    pub charge: Option<String>,
    pub closed: bool,
    pub currency: Currency,
    pub customer: String,
    pub date: Timestamp,
    pub description: Option<String>,
    pub discount: Option<Discount>,
    pub ending_balance: Option<i64>,
    pub forgiven: bool,
    pub lines: List<InvoiceLine>,
    pub livemode: bool,
    pub metadata: Metadata,
    pub next_payment_attempt: Option<Timestamp>,
    pub paid: bool,
    pub period_end: Timestamp,
    pub period_start: Timestamp,
    pub receipt_number: Option<String>,
    pub starting_balance: i64,
    pub statment_descriptor: Option<String>,
    pub subscription: Option<String>,
    pub subscription_proration_date: Option<Timestamp>,
    pub subtotal: i64,
    pub tax: Option<i64>,
    pub tax_percent: Option<f64>,
    pub total: i64,
    pub webhooks_delivered_at: Option<Timestamp>,
}

#[derive(Default, Serialize)]
pub struct InvoiceListParams<'a> {
    #[serde(skip_serializing_if = "Option::is_none")] pub limit: Option<u64>,
    #[serde(skip_serializing_if = "Option::is_none")] pub customer: Option<&'a str>,
}

impl Invoice {
    /// Creates a new invoice.
    ///
    /// For more details see https://stripe.com/docs/api#create_invoice.
    pub fn create(client: &Client, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post("/invoices", params)
    }

    /// Retrieves the details of an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#retrieve_invoice.
    pub fn retrieve(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.get(&format!("/invoices/{}", invoice_id))
    }

    // TODO: Implement InvoiceListLinesParams
    // pub fn get_lines(client: &Client, invoice_id: &str, params: InvoiceListLinesParams) -> Result<List<InvoiceLine>, Error> {
    //     client.get(&format!("/invoices/{}/lines", invoice_id))
    // }

    // TODO: Implement InvoiceUpcomingParams
    // pub fn get_upcoming(client: &Client, params: InvoiceUpcomingParams) -> Result<Invoice, Error> {
    //     client.get(&format!("/invoices/upcoming?customer={}", invoice_id))
    // }

    /// Pays an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#pay_invoice.
    pub fn pay(client: &Client, invoice_id: &str) -> Result<Invoice, Error> {
        client.post_empty(&format!("/invoices/{}/pay", invoice_id))
    }

    /// Updates an invoice.
    ///
    /// For more details see https://stripe.com/docs/api#update_invoice.
    pub fn update(client: &Client, invoice_id: &str, params: InvoiceParams) -> Result<Invoice, Error> {
        client.post(&format!("/invoices/{}", invoice_id), &params)
    }

    /// Lists all invoices with optional customer_id and limit params
    ///
    /// For more details see https://stripe.com/docs/api#list_invoices.
    pub fn list(client: &Client, params: InvoiceListParams) -> Result<List<Invoice>, Error> {
        client.get(&format!("/invoices?{}", query::to_string(&params)?))
    }
}

impl InvoiceLine {
    /// Creates an invoice line item.
    ///
    /// For more details see https://stripe.com/docs/api/node#invoice_line_item_object
    pub fn create(client: &Client, params: InvoiceItemParams) -> Result<InvoiceLine, Error> {
        client.post(&format!("/invoiceitems"), &params)
    }

}
<|endoftext|>