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

use std::fmt;
use std::io;

#[deriving(Clone)]
pub struct Layout {
    logo: ~str,
    favicon: ~str,
    krate: ~str,
}

pub struct Page<'a> {
    title: &'a str,
    ty: &'a str,
    root_path: &'a str,
}

pub fn render<T: fmt::Show, S: fmt::Show>(
    dst: &mut io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T)
    -> fmt::Result
{
    write!(dst,
r##"<!DOCTYPE html>

    <meta charset="utf-8" />
    <title>{title}</title>

    <link href='http://fonts.googleapis.com/css?family=Oswald:700|Inconsolata:400,700'
          rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href="{root_path}main.css">

    {favicon, select, none{} other{<link rel="shortcut icon" href="\#" />}}

        {logo, select, none{} other{

        }}

        {sidebar}

        <form class="search-form js-only">
            <button class="do-search">Search</button>

                <input class="search-input" name="search"
                       autocomplete="off"
                       placeholder="Search documentation..."
                       type="search" />

        </form>

{content}

Keyboard shortcuts

?

Show this help dialog

S

Focus the search field

↑

Move up in search results

↓

Move down in search results

&\#9166;

Go to active search result

Search tricks

                Prefix searches with a type followed by a colon (e.g.
                fn:) to restrict the search to a given type.

                Accepted types are: fn, mod,
                struct (or str), enum,
                trait, typedef (or
                tdef).

"##,
    content   = *t,
    root_path = page.root_path,
    ty        = page.ty,
    logo      = nonestr(layout.logo),
    title     = page.title,
    favicon   = nonestr(layout.favicon),
    sidebar   = *sidebar,
    krate     = layout.krate,
    )
}

fn nonestr<'a>(s: &'a str) -> &'a str {
    if s == "" { "none" } else { s }
}
<commit_msg>rustdoc: Display rust logo again. Closes #13148<commit_after>// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::fmt;
use std::io;

#[deriving(Clone)]
pub struct Layout {
    logo: ~str,
    favicon: ~str,
    krate: ~str,
}

pub struct Page<'a> {
    title: &'a str,
    ty: &'a str,
    root_path: &'a str,
}

pub fn render<T: fmt::Show, S: fmt::Show>(
    dst: &mut io::Writer, layout: &Layout, page: &Page, sidebar: &S, t: &T)
    -> fmt::Result
{
    write!(dst,
r##"<!DOCTYPE html>

    <meta charset="utf-8" />
    <title>{title}</title>

    <link href='http://fonts.googleapis.com/css?family=Oswald:700|Inconsolata:400,700'
          rel='stylesheet' type='text/css'>
    <link rel="stylesheet" type="text/css" href="{root_path}main.css">

    {favicon, select, none{} other{<link rel="shortcut icon" href="#" />}}

        {logo, select, none{} other{

        }}

        {sidebar}

        <form class="search-form js-only">
            <button class="do-search">Search</button>

                <input class="search-input" name="search"
                       autocomplete="off"
                       placeholder="Search documentation..."
                       type="search" />

        </form>

{content}

Keyboard shortcuts

?

Show this help dialog

S

Focus the search field

↑

Move up in search results

↓

Move down in search results

&\#9166;

Go to active search result

Search tricks

                Prefix searches with a type followed by a colon (e.g.
                fn:) to restrict the search to a given type.

                Accepted types are: fn, mod,
                struct (or str), enum,
                trait, typedef (or
                tdef).

"##,
    content   = *t,
    root_path = page.root_path,
    ty        = page.ty,
    logo      = nonestr(layout.logo),
    title     = page.title,
    favicon   = nonestr(layout.favicon),
    sidebar   = *sidebar,
    krate     = layout.krate,
    )
}

fn nonestr<'a>(s: &'a str) -> &'a str {
    if s == "" { "none" } else { s }
}
<|endoftext|>


<commit_before>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::num::Wrapping;
use std::sync::atomic::{fence, Ordering};

use sys_util::{error, GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

/// An iterator over a single descriptor chain.  Not to be confused with AvailIter,
/// which iterates over the descriptor chain heads in a queue.
pub struct DescIter<'a> {
    next: Option<DescriptorChain<'a>>,
}

impl<'a> DescIter<'a> {
    /// Returns an iterator that only yields the readable descriptors in the chain.
    pub fn readable(self) -> impl Iterator<Item = DescriptorChain<'a>> {
        self.take_while(DescriptorChain::is_read_only)
    }

    /// Returns an iterator that only yields the writable descriptors in the chain.
    pub fn writable(self) -> impl Iterator<Item = DescriptorChain<'a>> {
        self.skip_while(DescriptorChain::is_read_only)
    }
}

impl<'a> Iterator for DescIter<'a> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(current) = self.next.take() {
            self.next = current.next_descriptor();
            Some(current)
        } else {
            None
        }
    }
}

/// A virtio descriptor chain.
#[derive(Clone)]
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    pub(crate) fn checked_new(
        mem: &GuestMemory,
        desc_table: GuestAddress,
        queue_size: u16,
        index: u16,
    ) -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as u64) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as u64);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8)).unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12)).unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14)).unwrap();
        let chain = DescriptorChain {
            mem,
            desc_table,
            queue_size,
            ttl: queue_size,
            index,
            addr,
            len,
            flags,
            next,
        };

        if chain.is_valid() {
            Some(chain)
        } else {
            None
        }
    }

    #[allow(clippy::if_same_then_else)]
    fn is_valid(&self) -> bool {
        if self
            .mem
            .checked_offset(self.addr, self.len as u64)
            .is_none()
        {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    /// Write only means the the emulated device can write and the driver can read.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// If the driver designated this as a read only descriptor.
    ///
    /// If this is false, this descriptor is write only.
    /// Read only means the emulated device can read and the driver can write.
    pub fn is_read_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE == 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next).map(
                |mut c| {
                    c.ttl = self.ttl - 1;
                    c
                },
            )
        } else {
            None
        }
    }

    /// Produces an iterator over all the descriptors in this chain.
    pub fn into_iter(self) -> DescIter<'a> {
        DescIter { next: Some(self) }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    queue: &'b mut Queue,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        self.queue.pop(self.mem)
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: Wrapping<u16>,
    next_used: Wrapping<u16>,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size,
            size: max_size,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: Wrapping(0),
            next_used: Wrapping(0),
        }
    }

    /// Return the actual size of the queue, as the driver may not set up a
    /// queue as big as the device allows.
    pub fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    pub fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            error!("attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 || (self.size & (self.size - 1)) != 0
        {
            error!("virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
            .checked_add(desc_table_size as u64)
            .map_or(true, |v| !mem.address_in_range(v))
        {
            error!(
                "virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                desc_table.offset(),
                desc_table_size
            );
            false
        } else if avail_ring
            .checked_add(avail_ring_size as u64)
            .map_or(true, |v| !mem.address_in_range(v))
        {
            error!(
                "virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                avail_ring.offset(),
                avail_ring_size
            );
            false
        } else if used_ring
            .checked_add(used_ring_size as u64)
            .map_or(true, |v| !mem.address_in_range(v))
        {
            error!(
                "virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                used_ring.offset(),
                used_ring_size
            );
            false
        } else {
            true
        }
    }

    /// If a new DescriptorHead is available, returns one and removes it from the queue.
    pub fn pop<'a>(&mut self, mem: &'a GuestMemory) -> Option<DescriptorChain<'a>> {
        if !self.is_valid(mem) {
            return None;
        }

        let queue_size = self.actual_size();
        let avail_index_addr = mem.checked_offset(self.avail_ring, 2).unwrap();
        let avail_index: u16 = mem.read_obj_from_addr(avail_index_addr).unwrap();
        let avail_len = Wrapping(avail_index) - self.next_avail;

        if avail_len.0 > queue_size || self.next_avail == Wrapping(avail_index) {
            return None;
        }

        let desc_idx_addr_offset = (4 + (self.next_avail.0 % queue_size) * 2) as u64;
        let desc_idx_addr = mem.checked_offset(self.avail_ring, desc_idx_addr_offset)?;

        // This index is checked below in checked_new.
        let descriptor_index: u16 = mem.read_obj_from_addr(desc_idx_addr).unwrap();

        let descriptor_chain =
            DescriptorChain::checked_new(mem, self.desc_table, queue_size, descriptor_index);
        if descriptor_chain.is_some() {
            self.next_avail += Wrapping(1);
        }
        descriptor_chain
    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        AvailIter { mem, queue: self }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            error!(
                "attempted to add out of bounds descriptor to used ring: {}",
                desc_index
            );
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used.0 % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add((4 + next_used * 8) as u64);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem).unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        mem.write_obj_at_addr(self.next_used.0 as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<commit_msg>devices: fix virtio-queue range check<commit_after>// Copyright 2017 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::cmp::min;
use std::num::Wrapping;
use std::sync::atomic::{fence, Ordering};

use sys_util::{error, GuestAddress, GuestMemory};

const VIRTQ_DESC_F_NEXT: u16 = 0x1;
const VIRTQ_DESC_F_WRITE: u16 = 0x2;
#[allow(dead_code)]
const VIRTQ_DESC_F_INDIRECT: u16 = 0x4;

/// An iterator over a single descriptor chain.  Not to be confused with AvailIter,
/// which iterates over the descriptor chain heads in a queue.
pub struct DescIter<'a> {
    next: Option<DescriptorChain<'a>>,
}

impl<'a> DescIter<'a> {
    /// Returns an iterator that only yields the readable descriptors in the chain.
    pub fn readable(self) -> impl Iterator<Item = DescriptorChain<'a>> {
        self.take_while(DescriptorChain::is_read_only)
    }

    /// Returns an iterator that only yields the writable descriptors in the chain.
    pub fn writable(self) -> impl Iterator<Item = DescriptorChain<'a>> {
        self.skip_while(DescriptorChain::is_read_only)
    }
}

impl<'a> Iterator for DescIter<'a> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(current) = self.next.take() {
            self.next = current.next_descriptor();
            Some(current)
        } else {
            None
        }
    }
}

/// A virtio descriptor chain.
#[derive(Clone)]
pub struct DescriptorChain<'a> {
    mem: &'a GuestMemory,
    desc_table: GuestAddress,
    queue_size: u16,
    ttl: u16, // used to prevent infinite chain cycles

    /// Index into the descriptor table
    pub index: u16,

    /// Guest physical address of device specific data
    pub addr: GuestAddress,

    /// Length of device specific data
    pub len: u32,

    /// Includes next, write, and indirect bits
    pub flags: u16,

    /// Index into the descriptor table of the next descriptor if flags has
    /// the next bit set
    pub next: u16,
}

impl<'a> DescriptorChain<'a> {
    pub(crate) fn checked_new(
        mem: &GuestMemory,
        desc_table: GuestAddress,
        queue_size: u16,
        index: u16,
    ) -> Option<DescriptorChain> {
        if index >= queue_size {
            return None;
        }

        let desc_head = match mem.checked_offset(desc_table, (index as u64) * 16) {
            Some(a) => a,
            None => return None,
        };
        // These reads can't fail unless Guest memory is hopelessly broken.
        let addr = GuestAddress(mem.read_obj_from_addr::<u64>(desc_head).unwrap() as u64);
        if mem.checked_offset(desc_head, 16).is_none() {
            return None;
        }
        let len: u32 = mem.read_obj_from_addr(desc_head.unchecked_add(8)).unwrap();
        let flags: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(12)).unwrap();
        let next: u16 = mem.read_obj_from_addr(desc_head.unchecked_add(14)).unwrap();
        let chain = DescriptorChain {
            mem,
            desc_table,
            queue_size,
            ttl: queue_size,
            index,
            addr,
            len,
            flags,
            next,
        };

        if chain.is_valid() {
            Some(chain)
        } else {
            None
        }
    }

    #[allow(clippy::if_same_then_else)]
    fn is_valid(&self) -> bool {
        if self.len > 0
            && self
                .mem
                .checked_offset(self.addr, self.len as u64 - 1u64)
                .is_none()
        {
            false
        } else if self.has_next() && self.next >= self.queue_size {
            false
        } else {
            true
        }
    }

    /// Gets if this descriptor chain has another descriptor chain linked after it.
    pub fn has_next(&self) -> bool {
        self.flags & VIRTQ_DESC_F_NEXT != 0 && self.ttl > 1
    }

    /// If the driver designated this as a write only descriptor.
    ///
    /// If this is false, this descriptor is read only.
    /// Write only means the the emulated device can write and the driver can read.
    pub fn is_write_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE != 0
    }

    /// If the driver designated this as a read only descriptor.
    ///
    /// If this is false, this descriptor is write only.
    /// Read only means the emulated device can read and the driver can write.
    pub fn is_read_only(&self) -> bool {
        self.flags & VIRTQ_DESC_F_WRITE == 0
    }

    /// Gets the next descriptor in this descriptor chain, if there is one.
    ///
    /// Note that this is distinct from the next descriptor chain returned by `AvailIter`, which is
    /// the head of the next _available_ descriptor chain.
    pub fn next_descriptor(&self) -> Option<DescriptorChain<'a>> {
        if self.has_next() {
            DescriptorChain::checked_new(self.mem, self.desc_table, self.queue_size, self.next).map(
                |mut c| {
                    c.ttl = self.ttl - 1;
                    c
                },
            )
        } else {
            None
        }
    }

    /// Produces an iterator over all the descriptors in this chain.
    pub fn into_iter(self) -> DescIter<'a> {
        DescIter { next: Some(self) }
    }
}

/// Consuming iterator over all available descriptor chain heads in the queue.
pub struct AvailIter<'a, 'b> {
    mem: &'a GuestMemory,
    queue: &'b mut Queue,
}

impl<'a, 'b> Iterator for AvailIter<'a, 'b> {
    type Item = DescriptorChain<'a>;

    fn next(&mut self) -> Option<Self::Item> {
        self.queue.pop(self.mem)
    }
}

#[derive(Clone)]
/// A virtio queue's parameters.
pub struct Queue {
    /// The maximal size in elements offered by the device
    pub max_size: u16,

    /// The queue size in elements the driver selected
    pub size: u16,

    /// Inidcates if the queue is finished with configuration
    pub ready: bool,

    /// Guest physical address of the descriptor table
    pub desc_table: GuestAddress,

    /// Guest physical address of the available ring
    pub avail_ring: GuestAddress,

    /// Guest physical address of the used ring
    pub used_ring: GuestAddress,

    next_avail: Wrapping<u16>,
    next_used: Wrapping<u16>,
}

impl Queue {
    /// Constructs an empty virtio queue with the given `max_size`.
    pub fn new(max_size: u16) -> Queue {
        Queue {
            max_size,
            size: max_size,
            ready: false,
            desc_table: GuestAddress(0),
            avail_ring: GuestAddress(0),
            used_ring: GuestAddress(0),
            next_avail: Wrapping(0),
            next_used: Wrapping(0),
        }
    }

    /// Return the actual size of the queue, as the driver may not set up a
    /// queue as big as the device allows.
    pub fn actual_size(&self) -> u16 {
        min(self.size, self.max_size)
    }

    pub fn is_valid(&self, mem: &GuestMemory) -> bool {
        let queue_size = self.actual_size() as usize;
        let desc_table = self.desc_table;
        let desc_table_size = 16 * queue_size;
        let avail_ring = self.avail_ring;
        let avail_ring_size = 6 + 2 * queue_size;
        let used_ring = self.used_ring;
        let used_ring_size = 6 + 8 * queue_size;
        if !self.ready {
            error!("attempt to use virtio queue that is not marked ready");
            false
        } else if self.size > self.max_size || self.size == 0 || (self.size & (self.size - 1)) != 0
        {
            error!("virtio queue with invalid size: {}", self.size);
            false
        } else if desc_table
            .checked_add(desc_table_size as u64)
            .map_or(true, |v| !mem.address_in_range(v))
        {
            error!(
                "virtio queue descriptor table goes out of bounds: start:0x{:08x} size:0x{:08x}",
                desc_table.offset(),
                desc_table_size
            );
            false
        } else if avail_ring
            .checked_add(avail_ring_size as u64)
            .map_or(true, |v| !mem.address_in_range(v))
        {
            error!(
                "virtio queue available ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                avail_ring.offset(),
                avail_ring_size
            );
            false
        } else if used_ring
            .checked_add(used_ring_size as u64)
            .map_or(true, |v| !mem.address_in_range(v))
        {
            error!(
                "virtio queue used ring goes out of bounds: start:0x{:08x} size:0x{:08x}",
                used_ring.offset(),
                used_ring_size
            );
            false
        } else {
            true
        }
    }

    /// If a new DescriptorHead is available, returns one and removes it from the queue.
    pub fn pop<'a>(&mut self, mem: &'a GuestMemory) -> Option<DescriptorChain<'a>> {
        if !self.is_valid(mem) {
            return None;
        }

        let queue_size = self.actual_size();
        let avail_index_addr = mem.checked_offset(self.avail_ring, 2).unwrap();
        let avail_index: u16 = mem.read_obj_from_addr(avail_index_addr).unwrap();
        let avail_len = Wrapping(avail_index) - self.next_avail;

        if avail_len.0 > queue_size || self.next_avail == Wrapping(avail_index) {
            return None;
        }

        let desc_idx_addr_offset = (4 + (self.next_avail.0 % queue_size) * 2) as u64;
        let desc_idx_addr = mem.checked_offset(self.avail_ring, desc_idx_addr_offset)?;

        // This index is checked below in checked_new.
        let descriptor_index: u16 = mem.read_obj_from_addr(desc_idx_addr).unwrap();

        let descriptor_chain =
            DescriptorChain::checked_new(mem, self.desc_table, queue_size, descriptor_index);
        if descriptor_chain.is_some() {
            self.next_avail += Wrapping(1);
        }
        descriptor_chain
    }

    /// A consuming iterator over all available descriptor chain heads offered by the driver.
    pub fn iter<'a, 'b>(&'b mut self, mem: &'a GuestMemory) -> AvailIter<'a, 'b> {
        AvailIter { mem, queue: self }
    }

    /// Puts an available descriptor head into the used ring for use by the guest.
    pub fn add_used(&mut self, mem: &GuestMemory, desc_index: u16, len: u32) {
        if desc_index >= self.actual_size() {
            error!(
                "attempted to add out of bounds descriptor to used ring: {}",
                desc_index
            );
            return;
        }

        let used_ring = self.used_ring;
        let next_used = (self.next_used.0 % self.actual_size()) as usize;
        let used_elem = used_ring.unchecked_add((4 + next_used * 8) as u64);

        // These writes can't fail as we are guaranteed to be within the descriptor ring.
        mem.write_obj_at_addr(desc_index as u32, used_elem).unwrap();
        mem.write_obj_at_addr(len as u32, used_elem.unchecked_add(4))
            .unwrap();

        self.next_used += Wrapping(1);

        // This fence ensures all descriptor writes are visible before the index update is.
        fence(Ordering::Release);

        mem.write_obj_at_addr(self.next_used.0 as u16, used_ring.unchecked_add(2))
            .unwrap();
    }
}
<|endoftext|>


<commit_before>
use std::io;
use std::slice::Iter;

use parser::ast::*;
use processing::structs::*;
use output::scope::*;
use output::client_ops_writer::*;

#[inline]
pub fn write_js_var_reference(w: &mut io::Write,
                                    var_name: Option<&str>,
                                    doc: &DocumentState,
                                    scope_prefixes: &ScopePrefixes)
                                    -> Result {
    let default_var_scope = scope_prefixes.default_var_scope();
    if let Some(ref var_name) = var_name {
        let var_key = scope_prefixes.var_prefix(var_name);
        write!(w, "{}", var_key)?;
    } else {
        let default_var_scope = scope_prefixes.default_var_scope();
        let default_var = scope_prefixes.default_var();
        let var_key = default_var_scope
            .or_else(|| default_var)
            .unwrap_or("default".to_owned());
        write!(w, "{}", var_key)?;
    };

    // let state_key = "".to_owned();
    // let state_key = scope.state_lookup_key(var_name);
    // let is_scope_key = state_key.map_or(false, |s| doc.default_state_map.contains_key(s.as_str()));
    // let var_reference = scope.var_reference(is_scope_key, var_name);
    // write!(w, "{}", var_reference)?;
    // write!(w, "{}", var_key)?;
    Ok(())
}

#[inline]
pub fn write_js_expr_value(w: &mut io::Write,
                                node: &ExprValue,
                                doc: &DocumentState,
                                scope_prefixes: &ScopePrefixes)
                                -> Result {
    match node {
        // TODO: Handle the case where quotes appear in the string
        &ExprValue::LiteralString(ref s) => {
            write!(w, "\"{}\"", s)?;
        }
        &ExprValue::LiteralNumber(ref n) => {
            write!(w, "{}", n)?;
        }

        &ExprValue::LiteralArray(ref items) => {
            if let &Some(ref items) = items {
                write!(w, "[")?;
                for ref item in items {
                    write_js_expr_value(w, item, doc, scope_prefixes)?;
                }
                write!(w, "]")?;
            };
        }

        &ExprValue::DefaultVariableReference => {
            write_js_var_reference(w, None, doc, scope_prefixes)?;
        }

        &ExprValue::VariableReference(ref var_name) => {
            write_js_var_reference(w, Some(var_name.as_str()), doc, scope_prefixes)?;
        }

        &ExprValue::SymbolReference(ref sym) => {
            match sym {
                &(Some(ref sym), _) => {
                    match sym {
                        &SymbolReferenceType::LocalVarReference(ref var_name) => {
                            write_js_var_reference(w, Some(var_name.as_str()), doc, scope_prefixes)?;
                        }

                        &SymbolReferenceType::ParameterReference(ref param_key) => {
                            write_js_var_reference(w, Some(param_key.as_str()), doc, scope_prefixes)?;
                        }

                        &SymbolReferenceType::ReducerKeyReference(ref as_reducer_key) => {
                            write_js_var_reference(w, Some(as_reducer_key.as_str()), doc, scope_prefixes)?;
                        }

                        _ => {}
                    };
                }
                _ => {}
            };
        }

        // &ExprValue::Expr(ExprOp::Add, box ExprValue::DefaultVariableReference, ref r) => {
        //     // let state_ty = scope().unwrap().state_lookup_key(None);
        //     // let state_ty = state_ty.map_or(None, |s| doc.default_state_map.get(s.as_str()));

        //     // write!(w, "(")?;
        //     // write_js_var_reference(w, None, doc, scope)?;
        //     // if let Some(&(Some(VarType::ArrayVar(..)), _)) = state_ty {
        //     //     write!(w, ").concat(")?;
        //     // } else {
        //     //     write!(w, "+ (")?;
        //     // }
        //     // write_js_expr_value(w, r, doc, scope)?;
        //     // write!(w, ")")?;

        //     // let state_ty = scope().unwrap().state_lookup_key(None);
        //     // let state_ty = state_ty.map_or(None, |s| doc.default_state_map.get(s.as_str()));
        //     write!(w, "(")?;
        //     let
        //     write_js_expr_value(w, ExprValue::DefaultVariableReference, doc, scope_prefixes)?;
        //     // write_js_var_reference(w, None, doc, scope_prefixes)?;
        //     // if let Some(&(Some(VarType::ArrayVar(..)), _)) = state_ty {
        //         write!(w, ").concat(")?;
        //     // } else {
        //         // write!(w, "+ (")?;
        //     // }
        //     write_js_expr_value(w, r, doc, scope_prefixes)?;
        //     write!(w, ")")?;
        // }

        // &ExprValue::Expr(ExprOp::Add, box ExprValue::VariableReference(ref var_name), ref r) => {
        //     // let state_ty = scope.state_lookup_key(Some(var_name.as_str())).as_ref()
        //     //     .map_or(None, |s| doc.default_state_map.get(s.as_str()));

        //     // write!(w, "(")?;
        //     // write_js_var_reference(w, None, doc, scope)?;
        //     // if let Some(&(Some(VarType::ArrayVar(..)), _)) = state_ty {
        //     //     write!(w, ").concat(")?;
        //     // } else {
        //     //     write!(w, "+ (")?;
        //     // }
        //     // write_js_expr_value(w, r, doc, scope)?;
        //     // write!(w, ")")?;
        // }

        &ExprValue::Expr(ref sym, ref l, ref r) => {
            write!(w, "(")?;
            write_js_expr_value(w, l, doc, scope_prefixes)?;
            match sym {
                &ExprOp::Add => {
                    write!(w, ").concat(")?;
                    // write!(w, " + ")?;
                }
                &ExprOp::Sub => {
                    write!(w, " - ")?;
                }
                &ExprOp::Mul => {
                    write!(w, " * ")?;
                }
                &ExprOp::Div => {
                    write!(w, " / ")?;
                }
            }
            write_js_expr_value(w, r, doc, scope_prefixes)?;
            write!(w, ")")?;
        }

        &ExprValue::ContentNode(..) => {}
        &ExprValue::DefaultAction(..) => {}
        &ExprValue::Action(..) => {}
    }
    Ok(())
}

#[inline]
#[allow(unused_variables)]
pub fn write_js_props_object<'input>(w: &mut io::Write,
                                props: Option<Iter<'input, Prop>>,
                                doc: &DocumentState,
                                scope_prefixes: &ScopePrefixes)
                        -> Result {
    write!(w, "{{")?;
    let mut wrote_first = false;
    if let Some(props) = props {
        for &(ref key, ref expr) in props {
            if wrote_first {
                write!(w, ", ")?
            } else {
                wrote_first = true;
            }

            // Write the property name
            write!(w, "\"{}\": ", key)?;

            // Write the property value or undefined for None
            if let &Some(ref expr) = expr {

                if let &ExprValue::DefaultAction(ref params, ref act_ops) = expr {
                    write!(w, "\"{}\", ", key)?;
                    write!(w, "function(event) {{")?;
                    if let &Some(ref act_ops) = act_ops {
                        for ref act_op in act_ops {
                            match *act_op {
                                &ActionOpNode::DispatchAction(ref action, ref params) => {
                                    write!(w, " store.dispatch({{\"type\": \"{}\"}}); ", action)?;
                                }
                            }
                        }
                    }
                    write!(w, "}}")?;
                    continue;
                };

                write_js_expr_value(w,
                                    &expr,
                                    doc,
                                    scope_prefixes)?;

            } else {
                write!(w, "undefined")?;
            }
        }
    };
    write!(w, "}}")?;
    Ok(())
}

#[inline]
#[allow(dead_code)]
#[allow(unused_variables)]
pub fn write_js_incdom_attr_array<'input>(w: &mut io::Write,
                                    attrs: Option<Iter<'input, Prop>>,
                                    doc: &DocumentState,
                                    scope_prefixes: &ScopePrefixes,
                                    base_key: Option<&str>)
                                    -> Result {
    let mut wrote_first = false;
    if let Some(base_key) = base_key {
        write!(w, "\"data-id\", \"{}\", ", base_key)?;
    };

    if let Some(attrs) = attrs {
        for &(ref key, ref expr) in attrs {
            if let &Some(ref expr) = expr {
                if wrote_first {
                    write!(w, ", ")?
                } else {
                    wrote_first = true;
                }

                if let &ExprValue::DefaultAction(ref params, ref act_ops) = expr {
                    write!(w, "\"{}\", ", key)?;
                    write!(w, "function(event) {{")?;
                    if let &Some(ref act_ops) = act_ops {
                        for ref act_op in act_ops {
                            match *act_op {
                                &ActionOpNode::DispatchAction(ref action, ref params) => {
                                    write!(w, " store.dispatch({{\"type\": \"{}\"}}); ", action)?;
                                }
                            }
                        }
                    }
                    write!(w, "}}")?;
                    continue;
                };

                write!(w, "\"{}\", ", key)?;
                write_js_expr_value(w, expr, doc, scope_prefixes)?;
            } else {
                write!(w, "\"{}\", ", key)?;
                write!(w, "undefined")?;
            }
        }
    };
    Ok(())
}<commit_msg>Stop hardcoded array concat when we have a type<commit_after>
use std::io;
use std::slice::Iter;

use parser::ast::*;
use processing::structs::*;
use output::scope::*;
use output::client_ops_writer::*;

#[inline]
pub fn write_js_var_reference(w: &mut io::Write,
                                    var_name: Option<&str>,
                                    doc: &DocumentState,
                                    scope_prefixes: &ScopePrefixes)
                                    -> Result {
    let default_var_scope = scope_prefixes.default_var_scope();
    if let Some(ref var_name) = var_name {
        let var_key = scope_prefixes.var_prefix(var_name);
        write!(w, "{}", var_key)?;
    } else {
        let default_var_scope = scope_prefixes.default_var_scope();
        let default_var = scope_prefixes.default_var();
        let var_key = default_var_scope
            .or_else(|| default_var)
            .unwrap_or("default".to_owned());
        write!(w, "{}", var_key)?;
    };

    // let state_key = "".to_owned();
    // let state_key = scope.state_lookup_key(var_name);
    // let is_scope_key = state_key.map_or(false, |s| doc.default_state_map.contains_key(s.as_str()));
    // let var_reference = scope.var_reference(is_scope_key, var_name);
    // write!(w, "{}", var_reference)?;
    // write!(w, "{}", var_key)?;
    Ok(())
}

#[inline]
pub fn write_js_expr_value(w: &mut io::Write,
                                node: &ExprValue,
                                doc: &DocumentState,
                                scope_prefixes: &ScopePrefixes)
                                -> Result {
    match node {
        // TODO: Handle the case where quotes appear in the string
        &ExprValue::LiteralString(ref s) => {
            write!(w, "\"{}\"", s)?;
        }
        &ExprValue::LiteralNumber(ref n) => {
            write!(w, "{}", n)?;
        }

        &ExprValue::LiteralArray(ref items) => {
            if let &Some(ref items) = items {
                write!(w, "[")?;
                for ref item in items {
                    write_js_expr_value(w, item, doc, scope_prefixes)?;
                }
                write!(w, "]")?;
            };
        }

        &ExprValue::DefaultVariableReference => {
            write_js_var_reference(w, None, doc, scope_prefixes)?;
        }

        &ExprValue::VariableReference(ref var_name) => {
            write_js_var_reference(w, Some(var_name.as_str()), doc, scope_prefixes)?;
        }

        &ExprValue::SymbolReference(ref sym) => {
            match sym {
                &(Some(ref sym), _) => {
                    match sym {
                        &SymbolReferenceType::LocalVarReference(ref var_name) => {
                            write_js_var_reference(w, Some(var_name.as_str()), doc, scope_prefixes)?;
                        }

                        &SymbolReferenceType::ParameterReference(ref param_key) => {
                            write_js_var_reference(w, Some(param_key.as_str()), doc, scope_prefixes)?;
                        }

                        &SymbolReferenceType::ReducerKeyReference(ref as_reducer_key) => {
                            write_js_var_reference(w, Some(as_reducer_key.as_str()), doc, scope_prefixes)?;
                        }

                        _ => {}
                    };
                }
                _ => {}
            };
        }

        // &ExprValue::Expr(ExprOp::Add, box ExprValue::DefaultVariableReference, ref r) => {
        //     // let state_ty = scope().unwrap().state_lookup_key(None);
        //     // let state_ty = state_ty.map_or(None, |s| doc.default_state_map.get(s.as_str()));

        //     // write!(w, "(")?;
        //     // write_js_var_reference(w, None, doc, scope)?;
        //     // if let Some(&(Some(VarType::ArrayVar(..)), _)) = state_ty {
        //     //     write!(w, ").concat(")?;
        //     // } else {
        //     //     write!(w, "+ (")?;
        //     // }
        //     // write_js_expr_value(w, r, doc, scope)?;
        //     // write!(w, ")")?;

        //     // let state_ty = scope().unwrap().state_lookup_key(None);
        //     // let state_ty = state_ty.map_or(None, |s| doc.default_state_map.get(s.as_str()));
        //     write!(w, "(")?;
        //     let
        //     write_js_expr_value(w, ExprValue::DefaultVariableReference, doc, scope_prefixes)?;
        //     // write_js_var_reference(w, None, doc, scope_prefixes)?;
        //     // if let Some(&(Some(VarType::ArrayVar(..)), _)) = state_ty {
        //         write!(w, ").concat(")?;
        //     // } else {
        //         // write!(w, "+ (")?;
        //     // }
        //     write_js_expr_value(w, r, doc, scope_prefixes)?;
        //     write!(w, ")")?;
        // }

        // &ExprValue::Expr(ExprOp::Add, box ExprValue::VariableReference(ref var_name), ref r) => {
        //     // let state_ty = scope.state_lookup_key(Some(var_name.as_str())).as_ref()
        //     //     .map_or(None, |s| doc.default_state_map.get(s.as_str()));

        //     // write!(w, "(")?;
        //     // write_js_var_reference(w, None, doc, scope)?;
        //     // if let Some(&(Some(VarType::ArrayVar(..)), _)) = state_ty {
        //     //     write!(w, ").concat(")?;
        //     // } else {
        //     //     write!(w, "+ (")?;
        //     // }
        //     // write_js_expr_value(w, r, doc, scope)?;
        //     // write!(w, ")")?;
        // }

        &ExprValue::Expr(ref op, box ExprValue::SymbolReference(ref l_sym), ref r) => {
            let is_array = match l_sym {
                &(Some(_), Some(VarType::ArrayVar(_))) => true,
                _ => false
            };

            match op {
                &ExprOp::Add if is_array => write!(w, ").concat("),
                &ExprOp::Add => write!(w, " + "),
                &ExprOp::Sub => write!(w, " - "),
                &ExprOp::Mul => write!(w, " * "),
                &ExprOp::Div => write!(w, " / ")
            }?;

            write_js_expr_value(w, r, doc, scope_prefixes)?;
            if is_array {
                write!(w, ")")?;
            };
        }

        &ExprValue::Expr(ref sym, ref l, ref r) => {
            write!(w, "(")?;
            write_js_expr_value(w, l, doc, scope_prefixes)?;
            match sym {
                &ExprOp::Add => {
                    write!(w, ").concat(")?;
                    // write!(w, " + ")?;
                }
                &ExprOp::Sub => {
                    write!(w, " - ")?;
                }
                &ExprOp::Mul => {
                    write!(w, " * ")?;
                }
                &ExprOp::Div => {
                    write!(w, " / ")?;
                }
            }
            write_js_expr_value(w, r, doc, scope_prefixes)?;
            write!(w, ")")?;
        }

        &ExprValue::ContentNode(..) => {}
        &ExprValue::DefaultAction(..) => {}
        &ExprValue::Action(..) => {}
    }
    Ok(())
}

#[inline]
#[allow(unused_variables)]
pub fn write_js_props_object<'input>(w: &mut io::Write,
                                props: Option<Iter<'input, Prop>>,
                                doc: &DocumentState,
                                scope_prefixes: &ScopePrefixes)
                        -> Result {
    write!(w, "{{")?;
    let mut wrote_first = false;
    if let Some(props) = props {
        for &(ref key, ref expr) in props {
            if wrote_first {
                write!(w, ", ")?
            } else {
                wrote_first = true;
            }

            // Write the property name
            write!(w, "\"{}\": ", key)?;

            // Write the property value or undefined for None
            if let &Some(ref expr) = expr {

                if let &ExprValue::DefaultAction(ref params, ref act_ops) = expr {
                    write!(w, "\"{}\", ", key)?;
                    write!(w, "function(event) {{")?;
                    if let &Some(ref act_ops) = act_ops {
                        for ref act_op in act_ops {
                            match *act_op {
                                &ActionOpNode::DispatchAction(ref action, ref params) => {
                                    write!(w, " store.dispatch({{\"type\": \"{}\"}}); ", action)?;
                                }
                            }
                        }
                    }
                    write!(w, "}}")?;
                    continue;
                };

                write_js_expr_value(w,
                                    &expr,
                                    doc,
                                    scope_prefixes)?;

            } else {
                write!(w, "undefined")?;
            }
        }
    };
    write!(w, "}}")?;
    Ok(())
}

#[inline]
#[allow(dead_code)]
#[allow(unused_variables)]
pub fn write_js_incdom_attr_array<'input>(w: &mut io::Write,
                                    attrs: Option<Iter<'input, Prop>>,
                                    doc: &DocumentState,
                                    scope_prefixes: &ScopePrefixes,
                                    base_key: Option<&str>)
                                    -> Result {
    let mut wrote_first = false;
    if let Some(base_key) = base_key {
        write!(w, "\"data-id\", \"{}\", ", base_key)?;
    };

    if let Some(attrs) = attrs {
        for &(ref key, ref expr) in attrs {
            if let &Some(ref expr) = expr {
                if wrote_first {
                    write!(w, ", ")?
                } else {
                    wrote_first = true;
                }

                if let &ExprValue::DefaultAction(ref params, ref act_ops) = expr {
                    write!(w, "\"{}\", ", key)?;
                    write!(w, "function(event) {{")?;
                    if let &Some(ref act_ops) = act_ops {
                        for ref act_op in act_ops {
                            match *act_op {
                                &ActionOpNode::DispatchAction(ref action, ref params) => {
                                    write!(w, " store.dispatch({{\"type\": \"{}\"}}); ", action)?;
                                }
                            }
                        }
                    }
                    write!(w, "}}")?;
                    continue;
                };

                write!(w, "\"{}\", ", key)?;
                write_js_expr_value(w, expr, doc, scope_prefixes)?;
            } else {
                write!(w, "\"{}\", ", key)?;
                write!(w, "undefined")?;
            }
        }
    };
    Ok(())
}<|endoftext|>


<commit_before>use arch::context::Context;
use arch::memory;

use collections::string::ToString;

use common::event::MouseEvent;
use common::time::{self, Duration};

use core::{cmp, mem, ptr, slice};

use graphics::display::VBEMODEINFO;

use super::{Packet, Pipe, Setup};
use super::desc::*;

pub trait Hci {
    fn msg(&mut self, address: u8, endpoint: u8, pipe: Pipe, msgs: &[Packet]) -> usize;

    fn descriptor(&mut self,
                         address: u8,
                         descriptor_type: u8,
                         descriptor_index: u8,
                         descriptor_ptr: usize,
                         descriptor_len: usize) {
        self.msg(address, 0, Pipe::Control, &[
            Packet::Setup(&Setup::get_descriptor(descriptor_type, descriptor_index, 0, descriptor_len as u16)),
            Packet::In(&mut unsafe { slice::from_raw_parts_mut(descriptor_ptr as *mut u8, descriptor_len as usize) }),
            Packet::Out(&[])
        ]);
    }

    unsafe fn device(&mut self, address: u8) where Self: Sized + 'static {
        self.msg(0, 0, Pipe::Control, &[
            Packet::Setup(&Setup::set_address(address)),
            Packet::In(&mut [])
        ]);

        let mut desc_dev = box DeviceDescriptor::default();
        self.descriptor(address,
                        DESC_DEV,
                        0,
                        (&mut *desc_dev as *mut DeviceDescriptor) as usize,
                        mem::size_of_val(&*desc_dev));
        debugln!("{:#?}", *desc_dev);

        if desc_dev.manufacturer_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.manufacturer_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Manufacturer: {}", desc_str.str());
        }

        if desc_dev.product_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.product_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Product: {}", desc_str.str());
        }

        if desc_dev.serial_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.serial_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Serial: {}", desc_str.str());
        }

        for configuration in 0..(*desc_dev).configurations {
            let desc_cfg_len = 1023;
            let desc_cfg_buf = memory::alloc(desc_cfg_len) as *mut u8;
            for i in 0..desc_cfg_len as isize {
                ptr::write(desc_cfg_buf.offset(i), 0);
            }
            self.descriptor(address,
                            DESC_CFG,
                            configuration,
                            desc_cfg_buf as usize,
                            desc_cfg_len);

            let desc_cfg = ptr::read(desc_cfg_buf as *const ConfigDescriptor);
            debugln!("{:#?}", desc_cfg);

            if desc_cfg.string > 0 {
                let mut desc_str = box StringDescriptor::default();
                self.descriptor(address,
                                DESC_STR,
                                desc_cfg.string,
                                (&mut *desc_str as *mut StringDescriptor) as usize,
                                mem::size_of_val(&*desc_str));
                debugln!("Configuration: {}", desc_str.str());
            }

            let mut hid = false;

            let mut i = desc_cfg.length as isize;
            while i < desc_cfg.total_length as isize {
                let length = ptr::read(desc_cfg_buf.offset(i));
                let descriptor_type = ptr::read(desc_cfg_buf.offset(i + 1));
                match descriptor_type {
                    DESC_INT => {
                        let desc_int = ptr::read(desc_cfg_buf.offset(i) as *const InterfaceDescriptor);
                        debugln!("{:#?}", desc_int);

                        if desc_int.string > 0 {
                            let mut desc_str = box StringDescriptor::default();
                            self.descriptor(address,
                                            DESC_STR,
                                            desc_int.string,
                                            (&mut *desc_str as *mut StringDescriptor) as usize,
                                            mem::size_of_val(&*desc_str));
                            debugln!("Interface: {}", desc_str.str());
                        }
                    }
                    DESC_END => {
                        let desc_end = ptr::read(desc_cfg_buf.offset(i) as *const EndpointDescriptor);
                        debugln!("{:#?}", desc_end);

                        let endpoint = desc_end.address & 0xF;
                        let in_len = desc_end.max_packet_size as usize;

                        if hid {
                            let this = self as *mut Hci;
                            Context::spawn("kuhci_hid".to_string(), box move || {
                                debugln!("Starting HID driver");

                                let in_ptr = memory::alloc(in_len) as *mut u8;

                                loop {
                                    for i in 0..in_len as isize {
                                        ptr::write(in_ptr.offset(i), 0);
                                    }

                                    if (*this).msg(address, endpoint, Pipe::Isochronous, &[
                                        Packet::In(&mut slice::from_raw_parts_mut(in_ptr, in_len))
                                    ]) > 0 {
                                        let buttons = ptr::read(in_ptr.offset(0) as *const u8) as usize;
                                        let x = ptr::read(in_ptr.offset(1) as *const u16) as usize;
                                        let y = ptr::read(in_ptr.offset(3) as *const u16) as usize;

                                        let mode_info = &*VBEMODEINFO;
                                        let mouse_x = (x * mode_info.xresolution as usize) / 32768;
                                        let mouse_y = (y * mode_info.yresolution as usize) / 32768;

                                        let mouse_event = MouseEvent {
                                            x: cmp::max(0, cmp::min(mode_info.xresolution as i32 - 1, mouse_x as i32)),
                                            y: cmp::max(0, cmp::min(mode_info.yresolution as i32 - 1, mouse_y as i32)),
                                            left_button: buttons & 1 == 1,
                                            middle_button: buttons & 4 == 4,
                                            right_button: buttons & 2 == 2,
                                        };
                                        ::env().events.lock().push_back(mouse_event.to_event());
                                    }

                                    Duration::new(0, 10 * time::NANOS_PER_MILLI).sleep();
                                }
                            });
                        }
                    }
                    DESC_HID => {
                        let desc_hid = &*(desc_cfg_buf.offset(i) as *const HIDDescriptor);
                        debugln!("{:#?}", desc_hid);
                        hid = true;
                    }
                    _ => {
                        debugln!("Unknown Descriptor Length {} Type {:X}", length as usize, descriptor_type);
                    }
                }
                i += length as isize;
            }

            memory::unalloc(desc_cfg_buf as usize);
        }
    }
}
<commit_msg>Comment out some USB debugging<commit_after>use arch::context::Context;
use arch::memory;

use collections::string::ToString;

use common::event::MouseEvent;
use common::time::{self, Duration};

use core::{cmp, mem, ptr, slice};

use graphics::display::VBEMODEINFO;

use super::{Packet, Pipe, Setup};
use super::desc::*;

pub trait Hci {
    fn msg(&mut self, address: u8, endpoint: u8, pipe: Pipe, msgs: &[Packet]) -> usize;

    fn descriptor(&mut self,
                         address: u8,
                         descriptor_type: u8,
                         descriptor_index: u8,
                         descriptor_ptr: usize,
                         descriptor_len: usize) {
        self.msg(address, 0, Pipe::Control, &[
            Packet::Setup(&Setup::get_descriptor(descriptor_type, descriptor_index, 0, descriptor_len as u16)),
            Packet::In(&mut unsafe { slice::from_raw_parts_mut(descriptor_ptr as *mut u8, descriptor_len as usize) }),
            Packet::Out(&[])
        ]);
    }

    unsafe fn device(&mut self, address: u8) where Self: Sized + 'static {
        self.msg(0, 0, Pipe::Control, &[
            Packet::Setup(&Setup::set_address(address)),
            Packet::In(&mut [])
        ]);

        let mut desc_dev = box DeviceDescriptor::default();
        self.descriptor(address,
                        DESC_DEV,
                        0,
                        (&mut *desc_dev as *mut DeviceDescriptor) as usize,
                        mem::size_of_val(&*desc_dev));
        //debugln!("{:#?}", *desc_dev);

        if desc_dev.manufacturer_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.manufacturer_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Manufacturer: {}", desc_str.str());
        }

        if desc_dev.product_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.product_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Product: {}", desc_str.str());
        }

        if desc_dev.serial_string > 0 {
            let mut desc_str = box StringDescriptor::default();
            self.descriptor(address,
                            DESC_STR,
                            desc_dev.serial_string,
                            (&mut *desc_str as *mut StringDescriptor) as usize,
                            mem::size_of_val(&*desc_str));
            debugln!("Serial: {}", desc_str.str());
        }

        for configuration in 0..(*desc_dev).configurations {
            let desc_cfg_len = 1023;
            let desc_cfg_buf = memory::alloc(desc_cfg_len) as *mut u8;
            for i in 0..desc_cfg_len as isize {
                ptr::write(desc_cfg_buf.offset(i), 0);
            }
            self.descriptor(address,
                            DESC_CFG,
                            configuration,
                            desc_cfg_buf as usize,
                            desc_cfg_len);

            let desc_cfg = ptr::read(desc_cfg_buf as *const ConfigDescriptor);
            //debugln!("{:#?}", desc_cfg);

            if desc_cfg.string > 0 {
                let mut desc_str = box StringDescriptor::default();
                self.descriptor(address,
                                DESC_STR,
                                desc_cfg.string,
                                (&mut *desc_str as *mut StringDescriptor) as usize,
                                mem::size_of_val(&*desc_str));
                //debugln!("Configuration: {}", desc_str.str());
            }

            let mut hid = false;

            let mut i = desc_cfg.length as isize;
            while i < desc_cfg.total_length as isize {
                let length = ptr::read(desc_cfg_buf.offset(i));
                let descriptor_type = ptr::read(desc_cfg_buf.offset(i + 1));
                match descriptor_type {
                    DESC_INT => {
                        let desc_int = ptr::read(desc_cfg_buf.offset(i) as *const InterfaceDescriptor);
                        //debugln!("{:#?}", desc_int);

                        if desc_int.string > 0 {
                            let mut desc_str = box StringDescriptor::default();
                            self.descriptor(address,
                                            DESC_STR,
                                            desc_int.string,
                                            (&mut *desc_str as *mut StringDescriptor) as usize,
                                            mem::size_of_val(&*desc_str));
                            //debugln!("Interface: {}", desc_str.str());
                        }
                    }
                    DESC_END => {
                        let desc_end = ptr::read(desc_cfg_buf.offset(i) as *const EndpointDescriptor);
                        //debugln!("{:#?}", desc_end);

                        let endpoint = desc_end.address & 0xF;
                        let in_len = desc_end.max_packet_size as usize;

                        if hid {
                            let this = self as *mut Hci;
                            Context::spawn("kuhci_hid".to_string(), box move || {
                                debugln!("Starting HID driver");

                                let in_ptr = memory::alloc(in_len) as *mut u8;

                                loop {
                                    for i in 0..in_len as isize {
                                        ptr::write(in_ptr.offset(i), 0);
                                    }

                                    if (*this).msg(address, endpoint, Pipe::Isochronous, &[
                                        Packet::In(&mut slice::from_raw_parts_mut(in_ptr, in_len))
                                    ]) > 0 {
                                        let buttons = ptr::read(in_ptr.offset(0) as *const u8) as usize;
                                        let x = ptr::read(in_ptr.offset(1) as *const u16) as usize;
                                        let y = ptr::read(in_ptr.offset(3) as *const u16) as usize;

                                        let mode_info = &*VBEMODEINFO;
                                        let mouse_x = (x * mode_info.xresolution as usize) / 32768;
                                        let mouse_y = (y * mode_info.yresolution as usize) / 32768;

                                        let mouse_event = MouseEvent {
                                            x: cmp::max(0, cmp::min(mode_info.xresolution as i32 - 1, mouse_x as i32)),
                                            y: cmp::max(0, cmp::min(mode_info.yresolution as i32 - 1, mouse_y as i32)),
                                            left_button: buttons & 1 == 1,
                                            middle_button: buttons & 4 == 4,
                                            right_button: buttons & 2 == 2,
                                        };
                                        ::env().events.lock().push_back(mouse_event.to_event());
                                    }

                                    Duration::new(0, 10 * time::NANOS_PER_MILLI).sleep();
                                }
                            });
                        }
                    }
                    DESC_HID => {
                        //let desc_hid = &*(desc_cfg_buf.offset(i) as *const HIDDescriptor);
                        //debugln!("{:#?}", desc_hid);
                        hid = true;
                    }
                    _ => {
                        debugln!("Unknown Descriptor Length {} Type {:X}", length as usize, descriptor_type);
                    }
                }
                i += length as isize;
            }

            memory::unalloc(desc_cfg_buf as usize);
        }
    }
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

use std::io::prelude::*;
use std::fs::File;
use std::error::Error;

#[derive(Debug, PartialEq, Eq)]
enum ParseExpansionError {
    BadChar { expected: char, got: char },
    BadInt(std::num::ParseIntError),
    NotEnoughInput,
}

impl std::fmt::Display for ParseExpansionError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match *self {
            ParseExpansionError::BadChar { expected: ref e, got: ref g } => {
                write!(f, "Expected {}, got {}", e, g)
            }
            ParseExpansionError::BadInt(ref e) => write!(f, "{}", e),
            ParseExpansionError::NotEnoughInput => {
                write!(f, "Not enough input")
            }
        }
    }
}

impl Error for ParseExpansionError {
    fn description(&self) -> &str {
        "Could not parse Expansion"
    }
    fn cause(&self) -> Option<&Error> {
        match *self {
            ParseExpansionError::BadInt(ref e) => Some(e),
            _ => None,
        }
    }
}

impl From<std::num::ParseIntError> for ParseExpansionError {
    fn from(err: std::num::ParseIntError) -> Self {
        ParseExpansionError::BadInt(err)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Expansion {
    width: usize,
    repetitions: usize,
}

fn read_expansion(input: &[u8])
                  -> Result<(Expansion, usize), ParseExpansionError> {
    use ParseExpansionError::*;
    // read '('
    if input.len() == 0 {
        return Err(NotEnoughInput);
    } else if input[0] != '(' as u8 {
        return Err(BadChar {
            expected: '(',
            got: input[0] as char,
        });
    }
    // read `width`
    let mut idx = 1;
    while idx < input.len() && (input[idx] as char).is_digit(10) {
        idx += 1;
    }
    let width = std::str::from_utf8(&input[1..idx]).unwrap().parse()?;
    // read 'x'
    if input.len() < idx + 1 {
        return Err(NotEnoughInput);
    } else if input[idx] != 'x' as u8 {
        return Err(BadChar {
            expected: 'x',
            got: input[idx] as char,
        });
    }
    // read `repetitions`
    idx += 1;
    let repititions_start = idx;
    while idx < input.len() && (input[idx] as char).is_digit(10) {
        idx += 1;
    }
    let repetitions =
        std::str::from_utf8(&input[repititions_start..idx]).unwrap().parse()?;
    if input.len() < idx + 1 {
        return Err(NotEnoughInput);
    } else if input[idx] != ')' as u8 {
        return Err(BadChar {
            expected: ')',
            got: input[idx] as char,
        });
    }
    Ok((Expansion {
        width: width,
        repetitions: repetitions,
    },
        idx + 1))
}

fn decompress_a(input: &[u8]) -> Vec<u8> {
    let mut out = Vec::new();
    let mut idx = 0;
    while idx < input.len() {
        if let Ok((Expansion { width, repetitions }, exp_len)) =
               read_expansion(&input[idx..]) {
            idx += exp_len;
            for _ in 0..repetitions {
                out.extend_from_slice(&input[idx..idx +
                                                  std::cmp::min(width,
                                                                input.len() -
                                                                idx)]);
            }
            idx += width;
        } else {
            out.push(input[idx]);
            idx += 1;
        }
    }
    out
}

fn decompressed_b_len(input: &[u8]) -> usize {
    let mut len = 0;
    let mut idx = 0;
    while idx < input.len() {
        if let Ok((Expansion { width, repetitions }, exp_len)) =
               read_expansion(&input[idx..]) {
            idx += exp_len;
            let sub_len =
                decompressed_b_len(&input[idx..idx +
                                               std::cmp::min(width,
                                                             input.len() -
                                                             idx)]);
            len += sub_len * repetitions;
            idx += width;
        } else {
            if !(input[idx] as char).is_whitespace() {
                len += 1;
            }
            idx += 1;
        }
    }
    len
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 09")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("file")
            .index(1)
            .short("f")
            .long("file")
            .help("file to decompress. Reads from stdin otherwise")
            .takes_value(true))
        .get_matches();
    let source = matches.value_of_os("file");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn main() {
    let compressed = parse_args()
        .unwrap_or_else(|err| panic!("Error reading input: {}", err));
    let decompressed = decompress_a(compressed.as_bytes());
    println!("Decompressed length (first algorithm): {}",
             decompressed.iter()
                 .filter(|c| !(**c as char).is_whitespace())
                 .count());
    println!("Decompressed length (second algorithm): {}",
             decompressed_b_len(compressed.as_bytes()));
}

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

    #[test]
    fn decompress_a_1() {
        assert_eq!(&decompress_a(b"ADVENT"), b"ADVENT")
    }

    #[test]
    fn decompress_a_2() {
        assert_eq!(&decompress_a(b"A(1x5)BC"), b"ABBBBBC")
    }

    #[test]
    fn decompress_a_3() {
        assert_eq!(&decompress_a(b"(3x3)XYZ"), b"XYZXYZXYZ")
    }

    #[test]
    fn decompress_a_4() {
        assert_eq!(&decompress_a(b"A(2x2)BCD(2x2)EFG"), b"ABCBCDEFEFG")
    }

    #[test]
    fn decompress_a_5() {
        assert_eq!(&decompress_a(b"(6x1)(1x3)A"), b"(1x3)A")
    }

    #[test]
    fn decompress_a_6() {
        assert_eq!(&decompress_a(b"X(8x2)(3x3)ABCY"), b"X(3x3)ABC(3x3)ABCY")
    }

    #[test]
    fn decompress_a_not_enough_input() {
        assert_eq!(&decompress_a(b"(3x3)XY"), b"XYXYXY");
        assert_eq!(&decompress_a(b"(3x3)"), b"")
    }

    #[test]
    fn read_expansion_success() {
        assert_eq!(read_expansion(b"(123x456)foo"),
                   Ok((Expansion {
                       width: 123,
                       repetitions: 456,
                   },
                       9)))
    }

    #[test]
    fn read_expansion_not_enough_input() {
        assert_eq!(read_expansion(b""),
                   Err(ParseExpansionError::NotEnoughInput));
        assert_eq!(read_expansion(b"(1"),
                   Err(ParseExpansionError::NotEnoughInput));
        assert_eq!(read_expansion(b"(1x2"),
                   Err(ParseExpansionError::NotEnoughInput));
    }

    #[test]
    fn read_expansion_expected() {
        assert_eq!(read_expansion(b"1"),
                   Err(ParseExpansionError::BadChar {
                       expected: '(',
                       got: '1',
                   }));
        assert_eq!(read_expansion(b"(1,"),
                   Err(ParseExpansionError::BadChar {
                       expected: 'x',
                       got: ',',
                   }));
        assert_eq!(read_expansion(b"(1x2x"),
                   Err(ParseExpansionError::BadChar {
                       expected: ')',
                       got: 'x',
                   }));
    }

    #[test]
    fn read_expansion_bad_int() {
        let empty_int_error = "".parse::<usize>().unwrap_err();
        assert_eq!(read_expansion(b"(x456)"),
                   Err(ParseExpansionError::BadInt(empty_int_error.clone())));
        assert_eq!(read_expansion(b"(123x)"),
                   Err(ParseExpansionError::BadInt(empty_int_error)));
    }

    #[test]
    fn decompress_b_len_1() {
        assert_eq!(decompressed_b_len(b"(3x3)XYZ"), 9);
    }

    #[test]
    fn decompress_b_len_2() {
        assert_eq!(decompressed_b_len(b"X(8x2)(3x3)ABCY"), 20);
    }

    #[test]
    fn decompress_b_len_3() {
        assert_eq!(decompressed_b_len(b"(27x12)(20x12)(13x14)(7x10)(1x12)A"),
                   241920);
    }

    #[test]
    fn decompress_b_len_4() {
        assert_eq!(decompressed_b_len(
                b"(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN"),
                   445);
    }
}
<commit_msg>Day 9 clippy<commit_after>#[macro_use]
extern crate clap;

use std::io::prelude::*;
use std::fs::File;
use std::error::Error;

#[derive(Debug, PartialEq, Eq)]
enum ParseExpansionError {
    BadChar { expected: char, got: char },
    BadInt(std::num::ParseIntError),
    NotEnoughInput,
}

impl std::fmt::Display for ParseExpansionError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        match *self {
            ParseExpansionError::BadChar { expected: ref e, got: ref g } => {
                write!(f, "Expected {}, got {}", e, g)
            }
            ParseExpansionError::BadInt(ref e) => write!(f, "{}", e),
            ParseExpansionError::NotEnoughInput => {
                write!(f, "Not enough input")
            }
        }
    }
}

impl Error for ParseExpansionError {
    fn description(&self) -> &str {
        "Could not parse Expansion"
    }
    fn cause(&self) -> Option<&Error> {
        match *self {
            ParseExpansionError::BadInt(ref e) => Some(e),
            _ => None,
        }
    }
}

impl From<std::num::ParseIntError> for ParseExpansionError {
    fn from(err: std::num::ParseIntError) -> Self {
        ParseExpansionError::BadInt(err)
    }
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
struct Expansion {
    width: usize,
    repetitions: usize,
}

fn read_expansion(input: &[u8])
                  -> Result<(Expansion, usize), ParseExpansionError> {
    use ParseExpansionError::*;
    // read '('
    if input.len() == 0 {
        return Err(NotEnoughInput);
    } else if input[0] != b'(' {
        return Err(BadChar {
            expected: '(',
            got: input[0] as char,
        });
    }
    // read `width`
    let mut idx = 1;
    while idx < input.len() && (input[idx] as char).is_digit(10) {
        idx += 1;
    }
    let width = std::str::from_utf8(&input[1..idx]).unwrap().parse()?;
    // read 'x'
    if input.len() < idx + 1 {
        return Err(NotEnoughInput);
    } else if input[idx] != b'x' {
        return Err(BadChar {
            expected: 'x',
            got: input[idx] as char,
        });
    }
    // read `repetitions`
    idx += 1;
    let repititions_start = idx;
    while idx < input.len() && (input[idx] as char).is_digit(10) {
        idx += 1;
    }
    let repetitions =
        std::str::from_utf8(&input[repititions_start..idx]).unwrap().parse()?;
    if input.len() < idx + 1 {
        return Err(NotEnoughInput);
    } else if input[idx] != b')' {
        return Err(BadChar {
            expected: ')',
            got: input[idx] as char,
        });
    }
    Ok((Expansion {
        width: width,
        repetitions: repetitions,
    },
        idx + 1))
}

fn decompress_a(input: &[u8]) -> Vec<u8> {
    let mut out = Vec::new();
    let mut idx = 0;
    while idx < input.len() {
        if let Ok((Expansion { width, repetitions }, exp_len)) =
               read_expansion(&input[idx..]) {
            idx += exp_len;
            for _ in 0..repetitions {
                out.extend_from_slice(&input[idx..idx +
                                                  std::cmp::min(width,
                                                                input.len() -
                                                                idx)]);
            }
            idx += width;
        } else {
            out.push(input[idx]);
            idx += 1;
        }
    }
    out
}

fn decompressed_b_len(input: &[u8]) -> usize {
    let mut len = 0;
    let mut idx = 0;
    while idx < input.len() {
        if let Ok((Expansion { width, repetitions }, exp_len)) =
               read_expansion(&input[idx..]) {
            idx += exp_len;
            let sub_len =
                decompressed_b_len(&input[idx..idx +
                                               std::cmp::min(width,
                                                             input.len() -
                                                             idx)]);
            len += sub_len * repetitions;
            idx += width;
        } else {
            if !(input[idx] as char).is_whitespace() {
                len += 1;
            }
            idx += 1;
        }
    }
    len
}

fn parse_args() -> std::io::Result<String> {
    let matches = clap::App::new("Day 09")
        .author("Devon Hollowood")
        .arg(clap::Arg::with_name("file")
            .index(1)
            .short("f")
            .long("file")
            .help("file to decompress. Reads from stdin otherwise")
            .takes_value(true))
        .get_matches();
    let source = matches.value_of_os("file");
    let mut contents = String::new();
    match source {
        Some(filename) => {
            let mut input = File::open(filename)?;
            input.read_to_string(&mut contents)?;
        }
        None => {
            let mut input = std::io::stdin();
            input.read_to_string(&mut contents)?;
        }
    }
    Ok(contents)
}

fn main() {
    let compressed = parse_args()
        .unwrap_or_else(|err| panic!("Error reading input: {}", err));
    let decompressed = decompress_a(compressed.as_bytes());
    println!("Decompressed length (first algorithm): {}",
             decompressed.iter()
                 .filter(|c| !(**c as char).is_whitespace())
                 .count());
    println!("Decompressed length (second algorithm): {}",
             decompressed_b_len(compressed.as_bytes()));
}

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

    #[test]
    fn decompress_a_1() {
        assert_eq!(&decompress_a(b"ADVENT"), b"ADVENT")
    }

    #[test]
    fn decompress_a_2() {
        assert_eq!(&decompress_a(b"A(1x5)BC"), b"ABBBBBC")
    }

    #[test]
    fn decompress_a_3() {
        assert_eq!(&decompress_a(b"(3x3)XYZ"), b"XYZXYZXYZ")
    }

    #[test]
    fn decompress_a_4() {
        assert_eq!(&decompress_a(b"A(2x2)BCD(2x2)EFG"), b"ABCBCDEFEFG")
    }

    #[test]
    fn decompress_a_5() {
        assert_eq!(&decompress_a(b"(6x1)(1x3)A"), b"(1x3)A")
    }

    #[test]
    fn decompress_a_6() {
        assert_eq!(&decompress_a(b"X(8x2)(3x3)ABCY"), b"X(3x3)ABC(3x3)ABCY")
    }

    #[test]
    fn decompress_a_not_enough_input() {
        assert_eq!(&decompress_a(b"(3x3)XY"), b"XYXYXY");
        assert_eq!(&decompress_a(b"(3x3)"), b"")
    }

    #[test]
    fn read_expansion_success() {
        assert_eq!(read_expansion(b"(123x456)foo"),
                   Ok((Expansion {
                       width: 123,
                       repetitions: 456,
                   },
                       9)))
    }

    #[test]
    fn read_expansion_not_enough_input() {
        assert_eq!(read_expansion(b""),
                   Err(ParseExpansionError::NotEnoughInput));
        assert_eq!(read_expansion(b"(1"),
                   Err(ParseExpansionError::NotEnoughInput));
        assert_eq!(read_expansion(b"(1x2"),
                   Err(ParseExpansionError::NotEnoughInput));
    }

    #[test]
    fn read_expansion_expected() {
        assert_eq!(read_expansion(b"1"),
                   Err(ParseExpansionError::BadChar {
                       expected: '(',
                       got: '1',
                   }));
        assert_eq!(read_expansion(b"(1,"),
                   Err(ParseExpansionError::BadChar {
                       expected: 'x',
                       got: ',',
                   }));
        assert_eq!(read_expansion(b"(1x2x"),
                   Err(ParseExpansionError::BadChar {
                       expected: ')',
                       got: 'x',
                   }));
    }

    #[test]
    fn read_expansion_bad_int() {
        let empty_int_error = "".parse::<usize>().unwrap_err();
        assert_eq!(read_expansion(b"(x456)"),
                   Err(ParseExpansionError::BadInt(empty_int_error.clone())));
        assert_eq!(read_expansion(b"(123x)"),
                   Err(ParseExpansionError::BadInt(empty_int_error)));
    }

    #[test]
    fn decompress_b_len_1() {
        assert_eq!(decompressed_b_len(b"(3x3)XYZ"), 9);
    }

    #[test]
    fn decompress_b_len_2() {
        assert_eq!(decompressed_b_len(b"X(8x2)(3x3)ABCY"), 20);
    }

    #[test]
    fn decompress_b_len_3() {
        assert_eq!(decompressed_b_len(b"(27x12)(20x12)(13x14)(7x10)(1x12)A"),
                   241920);
    }

    #[test]
    fn decompress_b_len_4() {
        assert_eq!(decompressed_b_len(
                b"(25x3)(3x3)ABC(2x3)XY(5x2)PQRSTX(18x9)(3x2)TWO(5x7)SEVEN"),
                   445);
    }
}
<|endoftext|>


<commit_before>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// 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 std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;

use super::input::Input;
use super::span;

#[derive(Eq, Ord)]
pub struct Position<I: Input> {
    input: Rc<Arc<I>>,
    pos:   usize
}

#[inline]
pub fn new<I: Input>(input: Rc<Arc<I>>, pos: usize) -> Position<I> {
    Position {
        input: input,
        pos:   pos
    }
}

impl<I: Input> Position<I> {
    #[inline]
    pub fn pos(&self) -> usize {
        self.pos
    }

    #[inline]
    pub fn span(self, other: Position<I>) -> span::Span<I> {
        if &**self.input as *const I == &**other.input as *const I {
            span::new(self.input, self.pos, other.pos)
        } else {
            panic!("Span created from positions coming from different inputs")
        }
    }

    #[inline]
    pub fn line_col(&self) -> (usize, usize) {
        unsafe { self.input.line_col(self.pos) }
    }

    #[inline]
    pub fn line_of(&self) -> &str {
        unsafe { self.input.line_of(self.pos) }
    }

    #[inline]
    pub fn at_start(self) -> Result<Position<I>, Position<I>> {
        if self.pos == 0 {
            Ok(self)
        } else {
            Err(self)
        }
    }

    #[inline]
    pub fn at_end(self) -> Result<Position<I>, Position<I>> {
        if self.pos == self.input.len() {
            Ok(self)
        } else {
            Err(self)
        }
    }

    #[inline]
    pub fn skip(self, n: usize) -> Result<Position<I>, Position<I>> {
        let skipped = unsafe { self.input.skip(n, self.pos) };

        match skipped {
            Some(len) => Ok(new(self.input, self.pos + len)),
            None      => Err(self)
        }
    }

    #[inline]
    pub fn match_string(self, string: &str) -> Result<Position<I>, Position<I>> {
        if unsafe { self.input.match_string(string, self.pos) } {
            Ok(new(self.input, self.pos + string.len()))
        } else {
            Err(self)
        }
    }

    #[inline]
    pub fn match_insensitive(self, string: &str) -> Result<Position<I>, Position<I>> {
        if unsafe { self.input.match_insensitive(string, self.pos) } {
            Ok(new(self.input, self.pos + string.len()))
        } else {
            Err(self)
        }
    }

    #[inline]
    pub fn match_range(self, range: Range<char>) -> Result<Position<I>, Position<I>> {
        let len = unsafe { self.input.match_range(range, self.pos) };

        match len {
            Some(len) => Ok(new(self.input, self.pos + len)),
            None      => Err(self)
        }
    }

    #[inline]
    pub fn sequence<F>(self, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>) -> Result<Position<I>, Position<I>> {

        let result = f(self.clone());

        match result {
            Ok(pos) => Ok(pos),
            Err(_)  => Err(self)
        }
    }

    #[inline]
    pub fn lookahead<F>(self, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>) -> Result<Position<I>, Position<I>> {

        let result = f(self.clone());

        match result {
            Ok(_)  => Ok(self),
            Err(_) => Err(self)
        }
    }

    #[inline]
    pub fn negate<F>(self, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>) -> Result<Position<I>, Position<I>> {

        let result = f(self);

        match result {
            Ok(pos)  => Err(pos),
            Err(pos) => Ok(pos)
        }
    }

    #[inline]
    pub fn optional<F>(self, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>) -> Result<Position<I>, Position<I>> {

        let result = f(self);

        match result {
            Ok(pos)  => Ok(pos),
            Err(pos) => Ok(pos)
        }
    }

    #[inline]
    pub fn repeat<F>(self, mut f: F) -> Result<Position<I>, Position<I>>
        where F: FnMut(Position<I>) -> Result<Position<I>, Position<I>> {

        let result = f(self);

        match result {
            Ok(pos)  => pos.repeat(f),
            Err(pos) => Ok(pos)
        }
    }
}

impl<I: Input> fmt::Debug for Position<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Position {{ pos: {} }}", self.pos)
    }
}

impl<I: Input> Clone for Position<I> {
    fn clone(&self) -> Position<I> {
        new(self.input.clone(), self.pos)
    }
}

impl<I: Input> PartialEq for Position<I> {
    fn eq(&self, other: &Position<I>) -> bool {
        &**self.input as *const I == &**other.input as *const I &&
        self.pos == other.pos
    }
}

impl<I: Input> PartialOrd for Position<I> {
    fn partial_cmp(&self, other: &Position<I>) -> Option<Ordering> {
        if &**self.input as *const I == &**other.input as *const I {
            self.pos.partial_cmp(&other.pos)
        } else {
            None
        }
    }
}

impl<I: Input> Hash for Position<I> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        (&**self.input as *const I).hash(state);
        self.pos.hash(state);
    }
}
<commit_msg>Improved performance of Position::repeat.<commit_after>// pest. The Elegant Parser
// Copyright (C) 2017  Dragoș Tiselice
//
// 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 std::cmp::Ordering;
use std::fmt;
use std::hash::{Hash, Hasher};
use std::ops::Range;
use std::rc::Rc;
use std::sync::Arc;

use super::input::Input;
use super::span;

#[derive(Eq, Ord)]
pub struct Position<I: Input> {
    input: Rc<Arc<I>>,
    pos:   usize
}

#[inline]
pub fn new<I: Input>(input: Rc<Arc<I>>, pos: usize) -> Position<I> {
    Position {
        input: input,
        pos:   pos
    }
}

impl<I: Input> Position<I> {
    #[inline]
    pub fn pos(&self) -> usize {
        self.pos
    }

    #[inline]
    pub fn span(self, other: Position<I>) -> span::Span<I> {
        if &**self.input as *const I == &**other.input as *const I {
            span::new(self.input, self.pos, other.pos)
        } else {
            panic!("Span created from positions coming from different inputs")
        }
    }

    #[inline]
    pub fn line_col(&self) -> (usize, usize) {
        unsafe { self.input.line_col(self.pos) }
    }

    #[inline]
    pub fn line_of(&self) -> &str {
        unsafe { self.input.line_of(self.pos) }
    }

    #[inline]
    pub fn at_start(self) -> Result<Position<I>, Position<I>> {
        if self.pos == 0 {
            Ok(self)
        } else {
            Err(self)
        }
    }

    #[inline]
    pub fn at_end(self) -> Result<Position<I>, Position<I>> {
        if self.pos == self.input.len() {
            Ok(self)
        } else {
            Err(self)
        }
    }

    #[inline]
    pub fn skip(self, n: usize) -> Result<Position<I>, Position<I>> {
        let skipped = unsafe { self.input.skip(n, self.pos) };

        match skipped {
            Some(len) => Ok(new(self.input, self.pos + len)),
            None      => Err(self)
        }
    }

    #[inline]
    pub fn match_string(self, string: &str) -> Result<Position<I>, Position<I>> {
        if unsafe { self.input.match_string(string, self.pos) } {
            Ok(new(self.input, self.pos + string.len()))
        } else {
            Err(self)
        }
    }

    #[inline]
    pub fn match_insensitive(self, string: &str) -> Result<Position<I>, Position<I>> {
        if unsafe { self.input.match_insensitive(string, self.pos) } {
            Ok(new(self.input, self.pos + string.len()))
        } else {
            Err(self)
        }
    }

    #[inline]
    pub fn match_range(self, range: Range<char>) -> Result<Position<I>, Position<I>> {
        let len = unsafe { self.input.match_range(range, self.pos) };

        match len {
            Some(len) => Ok(new(self.input, self.pos + len)),
            None      => Err(self)
        }
    }

    #[inline]
    pub fn sequence<F>(self, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>) -> Result<Position<I>, Position<I>> {

        let result = f(self.clone());

        match result {
            Ok(pos) => Ok(pos),
            Err(_)  => Err(self)
        }
    }

    #[inline]
    pub fn lookahead<F>(self, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>) -> Result<Position<I>, Position<I>> {

        let result = f(self.clone());

        match result {
            Ok(_)  => Ok(self),
            Err(_) => Err(self)
        }
    }

    #[inline]
    pub fn negate<F>(self, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>) -> Result<Position<I>, Position<I>> {

        let result = f(self);

        match result {
            Ok(pos)  => Err(pos),
            Err(pos) => Ok(pos)
        }
    }

    #[inline]
    pub fn optional<F>(self, f: F) -> Result<Position<I>, Position<I>>
        where F: FnOnce(Position<I>) -> Result<Position<I>, Position<I>> {

        let result = f(self);

        match result {
            Ok(pos)  => Ok(pos),
            Err(pos) => Ok(pos)
        }
    }

    #[inline]
    pub fn repeat<F>(self, mut f: F) -> Result<Position<I>, Position<I>>
        where F: FnMut(Position<I>) -> Result<Position<I>, Position<I>> {

        let mut result = f(self);

        while result.is_ok() {
            result = f(result.unwrap());
        }

        match result {
            Ok(pos)  => Ok(pos),
            Err(pos) => Ok(pos)
        }
    }
}

impl<I: Input> fmt::Debug for Position<I> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Position {{ pos: {} }}", self.pos)
    }
}

impl<I: Input> Clone for Position<I> {
    fn clone(&self) -> Position<I> {
        new(self.input.clone(), self.pos)
    }
}

impl<I: Input> PartialEq for Position<I> {
    fn eq(&self, other: &Position<I>) -> bool {
        &**self.input as *const I == &**other.input as *const I &&
        self.pos == other.pos
    }
}

impl<I: Input> PartialOrd for Position<I> {
    fn partial_cmp(&self, other: &Position<I>) -> Option<Ordering> {
        if &**self.input as *const I == &**other.input as *const I {
            self.pos.partial_cmp(&other.pos)
        } else {
            None
        }
    }
}

impl<I: Input> Hash for Position<I> {
    fn hash<H: Hasher>(&self, state: &mut H) {
        (&**self.input as *const I).hash(state);
        self.pos.hash(state);
    }
}
<|endoftext|>