<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 mut atoms: Vec<Atom> = vec!();
        for token in split_html_space_chars(&tokens).map(Atom::from_slice) {
            if !atoms.iter().any(|atom| *atom == token) {
                atoms.push(token);
            }
        }
        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>Auto merge of #6556 - frewsxcv:AttrValue-from_serialized_tokenlist, r=Ms2ger<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().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()
    }
}
<|endoftext|>


<commit_before>use unicode_width::UnicodeWidthStr;

use crate::buffer::Buffer;
use crate::layout::Rect;
use crate::style::Style;
use crate::symbols::line;
use crate::widgets::{Block, Widget};

/// A widget to display available tabs in a multiple panels context.
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, Borders, Tabs};
/// # use tui::style::{Style, Color};
/// # use tui::symbols::{DOT};
/// # fn main() {
/// Tabs::default()
///     .block(Block::default().title("Tabs").borders(Borders::ALL))
///     .titles(&["Tab1", "Tab2", "Tab3", "Tab4"])
///     .style(Style::default().fg(Color::White))
///     .highlight_style(Style::default().fg(Color::Yellow));
///     .divider(DOT);
/// # }
/// ```
pub struct Tabs<'a, T>
where
    T: AsRef<str> + 'a,
{
    /// A block to wrap this widget in if necessary
    block: Option<Block<'a>>,
    /// One title for each tab
    titles: &'a [T],
    /// The index of the selected tabs
    selected: usize,
    /// The style used to draw the text
    style: Style,
    /// The style used to display the selected item
    highlight_style: Style,
    /// Tab divider
    divider: &'a str,
}

impl<'a, T> Default for Tabs<'a, T>
where
    T: AsRef<str>,
{
    fn default() -> Tabs<'a, T> {
        Tabs {
            block: None,
            titles: &[],
            selected: 0,
            style: Default::default(),
            highlight_style: Default::default(),
            divider: line::VERTICAL,
        }
    }
}

impl<'a, T> Tabs<'a, T>
where
    T: AsRef<str>,
{
    pub fn block(mut self, block: Block<'a>) -> Tabs<'a, T> {
        self.block = Some(block);
        self
    }

    pub fn titles(mut self, titles: &'a [T]) -> Tabs<'a, T> {
        self.titles = titles;
        self
    }

    pub fn select(mut self, selected: usize) -> Tabs<'a, T> {
        self.selected = selected;
        self
    }

    pub fn style(mut self, style: Style) -> Tabs<'a, T> {
        self.style = style;
        self
    }

    pub fn highlight_style(mut self, style: Style) -> Tabs<'a, T> {
        self.highlight_style = style;
        self
    }

    pub fn divider(mut self, divider: &'a str) -> Tabs<'a, T> {
        self.divider = divider;
        self
    }
}

impl<'a, T> Widget for Tabs<'a, T>
where
    T: AsRef<str>,
{
    fn draw(&mut self, area: Rect, buf: &mut Buffer) {
        let tabs_area = match self.block {
            Some(ref mut b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => area,
        };

        if tabs_area.height < 1 {
            return;
        }

        self.background(&tabs_area, buf, self.style.bg);

        let mut x = tabs_area.left();
        let divider_width = self.divider.chars().count() as u16;
        for (title, style) in self.titles.iter().enumerate().map(|(i, t)| {
            if i == self.selected {
                (t, self.highlight_style)
            } else {
                (t, self.style)
            }
        }) {
            x += 1;
            if x > tabs_area.right() {
                break;
            } else {
                buf.set_string(x, tabs_area.top(), title.as_ref(), style);
                x += title.as_ref().width() as u16 + 1;
                if x >= tabs_area.right() {
                    break;
                } else {
                    buf.get_mut(x, tabs_area.top())
                        .set_symbol(self.divider)
                        .set_fg(self.style.fg)
                        .set_bg(self.style.bg);
                    x += divider_width;
                }
            }
        }
    }
}
<commit_msg>Don't show divider after last tab<commit_after>use unicode_width::UnicodeWidthStr;

use crate::buffer::Buffer;
use crate::layout::Rect;
use crate::style::Style;
use crate::symbols::line;
use crate::widgets::{Block, Widget};

/// A widget to display available tabs in a multiple panels context.
///
/// # Examples
///
/// ```
/// # use tui::widgets::{Block, Borders, Tabs};
/// # use tui::style::{Style, Color};
/// # use tui::symbols::{DOT};
/// # fn main() {
/// Tabs::default()
///     .block(Block::default().title("Tabs").borders(Borders::ALL))
///     .titles(&["Tab1", "Tab2", "Tab3", "Tab4"])
///     .style(Style::default().fg(Color::White))
///     .highlight_style(Style::default().fg(Color::Yellow));
///     .divider(DOT);
/// # }
/// ```
pub struct Tabs<'a, T>
where
    T: AsRef<str> + 'a,
{
    /// A block to wrap this widget in if necessary
    block: Option<Block<'a>>,
    /// One title for each tab
    titles: &'a [T],
    /// The index of the selected tabs
    selected: usize,
    /// The style used to draw the text
    style: Style,
    /// The style used to display the selected item
    highlight_style: Style,
    /// Tab divider
    divider: &'a str,
}

impl<'a, T> Default for Tabs<'a, T>
where
    T: AsRef<str>,
{
    fn default() -> Tabs<'a, T> {
        Tabs {
            block: None,
            titles: &[],
            selected: 0,
            style: Default::default(),
            highlight_style: Default::default(),
            divider: line::VERTICAL,
        }
    }
}

impl<'a, T> Tabs<'a, T>
where
    T: AsRef<str>,
{
    pub fn block(mut self, block: Block<'a>) -> Tabs<'a, T> {
        self.block = Some(block);
        self
    }

    pub fn titles(mut self, titles: &'a [T]) -> Tabs<'a, T> {
        self.titles = titles;
        self
    }

    pub fn select(mut self, selected: usize) -> Tabs<'a, T> {
        self.selected = selected;
        self
    }

    pub fn style(mut self, style: Style) -> Tabs<'a, T> {
        self.style = style;
        self
    }

    pub fn highlight_style(mut self, style: Style) -> Tabs<'a, T> {
        self.highlight_style = style;
        self
    }

    pub fn divider(mut self, divider: &'a str) -> Tabs<'a, T> {
        self.divider = divider;
        self
    }
}

impl<'a, T> Widget for Tabs<'a, T>
where
    T: AsRef<str>,
{
    fn draw(&mut self, area: Rect, buf: &mut Buffer) {
        let tabs_area = match self.block {
            Some(ref mut b) => {
                b.draw(area, buf);
                b.inner(area)
            }
            None => area,
        };

        if tabs_area.height < 1 {
            return;
        }

        self.background(&tabs_area, buf, self.style.bg);

        let mut x = tabs_area.left();
        let titles_length = self.titles.len();
        let divider_width = self.divider.chars().count() as u16;
        for (title, style, last_title) in self.titles.iter().enumerate().map(|(i, t)| {
            let lt = i + 1 == titles_length;
            if i == self.selected {
                (t, self.highlight_style, lt)
            } else {
                (t, self.style, lt)
            }
        }) {
            x += 1;
            if x > tabs_area.right() {
                break;
            } else {
                buf.set_string(x, tabs_area.top(), title.as_ref(), style);
                x += title.as_ref().width() as u16 + 1;
                if x >= tabs_area.right() || last_title {
                    break;
                } else {
                    buf.get_mut(x, tabs_area.top())
                        .set_symbol(self.divider)
                        .set_fg(self.style.fg)
                        .set_bg(self.style.bg);
                    x += divider_width;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! A widget that emits a signal when clicked on

use gtk::{mod, ffi, traits, cast};

pub struct TreeViewColumn {
    pointer: *mut ffi::C_GtkTreeViewColumn
}

impl TreeViewColumn {
    pub fn new() -> Option<TreeViewColumn> {
        let tmp_pointer = unsafe { ffi::gtk_tree_view_column_new() };
        check_pointer!(tmp_pointer, TreeViewColumn, G_OBJECT_FROM_TREE_VIEW_COLUMN)
    }

    pub fn clear(&mut self) {
        unsafe {
            ffi::gtk_tree_view_column_clear(self.pointer)
        }
    }

    pub fn set_spacing(&mut self, spacing: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_spacing(self.pointer, spacing)
        }
    }

    pub fn get_spacing(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_spacing(self.pointer)
        }
    }

    pub fn set_visible(&mut self, visible: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_visible(self.pointer, ffi::to_gboolean(visible))
        }
    }

    pub fn get_visible(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_visible(self.pointer))
        }
    }

    pub fn set_resizable(&mut self, resizable: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_resizable(self.pointer, ffi::to_gboolean(resizable))
        }
    }

    pub fn get_resizable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_resizable(self.pointer))
        }
    }

    pub fn set_sizing(&mut self, ty: gtk::TreeViewColumnSizing) {
        unsafe {
            ffi::gtk_tree_view_column_set_sizing(self.pointer, ty)
        }
    }

    pub fn get_sizing(&self) -> gtk::TreeViewColumnSizing {
        unsafe {
            ffi::gtk_tree_view_column_get_sizing(self.pointer)
        }
    }

    pub fn get_x_offset(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_x_offset(self.pointer)
        }
    }

    pub fn get_width(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_width(self.pointer)
        }
    }

    pub fn get_fixed_width(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_fixed_width(self.pointer)
        }
    }

    pub fn set_fixed_width(&self, fixed_width: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_fixed_width(self.pointer, fixed_width)
        }
    }

    pub fn set_min_width(&self, min_width: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_min_width(self.pointer, min_width)
        }
    }

    pub fn set_max_width(&self, max_width: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_max_width(self.pointer, max_width)
        }
    }

    pub fn get_min_width(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_min_width(self.pointer)
        }
    }

    pub fn get_max_width(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_max_width(self.pointer)
        }
    }

    pub fn clicked(&self) {
        unsafe {
            ffi::gtk_tree_view_column_clicked(self.pointer)
        }
    }

    pub fn set_title(&mut self, title: &str) {
        unsafe {
            title.with_c_str(|c_str| {
                ffi::gtk_tree_view_column_set_title(self.pointer, c_str)
            });
        }
    }

    pub fn get_title(&self) -> String {
        unsafe {
            ::std::string::raw::from_buf(ffi::gtk_tree_view_column_get_title(self.pointer) as *const u8)
        }
    }

    pub fn set_expand(&mut self, expand: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_expand(self.pointer, ffi::to_gboolean(expand))
        }
    }

    pub fn get_expand(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_expand(self.pointer))
        }
    }

    pub fn set_clickable(&mut self, clickable: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_clickable(self.pointer, ffi::to_gboolean(clickable))
        }
    }

    pub fn get_clickable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_clickable(self.pointer))
        }
    }

    pub fn set_widget(&mut self, widget: &traits::Widget) {
        unsafe {
            ffi::gtk_tree_view_column_set_widget(self.pointer, widget.get_widget())
        }
    }

    pub fn get_widget<T: traits::Widget>(&self) -> T {
        unsafe {
            ffi::FFIWidget::wrap(ffi::gtk_tree_view_column_get_widget(self.pointer))
        }
    }

    pub fn set_alignment(&mut self, x_align: f32) {
        unsafe {
            ffi::gtk_tree_view_column_set_alignment(self.pointer, x_align)
        }
    }

    pub fn get_alignment(&self) -> f32 {
        unsafe {
            ffi::gtk_tree_view_column_get_alignment(self.pointer)
        }
    }

    pub fn set_reorderable(&mut self, reorderable: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_reorderable(self.pointer, ffi::to_gboolean(reorderable))
        }
    }

    pub fn get_reorderable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_reorderable(self.pointer))
        }
    }

    pub fn get_sort_column_id(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_sort_column_id(self.pointer)
        }
    }

    pub fn set_sort_column_id(&mut self, sort_column_id: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_sort_column_id(self.pointer, sort_column_id)
        }
    }

    pub fn set_sort_indicator(&mut self, setting: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_sort_indicator(self.pointer, ffi::to_gboolean(setting))
        }
    }

    pub fn get_sort_indicator(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_sort_indicator(self.pointer))
        }
    }

    pub fn set_sort_order(&mut self, order: gtk::SortType) {
        unsafe {
            ffi::gtk_tree_view_column_set_sort_order(self.pointer, order)
        }
    }

    pub fn get_sort_order(&self) -> gtk::SortType {
        unsafe {
            ffi::gtk_tree_view_column_get_sort_order(self.pointer)
        }
    }

    pub fn column_cell_is_visible(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_cell_is_visible(self.pointer))
        }
    }

    pub fn queue_resize(&mut self) {
        unsafe {
            ffi::gtk_tree_view_column_queue_resize(self.pointer)
        }
    }

    pub fn get_tree_view(&self) -> gtk::TreeView {
        unsafe {
            ffi::FFIWidget::wrap(ffi::gtk_tree_view_column_get_tree_view(self.pointer))
        }
    }

    pub fn get_button<T: traits::Widget + traits::Button>(&self) -> T {
        unsafe {
            ffi::FFIWidget::wrap(ffi::gtk_tree_view_column_get_button(self.pointer))
        }
    }

    pub fn add_attribute<T: ffi::FFIWidget + traits::CellRenderer>(&self, cell: &T, attribute: &str, column: i32) {
        let attribute_c = attribute.to_c_str();
        unsafe { ffi::gtk_tree_view_column_add_attribute(self.pointer,
                                                         cast::GTK_CELL_RENDERER(cell.get_widget()),
                                                         attribute_c.as_ptr(),
                                                         column) }
    }

    pub fn clear_attributes<T: ffi::FFIWidget + traits::CellRenderer>(&self, cell: &T) {
        unsafe { ffi::gtk_tree_view_column_clear_attributes(self.pointer,
                                                            cast::GTK_CELL_RENDERER(cell.get_widget())) }
    }

    pub fn pack_start<T: ffi::FFIWidget + traits::CellRenderer>(&self, cell: &T, expand: bool) {
        unsafe { ffi::gtk_tree_view_column_pack_start(self.pointer,
                                                      cast::GTK_CELL_RENDERER(cell.get_widget()),
                                                      ffi::to_gboolean(expand)) }
    }

    pub fn pack_end<T: ffi::FFIWidget + traits::CellRenderer>(&self, cell: &T, expand: bool) {
        unsafe { ffi::gtk_tree_view_column_pack_end(self.pointer,
                                                    cast::GTK_CELL_RENDERER(cell.get_widget()),
                                                    ffi::to_gboolean(expand)) }
    }

    #[doc(hidden)]
    pub fn get_pointer(&self) -> *mut ffi::C_GtkTreeViewColumn {
        self.pointer
    }

    #[doc(hidden)]
    pub fn wrap_pointer(treeview_column: *mut ffi::C_GtkTreeViewColumn) -> TreeViewColumn {
        unsafe{
            ::glib::ffi::g_object_ref(treeview_column as *mut ::glib::ffi::C_GObject);
        }

        TreeViewColumn {
            pointer: treeview_column
        }
    }
}

impl Drop for TreeViewColumn {
    fn drop(&mut self) {
        unsafe {
            ::glib::ffi::g_object_unref(self.pointer as *mut ::glib::ffi::C_GObject);
        }
    }
}

impl Clone for TreeViewColumn {
    fn clone(&self) -> TreeViewColumn {
        let pointer = unsafe {
            ::glib::ffi::g_object_ref(self.pointer as *mut ::glib::ffi::C_GObject)
        };

        TreeViewColumn {
            pointer: pointer as *mut ffi::C_GtkTreeViewColumn
        }
    }
}
<commit_msg>implement FFIGObject and Clicked signal for TreeViewColumn<commit_after>// This file is part of rgtk.
//
// rgtk is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// rgtk is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with rgtk.  If not, see <http://www.gnu.org/licenses/>.

//! A widget that emits a signal when clicked on

use glib;
use gtk::{mod, ffi, traits, cast};

pub struct TreeViewColumn {
    pointer: *mut ffi::C_GtkTreeViewColumn
}

impl TreeViewColumn {
    pub fn new() -> Option<TreeViewColumn> {
        let tmp_pointer = unsafe { ffi::gtk_tree_view_column_new() };
        check_pointer!(tmp_pointer, TreeViewColumn, G_OBJECT_FROM_TREE_VIEW_COLUMN)
    }

    pub fn clear(&mut self) {
        unsafe {
            ffi::gtk_tree_view_column_clear(self.pointer)
        }
    }

    pub fn set_spacing(&mut self, spacing: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_spacing(self.pointer, spacing)
        }
    }

    pub fn get_spacing(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_spacing(self.pointer)
        }
    }

    pub fn set_visible(&mut self, visible: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_visible(self.pointer, ffi::to_gboolean(visible))
        }
    }

    pub fn get_visible(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_visible(self.pointer))
        }
    }

    pub fn set_resizable(&mut self, resizable: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_resizable(self.pointer, ffi::to_gboolean(resizable))
        }
    }

    pub fn get_resizable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_resizable(self.pointer))
        }
    }

    pub fn set_sizing(&mut self, ty: gtk::TreeViewColumnSizing) {
        unsafe {
            ffi::gtk_tree_view_column_set_sizing(self.pointer, ty)
        }
    }

    pub fn get_sizing(&self) -> gtk::TreeViewColumnSizing {
        unsafe {
            ffi::gtk_tree_view_column_get_sizing(self.pointer)
        }
    }

    pub fn get_x_offset(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_x_offset(self.pointer)
        }
    }

    pub fn get_width(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_width(self.pointer)
        }
    }

    pub fn get_fixed_width(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_fixed_width(self.pointer)
        }
    }

    pub fn set_fixed_width(&self, fixed_width: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_fixed_width(self.pointer, fixed_width)
        }
    }

    pub fn set_min_width(&self, min_width: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_min_width(self.pointer, min_width)
        }
    }

    pub fn set_max_width(&self, max_width: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_max_width(self.pointer, max_width)
        }
    }

    pub fn get_min_width(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_min_width(self.pointer)
        }
    }

    pub fn get_max_width(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_max_width(self.pointer)
        }
    }

    pub fn clicked(&self) {
        unsafe {
            ffi::gtk_tree_view_column_clicked(self.pointer)
        }
    }

    pub fn set_title(&mut self, title: &str) {
        unsafe {
            title.with_c_str(|c_str| {
                ffi::gtk_tree_view_column_set_title(self.pointer, c_str)
            });
        }
    }

    pub fn get_title(&self) -> String {
        unsafe {
            ::std::string::raw::from_buf(ffi::gtk_tree_view_column_get_title(self.pointer) as *const u8)
        }
    }

    pub fn set_expand(&mut self, expand: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_expand(self.pointer, ffi::to_gboolean(expand))
        }
    }

    pub fn get_expand(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_expand(self.pointer))
        }
    }

    pub fn set_clickable(&mut self, clickable: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_clickable(self.pointer, ffi::to_gboolean(clickable))
        }
    }

    pub fn get_clickable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_clickable(self.pointer))
        }
    }

    pub fn set_widget(&mut self, widget: &traits::Widget) {
        unsafe {
            ffi::gtk_tree_view_column_set_widget(self.pointer, widget.get_widget())
        }
    }

    pub fn get_widget<T: traits::Widget>(&self) -> T {
        unsafe {
            ffi::FFIWidget::wrap(ffi::gtk_tree_view_column_get_widget(self.pointer))
        }
    }

    pub fn set_alignment(&mut self, x_align: f32) {
        unsafe {
            ffi::gtk_tree_view_column_set_alignment(self.pointer, x_align)
        }
    }

    pub fn get_alignment(&self) -> f32 {
        unsafe {
            ffi::gtk_tree_view_column_get_alignment(self.pointer)
        }
    }

    pub fn set_reorderable(&mut self, reorderable: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_reorderable(self.pointer, ffi::to_gboolean(reorderable))
        }
    }

    pub fn get_reorderable(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_reorderable(self.pointer))
        }
    }

    pub fn get_sort_column_id(&self) -> i32 {
        unsafe {
            ffi::gtk_tree_view_column_get_sort_column_id(self.pointer)
        }
    }

    pub fn set_sort_column_id(&mut self, sort_column_id: i32) {
        unsafe {
            ffi::gtk_tree_view_column_set_sort_column_id(self.pointer, sort_column_id)
        }
    }

    pub fn set_sort_indicator(&mut self, setting: bool) {
        unsafe {
            ffi::gtk_tree_view_column_set_sort_indicator(self.pointer, ffi::to_gboolean(setting))
        }
    }

    pub fn get_sort_indicator(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_get_sort_indicator(self.pointer))
        }
    }

    pub fn set_sort_order(&mut self, order: gtk::SortType) {
        unsafe {
            ffi::gtk_tree_view_column_set_sort_order(self.pointer, order)
        }
    }

    pub fn get_sort_order(&self) -> gtk::SortType {
        unsafe {
            ffi::gtk_tree_view_column_get_sort_order(self.pointer)
        }
    }

    pub fn column_cell_is_visible(&self) -> bool {
        unsafe {
            ffi::to_bool(ffi::gtk_tree_view_column_cell_is_visible(self.pointer))
        }
    }

    pub fn queue_resize(&mut self) {
        unsafe {
            ffi::gtk_tree_view_column_queue_resize(self.pointer)
        }
    }

    pub fn get_tree_view(&self) -> gtk::TreeView {
        unsafe {
            ffi::FFIWidget::wrap(ffi::gtk_tree_view_column_get_tree_view(self.pointer))
        }
    }

    pub fn get_button<T: traits::Widget + traits::Button>(&self) -> T {
        unsafe {
            ffi::FFIWidget::wrap(ffi::gtk_tree_view_column_get_button(self.pointer))
        }
    }

    pub fn add_attribute<T: ffi::FFIWidget + traits::CellRenderer>(&self, cell: &T, attribute: &str, column: i32) {
        let attribute_c = attribute.to_c_str();
        unsafe { ffi::gtk_tree_view_column_add_attribute(self.pointer,
                                                         cast::GTK_CELL_RENDERER(cell.get_widget()),
                                                         attribute_c.as_ptr(),
                                                         column) }
    }

    pub fn clear_attributes<T: ffi::FFIWidget + traits::CellRenderer>(&self, cell: &T) {
        unsafe { ffi::gtk_tree_view_column_clear_attributes(self.pointer,
                                                            cast::GTK_CELL_RENDERER(cell.get_widget())) }
    }

    pub fn pack_start<T: ffi::FFIWidget + traits::CellRenderer>(&self, cell: &T, expand: bool) {
        unsafe { ffi::gtk_tree_view_column_pack_start(self.pointer,
                                                      cast::GTK_CELL_RENDERER(cell.get_widget()),
                                                      ffi::to_gboolean(expand)) }
    }

    pub fn pack_end<T: ffi::FFIWidget + traits::CellRenderer>(&self, cell: &T, expand: bool) {
        unsafe { ffi::gtk_tree_view_column_pack_end(self.pointer,
                                                    cast::GTK_CELL_RENDERER(cell.get_widget()),
                                                    ffi::to_gboolean(expand)) }
    }

    #[doc(hidden)]
    pub fn get_pointer(&self) -> *mut ffi::C_GtkTreeViewColumn {
        self.pointer
    }

    #[doc(hidden)]
    pub fn wrap_pointer(treeview_column: *mut ffi::C_GtkTreeViewColumn) -> TreeViewColumn {
        unsafe{
            ::glib::ffi::g_object_ref(treeview_column as *mut ::glib::ffi::C_GObject);
        }

        TreeViewColumn {
            pointer: treeview_column
        }
    }
}

impl glib::traits::FFIGObject for TreeViewColumn {
    fn get_gobject(&self) -> *mut glib::ffi::C_GObject {
        gtk::cast::G_OBJECT_FROM_TREE_VIEW_COLUMN(self.pointer)
    }
}

impl_connect!(TreeViewColumn -> Clicked)

impl Drop for TreeViewColumn {
    fn drop(&mut self) {
        unsafe {
            ::glib::ffi::g_object_unref(self.pointer as *mut ::glib::ffi::C_GObject);
        }
    }
}

impl Clone for TreeViewColumn {
    fn clone(&self) -> TreeViewColumn {
        let pointer = unsafe {
            ::glib::ffi::g_object_ref(self.pointer as *mut ::glib::ffi::C_GObject)
        };

        TreeViewColumn {
            pointer: pointer as *mut ffi::C_GtkTreeViewColumn
        }
    }
}
<|endoftext|>


<commit_before>use ::storage::{StorageValue, Error};
use ::storage::fields::DeserializeFromJson;
use ::crypto::Hash;
use std::fmt;
use serde::{Serialize, Serializer};
use serde_json::Value;
use super::hash_rules;
const LEFT_DESC: &'static str = "left";
const RIGHT_DESC: &'static str = "rigth";
const VAL_DESC: &'static str = "val";
#[allow(dead_code)]
pub fn proof_indices_values<V: StorageValue>(proof: &Proofnode<V>) -> Vec<(usize, &V)> {
    let mut res = Vec::new();
    proof.indices_and_values(0usize, &mut res);
    res
}

pub enum Proofnode<V> {
    Full(Box<Proofnode<V>>, Box<Proofnode<V>>),
    Left(Box<Proofnode<V>>, Option<Hash>),
    Right(Hash, Box<Proofnode<V>>),
    Leaf(V),
}

impl<V: Serialize> Serialize for Proofnode<V> {
    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        use self::Proofnode::*;
        let mut state;
        match *self {
            Full(ref left_proof, ref right_proof) => {
                state = ser.serialize_struct("Full", 2)?;
                ser.serialize_struct_elt(&mut state, LEFT_DESC, left_proof)?;
                ser.serialize_struct_elt(&mut state, RIGHT_DESC, right_proof)?;
            }
            Left(ref left_proof, ref option_hash) => {
                if let Some(ref hash) = *option_hash {
                    state = ser.serialize_struct("Left", 2)?;
                    ser.serialize_struct_elt(&mut state, LEFT_DESC, left_proof)?;
                    ser.serialize_struct_elt(&mut state, RIGHT_DESC, hash)?;
                } else {
                    state = ser.serialize_struct("Left", 1)?;
                    ser.serialize_struct_elt(&mut state, LEFT_DESC, left_proof)?;
                }
            }
            Right(ref hash, ref right_proof) => {
                state = ser.serialize_struct("Right", 2)?;
                ser.serialize_struct_elt(&mut state, LEFT_DESC, hash)?;
                ser.serialize_struct_elt(&mut state, RIGHT_DESC, right_proof)?;
            }
            Leaf(ref val) => {
                state = ser.serialize_struct("Leaf", 1)?;
                ser.serialize_struct_elt(&mut state, VAL_DESC, val)?;
            }
        }
        ser.serialize_struct_end(state)
    }
}
impl<V: DeserializeFromJson> DeserializeFromJson for Proofnode<V> {
    fn deserialize(json: &Value) -> Result<Self, Error> {
        if !json.is_object() {
            return Err(Error::new(format!("Invalid json: it is expected to be json Object. \
                                           json: {:?}",
                                          json)));
        }
        let map_key_value = json.as_object().unwrap();
        let res: Self = match map_key_value.len() {
            2 => {
                let left_value: &Value = match map_key_value.get(LEFT_DESC) {
                    None => {
                        return Err(Error::new(format!("Invalid json: Key {} not found. Value: \
                                                       {:?}",
                                                      LEFT_DESC,
                                                      json)))
                    }
                    Some(left) => left,
                };
                let right_value: &Value = match map_key_value.get(RIGHT_DESC) {
                    None => {
                        return Err(Error::new(format!("Invalid json: Key {} not found. Value: \
                                                       {:?}",
                                                      RIGHT_DESC,
                                                      json)))
                    }
                    Some(right) => right,
                };
                if right_value.is_string() {
                    let left_proof = Self::deserialize(left_value)?;
                    let right_hash: Hash = DeserializeFromJson::deserialize(right_value)?;
                    Proofnode::Left(Box::new(left_proof), Some(right_hash))
                } else if left_value.is_string() {
                    let right_proof = Self::deserialize(right_value)?;
                    let left_hash: Hash = DeserializeFromJson::deserialize(left_value)?;
                    Proofnode::Right(left_hash, Box::new(right_proof))
                } else {
                    let left_proof = Self::deserialize(left_value)?;
                    let right_proof = Self::deserialize(right_value)?;
                    Proofnode::Full(Box::new(left_proof), Box::new(right_proof))
                }
            }
            1 => {
                if map_key_value.get(VAL_DESC).is_none() && map_key_value.get(LEFT_DESC).is_none() {
                    return Err(Error::new(format!("Invalid json: unknown key met. Expected: {} \
                                                   or {}. json: {:?}",
                                                  VAL_DESC,
                                                  LEFT_DESC,
                                                  json)));
                }
                if let Some(leaf_value) = map_key_value.get(VAL_DESC) {
                    let val: V = V::deserialize(leaf_value)?;
                    Proofnode::Leaf(val)
                } else {
                    // LEFT_DESC is present
                    let left_proof_value = map_key_value.get(LEFT_DESC).unwrap();
                    let left_proof = Self::deserialize(left_proof_value)?;
                    Proofnode::Left(Box::new(left_proof), None)
                }
            }
            _ => {
                return Err(Error::new(format!("Invalid json: Number of keys should be either 1 \
                                               or 2. json: {:?}",
                                              json)))
            }
        };
        Ok(res)
    }
}
impl<V: StorageValue> Proofnode<V> {
    pub fn compute_proof_root(&self) -> Hash {
        match *self {
            Proofnode::Full(ref left, ref right) => {
                hash_rules::hash_branch(left.compute_proof_root(), right.compute_proof_root())
            }
            Proofnode::Left(ref left_proof, ref right_hash) => {
                if let Some(ref hash_val) = *right_hash {
                    hash_rules::hash_branch(left_proof.compute_proof_root(), *hash_val)
                } else {
                    hash_rules::hash_single_branch(left_proof.compute_proof_root())
                }
            }
            Proofnode::Right(ref left_hash, ref right_proof) => {
                hash_rules::hash_branch(*left_hash, right_proof.compute_proof_root())
            }
            Proofnode::Leaf(ref val) => hash_rules::hash_leaf(val),
        }
    }

    fn indices_and_values<'a>(&'a self, index: usize, collect: &mut Vec<(usize, &'a V)>) {
        let left_ch_ind = index * 2;
        let right_ch_ind = index * 2 + 1;
        match *self {
            Proofnode::Full(ref left, ref right) => {
                left.indices_and_values(left_ch_ind, collect);
                right.indices_and_values(right_ch_ind, collect);
            }
            Proofnode::Left(ref left_proof, _) => {
                left_proof.indices_and_values(left_ch_ind, collect);
            }
            Proofnode::Right(_, ref right_proof) => {
                right_proof.indices_and_values(right_ch_ind, collect);
            }
            Proofnode::Leaf(ref val) => collect.push((index, val)),
        }
    }
}

impl<V: fmt::Debug> fmt::Debug for Proofnode<V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Proofnode::*;
        match *self {
            Full(ref left, ref right) => write!(f, "{{\"left\":{:?},\"right\":{:?}}}", left, right),
            Left(ref left_proof, ref right_hash) => {
                if let Some(ref digest) = *right_hash {
                    write!(f, "{{\"left\":{:?},\"right\":{:?}}}", left_proof, digest)
                } else {
                    write!(f, "{{\"left\":{:?}}}", left_proof)
                }
            }
            Right(ref left_hash, ref right) => {
                write!(f, "{{\"left\":{:?},\"right\":{:?}}}", left_hash, right)
            }
            Leaf(ref val) => write!(f, "{{\"val\":{:?}}}", val),
        }
    }
}
<commit_msg>Corrected tag "rigth" -> "right" in json.<commit_after>use ::storage::{StorageValue, Error};
use ::storage::fields::DeserializeFromJson;
use ::crypto::Hash;
use std::fmt;
use serde::{Serialize, Serializer};
use serde_json::Value;
use super::hash_rules;
const LEFT_DESC: &'static str = "left";
const RIGHT_DESC: &'static str = "right";
const VAL_DESC: &'static str = "val";
#[allow(dead_code)]
pub fn proof_indices_values<V: StorageValue>(proof: &Proofnode<V>) -> Vec<(usize, &V)> {
    let mut res = Vec::new();
    proof.indices_and_values(0usize, &mut res);
    res
}

pub enum Proofnode<V> {
    Full(Box<Proofnode<V>>, Box<Proofnode<V>>),
    Left(Box<Proofnode<V>>, Option<Hash>),
    Right(Hash, Box<Proofnode<V>>),
    Leaf(V),
}

impl<V: Serialize> Serialize for Proofnode<V> {
    fn serialize<S>(&self, ser: &mut S) -> Result<(), S::Error>
        where S: Serializer
    {
        use self::Proofnode::*;
        let mut state;
        match *self {
            Full(ref left_proof, ref right_proof) => {
                state = ser.serialize_struct("Full", 2)?;
                ser.serialize_struct_elt(&mut state, LEFT_DESC, left_proof)?;
                ser.serialize_struct_elt(&mut state, RIGHT_DESC, right_proof)?;
            }
            Left(ref left_proof, ref option_hash) => {
                if let Some(ref hash) = *option_hash {
                    state = ser.serialize_struct("Left", 2)?;
                    ser.serialize_struct_elt(&mut state, LEFT_DESC, left_proof)?;
                    ser.serialize_struct_elt(&mut state, RIGHT_DESC, hash)?;
                } else {
                    state = ser.serialize_struct("Left", 1)?;
                    ser.serialize_struct_elt(&mut state, LEFT_DESC, left_proof)?;
                }
            }
            Right(ref hash, ref right_proof) => {
                state = ser.serialize_struct("Right", 2)?;
                ser.serialize_struct_elt(&mut state, LEFT_DESC, hash)?;
                ser.serialize_struct_elt(&mut state, RIGHT_DESC, right_proof)?;
            }
            Leaf(ref val) => {
                state = ser.serialize_struct("Leaf", 1)?;
                ser.serialize_struct_elt(&mut state, VAL_DESC, val)?;
            }
        }
        ser.serialize_struct_end(state)
    }
}
impl<V: DeserializeFromJson> DeserializeFromJson for Proofnode<V> {
    fn deserialize(json: &Value) -> Result<Self, Error> {
        if !json.is_object() {
            return Err(Error::new(format!("Invalid json: it is expected to be json Object. \
                                           json: {:?}",
                                          json)));
        }
        let map_key_value = json.as_object().unwrap();
        let res: Self = match map_key_value.len() {
            2 => {
                let left_value: &Value = match map_key_value.get(LEFT_DESC) {
                    None => {
                        return Err(Error::new(format!("Invalid json: Key {} not found. Value: \
                                                       {:?}",
                                                      LEFT_DESC,
                                                      json)))
                    }
                    Some(left) => left,
                };
                let right_value: &Value = match map_key_value.get(RIGHT_DESC) {
                    None => {
                        return Err(Error::new(format!("Invalid json: Key {} not found. Value: \
                                                       {:?}",
                                                      RIGHT_DESC,
                                                      json)))
                    }
                    Some(right) => right,
                };
                if right_value.is_string() {
                    let left_proof = Self::deserialize(left_value)?;
                    let right_hash: Hash = DeserializeFromJson::deserialize(right_value)?;
                    Proofnode::Left(Box::new(left_proof), Some(right_hash))
                } else if left_value.is_string() {
                    let right_proof = Self::deserialize(right_value)?;
                    let left_hash: Hash = DeserializeFromJson::deserialize(left_value)?;
                    Proofnode::Right(left_hash, Box::new(right_proof))
                } else {
                    let left_proof = Self::deserialize(left_value)?;
                    let right_proof = Self::deserialize(right_value)?;
                    Proofnode::Full(Box::new(left_proof), Box::new(right_proof))
                }
            }
            1 => {
                if map_key_value.get(VAL_DESC).is_none() && map_key_value.get(LEFT_DESC).is_none() {
                    return Err(Error::new(format!("Invalid json: unknown key met. Expected: {} \
                                                   or {}. json: {:?}",
                                                  VAL_DESC,
                                                  LEFT_DESC,
                                                  json)));
                }
                if let Some(leaf_value) = map_key_value.get(VAL_DESC) {
                    let val: V = V::deserialize(leaf_value)?;
                    Proofnode::Leaf(val)
                } else {
                    // LEFT_DESC is present
                    let left_proof_value = map_key_value.get(LEFT_DESC).unwrap();
                    let left_proof = Self::deserialize(left_proof_value)?;
                    Proofnode::Left(Box::new(left_proof), None)
                }
            }
            _ => {
                return Err(Error::new(format!("Invalid json: Number of keys should be either 1 \
                                               or 2. json: {:?}",
                                              json)))
            }
        };
        Ok(res)
    }
}
impl<V: StorageValue> Proofnode<V> {
    pub fn compute_proof_root(&self) -> Hash {
        match *self {
            Proofnode::Full(ref left, ref right) => {
                hash_rules::hash_branch(left.compute_proof_root(), right.compute_proof_root())
            }
            Proofnode::Left(ref left_proof, ref right_hash) => {
                if let Some(ref hash_val) = *right_hash {
                    hash_rules::hash_branch(left_proof.compute_proof_root(), *hash_val)
                } else {
                    hash_rules::hash_single_branch(left_proof.compute_proof_root())
                }
            }
            Proofnode::Right(ref left_hash, ref right_proof) => {
                hash_rules::hash_branch(*left_hash, right_proof.compute_proof_root())
            }
            Proofnode::Leaf(ref val) => hash_rules::hash_leaf(val),
        }
    }

    fn indices_and_values<'a>(&'a self, index: usize, collect: &mut Vec<(usize, &'a V)>) {
        let left_ch_ind = index * 2;
        let right_ch_ind = index * 2 + 1;
        match *self {
            Proofnode::Full(ref left, ref right) => {
                left.indices_and_values(left_ch_ind, collect);
                right.indices_and_values(right_ch_ind, collect);
            }
            Proofnode::Left(ref left_proof, _) => {
                left_proof.indices_and_values(left_ch_ind, collect);
            }
            Proofnode::Right(_, ref right_proof) => {
                right_proof.indices_and_values(right_ch_ind, collect);
            }
            Proofnode::Leaf(ref val) => collect.push((index, val)),
        }
    }
}

impl<V: fmt::Debug> fmt::Debug for Proofnode<V> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        use self::Proofnode::*;
        match *self {
            Full(ref left, ref right) => write!(f, "{{\"left\":{:?},\"right\":{:?}}}", left, right),
            Left(ref left_proof, ref right_hash) => {
                if let Some(ref digest) = *right_hash {
                    write!(f, "{{\"left\":{:?},\"right\":{:?}}}", left_proof, digest)
                } else {
                    write!(f, "{{\"left\":{:?}}}", left_proof)
                }
            }
            Right(ref left_hash, ref right) => {
                write!(f, "{{\"left\":{:?},\"right\":{:?}}}", left_hash, right)
            }
            Leaf(ref val) => write!(f, "{{\"val\":{:?}}}", val),
        }
    }
}
<|endoftext|>


<commit_before>use super::*;
use redox::*;

impl Editor {
    /// Remove from a given motion (row based)
    pub fn remove_rb<'a>(&mut self, (x, y): (usize, usize)) {
        if y == self.y() {
            // Single line mode
            let (a, b) = if self.x() < x {
                (self.x(), x)
            } else {
                (x, self.x())
            };
            for i in a..b {
                self.text[y].remove(i);
            }
        } else {
            // Full line mode
            let (a, b) = if self.y() < y {
                (self.y(), y)
            } else {
                (y, self.y())
            };
            for ln in a..(b + 1) {
                self.text.remove(ln);
            }
        }
    }
}
<commit_msg>Fix out-of-bound bug<commit_after>use super::*;
use redox::*;

impl Editor {
    /// Remove from a given motion (row based)
    pub fn remove_rb<'a>(&mut self, (x, y): (usize, usize)) {
        if y == self.y() {
            // Single line mode
            let (a, b) = if self.x() < x {
                (self.x(), x)
            } else {
                (x, self.x())
            };
            for _ in a..b {
                self.text[y].remove(a);
            }
        } else {
            // Full line mode
            let (a, b) = if self.y() < y {
                (self.y(), y)
            } else {
                (y, self.y())
            };
            for _ in a..(b + 1) {
                if self.text.len() > 1 {
                    self.text.remove(a);
                }
            }
        }
    }
}
<|endoftext|>


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

//! Exported interface for interacting with the kernel from C.

use crate::logging::SERIAL1;
use alloc::alloc::{alloc, dealloc, Layout};
use core::{
    cell::{LazyCell, RefCell},
    ffi::c_void,
    ptr::null_mut,
};
use hashbrown::HashMap;
use spinning_top::{const_spinlock, Spinlock};
use static_assertions::const_assert;

/// The maximum alignment that we need to support any C type that has fundamental alignment.
const MAX_ALIGNMENT: usize = core::mem::align_of::<libc::max_align_t>();

const_assert!(MAX_ALIGNMENT.is_power_of_two());

/// Cache for keeping track of which memory locations we allocated and the layout (size and
/// alignment) that was used for each allocation.
static ALLOCATED_ITEMS: Spinlock<LazyCell<RefCell<HashMap<usize, Layout>>>> =
    const_spinlock(LazyCell::new(|| RefCell::new(HashMap::new())));

/// Allocates memory of the given size with alignment that is suitable for any C type that has
/// fundamental alignment.
///
/// This function returns a pointer to the allocated memory if the allocation succeeds and null if
/// it fails. All allocated memory must be deallocated using `heap_free`.
///
/// The function is intentionally not named "malloc" to avoid naming clashes. It is up to the
/// compatibility layer to make sure that this function is used for allocating memory.
#[no_mangle]
pub extern "C" fn heap_alloc(size: usize) -> *mut c_void {
    if size == 0 {
        return null_mut();
    }

    // This should never panic since we checked that the size is non-zero and calculated a valid
    // alignment.
    let layout = Layout::from_size_align(size, calculate_alignment(size))
        .expect("Invalid alignment calculated.");

    // We use the global allocator directly (rather than using e.g. `Vec<u8>`) so that we have the
    // required control over the alignment of the allocated memory.
    //
    // Safety: we ensured that the size is not 0.
    let result = unsafe { alloc(layout) as *mut c_void };
    if !result.is_null() {
        ALLOCATED_ITEMS
            .lock()
            .borrow_mut()
            .insert(result as usize, layout);
    }

    result
}

#[inline]
fn calculate_alignment(size: usize) -> usize {
    MAX_ALIGNMENT.min(size.next_power_of_two())
}

/// Frees memory that was previously allocated using `heap_alloc`.
///
/// If the pointer is null, it does nothing. Panics if the pointer is non-null but was not allocated
/// using `heap_alloc`, or if it was already freed.
///
/// The function is intentionally not named "free" to avoid naming clashes. It is up to the
/// compatibility layer to make sure that this function is used for freeing memory.
#[no_mangle]
pub extern "C" fn heap_free(ptr: *mut c_void) {
    if ptr.is_null() {
        return;
    }

    let key = ptr as usize;
    let layout = ALLOCATED_ITEMS
        .lock()
        .borrow_mut()
        .remove(&key)
        .expect("Invalid memory region pointer. It was either already freed or not allocated.");

    // Safety: we have validated that we previously allocated the memory, found the layout that was
    // used to allocate it, and it was not yet freed.
    unsafe {
        dealloc(ptr as *mut u8, layout);
    }
}

/// Writes the specified number of bytes from a buffer to the serial console.
///
/// To be compatible with C write semantics the number of bytes written is returned on success and
/// -1 on failure.
///
/// #Safety
///
/// The pointer must point to a valid location of a buffer with at least the specified size.
#[no_mangle]
pub unsafe extern "C" fn write_console(ptr: *const u8, size: usize) -> isize {
    if ptr.is_null() {
        return -1;
    }

    let bytes = core::slice::from_raw_parts(ptr, size);
    let mut serial = SERIAL1.borrow_mut();
    for byte in bytes {
        if serial.send(*byte).is_err() {
            return -1;
        }
    }

    size as isize
}
<commit_msg>Add exported function for exiting the VM (#3366)<commit_after>//
// Copyright 2022 The Project Oak Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

//! Exported interface for interacting with the kernel from C.

use crate::{i8042::shutdown, logging::SERIAL1};
use alloc::alloc::{alloc, dealloc, Layout};
use core::{
    cell::{LazyCell, RefCell},
    ffi::c_void,
    ptr::null_mut,
};
use hashbrown::HashMap;
use log::info;
use spinning_top::{const_spinlock, Spinlock};
use static_assertions::const_assert;

/// The maximum alignment that we need to support any C type that has fundamental alignment.
const MAX_ALIGNMENT: usize = core::mem::align_of::<libc::max_align_t>();

const_assert!(MAX_ALIGNMENT.is_power_of_two());

/// Cache for keeping track of which memory locations we allocated and the layout (size and
/// alignment) that was used for each allocation.
static ALLOCATED_ITEMS: Spinlock<LazyCell<RefCell<HashMap<usize, Layout>>>> =
    const_spinlock(LazyCell::new(|| RefCell::new(HashMap::new())));

/// Allocates memory of the given size with alignment that is suitable for any C type that has
/// fundamental alignment.
///
/// This function returns a pointer to the allocated memory if the allocation succeeds and null if
/// it fails. All allocated memory must be deallocated using `heap_free`.
///
/// The function is intentionally not named "malloc" to avoid naming clashes. It is up to the
/// compatibility layer to make sure that this function is used for allocating memory.
#[no_mangle]
pub extern "C" fn heap_alloc(size: usize) -> *mut c_void {
    if size == 0 {
        return null_mut();
    }

    // This should never panic since we checked that the size is non-zero and calculated a valid
    // alignment.
    let layout = Layout::from_size_align(size, calculate_alignment(size))
        .expect("Invalid alignment calculated.");

    // We use the global allocator directly (rather than using e.g. `Vec<u8>`) so that we have the
    // required control over the alignment of the allocated memory.
    //
    // Safety: we ensured that the size is not 0.
    let result = unsafe { alloc(layout) as *mut c_void };
    if !result.is_null() {
        ALLOCATED_ITEMS
            .lock()
            .borrow_mut()
            .insert(result as usize, layout);
    }

    result
}

#[inline]
fn calculate_alignment(size: usize) -> usize {
    MAX_ALIGNMENT.min(size.next_power_of_two())
}

/// Frees memory that was previously allocated using `heap_alloc`.
///
/// If the pointer is null, it does nothing. Panics if the pointer is non-null but was not allocated
/// using `heap_alloc`, or if it was already freed.
///
/// The function is intentionally not named "free" to avoid naming clashes. It is up to the
/// compatibility layer to make sure that this function is used for freeing memory.
#[no_mangle]
pub extern "C" fn heap_free(ptr: *mut c_void) {
    if ptr.is_null() {
        return;
    }

    let key = ptr as usize;
    let layout = ALLOCATED_ITEMS
        .lock()
        .borrow_mut()
        .remove(&key)
        .expect("Invalid memory region pointer. It was either already freed or not allocated.");

    // Safety: we have validated that we previously allocated the memory, found the layout that was
    // used to allocate it, and it was not yet freed.
    unsafe {
        dealloc(ptr as *mut u8, layout);
    }
}

/// Writes the specified number of bytes from a buffer to the serial console.
///
/// To be compatible with C write semantics the number of bytes written is returned on success and
/// -1 on failure.
///
/// #Safety
///
/// The pointer must point to a valid location of a buffer with at least the specified size.
#[no_mangle]
pub unsafe extern "C" fn write_console(ptr: *const u8, size: usize) -> isize {
    if ptr.is_null() {
        return -1;
    }

    let bytes = core::slice::from_raw_parts(ptr, size);
    let mut serial = SERIAL1.borrow_mut();
    for byte in bytes {
        if serial.send(*byte).is_err() {
            return -1;
        }
    }

    size as isize
}

/// Causes the VM to exit after logging the code.
///
/// The function is intentionally not named "exit" to avoid naming clashes. It is up to the
/// compatibility layer to make sure that this function is used for exiting.
#[no_mangle]
pub extern "C" fn exit_vm(code: i32) {
    info!("Exit called with code: {}", code);
    shutdown();
}
<|endoftext|>


<commit_before>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

extern crate ears;

use std::io::stdin;
use std::io::stdio::flush;

use ears::{Music, AudioController, Playing, Stopped, Paused};

fn main() {

    // Read the inputs
    let mut stdin = stdin();

    print!("Insert the path to an audio file : ");
    flush();

    let mut line = stdin.read_line().unwrap();
    line.pop_char();

    // Try to create the music
    let mut music = match Music::new(line) {
        Some(music) => music,
        None        => fail!("Cannot load the music.")
    };

    // Play it
    music.play();

    loop {
        // Make your choice
        println!("Commands :\n\tPlay  : l\n\tPause : p\n\tStop  : s\n\tExit  : x\n");
        match stdin.read_line().unwrap() {
            ~"l\n"    => music.play(),
            ~"p\n"    => music.pause(),
            ~"s\n"    => music.stop(),
            ~"x\n"    => { music.stop(); break; },
            _       => println!("Unknwon command.")
        }
        match music.get_state() {
            Playing => println!("State : Playing"),
            Stopped => println!("State : Stopped"),
            Paused  => println!("State : Paused"),
            _       => unreachable!()
        };
    }
    println!("Goodbye!");
}<commit_msg>fix build to last Rust master<commit_after>// The MIT License (MIT)
//
// Copyright (c) 2013 Jeremy Letang (letang.jeremy@gmail.com)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

extern crate ears;

use std::io::stdin;
use std::io::stdio::flush;

use ears::{Music, AudioController, Playing, Stopped, Paused};

fn main() {

    // Read the inputs
    let mut stdin = stdin();

    print!("Insert the path to an audio file : ");
    flush();

    let mut line = stdin.read_line().unwrap();
    line.pop_char();

    // Try to create the music
    let mut music = match Music::new(line) {
        Some(music) => music,
        None        => fail!("Cannot load the music.")
    };

    // Play it
    music.play();

    loop {
        // Make your choice
        println!("Commands :\n\tPlay  : l\n\tPause : p\n\tStop  : s\n\tExit  : x\n");
        match stdin.read_line().unwrap().as_slice() {
            "l\n"    => music.play(),
            "p\n"    => music.pause(),
            "s\n"    => music.stop(),
            "x\n"    => { music.stop(); break; },
            _       => println!("Unknwon command.")
        }
        match music.get_state() {
            Playing => println!("State : Playing"),
            Stopped => println!("State : Stopped"),
            Paused  => println!("State : Paused"),
            _       => unreachable!()
        };
    }
    println!("Goodbye!");
}<|endoftext|>


<commit_before>//! An example that displays RDTSC frequency.
extern crate raw_cpuid;
extern crate x86;

use std::time;
use x86::time::rdtscp;

const MHZ_TO_HZ: u64 = 1000000;
const KHZ_TO_HZ: u64 = 1000;

fn main() {
    let cpuid = raw_cpuid::CpuId::new();
    let has_tsc = cpuid
        .get_feature_info()
        .map_or(false, |finfo| finfo.has_tsc());

    let has_invariant_tsc = cpuid
        .get_extended_function_info()
        .map_or(false, |efinfo| efinfo.has_invariant_tsc());

    let tsc_frequency_hz = cpuid.get_tsc_info().map(|tinfo| {
        if tinfo.nominal_frequency() != 0 {
            Some(tinfo.tsc_frequency())
        } else if tinfo.numerator() != 0 && tinfo.denominator() != 0 {
            // Skylake and Kabylake don't report the crystal clock, approximate with base frequency:
            cpuid
                .get_processor_frequency_info()
                .map(|pinfo| pinfo.processor_base_frequency() as u64 * MHZ_TO_HZ)
                .map(|cpu_base_freq_hz| {
                    let crystal_hz =
                        cpu_base_freq_hz * tinfo.denominator() as u64 / tinfo.numerator() as u64;
                    crystal_hz * tinfo.numerator() as u64 / tinfo.denominator() as u64
                })
        } else {
            None
        }
    });

    if has_tsc {
        println!(
            "TSC Frequency is: {} ({})",
            match tsc_frequency_hz {
                Some(x) => format!("{} Hz", x.unwrap_or(0)),
                None => String::from("unknown"),
            },
            if has_invariant_tsc {
                "invariant"
            } else {
                "TSC frequency varies with speed-stepping"
            }
        );
    }

    cpuid.get_hypervisor_info().map(|hv| {
        hv.tsc_frequency().map(|tsc_khz| {
            let virtual_tsc_frequency_hz = tsc_khz as u64 * KHZ_TO_HZ;
            println!(
                "Hypervisor reports TSC Frequency at: {} Hz",
                virtual_tsc_frequency_hz
            );
        })
    });

    let one_second = time::Duration::from_secs(1);
    let now = time::Instant::now();
    let start = unsafe { rdtscp() };
    loop {
        if now.elapsed() >= one_second {
            break;
        }
    }
    let end = unsafe { rdtscp() };
    println!(
        "Empirical measurement of TSC frequency was: {} Hz",
        (end - start)
    );
}
<commit_msg>Change documentation.<commit_after>//! An example that determines the time stamp counter frequency (RDTSC, RDTSCP) .
extern crate raw_cpuid;
extern crate x86;

use std::time;
use x86::time::rdtscp;

const MHZ_TO_HZ: u64 = 1000000;
const KHZ_TO_HZ: u64 = 1000;

fn main() {
    let cpuid = raw_cpuid::CpuId::new();
    let has_tsc = cpuid
        .get_feature_info()
        .map_or(false, |finfo| finfo.has_tsc());

    let has_invariant_tsc = cpuid
        .get_extended_function_info()
        .map_or(false, |efinfo| efinfo.has_invariant_tsc());

    let tsc_frequency_hz = cpuid.get_tsc_info().map(|tinfo| {
        if tinfo.nominal_frequency() != 0 {
            Some(tinfo.tsc_frequency())
        } else if tinfo.numerator() != 0 && tinfo.denominator() != 0 {
            // Skylake and Kabylake don't report the crystal clock, approximate with base frequency:
            cpuid
                .get_processor_frequency_info()
                .map(|pinfo| pinfo.processor_base_frequency() as u64 * MHZ_TO_HZ)
                .map(|cpu_base_freq_hz| {
                    let crystal_hz =
                        cpu_base_freq_hz * tinfo.denominator() as u64 / tinfo.numerator() as u64;
                    crystal_hz * tinfo.numerator() as u64 / tinfo.denominator() as u64
                })
        } else {
            None
        }
    });

    if has_tsc {
        println!(
            "TSC Frequency is: {} ({})",
            match tsc_frequency_hz {
                Some(x) => format!("{} Hz", x.unwrap_or(0)),
                None => String::from("unknown"),
            },
            if has_invariant_tsc {
                "invariant"
            } else {
                "TSC frequency varies with speed-stepping"
            }
        );
    }

    cpuid.get_hypervisor_info().map(|hv| {
        hv.tsc_frequency().map(|tsc_khz| {
            let virtual_tsc_frequency_hz = tsc_khz as u64 * KHZ_TO_HZ;
            println!(
                "Hypervisor reports TSC Frequency at: {} Hz",
                virtual_tsc_frequency_hz
            );
        })
    });

    let one_second = time::Duration::from_secs(1);
    let now = time::Instant::now();
    let start = unsafe { rdtscp() };
    loop {
        if now.elapsed() >= one_second {
            break;
        }
    }
    let end = unsafe { rdtscp() };
    println!(
        "Empirical measurement of TSC frequency was: {} Hz",
        (end - start)
    );
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::iter::FromIterator;
use std::time::Duration;

use serialport as sp;
use serial_support::errors::*;

/// Struct for containing Port information
struct OpenPort {
  /// The opened serial port
  /// SerialPort is not Sized, so it makes hashmap mad
  /// and so we deal with these shennanigans
  port: Box<sp::SerialPort>,
}

impl OpenPort {
  /// Write data to the serial port
  pub fn write_port(&mut self, data: &[u8]) -> Result<()> {
    self
      .port
      .write_all(data)
      .map_err(|err| ErrorKind::Io(err).into())
  }

  /// Read data from the serial port
  pub fn read_port(&mut self, buff: &mut [u8]) -> Result<usize> {
    self
      .port
      .read(buff)
      .map_err(|err| ErrorKind::Io(err).into())
  }
}

/// Manages ports and their locks
pub struct PortManager {
  /// Maintains list of ports
  open_ports: HashMap<String, OpenPort>,
}

impl PortManager {
  /// Create a new PortManager instance
  pub fn new() -> PortManager {
    PortManager { open_ports: HashMap::new() }
  }

  /// Has the port been opened
  pub fn is_port_open(&self, port_name: &String) -> bool {
    self.open_ports.contains_key(port_name)
  }

  /// List all serial ports
  pub fn list_ports(&self) -> Result<Vec<sp::SerialPortInfo>> {
    sp::available_ports().map_err(|e| ErrorKind::Serialport(e).into())
  }

  /// Open a port
  pub fn open_port(&mut self, port_name: &String) -> Result<()> {

    if self.is_port_open(port_name) {
      Ok(())
    } else {

      let sp_settings = sp::SerialPortSettings {
        baud_rate: sp::BaudRate::Baud115200,
        data_bits: sp::DataBits::Eight,
        flow_control: sp::FlowControl::None,
        parity: sp::Parity::None,
        // Bug: serialport 1.0.1 has One and Two mixed up
        // FIXME: Will be fixed in next release
        // So here we use Two to select One stop bit
        stop_bits: sp::StopBits::One,
        timeout: Duration::from_millis(1),
      };

      match sp::open_with_settings(&port_name, &sp_settings) {
        Ok(serial_port) => {
          let open_port = OpenPort { port: serial_port };
          self.open_ports.insert(port_name.to_string(), open_port);
          Ok(())
        }
        Err(e) => Err(ErrorKind::Serialport(e).into()),
      }
    }
  }

  pub fn close_port(&mut self, port_name: &String) {
    // This drops the underlying serial port and box
    self.open_ports.remove(port_name);
  }

  /// Write data to the port
  /// To write data to a port the port must have been previously locked by sub_id
  pub fn write_port(&mut self, port_name: &String, data: &[u8]) -> Result<()> {
    match self.open_ports.get_mut(port_name) {
      None => Err(ErrorKind::OpenPortNotFound(port_name.to_string()).into()),
      Some(p) => p.write_port(data),
    }
  }

  /// Read data from a port into the buffer buff
  /// If successful, returns Ok(usize) which is the number of
  /// bytes read
  pub fn read_port(&mut self, port_name: &String, buff: &mut [u8]) -> Result<usize> {
    match self.open_ports.get_mut(port_name) {
      None => Err(ErrorKind::OpenPortNotFound(port_name.to_string()).into()),
      Some(p) => p.read_port(buff),
    }
  }

  /// Read all currently open ports, return a hashmap of
  /// ports to Result<Vec<u8>>
  pub fn read_all_ports(&mut self) -> HashMap<String, Result<Vec<u8>>> {
    let mut buffer = vec![0; 4096];
    let mut map = HashMap::new();
    for (port_name, open_port) in self.open_ports.iter_mut() {
      match open_port.read_port(buffer.as_mut_slice()) {
        Ok(bytes_read) => {
          if bytes_read == 0 {
            // EOF
            info!("Received EOF reading from port {}", port_name);
            map.insert(
              port_name.to_string(),
              Err(ErrorKind::PortEOFError(port_name.clone()).into()),
            );
          } else {
            let bytes = buffer[0..bytes_read].to_vec();
            map.insert(port_name.to_string(), Ok(bytes));
          }
        }
        Err(e) => {
          // debug!("Error {} reading from port {}", e, port_name);
          match e.description() {
            "Operation timed out" => {}
            _ => {
              map.insert(port_name.to_string(), Err(e.into()));
            }
          }

        }
      }
    }
    map
  }

  /// Get a vec of open ports
  pub fn open_ports(&self) -> HashSet<String> {
    HashSet::<String>::from_iter(self.open_ports.keys().map(|k| k.clone()))
  }
}
<commit_msg>Remove unused import<commit_after>use std::collections::{HashMap, HashSet};
use std::error::Error;
use std::iter::FromIterator;
use std::time::Duration;

use serialport as sp;
use serial_support::errors::*;

/// Struct for containing Port information
struct OpenPort {
  /// The opened serial port
  /// SerialPort is not Sized, so it makes hashmap mad
  /// and so we deal with these shennanigans
  port: Box<sp::SerialPort>,
}

impl OpenPort {
  /// Write data to the serial port
  pub fn write_port(&mut self, data: &[u8]) -> Result<()> {
    self
      .port
      .write_all(data)
      .map_err(|err| ErrorKind::Io(err).into())
  }

  /// Read data from the serial port
  pub fn read_port(&mut self, buff: &mut [u8]) -> Result<usize> {
    self
      .port
      .read(buff)
      .map_err(|err| ErrorKind::Io(err).into())
  }
}

/// Manages ports and their locks
pub struct PortManager {
  /// Maintains list of ports
  open_ports: HashMap<String, OpenPort>,
}

impl PortManager {
  /// Create a new PortManager instance
  pub fn new() -> PortManager {
    PortManager { open_ports: HashMap::new() }
  }

  /// Has the port been opened
  pub fn is_port_open(&self, port_name: &String) -> bool {
    self.open_ports.contains_key(port_name)
  }

  /// List all serial ports
  pub fn list_ports(&self) -> Result<Vec<sp::SerialPortInfo>> {
    sp::available_ports().map_err(|e| ErrorKind::Serialport(e).into())
  }

  /// Open a port
  pub fn open_port(&mut self, port_name: &String) -> Result<()> {

    if self.is_port_open(port_name) {
      Ok(())
    } else {

      let sp_settings = sp::SerialPortSettings {
        baud_rate: sp::BaudRate::Baud115200,
        data_bits: sp::DataBits::Eight,
        flow_control: sp::FlowControl::None,
        parity: sp::Parity::None,
        // Bug: serialport 1.0.1 has One and Two mixed up
        // FIXME: Will be fixed in next release
        // So here we use Two to select One stop bit
        stop_bits: sp::StopBits::One,
        timeout: Duration::from_millis(1),
      };

      match sp::open_with_settings(&port_name, &sp_settings) {
        Ok(serial_port) => {
          let open_port = OpenPort { port: serial_port };
          self.open_ports.insert(port_name.to_string(), open_port);
          Ok(())
        }
        Err(e) => Err(ErrorKind::Serialport(e).into()),
      }
    }
  }

  pub fn close_port(&mut self, port_name: &String) {
    // This drops the underlying serial port and box
    self.open_ports.remove(port_name);
  }

  /// Write data to the port
  /// To write data to a port the port must have been previously locked by sub_id
  pub fn write_port(&mut self, port_name: &String, data: &[u8]) -> Result<()> {
    match self.open_ports.get_mut(port_name) {
      None => Err(ErrorKind::OpenPortNotFound(port_name.to_string()).into()),
      Some(p) => p.write_port(data),
    }
  }

  /// Read data from a port into the buffer buff
  /// If successful, returns Ok(usize) which is the number of
  /// bytes read
  pub fn read_port(&mut self, port_name: &String, buff: &mut [u8]) -> Result<usize> {
    match self.open_ports.get_mut(port_name) {
      None => Err(ErrorKind::OpenPortNotFound(port_name.to_string()).into()),
      Some(p) => p.read_port(buff),
    }
  }

  /// Read all currently open ports, return a hashmap of
  /// ports to Result<Vec<u8>>
  pub fn read_all_ports(&mut self) -> HashMap<String, Result<Vec<u8>>> {
    let mut buffer = vec![0; 4096];
    let mut map = HashMap::new();
    for (port_name, open_port) in self.open_ports.iter_mut() {
      match open_port.read_port(buffer.as_mut_slice()) {
        Ok(bytes_read) => {
          if bytes_read == 0 {
            // EOF
            info!("Received EOF reading from port {}", port_name);
            map.insert(
              port_name.to_string(),
              Err(ErrorKind::PortEOFError(port_name.clone()).into()),
            );
          } else {
            let bytes = buffer[0..bytes_read].to_vec();
            map.insert(port_name.to_string(), Ok(bytes));
          }
        }
        Err(e) => {
          // debug!("Error {} reading from port {}", e, port_name);
          match e.description() {
            "Operation timed out" => {}
            _ => {
              map.insert(port_name.to_string(), Err(e.into()));
            }
          }

        }
      }
    }
    map
  }

  /// Get a vec of open ports
  pub fn open_ports(&self) -> HashSet<String> {
    HashSet::<String>::from_iter(self.open_ports.keys().map(|k| k.clone()))
  }
}
<|endoftext|>