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

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods};
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap};
use dom::bindings::js::{Root, RootedReference, LayoutJS};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use util::str::{DOMString, parse_unsigned_integer, split_html_space_chars};

use string_cache::{Atom, Namespace};

use std::borrow::ToOwned;
use std::cell::Ref;
use std::mem;
use std::ops::Deref;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[derive(JSTraceable, PartialEq, Clone)]
pub enum AttrValue {
    String(DOMString),
    TokenList(DOMString, Vec<Atom>),
    UInt(DOMString, u32),
    Atom(Atom),
}

impl AttrValue {
    pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue {
        let atoms =
            split_html_space_chars(&tokens)
            .map(Atom::from_slice)
            .fold(vec![], |mut acc, atom| {
                if !acc.contains(&atom) { acc.push(atom) }
                acc
            });
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
        let tokens = atoms.iter().map(|x| &**x).collect::<Vec<_>>().connect("\x20");
        AttrValue::TokenList(tokens, atoms)
    }

    // https://html.spec.whatwg.org/multipage/#reflecting-content-attributes-in-idl-attributes:idl-unsigned-long
    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
        let result = if result > 2147483647 {
            default
        } else {
            result
        };
        AttrValue::UInt(string, result)
    }

    // https://html.spec.whatwg.org/multipage/#limited-to-only-non-negative-numbers-greater-than-zero
    pub fn from_limited_u32(string: DOMString, default: u32) -> AttrValue {
        let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
        let result = if result == 0 || result > 2147483647 {
            default
        } else {
            result
        };
        AttrValue::UInt(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(&string);
        AttrValue::Atom(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<&'a [Atom]> {
        match *self {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None
        }
    }

    pub fn atom<'a>(&'a self) -> Option<&'a Atom> {
        match *self {
            AttrValue::Atom(ref value) => Some(value),
            _ => None
        }
    }
}

impl Deref for AttrValue {
    type Target = str;

    fn deref<'a>(&'a self) -> &'a str {
        match *self {
            AttrValue::String(ref value) |
                AttrValue::TokenList(ref value, _) |
                AttrValue::UInt(ref value, _) => &value,
            AttrValue::Atom(ref value) => &value,
        }
    }
}

// https://dom.spec.whatwg.org/#interface-attr
#[dom_struct]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: DOMRefCell<AttrValue>,
    name: Atom,
    namespace: Namespace,
    prefix: Option<Atom>,

    /// the element that owns this attribute.
    owner: MutNullableHeap<JS<Element>>,
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace,
                     prefix: Option<Atom>, owner: Option<&Element>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: DOMRefCell::new(value),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: MutNullableHeap::new(owner.map(JS::from_ref)),
        }
    }

    pub fn new(window: &Window, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<Atom>, owner: Option<&Element>) -> Root<Attr> {
        reflect_dom_object(
            box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
            GlobalRef::Window(window),
            AttrBinding::Wrap)
    }

    #[inline]
    pub fn name<'a>(&'a self) -> &'a Atom {
        &self.name
    }

    #[inline]
    pub fn namespace<'a>(&'a self) -> &'a Namespace {
        &self.namespace
    }

    #[inline]
    pub fn prefix<'a>(&'a self) -> &'a Option<Atom> {
        &self.prefix
    }
}

impl<'a> AttrMethods for &'a Attr {
    // https://dom.spec.whatwg.org/#dom-attr-localname
    fn LocalName(self) -> DOMString {
        (**self.local_name()).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn Value(self) -> DOMString {
        (**self.value()).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn SetValue(self, value: DOMString) {
        match self.owner() {
            None => *self.value.borrow_mut() = AttrValue::String(value),
            Some(owner) => {
                let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
                self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
            }
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn TextContent(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn SetTextContent(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn NodeValue(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn SetNodeValue(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-name
    fn Name(self) -> DOMString {
        (*self.name).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-namespaceuri
    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match &**atom {
            "" => None,
            url => Some(url.to_owned()),
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-prefix
    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix().as_ref().map(|p| (**p).to_owned())
    }

    // https://dom.spec.whatwg.org/#dom-attr-ownerelement
    fn GetOwnerElement(self) -> Option<Root<Element>> {
        self.owner()
    }

    // https://dom.spec.whatwg.org/#dom-attr-specified
    fn Specified(self) -> bool {
        true // Always returns true
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn set_owner(self, owner: Option<&Element>);
    fn owner(self) -> Option<Root<Element>>;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for &'a Attr {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
        assert!(Some(owner) == self.owner().r());

        let node = NodeCast::from_ref(owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            AttrSettingType::ReplacedAttr if namespace_is_null =>
                vtable_for(&node).before_remove_attr(self),
            _ => ()
        }

        *self.value.borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(self)
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.local_name
    }

    /// Sets the owner element. Should be called after the attribute is added
    /// or removed from its older parent.
    fn set_owner(self, owner: Option<&Element>) {
        let ref ns = self.namespace;
        match (self.owner().r(), owner) {
            (None, Some(new)) => {
                // Already in the list of attributes of new owner.
                assert!(new.get_attribute(&ns, &self.local_name) == Some(Root::from_ref(self)))
            }
            (Some(old), None) => {
                // Already gone from the list of attributes of old owner.
                assert!(old.get_attribute(&ns, &self.local_name).is_none())
            }
            (old, new) => assert!(old == new)
        }
        self.owner.set(owner.map(JS::from_ref))
    }

    fn owner(self) -> Option<Root<Element>> {
        self.owner.get().map(Root::from_rooted)
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: (**ns).to_owned(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

#[allow(unsafe_code)]
pub trait AttrHelpersForLayout {
    unsafe fn value_forever(&self) -> &'static AttrValue;
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
    unsafe fn value_for_layout(&self) -> &AttrValue;
}

#[allow(unsafe_code)]
impl AttrHelpersForLayout for LayoutJS<Attr> {
    #[inline]
    unsafe fn value_forever(&self) -> &'static AttrValue {
        // This transmute is used to cheat the lifetime restriction.
        mem::transmute::<&AttrValue, &AttrValue>((*self.unsafe_get()).value.borrow_for_layout())
    }

    #[inline]
    unsafe fn value_ref_forever(&self) -> &'static str {
        &**self.value_forever()
    }

    #[inline]
    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        let value = (*self.unsafe_get()).value.borrow_for_layout();
        match *value {
            AttrValue::Atom(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        match *self.value_forever() {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None,
        }
    }

    #[inline]
    unsafe fn local_name_atom_forever(&self) -> Atom {
        (*self.unsafe_get()).local_name.clone()
    }

    #[inline]
    unsafe fn value_for_layout(&self) -> &AttrValue {
        (*self.unsafe_get()).value.borrow_for_layout()
    }
}
<commit_msg>Join Atoms without requiring intermediate Vec<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::cell::DOMRefCell;
use dom::bindings::codegen::Bindings::AttrBinding::{self, AttrMethods};
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::GlobalRef;
use dom::bindings::js::{JS, MutNullableHeap};
use dom::bindings::js::{Root, RootedReference, LayoutJS};
use dom::bindings::utils::{Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::window::Window;
use dom::virtualmethods::vtable_for;

use devtools_traits::AttrInfo;
use util::str::{DOMString, parse_unsigned_integer, split_html_space_chars};

use string_cache::{Atom, Namespace};

use std::borrow::ToOwned;
use std::cell::Ref;
use std::mem;
use std::ops::Deref;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[derive(JSTraceable, PartialEq, Clone)]
pub enum AttrValue {
    String(DOMString),
    TokenList(DOMString, Vec<Atom>),
    UInt(DOMString, u32),
    Atom(Atom),
}

impl AttrValue {
    pub fn from_serialized_tokenlist(tokens: DOMString) -> AttrValue {
        let atoms =
            split_html_space_chars(&tokens)
            .map(Atom::from_slice)
            .fold(vec![], |mut acc, atom| {
                if !acc.contains(&atom) { acc.push(atom) }
                acc
            });
        AttrValue::TokenList(tokens, atoms)
    }

    pub fn from_atomic_tokens(atoms: Vec<Atom>) -> AttrValue {
        let tokens = atoms.iter().fold(String::new(), |mut s, atom| {
            if !s.is_empty() { s.push('\x20'); }
            s.push_str(atom);
            s
        });
        AttrValue::TokenList(tokens, atoms)
    }

    // https://html.spec.whatwg.org/multipage/#reflecting-content-attributes-in-idl-attributes:idl-unsigned-long
    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
        let result = if result > 2147483647 {
            default
        } else {
            result
        };
        AttrValue::UInt(string, result)
    }

    // https://html.spec.whatwg.org/multipage/#limited-to-only-non-negative-numbers-greater-than-zero
    pub fn from_limited_u32(string: DOMString, default: u32) -> AttrValue {
        let result = parse_unsigned_integer(string.chars()).unwrap_or(default);
        let result = if result == 0 || result > 2147483647 {
            default
        } else {
            result
        };
        AttrValue::UInt(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(&string);
        AttrValue::Atom(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<&'a [Atom]> {
        match *self {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None
        }
    }

    pub fn atom<'a>(&'a self) -> Option<&'a Atom> {
        match *self {
            AttrValue::Atom(ref value) => Some(value),
            _ => None
        }
    }
}

impl Deref for AttrValue {
    type Target = str;

    fn deref<'a>(&'a self) -> &'a str {
        match *self {
            AttrValue::String(ref value) |
                AttrValue::TokenList(ref value, _) |
                AttrValue::UInt(ref value, _) => &value,
            AttrValue::Atom(ref value) => &value,
        }
    }
}

// https://dom.spec.whatwg.org/#interface-attr
#[dom_struct]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: DOMRefCell<AttrValue>,
    name: Atom,
    namespace: Namespace,
    prefix: Option<Atom>,

    /// the element that owns this attribute.
    owner: MutNullableHeap<JS<Element>>,
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue, name: Atom, namespace: Namespace,
                     prefix: Option<Atom>, owner: Option<&Element>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: DOMRefCell::new(value),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: MutNullableHeap::new(owner.map(JS::from_ref)),
        }
    }

    pub fn new(window: &Window, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<Atom>, owner: Option<&Element>) -> Root<Attr> {
        reflect_dom_object(
            box Attr::new_inherited(local_name, value, name, namespace, prefix, owner),
            GlobalRef::Window(window),
            AttrBinding::Wrap)
    }

    #[inline]
    pub fn name<'a>(&'a self) -> &'a Atom {
        &self.name
    }

    #[inline]
    pub fn namespace<'a>(&'a self) -> &'a Namespace {
        &self.namespace
    }

    #[inline]
    pub fn prefix<'a>(&'a self) -> &'a Option<Atom> {
        &self.prefix
    }
}

impl<'a> AttrMethods for &'a Attr {
    // https://dom.spec.whatwg.org/#dom-attr-localname
    fn LocalName(self) -> DOMString {
        (**self.local_name()).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn Value(self) -> DOMString {
        (**self.value()).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-value
    fn SetValue(self, value: DOMString) {
        match self.owner() {
            None => *self.value.borrow_mut() = AttrValue::String(value),
            Some(owner) => {
                let value = owner.r().parse_attribute(&self.namespace, self.local_name(), value);
                self.set_value(AttrSettingType::ReplacedAttr, value, owner.r());
            }
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn TextContent(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-textcontent
    fn SetTextContent(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn NodeValue(self) -> DOMString {
        self.Value()
    }

    // https://dom.spec.whatwg.org/#dom-attr-nodevalue
    fn SetNodeValue(self, value: DOMString) {
        self.SetValue(value)
    }

    // https://dom.spec.whatwg.org/#dom-attr-name
    fn Name(self) -> DOMString {
        (*self.name).to_owned()
    }

    // https://dom.spec.whatwg.org/#dom-attr-namespaceuri
    fn GetNamespaceURI(self) -> Option<DOMString> {
        let Namespace(ref atom) = self.namespace;
        match &**atom {
            "" => None,
            url => Some(url.to_owned()),
        }
    }

    // https://dom.spec.whatwg.org/#dom-attr-prefix
    fn GetPrefix(self) -> Option<DOMString> {
        self.prefix().as_ref().map(|p| (**p).to_owned())
    }

    // https://dom.spec.whatwg.org/#dom-attr-ownerelement
    fn GetOwnerElement(self) -> Option<Root<Element>> {
        self.owner()
    }

    // https://dom.spec.whatwg.org/#dom-attr-specified
    fn Specified(self) -> bool {
        true // Always returns true
    }
}

pub trait AttrHelpers<'a> {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element);
    fn value(self) -> Ref<'a, AttrValue>;
    fn local_name(self) -> &'a Atom;
    fn set_owner(self, owner: Option<&Element>);
    fn owner(self) -> Option<Root<Element>>;
    fn summarize(self) -> AttrInfo;
}

impl<'a> AttrHelpers<'a> for &'a Attr {
    fn set_value(self, set_type: AttrSettingType, value: AttrValue, owner: &Element) {
        assert!(Some(owner) == self.owner().r());

        let node = NodeCast::from_ref(owner);
        let namespace_is_null = self.namespace == ns!("");

        match set_type {
            AttrSettingType::ReplacedAttr if namespace_is_null =>
                vtable_for(&node).before_remove_attr(self),
            _ => ()
        }

        *self.value.borrow_mut() = value;

        if namespace_is_null {
            vtable_for(&node).after_set_attr(self)
        }
    }

    fn value(self) -> Ref<'a, AttrValue> {
        self.value.borrow()
    }

    fn local_name(self) -> &'a Atom {
        &self.local_name
    }

    /// Sets the owner element. Should be called after the attribute is added
    /// or removed from its older parent.
    fn set_owner(self, owner: Option<&Element>) {
        let ref ns = self.namespace;
        match (self.owner().r(), owner) {
            (None, Some(new)) => {
                // Already in the list of attributes of new owner.
                assert!(new.get_attribute(&ns, &self.local_name) == Some(Root::from_ref(self)))
            }
            (Some(old), None) => {
                // Already gone from the list of attributes of old owner.
                assert!(old.get_attribute(&ns, &self.local_name).is_none())
            }
            (old, new) => assert!(old == new)
        }
        self.owner.set(owner.map(JS::from_ref))
    }

    fn owner(self) -> Option<Root<Element>> {
        self.owner.get().map(Root::from_rooted)
    }

    fn summarize(self) -> AttrInfo {
        let Namespace(ref ns) = self.namespace;
        AttrInfo {
            namespace: (**ns).to_owned(),
            name: self.Name(),
            value: self.Value(),
        }
    }
}

#[allow(unsafe_code)]
pub trait AttrHelpersForLayout {
    unsafe fn value_forever(&self) -> &'static AttrValue;
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]>;
    unsafe fn local_name_atom_forever(&self) -> Atom;
    unsafe fn value_for_layout(&self) -> &AttrValue;
}

#[allow(unsafe_code)]
impl AttrHelpersForLayout for LayoutJS<Attr> {
    #[inline]
    unsafe fn value_forever(&self) -> &'static AttrValue {
        // This transmute is used to cheat the lifetime restriction.
        mem::transmute::<&AttrValue, &AttrValue>((*self.unsafe_get()).value.borrow_for_layout())
    }

    #[inline]
    unsafe fn value_ref_forever(&self) -> &'static str {
        &**self.value_forever()
    }

    #[inline]
    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        let value = (*self.unsafe_get()).value.borrow_for_layout();
        match *value {
            AttrValue::Atom(ref val) => Some(val.clone()),
            _ => None,
        }
    }

    #[inline]
    unsafe fn value_tokens_forever(&self) -> Option<&'static [Atom]> {
        // This transmute is used to cheat the lifetime restriction.
        match *self.value_forever() {
            AttrValue::TokenList(_, ref tokens) => Some(tokens),
            _ => None,
        }
    }

    #[inline]
    unsafe fn local_name_atom_forever(&self) -> Atom {
        (*self.unsafe_get()).local_name.clone()
    }

    #[inline]
    unsafe fn value_for_layout(&self) -> &AttrValue {
        (*self.unsafe_get()).value.borrow_for_layout()
    }
}
<|endoftext|>


<commit_before>use crate::borrow_check::borrow_set::BorrowSet;
use crate::borrow_check::location::LocationTable;
use crate::borrow_check::nll::ToRegionVid;
use crate::borrow_check::nll::facts::AllFacts;
use crate::borrow_check::nll::region_infer::values::LivenessValues;
use rustc::infer::InferCtxt;
use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor;
use rustc::mir::{BasicBlock, BasicBlockData, Location, Body, Place, PlaceBase, Rvalue, TerminatorKind};
use rustc::mir::{Local, SourceInfo, Statement, StatementKind, Terminator};
use rustc::mir::UserTypeProjection;
use rustc::ty::fold::TypeFoldable;
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty};
use rustc::ty::subst::SubstsRef;

pub(super) fn generate_constraints<'cx, 'tcx>(
    infcx: &InferCtxt<'cx, 'tcx>,
    liveness_constraints: &mut LivenessValues<RegionVid>,
    all_facts: &mut Option<AllFacts>,
    location_table: &LocationTable,
    body: &Body<'tcx>,
    borrow_set: &BorrowSet<'tcx>,
) {
    let mut cg = ConstraintGeneration {
        borrow_set,
        infcx,
        liveness_constraints,
        location_table,
        all_facts,
    };

    for (bb, data) in body.basic_blocks().iter_enumerated() {
        cg.visit_basic_block_data(bb, data);
    }
}

/// 'cg = the duration of the constraint generation process itself.
struct ConstraintGeneration<'cg, 'cx, 'tcx> {
    infcx: &'cg InferCtxt<'cx, 'tcx>,
    all_facts: &'cg mut Option<AllFacts>,
    location_table: &'cg LocationTable,
    liveness_constraints: &'cg mut LivenessValues<RegionVid>,
    borrow_set: &'cg BorrowSet<'tcx>,
}

impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
    fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) {
        self.super_basic_block_data(bb, data);
    }

    /// We sometimes have `substs` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_substs(&mut self, substs: &SubstsRef<'tcx>, location: Location) {
        self.add_regular_live_constraint(*substs, location);
        self.super_substs(substs);
    }

    /// We sometimes have `region` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_region(&mut self, region: &ty::Region<'tcx>, location: Location) {
        self.add_regular_live_constraint(*region, location);
        self.super_region(region);
    }

    /// We sometimes have `ty` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) {
        match ty_context {
            TyContext::ReturnTy(SourceInfo { span, .. })
            | TyContext::YieldTy(SourceInfo { span, .. })
            | TyContext::UserTy(span)
            | TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
                span_bug!(
                    span,
                    "should not be visiting outside of the CFG: {:?}",
                    ty_context
                );
            }
            TyContext::Location(location) => {
                self.add_regular_live_constraint(ty, location);
            }
        }

        self.super_ty(ty);
    }

    /// We sometimes have `generator_substs` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) {
        self.add_regular_live_constraint(*substs, location);
        self.super_generator_substs(substs);
    }

    /// We sometimes have `closure_substs` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, location: Location) {
        self.add_regular_live_constraint(*substs, location);
        self.super_closure_substs(substs);
    }

    fn visit_statement(
        &mut self,
        statement: &Statement<'tcx>,
        location: Location,
    ) {
        if let Some(all_facts) = self.all_facts {
            all_facts.cfg_edge.push((
                self.location_table.start_index(location),
                self.location_table.mid_index(location),
            ));

            all_facts.cfg_edge.push((
                self.location_table.mid_index(location),
                self.location_table
                    .start_index(location.successor_within_block()),
            ));

            // If there are borrows on this now dead local, we need to record them as `killed`.
            if let StatementKind::StorageDead(ref local) = statement.kind {
                record_killed_borrows_for_local(
                    all_facts,
                    self.borrow_set,
                    self.location_table,
                    local,
                    location,
                );
            }
        }

        self.super_statement(statement, location);
    }

    fn visit_assign(
        &mut self,
        place: &Place<'tcx>,
        rvalue: &Rvalue<'tcx>,
        location: Location,
    ) {
        // When we see `X = ...`, then kill borrows of
        // `(*X).foo` and so forth.
        self.record_killed_borrows_for_place(place, location);

        self.super_assign(place, rvalue, location);
    }

    fn visit_terminator(
        &mut self,
        terminator: &Terminator<'tcx>,
        location: Location,
    ) {
        if let Some(all_facts) = self.all_facts {
            all_facts.cfg_edge.push((
                self.location_table.start_index(location),
                self.location_table.mid_index(location),
            ));

            let successor_blocks = terminator.successors();
            all_facts.cfg_edge.reserve(successor_blocks.size_hint().0);
            for successor_block in successor_blocks {
                all_facts.cfg_edge.push((
                    self.location_table.mid_index(location),
                    self.location_table
                        .start_index(successor_block.start_location()),
                ));
            }
        }

        // A `Call` terminator's return value can be a local which has borrows,
        // so we need to record those as `killed` as well.
        if let TerminatorKind::Call { ref destination, .. } = terminator.kind {
            if let Some((place, _)) = destination {
                self.record_killed_borrows_for_place(place, location);
            }
        }

        self.super_terminator(terminator, location);
    }

    fn visit_ascribe_user_ty(
        &mut self,
        _place: &Place<'tcx>,
        _variance: &ty::Variance,
        _user_ty: &UserTypeProjection,
        _location: Location,
    ) {
    }
}

impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
    /// Some variable with type `live_ty` is "regular live" at
    /// `location` -- i.e., it may be used later. This means that all
    /// regions appearing in the type `live_ty` must be live at
    /// `location`.
    fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location)
    where
        T: TypeFoldable<'tcx>,
    {
        debug!(
            "add_regular_live_constraint(live_ty={:?}, location={:?})",
            live_ty, location
        );

        self.infcx
            .tcx
            .for_each_free_region(&live_ty, |live_region| {
                let vid = live_region.to_region_vid();
                self.liveness_constraints.add_element(vid, location);
            });
    }

    /// When recording facts for Polonius, records the borrows on the specified place
    /// as `killed`. For example, when assigning to a local, or on a call's return destination.
    fn record_killed_borrows_for_place(&mut self, place: &Place<'tcx>, location: Location) {
        if let Some(all_facts) = self.all_facts {
            if let Place {
                base: PlaceBase::Local(local),
                projection: None,
            } = place {
                record_killed_borrows_for_local(
                    all_facts,
                    self.borrow_set,
                    self.location_table,
                    local,
                    location,
                );
            }
        }
    }
}

/// When recording facts for Polonius, records the borrows on the specified local as `killed`.
fn record_killed_borrows_for_local(
    all_facts: &mut AllFacts,
    borrow_set: &BorrowSet<'_>,
    location_table: &LocationTable,
    local: &Local,
    location: Location,
) {
    if let Some(borrow_indices) = borrow_set.local_map.get(local) {
        all_facts.killed.reserve(borrow_indices.len());
        for &borrow_index in borrow_indices {
            let location_index = location_table.mid_index(location);
            all_facts.killed.push((borrow_index, location_index));
        }
    }
}
<commit_msg>Polonius: generate `killed` facts for assignments to projections<commit_after>use crate::borrow_check::borrow_set::BorrowSet;
use crate::borrow_check::location::LocationTable;
use crate::borrow_check::nll::ToRegionVid;
use crate::borrow_check::nll::facts::AllFacts;
use crate::borrow_check::nll::region_infer::values::LivenessValues;
use crate::borrow_check::places_conflict;
use rustc::infer::InferCtxt;
use rustc::mir::visit::TyContext;
use rustc::mir::visit::Visitor;
use rustc::mir::{
    BasicBlock, BasicBlockData, Body, Local, Location, Place, PlaceBase, Projection,
    ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind,
    UserTypeProjection,
};
use rustc::ty::fold::TypeFoldable;
use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty};
use rustc::ty::subst::SubstsRef;

pub(super) fn generate_constraints<'cx, 'tcx>(
    infcx: &InferCtxt<'cx, 'tcx>,
    liveness_constraints: &mut LivenessValues<RegionVid>,
    all_facts: &mut Option<AllFacts>,
    location_table: &LocationTable,
    body: &Body<'tcx>,
    borrow_set: &BorrowSet<'tcx>,
) {
    let mut cg = ConstraintGeneration {
        borrow_set,
        infcx,
        liveness_constraints,
        location_table,
        all_facts,
        body,
    };

    for (bb, data) in body.basic_blocks().iter_enumerated() {
        cg.visit_basic_block_data(bb, data);
    }
}

/// 'cg = the duration of the constraint generation process itself.
struct ConstraintGeneration<'cg, 'cx, 'tcx> {
    infcx: &'cg InferCtxt<'cx, 'tcx>,
    all_facts: &'cg mut Option<AllFacts>,
    location_table: &'cg LocationTable,
    liveness_constraints: &'cg mut LivenessValues<RegionVid>,
    borrow_set: &'cg BorrowSet<'tcx>,
    body: &'cg Body<'tcx>,
}

impl<'cg, 'cx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'tcx> {
    fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>) {
        self.super_basic_block_data(bb, data);
    }

    /// We sometimes have `substs` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_substs(&mut self, substs: &SubstsRef<'tcx>, location: Location) {
        self.add_regular_live_constraint(*substs, location);
        self.super_substs(substs);
    }

    /// We sometimes have `region` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_region(&mut self, region: &ty::Region<'tcx>, location: Location) {
        self.add_regular_live_constraint(*region, location);
        self.super_region(region);
    }

    /// We sometimes have `ty` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_ty(&mut self, ty: Ty<'tcx>, ty_context: TyContext) {
        match ty_context {
            TyContext::ReturnTy(SourceInfo { span, .. })
            | TyContext::YieldTy(SourceInfo { span, .. })
            | TyContext::UserTy(span)
            | TyContext::LocalDecl { source_info: SourceInfo { span, .. }, .. } => {
                span_bug!(
                    span,
                    "should not be visiting outside of the CFG: {:?}",
                    ty_context
                );
            }
            TyContext::Location(location) => {
                self.add_regular_live_constraint(ty, location);
            }
        }

        self.super_ty(ty);
    }

    /// We sometimes have `generator_substs` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) {
        self.add_regular_live_constraint(*substs, location);
        self.super_generator_substs(substs);
    }

    /// We sometimes have `closure_substs` within an rvalue, or within a
    /// call. Make them live at the location where they appear.
    fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, location: Location) {
        self.add_regular_live_constraint(*substs, location);
        self.super_closure_substs(substs);
    }

    fn visit_statement(
        &mut self,
        statement: &Statement<'tcx>,
        location: Location,
    ) {
        if let Some(all_facts) = self.all_facts {
            all_facts.cfg_edge.push((
                self.location_table.start_index(location),
                self.location_table.mid_index(location),
            ));

            all_facts.cfg_edge.push((
                self.location_table.mid_index(location),
                self.location_table
                    .start_index(location.successor_within_block()),
            ));

            // If there are borrows on this now dead local, we need to record them as `killed`.
            if let StatementKind::StorageDead(ref local) = statement.kind {
                record_killed_borrows_for_local(
                    all_facts,
                    self.borrow_set,
                    self.location_table,
                    local,
                    location,
                );
            }
        }

        self.super_statement(statement, location);
    }

    fn visit_assign(
        &mut self,
        place: &Place<'tcx>,
        rvalue: &Rvalue<'tcx>,
        location: Location,
    ) {
        // When we see `X = ...`, then kill borrows of
        // `(*X).foo` and so forth.
        self.record_killed_borrows_for_place(place, location);

        self.super_assign(place, rvalue, location);
    }

    fn visit_terminator(
        &mut self,
        terminator: &Terminator<'tcx>,
        location: Location,
    ) {
        if let Some(all_facts) = self.all_facts {
            all_facts.cfg_edge.push((
                self.location_table.start_index(location),
                self.location_table.mid_index(location),
            ));

            let successor_blocks = terminator.successors();
            all_facts.cfg_edge.reserve(successor_blocks.size_hint().0);
            for successor_block in successor_blocks {
                all_facts.cfg_edge.push((
                    self.location_table.mid_index(location),
                    self.location_table
                        .start_index(successor_block.start_location()),
                ));
            }
        }

        // A `Call` terminator's return value can be a local which has borrows,
        // so we need to record those as `killed` as well.
        if let TerminatorKind::Call { ref destination, .. } = terminator.kind {
            if let Some((place, _)) = destination {
                self.record_killed_borrows_for_place(place, location);
            }
        }

        self.super_terminator(terminator, location);
    }

    fn visit_ascribe_user_ty(
        &mut self,
        _place: &Place<'tcx>,
        _variance: &ty::Variance,
        _user_ty: &UserTypeProjection,
        _location: Location,
    ) {
    }
}

impl<'cx, 'cg, 'tcx> ConstraintGeneration<'cx, 'cg, 'tcx> {
    /// Some variable with type `live_ty` is "regular live" at
    /// `location` -- i.e., it may be used later. This means that all
    /// regions appearing in the type `live_ty` must be live at
    /// `location`.
    fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location)
    where
        T: TypeFoldable<'tcx>,
    {
        debug!(
            "add_regular_live_constraint(live_ty={:?}, location={:?})",
            live_ty, location
        );

        self.infcx
            .tcx
            .for_each_free_region(&live_ty, |live_region| {
                let vid = live_region.to_region_vid();
                self.liveness_constraints.add_element(vid, location);
            });
    }

    /// When recording facts for Polonius, records the borrows on the specified place
    /// as `killed`. For example, when assigning to a local, or on a call's return destination.
    fn record_killed_borrows_for_place(&mut self, place: &Place<'tcx>, location: Location) {
        if let Some(all_facts) = self.all_facts {
            // Depending on the `Place` we're killing:
            // - if it's a local, or a single deref of a local,
            //   we kill all the borrows on the local.
            // - if it's a deeper projection, we have to filter which
            //   of the borrows are killed: the ones whose `borrowed_place`
            //   conflicts with the `place`.
            match place {
                Place {
                    base: PlaceBase::Local(local),
                    projection: None,
                } |
                Place {
                    base: PlaceBase::Local(local),
                    projection: Some(box Projection {
                        base: None,
                        elem: ProjectionElem::Deref,
                    }),
                } => {
                    debug!(
                        "Recording `killed` facts for borrows of local={:?} at location={:?}",
                        local, location
                    );

                    record_killed_borrows_for_local(
                        all_facts,
                        self.borrow_set,
                        self.location_table,
                        local,
                        location,
                    );
                }

                Place {
                    base: PlaceBase::Static(_),
                    ..
                } => {
                    // Ignore kills of static or static mut variables.
                }

                Place {
                    base: PlaceBase::Local(local),
                    projection: Some(_),
                } => {
                    // Kill conflicting borrows of the innermost local.
                    debug!(
                        "Recording `killed` facts for borrows of \
                            innermost projected local={:?} at location={:?}",
                        local, location
                    );

                    if let Some(borrow_indices) = self.borrow_set.local_map.get(local) {
                        for &borrow_index in borrow_indices {
                            let places_conflict = places_conflict::places_conflict(
                                self.infcx.tcx,
                                self.body,
                                &self.borrow_set.borrows[borrow_index].borrowed_place,
                                place,
                                places_conflict::PlaceConflictBias::NoOverlap,
                            );

                            if places_conflict {
                                let location_index = self.location_table.mid_index(location);
                                all_facts.killed.push((borrow_index, location_index));
                            }
                        }
                    }
                }
            }
        }
    }
}

/// When recording facts for Polonius, records the borrows on the specified local as `killed`.
fn record_killed_borrows_for_local(
    all_facts: &mut AllFacts,
    borrow_set: &BorrowSet<'_>,
    location_table: &LocationTable,
    local: &Local,
    location: Location,
) {
    if let Some(borrow_indices) = borrow_set.local_map.get(local) {
        all_facts.killed.reserve(borrow_indices.len());
        for &borrow_index in borrow_indices {
            let location_index = location_table.mid_index(location);
            all_facts.killed.push((borrow_index, location_index));
        }
    }
}
<|endoftext|>


<commit_before>extern crate multibloom;

use multibloom::BloomFilter;

use std::fs::File;
use std::path::Path;
use std::io::Read;

fn main() {
    let path = Path::new("/usr/share/dict/words");
    let mut dict_file = File::open(&path).unwrap();
    let mut word_list = String::new();
    dict_file.read_to_string(&mut word_list).ok();

    let words: Vec<&str> = word_list.split('\n').collect();

    let expected_false_positive_rate = 0.1;

    let size_of_bloom_filter = 100_000;

    let mut dict_bloom = BloomFilter::new_with_params(size_of_bloom_filter, expected_false_positive_rate);

    let words_iter = words.iter();

    let no_to_check = 20000;
    let no_to_add = 100000;

    let new_words = words_iter.clone().take(no_to_add);
    for new_word in new_words {
        dict_bloom.add(new_word);
    }

    let mut false_positives = 0;

    let check_words = words_iter.skip(no_to_add).take(no_to_check);
    for check_word in check_words {
        if dict_bloom.query(check_word) {
            false_positives += 1;
        }
    }

    println!("Bloom filter: {:?}", dict_bloom);
    println!("Found {:?}% false positives. Expected {:?}", false_positives as f32 * 100.0 / no_to_check as f32, expected_false_positive_rate);
}
<commit_msg>Example variable name clearer<commit_after>extern crate multibloom;

use multibloom::BloomFilter;

use std::fs::File;
use std::path::Path;
use std::io::Read;

fn main() {
    let path = Path::new("/usr/share/dict/words");
    let mut dict_file = File::open(&path).unwrap();
    let mut word_list = String::new();
    dict_file.read_to_string(&mut word_list).ok();

    let words: Vec<&str> = word_list.split('\n').collect();

    let expected_false_positive_rate = 0.1;

    let expected_number_items = 100_000;

    let mut dict_bloom = BloomFilter::new_with_params(expected_number_items, expected_false_positive_rate);

    let words_iter = words.iter();

    let no_to_check = 20000;
    let no_to_add = 100000;

    let new_words = words_iter.clone().take(no_to_add);
    for new_word in new_words {
        dict_bloom.add(new_word);
    }

    let mut false_positives = 0;

    let check_words = words_iter.skip(no_to_add).take(no_to_check);
    for check_word in check_words {
        if dict_bloom.query(check_word) {
            false_positives += 1;
        }
    }

    println!("Bloom filter: {:?}", dict_bloom);
    println!("Found {:?}% false positives. Expected {:?}", false_positives as f32 * 100.0 / no_to_check as f32, expected_false_positive_rate);
}
<|endoftext|>


<commit_before>///This zero-delay feedback filter is based on a 4-stage transistor ladder filter.
///It follows the following equations:
///x = input - tanh(self.res * self.vout[3])
///vout[0] = self.g * (tanh(x) - tanh(self.vout[0])) + self.s[0]
///vout[1] = self.g * (tanh(self.vout[0]) - tanh(self.vout[1])) + self.s[1]
///vout[0] = self.g * (tanh(self.vout[1]) - tanh(self.vout[2])) + self.s[2]
///vout[0] = self.g * (tanh(self.vout[2]) - tanh(self.vout[3])) + self.s[3]
///since we can't easily solve a nonlinear equation,
///Mystran's fixed-pivot method is used to approximate the tanh() parts.
///Quality can be improved a lot by oversampling a bit.
///Feedback is clipped independently of the input, so it doesn't disappear at high gains.

 #[macro_use] extern crate vst;
use vst::buffer::AudioBuffer;
use vst::plugin::{Info, Plugin, Category};

#[derive(PartialEq)]
enum Method {
    Linear,  // linear solution
    Pivotal, // Mystran's "cheap" method, using x=0 as pivot
}

//this is a 4-pole filter with resonance, which is why there's 4 states and vouts
#[derive(Clone)]
struct LadderFilter {
    //the output of the different filter stages
    vout: [f32; 4],
    //s is the "state" parameter. In an IIR it would be the last value from the filter
    //In this we find it by trapezoidal integration to avoid the unit delay
    s: [f32; 4],
    //the "cutoff" parameter. Determines how heavy filtering is
    cutoff: f32,
    g: f32,
    //needed to calculate cutoff.
    sample_rate: f32,
    //makes a peak at cutoff
    res: f32,
    //used to choose if we want it to output 1 or 2 order filtering
    poles: usize,
    //a drive parameter. Just used to increase the volume, which results in heavier distortion
    drive: f32,
}
//member methods for the struct
impl LadderFilter {
    pub fn set_cutoff(&mut self, value: f32) {
        //cutoff formula gives us a natural feeling cutoff knob that spends more time in the low frequencies
        self.cutoff = 20000. * (1.8f32.powf(10. * value - 10.));
        //bilinear transformation for g gives us a very accurate cutoff
        self.g = (3.1415 * self.cutoff / (self.sample_rate)).tan();
    }
    //the state needs to be updated after each process. Found by trapezoidal integration
    fn update_state(&mut self) {
        self.s[0] = 2. * self.vout[0] - self.s[0];
        self.s[1] = 2. * self.vout[1] - self.s[1];
        self.s[2] = 2. * self.vout[2] - self.s[2];
        self.s[3] = 2. * self.vout[3] - self.s[3];
    }
    //performs a complete filter process (mystran's method)
    fn tick_pivotal(&mut self, input: f32) {
        if self.drive > 0. {
            self.run_ladder_nonlinear(input * (self.drive + 0.7), Method::Pivotal);
        } else {
            //
            self.run_ladder_nonlinear(input, Method::Linear);
        }
        self.update_state();
    }
    //instead of proper nonlinearities, this just has soft-clipping on the input
    fn _tick_simple(&mut self, input: f32) {
        if self.drive > 0. {
            self.run_ladder_simple(input * (self.drive + 0.7));
        }
        else {
            self.run_ladder_nonlinear(input, Method::Linear);
        }
        self.update_state();
    }
    fn run_ladder_simple(&mut self, input: f32) {
        let x = input.tanh();
        //denominators of solutions of individual stages. Simplifies the math a bit
            let g0 = 1. / (1. + self.g);
            let g1 = self.g * g0 * g0;
            let g2 = self.g * g1 * g0;
            let g3 = self.g * g2 * g0;
            //outputs a 24db filter
            self.vout[3] = (g3 * self.g * x
                + g0 * self.s[3]
                + g1 * self.s[2]
                + g2 * self.s[1]
                + g3 * self.s[0])
                / (g3 * self.g * self.res + 1.);
            //since we know the feedback, we can solve the remaining outputs:
            self.vout[0] = g0 * (self.g * (x - self.res * self.vout[3]) + self.s[0]);
            self.vout[1] = g0 * (self.g * self.vout[0] + self.s[1]);
            self.vout[2] = g0 * (self.g * self.vout[1] + self.s[2]);
    }
    //nonlinear ladder filter function.
    fn run_ladder_nonlinear(&mut self, input: f32, method: Method) {
        let mut a = [1f32; 5];
        //version with drive
        if method == Method::Pivotal {
            let base = [
                0.,//self.res * self.s[3],
                self.s[0],
                self.s[1],
                self.s[2],
                self.s[3],
            ];
            //a[n] is the fixed-pivot approximation for tanh()
            for n in 0..base.len() {
                if base[n] != 0. {
                    a[n] = base[n].tanh() / base[n];
                } else {
                    a[n] = 1.;
                }
            }
            //denominators of solutions of individual stages. Simplifies the math a bit
            let g0 = 1. / (1. + self.g * a[1]); let g1 = 1. / (1. + self.g * a[2]);
            let g2 = 1. / (1. + self.g * a[3]); let g3 = 1. / (1. + self.g * a[4]);
            // these are just factored out of the feedback solution. Makes the math way easier to read
            let f3 = self.g * a[3] * g3; let f2 = self.g * a[2] * g2 * f3;
            let f1 = self.g * a[1] * g1 * f2; let f0 = self.g * g0 * f1;
            //outputs a 24db filter
            self.vout[3] = (f0 * input + f1 * g0 * self.s[0]
                + f2 * g1 * self.s[1]
                + f3 * g2 * self.s[2]
                + g3 * self.s[3])
                / (f0 * self.res * a[3] + 1.);
            //since we know the feedback, we can solve the remaining outputs:
            self.vout[0] =
                g0 * (self.g * a[1] * (input - self.res * a[3] * self.vout[3]) + self.s[0]);
            self.vout[1] = g1 * (self.g * a[2] * self.vout[0] + self.s[1]);
            self.vout[2] = g2 * (self.g * a[3] * self.vout[1] + self.s[2]);
        }
        //linear version without drive
        else {
            //denominators of solutions of individual stages. Simplifies the math a bit
            let g0 = 1. / (1. + self.g);
            let g1 = self.g * g0 * g0;
            let g2 = self.g * g1 * g0;
            let g3 = self.g * g2 * g0;
            //outputs a 24db filter
            self.vout[3] = (g3 * self.g * input
                + g0 * self.s[3]
                + g1 * self.s[2]
                + g2 * self.s[1]
                + g3 * self.s[0])
                / (g3 * self.g * self.res + 1.);
            //since we know the feedback, we can solve the remaining outputs:
            self.vout[0] = g0 * (self.g * (input - self.res * self.vout[3]) + self.s[0]);
            self.vout[1] = g0 * (self.g * self.vout[0] + self.s[1]);
            self.vout[2] = g0 * (self.g * self.vout[1] + self.s[2]);
        }
    }
}
//default values for parameters
impl Default for LadderFilter {
    fn default() -> LadderFilter {
        LadderFilter {
            vout: [0f32; 4],
            s: [0f32; 4],
            sample_rate: 88200.,
            cutoff: 1000.,
            res: 2.0,
            g: 0.07135868087,
            poles: 3,
            drive: 0.,
        }
    }
}

impl Plugin for LadderFilter
{
    fn set_sample_rate(&mut self, rate: f32) {
        self.sample_rate = rate;
    }
    fn get_info(&self) -> Info
    {
        Info  {
            name: "LadderFilter".to_string(),
            unique_id: 9263,
            inputs: 1,
            outputs: 1,
            category: Category::Effect,
            parameters: 4,
            ..Default::default()
        }
    }
    fn get_parameter(&self, index: i32) -> f32 {
    match index {
        0 => self.cutoff,
        1 => self.res,
        2 => (self.poles) as f32 + 1.,
        3 => self.drive,
        _ => 0.0,
        }
    }
    fn set_parameter(&mut self, index: i32, value: f32) {
        match index {
            0 => self.set_cutoff(value),
            1 => self.res = value * 4.,
            2 => self.poles = ((value * 3.).round()) as usize,
            3 => self.drive = value * 5.,
            _ => (),
        }
    }

    fn get_parameter_name(&self, index: i32) -> String {
        match index {
            0 => "cutoff".to_string(),
            1 => "resonance".to_string(),
            2 => "filter order".to_string(),
            3 => "drive".to_string(),
            _ => "".to_string(),
        }
    }
    fn get_parameter_label(&self, index: i32) -> String {
        match index {
            0 => "Hz".to_string(),
            1 => "%".to_string(),
            2 => "poles".to_string(),
            3 => "%".to_string(),
            _ => "".to_string(),
        }
    }
    fn process(&mut self, buffer: &mut AudioBuffer<f32>) {
        for (input_buffer, output_buffer) in buffer.zip() {
            for (input_sample, output_sample) in input_buffer.iter().zip(output_buffer) {
                self.tick_pivotal(*input_sample);
                //the poles parameter chooses which filter stage we take our output from.
                *output_sample = self.vout[self.poles];
            }
        }
    }
}
plugin_main!(LadderFilter);
<commit_msg>Changed /// to //!<commit_after>//!This zero-delay feedback filter is based on a 4-stage transistor ladder filter.
//!It follows the following equations:
//!x = input - tanh(self.res * self.vout[3])
//!vout[0] = self.g * (tanh(x) - tanh(self.vout[0])) + self.s[0]
//!vout[1] = self.g * (tanh(self.vout[0]) - tanh(self.vout[1])) + self.s[1]
//!vout[0] = self.g * (tanh(self.vout[1]) - tanh(self.vout[2])) + self.s[2]
//!vout[0] = self.g * (tanh(self.vout[2]) - tanh(self.vout[3])) + self.s[3]
//!since we can't easily solve a nonlinear equation,
//!Mystran's fixed-pivot method is used to approximate the tanh() parts.
//!Quality can be improved a lot by oversampling a bit.
//!Feedback is clipped independently of the input, so it doesn't disappear at high gains.

 #[macro_use] extern crate vst;
use vst::buffer::AudioBuffer;
use vst::plugin::{Info, Plugin, Category};

#[derive(PartialEq)]
enum Method {
    Linear,  // linear solution
    Pivotal, // Mystran's "cheap" method, using x=0 as pivot
}

//this is a 4-pole filter with resonance, which is why there's 4 states and vouts
#[derive(Clone)]
struct LadderFilter {
    //the output of the different filter stages
    vout: [f32; 4],
    //s is the "state" parameter. In an IIR it would be the last value from the filter
    //In this we find it by trapezoidal integration to avoid the unit delay
    s: [f32; 4],
    //the "cutoff" parameter. Determines how heavy filtering is
    cutoff: f32,
    g: f32,
    //needed to calculate cutoff.
    sample_rate: f32,
    //makes a peak at cutoff
    res: f32,
    //used to choose if we want it to output 1 or 2 order filtering
    poles: usize,
    //a drive parameter. Just used to increase the volume, which results in heavier distortion
    drive: f32,
}
//member methods for the struct
impl LadderFilter {
    pub fn set_cutoff(&mut self, value: f32) {
        //cutoff formula gives us a natural feeling cutoff knob that spends more time in the low frequencies
        self.cutoff = 20000. * (1.8f32.powf(10. * value - 10.));
        //bilinear transformation for g gives us a very accurate cutoff
        self.g = (3.1415 * self.cutoff / (self.sample_rate)).tan();
    }
    //the state needs to be updated after each process. Found by trapezoidal integration
    fn update_state(&mut self) {
        self.s[0] = 2. * self.vout[0] - self.s[0];
        self.s[1] = 2. * self.vout[1] - self.s[1];
        self.s[2] = 2. * self.vout[2] - self.s[2];
        self.s[3] = 2. * self.vout[3] - self.s[3];
    }
    //performs a complete filter process (mystran's method)
    fn tick_pivotal(&mut self, input: f32) {
        if self.drive > 0. {
            self.run_ladder_nonlinear(input * (self.drive + 0.7), Method::Pivotal);
        } else {
            //
            self.run_ladder_nonlinear(input, Method::Linear);
        }
        self.update_state();
    }
    //instead of proper nonlinearities, this just has soft-clipping on the input
    fn _tick_simple(&mut self, input: f32) {
        if self.drive > 0. {
            self.run_ladder_simple(input * (self.drive + 0.7));
        }
        else {
            self.run_ladder_nonlinear(input, Method::Linear);
        }
        self.update_state();
    }
    fn run_ladder_simple(&mut self, input: f32) {
        let x = input.tanh();
        //denominators of solutions of individual stages. Simplifies the math a bit
            let g0 = 1. / (1. + self.g);
            let g1 = self.g * g0 * g0;
            let g2 = self.g * g1 * g0;
            let g3 = self.g * g2 * g0;
            //outputs a 24db filter
            self.vout[3] = (g3 * self.g * x
                + g0 * self.s[3]
                + g1 * self.s[2]
                + g2 * self.s[1]
                + g3 * self.s[0])
                / (g3 * self.g * self.res + 1.);
            //since we know the feedback, we can solve the remaining outputs:
            self.vout[0] = g0 * (self.g * (x - self.res * self.vout[3]) + self.s[0]);
            self.vout[1] = g0 * (self.g * self.vout[0] + self.s[1]);
            self.vout[2] = g0 * (self.g * self.vout[1] + self.s[2]);
    }
    //nonlinear ladder filter function.
    fn run_ladder_nonlinear(&mut self, input: f32, method: Method) {
        let mut a = [1f32; 5];
        //version with drive
        if method == Method::Pivotal {
            let base = [
                0.,//self.res * self.s[3],
                self.s[0],
                self.s[1],
                self.s[2],
                self.s[3],
            ];
            //a[n] is the fixed-pivot approximation for tanh()
            for n in 0..base.len() {
                if base[n] != 0. {
                    a[n] = base[n].tanh() / base[n];
                } else {
                    a[n] = 1.;
                }
            }
            //denominators of solutions of individual stages. Simplifies the math a bit
            let g0 = 1. / (1. + self.g * a[1]); let g1 = 1. / (1. + self.g * a[2]);
            let g2 = 1. / (1. + self.g * a[3]); let g3 = 1. / (1. + self.g * a[4]);
            // these are just factored out of the feedback solution. Makes the math way easier to read
            let f3 = self.g * a[3] * g3; let f2 = self.g * a[2] * g2 * f3;
            let f1 = self.g * a[1] * g1 * f2; let f0 = self.g * g0 * f1;
            //outputs a 24db filter
            self.vout[3] = (f0 * input + f1 * g0 * self.s[0]
                + f2 * g1 * self.s[1]
                + f3 * g2 * self.s[2]
                + g3 * self.s[3])
                / (f0 * self.res * a[3] + 1.);
            //since we know the feedback, we can solve the remaining outputs:
            self.vout[0] =
                g0 * (self.g * a[1] * (input - self.res * a[3] * self.vout[3]) + self.s[0]);
            self.vout[1] = g1 * (self.g * a[2] * self.vout[0] + self.s[1]);
            self.vout[2] = g2 * (self.g * a[3] * self.vout[1] + self.s[2]);
        }
        //linear version without drive
        else {
            //denominators of solutions of individual stages. Simplifies the math a bit
            let g0 = 1. / (1. + self.g);
            let g1 = self.g * g0 * g0;
            let g2 = self.g * g1 * g0;
            let g3 = self.g * g2 * g0;
            //outputs a 24db filter
            self.vout[3] = (g3 * self.g * input
                + g0 * self.s[3]
                + g1 * self.s[2]
                + g2 * self.s[1]
                + g3 * self.s[0])
                / (g3 * self.g * self.res + 1.);
            //since we know the feedback, we can solve the remaining outputs:
            self.vout[0] = g0 * (self.g * (input - self.res * self.vout[3]) + self.s[0]);
            self.vout[1] = g0 * (self.g * self.vout[0] + self.s[1]);
            self.vout[2] = g0 * (self.g * self.vout[1] + self.s[2]);
        }
    }
}
//default values for parameters
impl Default for LadderFilter {
    fn default() -> LadderFilter {
        LadderFilter {
            vout: [0f32; 4],
            s: [0f32; 4],
            sample_rate: 88200.,
            cutoff: 1000.,
            res: 2.0,
            g: 0.07135868087,
            poles: 3,
            drive: 0.,
        }
    }
}

impl Plugin for LadderFilter
{
    fn set_sample_rate(&mut self, rate: f32) {
        self.sample_rate = rate;
    }
    fn get_info(&self) -> Info
    {
        Info  {
            name: "LadderFilter".to_string(),
            unique_id: 9263,
            inputs: 1,
            outputs: 1,
            category: Category::Effect,
            parameters: 4,
            ..Default::default()
        }
    }
    fn get_parameter(&self, index: i32) -> f32 {
    match index {
        0 => self.cutoff,
        1 => self.res,
        2 => (self.poles) as f32 + 1.,
        3 => self.drive,
        _ => 0.0,
        }
    }
    fn set_parameter(&mut self, index: i32, value: f32) {
        match index {
            0 => self.set_cutoff(value),
            1 => self.res = value * 4.,
            2 => self.poles = ((value * 3.).round()) as usize,
            3 => self.drive = value * 5.,
            _ => (),
        }
    }

    fn get_parameter_name(&self, index: i32) -> String {
        match index {
            0 => "cutoff".to_string(),
            1 => "resonance".to_string(),
            2 => "filter order".to_string(),
            3 => "drive".to_string(),
            _ => "".to_string(),
        }
    }
    fn get_parameter_label(&self, index: i32) -> String {
        match index {
            0 => "Hz".to_string(),
            1 => "%".to_string(),
            2 => "poles".to_string(),
            3 => "%".to_string(),
            _ => "".to_string(),
        }
    }
    fn process(&mut self, buffer: &mut AudioBuffer<f32>) {
        for (input_buffer, output_buffer) in buffer.zip() {
            for (input_sample, output_sample) in input_buffer.iter().zip(output_buffer) {
                self.tick_pivotal(*input_sample);
                //the poles parameter chooses which filter stage we take our output from.
                *output_sample = self.vout[self.poles];
            }
        }
    }
}
plugin_main!(LadderFilter);
<|endoftext|>


<commit_before>use crate::BeaconChain;
use db::{
    stores::{BeaconBlockAtSlotError, BeaconBlockStore},
    ClientDB, DBError,
};
use slot_clock::{SlotClock, TestingSlotClockError};
use std::collections::HashSet;
use std::sync::Arc;
use types::{
    readers::{BeaconBlockReader, BeaconStateReader},
    validator_registry::get_active_validator_indices,
    Hash256, Slot,
};

#[derive(Debug, PartialEq)]
pub enum Error {
    DBError(String),
    MissingBeaconState(Hash256),
    InvalidBeaconState(Hash256),
    MissingBeaconBlock(Hash256),
    InvalidBeaconBlock(Hash256),
}

impl<T, U> BeaconChain<T, U>
where
    T: ClientDB,
    U: SlotClock,
    Error: From<<U as SlotClock>::Error>,
{
    /// Run the fork-choice rule on the current chain, updating the canonical head, if required.
    pub fn fork_choice(&self) -> Result<(), Error> {
        let present_head = &self.finalized_head().beacon_block_root;

        let new_head = self.slow_lmd_ghost(&self.finalized_head().beacon_block_root)?;

        if new_head != *present_head {
            let block = self
                .block_store
                .get_deserialized(&new_head)?
                .ok_or_else(|| Error::MissingBeaconBlock(new_head))?;
            let block_root = block.canonical_root();

            let state = self
                .state_store
                .get_deserialized(&block.state_root)?
                .ok_or_else(|| Error::MissingBeaconState(block.state_root))?;
            let state_root = state.canonical_root();

            self.update_canonical_head(block, block_root, state, state_root);
        }

        Ok(())
    }

    /// A very inefficient implementation of LMD ghost.
    pub fn slow_lmd_ghost(&self, start_hash: &Hash256) -> Result<Hash256, Error> {
        let start = self
            .block_store
            .get_reader(&start_hash)?
            .ok_or(Error::MissingBeaconBlock(*start_hash))?;

        let start_state_root = start.state_root();

        let state = self
            .state_store
            .get_reader(&start_state_root)?
            .ok_or(Error::MissingBeaconState(start_state_root))?
            .into_beacon_state()
            .ok_or(Error::InvalidBeaconState(start_state_root))?;

        let active_validator_indices = get_active_validator_indices(
            &state.validator_registry,
            start.slot().epoch(self.spec.epoch_length),
        );

        let mut attestation_targets = Vec::with_capacity(active_validator_indices.len());
        for i in active_validator_indices {
            if let Some(target) = self.get_latest_attestation_target(i as u64) {
                attestation_targets.push(target);
            }
        }

        let mut head_hash = Hash256::zero();
        let mut head_vote_count = 0;

        loop {
            let child_hashes_and_slots = get_child_hashes_and_slots(
                &self.block_store,
                &head_hash,
                &self.block_graph.leaves(),
            )?;

            if child_hashes_and_slots.len() == 0 {
                break;
            }

            for (child_hash, child_slot) in child_hashes_and_slots {
                let vote_count = get_vote_count(
                    &self.block_store,
                    &attestation_targets[..],
                    &child_hash,
                    child_slot,
                )?;

                if vote_count > head_vote_count {
                    head_hash = child_hash;
                    head_vote_count = vote_count;
                }
            }
        }

        Ok(head_hash)
    }
}

/// Get the total number of votes for some given block root.
///
/// The vote count is incrememented each time an attestation target votes for a block root.
fn get_vote_count<T: ClientDB>(
    block_store: &Arc<BeaconBlockStore<T>>,
    attestation_targets: &[Hash256],
    block_root: &Hash256,
    slot: Slot,
) -> Result<u64, Error> {
    let mut count = 0;
    for target in attestation_targets {
        let (root_at_slot, _) = block_store
            .block_at_slot(&block_root, slot)?
            .ok_or(Error::MissingBeaconBlock(*block_root))?;
        if root_at_slot == *target {
            count += 1;
        }
    }
    Ok(count)
}

/// Starting from some `leaf_hashes`, recurse back down each branch until the `root_hash`, adding
/// each `block_root` and `slot` to a HashSet.
fn get_child_hashes_and_slots<T: ClientDB>(
    block_store: &Arc<BeaconBlockStore<T>>,
    root_hash: &Hash256,
    leaf_hashes: &HashSet<Hash256>,
) -> Result<HashSet<(Hash256, Slot)>, Error> {
    let mut hash_set = HashSet::new();

    for leaf_hash in leaf_hashes {
        let mut current_hash = *leaf_hash;

        loop {
            if let Some(block_reader) = block_store.get_reader(&current_hash)? {
                let parent_root = block_reader.parent_root();

                let new_hash = hash_set.insert((current_hash, block_reader.slot()));

                // If the hash just added was already in the set, break the loop.
                //
                // In such a case, the present branch has merged with a branch that is already in
                // the set.
                if !new_hash {
                    break;
                }

                // The branch is exhausted if the parent of this block is the root_hash.
                if parent_root == *root_hash {
                    break;
                }

                current_hash = parent_root.clone();
            } else {
                return Err(Error::MissingBeaconBlock(current_hash));
            }
        }
    }

    Ok(hash_set)
}

impl From<DBError> for Error {
    fn from(e: DBError) -> Error {
        Error::DBError(e.message)
    }
}

impl From<BeaconBlockAtSlotError> for Error {
    fn from(e: BeaconBlockAtSlotError) -> Error {
        match e {
            BeaconBlockAtSlotError::UnknownBeaconBlock(h) => Error::MissingBeaconBlock(h),
            BeaconBlockAtSlotError::InvalidBeaconBlock(h) => Error::InvalidBeaconBlock(h),
            BeaconBlockAtSlotError::DBError(msg) => Error::DBError(msg),
        }
    }
}

impl From<TestingSlotClockError> for Error {
    fn from(_: TestingSlotClockError) -> Error {
        unreachable!(); // Testing clock never throws an error.
    }
}
<commit_msg>Fix clippy lints in lmd_ghost<commit_after>use crate::BeaconChain;
use db::{
    stores::{BeaconBlockAtSlotError, BeaconBlockStore},
    ClientDB, DBError,
};
use slot_clock::{SlotClock, TestingSlotClockError};
use std::collections::HashSet;
use std::sync::Arc;
use types::{
    readers::{BeaconBlockReader, BeaconStateReader},
    validator_registry::get_active_validator_indices,
    Hash256, Slot,
};

#[derive(Debug, PartialEq)]
pub enum Error {
    DBError(String),
    MissingBeaconState(Hash256),
    InvalidBeaconState(Hash256),
    MissingBeaconBlock(Hash256),
    InvalidBeaconBlock(Hash256),
}

impl<T, U> BeaconChain<T, U>
where
    T: ClientDB,
    U: SlotClock,
    Error: From<<U as SlotClock>::Error>,
{
    /// Run the fork-choice rule on the current chain, updating the canonical head, if required.
    pub fn fork_choice(&self) -> Result<(), Error> {
        let present_head = &self.finalized_head().beacon_block_root;

        let new_head = self.slow_lmd_ghost(&self.finalized_head().beacon_block_root)?;

        if new_head != *present_head {
            let block = self
                .block_store
                .get_deserialized(&new_head)?
                .ok_or_else(|| Error::MissingBeaconBlock(new_head))?;
            let block_root = block.canonical_root();

            let state = self
                .state_store
                .get_deserialized(&block.state_root)?
                .ok_or_else(|| Error::MissingBeaconState(block.state_root))?;
            let state_root = state.canonical_root();

            self.update_canonical_head(block, block_root, state, state_root);
        }

        Ok(())
    }

    /// A very inefficient implementation of LMD ghost.
    pub fn slow_lmd_ghost(&self, start_hash: &Hash256) -> Result<Hash256, Error> {
        let start = self
            .block_store
            .get_reader(&start_hash)?
            .ok_or_else(|| Error::MissingBeaconBlock(*start_hash))?;

        let start_state_root = start.state_root();

        let state = self
            .state_store
            .get_reader(&start_state_root)?
            .ok_or_else(|| Error::MissingBeaconState(start_state_root))?
            .into_beacon_state()
            .ok_or_else(|| Error::InvalidBeaconState(start_state_root))?;

        let active_validator_indices = get_active_validator_indices(
            &state.validator_registry,
            start.slot().epoch(self.spec.epoch_length),
        );

        let mut attestation_targets = Vec::with_capacity(active_validator_indices.len());
        for i in active_validator_indices {
            if let Some(target) = self.get_latest_attestation_target(i as u64) {
                attestation_targets.push(target);
            }
        }

        let mut head_hash = Hash256::zero();
        let mut head_vote_count = 0;

        loop {
            let child_hashes_and_slots = get_child_hashes_and_slots(
                &self.block_store,
                &head_hash,
                &self.block_graph.leaves(),
            )?;

            if child_hashes_and_slots.is_empty() {
                break;
            }

            for (child_hash, child_slot) in child_hashes_and_slots {
                let vote_count = get_vote_count(
                    &self.block_store,
                    &attestation_targets[..],
                    &child_hash,
                    child_slot,
                )?;

                if vote_count > head_vote_count {
                    head_hash = child_hash;
                    head_vote_count = vote_count;
                }
            }
        }

        Ok(head_hash)
    }
}

/// Get the total number of votes for some given block root.
///
/// The vote count is incrememented each time an attestation target votes for a block root.
fn get_vote_count<T: ClientDB>(
    block_store: &Arc<BeaconBlockStore<T>>,
    attestation_targets: &[Hash256],
    block_root: &Hash256,
    slot: Slot,
) -> Result<u64, Error> {
    let mut count = 0;
    for target in attestation_targets {
        let (root_at_slot, _) = block_store
            .block_at_slot(&block_root, slot)?
            .ok_or_else(|| Error::MissingBeaconBlock(*block_root))?;
        if root_at_slot == *target {
            count += 1;
        }
    }
    Ok(count)
}

/// Starting from some `leaf_hashes`, recurse back down each branch until the `root_hash`, adding
/// each `block_root` and `slot` to a HashSet.
fn get_child_hashes_and_slots<T: ClientDB>(
    block_store: &Arc<BeaconBlockStore<T>>,
    root_hash: &Hash256,
    leaf_hashes: &HashSet<Hash256>,
) -> Result<HashSet<(Hash256, Slot)>, Error> {
    let mut hash_set = HashSet::new();

    for leaf_hash in leaf_hashes {
        let mut current_hash = *leaf_hash;

        loop {
            if let Some(block_reader) = block_store.get_reader(&current_hash)? {
                let parent_root = block_reader.parent_root();

                let new_hash = hash_set.insert((current_hash, block_reader.slot()));

                // If the hash just added was already in the set, break the loop.
                //
                // In such a case, the present branch has merged with a branch that is already in
                // the set.
                if !new_hash {
                    break;
                }

                // The branch is exhausted if the parent of this block is the root_hash.
                if parent_root == *root_hash {
                    break;
                }

                current_hash = parent_root;
            } else {
                return Err(Error::MissingBeaconBlock(current_hash));
            }
        }
    }

    Ok(hash_set)
}

impl From<DBError> for Error {
    fn from(e: DBError) -> Error {
        Error::DBError(e.message)
    }
}

impl From<BeaconBlockAtSlotError> for Error {
    fn from(e: BeaconBlockAtSlotError) -> Error {
        match e {
            BeaconBlockAtSlotError::UnknownBeaconBlock(h) => Error::MissingBeaconBlock(h),
            BeaconBlockAtSlotError::InvalidBeaconBlock(h) => Error::InvalidBeaconBlock(h),
            BeaconBlockAtSlotError::DBError(msg) => Error::DBError(msg),
        }
    }
}

impl From<TestingSlotClockError> for Error {
    fn from(_: TestingSlotClockError) -> Error {
        unreachable!(); // Testing clock never throws an error.
    }
}
<|endoftext|>


<commit_before>use std::cell::Cell;
use std::marker::PhantomData;

use super::{BaseIndex, BaseIndexIter, Snapshot, Fork, StorageValue};

#[derive(Debug)]
pub struct ListIndex<T, V> {
    base: BaseIndex<T>,
    length: Cell<Option<u64>>,
    _v: PhantomData<V>,
}

#[derive(Debug)]
pub struct ListIndexIter<'a, V> {
    base_iter: BaseIndexIter<'a, u64, V>,
}

impl<T, V> ListIndex<T, V> {
    pub fn new(prefix: Vec<u8>, base: T) -> Self {
        ListIndex {
            base: BaseIndex::new(prefix, base),
            length: Cell::new(None),
            _v: PhantomData,
        }
    }
}

impl<T, V> ListIndex<T, V>
    where T: AsRef<Snapshot>,
          V: StorageValue
{
    pub fn get(&self, index: u64) -> Option<V> {
        self.base.get(&index)
    }

    pub fn last(&self) -> Option<V> {
        match self.len() {
            0 => None,
            l => self.get(l - 1),
        }
    }

    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    pub fn len(&self) -> u64 {
        if let Some(len) = self.length.get() {
            return len;
        }
        let len = self.base.get(&()).unwrap_or(0);
        self.length.set(Some(len));
        len
    }

    pub fn iter(&self) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&(), &0u64) }
    }

    pub fn iter_from(&self, from: u64) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&(), &from) }
    }
}

impl<'a, V> ListIndex<&'a mut Fork, V>
    where V: StorageValue
{
    fn set_len(&mut self, len: u64) {
        self.base.put(&(), len);
        self.length.set(Some(len));
    }

    pub fn push(&mut self, value: V) {
        let len = self.len();
        self.base.put(&len, value);
        self.set_len(len + 1)
    }

    pub fn pop(&mut self) -> Option<V> {
        // TODO: shoud we get and return dropped value?
        match self.len() {
            0 => None,
            l => {
                let v = self.base.get(&(l - 1));
                self.base.remove(&(l - 1));
                self.set_len(l - 1);
                v
            }
        }
    }

    pub fn extend<I>(&mut self, iter: I)
        where I: IntoIterator<Item = V>
    {
        let mut len = self.len();
        for value in iter {
            self.base.put(&len, value);
            len += 1;
        }
        self.base.put(&(), len);
        self.set_len(len);
    }

    pub fn truncate(&mut self, len: u64) {
        // TODO: optimize this
        while self.len() > len {
            self.pop();
        }
    }

    pub fn set(&mut self, index: u64, value: V) {
        if index >= self.len() {
            panic!("index out of bounds: \
                    the len is {} but the index is {}",
                   self.len(),
                   index);
        }
        self.base.put(&index, value)
    }

    pub fn clear(&mut self) {
        self.length.set(Some(0));
        self.base.clear()
    }
}

impl<'a, T, V> ::std::iter::IntoIterator for &'a ListIndex<T, V>
    where T: AsRef<Snapshot>,
          V: StorageValue
{
    type Item = V;
    type IntoIter = ListIndexIter<'a, V>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, V> Iterator for ListIndexIter<'a, V>
    where V: StorageValue
{
    type Item = V;

    fn next(&mut self) -> Option<Self::Item> {
        self.base_iter.next().map(|(.., v)| v)
    }
}

#[cfg(test)]
mod tests {
    use super::ListIndex;
    use super::super::{MemoryDB, Database};

    #[test]
    fn test_list_index_methods() {
        let mut fork = MemoryDB::new().fork();
        let mut list_index = ListIndex::new(vec![255], &mut fork);

        assert!(list_index.is_empty());
        assert_eq!(0, list_index.len());
        assert!(list_index.last().is_none());

        let extended_by = vec![45, 3422, 234];
        list_index.extend(extended_by);
        assert!(!list_index.is_empty());
        assert_eq!(Some(45), list_index.get(0));
        assert_eq!(Some(3422), list_index.get(1));
        assert_eq!(Some(234), list_index.get(2));
        assert_eq!(3, list_index.len());

        list_index.set(2, 777);
        assert_eq!(Some(777), list_index.get(2));
        assert_eq!(Some(777), list_index.last());
        assert_eq!(3, list_index.len());

        let mut extended_by_again = vec![666, 999];
        for el in &extended_by_again {
            list_index.push(*el);
        }
        assert_eq!(Some(666), list_index.get(3));
        assert_eq!(Some(999), list_index.get(4));
        assert_eq!(5, list_index.len());
        extended_by_again[1] = 1001;
        list_index.extend(extended_by_again);
        assert_eq!(7, list_index.len());
        assert_eq!(Some(1001), list_index.last());

        assert_eq!(Some(1001), list_index.pop());
        assert_eq!(6, list_index.len());

        list_index.truncate(3);

        assert_eq!(3, list_index.len());
        assert_eq!(Some(777), list_index.last());
    }

    #[test]
    fn test_list_index_iter() {
        let mut fork = MemoryDB::new().fork();
        let mut list_index = ListIndex::new(vec![255], &mut fork);

        list_index.extend(vec![1u8, 2, 3]);

        assert_eq!(list_index.iter().collect::<Vec<u8>>(), vec![1, 2, 3]);

        assert_eq!(list_index.iter_from(0).collect::<Vec<u8>>(), vec![1, 2, 3]);
        assert_eq!(list_index.iter_from(1).collect::<Vec<u8>>(), vec![2, 3]);
        assert_eq!(list_index.iter_from(3).collect::<Vec<u8>>(),
                   Vec::<u8>::new());
    }
}
<commit_msg>Docs for ListIndex<commit_after>//! An implementation of array list of items.
use std::cell::Cell;
use std::marker::PhantomData;

use super::{BaseIndex, BaseIndexIter, Snapshot, Fork, StorageValue};

/// A list of items that implemets `StorageValue` trait.
///
/// `ListIndex` implements an array list, storing the element as values and using `u64` as an index.
/// `ListIndex` requires that the elements implement the [`StorageValue`] trait.
/// [`StorageValue`]: ../trait.StorageValue.html
#[derive(Debug)]
pub struct ListIndex<T, V> {
    base: BaseIndex<T>,
    length: Cell<Option<u64>>,
    _v: PhantomData<V>,
}

/// An iterator over the items of a `ListIndex`.
///
/// This struct is created by the [`iter`] or
/// [`iter_from`] methods on [`ListIndex`]. See its documentation for more.
///
/// [`iter`]: struct.ListIndex.html#method.iter
/// [`iter_from`]: struct.ListIndex.html#method.iter_from
/// [`ListIndex`]: struct.ListIndex.html
#[derive(Debug)]
pub struct ListIndexIter<'a, V> {
    base_iter: BaseIndexIter<'a, u64, V>,
}

impl<T, V> ListIndex<T, V> {
    /// Creates a new index representation based on the common prefix of its keys and storage view.
    ///
    /// Storage view can be specified as [`&Snapshot`] or [`&mut Fork`]. In the first case only
    /// immutable methods are available. In the second case both immutable and mutable methods are
    /// available.
    /// [`&Snapshot`]: ../trait.Snapshot.html
    /// [`&mut Fork`]: ../struct.Fork.html
    pub fn new(prefix: Vec<u8>, base: T) -> Self {
        ListIndex {
            base: BaseIndex::new(prefix, base),
            length: Cell::new(None),
            _v: PhantomData,
        }
    }
}

impl<T, V> ListIndex<T, V>
    where T: AsRef<Snapshot>,
          V: StorageValue
{
    /// Returns an element at that position or `None` if out of bounds.
    pub fn get(&self, index: u64) -> Option<V> {
        self.base.get(&index)
    }

    /// Returns the last element of the list, or `None` if it is empty.
    pub fn last(&self) -> Option<V> {
        match self.len() {
            0 => None,
            l => self.get(l - 1),
        }
    }

    /// Returns `true` if the list contains no elements.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Returns the number of elements in the list.
    pub fn len(&self) -> u64 {
        if let Some(len) = self.length.get() {
            return len;
        }
        let len = self.base.get(&()).unwrap_or(0);
        self.length.set(Some(len));
        len
    }

    /// Returns an iterator over the list. The iterator element type is T.
    pub fn iter(&self) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&(), &0u64) }
    }

    /// Returns an iterator over the list starting from the specified position. The iterator
    /// element type is T.
    pub fn iter_from(&self, from: u64) -> ListIndexIter<V> {
        ListIndexIter { base_iter: self.base.iter_from(&(), &from) }
    }
}

impl<'a, V> ListIndex<&'a mut Fork, V>
    where V: StorageValue
{
    fn set_len(&mut self, len: u64) {
        self.base.put(&(), len);
        self.length.set(Some(len));
    }

    /// Appends an element to the back of the list.
    pub fn push(&mut self, value: V) {
        let len = self.len();
        self.base.put(&len, value);
        self.set_len(len + 1)
    }

    /// Removes the last element from the list and returns it, or None if it is empty.
    pub fn pop(&mut self) -> Option<V> {
        // TODO: shoud we get and return dropped value?
        match self.len() {
            0 => None,
            l => {
                let v = self.base.get(&(l - 1));
                self.base.remove(&(l - 1));
                self.set_len(l - 1);
                v
            }
        }
    }

    /// Extends the list with the contents of an iterator.
    pub fn extend<I>(&mut self, iter: I)
        where I: IntoIterator<Item = V>
    {
        let mut len = self.len();
        for value in iter {
            self.base.put(&len, value);
            len += 1;
        }
        self.base.put(&(), len);
        self.set_len(len);
    }

    /// Shortens the list, keeping the first `len` elements and dropping the rest.
    ///
    /// If `len` is greater than the list's current length, this has no effect.
    pub fn truncate(&mut self, len: u64) {
        // TODO: optimize this
        while self.len() > len {
            self.pop();
        }
    }

    /// Changes a value at specified position.
    ///
    /// # Panics
    /// Panics if `index` is equal or greater than the list's current length.
    pub fn set(&mut self, index: u64, value: V) {
        if index >= self.len() {
            panic!("index out of bounds: \
                    the len is {} but the index is {}",
                   self.len(),
                   index);
        }
        self.base.put(&index, value)
    }

    /// Clears the list, removing all values.
    ///
    /// # Notes
    /// Currently this method is not optimized to delete large set of data. During the execution of
    /// this method the amount of allocated memory is linearly dependent on the number of elements
    /// in the index.
    pub fn clear(&mut self) {
        self.length.set(Some(0));
        self.base.clear()
    }
}

impl<'a, T, V> ::std::iter::IntoIterator for &'a ListIndex<T, V>
    where T: AsRef<Snapshot>,
          V: StorageValue
{
    type Item = V;
    type IntoIter = ListIndexIter<'a, V>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a, V> Iterator for ListIndexIter<'a, V>
    where V: StorageValue
{
    type Item = V;

    fn next(&mut self) -> Option<Self::Item> {
        self.base_iter.next().map(|(.., v)| v)
    }
}

#[cfg(test)]
mod tests {
    use super::ListIndex;
    use super::super::{MemoryDB, Database};

    #[test]
    fn test_list_index_methods() {
        let mut fork = MemoryDB::new().fork();
        let mut list_index = ListIndex::new(vec![255], &mut fork);

        assert!(list_index.is_empty());
        assert_eq!(0, list_index.len());
        assert!(list_index.last().is_none());

        let extended_by = vec![45, 3422, 234];
        list_index.extend(extended_by);
        assert!(!list_index.is_empty());
        assert_eq!(Some(45), list_index.get(0));
        assert_eq!(Some(3422), list_index.get(1));
        assert_eq!(Some(234), list_index.get(2));
        assert_eq!(3, list_index.len());

        list_index.set(2, 777);
        assert_eq!(Some(777), list_index.get(2));
        assert_eq!(Some(777), list_index.last());
        assert_eq!(3, list_index.len());

        let mut extended_by_again = vec![666, 999];
        for el in &extended_by_again {
            list_index.push(*el);
        }
        assert_eq!(Some(666), list_index.get(3));
        assert_eq!(Some(999), list_index.get(4));
        assert_eq!(5, list_index.len());
        extended_by_again[1] = 1001;
        list_index.extend(extended_by_again);
        assert_eq!(7, list_index.len());
        assert_eq!(Some(1001), list_index.last());

        assert_eq!(Some(1001), list_index.pop());
        assert_eq!(6, list_index.len());

        list_index.truncate(3);

        assert_eq!(3, list_index.len());
        assert_eq!(Some(777), list_index.last());
    }

    #[test]
    fn test_list_index_iter() {
        let mut fork = MemoryDB::new().fork();
        let mut list_index = ListIndex::new(vec![255], &mut fork);

        list_index.extend(vec![1u8, 2, 3]);

        assert_eq!(list_index.iter().collect::<Vec<u8>>(), vec![1, 2, 3]);

        assert_eq!(list_index.iter_from(0).collect::<Vec<u8>>(), vec![1, 2, 3]);
        assert_eq!(list_index.iter_from(1).collect::<Vec<u8>>(), vec![2, 3]);
        assert_eq!(list_index.iter_from(3).collect::<Vec<u8>>(),
                   Vec::<u8>::new());
    }
}
<|endoftext|>


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

#![feature(rustc_attrs)]

struct Foo {
    x: u8
}

impl Foo {
    // Changing the item `new`...
    #[rustc_if_this_changed(HirBody)]
    fn new() -> Foo {
        Foo { x: 0 }
    }

    // ...should not cause us to recompute the tables for `with`!
    #[rustc_then_this_would_need(Tables)] //~ ERROR no path
    fn with(x: u8) -> Foo {
        Foo { x: x }
    }
}

fn main() {
    let f = Foo::new();
    let g = Foo::with(22);
    assert_eq!(f.x, g.x - 22);
}
<commit_msg>fix the test case by supplying proper options<commit_after>// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Test that the `Tables` nodes for impl items are independent from
// one another.

// compile-flags: -Z query-dep-graph

#![feature(rustc_attrs)]

struct Foo {
    x: u8
}

impl Foo {
    // Changing the item `new`...
    #[rustc_if_this_changed(HirBody)]
    fn new() -> Foo {
        Foo { x: 0 }
    }

    // ...should not cause us to recompute the tables for `with`!
    #[rustc_then_this_would_need(Tables)] //~ ERROR no path
    fn with(x: u8) -> Foo {
        Foo { x: x }
    }
}

fn main() {
    let f = Foo::new();
    let g = Foo::with(22);
    assert_eq!(f.x, g.x - 22);
}
<|endoftext|>


<commit_before>
#![feature(globs)]

///! Use SPACE to play the sound.

extern crate graphics;
extern crate piston;

use piston::{
    keyboard,
    AssetStore,
    GameIterator,
    GameIteratorSettings,
    GameWindow,
    GameWindowSDL2,
    GameWindowSettings,
    Update,
    KeyPress,
    AudioBackEnd,
    AudioSDL2,
    SoundSDL2,
    MusicSDL2,
};

#[start]
fn start(argc: int, argv: **u8) -> int {
    // Run gui on the main thread.
    native::start(argc, argv, main)
}

fn main() {
    let mut window: GameWindowSDL2 = GameWindow::new(
        GameWindowSettings {
            title: "Audio".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            background_color: [1.0, 1.0, 1.0, 1.0],
        }
    );

    let asset_store = AssetStore::from_folder("assets");

    let game_iter_settings = GameIteratorSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    let mut game_iter = GameIterator::new(&mut window, &game_iter_settings);

    let audio = AudioSDL2::new();

    let sound = asset_store.path("beeep.ogg").unwrap();
    let sound = SoundSDL2::from_path(&sound).unwrap();

    let music = asset_store.path("background-music.ogg").unwrap();
    let music = MusicSDL2::from_path(&music).unwrap();

    let mut play_sound = false;
    let mut is_playing_background_music = false;

    loop {
        match game_iter.next() {
            None => { break },
            Some(e) => match e {
                Interactive(KeyPress(args)) => {
                    if args.key == keyboard::Space {
                        play_sound = true;
                    }
                },
                Update(_) => {
                    if play_sound {
                        audio.play_sound(&sound);
                        play_sound = false;
                    }

                    if !is_playing_background_music {
                        audio.play_music(&music);
                        is_playing_background_music = true;
                    }
                },
                _ => {}
            },
        }
    }
}

<commit_msg>Fixed audio_iter example<commit_after>
#![feature(globs)]

///! Use SPACE to play the sound.

extern crate graphics;
extern crate piston;

use piston::{
    keyboard,
    AssetStore,
    GameIterator,
    GameIteratorSettings,
    GameWindow,
    GameWindowSDL2,
    GameWindowSettings,
    Update,
    KeyPress,
    AudioBackEnd,
    AudioSDL2,
    SoundSDL2,
    MusicSDL2,
};

#[start]
fn start(argc: int, argv: **u8) -> int {
    // Run gui on the main thread.
    native::start(argc, argv, main)
}

fn main() {
    let mut window: GameWindowSDL2 = GameWindow::new(
        GameWindowSettings {
            title: "Audio".to_string(),
            size: [300, 300],
            fullscreen: false,
            exit_on_esc: true,
            background_color: [1.0, 1.0, 1.0, 1.0],
        }
    );

    let asset_store = AssetStore::from_folder("assets");

    let game_iter_settings = GameIteratorSettings {
            updates_per_second: 120,
            max_frames_per_second: 60,
        };
    let mut game_iter = GameIterator::new(&mut window, &game_iter_settings);

    let audio = AudioSDL2::new();

    let sound = asset_store.path("beeep.ogg").unwrap();
    let sound = SoundSDL2::from_path(&sound).unwrap();

    let music = asset_store.path("background-music.ogg").unwrap();
    let music = MusicSDL2::from_path(&music).unwrap();

    let mut play_sound = false;
    let mut is_playing_background_music = false;

    loop {
        match game_iter.next() {
            None => { break },
            Some(e) => match e {
                KeyPress(args) => {
                    if args.key == keyboard::Space {
                        play_sound = true;
                    }
                },
                Update(_) => {
                    if play_sound {
                        audio.play_sound(&sound);
                        play_sound = false;
                    }

                    if !is_playing_background_music {
                        audio.play_music(&music);
                        is_playing_background_music = true;
                    }
                },
                _ => {}
            },
        }
    }
}

<|endoftext|>