<commit_before>// https://leetcode.com/problems/minimum-length-of-string-after-deleting-similar-ends/
pub fn minimum_length(s: String) -> i32 {
    todo!()
}

fn main() {
    println!("{}", minimum_length("ca".to_string())); // 2
    println!("{}", minimum_length("cabaabac".to_string())); // 0
    println!("{}", minimum_length("aabccabba".to_string())); // 3
}
<commit_msg>Update problem 1750<commit_after>// https://leetcode.com/problems/minimum-length-of-string-after-deleting-similar-ends/
pub fn minimum_length(s: String) -> i32 {
    let bytes = s.as_bytes();
    let mut i = 0;
    let mut j = bytes.len() - 1;
    while i <= j && bytes[i] == bytes[j] {
        let tmp = bytes[i];
        while i <= j && bytes[i] == bytes[j] {
            i += 1;
        }
        while i <= j && tmp == bytes[j] {
            j -= 1;
        }
    }
    let answer = (j as i32 - i as i32) + 1;
    answer
}

fn main() {
    println!("{}", minimum_length("ca".to_string())); // 2
    println!("{}", minimum_length("cabaabac".to_string())); // 0
    println!("{}", minimum_length("aabccabba".to_string())); // 3
    println!(
        "{}",
        minimum_length("bbbbbbbbbbbbbbbbbbbbbbbbbbbabbbbbbbbbbbbbbbccbcbcbccbbabbb".to_string())
    ); // 1
}
<|endoftext|>


<commit_before>use core::alloc::{GlobalAlloc, Layout};
use core::ptr::{self, NonNull};
use linked_list_allocator::Heap;
use spin::Mutex;

use crate::paging::{ActivePageTable, TableKind};

static HEAP: Mutex<Option<Heap>> = Mutex::new(None);

pub struct Allocator;

impl Allocator {
    pub unsafe fn init(offset: usize, size: usize) {
        *HEAP.lock() = Some(Heap::new(offset, size));
    }
}

unsafe impl GlobalAlloc for Allocator {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        loop {
            let res = if let Some(ref mut heap) = *HEAP.lock() {
                heap.allocate_first_fit(layout)
            } else {
                panic!("__rust_allocate: heap not initialized");
            };

            match res {
                Err(()) => {
                    let size = if let Some(ref heap) = *HEAP.lock() {
                        heap.size()
                    } else {
                        panic!("__rust_allocate: heap not initialized");
                    };

                    super::map_heap(&mut ActivePageTable::new(TableKind::Kernel), crate::KERNEL_HEAP_OFFSET + size, crate::KERNEL_HEAP_SIZE);

                    if let Some(ref mut heap) = *HEAP.lock() {
                        heap.extend(crate::KERNEL_HEAP_SIZE);
                    } else {
                        panic!("__rust_allocate: heap not initialized");
                    }
                },
                other => return other.ok().map_or(ptr::null_mut(), |allocation| allocation.as_ptr()),
            }
        }
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        if let Some(ref mut heap) = *HEAP.lock() {
            heap.deallocate(NonNull::new_unchecked(ptr), layout)
        } else {
            panic!("__rust_deallocate: heap not initialized");
        }
    }
}
<commit_msg>Fix allocator race condition<commit_after>use core::alloc::{GlobalAlloc, Layout};
use core::ptr::{self, NonNull};
use linked_list_allocator::Heap;
use spin::Mutex;

use crate::paging::{ActivePageTable, TableKind};

static HEAP: Mutex<Option<Heap>> = Mutex::new(None);

pub struct Allocator;

impl Allocator {
    pub unsafe fn init(offset: usize, size: usize) {
        *HEAP.lock() = Some(Heap::new(offset, size));
    }
}

unsafe impl GlobalAlloc for Allocator {
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        while let Some(ref mut heap) = *HEAP.lock() {
            match heap.allocate_first_fit(layout) {
                Err(()) => {
                    let size = heap.size();
                    super::map_heap(&mut ActivePageTable::new(TableKind::Kernel), crate::KERNEL_HEAP_OFFSET + size, crate::KERNEL_HEAP_SIZE);
                    heap.extend(crate::KERNEL_HEAP_SIZE);
                },
                other => return other.ok().map_or(ptr::null_mut(), |allocation| allocation.as_ptr()),
            }
        }
        panic!("__rust_allocate: heap not initialized");
    }

    unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) {
        if let Some(ref mut heap) = *HEAP.lock() {
            heap.deallocate(NonNull::new_unchecked(ptr), layout)
        } else {
            panic!("__rust_deallocate: heap not initialized");
        }
    }
}
<|endoftext|>


<commit_before>// compile-flags: -O

#![crate_type = "lib"]

// CHECK: define { i8, i8 } @pair_bool_bool(i1 zeroext %pair.0, i1 zeroext %pair.1)
#[no_mangle]
pub fn pair_bool_bool(pair: (bool, bool)) -> (bool, bool) {
    pair
}

// CHECK: define { i8, i32 } @pair_bool_i32(i1 zeroext %pair.0, i32 %pair.1)
#[no_mangle]
pub fn pair_bool_i32(pair: (bool, i32)) -> (bool, i32) {
    pair
}

// CHECK: define { i32, i8 } @pair_i32_bool(i32 %pair.0, i1 zeroext %pair.1)
#[no_mangle]
pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) {
    pair
}

// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %_1.0, i1 zeroext %_1.1)
#[no_mangle]
pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) {
    // Make sure it can operate directly on the unpacked args
    // CHECK: and i1 %_1.0, %_1.1
    // CHECK: or i1 %_1.0, %_1.1
    (a && b, a || b)
}

// CHECK: define void @pair_branches(i1 zeroext %_1.0, i1 zeroext %_1.1)
#[no_mangle]
pub fn pair_branches((a, b): (bool, bool)) {
    // Make sure it can branch directly on the unpacked bool args
    // CHECK: br i1 %_1.0
    if a {
        println!("Hello!");
    }
    // CHECK: br i1 %_1.1
    if b {
        println!("Goodbye!");
    }
}
<commit_msg>Match scalar-pair-bool more flexibly for LLVM 11<commit_after>// compile-flags: -O

#![crate_type = "lib"]

// CHECK: define { i8, i8 } @pair_bool_bool(i1 zeroext %pair.0, i1 zeroext %pair.1)
#[no_mangle]
pub fn pair_bool_bool(pair: (bool, bool)) -> (bool, bool) {
    pair
}

// CHECK: define { i8, i32 } @pair_bool_i32(i1 zeroext %pair.0, i32 %pair.1)
#[no_mangle]
pub fn pair_bool_i32(pair: (bool, i32)) -> (bool, i32) {
    pair
}

// CHECK: define { i32, i8 } @pair_i32_bool(i32 %pair.0, i1 zeroext %pair.1)
#[no_mangle]
pub fn pair_i32_bool(pair: (i32, bool)) -> (i32, bool) {
    pair
}

// CHECK: define { i8, i8 } @pair_and_or(i1 zeroext %_1.0, i1 zeroext %_1.1)
#[no_mangle]
pub fn pair_and_or((a, b): (bool, bool)) -> (bool, bool) {
    // Make sure it can operate directly on the unpacked args
    // (but it might not be using simple and/or instructions)
    // CHECK-DAG: %_1.0
    // CHECK-DAG: %_1.1
    (a && b, a || b)
}

// CHECK: define void @pair_branches(i1 zeroext %_1.0, i1 zeroext %_1.1)
#[no_mangle]
pub fn pair_branches((a, b): (bool, bool)) {
    // Make sure it can branch directly on the unpacked bool args
    // CHECK: br i1 %_1.0
    if a {
        println!("Hello!");
    }
    // CHECK: br i1 %_1.1
    if b {
        println!("Goodbye!");
    }
}
<|endoftext|>


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

// ignore-tidy-linelength

use std::ops::{Add, Sub};

type Test = Add +
            //~^ ERROR E0393
            //~| NOTE missing reference to `RHS`
            //~| NOTE because of the default `Self` reference, type parameters must be specified on object types
            //~| ERROR E0191
            //~| NOTE missing associated type `Output` value
            Sub;
            //~^ ERROR E0225
            //~| NOTE non-Send/Sync additional trait

fn main() { }
<commit_msg>Fix a test to recognize newly introduced errors.<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// ignore-tidy-linelength

use std::ops::{Add, Sub};

type Test = Add +
            //~^ ERROR E0393
            //~| NOTE missing reference to `RHS`
            //~| NOTE because of the default `Self` reference, type parameters must be specified on object types
            //~| ERROR E0191
            //~| NOTE missing associated type `Output` value
            Sub;
            //~^ ERROR E0393
            //~| NOTE missing reference to `RHS`
            //~| NOTE because of the default `Self` reference, type parameters must be specified on object types
            //~| ERROR E0225
            //~| NOTE non-Send/Sync additional trait

fn main() { }
<|endoftext|>


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

#![feature(rustc_attrs)]

// check raw fat pointer ops in mir
// FIXME: please improve this when we get monomorphization support

use std::mem;

#[derive(Debug, PartialEq, Eq)]
struct ComparisonResults {
    lt: bool,
    le: bool,
    gt: bool,
    ge: bool,
    eq: bool,
    ne: bool
}

const LT: ComparisonResults = ComparisonResults {
    lt: true,
    le: true,
    gt: false,
    ge: false,
    eq: false,
    ne: true
};

const EQ: ComparisonResults = ComparisonResults {
    lt: false,
    le: true,
    gt: false,
    ge: true,
    eq: true,
    ne: false
};

const GT: ComparisonResults = ComparisonResults {
    lt: false,
    le: false,
    gt: true,
    ge: true,
    eq: false,
    ne: true
};

#[rustc_mir]
fn compare_su8(a: *const S<[u8]>, b: *const S<[u8]>) -> ComparisonResults {
    ComparisonResults {
        lt: a < b,
        le: a <= b,
        gt: a > b,
        ge: a >= b,
        eq: a == b,
        ne: a != b
    }
}

#[rustc_mir]
fn compare_au8(a: *const [u8], b: *const [u8]) -> ComparisonResults {
    ComparisonResults {
        lt: a < b,
        le: a <= b,
        gt: a > b,
        ge: a >= b,
        eq: a == b,
        ne: a != b
    }
}

#[rustc_mir(graphviz="comparefoo.gv")]
fn compare_foo<'a>(a: *const (Foo+'a), b: *const (Foo+'a)) -> ComparisonResults {
    ComparisonResults {
        lt: a < b,
        le: a <= b,
        gt: a > b,
        ge: a >= b,
        eq: a == b,
        ne: a != b
    }
}

#[rustc_mir(graphviz="simpleeq.gv")]
fn simple_eq<'a>(a: *const (Foo+'a), b: *const (Foo+'a)) -> bool {
    let result = a == b;
    result
}

fn assert_inorder<T: Copy>(a: &[T],
                           compare: fn(T, T) -> ComparisonResults) {
    for i in 0..a.len() {
        for j in 0..a.len() {
            let cres = compare(a[i], a[j]);
            if i < j {
                assert_eq!(cres, LT);
            } else if i == j {
                assert_eq!(cres, EQ);
            } else {
                assert_eq!(cres, GT);
            }
        }
    }
}

trait Foo { fn foo(&self) -> usize; }
impl<T> Foo for T {
    fn foo(&self) -> usize {
        mem::size_of::<T>()
    }
}

struct S<T:?Sized>(u32, T);

fn main() {
    let array = [0,1,2,3,4];
    let array2 = [5,6,7,8,9];

    // fat ptr comparison: addr then extra

    // check ordering for arrays
    let mut ptrs: Vec<*const [u8]> = vec![
        &array[0..0], &array[0..1], &array, &array[1..]
    ];

    let array_addr = &array as *const [u8] as *const u8 as usize;
    let array2_addr = &array2 as *const [u8] as *const u8 as usize;
    if array2_addr < array_addr {
        ptrs.insert(0, &array2);
    } else {
        ptrs.push(&array2);
    }
    assert_inorder(&ptrs, compare_au8);

    let u8_ = (0u8, 1u8);
    let u32_ = (4u32, 5u32);

    // check ordering for ptrs
    let buf: &mut [*const Foo] = &mut [
        &u8_, &u8_.0,
        &u32_, &u32_.0,
    ];
    buf.sort_by(|u,v| {
        let u : [*const (); 2] = unsafe { mem::transmute(*u) };
        let v : [*const (); 2] = unsafe { mem::transmute(*v) };
        u.cmp(&v)
    });
    assert_inorder(buf, compare_foo);

    // check ordering for structs containing arrays
    let ss: (S<[u8; 2]>,
             S<[u8; 3]>,
             S<[u8; 2]>) = (
        S(7, [8, 9]),
        S(10, [11, 12, 13]),
        S(4, [5, 6])
    );
    assert_inorder(&[
        &ss.0 as *const S<[u8]>,
        &ss.1 as *const S<[u8]>,
        &ss.2 as *const S<[u8]>
            ], compare_su8);

    assert!(simple_eq(&0u8 as *const _, &0u8 as *const _));
    assert!(!simple_eq(&0u8 as *const _, &1u8 as *const _));
}
<commit_msg>Rollup merge of #29868 - petrochenkov:gv, r=sanxiyn<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(rustc_attrs)]

// check raw fat pointer ops in mir
// FIXME: please improve this when we get monomorphization support

use std::mem;

#[derive(Debug, PartialEq, Eq)]
struct ComparisonResults {
    lt: bool,
    le: bool,
    gt: bool,
    ge: bool,
    eq: bool,
    ne: bool
}

const LT: ComparisonResults = ComparisonResults {
    lt: true,
    le: true,
    gt: false,
    ge: false,
    eq: false,
    ne: true
};

const EQ: ComparisonResults = ComparisonResults {
    lt: false,
    le: true,
    gt: false,
    ge: true,
    eq: true,
    ne: false
};

const GT: ComparisonResults = ComparisonResults {
    lt: false,
    le: false,
    gt: true,
    ge: true,
    eq: false,
    ne: true
};

#[rustc_mir]
fn compare_su8(a: *const S<[u8]>, b: *const S<[u8]>) -> ComparisonResults {
    ComparisonResults {
        lt: a < b,
        le: a <= b,
        gt: a > b,
        ge: a >= b,
        eq: a == b,
        ne: a != b
    }
}

#[rustc_mir]
fn compare_au8(a: *const [u8], b: *const [u8]) -> ComparisonResults {
    ComparisonResults {
        lt: a < b,
        le: a <= b,
        gt: a > b,
        ge: a >= b,
        eq: a == b,
        ne: a != b
    }
}

#[rustc_mir]
fn compare_foo<'a>(a: *const (Foo+'a), b: *const (Foo+'a)) -> ComparisonResults {
    ComparisonResults {
        lt: a < b,
        le: a <= b,
        gt: a > b,
        ge: a >= b,
        eq: a == b,
        ne: a != b
    }
}

#[rustc_mir]
fn simple_eq<'a>(a: *const (Foo+'a), b: *const (Foo+'a)) -> bool {
    let result = a == b;
    result
}

fn assert_inorder<T: Copy>(a: &[T],
                           compare: fn(T, T) -> ComparisonResults) {
    for i in 0..a.len() {
        for j in 0..a.len() {
            let cres = compare(a[i], a[j]);
            if i < j {
                assert_eq!(cres, LT);
            } else if i == j {
                assert_eq!(cres, EQ);
            } else {
                assert_eq!(cres, GT);
            }
        }
    }
}

trait Foo { fn foo(&self) -> usize; }
impl<T> Foo for T {
    fn foo(&self) -> usize {
        mem::size_of::<T>()
    }
}

struct S<T:?Sized>(u32, T);

fn main() {
    let array = [0,1,2,3,4];
    let array2 = [5,6,7,8,9];

    // fat ptr comparison: addr then extra

    // check ordering for arrays
    let mut ptrs: Vec<*const [u8]> = vec![
        &array[0..0], &array[0..1], &array, &array[1..]
    ];

    let array_addr = &array as *const [u8] as *const u8 as usize;
    let array2_addr = &array2 as *const [u8] as *const u8 as usize;
    if array2_addr < array_addr {
        ptrs.insert(0, &array2);
    } else {
        ptrs.push(&array2);
    }
    assert_inorder(&ptrs, compare_au8);

    let u8_ = (0u8, 1u8);
    let u32_ = (4u32, 5u32);

    // check ordering for ptrs
    let buf: &mut [*const Foo] = &mut [
        &u8_, &u8_.0,
        &u32_, &u32_.0,
    ];
    buf.sort_by(|u,v| {
        let u : [*const (); 2] = unsafe { mem::transmute(*u) };
        let v : [*const (); 2] = unsafe { mem::transmute(*v) };
        u.cmp(&v)
    });
    assert_inorder(buf, compare_foo);

    // check ordering for structs containing arrays
    let ss: (S<[u8; 2]>,
             S<[u8; 3]>,
             S<[u8; 2]>) = (
        S(7, [8, 9]),
        S(10, [11, 12, 13]),
        S(4, [5, 6])
    );
    assert_inorder(&[
        &ss.0 as *const S<[u8]>,
        &ss.1 as *const S<[u8]>,
        &ss.2 as *const S<[u8]>
            ], compare_su8);

    assert!(simple_eq(&0u8 as *const _, &0u8 as *const _));
    assert!(!simple_eq(&0u8 as *const _, &1u8 as *const _));
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Formatter, Result};

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Orientation {
  Right = 0,
  UpRight = 1,
  Up = 2,
  UpLeft = 3,
  Left = 4,
  DownLeft = 5,
  Down = 6,
  DownRight = 7,
  Still = 8,
}

impl Display for Orientation {
  fn fmt(&self, f: &mut Formatter) -> Result {
    match *self {
      Orientation::Right => write!(f, "0"),
      Orientation::UpRight => write!(f, "1"),
      Orientation::Up => write!(f, "2"),
      Orientation::UpLeft => write!(f, "3"),
      Orientation::Left => write!(f, "4"),
      Orientation::DownLeft => write!(f, "5"),
      Orientation::Down => write!(f, "6"),
      Orientation::DownRight => write!(f, "7"),
      Orientation::Still => write!(f, "8"),
    }
  }
}
<commit_msg>Add Stance struct for character stance<commit_after>use std::fmt::{Display, Formatter, Result};

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Orientation {
  Right = 0,
  UpRight = 1,
  Up = 2,
  UpLeft = 3,
  Left = 4,
  DownLeft = 5,
  Down = 6,
  DownRight = 7,
  Still = 8,
}

impl Display for Orientation {
  fn fmt(&self, f: &mut Formatter) -> Result {
    match *self {
      Orientation::Right => write!(f, "0"),
      Orientation::UpRight => write!(f, "1"),
      Orientation::Up => write!(f, "2"),
      Orientation::UpLeft => write!(f, "3"),
      Orientation::Left => write!(f, "4"),
      Orientation::DownLeft => write!(f, "5"),
      Orientation::Down => write!(f, "6"),
      Orientation::DownRight => write!(f, "7"),
      Orientation::Still => write!(f, "8"),
    }
  }
}

#[derive(Clone, Copy, Debug, PartialEq)]
pub enum Stance {
  Normal = 0,
  Firing = 1,
}

impl Display for Stance {
  fn fmt(&self, f: &mut Formatter) -> Result {
    match *self {
      Stance::Normal => write!(f, "0"),
      Stance::Firing => write!(f, "1"),
    }
  }
}

<|endoftext|>


<commit_before>//! Helpers for code generation that need struct layout

use super::helpers::BlobTyBuilder;

use aster::struct_field::StructFieldBuilder;

use ir::comp::CompInfo;
use ir::context::BindgenContext;
use ir::layout::Layout;
use ir::ty::Type;
use std::cmp;
use std::mem;

use syntax::ast;

/// Trace the layout of struct.
pub struct StructLayoutTracker<'a, 'ctx: 'a> {
    ctx: &'a BindgenContext<'ctx>,
    comp: &'a CompInfo,
    latest_offset: usize,
    padding_count: usize,
    latest_field_layout: Option<Layout>,
    max_field_align: usize,
}

impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
    pub fn new(ctx: &'a BindgenContext<'ctx>, comp: &'a CompInfo) -> Self {
        StructLayoutTracker {
            ctx: ctx,
            comp: comp,
            latest_offset: 0,
            padding_count: 0,
            latest_field_layout: None,
            max_field_align: 0,
        }
    }

    pub fn saw_vtable(&mut self) {
        let ptr_size = mem::size_of::<*mut ()>();
        self.latest_offset += ptr_size;
        self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size));
        self.max_field_align = ptr_size;
    }

    pub fn saw_base(&mut self, base_ty: &Type) {
        self.align_to_latest_field();

        if let Some(layout) = base_ty.layout(self.ctx) {
            self.latest_offset += self.padding_bytes(layout) + layout.size;
            self.latest_field_layout = Some(layout);
            self.max_field_align = cmp::max(self.max_field_align, layout.align);
        }
    }

    pub fn saw_bitfield(&mut self, layout: Layout) {
        self.align_to_latest_field();

        self.latest_offset += self.padding_bytes(layout) + layout.size;
        self.latest_field_layout = Some(layout);
        self.max_field_align = cmp::max(self.max_field_align, layout.align);
    }

    pub fn saw_union(&mut self, layout: Layout) {
        self.align_to_latest_field();

        self.latest_offset += self.padding_bytes(layout) + layout.size;
        self.latest_field_layout = Some(layout);
        self.max_field_align = cmp::max(self.max_field_align, layout.align);
    }

    pub fn pad_field(&mut self,
                     field_name: &str,
                     field_ty: &Type,
                     field_offset: Option<usize>)
                     -> Option<ast::StructField> {
        field_ty.layout(self.ctx).and_then(|field_layout| {
            self.align_to_latest_field();

            let padding_layout = if self.comp.packed() {
                None
            } else {
                let calculated_layout = field_ty.as_comp()
                    .and_then(|comp| comp.calc_layout(self.ctx))
                    .unwrap_or(field_layout);

                let align = cmp::min(calculated_layout.align, mem::size_of::<*mut ()>());

                let (padding_bytes, need_padding) = match field_offset {
                    Some(offset) if offset / 8  > self.latest_offset => {
                        (offset / 8  - self.latest_offset, true)
                    }
                    _ => {
                        (self.padding_bytes(field_layout), (self.latest_offset % field_layout.align) != 0)
                    }
                };

                self.latest_offset += padding_bytes;

                debug!("align field {} to {}/{} with {} padding bytes {:?}, calculated {:?}",
                    field_name,
                    self.latest_offset,
                    field_offset.unwrap_or(0) / 8,
                    padding_bytes,
                    field_layout,
                    calculated_layout);

                if need_padding &&
                   (padding_bytes > calculated_layout.align ||
                    field_layout.align > mem::size_of::<*mut ()>()) {
                    Some(Layout::new(padding_bytes, align))
                } else {
                    None
                }
            };

            self.latest_offset += field_ty.calc_size(self.ctx).unwrap_or(field_layout.size);

            self.latest_field_layout = Some(field_layout);
            self.max_field_align = cmp::max(self.max_field_align, field_layout.align);

            padding_layout.map(|layout| self.padding_field(layout))
        })
    }

    pub fn pad_struct(&mut self, layout: Layout) -> Option<ast::StructField> {
        if layout.size < self.latest_offset {
            warn!("calculate struct layout incorrect, too more {} bytes",
                  self.latest_offset - layout.size);

            None
        } else {
            let padding_bytes = layout.size - self.latest_offset;
            let struct_align = cmp::min(layout.align,
                                        mem::size_of::<*mut ()>());

            if padding_bytes > struct_align ||
               (layout.align > mem::size_of::<*mut ()>() && padding_bytes > 0) {
                let padding_align = if self.comp.packed() {
                    1
                } else {
                    cmp::min(1 << padding_bytes.trailing_zeros(),
                             mem::size_of::<*mut ()>())
                };

                Some(self.padding_field(Layout::new(padding_bytes, padding_align)))
            } else {
                None
            }
        }
    }

    pub fn align_struct(&self, layout: Layout) -> Option<ast::StructField> {
        if self.max_field_align < layout.align &&
           layout.align <= mem::size_of::<*mut ()>() {
            let ty = BlobTyBuilder::new(Layout::new(0, layout.align)).build();

            Some(StructFieldBuilder::named("__bindgen_align")
                .pub_()
                .build_ty(ty))
        } else {
            None
        }
    }

    fn padding_bytes(&self, layout: Layout) -> usize {
        if self.latest_offset % layout.align == 0 {
            0
        } else {
            layout.align - (self.latest_offset % layout.align)
        }
    }

    fn padding_field(&mut self, layout: Layout) -> ast::StructField {
        let ty = BlobTyBuilder::new(layout).build();
        let padding_count = self.padding_count;

        self.padding_count += 1;

        let padding_field_name = format!("__bindgen_padding_{}", padding_count);

        self.max_field_align = cmp::max(self.max_field_align, layout.align);

        StructFieldBuilder::named(padding_field_name).pub_().build_ty(ty)
    }

    fn align_to_latest_field(&mut self) {
        if self.comp.packed() {
            // skip to align field when packed
        } else if let Some(layout) = self.latest_field_layout {
            self.latest_offset += self.padding_bytes(layout);
        }
    }
}
<commit_msg>Auto merge of #494 - flier:fix-493, r=emilio<commit_after>//! Helpers for code generation that need struct layout

use super::helpers::BlobTyBuilder;

use aster::struct_field::StructFieldBuilder;

use ir::comp::CompInfo;
use ir::context::BindgenContext;
use ir::layout::Layout;
use ir::ty::Type;
use std::cmp;
use std::mem;

use syntax::ast;

/// Trace the layout of struct.
pub struct StructLayoutTracker<'a, 'ctx: 'a> {
    ctx: &'a BindgenContext<'ctx>,
    comp: &'a CompInfo,
    latest_offset: usize,
    padding_count: usize,
    latest_field_layout: Option<Layout>,
    max_field_align: usize,
}

impl<'a, 'ctx> StructLayoutTracker<'a, 'ctx> {
    pub fn new(ctx: &'a BindgenContext<'ctx>, comp: &'a CompInfo) -> Self {
        StructLayoutTracker {
            ctx: ctx,
            comp: comp,
            latest_offset: 0,
            padding_count: 0,
            latest_field_layout: None,
            max_field_align: 0,
        }
    }

    pub fn saw_vtable(&mut self) {
        let ptr_size = mem::size_of::<*mut ()>();
        self.latest_offset += ptr_size;
        self.latest_field_layout = Some(Layout::new(ptr_size, ptr_size));
        self.max_field_align = ptr_size;
    }

    pub fn saw_base(&mut self, base_ty: &Type) {
        self.align_to_latest_field();

        if let Some(layout) = base_ty.layout(self.ctx) {
            self.latest_offset += self.padding_bytes(layout) + layout.size;
            self.latest_field_layout = Some(layout);
            self.max_field_align = cmp::max(self.max_field_align, layout.align);
        }
    }

    pub fn saw_bitfield(&mut self, layout: Layout) {
        self.align_to_latest_field();

        self.latest_offset += self.padding_bytes(layout) + layout.size;
        self.latest_field_layout = Some(layout);
        self.max_field_align = cmp::max(self.max_field_align, layout.align);
    }

    pub fn saw_union(&mut self, layout: Layout) {
        self.align_to_latest_field();

        self.latest_offset += self.padding_bytes(layout) + layout.size;
        self.latest_field_layout = Some(layout);
        self.max_field_align = cmp::max(self.max_field_align, layout.align);
    }

    pub fn pad_field(&mut self,
                     field_name: &str,
                     field_ty: &Type,
                     field_offset: Option<usize>)
                     -> Option<ast::StructField> {
        field_ty.layout(self.ctx).and_then(|field_layout| {
            self.align_to_latest_field();

            let padding_layout = if self.comp.packed() {
                None
            } else {
                let calculated_layout = field_ty.as_comp()
                    .and_then(|comp| comp.calc_layout(self.ctx))
                    .unwrap_or(field_layout);

                let align = cmp::min(calculated_layout.align, mem::size_of::<*mut ()>());

                let (padding_bytes, need_padding) = match field_offset {
                    Some(offset) if offset / 8  > self.latest_offset => {
                        (offset / 8  - self.latest_offset, true)
                    }
                    _ => {
                        (self.padding_bytes(field_layout), (self.latest_offset % field_layout.align) != 0)
                    }
                };

                self.latest_offset += padding_bytes;

                debug!("align field {} to {}/{} with {} padding bytes {:?}, calculated {:?}",
                    field_name,
                    self.latest_offset,
                    field_offset.unwrap_or(0) / 8,
                    padding_bytes,
                    field_layout,
                    calculated_layout);

                if need_padding &&
                   (padding_bytes > calculated_layout.align ||
                    field_layout.align > mem::size_of::<*mut ()>()) {
                    Some(Layout::new(padding_bytes, align))
                } else {
                    None
                }
            };

            self.latest_offset += field_ty.calc_size(self.ctx).unwrap_or(field_layout.size);

            self.latest_field_layout = Some(field_layout);
            self.max_field_align = cmp::max(self.max_field_align, field_layout.align);

            padding_layout.map(|layout| self.padding_field(layout))
        })
    }

    pub fn pad_struct(&mut self, layout: Layout) -> Option<ast::StructField> {
        if layout.size < self.latest_offset {
            warn!("calculate struct layout incorrect, too more {} bytes",
                  self.latest_offset - layout.size);

            None
        } else {
            let padding_bytes = layout.size - self.latest_offset;
            let struct_align = cmp::min(layout.align,
                                        mem::size_of::<*mut ()>());

            if padding_bytes > struct_align ||
               (layout.align > mem::size_of::<*mut ()>() && padding_bytes > 0) {
                let padding_align = if self.comp.packed() {
                    1
                } else {
                    cmp::min(1 << padding_bytes.trailing_zeros(),
                             mem::size_of::<*mut ()>())
                };

                Some(self.padding_field(Layout::new(padding_bytes, padding_align)))
            } else {
                None
            }
        }
    }

    pub fn align_struct(&self, layout: Layout) -> Option<ast::StructField> {
        if self.max_field_align < layout.align &&
           layout.align <= mem::size_of::<*mut ()>() {
            let ty = BlobTyBuilder::new(Layout::new(0, layout.align)).build();

            Some(StructFieldBuilder::named("__bindgen_align")
                .pub_()
                .build_ty(ty))
        } else {
            None
        }
    }

    fn padding_bytes(&self, layout: Layout) -> usize {
        if layout.align == 0 {
            warn!("try to padding bytes without layout");

            0
        } else if self.latest_offset % layout.align == 0 {
            0
        } else {
            layout.align - (self.latest_offset % layout.align)
        }
    }

    fn padding_field(&mut self, layout: Layout) -> ast::StructField {
        let ty = BlobTyBuilder::new(layout).build();
        let padding_count = self.padding_count;

        self.padding_count += 1;

        let padding_field_name = format!("__bindgen_padding_{}", padding_count);

        self.max_field_align = cmp::max(self.max_field_align, layout.align);

        StructFieldBuilder::named(padding_field_name).pub_().build_ty(ty)
    }

    fn align_to_latest_field(&mut self) {
        if self.comp.packed() {
            // skip to align field when packed
        } else if let Some(layout) = self.latest_field_layout {
            self.latest_offset += self.padding_bytes(layout);
        }
    }
}
<|endoftext|>


<commit_before>use super::Gba;
use arm::Cycles;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

pub type EventFn = fn(gba: &mut Gba, late: Cycles);

#[derive(Default, Clone)]
pub struct Scheduler {
    inner: Rc<RefCell<Inner>>,
}

impl Scheduler {
    pub fn schedule(&mut self, callback: EventFn, cycles: impl Into<Cycles>) {
        self.inner.borrow_mut().schedule(Event {
            callback,
            cycles_remaining: cycles.into(),
        });
    }

    pub fn advance(&mut self, cycles: impl Into<Cycles>) -> Option<(EventFn, Cycles)> {
        self.inner.borrow_mut().advance(cycles.into())
    }
}

pub struct Event {
    callback: EventFn,
    cycles_remaining: Cycles,
}

#[derive(Default)]
struct Inner {
    events: VecDeque<Event>,
}

impl Inner {
    fn schedule(&mut self, mut new_event: Event) {
        let mut insert_idx = self.events.len();
        for (idx, event) in self.events.iter_mut().enumerate() {
            if new_event.cycles_remaining < event.cycles_remaining {
                event.cycles_remaining -= new_event.cycles_remaining;
                insert_idx = idx;
                break;
            }
            new_event.cycles_remaining -= event.cycles_remaining;
        }
        self.events.insert(insert_idx, new_event);
    }

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if let Some(event) = self.events.front_mut() {
            if event.cycles_remaining > cycles {
                event.cycles_remaining -= cycles;
                return None;
            }
        } else {
            return None;
        }

        let event = self.events.pop_front().unwrap();
        Some((event.callback, cycles - event.cycles_remaining))
    }
}

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if self.has_next_event(cycles) {
            let event = self.events.pop_front().unwrap();
            Some((event.callback, cycles - event.cycles_remaining))
        } else {
            None
        }
    }
}
<commit_msg>Add unit test for scheduler.<commit_after>use super::Gba;
use arm::Cycles;
use std::cell::RefCell;
use std::collections::VecDeque;
use std::rc::Rc;

pub type EventFn = fn(gba: &mut Gba, late: Cycles);

#[derive(Default, Clone)]
pub struct Scheduler {
    inner: Rc<RefCell<Inner>>,
}

impl Scheduler {
    pub fn schedule(&mut self, callback: EventFn, cycles: impl Into<Cycles>) {
        self.inner.borrow_mut().schedule(Event {
            callback,
            cycles_remaining: cycles.into(),
        });
    }

    pub fn advance(&mut self, cycles: impl Into<Cycles>) -> Option<(EventFn, Cycles)> {
        self.inner.borrow_mut().advance(cycles.into())
    }

    #[cfg(test)]
    pub fn dump(&self) {
        for (idx, event) in self.inner.borrow().events.iter().enumerate() {
            println!("EVENT{}: {} cycles", idx, event.cycles_remaining);
        }
    }
}

pub struct Event {
    callback: EventFn,
    cycles_remaining: Cycles,
}

#[derive(Default)]
struct Inner {
    events: VecDeque<Event>,
}

impl Inner {
    fn schedule(&mut self, mut new_event: Event) {
        let mut insert_idx = self.events.len();
        for (idx, event) in self.events.iter_mut().enumerate() {
            if new_event.cycles_remaining < event.cycles_remaining {
                event.cycles_remaining -= new_event.cycles_remaining;
                insert_idx = idx;
                break;
            }
            new_event.cycles_remaining -= event.cycles_remaining;
        }
        self.events.insert(insert_idx, new_event);
    }

    fn advance(&mut self, cycles: Cycles) -> Option<(EventFn, Cycles)> {
        if let Some(event) = self.events.front_mut() {
            if event.cycles_remaining > cycles {
                event.cycles_remaining -= cycles;
                return None;
            }
        } else {
            return None;
        }

        let event = self.events.pop_front().unwrap();
        Some((event.callback, cycles - event.cycles_remaining))
    }
}

#[cfg(test)]
mod test {
    use arm::Cycles;

    use crate::Gba;

    use super::Scheduler;

    #[test]
    fn basic_scheduling() {
        let mut gba = Gba::default();
        let mut scheduler = Scheduler::default();

        scheduler.schedule(|_, _| data()[0] = 1, 10u32);
        scheduler.schedule(|_, _| data()[3] = 1, 17u32);
        scheduler.schedule(|_, _| data()[1] = 1, 13u32);
        scheduler.schedule(|_, _| data()[2] = 1, 13u32);
        scheduler.dump();

        assert!(scheduler.advance(6u32).is_none());
        assert_eq!(data()[0], 0);

        let (cb, cycles) = scheduler.advance(6u32).expect("expected event");
        assert_eq!(cycles, Cycles::from(2u32));
        cb(&mut gba, cycles);
        assert!(scheduler.advance(cycles).is_none());
        assert_eq!(*data(), [1, 0, 0, 0]);

        let (cb, cycles) = scheduler.advance(Cycles::ONE).expect("expected event");
        assert_eq!(cycles, Cycles::ZERO);
        cb(&mut gba, cycles);
        assert_eq!(*data(), [1, 1, 0, 0]);
        let (cb, cycles) = scheduler.advance(cycles).expect("expected event");
        assert_eq!(cycles, Cycles::ZERO);
        cb(&mut gba, cycles);
        assert!(scheduler.advance(cycles).is_none());
        assert_eq!(*data(), [1, 1, 1, 0]);

        let (cb, cycles) = scheduler.advance(8).expect("expected event");
        assert_eq!(cycles, Cycles::from(4u32));
        cb(&mut gba, cycles);
        assert!(scheduler.advance(cycles).is_none());
        assert_eq!(*data(), [1, 1, 1, 1]);

        static mut DATA: [u32; 4] = [0; 4];
        fn data() -> &'static mut [u32; 4] {
            unsafe { &mut DATA }
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt::{self, Debug};
use std::marker::PhantomData;
use std::path::Path;

/// Build configuration. See [CFG].
pub struct Cfg<'a> {
    pub include_prefix: &'a str,
    // Not implemented yet. https://github.com/dtolnay/cxx/issues/417
    #[doc(hidden)]
    pub exported_header_dirs: Vec<&'a Path>,
    #[doc(hidden)]
    pub exported_header_prefixes: Vec<&'a str>,
    #[doc(hidden)]
    pub exported_header_links: Vec<&'a str>,
    marker: PhantomData<*const ()>, // !Send + !Sync
}

/// Global configuration of the current build.
///
///

///
/// ## **`CFG.include_prefix`**
///
/// Presently the only exposed configuration is the `include_prefix`, the prefix
/// at which C++ code from your crate as well as directly dependent crates can
/// access the code generated during this build.
///
/// By default, the `include_prefix` is equal to the name of the current crate.
/// That means if our crate is called `demo` and has Rust source files in a
/// *src/* directory and maybe some handwritten C++ header files in an
/// *include/* directory, then the current crate as well as downstream crates
/// might include them as follows:
///
/// ```
/// # const _: &str = stringify! {
///   // include one of the handwritten headers:
/// #include "demo/include/wow.h"
///
///   // include a header generated from Rust cxx::bridge:
/// #include "demo/src/lib.rs.h"
/// # };
/// ```
///
/// By modifying `CFG.include_prefix` we can substitute a prefix that is
/// different from the crate name if desired. Here we'll change it to
/// `"path/to"` which will make import paths take the form
/// `"path/to/include/wow.h"` and `"path/to/src/lib.rs.h"`.
///
/// ```no_run
/// // build.rs
///
/// use cxx_build::CFG;
///
/// fn main() {
///     CFG.include_prefix = "path/to";
///
///     cxx_build::bridge("src/lib.rs")
///         .file("src/demo.cc") // probably contains `#include "path/to/src/lib.rs.h"`
///         /* ... */
///         .compile("demo");
/// }
/// ```
///
/// Note that cross-crate imports are only made available between **direct
/// dependencies**. Another crate must directly depend on your crate in order to
/// #include its headers; a transitive dependency is not sufficient.
/// Additionally, headers from a direct dependency are only importable if the
/// dependency's Cargo.toml manifest contains a `links` key. If not, its headers
/// will not be importable from outside of the same crate.
#[cfg(doc)]
pub static mut CFG: Cfg = Cfg {
    include_prefix: "",
    exported_header_dirs: Vec::new(),
    exported_header_prefixes: Vec::new(),
    exported_header_links: Vec::new(),
    marker: PhantomData,
};

impl<'a> Debug for Cfg<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_struct("Cfg")
            .field("include_prefix", &self.include_prefix)
            .finish()
    }
}

#[cfg(not(doc))]
pub use self::r#impl::Cfg::CFG;

#[cfg(not(doc))]
mod r#impl {
    use crate::intern::{intern, InternedString};
    use lazy_static::lazy_static;
    use std::cell::RefCell;
    use std::collections::HashMap;
    use std::fmt::{self, Debug};
    use std::marker::PhantomData;
    use std::ops::{Deref, DerefMut};
    use std::sync::{PoisonError, RwLock};

    lazy_static! {
        static ref INCLUDE_PREFIX: RwLock<InternedString> = RwLock::new({
            crate::env_os("CARGO_PKG_NAME")
                .map(|pkg| intern(&pkg.to_string_lossy()))
                .unwrap_or_default()
        });
    }

    thread_local! {
        // FIXME: If https://github.com/rust-lang/rust/issues/77425 is resolved,
        // we can delete this thread local side table and instead make each CFG
        // instance directly own the associated super::Cfg.
        //
        //     #[allow(const_item_mutation)]
        //     pub const CFG: Cfg = Cfg {
        //         cfg: AtomicPtr::new(ptr::null_mut()),
        //     };
        //     pub struct Cfg {
        //         cfg: AtomicPtr<super::Cfg>,
        //     }
        //
        static CONST_DEREFS: RefCell<HashMap<Handle, Box<super::Cfg<'static>>>> = RefCell::default();
    }

    #[derive(Eq, PartialEq, Hash)]
    struct Handle(*const Cfg<'static>);

    impl<'a> Cfg<'a> {
        fn current() -> super::Cfg<'a> {
            let include_prefix = INCLUDE_PREFIX
                .read()
                .unwrap_or_else(PoisonError::into_inner)
                .str();
            super::Cfg {
                include_prefix,
                exported_header_dirs: Vec::new(),
                exported_header_prefixes: Vec::new(),
                exported_header_links: Vec::new(),
                marker: PhantomData,
            }
        }

        const fn handle(self: &Cfg<'a>) -> Handle {
            Handle(<*const Cfg>::cast(self))
        }
    }

    // Since super::Cfg is !Send and !Sync, all Cfg are thread local and will
    // drop on the same thread where they were created.
    pub enum Cfg<'a> {
        Mut(super::Cfg<'a>),
        CFG,
    }

    impl<'a> Debug for Cfg<'a> {
        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            if let Cfg::Mut(cfg) = self {
                Debug::fmt(cfg, formatter)
            } else {
                Debug::fmt(&Cfg::current(), formatter)
            }
        }
    }

    impl<'a> Deref for Cfg<'a> {
        type Target = super::Cfg<'a>;

        fn deref(&self) -> &Self::Target {
            if let Cfg::Mut(cfg) = self {
                cfg
            } else {
                let cfg = CONST_DEREFS.with(|derefs| -> *mut super::Cfg {
                    &mut **derefs
                        .borrow_mut()
                        .entry(self.handle())
                        .or_insert_with(|| Box::new(Cfg::current()))
                });
                unsafe { &mut *cfg }
            }
        }
    }

    impl<'a> DerefMut for Cfg<'a> {
        fn deref_mut(&mut self) -> &mut Self::Target {
            if let Cfg::CFG = self {
                CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
                *self = Cfg::Mut(Cfg::current());
            }
            match self {
                Cfg::Mut(cfg) => cfg,
                Cfg::CFG => unreachable!(),
            }
        }
    }

    impl<'a> Drop for Cfg<'a> {
        fn drop(&mut self) {
            if let Cfg::Mut(cfg) = self {
                *INCLUDE_PREFIX
                    .write()
                    .unwrap_or_else(PoisonError::into_inner) = intern(cfg.include_prefix);
            } else {
                CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
            }
        }
    }
}
<commit_msg>Wire up exported headers storage<commit_after>use std::fmt::{self, Debug};
use std::marker::PhantomData;
use std::path::Path;

/// Build configuration. See [CFG].
pub struct Cfg<'a> {
    pub include_prefix: &'a str,
    // Not implemented yet. https://github.com/dtolnay/cxx/issues/417
    #[doc(hidden)]
    pub exported_header_dirs: Vec<&'a Path>,
    #[doc(hidden)]
    pub exported_header_prefixes: Vec<&'a str>,
    #[doc(hidden)]
    pub exported_header_links: Vec<&'a str>,
    marker: PhantomData<*const ()>, // !Send + !Sync
}

/// Global configuration of the current build.
///
///

///
/// ## **`CFG.include_prefix`**
///
/// Presently the only exposed configuration is the `include_prefix`, the prefix
/// at which C++ code from your crate as well as directly dependent crates can
/// access the code generated during this build.
///
/// By default, the `include_prefix` is equal to the name of the current crate.
/// That means if our crate is called `demo` and has Rust source files in a
/// *src/* directory and maybe some handwritten C++ header files in an
/// *include/* directory, then the current crate as well as downstream crates
/// might include them as follows:
///
/// ```
/// # const _: &str = stringify! {
///   // include one of the handwritten headers:
/// #include "demo/include/wow.h"
///
///   // include a header generated from Rust cxx::bridge:
/// #include "demo/src/lib.rs.h"
/// # };
/// ```
///
/// By modifying `CFG.include_prefix` we can substitute a prefix that is
/// different from the crate name if desired. Here we'll change it to
/// `"path/to"` which will make import paths take the form
/// `"path/to/include/wow.h"` and `"path/to/src/lib.rs.h"`.
///
/// ```no_run
/// // build.rs
///
/// use cxx_build::CFG;
///
/// fn main() {
///     CFG.include_prefix = "path/to";
///
///     cxx_build::bridge("src/lib.rs")
///         .file("src/demo.cc") // probably contains `#include "path/to/src/lib.rs.h"`
///         /* ... */
///         .compile("demo");
/// }
/// ```
///
/// Note that cross-crate imports are only made available between **direct
/// dependencies**. Another crate must directly depend on your crate in order to
/// #include its headers; a transitive dependency is not sufficient.
/// Additionally, headers from a direct dependency are only importable if the
/// dependency's Cargo.toml manifest contains a `links` key. If not, its headers
/// will not be importable from outside of the same crate.
#[cfg(doc)]
pub static mut CFG: Cfg = Cfg {
    include_prefix: "",
    exported_header_dirs: Vec::new(),
    exported_header_prefixes: Vec::new(),
    exported_header_links: Vec::new(),
    marker: PhantomData,
};

impl<'a> Debug for Cfg<'a> {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        formatter
            .debug_struct("Cfg")
            .field("include_prefix", &self.include_prefix)
            .finish()
    }
}

#[cfg(not(doc))]
pub use self::r#impl::Cfg::CFG;

#[cfg(not(doc))]
mod r#impl {
    use crate::intern::{intern, InternedString};
    use lazy_static::lazy_static;
    use std::cell::RefCell;
    use std::collections::HashMap;
    use std::fmt::{self, Debug};
    use std::marker::PhantomData;
    use std::ops::{Deref, DerefMut};
    use std::path::Path;
    use std::sync::{PoisonError, RwLock};

    lazy_static! {
        static ref INCLUDE_PREFIX: RwLock<InternedString> = RwLock::new({
            crate::env_os("CARGO_PKG_NAME")
                .map(|pkg| intern(&pkg.to_string_lossy()))
                .unwrap_or_default()
        });
        static ref EXPORTED_HEADER_DIRS: RwLock<Vec<InternedString>> = RwLock::new(Vec::new());
        static ref EXPORTED_HEADER_PREFIXES: RwLock<Vec<InternedString>> = RwLock::new(Vec::new());
        static ref EXPORTED_HEADER_LINKS: RwLock<Vec<InternedString>> = RwLock::new(Vec::new());
    }

    thread_local! {
        // FIXME: If https://github.com/rust-lang/rust/issues/77425 is resolved,
        // we can delete this thread local side table and instead make each CFG
        // instance directly own the associated super::Cfg.
        //
        //     #[allow(const_item_mutation)]
        //     pub const CFG: Cfg = Cfg {
        //         cfg: AtomicPtr::new(ptr::null_mut()),
        //     };
        //     pub struct Cfg {
        //         cfg: AtomicPtr<super::Cfg>,
        //     }
        //
        static CONST_DEREFS: RefCell<HashMap<Handle, Box<super::Cfg<'static>>>> = RefCell::default();
    }

    #[derive(Eq, PartialEq, Hash)]
    struct Handle(*const Cfg<'static>);

    impl<'a> Cfg<'a> {
        fn current() -> super::Cfg<'a> {
            let include_prefix = INCLUDE_PREFIX
                .read()
                .unwrap_or_else(PoisonError::into_inner)
                .str();
            let exported_header_dirs = EXPORTED_HEADER_DIRS
                .read()
                .unwrap_or_else(PoisonError::into_inner)
                .iter()
                .copied()
                .map(InternedString::str)
                .map(Path::new)
                .collect();
            let exported_header_prefixes = EXPORTED_HEADER_PREFIXES
                .read()
                .unwrap_or_else(PoisonError::into_inner)
                .iter()
                .copied()
                .map(InternedString::str)
                .collect();
            let exported_header_links = EXPORTED_HEADER_LINKS
                .read()
                .unwrap_or_else(PoisonError::into_inner)
                .iter()
                .copied()
                .map(InternedString::str)
                .collect();
            super::Cfg {
                include_prefix,
                exported_header_dirs,
                exported_header_prefixes,
                exported_header_links,
                marker: PhantomData,
            }
        }

        const fn handle(self: &Cfg<'a>) -> Handle {
            Handle(<*const Cfg>::cast(self))
        }
    }

    // Since super::Cfg is !Send and !Sync, all Cfg are thread local and will
    // drop on the same thread where they were created.
    pub enum Cfg<'a> {
        Mut(super::Cfg<'a>),
        CFG,
    }

    impl<'a> Debug for Cfg<'a> {
        fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            if let Cfg::Mut(cfg) = self {
                Debug::fmt(cfg, formatter)
            } else {
                Debug::fmt(&Cfg::current(), formatter)
            }
        }
    }

    impl<'a> Deref for Cfg<'a> {
        type Target = super::Cfg<'a>;

        fn deref(&self) -> &Self::Target {
            if let Cfg::Mut(cfg) = self {
                cfg
            } else {
                let cfg = CONST_DEREFS.with(|derefs| -> *mut super::Cfg {
                    &mut **derefs
                        .borrow_mut()
                        .entry(self.handle())
                        .or_insert_with(|| Box::new(Cfg::current()))
                });
                unsafe { &mut *cfg }
            }
        }
    }

    impl<'a> DerefMut for Cfg<'a> {
        fn deref_mut(&mut self) -> &mut Self::Target {
            if let Cfg::CFG = self {
                CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
                *self = Cfg::Mut(Cfg::current());
            }
            match self {
                Cfg::Mut(cfg) => cfg,
                Cfg::CFG => unreachable!(),
            }
        }
    }

    impl<'a> Drop for Cfg<'a> {
        fn drop(&mut self) {
            if let Cfg::Mut(cfg) = self {
                *INCLUDE_PREFIX
                    .write()
                    .unwrap_or_else(PoisonError::into_inner) = intern(cfg.include_prefix);
                *EXPORTED_HEADER_DIRS
                    .write()
                    .unwrap_or_else(PoisonError::into_inner) = cfg
                    .exported_header_dirs
                    .iter()
                    .copied()
                    .map(|path| intern(&path.to_string_lossy()))
                    .collect();
                *EXPORTED_HEADER_PREFIXES
                    .write()
                    .unwrap_or_else(PoisonError::into_inner) = cfg
                    .exported_header_prefixes
                    .iter()
                    .copied()
                    .map(intern)
                    .collect();
                *EXPORTED_HEADER_LINKS
                    .write()
                    .unwrap_or_else(PoisonError::into_inner) = cfg
                    .exported_header_links
                    .iter()
                    .copied()
                    .map(intern)
                    .collect();
            } else {
                CONST_DEREFS.with(|derefs| derefs.borrow_mut().remove(&self.handle()));
            }
        }
    }
}
<|endoftext|>


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

/// Creates a `Vec` containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a `Vec` containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a `Vec` from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement `Clone` and the number of elements doesn't have to be
/// a constant.
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec($crate::boxed::Box::new([$($x),*]))
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec($crate::boxed::Box::new([$($x),*]))
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Use the syntax described in `std::fmt` to create a value of type `String`.
/// See `std::fmt` for more information.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
    ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
}
<commit_msg>Add note about clone in docs for vec![]<commit_after>// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

/// Creates a `Vec` containing the arguments.
///
/// `vec!` allows `Vec`s to be defined with the same syntax as array expressions.
/// There are two forms of this macro:
///
/// - Create a `Vec` containing a given list of elements:
///
/// ```
/// let v = vec![1, 2, 3];
/// assert_eq!(v[0], 1);
/// assert_eq!(v[1], 2);
/// assert_eq!(v[2], 3);
/// ```
///
/// - Create a `Vec` from a given element and size:
///
/// ```
/// let v = vec![1; 3];
/// assert_eq!(v, [1, 1, 1]);
/// ```
///
/// Note that unlike array expressions this syntax supports all elements
/// which implement `Clone` and the number of elements doesn't have to be
/// a constant.
///
/// This will use `clone()` to duplicate an expression, so one should be careful
/// using this with types having a nonstandard `Clone` implementation. For
/// example, `vec![Rc::new(1); 5]` will create a vector of five references
/// to the same boxed integer value, not five references pointing to independently
/// boxed integers.
#[cfg(not(test))]
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        <[_]>::into_vec($crate::boxed::Box::new([$($x),*]))
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

// HACK(japaric): with cfg(test) the inherent `[T]::into_vec` method, which is
// required for this macro definition, is not available. Instead use the
// `slice::into_vec`  function which is only available with cfg(test)
// NB see the slice::hack module in slice.rs for more information
#[cfg(test)]
macro_rules! vec {
    ($elem:expr; $n:expr) => (
        $crate::vec::from_elem($elem, $n)
    );
    ($($x:expr),*) => (
        $crate::slice::into_vec($crate::boxed::Box::new([$($x),*]))
    );
    ($($x:expr,)*) => (vec![$($x),*])
}

/// Use the syntax described in `std::fmt` to create a value of type `String`.
/// See `std::fmt` for more information.
///
/// # Examples
///
/// ```
/// format!("test");
/// format!("hello {}", "world!");
/// format!("x = {}, y = {y}", 10, y = 30);
/// ```
#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
macro_rules! format {
    ($($arg:tt)*) => ($crate::fmt::format(format_args!($($arg)*)))
}
<|endoftext|>


<commit_before>#![unstable(feature = "futures_api",
            reason = "futures in libcore are unstable",
            issue = "50547")]

use crate::marker::Unpin;
use crate::ops;
use crate::pin::Pin;
use crate::task::{Context, Poll};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The `context` passed to the `poll`
/// method can provide a `Waker`, which is a handle for waking up the current
/// task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
#[doc(spotlight)]
#[must_use = "futures do nothing unless polled"]
pub trait Future {
    /// The type of value produced on completion.
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] copied from the current [`Context`].
    /// This [`Waker`] is then woken once the future can make progress.
    /// For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// `[Waker::wake]` is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the [`Waker`] from the
    /// [`Context`] passed to the most recent call should be scheduled to
    /// receive a wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`), calling its
    /// `poll` method again may panic, block forever, or cause other kinds of
    /// problems; the `Future` trait places no requirements on the effects of
    /// such a call. However, as the `poll` method is not marked `unsafe`,
    /// Rust's usual rules apply: calls must never cause undefined behavior
    /// (memory corruption, incorrect use of `unsafe` functions, or the like),
    /// regardless of the future's state.
    ///
    /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
    /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
    /// [`Context`]: ../task/struct.Context.html
    /// [`Waker`]: ../task/struct.Waker.html
    /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), cx)
    }
}

impl
 Future for Pin

where
    P: Unpin + ops::DerefMut,
    P::Target: Future,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(cx)
    }
}
<commit_msg>core::future::Future: Fix markup typo in docs.<commit_after>#![unstable(feature = "futures_api",
            reason = "futures in libcore are unstable",
            issue = "50547")]

use crate::marker::Unpin;
use crate::ops;
use crate::pin::Pin;
use crate::task::{Context, Poll};

/// A future represents an asynchronous computation.
///
/// A future is a value that may not have finished computing yet. This kind of
/// "asynchronous value" makes it possible for a thread to continue doing useful
/// work while it waits for the value to become available.
///
/// # The `poll` method
///
/// The core method of future, `poll`, *attempts* to resolve the future into a
/// final value. This method does not block if the value is not ready. Instead,
/// the current task is scheduled to be woken up when it's possible to make
/// further progress by `poll`ing again. The `context` passed to the `poll`
/// method can provide a `Waker`, which is a handle for waking up the current
/// task.
///
/// When using a future, you generally won't call `poll` directly, but instead
/// `await!` the value.
#[doc(spotlight)]
#[must_use = "futures do nothing unless polled"]
pub trait Future {
    /// The type of value produced on completion.
    type Output;

    /// Attempt to resolve the future to a final value, registering
    /// the current task for wakeup if the value is not yet available.
    ///
    /// # Return value
    ///
    /// This function returns:
    ///
    /// - [`Poll::Pending`] if the future is not ready yet
    /// - [`Poll::Ready(val)`] with the result `val` of this future if it
    ///   finished successfully.
    ///
    /// Once a future has finished, clients should not `poll` it again.
    ///
    /// When a future is not ready yet, `poll` returns `Poll::Pending` and
    /// stores a clone of the [`Waker`] copied from the current [`Context`].
    /// This [`Waker`] is then woken once the future can make progress.
    /// For example, a future waiting for a socket to become
    /// readable would call `.clone()` on the [`Waker`] and store it.
    /// When a signal arrives elsewhere indicating that the socket is readable,
    /// [`Waker::wake`] is called and the socket future's task is awoken.
    /// Once a task has been woken up, it should attempt to `poll` the future
    /// again, which may or may not produce a final value.
    ///
    /// Note that on multiple calls to `poll`, only the [`Waker`] from the
    /// [`Context`] passed to the most recent call should be scheduled to
    /// receive a wakeup.
    ///
    /// # Runtime characteristics
    ///
    /// Futures alone are *inert*; they must be *actively* `poll`ed to make
    /// progress, meaning that each time the current task is woken up, it should
    /// actively re-`poll` pending futures that it still has an interest in.
    ///
    /// The `poll` function is not called repeatedly in a tight loop -- instead,
    /// it should only be called when the future indicates that it is ready to
    /// make progress (by calling `wake()`). If you're familiar with the
    /// `poll(2)` or `select(2)` syscalls on Unix it's worth noting that futures
    /// typically do *not* suffer the same problems of "all wakeups must poll
    /// all events"; they are more like `epoll(4)`.
    ///
    /// An implementation of `poll` should strive to return quickly, and should
    /// not block. Returning quickly prevents unnecessarily clogging up
    /// threads or event loops. If it is known ahead of time that a call to
    /// `poll` may end up taking awhile, the work should be offloaded to a
    /// thread pool (or something similar) to ensure that `poll` can return
    /// quickly.
    ///
    /// # Panics
    ///
    /// Once a future has completed (returned `Ready` from `poll`), calling its
    /// `poll` method again may panic, block forever, or cause other kinds of
    /// problems; the `Future` trait places no requirements on the effects of
    /// such a call. However, as the `poll` method is not marked `unsafe`,
    /// Rust's usual rules apply: calls must never cause undefined behavior
    /// (memory corruption, incorrect use of `unsafe` functions, or the like),
    /// regardless of the future's state.
    ///
    /// [`Poll::Pending`]: ../task/enum.Poll.html#variant.Pending
    /// [`Poll::Ready(val)`]: ../task/enum.Poll.html#variant.Ready
    /// [`Context`]: ../task/struct.Context.html
    /// [`Waker`]: ../task/struct.Waker.html
    /// [`Waker::wake`]: ../task/struct.Waker.html#method.wake
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
}

impl<F: ?Sized + Future + Unpin> Future for &mut F {
    type Output = F::Output;

    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        F::poll(Pin::new(&mut **self), cx)
    }
}

impl
 Future for Pin

where
    P: Unpin + ops::DerefMut,
    P::Target: Future,
{
    type Output = <
::Target as Future>::Output;

    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        Pin::get_mut(self).as_mut().poll(cx)
    }
}
<|endoftext|>


<commit_before>use crate::alloc::{GlobalAlloc, Layout, System};
use crate::ptr;
use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};
use libc;

#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
    #[inline]
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
            libc::malloc(layout.size()) as *mut u8
        } else {
            libc::aligned_alloc(layout.size(), layout.align()) as *mut u8
        }
    }

    #[inline]
    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
            libc::calloc(layout.size(), 1) as *mut u8
        } else {
            let ptr = self.alloc(layout.clone());
            if !ptr.is_null() {
                ptr::write_bytes(ptr, 0, layout.size());
            }
            ptr
        }
    }

    #[inline]
    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
        libc::free(ptr as *mut libc::c_void)
    }

    #[inline]
    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
        if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
            libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
        } else {
            realloc_fallback(self, ptr, layout, new_size)
        }
    }
}
<commit_msg>std: Fix over-aligned allocations on wasm32-wasi<commit_after>use crate::alloc::{GlobalAlloc, Layout, System};
use crate::ptr;
use crate::sys_common::alloc::{realloc_fallback, MIN_ALIGN};
use libc;

#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
    #[inline]
    unsafe fn alloc(&self, layout: Layout) -> *mut u8 {
        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
            libc::malloc(layout.size()) as *mut u8
        } else {
            libc::aligned_alloc(layout.align(), layout.size()) as *mut u8
        }
    }

    #[inline]
    unsafe fn alloc_zeroed(&self, layout: Layout) -> *mut u8 {
        if layout.align() <= MIN_ALIGN && layout.align() <= layout.size() {
            libc::calloc(layout.size(), 1) as *mut u8
        } else {
            let ptr = self.alloc(layout.clone());
            if !ptr.is_null() {
                ptr::write_bytes(ptr, 0, layout.size());
            }
            ptr
        }
    }

    #[inline]
    unsafe fn dealloc(&self, ptr: *mut u8, _layout: Layout) {
        libc::free(ptr as *mut libc::c_void)
    }

    #[inline]
    unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 {
        if layout.align() <= MIN_ALIGN && layout.align() <= new_size {
            libc::realloc(ptr as *mut libc::c_void, new_size) as *mut u8
        } else {
            realloc_fallback(self, ptr, layout, new_size)
        }
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use criterion::*;
use rand::{Rng, SeedableRng};
use rand_chacha::ChaChaRng;
use rav1e::bench::transform;

fn bench_idct4(b: &mut Bencher, bit_depth: &usize) {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let input: [i32; 4] = ra.gen();
  let mut output = [0i32; 4];
  let range = bit_depth + 8;

  b.iter(|| {
    transform::av1_idct4(&input[..], &mut output[..], range);
  });
}

pub fn av1_idct4(c: &mut Criterion) {
  let plain = Fun::new("plain", bench_idct4);
  let funcs = vec![plain];

  c.bench_functions("av1_idct4_8", funcs, 8);
}

fn bench_idct8(b: &mut Bencher, bit_depth: &usize) {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let input: [i32; 8] = ra.gen();
  let mut output = [0i32; 8];
  let range = bit_depth + 8;

  b.iter(|| {
    transform::av1_idct8(&input[..], &mut output[..], range);
  });
}

pub fn av1_idct8(c: &mut Criterion) {
  let plain = Fun::new("plain", bench_idct8);
  let funcs = vec![plain];

  c.bench_functions("av1_idct8_8", funcs, 8);
}

criterion_group!(transform, av1_idct4, av1_idct8);
<commit_msg>Simplify transform benchmarks<commit_after>// Copyright (c) 2017-2018, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use criterion::*;
use rand::{Rng, SeedableRng};
use rand_chacha::ChaChaRng;
use rav1e::bench::transform;

fn init_buffers(size: usize) -> (Vec<i32>, Vec<i32>) {
  let mut ra = ChaChaRng::from_seed([0; 32]);
  let input: Vec<i32> = (0..size).map(|_| ra.gen()).collect();
  let output = vec![0i32; size];

  (input, output)
}

pub fn av1_idct4(c: &mut Criterion) {
  let (input, mut output) = init_buffers(4);

  c.bench_function("av1_idct4_8", move |b| b.iter(
    || transform::av1_idct4(&input[..], &mut output[..], 16)));
}

pub fn av1_idct8(c: &mut Criterion) {
  let (input, mut output) = init_buffers(8);

  c.bench_function("av1_idct8_8", move |b| b.iter(
    || transform::av1_idct8(&input[..], &mut output[..], 16)));
}

criterion_group!(transform, av1_idct4, av1_idct8);
<|endoftext|>


<commit_before>use desync::scheduler::*;

use super::timeout::*;

#[test]
fn will_despawn_extra_threads() {
    // As we join with the threads, we'll timeout if any of the spawned threads fail to end
    let scheduler = scheduler();

    // Maximum of 10 threads, but we'll spawn 20
    scheduler.set_max_threads(10);
    for _ in 1..20 {
        scheduler.spawn_thread();
    }

    scheduler.despawn_threads_if_overloaded();
}
<commit_msg>This is unused<commit_after>use desync::scheduler::*;

#[test]
fn will_despawn_extra_threads() {
    // As we join with the threads, we'll timeout if any of the spawned threads fail to end
    let scheduler = scheduler();

    // Maximum of 10 threads, but we'll spawn 20
    scheduler.set_max_threads(10);
    for _ in 1..20 {
        scheduler.spawn_thread();
    }

    scheduler.despawn_threads_if_overloaded();
}
<|endoftext|>


<commit_before>#[crate_id(name="hostname", vers="1.0.0", author="Alan Andrade")];
/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Jordi Boggiano <j.boggiano@seld.be>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * Synced with:
 *
 * https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt
 */

extern mod extra;

use std::{os,libc,vec,str};
use extra::getopts::{optflag, getopts};

extern {
    fn gethostname(name: *libc::c_char, namelen: libc::size_t) -> libc::c_int;
    fn sethostname(name: *libc::c_char, namelen: libc::c_int) -> libc::c_int;
}

fn main () {
    let args = os::args();

    let options = [
        optflag("f"),
        optflag("s")
    ];

    let matches = match getopts(args.tail(), options) {
        Ok(m) => { m }
        _ => { usage(); return; }
    };

    match matches.free.len() {
        0 => {
            let hostname: ~str = xgethostname();

            if matches.opt_present("s") {
                let pos = hostname.find_str(".");
                if pos.is_some() {
                    println!("{:s}", hostname.slice_to(pos.unwrap()));
                    return;
                }
            }

            println!("{:s}", hostname);
        }
        1 => { xsethostname( matches.free.last().unwrap() ) }
        _ => { usage() }
    };
}

fn usage() {
    println!("usage: hostname [-fs] [name-of-host]");
}

fn xgethostname() -> ~str {
    let namelen = 255u;
    let mut name = vec::from_elem(namelen, 0u8);

    let err = unsafe {
        gethostname (name.as_mut_ptr() as *libc::c_char,
                                        namelen as libc::size_t)
    };

    if err != 0 {
        fail!("Cannot determine hostname");
    }

    let last_char = name.iter().position(|byte| *byte == 0).unwrap_or(namelen);

    str::from_utf8(name.slice_to(last_char)).unwrap().to_owned()
}

fn xsethostname(name: &~str) {
    let vec_name: ~[libc::c_char] = name.bytes().map(|c| c as i8).collect();

    let err = unsafe {
        sethostname (vec_name.as_ptr(), vec_name.len() as i32)
    };

    if err != 0 {
        println!("Cannot set hostname to {:s}", *name);
    }
}
<commit_msg>Add -h help and -V version flags<commit_after>#[crate_id(name="hostname", vers="1.0.0", author="Alan Andrade")];
/*
 * This file is part of the uutils coreutils package.
 *
 * (c) Alan Andrade <alan.andradec@gmail.com>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 *
 * Synced with:
 *
 * https://www.opensource.apple.com/source/shell_cmds/shell_cmds-170/hostname/hostname.c?txt
 */

extern mod extra;
extern mod getopts;

use std::{os,libc,vec,str};
use getopts::{optflag, getopts, usage};

extern {
    fn gethostname(name: *libc::c_char, namelen: libc::size_t) -> libc::c_int;
    fn sethostname(name: *libc::c_char, namelen: libc::c_int) -> libc::c_int;
}

fn main () {
    let args = os::args();
    let program = args[0].to_owned();

    let options = [
        optflag("f", "full", "Default option to show full name"),
        optflag("s", "slice subdomain", "Cuts the subdomain off if any"),
        optflag("h", "help", "Show help"),
        optflag("V", "version", "Show program's version")
    ];

    let matches = match getopts(args.tail(), options) {
        Ok(m) => { m }
        _ => { println!("{:s}", usage(program, options)); return; }
    };

    if matches.opt_present("h") {
        println!("{:s}", usage(program, options));
        return
    }
    if matches.opt_present("V") { version(); return }

    match matches.free.len() {
        0 => {
            let hostname: ~str = xgethostname();

            if matches.opt_present("s") {
                let pos = hostname.find_str(".");
                if pos.is_some() {
                    println!("{:s}", hostname.slice_to(pos.unwrap()));
                    return;
                }
            }

            println!("{:s}", hostname);
        }
        1 => { xsethostname( matches.free.last().unwrap() ) }
        _ => { println!("{:s}", usage(program, options)); }
    };
}

fn version() {
    println!("hostname version 1.0.0");
}

fn xgethostname() -> ~str {
    let namelen = 255u;
    let mut name = vec::from_elem(namelen, 0u8);

    let err = unsafe {
        gethostname (name.as_mut_ptr() as *libc::c_char,
                                        namelen as libc::size_t)
    };

    if err != 0 {
        fail!("Cannot determine hostname");
    }

    let last_char = name.iter().position(|byte| *byte == 0).unwrap_or(namelen);

    str::from_utf8(name.slice_to(last_char)).unwrap().to_owned()
}

fn xsethostname(name: &~str) {
    let vec_name: ~[libc::c_char] = name.bytes().map(|c| c as i8).collect();

    let err = unsafe {
        sethostname (vec_name.as_ptr(), vec_name.len() as i32)
    };

    if err != 0 {
        println!("Cannot set hostname to {:s}", *name);
    }
}
<|endoftext|>


<commit_before>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Entropy generator, or wrapper around external generators

#![allow(deprecated)]   // whole module is deprecated

use rand_core::{RngCore, CryptoRng, Error};
#[allow(unused)]
use crate::rngs::OsRng;

/// An interface returning random data from external source(s), provided
/// specifically for securely seeding algorithmic generators (PRNGs).
///
/// This is deprecated. It is suggested you use [`rngs::OsRng`] instead.
///
/// [`rngs::OsRng`]: crate::rngs::OsRng
#[derive(Debug)]
#[deprecated(since="0.7.0", note="use rngs::OsRng instead")]
pub struct EntropyRng {
    source: OsRng,
}

impl EntropyRng {
    /// Create a new `EntropyRng`.
    ///
    /// This method will do no system calls or other initialization routines,
    /// those are done on first use. This is done to make `new` infallible,
    /// and `try_fill_bytes` the only place to report errors.
    pub fn new() -> Self {
        EntropyRng { source: OsRng }
    }
}

impl Default for EntropyRng {
    fn default() -> Self {
        EntropyRng::new()
    }
}

impl RngCore for EntropyRng {
    fn next_u32(&mut self) -> u32 {
        self.source.next_u32()
    }

    fn next_u64(&mut self) -> u64 {
        self.source.next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.source.fill_bytes(dest)
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.source.try_fill_bytes(dest)
    }
}

impl CryptoRng for EntropyRng {}

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

    #[test]
    fn test_entropy() {
        let mut rng = EntropyRng::new();
        let n = (rng.next_u32() ^ rng.next_u32()).count_ones();
        assert!(n >= 2);    // p(failure) approx 1e-7
    }
}
<commit_msg>Remove useless annotation<commit_after>// Copyright 2018 Developers of the Rand project.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! Entropy generator, or wrapper around external generators

#![allow(deprecated)]   // whole module is deprecated

use rand_core::{RngCore, CryptoRng, Error};
use crate::rngs::OsRng;

/// An interface returning random data from external source(s), provided
/// specifically for securely seeding algorithmic generators (PRNGs).
///
/// This is deprecated. It is suggested you use [`rngs::OsRng`] instead.
///
/// [`rngs::OsRng`]: crate::rngs::OsRng
#[derive(Debug)]
#[deprecated(since="0.7.0", note="use rngs::OsRng instead")]
pub struct EntropyRng {
    source: OsRng,
}

impl EntropyRng {
    /// Create a new `EntropyRng`.
    ///
    /// This method will do no system calls or other initialization routines,
    /// those are done on first use. This is done to make `new` infallible,
    /// and `try_fill_bytes` the only place to report errors.
    pub fn new() -> Self {
        EntropyRng { source: OsRng }
    }
}

impl Default for EntropyRng {
    fn default() -> Self {
        EntropyRng::new()
    }
}

impl RngCore for EntropyRng {
    fn next_u32(&mut self) -> u32 {
        self.source.next_u32()
    }

    fn next_u64(&mut self) -> u64 {
        self.source.next_u64()
    }

    fn fill_bytes(&mut self, dest: &mut [u8]) {
        self.source.fill_bytes(dest)
    }

    fn try_fill_bytes(&mut self, dest: &mut [u8]) -> Result<(), Error> {
        self.source.try_fill_bytes(dest)
    }
}

impl CryptoRng for EntropyRng {}

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

    #[test]
    fn test_entropy() {
        let mut rng = EntropyRng::new();
        let n = (rng.next_u32() ^ rng.next_u32()).count_ones();
        assert!(n >= 2);    // p(failure) approx 1e-7
    }
}
<|endoftext|>


<commit_before>use std::marker;

trait Vector {
  fn size(&self) -> usize;

  //fn as_array<T: Sized>() -> &[T]
}

struct ArrayVector {
  array: [i32; 1]
}

impl Vector for ArrayVector {
 fn size(&self) -> usize {
  self.array.len()
 }
}

trait RowBlock<'b> {
  fn vector(&'b self, cid: usize) -> &'b Vector;
}

struct AssemblyRowBlock<'b> {
  vectors: Vec<Box<&'b Vector>>
}

impl<'b> AssemblyRowBlock<'b> {
  fn set_vector(&mut self, v: &'b Vector) {
    self.vectors.push(Box::new(v));
  }
}

impl<'b> RowBlock<'b> for AssemblyRowBlock<'b> {
 fn vector(&self, cid: usize) -> &'b Vector {
   *self.vectors[cid]
 }
}

struct YRowBlock<'a> {
  vectors: Vec<Box<Vector>>,
  _marker: marker::PhantomData<&'a ()>
}

impl<'a> YRowBlock<'a> {
  fn set_vector(&mut self, v: Box<Vector>) {
    self.vectors.push(v);
  }
}

impl<'a> RowBlock<'a> for YRowBlock<'a> {
 fn vector(&'a self, cid: usize) -> &'a Vector {
   &*self.vectors[cid]
 }
}

#[test]
fn test_yrowblock() {
  let mut y = YRowBlock {vectors: Vec::new(), _marker: marker::PhantomData};
  let vector = ArrayVector {array: [0]};
  y.set_vector(Box::new(vector));

  let mut ass = AssemblyRowBlock {vectors: Vec::new()};
  ass.set_vector(y.vector(0));
  let v: &Vector = ass.vector(0);
}<commit_msg>Implement Drop for ArrayVEctor.<commit_after>use alloc::heap;
use std::marker;

use common::constant::VECTOR_SIZE;
use intrinsics::sse;
use types::{Ty, DataTy, HasDataTy};

trait Vector {
  fn size(&self) -> usize;

  //fn as_array<T: Sized>() -> &[T];
}

struct ArrayVector {
  ptr: *mut u8,
  data_ty: DataTy
}

impl ArrayVector {
  pub fn new(data_ty: &DataTy) -> ArrayVector {
    let alloc_size = sse::compute_aligned_size(
      data_ty.bytes_len() as usize * VECTOR_SIZE);

    let ptr = unsafe {
      heap::allocate(alloc_size, sse::ALIGNED_SIZE)
    };

    ArrayVector {
      ptr: ptr,
      data_ty: data_ty.clone(),
    }
  }
}

impl Drop for ArrayVector {
  fn drop(&mut self) {
    unsafe {
      let alloc_size = sse::compute_aligned_size(
        self.data_ty.bytes_len() as usize * VECTOR_SIZE);

      heap::deallocate(self.ptr as *mut u8, alloc_size, sse::ALIGNED_SIZE);
    }
  }
}

impl Vector for ArrayVector {
 fn size(&self) -> usize {
  VECTOR_SIZE
 }
}

trait RowBlock<'b> {
  fn vector(&'b self, cid: usize) -> &'b Vector;
}

struct AssemblyRowBlock<'b> {
  vectors: Vec<Box<&'b Vector>>
}

impl<'b> AssemblyRowBlock<'b> {
  fn set_vector(&mut self, v: &'b Vector) {
    self.vectors.push(Box::new(v));
  }
}

impl<'b> RowBlock<'b> for AssemblyRowBlock<'b> {
 fn vector(&self, cid: usize) -> &'b Vector {
   *self.vectors[cid]
 }
}

struct YRowBlock<'a> {
  vectors: Vec<Box<Vector>>,
  _marker: marker::PhantomData<&'a ()>
}

impl<'a> YRowBlock<'a> {
  fn set_vector(&mut self, v: Box<Vector>) {
    self.vectors.push(v);
  }
}

impl<'a> RowBlock<'a> for YRowBlock<'a> {
 fn vector(&'a self, cid: usize) -> &'a Vector {
   &*self.vectors[cid]
 }
}

#[test]
fn test_yrowblock() {
  let mut y = YRowBlock {vectors: Vec::new(), _marker: marker::PhantomData};
  let vector = ArrayVector::new(&DataTy::new(Ty::Int4));
  y.set_vector(Box::new(vector));

  let mut ass = AssemblyRowBlock {vectors: Vec::new()};
  ass.set_vector(y.vector(0));
  let v: &Vector = ass.vector(0);
}<|endoftext|>


<commit_before>//! Loop movement balance analysis.
//!
//! This analysis determines, for the body of a loop, whether its net movement is an exact
//! amount, an unknown amount in a given direction, or unknown altogether. This is used by the
//! bound checking analysis when it encounters loops.

use std::collections::HashMap;
use peephole::{Statement, Program};

/// The body of a loop is a boxed slice of `Statement`s.
pub type LoopBody = Box<[Statement]>;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
/// The net movement of a loop.
pub enum LoopBalance {
    /// The exact movement of one iteration.
    Exact(isize),
    /// May move right but not left.
    RightOnly,
    /// May move left but not right.
    LeftOnly,
    /// Net movement may be either direction.
    Unknown,
}

/// An index to a loop.
///
/// This is represented as the address of the first instruction of the loop.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct LoopIndex(usize);

/// The computed net movement for each loop.
#[derive(Debug)]
pub struct LoopBalanceMap(HashMap<LoopIndex, LoopBalance>);

impl LoopBalance {
    /// Is the loop body exactly balanced between right and left?
    pub fn is_balanced(self) -> bool {
        self == LoopBalance::Exact(0)
    }

    /// Does the loop move net right (if at all)?
    pub fn is_right_only(self) -> bool {
        use self::LoopBalance::*;

        match self {
            Exact(disp) => disp >= 0,
            RightOnly   => true,
            LeftOnly    => false,
            Unknown     => false,
        }
    }

    /// Does the loop move net left (if at all)?
    pub fn is_left_only(self) -> bool {
        use self::LoopBalance::*;

        match self {
            Exact(disp) => disp <= 0,
            RightOnly   => false,
            LeftOnly    => true,
            Unknown     => false,
        }
    }
}

impl LoopIndex {
    /// Gets the loop index from a boxed loop.
    fn from_loop_body(body: &LoopBody) -> Self {
        LoopIndex(body.as_ptr() as usize)
    }
}

impl LoopBalanceMap {
    /// Initializes the map for the given program.
    pub fn new(program: &Program) -> Self {
        let mut lbm = LoopBalanceMap(HashMap::new());

        for statement in program {
            match *statement {
                Statement::Instr(_) => (),
                Statement::Loop(ref body) => {
                    lbm.analyze_loop(body);
                }
            }
        }

        lbm
    }

    /// Gets the balance of the given loop body.
    pub fn get(&self, body: &LoopBody) -> LoopBalance {
        *self.0.get(&LoopIndex::from_loop_body(body)).unwrap_or(&LoopBalance::Unknown)
    }

    /// Performs the analysis for the given loop body and any sub-loops.
    ///
    /// Stores the result of the analysis in `self`.
    fn analyze_loop(&mut self, body: &LoopBody) -> LoopBalance {
        use peephole::Statement::*;
        use common::Instruction::*;
        use self::LoopBalance::*;

        let mut net = Exact(0);

        for statement in &**body {
            match *statement {
                Instr(Right(count)) => net = match net {
                    Exact(disp) => Exact(disp + count as isize),
                    RightOnly   => RightOnly,
                    _           => Unknown,
                },

                Instr(Left(count)) => net = match net {
                    Exact(disp) => Exact(disp - count as isize),
                    LeftOnly    => LeftOnly,
                    _           => Unknown,
                },

                Instr(Add(_)) | Instr(In) | Instr(Out) => (),

                Instr(JumpZero(_)) | Instr(JumpNotZero(_)) =>
                    panic!("unexpected jump instruction"),

                Instr(SetZero) | Instr(OffsetAddRight(_)) | Instr(OffsetAddLeft(_)) => (),

                Instr(FindZeroRight(_)) =>
                    net = if net.is_right_only() { RightOnly } else { Unknown },

                Instr(FindZeroLeft(_)) =>
                    net = if net.is_left_only() { LeftOnly } else { Unknown },

                Loop(ref body) => {
                    let body = self.analyze_loop(body);

                    net = match net {
                        Exact(disp) if body.is_balanced()                   => Exact(disp),
                        _ if net.is_right_only() && body.is_right_only()    => RightOnly,
                        _ if net.is_left_only() && body.is_left_only()      => LeftOnly,
                        _                                                   => Unknown,
                    }
                }
            }
        }

        self.0.insert(LoopIndex::from_loop_body(body), net);

        net
    }
}
<commit_msg>Renamed a variable.<commit_after>//! Loop movement balance analysis.
//!
//! This analysis determines, for the body of a loop, whether its net movement is an exact
//! amount, an unknown amount in a given direction, or unknown altogether. This is used by the
//! bound checking analysis when it encounters loops.

use std::collections::HashMap;
use peephole::{Statement, Program};

/// The body of a loop is a boxed slice of `Statement`s.
pub type LoopBody = Box<[Statement]>;

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
/// The net movement of a loop.
pub enum LoopBalance {
    /// The exact movement of one iteration.
    Exact(isize),
    /// May move right but not left.
    RightOnly,
    /// May move left but not right.
    LeftOnly,
    /// Net movement may be either direction.
    Unknown,
}

/// An index to a loop.
///
/// This is represented as the address of the first instruction of the loop.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq)]
struct LoopIndex(usize);

/// The computed net movement for each loop.
#[derive(Debug)]
pub struct LoopBalanceMap(HashMap<LoopIndex, LoopBalance>);

impl LoopBalance {
    /// Is the loop body exactly balanced between right and left?
    pub fn is_balanced(self) -> bool {
        self == LoopBalance::Exact(0)
    }

    /// Does the loop move net right (if at all)?
    pub fn is_right_only(self) -> bool {
        use self::LoopBalance::*;

        match self {
            Exact(disp) => disp >= 0,
            RightOnly   => true,
            LeftOnly    => false,
            Unknown     => false,
        }
    }

    /// Does the loop move net left (if at all)?
    pub fn is_left_only(self) -> bool {
        use self::LoopBalance::*;

        match self {
            Exact(disp) => disp <= 0,
            RightOnly   => false,
            LeftOnly    => true,
            Unknown     => false,
        }
    }
}

impl LoopIndex {
    /// Gets the loop index from a boxed loop.
    fn from_loop_body(body: &LoopBody) -> Self {
        LoopIndex(body.as_ptr() as usize)
    }
}

impl LoopBalanceMap {
    /// Initializes the map for the given program.
    pub fn new(program: &Program) -> Self {
        let mut result = LoopBalanceMap(HashMap::new());

        for statement in program {
            match *statement {
                Statement::Instr(_) => (),
                Statement::Loop(ref body) => {
                    result.analyze_loop(body);
                }
            }
        }

        result
    }

    /// Gets the balance of the given loop body.
    pub fn get(&self, body: &LoopBody) -> LoopBalance {
        *self.0.get(&LoopIndex::from_loop_body(body)).unwrap_or(&LoopBalance::Unknown)
    }

    /// Performs the analysis for the given loop body and any sub-loops.
    ///
    /// Stores the result of the analysis in `self`.
    fn analyze_loop(&mut self, body: &LoopBody) -> LoopBalance {
        use peephole::Statement::*;
        use common::Instruction::*;
        use self::LoopBalance::*;

        let mut net = Exact(0);

        for statement in &**body {
            match *statement {
                Instr(Right(count)) => net = match net {
                    Exact(disp) => Exact(disp + count as isize),
                    RightOnly   => RightOnly,
                    _           => Unknown,
                },

                Instr(Left(count)) => net = match net {
                    Exact(disp) => Exact(disp - count as isize),
                    LeftOnly    => LeftOnly,
                    _           => Unknown,
                },

                Instr(Add(_)) | Instr(In) | Instr(Out) => (),

                Instr(JumpZero(_)) | Instr(JumpNotZero(_)) =>
                    panic!("unexpected jump instruction"),

                Instr(SetZero) | Instr(OffsetAddRight(_)) | Instr(OffsetAddLeft(_)) => (),

                Instr(FindZeroRight(_)) =>
                    net = if net.is_right_only() { RightOnly } else { Unknown },

                Instr(FindZeroLeft(_)) =>
                    net = if net.is_left_only() { LeftOnly } else { Unknown },

                Loop(ref body) => {
                    let body = self.analyze_loop(body);

                    net = match net {
                        Exact(disp) if body.is_balanced()                   => Exact(disp),
                        _ if net.is_right_only() && body.is_right_only()    => RightOnly,
                        _ if net.is_left_only() && body.is_left_only()      => LeftOnly,
                        _                                                   => Unknown,
                    }
                }
            }
        }

        self.0.insert(LoopIndex::from_loop_body(body), net);

        net
    }
}
<|endoftext|>