<commit_before>use hir::def_id::DefId;
use infer::error_reporting::nice_region_error::NiceRegionError;
use infer::lexical_region_resolve::RegionResolutionError;
use infer::ValuePairs;
use infer::{SubregionOrigin, TypeTrace};
use traits::{ObligationCause, ObligationCauseCode};
use ty;
use ty::error::ExpectedFound;
use ty::subst::Substs;
use util::common::ErrorReported;
use util::ppaux::RegionHighlightMode;

impl NiceRegionError<'me, 'gcx, 'tcx> {
    /// When given a `ConcreteFailure` for a function with arguments containing a named region and
    /// an anonymous region, emit an descriptive diagnostic error.
    pub(super) fn try_report_placeholder_conflict(&self) -> Option<ErrorReported> {
        match &self.error {
            ///////////////////////////////////////////////////////////////////////////
            // NB. The ordering of cases in this match is very
            // sensitive, because we are often matching against
            // specific cases and then using an `_` to match all
            // others.

            ///////////////////////////////////////////////////////////////////////////
            // Check for errors from comparing trait failures -- first
            // with two placeholders, then with one.
            Some(RegionResolutionError::SubSupConflict(
                vid,
                _,
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_placeholder @ ty::RePlaceholder(_),
                _,
                sup_placeholder @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(self.tcx().mk_region(ty::ReVar(*vid))),
                    cause,
                    Some(sub_placeholder),
                    Some(sup_placeholder),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::SubSupConflict(
                vid,
                _,
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_placeholder @ ty::RePlaceholder(_),
                _,
                _,
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(self.tcx().mk_region(ty::ReVar(*vid))),
                    cause,
                    Some(sub_placeholder),
                    None,
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::SubSupConflict(
                vid,
                _,
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                _,
                _,
                sup_placeholder @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(self.tcx().mk_region(ty::ReVar(*vid))),
                    cause,
                    None,
                    Some(*sup_placeholder),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::SubSupConflict(
                vid,
                _,
                _,
                _,
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sup_placeholder @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(self.tcx().mk_region(ty::ReVar(*vid))),
                    cause,
                    None,
                    Some(*sup_placeholder),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::ConcreteFailure(
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_region @ ty::RePlaceholder(_),
                sup_region @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    None,
                    cause,
                    Some(*sub_region),
                    Some(*sup_region),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::ConcreteFailure(
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_region @ ty::RePlaceholder(_),
                sup_region,
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(sup_region),
                    cause,
                    Some(*sub_region),
                    None,
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::ConcreteFailure(
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_region,
                sup_region @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(sub_region),
                    cause,
                    None,
                    Some(*sup_region),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            _ => None,
        }
    }

    // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
    //   --> /home/nmatsakis/tmp/foo.rs:12:5
    //    |
    // 12 |     all::<&'static u32>();
    //    |     ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    //    |
    //    = note: Due to a where-clause on the function `all`,
    //    = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
    //    = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
    fn try_report_placeholders_trait(
        &self,
        vid: Option<ty::Region<'tcx>>,
        cause: &ObligationCause<'tcx>,
        sub_placeholder: Option<ty::Region<'tcx>>,
        sup_placeholder: Option<ty::Region<'tcx>>,
        trait_def_id: DefId,
        expected_substs: &'tcx Substs<'tcx>,
        actual_substs: &'tcx Substs<'tcx>,
    ) -> ErrorReported {
        let mut err = self.tcx().sess.struct_span_err(
            cause.span(&self.tcx()),
            &format!(
                "implementation of `{}` is not general enough",
                self.tcx().item_path_str(trait_def_id),
            ),
        );

        match cause.code {
            ObligationCauseCode::ItemObligation(def_id) => {
                err.note(&format!(
                    "Due to a where-clause on `{}`,",
                    self.tcx().item_path_str(def_id),
                ));
            }
            _ => (),
        }

        let expected_trait_ref = ty::TraitRef {
            def_id: trait_def_id,
            substs: expected_substs,
        };
        let actual_trait_ref = ty::TraitRef {
            def_id: trait_def_id,
            substs: actual_substs,
        };

        // Search the expected and actual trait references to see (a)
        // whether the sub/sup placeholders appear in them (sometimes
        // you have a trait ref like `T: Foo<fn(&u8)>`, where the
        // placeholder was created as part of an inner type) and (b)
        // whether the inference variable appears. In each case,
        // assign a counter value in each case if so.
        let mut counter = 0;
        let mut has_sub = None;
        let mut has_sup = None;
        let mut has_vid = None;

        self.tcx().for_each_free_region(&expected_trait_ref, |r| {
            if Some(r) == sub_placeholder && has_sub.is_none() {
                has_sub = Some(counter);
                counter += 1;
            } else if Some(r) == sup_placeholder && has_sup.is_none() {
                has_sup = Some(counter);
                counter += 1;
            }
        });

        self.tcx().for_each_free_region(&actual_trait_ref, |r| {
            if Some(r) == vid && has_vid.is_none() {
                has_vid = Some(counter);
                counter += 1;
            }
        });

        let self_ty_has_vid = self
            .tcx()
            .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);

        RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || {
            RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || {
                match (has_sub, has_sup) {
                    (Some(n1), Some(n2)) => {
                        err.note(&format!(
                            "`{}` must implement `{}` \
                             for any two lifetimes `'{}` and `'{}`",
                            expected_trait_ref.self_ty(),
                            expected_trait_ref,
                            std::cmp::min(n1, n2),
                            std::cmp::max(n1, n2),
                        ));
                    }
                    (Some(n), _) | (_, Some(n)) => {
                        err.note(&format!(
                            "`{}` must implement `{}` \
                             for any lifetime `'{}`",
                            expected_trait_ref.self_ty(),
                            expected_trait_ref,
                            n,
                        ));
                    }
                    (None, None) => {
                        err.note(&format!(
                            "`{}` must implement `{}`",
                            expected_trait_ref.self_ty(),
                            expected_trait_ref,
                        ));
                    }
                }
            })
        });

        RegionHighlightMode::maybe_highlighting_region(vid, has_vid, || match has_vid {
            Some(n) => {
                if self_ty_has_vid {
                    err.note(&format!(
                        "but `{}` only implements `{}` for the lifetime `'{}`",
                        actual_trait_ref.self_ty(),
                        actual_trait_ref,
                        n
                    ));
                } else {
                    err.note(&format!(
                        "but `{}` only implements `{}` for some lifetime `'{}`",
                        actual_trait_ref.self_ty(),
                        actual_trait_ref,
                        n
                    ));
                }
            }
            None => {
                err.note(&format!(
                    "but `{}` only implements `{}`",
                    actual_trait_ref.self_ty(),
                    actual_trait_ref,
                ));
            }
        });

        err.emit();
        ErrorReported
    }
}
<commit_msg>Try to resolve type vars in the placeholder errors trait refs<commit_after>use hir::def_id::DefId;
use infer::error_reporting::nice_region_error::NiceRegionError;
use infer::lexical_region_resolve::RegionResolutionError;
use infer::ValuePairs;
use infer::{SubregionOrigin, TypeTrace};
use traits::{ObligationCause, ObligationCauseCode};
use ty;
use ty::error::ExpectedFound;
use ty::subst::Substs;
use util::common::ErrorReported;
use util::ppaux::RegionHighlightMode;

impl NiceRegionError<'me, 'gcx, 'tcx> {
    /// When given a `ConcreteFailure` for a function with arguments containing a named region and
    /// an anonymous region, emit an descriptive diagnostic error.
    pub(super) fn try_report_placeholder_conflict(&self) -> Option<ErrorReported> {
        match &self.error {
            ///////////////////////////////////////////////////////////////////////////
            // NB. The ordering of cases in this match is very
            // sensitive, because we are often matching against
            // specific cases and then using an `_` to match all
            // others.

            ///////////////////////////////////////////////////////////////////////////
            // Check for errors from comparing trait failures -- first
            // with two placeholders, then with one.
            Some(RegionResolutionError::SubSupConflict(
                vid,
                _,
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_placeholder @ ty::RePlaceholder(_),
                _,
                sup_placeholder @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(self.tcx().mk_region(ty::ReVar(*vid))),
                    cause,
                    Some(sub_placeholder),
                    Some(sup_placeholder),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::SubSupConflict(
                vid,
                _,
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_placeholder @ ty::RePlaceholder(_),
                _,
                _,
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(self.tcx().mk_region(ty::ReVar(*vid))),
                    cause,
                    Some(sub_placeholder),
                    None,
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::SubSupConflict(
                vid,
                _,
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                _,
                _,
                sup_placeholder @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(self.tcx().mk_region(ty::ReVar(*vid))),
                    cause,
                    None,
                    Some(*sup_placeholder),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::SubSupConflict(
                vid,
                _,
                _,
                _,
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sup_placeholder @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(self.tcx().mk_region(ty::ReVar(*vid))),
                    cause,
                    None,
                    Some(*sup_placeholder),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::ConcreteFailure(
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_region @ ty::RePlaceholder(_),
                sup_region @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    None,
                    cause,
                    Some(*sub_region),
                    Some(*sup_region),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::ConcreteFailure(
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_region @ ty::RePlaceholder(_),
                sup_region,
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(sup_region),
                    cause,
                    Some(*sub_region),
                    None,
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            Some(RegionResolutionError::ConcreteFailure(
                SubregionOrigin::Subtype(TypeTrace {
                    cause,
                    values: ValuePairs::TraitRefs(ExpectedFound { expected, found }),
                }),
                sub_region,
                sup_region @ ty::RePlaceholder(_),
            ))
                if expected.def_id == found.def_id =>
            {
                Some(self.try_report_placeholders_trait(
                    Some(sub_region),
                    cause,
                    None,
                    Some(*sup_region),
                    expected.def_id,
                    expected.substs,
                    found.substs,
                ))
            }

            _ => None,
        }
    }

    // error[E0308]: implementation of `Foo` does not apply to enough lifetimes
    //   --> /home/nmatsakis/tmp/foo.rs:12:5
    //    |
    // 12 |     all::<&'static u32>();
    //    |     ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    //    |
    //    = note: Due to a where-clause on the function `all`,
    //    = note: `T` must implement `...` for any two lifetimes `'1` and `'2`.
    //    = note: However, the type `T` only implements `...` for some specific lifetime `'2`.
    fn try_report_placeholders_trait(
        &self,
        vid: Option<ty::Region<'tcx>>,
        cause: &ObligationCause<'tcx>,
        sub_placeholder: Option<ty::Region<'tcx>>,
        sup_placeholder: Option<ty::Region<'tcx>>,
        trait_def_id: DefId,
        expected_substs: &'tcx Substs<'tcx>,
        actual_substs: &'tcx Substs<'tcx>,
    ) -> ErrorReported {
        let mut err = self.tcx().sess.struct_span_err(
            cause.span(&self.tcx()),
            &format!(
                "implementation of `{}` is not general enough",
                self.tcx().item_path_str(trait_def_id),
            ),
        );

        match cause.code {
            ObligationCauseCode::ItemObligation(def_id) => {
                err.note(&format!(
                    "Due to a where-clause on `{}`,",
                    self.tcx().item_path_str(def_id),
                ));
            }
            _ => (),
        }

        let expected_trait_ref = self.infcx.resolve_type_vars_if_possible(
            &ty::TraitRef {
                def_id: trait_def_id,
                substs: expected_substs,
            }
        );
        let actual_trait_ref = self.infcx.resolve_type_vars_if_possible(
            &ty::TraitRef {
                def_id: trait_def_id,
                substs: actual_substs,
            }
        );

        // Search the expected and actual trait references to see (a)
        // whether the sub/sup placeholders appear in them (sometimes
        // you have a trait ref like `T: Foo<fn(&u8)>`, where the
        // placeholder was created as part of an inner type) and (b)
        // whether the inference variable appears. In each case,
        // assign a counter value in each case if so.
        let mut counter = 0;
        let mut has_sub = None;
        let mut has_sup = None;
        let mut has_vid = None;

        self.tcx().for_each_free_region(&expected_trait_ref, |r| {
            if Some(r) == sub_placeholder && has_sub.is_none() {
                has_sub = Some(counter);
                counter += 1;
            } else if Some(r) == sup_placeholder && has_sup.is_none() {
                has_sup = Some(counter);
                counter += 1;
            }
        });

        self.tcx().for_each_free_region(&actual_trait_ref, |r| {
            if Some(r) == vid && has_vid.is_none() {
                has_vid = Some(counter);
                counter += 1;
            }
        });

        let self_ty_has_vid = self
            .tcx()
            .any_free_region_meets(&actual_trait_ref.self_ty(), |r| Some(r) == vid);

        RegionHighlightMode::maybe_highlighting_region(sub_placeholder, has_sub, || {
            RegionHighlightMode::maybe_highlighting_region(sup_placeholder, has_sup, || {
                match (has_sub, has_sup) {
                    (Some(n1), Some(n2)) => {
                        err.note(&format!(
                            "`{}` must implement `{}` \
                             for any two lifetimes `'{}` and `'{}`",
                            expected_trait_ref.self_ty(),
                            expected_trait_ref,
                            std::cmp::min(n1, n2),
                            std::cmp::max(n1, n2),
                        ));
                    }
                    (Some(n), _) | (_, Some(n)) => {
                        err.note(&format!(
                            "`{}` must implement `{}` \
                             for any lifetime `'{}`",
                            expected_trait_ref.self_ty(),
                            expected_trait_ref,
                            n,
                        ));
                    }
                    (None, None) => {
                        err.note(&format!(
                            "`{}` must implement `{}`",
                            expected_trait_ref.self_ty(),
                            expected_trait_ref,
                        ));
                    }
                }
            })
        });

        RegionHighlightMode::maybe_highlighting_region(vid, has_vid, || match has_vid {
            Some(n) => {
                if self_ty_has_vid {
                    err.note(&format!(
                        "but `{}` only implements `{}` for the lifetime `'{}`",
                        actual_trait_ref.self_ty(),
                        actual_trait_ref,
                        n
                    ));
                } else {
                    err.note(&format!(
                        "but `{}` only implements `{}` for some lifetime `'{}`",
                        actual_trait_ref.self_ty(),
                        actual_trait_ref,
                        n
                    ));
                }
            }
            None => {
                err.note(&format!(
                    "but `{}` only implements `{}`",
                    actual_trait_ref.self_ty(),
                    actual_trait_ref,
                ));
            }
        });

        err.emit();
        ErrorReported
    }
}
<|endoftext|>


<commit_before>use proc_macro2::TokenStream;

use quote::ToTokens;

use shared::path;

use std::path::PathBuf;

use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub source: Source,
    pub print: Print,
    pub escaping: EscapeMode,
    pub ext: Option<String>,
    pub parent: Option<&'a syn::Type>,
    pub path: PathBuf,
}

impl<'a> TemplateInput<'a> {
    pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
        let mut meta = None;
        for attr in &ast.attrs {
            match attr.interpret_meta() {
                Some(m) => if m.name() == "template" {
                    meta = Some(m)
                },
                None => {
                    let mut tokens = TokenStream::new();
                    attr.to_tokens(&mut tokens);
                    panic!("unable to interpret attribute: {}", tokens)
                }
            }
        }

        let meta_list = match meta.expect("no attribute 'template' found") {
            syn::Meta::List(inner) => inner,
            _ => panic!("attribute 'template' has incorrect type"),
        };

        let mut source = None;
        let mut print = Print::None;
        let mut escaping = None;
        let mut ext = None;
        for nm_item in meta_list.nested {
            if let syn::NestedMeta::Meta(ref item) = nm_item {
                if let syn::Meta::NameValue(ref pair) = item {
                    match pair.ident.to_string().as_ref() {
                        "path" => if let syn::Lit::Str(ref s) = pair.lit {
                            if source.is_some() {
                                panic!("must specify 'source' or 'path', not both");
                            }
                            source = Some(Source::Path(s.value()));
                        } else {
                            panic!("template path must be string literal");
                        },
                        "source" => if let syn::Lit::Str(ref s) = pair.lit {
                            if source.is_some() {
                                panic!("must specify 'source' or 'path', not both");
                            }
                            source = Some(Source::Source(s.value()));
                        } else {
                            panic!("template source must be string literal");
                        },
                        "print" => if let syn::Lit::Str(ref s) = pair.lit {
                            print = s.value().into();
                        } else {
                            panic!("print value must be string literal");
                        },
                        "escape" => if let syn::Lit::Str(ref s) = pair.lit {
                            escaping = Some(s.value().into());
                        } else {
                            panic!("escape value must be string literal");
                        },
                        "ext" => if let syn::Lit::Str(ref s) = pair.lit {
                            ext = Some(s.value());
                        } else {
                            panic!("ext value must be string literal");
                        },
                        attr => panic!("unsupported annotation key '{}' found", attr),
                    }
                }
            }
        }

        let source = source.expect("template path or source not found in attributes");
        let path = match (&source, &ext) {
            (&Source::Path(ref path), None) => path::find_template_from_path(path, None),
            (&Source::Source(_), Some(ext)) => PathBuf::from(format!("{}.{}", ast.ident, ext)),
            (&Source::Path(_), Some(_)) => {
                panic!("'ext' attribute cannot be used with 'path' attribute")
            }
            (&Source::Source(_), None) => {
                panic!("must include 'ext' attribute when using 'source' attribute")
            }
        };

        let parent = match ast.data {
            syn::Data::Struct(syn::DataStruct {
                fields: syn::Fields::Named(ref fields),
                ..
            }) => fields
                .named
                .iter()
                .find(|f| f.ident.as_ref().filter(|name| *name == "_parent").is_some())
                .map(|f| &f.ty),
            _ => panic!("derive(Template) only works for struct items"),
        };

        TemplateInput {
            ast,
            source,
            print,
            escaping: escaping.unwrap_or_else(|| EscapeMode::from_path(&path)),
            ext,
            parent,
            path,
        }
    }
}

pub enum Source {
    Path(String),
    Source(String),
}

#[derive(PartialEq)]
pub enum EscapeMode {
    Html,
    None,
}

impl From<String> for EscapeMode {
    fn from(s: String) -> EscapeMode {
        use self::EscapeMode::*;
        match s.as_ref() {
            "html" => Html,
            "none" => None,
            v => panic!("invalid value for escape option: {}", v),
        }
    }
}

impl EscapeMode {
    fn from_path(path: &PathBuf) -> EscapeMode {
        let extension = path.extension().map(|s| s.to_str().unwrap()).unwrap_or("");
        if HTML_EXTENSIONS.contains(&extension) {
            EscapeMode::Html
        } else {
            EscapeMode::None
        }
    }
}

#[derive(PartialEq)]
pub enum Print {
    All,
    Ast,
    Code,
    None,
}

impl From<String> for Print {
    fn from(s: String) -> Print {
        use self::Print::*;
        match s.as_ref() {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}

const HTML_EXTENSIONS: [&str; 3] = ["html", "htm", "xml"];
<commit_msg>Add some comments to TemplateInput::new() method<commit_after>use proc_macro2::TokenStream;

use quote::ToTokens;

use shared::path;

use std::path::PathBuf;

use syn;

pub struct TemplateInput<'a> {
    pub ast: &'a syn::DeriveInput,
    pub source: Source,
    pub print: Print,
    pub escaping: EscapeMode,
    pub ext: Option<String>,
    pub parent: Option<&'a syn::Type>,
    pub path: PathBuf,
}

impl<'a> TemplateInput<'a> {
    /// Extract the template metadata from the `DeriveInput` structure. This
    /// mostly recovers the data for the `TemplateInput` fields from the
    /// `template()` attribute list fields; it also finds the of the `_parent`
    /// field, if any.
    pub fn new(ast: &'a syn::DeriveInput) -> TemplateInput<'a> {
        // Check that an attribute called `template()` exists and that it is
        // the proper type (list).
        let mut meta = None;
        for attr in &ast.attrs {
            match attr.interpret_meta() {
                Some(m) => if m.name() == "template" {
                    meta = Some(m)
                },
                None => {
                    let mut tokens = TokenStream::new();
                    attr.to_tokens(&mut tokens);
                    panic!("unable to interpret attribute: {}", tokens)
                }
            }
        }

        let meta_list = match meta.expect("no attribute 'template' found") {
            syn::Meta::List(inner) => inner,
            _ => panic!("attribute 'template' has incorrect type"),
        };

        // Loop over the meta attributes and find everything that we
        // understand. Raise panics if something is not right.
        // `source` contains an enum that can represent `path` or `source`.
        let mut source = None;
        let mut print = Print::None;
        let mut escaping = None;
        let mut ext = None;
        for nm_item in meta_list.nested {
            if let syn::NestedMeta::Meta(ref item) = nm_item {
                if let syn::Meta::NameValue(ref pair) = item {
                    match pair.ident.to_string().as_ref() {
                        "path" => if let syn::Lit::Str(ref s) = pair.lit {
                            if source.is_some() {
                                panic!("must specify 'source' or 'path', not both");
                            }
                            source = Some(Source::Path(s.value()));
                        } else {
                            panic!("template path must be string literal");
                        },
                        "source" => if let syn::Lit::Str(ref s) = pair.lit {
                            if source.is_some() {
                                panic!("must specify 'source' or 'path', not both");
                            }
                            source = Some(Source::Source(s.value()));
                        } else {
                            panic!("template source must be string literal");
                        },
                        "print" => if let syn::Lit::Str(ref s) = pair.lit {
                            print = s.value().into();
                        } else {
                            panic!("print value must be string literal");
                        },
                        "escape" => if let syn::Lit::Str(ref s) = pair.lit {
                            escaping = Some(s.value().into());
                        } else {
                            panic!("escape value must be string literal");
                        },
                        "ext" => if let syn::Lit::Str(ref s) = pair.lit {
                            ext = Some(s.value());
                        } else {
                            panic!("ext value must be string literal");
                        },
                        attr => panic!("unsupported annotation key '{}' found", attr),
                    }
                }
            }
        }

        // Validate the `source` and `ext` value together, since they are
        // related. In case `source` was used instead of `path`, the value
        // of `ext` is merged into a synthetic `path` value here.
        let source = source.expect("template path or source not found in attributes");
        let path = match (&source, &ext) {
            (&Source::Path(ref path), None) => path::find_template_from_path(path, None),
            (&Source::Source(_), Some(ext)) => PathBuf::from(format!("{}.{}", ast.ident, ext)),
            (&Source::Path(_), Some(_)) => {
                panic!("'ext' attribute cannot be used with 'path' attribute")
            }
            (&Source::Source(_), None) => {
                panic!("must include 'ext' attribute when using 'source' attribute")
            }
        };

        // Check to see if a `_parent` field was defined on the context
        // struct, and store the type for it for use in the code generator.
        let parent = match ast.data {
            syn::Data::Struct(syn::DataStruct {
                fields: syn::Fields::Named(ref fields),
                ..
            }) => fields
                .named
                .iter()
                .find(|f| f.ident.as_ref().filter(|name| *name == "_parent").is_some())
                .map(|f| &f.ty),
            _ => panic!("derive(Template) only works for struct items"),
        };

        TemplateInput {
            ast,
            source,
            print,
            escaping: escaping.unwrap_or_else(|| EscapeMode::from_path(&path)),
            ext,
            parent,
            path,
        }
    }
}

pub enum Source {
    Path(String),
    Source(String),
}

#[derive(PartialEq)]
pub enum EscapeMode {
    Html,
    None,
}

impl From<String> for EscapeMode {
    fn from(s: String) -> EscapeMode {
        use self::EscapeMode::*;
        match s.as_ref() {
            "html" => Html,
            "none" => None,
            v => panic!("invalid value for escape option: {}", v),
        }
    }
}

impl EscapeMode {
    fn from_path(path: &PathBuf) -> EscapeMode {
        let extension = path.extension().map(|s| s.to_str().unwrap()).unwrap_or("");
        if HTML_EXTENSIONS.contains(&extension) {
            EscapeMode::Html
        } else {
            EscapeMode::None
        }
    }
}

#[derive(PartialEq)]
pub enum Print {
    All,
    Ast,
    Code,
    None,
}

impl From<String> for Print {
    fn from(s: String) -> Print {
        use self::Print::*;
        match s.as_ref() {
            "all" => All,
            "ast" => Ast,
            "code" => Code,
            "none" => None,
            v => panic!("invalid value for print option: {}", v),
        }
    }
}

const HTML_EXTENSIONS: [&str; 3] = ["html", "htm", "xml"];
<|endoftext|>


<commit_before>#![allow(unstable)]
extern crate hyper;

extern crate test;

use std::fmt::{self, Show};
use std::io::{IoResult, MemReader};
use std::io::net::ip::SocketAddr;
use std::os;
use std::path::BytesContainer;

use hyper::net;

static README: &'static [u8] = include_bytes!("../README.md");

struct MockStream {
    read: MemReader,
}

impl Clone for MockStream {
    fn clone(&self) -> MockStream {
        MockStream::new()
    }
}

impl MockStream {
    fn new() -> MockStream {
        let head = b"HTTP/1.1 200 OK\r\nServer: Mock\r\n\r\n";
        let mut res = head.to_vec();
        res.push_all(README);
        MockStream {
            read: MemReader::new(res),
        }
    }
}

impl Reader for MockStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
        self.read.read(buf)
    }
}

impl Writer for MockStream {
    fn write(&mut self, _msg: &[u8]) -> IoResult<()> {
        // we're mocking, what do we care.
        Ok(())
    }
}

#[derive(Clone)]
struct Foo;

impl hyper::header::Header for Foo {
    fn header_name(_: Option<Foo>) -> &'static str {
        "x-foo"
    }
    fn parse_header(_: &[Vec<u8>]) -> Option<Foo> {
        None
    }
}

impl hyper::header::HeaderFormat for Foo {
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        "Bar".fmt(fmt)
    }
}

impl net::NetworkStream for MockStream {
    fn peer_name(&mut self) -> IoResult<SocketAddr> {
        Ok("127.0.0.1:1337".parse().unwrap())
    }
}

struct MockConnector;

impl net::NetworkConnector for MockConnector {
    type Stream = MockStream;
    fn connect(&mut self, _: &str, _: u16, _: &str) -> IoResult<MockStream> {
        Ok(MockStream::new())
    }

}

#[bench]
fn bench_mock_hyper(b: &mut test::Bencher) {
    let url = "http://127.0.0.1:1337/";
    b.iter(|| {
        let mut req = hyper::client::Request::with_connector(
            hyper::Get, hyper::Url::parse(url).unwrap(), &mut MockConnector
        ).unwrap();
        req.headers_mut().set(Foo);

        req
            .start().unwrap()
            .send().unwrap()
            .read_to_string().unwrap()
    });
}

<commit_msg>test(benches): fix warnings in mock_tcp<commit_after>#![allow(unstable)]
extern crate hyper;

extern crate test;

use std::fmt::{self, Show};
use std::io::{IoResult, MemReader};
use std::io::net::ip::SocketAddr;

use hyper::net;

static README: &'static [u8] = include_bytes!("../README.md");

struct MockStream {
    read: MemReader,
}

impl Clone for MockStream {
    fn clone(&self) -> MockStream {
        MockStream::new()
    }
}

impl MockStream {
    fn new() -> MockStream {
        let head = b"HTTP/1.1 200 OK\r\nServer: Mock\r\n\r\n";
        let mut res = head.to_vec();
        res.push_all(README);
        MockStream {
            read: MemReader::new(res),
        }
    }
}

impl Reader for MockStream {
    fn read(&mut self, buf: &mut [u8]) -> IoResult<usize> {
        self.read.read(buf)
    }
}

impl Writer for MockStream {
    fn write(&mut self, _msg: &[u8]) -> IoResult<()> {
        // we're mocking, what do we care.
        Ok(())
    }
}

#[derive(Clone)]
struct Foo;

impl hyper::header::Header for Foo {
    fn header_name(_: Option<Foo>) -> &'static str {
        "x-foo"
    }
    fn parse_header(_: &[Vec<u8>]) -> Option<Foo> {
        None
    }
}

impl hyper::header::HeaderFormat for Foo {
    fn fmt_header(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        "Bar".fmt(fmt)
    }
}

impl net::NetworkStream for MockStream {
    fn peer_name(&mut self) -> IoResult<SocketAddr> {
        Ok("127.0.0.1:1337".parse().unwrap())
    }
}

struct MockConnector;

impl net::NetworkConnector for MockConnector {
    type Stream = MockStream;
    fn connect(&mut self, _: &str, _: u16, _: &str) -> IoResult<MockStream> {
        Ok(MockStream::new())
    }

}

#[bench]
fn bench_mock_hyper(b: &mut test::Bencher) {
    let url = "http://127.0.0.1:1337/";
    b.iter(|| {
        let mut req = hyper::client::Request::with_connector(
            hyper::Get, hyper::Url::parse(url).unwrap(), &mut MockConnector
        ).unwrap();
        req.headers_mut().set(Foo);

        req
            .start().unwrap()
            .send().unwrap()
            .read_to_string().unwrap()
    });
}

<|endoftext|>


<commit_before>// Copyright (c) 2020-present, Gregory Szorc
// All rights reserved.
//
// This software may be modified and distributed under the terms
// of the BSD license. See the LICENSE file for details.

use {
    crate::{
        compressor::CCtx,
        exceptions::ZstdError,
        stream::{make_in_buffer_source, InBufferSource},
    },
    pyo3::{prelude::*, types::PyBytes, PyIterProtocol},
    std::sync::Arc,
};

#[pyclass(module = "zstandard.backend_rust")]
pub struct ZstdCompressionChunker {
    cctx: Arc<CCtx<'static>>,
    chunk_size: usize,
    finished: bool,
    iterator: Option<Py<ZstdCompressionChunkerIterator>>,
}

impl ZstdCompressionChunker {
    pub fn new(cctx: Arc<CCtx<'static>>, chunk_size: usize) -> PyResult<Self> {
        Ok(Self {
            cctx,
            chunk_size,
            finished: false,
            iterator: None,
        })
    }
}

impl ZstdCompressionChunker {
    fn ensure_state(&mut self, py: Python) {
        // TODO preserve partial destination buffer
        if let Some(it) = &self.iterator {
            if it.borrow(py).finished {
                if it.borrow(py).mode == IteratorMode::Finish {
                    self.finished = true;
                }

                self.iterator = None;
            }
        }
    }
}

#[pymethods]
impl ZstdCompressionChunker {
    fn compress(
        &mut self,
        py: Python,
        data: &PyAny,
    ) -> PyResult<Py<ZstdCompressionChunkerIterator>> {
        self.ensure_state(py);

        if self.finished {
            return Err(ZstdError::new_err(
                "cannot call compress() after compression finished",
            ));
        }

        let source = make_in_buffer_source(py, data, zstd_safe::cstream_in_size())?;

        let it = Py::new(
            py,
            ZstdCompressionChunkerIterator {
                cctx: self.cctx.clone(),
                source,
                mode: IteratorMode::Normal,
                dest_buffer: Vec::with_capacity(self.chunk_size),
                finished: false,
            },
        )?;

        self.iterator = Some(it.clone());

        Ok(it)
    }

    fn flush<'p>(&mut self, py: Python<'p>) -> PyResult<Py<ZstdCompressionChunkerIterator>> {
        self.ensure_state(py);

        if self.finished {
            return Err(ZstdError::new_err(
                "cannot call flush() after compression finished",
            ));
        }

        if self.iterator.is_some() {
            return Err(ZstdError::new_err(
                "cannot call flush() before consuming output from previous operation",
            ));
        }

        let source =
            make_in_buffer_source(py, PyBytes::new(py, &[]), zstd_safe::cstream_in_size())?;

        let it = Py::new(
            py,
            ZstdCompressionChunkerIterator {
                cctx: self.cctx.clone(),
                source,
                mode: IteratorMode::Flush,
                dest_buffer: Vec::with_capacity(self.chunk_size),
                finished: false,
            },
        )?;

        self.iterator = Some(it.clone());

        Ok(it)
    }

    fn finish<'p>(&mut self, py: Python<'p>) -> PyResult<Py<ZstdCompressionChunkerIterator>> {
        self.ensure_state(py);

        if self.finished {
            return Err(ZstdError::new_err(
                "cannot call finish() after compression finished",
            ));
        }

        if self.iterator.is_some() {
            return Err(ZstdError::new_err(
                "cannot call finish() before consuming output from previous operation",
            ));
        }

        let source =
            make_in_buffer_source(py, PyBytes::new(py, &[]), zstd_safe::cstream_in_size())?;

        let it = Py::new(
            py,
            ZstdCompressionChunkerIterator {
                cctx: self.cctx.clone(),
                source,
                mode: IteratorMode::Finish,
                dest_buffer: Vec::with_capacity(self.chunk_size),
                finished: false,
            },
        )?;

        self.iterator = Some(it.clone());

        Ok(it)
    }
}

#[derive(Debug, PartialEq)]
enum IteratorMode {
    Normal,
    Flush,
    Finish,
}

#[pyclass(module = "zstandard.backend_rust")]
struct ZstdCompressionChunkerIterator {
    cctx: Arc<CCtx<'static>>,
    source: Box<dyn InBufferSource + Send>,
    mode: IteratorMode,
    dest_buffer: Vec<u8>,
    finished: bool,
}

#[pyproto]
impl PyIterProtocol for ZstdCompressionChunkerIterator {
    fn __iter__(slf: PyRef<Self>) -> PyRef<Self> {
        slf
    }

    fn __next__(mut slf: PyRefMut<Self>) -> PyResult<Option<PyObject>> {
        if slf.finished {
            return Ok(None);
        }

        let py = unsafe { Python::assume_gil_acquired() };

        // Consume any data left in the input.
        while let Some(mut in_buffer) = slf.source.input_buffer(py)? {
            let old_pos = in_buffer.pos;

            let mut out_buffer = zstd_sys::ZSTD_outBuffer {
                dst: slf.dest_buffer.as_mut_ptr() as *mut _,
                size: slf.dest_buffer.capacity(),
                pos: slf.dest_buffer.len(),
            };

            let zresult = unsafe {
                zstd_sys::ZSTD_compressStream2(
                    slf.cctx.cctx(),
                    &mut out_buffer as *mut _,
                    &mut in_buffer as *mut _,
                    zstd_sys::ZSTD_EndDirective::ZSTD_e_continue,
                )
            };
            if unsafe { zstd_sys::ZSTD_isError(zresult) } != 0 {
                return Err(ZstdError::new_err(format!(
                    "zstd compress error: {}",
                    zstd_safe::get_error_name(zresult)
                )));
            }

            slf.source.record_bytes_read(in_buffer.pos - old_pos);
            unsafe {
                slf.dest_buffer.set_len(out_buffer.pos);
            }

            // If we produced a full output chunk, emit it.
            if out_buffer.pos == out_buffer.size {
                let chunk = PyBytes::new(py, &slf.dest_buffer);

                unsafe {
                    slf.dest_buffer.set_len(0);
                }

                return Ok(Some(chunk.into_py(py)));
            }

            // Else continue to compress available input data.
            continue;
        }

        // No more input data. A partial chunk may be in the chunker's
        // destination buffer. If we're in normal compression mode, we're done.
        // Otherwise if we're in flush or finish mode, we need to emit what
        // data remains.

        let flush_mode = match slf.mode {
            IteratorMode::Normal => {
                slf.finished = true;
                return Ok(None);
            }
            IteratorMode::Flush => zstd_sys::ZSTD_EndDirective::ZSTD_e_flush,
            IteratorMode::Finish => zstd_sys::ZSTD_EndDirective::ZSTD_e_end,
        };

        let mut out_buffer = zstd_sys::ZSTD_outBuffer {
            dst: slf.dest_buffer.as_mut_ptr() as *mut _,
            size: slf.dest_buffer.capacity(),
            pos: slf.dest_buffer.len(),
        };

        let mut in_buffer = zstd_sys::ZSTD_inBuffer {
            src: std::ptr::null(),
            size: 0,
            pos: 0,
        };

        let zresult = unsafe {
            zstd_sys::ZSTD_compressStream2(
                slf.cctx.cctx(),
                &mut out_buffer as *mut _,
                &mut in_buffer as *mut _,
                flush_mode,
            )
        };
        if unsafe { zstd_sys::ZSTD_isError(zresult) } != 0 {
            return Err(ZstdError::new_err(format!(
                "zstd compress error: {}",
                zstd_safe::get_error_name(zresult)
            )));
        }

        // If we didn't emit anything to the output buffer, we must be finished.
        // Update state and stop iteration.
        if out_buffer.pos == 0 {
            slf.finished = true;
            return Ok(None);
        }

        // Else we have data in the output buffer. We're either in
        // flush or finish mode and all available data in the output buffer
        // should be emitted.

        unsafe {
            slf.dest_buffer.set_len(out_buffer.pos);
        }

        let chunk = PyBytes::new(py, &slf.dest_buffer);

        // If the flush or finish didn't fill the output buffer, we must
        // be done.
        // If compressor said operation is finished, we are also done.
        if out_buffer.pos < out_buffer.size || zresult == 0 {
            slf.finished = true;
        }

        unsafe {
            slf.dest_buffer.set_len(0);
        }

        Ok(Some(chunk.into_py(py)))
    }
}
<commit_msg>rust: preserve output buffer in ZstdCompressionChunker<commit_after>// Copyright (c) 2020-present, Gregory Szorc
// All rights reserved.
//
// This software may be modified and distributed under the terms
// of the BSD license. See the LICENSE file for details.

use {
    crate::{
        compressor::CCtx,
        exceptions::ZstdError,
        stream::{make_in_buffer_source, InBufferSource},
    },
    pyo3::{prelude::*, types::PyBytes, PyIterProtocol},
    std::sync::Arc,
};

#[pyclass(module = "zstandard.backend_rust")]
pub struct ZstdCompressionChunker {
    cctx: Arc<CCtx<'static>>,
    chunk_size: usize,
    finished: bool,
    iterator: Option<Py<ZstdCompressionChunkerIterator>>,
    partial_buffer: Option<Vec<u8>>,
}

impl ZstdCompressionChunker {
    pub fn new(cctx: Arc<CCtx<'static>>, chunk_size: usize) -> PyResult<Self> {
        Ok(Self {
            cctx,
            chunk_size,
            finished: false,
            iterator: None,
            partial_buffer: None,
        })
    }
}

impl ZstdCompressionChunker {
    fn ensure_state(&mut self, py: Python) {
        if let Some(it) = &self.iterator {
            if it.borrow(py).finished {
                if it.borrow(py).mode == IteratorMode::Finish {
                    self.finished = true;
                }

                if !it.borrow(py).dest_buffer.is_empty() {
                    // TODO can we avoid the memory copy?
                    // Vec.clone() won't preserve the capacity of the source.
                    // So we create a new Vec with desired capacity and copy to it.
                    // This is strictly better than a clone + resize.
                    let mut dest_buffer = Vec::with_capacity(self.chunk_size);
                    unsafe {
                        dest_buffer.set_len(it.borrow(py).dest_buffer.len());
                    }
                    dest_buffer.copy_from_slice(it.borrow(py).dest_buffer.as_slice());
                    self.partial_buffer = Some(dest_buffer);
                }

                self.iterator = None;
            }
        }
    }

    fn get_dest_buffer(&mut self) -> Vec<u8> {
        self.partial_buffer
            .take()
            .unwrap_or_else(|| Vec::with_capacity(self.chunk_size))
    }
}

#[pymethods]
impl ZstdCompressionChunker {
    fn compress(
        &mut self,
        py: Python,
        data: &PyAny,
    ) -> PyResult<Py<ZstdCompressionChunkerIterator>> {
        self.ensure_state(py);

        if self.finished {
            return Err(ZstdError::new_err(
                "cannot call compress() after compression finished",
            ));
        }

        let source = make_in_buffer_source(py, data, zstd_safe::cstream_in_size())?;

        let it = Py::new(
            py,
            ZstdCompressionChunkerIterator {
                cctx: self.cctx.clone(),
                source,
                mode: IteratorMode::Normal,
                dest_buffer: self.get_dest_buffer(),
                finished: false,
            },
        )?;

        self.iterator = Some(it.clone());

        Ok(it)
    }

    fn flush<'p>(&mut self, py: Python<'p>) -> PyResult<Py<ZstdCompressionChunkerIterator>> {
        self.ensure_state(py);

        if self.finished {
            return Err(ZstdError::new_err(
                "cannot call flush() after compression finished",
            ));
        }

        if self.iterator.is_some() {
            return Err(ZstdError::new_err(
                "cannot call flush() before consuming output from previous operation",
            ));
        }

        let source =
            make_in_buffer_source(py, PyBytes::new(py, &[]), zstd_safe::cstream_in_size())?;

        let it = Py::new(
            py,
            ZstdCompressionChunkerIterator {
                cctx: self.cctx.clone(),
                source,
                mode: IteratorMode::Flush,
                dest_buffer: self.get_dest_buffer(),
                finished: false,
            },
        )?;

        self.iterator = Some(it.clone());

        Ok(it)
    }

    fn finish<'p>(&mut self, py: Python<'p>) -> PyResult<Py<ZstdCompressionChunkerIterator>> {
        self.ensure_state(py);

        if self.finished {
            return Err(ZstdError::new_err(
                "cannot call finish() after compression finished",
            ));
        }

        if self.iterator.is_some() {
            return Err(ZstdError::new_err(
                "cannot call finish() before consuming output from previous operation",
            ));
        }

        let source =
            make_in_buffer_source(py, PyBytes::new(py, &[]), zstd_safe::cstream_in_size())?;

        let it = Py::new(
            py,
            ZstdCompressionChunkerIterator {
                cctx: self.cctx.clone(),
                source,
                mode: IteratorMode::Finish,
                dest_buffer: self.get_dest_buffer(),
                finished: false,
            },
        )?;

        self.iterator = Some(it.clone());

        Ok(it)
    }
}

#[derive(Debug, PartialEq)]
enum IteratorMode {
    Normal,
    Flush,
    Finish,
}

#[pyclass(module = "zstandard.backend_rust")]
struct ZstdCompressionChunkerIterator {
    cctx: Arc<CCtx<'static>>,
    source: Box<dyn InBufferSource + Send>,
    mode: IteratorMode,
    dest_buffer: Vec<u8>,
    finished: bool,
}

#[pyproto]
impl PyIterProtocol for ZstdCompressionChunkerIterator {
    fn __iter__(slf: PyRef<Self>) -> PyRef<Self> {
        slf
    }

    fn __next__(mut slf: PyRefMut<Self>) -> PyResult<Option<PyObject>> {
        if slf.finished {
            return Ok(None);
        }

        let py = unsafe { Python::assume_gil_acquired() };

        // Consume any data left in the input.
        while let Some(mut in_buffer) = slf.source.input_buffer(py)? {
            let old_pos = in_buffer.pos;

            let mut out_buffer = zstd_sys::ZSTD_outBuffer {
                dst: slf.dest_buffer.as_mut_ptr() as *mut _,
                size: slf.dest_buffer.capacity(),
                pos: slf.dest_buffer.len(),
            };

            let zresult = unsafe {
                zstd_sys::ZSTD_compressStream2(
                    slf.cctx.cctx(),
                    &mut out_buffer as *mut _,
                    &mut in_buffer as *mut _,
                    zstd_sys::ZSTD_EndDirective::ZSTD_e_continue,
                )
            };
            if unsafe { zstd_sys::ZSTD_isError(zresult) } != 0 {
                return Err(ZstdError::new_err(format!(
                    "zstd compress error: {}",
                    zstd_safe::get_error_name(zresult)
                )));
            }

            slf.source.record_bytes_read(in_buffer.pos - old_pos);
            unsafe {
                slf.dest_buffer.set_len(out_buffer.pos);
            }

            // If we produced a full output chunk, emit it.
            if out_buffer.pos == out_buffer.size {
                let chunk = PyBytes::new(py, &slf.dest_buffer);

                unsafe {
                    slf.dest_buffer.set_len(0);
                }

                return Ok(Some(chunk.into_py(py)));
            }

            // Else continue to compress available input data.
            continue;
        }

        // No more input data. A partial chunk may be in the destination
        // buffer. If we're in normal compression mode, we're done. Otherwise
        // if we're in flush or finish mode, we need to emit what data remains.

        let flush_mode = match slf.mode {
            IteratorMode::Normal => {
                slf.finished = true;
                return Ok(None);
            }
            IteratorMode::Flush => zstd_sys::ZSTD_EndDirective::ZSTD_e_flush,
            IteratorMode::Finish => zstd_sys::ZSTD_EndDirective::ZSTD_e_end,
        };

        let mut out_buffer = zstd_sys::ZSTD_outBuffer {
            dst: slf.dest_buffer.as_mut_ptr() as *mut _,
            size: slf.dest_buffer.capacity(),
            pos: slf.dest_buffer.len(),
        };

        let mut in_buffer = zstd_sys::ZSTD_inBuffer {
            src: std::ptr::null(),
            size: 0,
            pos: 0,
        };

        let zresult = unsafe {
            zstd_sys::ZSTD_compressStream2(
                slf.cctx.cctx(),
                &mut out_buffer as *mut _,
                &mut in_buffer as *mut _,
                flush_mode,
            )
        };
        if unsafe { zstd_sys::ZSTD_isError(zresult) } != 0 {
            return Err(ZstdError::new_err(format!(
                "zstd compress error: {}",
                zstd_safe::get_error_name(zresult)
            )));
        }

        unsafe {
            slf.dest_buffer.set_len(out_buffer.pos);
        }

        // When flushing or finishing, we always emit data in the output
        // buffer. But the operation could fill the output buffer and not be
        // finished.

        // If we didn't emit anything to the output buffer, we must be finished.
        // Update state and stop iteration.
        if out_buffer.pos == 0 {
            slf.finished = true;
            return Ok(None);
        }

        let chunk = PyBytes::new(py, &slf.dest_buffer);
        unsafe {
            slf.dest_buffer.set_len(0);
        }

        // If the flush or finish didn't fill the output buffer, we must
        // be done.
        // If compressor said operation is finished, we are also done.
        if zresult == 0 || out_buffer.pos < out_buffer.size {
            slf.finished = true;
        }

        Ok(Some(chunk.into_py(py)))
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 The Grin Developers
//
// 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.

//! Provides wrappers for throttling readers and writers

use std::time::Instant;
use std::io;

use futures::*;
use tokio_io::*;

/// A Rate Limited Reader
#[derive(Debug)]
pub struct ThrottledReader<R: AsyncRead> {
	reader: R,
	/// Max Bytes per second
	max: u32,
	/// Stores a count of last request and last request time
	allowed: usize,
	last_check: Instant,
}

#[allow(dead_code)]
impl<R: AsyncRead> ThrottledReader<R> {
	/// Adds throttling to a reader.
	/// The resulting reader will read at most `max` amount of bytes per second
	pub fn new(reader: R, max: u32) -> Self {
		ThrottledReader {
			reader: reader,
			max: max,
			allowed: max as usize,
			last_check: Instant::now(),
		}
	}

	/// Get a shared reference to the inner sink.
	pub fn get_ref(&self) -> &R {
		&self.reader
	}

	/// Get a mutable reference to the inner sink.
	pub fn get_mut(&mut self) -> &mut R {
		&mut self.reader
	}

	/// Consumes this combinator, returning the underlying sink.
	///
	/// Note that this may discard intermediate state of this combinator, so
	/// care should be taken to avoid losing resources when this is called.
	pub fn into_inner(self) -> R {
		self.reader
	}
}

impl<R: AsyncRead> io::Read for ThrottledReader<R> {
	fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
		// Check passed Time
		let time_passed = self.last_check.elapsed();
		self.last_check = Instant::now();
		self.allowed += time_passed.as_secs() as usize * self.max as usize;

		// Throttle
		if self.allowed > self.max as usize {
			self.allowed = self.max as usize;
		}

		// Check if Allowed
		if self.allowed < 1 {
			return Err(io::Error::new(
				io::ErrorKind::WouldBlock,
				"Reached Allowed Read Limit",
			));
		}

		// Read Max Allowed
		let buf = if buf.len() > self.allowed {
			&mut buf[0..self.allowed]
		} else {
			buf
		};
		let res = self.reader.read(buf);

		// Decrement Allowed amount written
		if let Ok(n) = res {
			self.allowed -= n;
		}
		res
	}
}

impl<R: AsyncRead> AsyncRead for ThrottledReader<R> {}

/// A Rate Limited Writer
#[derive(Debug)]
pub struct ThrottledWriter<W: AsyncWrite> {
	writer: W,
	/// Max Bytes per second
	max: u32,
	/// Stores a count of last request and last request time
	allowed: usize,
	last_check: Instant,
}

#[allow(dead_code)]
impl<W: AsyncWrite> ThrottledWriter<W> {
	/// Adds throttling to a writer.
	/// The resulting writer will write at most `max` amount of bytes per second
	pub fn new(writer: W, max: u32) -> Self {
		ThrottledWriter {
			writer: writer,
			max: max,
			allowed: max as usize,
			last_check: Instant::now(),
		}
	}

	/// Get a shared reference to the inner sink.
	pub fn get_ref(&self) -> &W {
		&self.writer
	}

	/// Get a mutable reference to the inner sink.
	pub fn get_mut(&mut self) -> &mut W {
		&mut self.writer
	}

	/// Consumes this combinator, returning the underlying sink.
	///
	/// Note that this may discard intermediate state of this combinator, so
	/// care should be taken to avoid losing resources when this is called.
	pub fn into_inner(self) -> W {
		self.writer
	}
}

impl<W: AsyncWrite> io::Write for ThrottledWriter<W> {
	fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
		// Check passed Time
		let time_passed = self.last_check.elapsed();
		self.last_check = Instant::now();
		self.allowed += time_passed.as_secs() as usize * self.max as usize;

		// Throttle
		if self.allowed > self.max as usize {
			self.allowed = self.max as usize;
		}

		// Check if Allowed
		if self.allowed < 1 {
			return Err(io::Error::new(
				io::ErrorKind::WouldBlock,
				"Reached Allowed Write Limit",
			));
		}

		// Write max allowed
		let buf = if buf.len() > self.allowed {
			&buf[0..self.allowed]
		} else {
			buf
		};
		let res = self.writer.write(buf);

		// Decrement Allowed amount written
		if let Ok(n) = res {
			self.allowed -= n;
		}
		res
	}

	fn flush(&mut self) -> io::Result<()> {
		self.writer.flush()
	}
}

impl<T: AsyncWrite> AsyncWrite for ThrottledWriter<T> {
	fn shutdown(&mut self) -> Poll<(), io::Error> {
		self.writer.shutdown()
	}
}

#[cfg(test)]
mod test {
	use super::*;
	use std::io::Cursor;

	#[test]
	fn should_throttle_write() {
		let buf = vec![0; 64];
		let mut t_buf = ThrottledWriter::new(Cursor::new(buf), 8);

		for _ in 0..16 {
			let _ = t_buf.write_buf(&mut Cursor::new(vec![1; 8]));
		}

		let cursor = t_buf.into_inner();
		assert_eq!(cursor.position(), 8);
	}

	#[test]
	fn should_throttle_read() {
		let buf = vec![1; 64];
		let mut t_buf = ThrottledReader::new(Cursor::new(buf), 8);

		let mut dst = Cursor::new(vec![0; 64]);

		for _ in 0..16 {
			let _ = t_buf.read_buf(&mut dst);
		}

		assert_eq!(dst.position(), 8);
	}
}
<commit_msg>Allowable write size as u64 instead of usize. Fix #303.<commit_after>// Copyright 2016 The Grin Developers
//
// 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.

//! Provides wrappers for throttling readers and writers

use std::time::Instant;
use std::{cmp, io};

use futures::*;
use tokio_io::*;

/// A Rate Limited Reader
#[derive(Debug)]
pub struct ThrottledReader<R: AsyncRead> {
	reader: R,
	/// Max Bytes per second
	max: u32,
	/// Stores a count of last request and last request time
	allowed: usize,
	last_check: Instant,
}

#[allow(dead_code)]
impl<R: AsyncRead> ThrottledReader<R> {
	/// Adds throttling to a reader.
	/// The resulting reader will read at most `max` amount of bytes per second
	pub fn new(reader: R, max: u32) -> Self {
		ThrottledReader {
			reader: reader,
			max: max,
			allowed: max as usize,
			last_check: Instant::now(),
		}
	}

	/// Get a shared reference to the inner sink.
	pub fn get_ref(&self) -> &R {
		&self.reader
	}

	/// Get a mutable reference to the inner sink.
	pub fn get_mut(&mut self) -> &mut R {
		&mut self.reader
	}

	/// Consumes this combinator, returning the underlying sink.
	///
	/// Note that this may discard intermediate state of this combinator, so
	/// care should be taken to avoid losing resources when this is called.
	pub fn into_inner(self) -> R {
		self.reader
	}
}

impl<R: AsyncRead> io::Read for ThrottledReader<R> {
	fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
		// Check passed Time
		let time_passed = self.last_check.elapsed();
		self.last_check = Instant::now();
		self.allowed += time_passed.as_secs() as usize * self.max as usize;

		// Throttle
		if self.allowed > self.max as usize {
			self.allowed = self.max as usize;
		}

		// Check if Allowed
		if self.allowed < 1 {
			return Err(io::Error::new(
				io::ErrorKind::WouldBlock,
				"Reached Allowed Read Limit",
			));
		}

		// Read Max Allowed
		let buf = if buf.len() > self.allowed {
			&mut buf[0..self.allowed]
		} else {
			buf
		};
		let res = self.reader.read(buf);

		// Decrement Allowed amount written
		if let Ok(n) = res {
			self.allowed -= n;
		}
		res
	}
}

impl<R: AsyncRead> AsyncRead for ThrottledReader<R> {}

/// A Rate Limited Writer
#[derive(Debug)]
pub struct ThrottledWriter<W: AsyncWrite> {
	writer: W,
	/// Max Bytes per second
	max: u64,
	/// Stores a count of last request and last request time
	allowed: u64,
	last_check: Instant,
}

#[allow(dead_code)]
impl<W: AsyncWrite> ThrottledWriter<W> {
	/// Adds throttling to a writer.
	/// The resulting writer will write at most `max` amount of bytes per second
	pub fn new(writer: W, max: u64) -> Self {
		ThrottledWriter {
			writer: writer,
			max: max,
			allowed: max,
			last_check: Instant::now(),
		}
	}

	/// Get a shared reference to the inner sink.
	pub fn get_ref(&self) -> &W {
		&self.writer
	}

	/// Get a mutable reference to the inner sink.
	pub fn get_mut(&mut self) -> &mut W {
		&mut self.writer
	}

	/// Consumes this combinator, returning the underlying sink.
	///
	/// Note that this may discard intermediate state of this combinator, so
	/// care should be taken to avoid losing resources when this is called.
	pub fn into_inner(self) -> W {
		self.writer
	}
}

impl<W: AsyncWrite> io::Write for ThrottledWriter<W> {
	fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
		// Check passed Time
		let time_passed = self.last_check.elapsed();
		self.last_check = Instant::now();
		self.allowed += time_passed.as_secs() * self.max;

		// Throttle
		if self.allowed > self.max {
			self.allowed = cmp::min(self.max, u32::max_value() as u64);
		}

		// Check if Allowed
		if self.allowed < 1 {
			return Err(io::Error::new(
				io::ErrorKind::WouldBlock,
				"Reached Allowed Write Limit",
			));
		}

		// Write max allowed
		let buf = if buf.len() > self.allowed as usize {
			&buf[0..self.allowed as usize]
		} else {
			buf
		};
		let res = self.writer.write(buf);

		// Decrement Allowed amount written
		if let Ok(n) = res {
			self.allowed -= n as u64;
		}
		res
	}

	fn flush(&mut self) -> io::Result<()> {
		self.writer.flush()
	}
}

impl<T: AsyncWrite> AsyncWrite for ThrottledWriter<T> {
	fn shutdown(&mut self) -> Poll<(), io::Error> {
		self.writer.shutdown()
	}
}

#[cfg(test)]
mod test {
	use super::*;
	use std::io::Cursor;

	#[test]
	fn should_throttle_write() {
		let buf = vec![0; 64];
		let mut t_buf = ThrottledWriter::new(Cursor::new(buf), 8);

		for _ in 0..16 {
			let _ = t_buf.write_buf(&mut Cursor::new(vec![1; 8]));
		}

		let cursor = t_buf.into_inner();
		assert_eq!(cursor.position(), 8);
	}

	#[test]
	fn should_throttle_read() {
		let buf = vec![1; 64];
		let mut t_buf = ThrottledReader::new(Cursor::new(buf), 8);

		let mut dst = Cursor::new(vec![0; 64]);

		for _ in 0..16 {
			let _ = t_buf.read_buf(&mut dst);
		}

		assert_eq!(dst.position(), 8);
	}
}
<|endoftext|>


<commit_before>use crate::*;
use rustc_target::abi::{Align, Size};

/// Implementation of the SYS_futex syscall.
pub fn futex<'tcx>(
    this: &mut MiriEvalContext<'_, 'tcx>,
    args: &[OpTy<'tcx, Tag>],
    dest: PlaceTy<'tcx, Tag>,
) -> InterpResult<'tcx> {
    if args.len() < 4 {
        throw_ub_format!("incorrect number of arguments for futex syscall: got {}, expected at least 4", args.len());
    }
    let addr = args[1];
    let addr_scalar = this.read_scalar(addr)?.check_init()?;
    let futex_ptr = this.force_ptr(addr_scalar)?.erase_tag();
    let op = this.read_scalar(args[2])?.to_i32()?;
    let val = this.read_scalar(args[3])?.to_i32()?;

    let thread = this.get_active_thread();

    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;

    match op & !futex_private {
        op if op == futex_wait => {
            if args.len() < 5 {
                throw_ub_format!("incorrect number of arguments for FUTEX_WAIT syscall: got {}, expected at least 5", args.len());
            }
            let timeout = this.read_scalar(args[4])?.check_init()?;
            if !this.is_null(timeout)? {
                throw_ub_format!("miri does not support timeouts for futex operations");
            }
            this.memory.check_ptr_access(addr_scalar, Size::from_bytes(4), Align::from_bytes(4).unwrap())?;
            let futex_val = this.read_scalar_at_offset(args[1], 0, this.machine.layouts.i32)?.to_i32()?;
            if val == futex_val {
                this.block_thread(thread);
                this.futex_wait(futex_ptr, thread);
                this.write_scalar(Scalar::from_i32(0), dest)?;
            } else {
                let eagain = this.eval_libc("EAGAIN")?;
                this.set_last_error(eagain)?;
                this.write_scalar(Scalar::from_i32(-1), dest)?;
            }
        }
        op if op == futex_wake => {
            let mut n = 0;
            for _ in 0..val {
                if let Some(thread) = this.futex_wake(futex_ptr) {
                    this.unblock_thread(thread);
                    n += 1;
                } else {
                    break;
                }
            }
            this.write_scalar(Scalar::from_i32(n), dest)?;
        }
        op => throw_unsup_format!("miri does not support SYS_futex operation {}", op),
    }

    Ok(())
}
<commit_msg>Check maximum amount of arguments to SYS_futex.<commit_after>use crate::*;
use rustc_target::abi::{Align, Size};

/// Implementation of the SYS_futex syscall.
pub fn futex<'tcx>(
    this: &mut MiriEvalContext<'_, 'tcx>,
    args: &[OpTy<'tcx, Tag>],
    dest: PlaceTy<'tcx, Tag>,
) -> InterpResult<'tcx> {
    // The amount of arguments used depends on the type of futex operation.
    // Some users always pass all arguments, even the unused ones, due to how they wrap this syscall in their code base.
    // Some other users pass only the arguments the operation actually needs. So we don't use `check_arg_count` here.
    if !(4..=7).contains(&args.len()) {
        throw_ub_format!("incorrect number of arguments for futex syscall: got {}, expected between 4 and 7 (inclusive)", args.len());
    }
    let addr = args[1];
    let addr_scalar = this.read_scalar(addr)?.check_init()?;
    let futex_ptr = this.force_ptr(addr_scalar)?.erase_tag();
    let op = this.read_scalar(args[2])?.to_i32()?;
    let val = this.read_scalar(args[3])?.to_i32()?;

    let thread = this.get_active_thread();

    let futex_private = this.eval_libc_i32("FUTEX_PRIVATE_FLAG")?;
    let futex_wait = this.eval_libc_i32("FUTEX_WAIT")?;
    let futex_wake = this.eval_libc_i32("FUTEX_WAKE")?;

    match op & !futex_private {
        op if op == futex_wait => {
            if args.len() < 5 {
                throw_ub_format!("incorrect number of arguments for FUTEX_WAIT syscall: got {}, expected at least 5", args.len());
            }
            let timeout = this.read_scalar(args[4])?.check_init()?;
            if !this.is_null(timeout)? {
                throw_ub_format!("miri does not support timeouts for futex operations");
            }
            this.memory.check_ptr_access(addr_scalar, Size::from_bytes(4), Align::from_bytes(4).unwrap())?;
            let futex_val = this.read_scalar_at_offset(args[1], 0, this.machine.layouts.i32)?.to_i32()?;
            if val == futex_val {
                this.block_thread(thread);
                this.futex_wait(futex_ptr, thread);
                this.write_scalar(Scalar::from_i32(0), dest)?;
            } else {
                let eagain = this.eval_libc("EAGAIN")?;
                this.set_last_error(eagain)?;
                this.write_scalar(Scalar::from_i32(-1), dest)?;
            }
        }
        op if op == futex_wake => {
            let mut n = 0;
            for _ in 0..val {
                if let Some(thread) = this.futex_wake(futex_ptr) {
                    this.unblock_thread(thread);
                    n += 1;
                } else {
                    break;
                }
            }
            this.write_scalar(Scalar::from_i32(n), dest)?;
        }
        op => throw_unsup_format!("miri does not support SYS_futex operation {}", op),
    }

    Ok(())
}
<|endoftext|>


<commit_before>/// Reverse the items in the list from [0..index].
#[inline]
fn reverse_until_index<T>(v: &mut Vec<T>, index: usize) {
    let (mut first, _) = v.split_at_mut(index+1);
    first.reverse();
}

/// Return the index of the largest item in the Vec between [0..index].
#[inline]
fn index_of_max<T>(v: &Vec<T>, index: usize) -> usize where T: PartialOrd {
    let mut max = &v[0];
    let mut max_index = 0;
    for i in 0..(index+1) {
        if v[i] > *max {
            max = &v[i];
            max_index = i;
        }
    }
    max_index
}

/// Sort the Vec using only `reverse_until_index` to exchange elements.
/// See: http://en.wikipedia.org/wiki/Pancake_sorting
///
/// # Examples
///
/// ```
/// use pancake::pancake_sort;
///
/// let mut v = vec![5, 1, 3, 4, 8, 2, 1, 9, 7];
/// pancake_sort(&mut v);
/// assert_eq!(vec![1, 1, 2, 3, 4, 5, 7, 8, 9], v);
/// ```
#[inline]
pub fn pancake_sort<T>(v: &mut Vec<T>) where T: PartialOrd {
    if v.len() == 0 {
        return;
    }
    let mut index = v.len() - 1;

    while index > 0 {
        let max_index = index_of_max(&v, index);
        if max_index != index {
            reverse_until_index(&mut *v, max_index);
            reverse_until_index(&mut *v, index);
        }
        index -= 1;
    }
}

#[test]
fn empty() {
    let mut v: Vec<i32> = vec![];
    pancake_sort(&mut v);
    assert!(v.is_empty());
}

#[test]
fn one_element() {
    let mut v = vec![1];
    pancake_sort(&mut v);
    assert_eq!(vec![1], v);
}

#[test]
fn reversed() {
    let mut v = vec![5, 4, 3, 2, 1];
    pancake_sort(&mut v);
    assert_eq!(vec![1, 2, 3, 4, 5], v);
}

#[test]
fn many_out_of_order() {
    let mut v = vec![4, 18, 3, -5, 7, 4, 1, 8, 3, 4, 19, 11, 23, 24, 25, 6, 0];
    pancake_sort(&mut v);
    assert_eq!(
        vec![-5, 0, 1, 3, 3, 4, 4, 4, 6, 7, 8, 11, 18, 19, 23, 24, 25],
        v);
}

#[test]
fn string() {
    let mut v = vec!["Charlie", "Alpha", "Brava", "Echo", "Delta", "Foxtrot"];
    pancake_sort(&mut v);
    assert_eq!(
        vec!["Alpha", "Brava", "Charlie", "Delta", "Echo", "Foxtrot"],
        v);
}
<commit_msg>Add some comments.<commit_after>/// Reverse the items in the list from [0..index].
#[inline]
fn reverse_until_index<T>(v: &mut Vec<T>, index: usize) {
    let (mut first, _) = v.split_at_mut(index+1);
    first.reverse();
}

/// Return the index of the largest item in the Vec between [0..index].
#[inline]
fn index_of_max<T>(v: &Vec<T>, index: usize) -> usize where T: PartialOrd {
    let mut max = &v[0];
    let mut max_index = 0;
    for i in 0..(index+1) {
        if v[i] > *max {
            max = &v[i];
            max_index = i;
        }
    }
    max_index
}

/// Sort the Vec using only `reverse_until_index` to exchange elements.
/// See: http://en.wikipedia.org/wiki/Pancake_sorting
///
/// # Examples
///
/// ```
/// use pancake::pancake_sort;
///
/// let mut v = vec![5, 1, 3, 4, 8, 2, 1, 9, 7];
/// pancake_sort(&mut v);
/// assert_eq!(vec![1, 1, 2, 3, 4, 5, 7, 8, 9], v);
/// ```
#[inline]
pub fn pancake_sort<T>(v: &mut Vec<T>) where T: PartialOrd {
    if v.len() == 0 {
        return;
    }
    let mut index = v.len() - 1;

    while index > 0 {
        // Only consider items in the range [0..index], which have yet to be
        // sorted.
        let max_index = index_of_max(&v, index);
        if max_index != index {
            // Move the largest item to the 0th position.
            reverse_until_index(&mut *v, max_index);
            // Reverse the Vec so the 0th item is now at `index`.
            reverse_until_index(&mut *v, index);
        }
        index -= 1;
    }
}

#[test]
fn empty() {
    let mut v: Vec<i32> = vec![];
    pancake_sort(&mut v);
    assert!(v.is_empty());
}

#[test]
fn one_element() {
    let mut v = vec![1];
    pancake_sort(&mut v);
    assert_eq!(vec![1], v);
}

#[test]
fn reversed() {
    let mut v = vec![5, 4, 3, 2, 1];
    pancake_sort(&mut v);
    assert_eq!(vec![1, 2, 3, 4, 5], v);
}

#[test]
fn many_out_of_order() {
    let mut v = vec![4, 18, 3, -5, 7, 4, 1, 8, 3, 4, 19, 11, 23, 24, 25, 6, 0];
    pancake_sort(&mut v);
    assert_eq!(
        vec![-5, 0, 1, 3, 3, 4, 4, 4, 6, 7, 8, 11, 18, 19, 23, 24, 25],
        v);
}

#[test]
fn string() {
    let mut v = vec!["Charlie", "Alpha", "Brava", "Echo", "Delta", "Foxtrot"];
    pancake_sort(&mut v);
    assert_eq!(
        vec!["Alpha", "Brava", "Charlie", "Delta", "Echo", "Foxtrot"],
        v);
}
<|endoftext|>


<commit_before>use std::rc::Rc;
use std::cell::RefCell;
use std::default::Default;

use progress::frontier::{MutableAntichain, Antichain};
use progress::{Scope, Timestamp};
use progress::nested::subgraph::Source::{ScopeOutput};
use progress::count_map::CountMap;
use progress::timestamp::RootTimestamp;
use progress::nested::product::Product;

use communication::{Communicator, Data, Message, Observer};
use communication::observer::{Tee, Counter};

use construction::stream::Stream;
use construction::builder::*;

// TODO : This is an exogenous input, but it would be nice to wrap a Subgraph in something
// TODO : more like a harness, with direct access to its inputs.

// NOTE : This only takes a &self, not a &mut self, which works but is a bit weird.
// NOTE : Experiments with &mut indicate that the borrow of 'a lives for too long.
// NOTE : Might be able to fix with another lifetime parameter, say 'c: 'a.

// returns both an input scope and a stream representing its output.
pub trait InputExtensionTrait<C: Communicator, T: Timestamp+Ord> {
    fn new_input<D:Data>(&self) -> (InputHelper<T, D>, Stream<SubgraphBuilder<GraphRoot<C>, T>, D>);
}

impl<C: Communicator, T: Timestamp+Ord> InputExtensionTrait<C, T> for SubgraphBuilder<GraphRoot<C>, T> {
    fn new_input<D:Data>(&self) -> (InputHelper<T, D>, Stream<SubgraphBuilder<GraphRoot<C>, T>, D>) {

        let (output, registrar) = Tee::<Product<RootTimestamp, T>, D>::new();
        let produced = Rc::new(RefCell::new(CountMap::new()));

        let helper = InputHelper::new(Counter::new(output, produced.clone()));
        // {
        //     frontier: Rc::new(RefCell::new(MutableAntichain::new_bottom(Default::default()))),
        //     progress: Rc::new(RefCell::new(CountMap::new())),
        //     output:   Counter::new(output, produced.clone()),
        //     now_at:   Default::default(),
        //     closed:   false,
        // };

        let copies = self.peers();

        let index = self.add_scope(InputScope {
            frontier: helper.frontier.clone(),
            progress: helper.progress.clone(),
            messages: produced.clone(),
            copies:   copies,
        });

        return (helper, Stream::new(ScopeOutput(index, 0), registrar, self.clone()));
    }
}

pub struct InputScope<T:Timestamp+Ord> {
    frontier:   Rc<RefCell<MutableAntichain<Product<RootTimestamp, T>>>>,   // times available for sending
    progress:   Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // times closed since last asked
    messages:   Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // messages sent since last asked
    copies:     u64,
}

impl<T:Timestamp+Ord> Scope<Product<RootTimestamp, T>> for InputScope<T> {
    fn name(&self) -> String { format!("Input") }
    fn inputs(&self) -> u64 { 0 }
    fn outputs(&self) -> u64 { 1 }

    fn get_internal_summary(&mut self) -> (Vec<Vec<Antichain<<Product<RootTimestamp, T> as Timestamp>::Summary>>>,
                                           Vec<CountMap<Product<RootTimestamp, T>>>) {
        let mut map = CountMap::new();
        for x in self.frontier.borrow().elements().iter() {
            map.update(x, self.copies as i64);
        }
        (Vec::new(), vec![map])
    }

    fn pull_internal_progress(&mut self, frontier_progress: &mut [CountMap<Product<RootTimestamp, T>>],
                                        _messages_consumed: &mut [CountMap<Product<RootTimestamp, T>>],
                                         messages_produced: &mut [CountMap<Product<RootTimestamp, T>>]) -> bool
    {
        self.messages.borrow_mut().drain_into(&mut messages_produced[0]);
        self.progress.borrow_mut().drain_into(&mut frontier_progress[0]);
        return false;
    }

    fn notify_me(&self) -> bool { false }
}

pub struct InputHelper<T: Timestamp+Ord, D: Data> {
    frontier: Rc<RefCell<MutableAntichain<Product<RootTimestamp, T>>>>,   // times available for sending
    progress: Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // times closed since last asked
    observer: Counter<Tee<Product<RootTimestamp, T>, D>>,
    buffer: Vec<D>,
    now_at: T,
}

impl<T:Timestamp+Ord, D: Data> InputHelper<T, D> {
    fn new(mut observer: Counter<Tee<Product<RootTimestamp, T>, D>>) -> InputHelper<T, D> {
        observer.open(&Default::default());
        InputHelper {
            frontier: Rc::new(RefCell::new(MutableAntichain::new_bottom(Default::default()))),
            progress: Rc::new(RefCell::new(CountMap::new())),
            observer: observer,
            buffer: Vec::with_capacity(4096),
            now_at: Default::default(),
        }
    }

    fn flush(&mut self) {
        let mut message = Message::from_typed(&mut self.buffer);
        self.observer.give(&mut message);
        self.buffer = message.into_typed(4096);
        self.buffer.clear();
    }

    #[inline(always)] pub fn give(&mut self, data: D) {
        self.buffer.push(data);
        if self.buffer.len() == self.buffer.capacity() {
            self.flush();
        }
    }

    pub fn advance_to(&mut self, next: T) {
        if next > self.now_at {
            if self.buffer.len() > 0 {
                self.flush();
            }
            self.observer.shut(&Product::new(RootTimestamp, self.now_at.clone()));

            self.frontier.borrow_mut().update_weight(&Product::new(RootTimestamp, self.now_at.clone()), -1, &mut (*self.progress.borrow_mut()));
            self.frontier.borrow_mut().update_weight(&Product::new(RootTimestamp, next.clone()),  1, &mut (*self.progress.borrow_mut()));
            self.now_at = next;
            self.observer.open(&Product::new(RootTimestamp, self.now_at.clone()));
        }
        else {
            println!("attempted to advance to {:?}, but input already at {:?}", next, self.now_at);
        }
    }

    pub fn close(self) { }

    pub fn epoch(&self) -> &T { &self.now_at }
}

impl<T:Timestamp+Ord, D: Data> Drop for InputHelper<T, D> {
    fn drop(&mut self) {
        if self.buffer.len() > 0 {
            self.flush();
        }
        self.observer.shut(&Product::new(RootTimestamp, self.now_at.clone()));
        self.frontier.borrow_mut().update_weight(&Product::new(RootTimestamp, self.now_at.clone()), -1, &mut (*self.progress.borrow_mut()));
    }
}
<commit_msg>better sequence open<commit_after>use std::rc::Rc;
use std::cell::RefCell;
use std::default::Default;

use progress::frontier::{MutableAntichain, Antichain};
use progress::{Scope, Timestamp};
use progress::nested::subgraph::Source::{ScopeOutput};
use progress::count_map::CountMap;
use progress::timestamp::RootTimestamp;
use progress::nested::product::Product;

use communication::{Communicator, Data, Message, Observer};
use communication::observer::{Tee, Counter};

use construction::stream::Stream;
use construction::builder::*;

// TODO : This is an exogenous input, but it would be nice to wrap a Subgraph in something
// TODO : more like a harness, with direct access to its inputs.

// NOTE : This only takes a &self, not a &mut self, which works but is a bit weird.
// NOTE : Experiments with &mut indicate that the borrow of 'a lives for too long.
// NOTE : Might be able to fix with another lifetime parameter, say 'c: 'a.

// returns both an input scope and a stream representing its output.
pub trait InputExtensionTrait<C: Communicator, T: Timestamp+Ord> {
    fn new_input<D:Data>(&self) -> (InputHelper<T, D>, Stream<SubgraphBuilder<GraphRoot<C>, T>, D>);
}

impl<C: Communicator, T: Timestamp+Ord> InputExtensionTrait<C, T> for SubgraphBuilder<GraphRoot<C>, T> {
    fn new_input<D:Data>(&self) -> (InputHelper<T, D>, Stream<SubgraphBuilder<GraphRoot<C>, T>, D>) {

        let (output, registrar) = Tee::<Product<RootTimestamp, T>, D>::new();
        let produced = Rc::new(RefCell::new(CountMap::new()));

        let helper = InputHelper::new(Counter::new(output, produced.clone()));
        // {
        //     frontier: Rc::new(RefCell::new(MutableAntichain::new_bottom(Default::default()))),
        //     progress: Rc::new(RefCell::new(CountMap::new())),
        //     output:   Counter::new(output, produced.clone()),
        //     now_at:   Default::default(),
        //     closed:   false,
        // };

        let copies = self.peers();

        let index = self.add_scope(InputScope {
            frontier: helper.frontier.clone(),
            progress: helper.progress.clone(),
            messages: produced.clone(),
            copies:   copies,
        });

        return (helper, Stream::new(ScopeOutput(index, 0), registrar, self.clone()));
    }
}

pub struct InputScope<T:Timestamp+Ord> {
    frontier:   Rc<RefCell<MutableAntichain<Product<RootTimestamp, T>>>>,   // times available for sending
    progress:   Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // times closed since last asked
    messages:   Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // messages sent since last asked
    copies:     u64,
}

impl<T:Timestamp+Ord> Scope<Product<RootTimestamp, T>> for InputScope<T> {
    fn name(&self) -> String { format!("Input") }
    fn inputs(&self) -> u64 { 0 }
    fn outputs(&self) -> u64 { 1 }

    fn get_internal_summary(&mut self) -> (Vec<Vec<Antichain<<Product<RootTimestamp, T> as Timestamp>::Summary>>>,
                                           Vec<CountMap<Product<RootTimestamp, T>>>) {
        let mut map = CountMap::new();
        for x in self.frontier.borrow().elements().iter() {
            map.update(x, self.copies as i64);
        }
        (Vec::new(), vec![map])
    }

    fn pull_internal_progress(&mut self, frontier_progress: &mut [CountMap<Product<RootTimestamp, T>>],
                                        _messages_consumed: &mut [CountMap<Product<RootTimestamp, T>>],
                                         messages_produced: &mut [CountMap<Product<RootTimestamp, T>>]) -> bool
    {
        self.messages.borrow_mut().drain_into(&mut messages_produced[0]);
        self.progress.borrow_mut().drain_into(&mut frontier_progress[0]);
        return false;
    }

    fn notify_me(&self) -> bool { false }
}

pub struct InputHelper<T: Timestamp+Ord, D: Data> {
    frontier: Rc<RefCell<MutableAntichain<Product<RootTimestamp, T>>>>,   // times available for sending
    progress: Rc<RefCell<CountMap<Product<RootTimestamp, T>>>>,           // times closed since last asked
    observer: Counter<Tee<Product<RootTimestamp, T>, D>>,
    buffer: Vec<D>,
    now_at: T,
}

impl<T:Timestamp+Ord, D: Data> InputHelper<T, D> {
    fn new(mut observer: Counter<Tee<Product<RootTimestamp, T>, D>>) -> InputHelper<T, D> {
        InputHelper {
            frontier: Rc::new(RefCell::new(MutableAntichain::new_bottom(Default::default()))),
            progress: Rc::new(RefCell::new(CountMap::new())),
            observer: observer,
            buffer: Vec::with_capacity(4096),
            now_at: Default::default(),
        }
    }

    fn flush(&mut self) {
        let mut message = Message::from_typed(&mut self.buffer);
        self.observer.give(&mut message);
        self.buffer = message.into_typed(4096);
        self.buffer.clear();
    }

    #[inline] pub fn open(&mut self) {
        self.observer.open(&Default::default());
    }

    #[inline(always)] pub fn give(&mut self, data: D) {
        self.buffer.push(data);
        if self.buffer.len() == self.buffer.capacity() {
            self.flush();
        }
    }

    pub fn advance_to(&mut self, next: T) {
        if next > self.now_at {
            if self.buffer.len() > 0 {
                self.flush();
            }
            self.observer.shut(&Product::new(RootTimestamp, self.now_at.clone()));

            self.frontier.borrow_mut().update_weight(&Product::new(RootTimestamp, self.now_at.clone()), -1, &mut (*self.progress.borrow_mut()));
            self.frontier.borrow_mut().update_weight(&Product::new(RootTimestamp, next.clone()),  1, &mut (*self.progress.borrow_mut()));
            self.now_at = next;
            self.observer.open(&Product::new(RootTimestamp, self.now_at.clone()));
        }
        else {
            println!("attempted to advance to {:?}, but input already at {:?}", next, self.now_at);
        }
    }

    pub fn close(self) { }

    pub fn epoch(&self) -> &T { &self.now_at }
}

impl<T:Timestamp+Ord, D: Data> Drop for InputHelper<T, D> {
    fn drop(&mut self) {
        if self.buffer.len() > 0 {
            self.flush();
        }
        self.observer.shut(&Product::new(RootTimestamp, self.now_at.clone()));
        self.frontier.borrow_mut().update_weight(&Product::new(RootTimestamp, self.now_at.clone()), -1, &mut (*self.progress.borrow_mut()));
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

use anyhow::Result;
use libra_config::config::NodeConfig;
use libra_crypto::{
    ed25519::{Ed25519PrivateKey, Ed25519PublicKey},
    test_utils::KeyPair,
};
use std::{
    fs::{self, File},
    io::Write,
    path::{Path, PathBuf},
};

pub struct SwarmConfig {
    pub config_files: Vec<PathBuf>,
    pub faucet_key_path: PathBuf,
}

impl SwarmConfig {
    pub fn build<B: BuildSwarm, P: AsRef<Path>>(
        builder: &B,
        config_path: P,
    ) -> Result<SwarmConfig> {
        let (mut configs, faucet_key) = builder.build_swarm()?;
        let mut config_files = Vec::new();
        let config_dir = config_path.as_ref().to_path_buf();

        for (index, config) in configs.iter_mut().enumerate() {
            let node_dir = config_dir.join(format!("{}", index));
            let node_path = node_dir.join("node.config.toml");
            fs::create_dir_all(&node_dir)?;
            config.set_data_dir(node_dir);
            config.save(&node_path)?;
            config_files.push(node_path);
        }

        let faucet_key_path = config_dir.join("mint.key");
        let faucet_keypair = KeyPair::<Ed25519PrivateKey, Ed25519PublicKey>::from(faucet_key);
        let serialized_key = lcs::to_bytes(&faucet_keypair)?;
        let mut faucet_key_file = File::create(&faucet_key_path)?;
        faucet_key_file.write_all(&serialized_key)?;

        Ok(Self {
            config_files,
            faucet_key_path,
        })
    }
}

pub trait BuildSwarm {
    fn build_swarm(&self) -> Result<(Vec<NodeConfig>, Ed25519PrivateKey)>;
}
<commit_msg>[config] delete dynamic-config-builder<commit_after><|endoftext|>