<commit_before>//! Collection types.

#![stable(feature = "rust1", since = "1.0.0")]

#[cfg(not(no_global_oom_handling))]
pub mod binary_heap;
#[cfg(not(no_global_oom_handling))]
mod btree;
#[cfg(not(no_global_oom_handling))]
pub mod linked_list;
#[cfg(not(no_global_oom_handling))]
pub mod vec_deque;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_map {
    //! A map based on a B-Tree.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub use super::btree::map::*;
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_set {
    //! A set based on a B-Tree.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub use super::btree::set::*;
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use binary_heap::BinaryHeap;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use btree_map::BTreeMap;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use btree_set::BTreeSet;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use linked_list::LinkedList;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use vec_deque::VecDeque;

use crate::alloc::{Layout, LayoutError};
use core::fmt::Display;

/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
pub enum TryReserveError {
    /// Error due to the computed capacity exceeding the collection's maximum
    /// (usually `isize::MAX` bytes).
    CapacityOverflow,

    /// The memory allocator returned an error
    AllocError {
        /// The layout of allocation request that failed
        layout: Layout,

        #[doc(hidden)]
        #[unstable(
            feature = "container_error_extra",
            issue = "none",
            reason = "\
            Enable exposing the allocator’s custom error value \
            if an associated type is added in the future: \
            https://github.com/rust-lang/wg-allocators/issues/23"
        )]
        non_exhaustive: (),
    },
}

#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
impl From<LayoutError> for TryReserveError {
    #[inline]
    fn from(_: LayoutError) -> Self {
        TryReserveError::CapacityOverflow
    }
}

#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
impl Display for TryReserveError {
    fn fmt(
        &self,
        fmt: &mut core::fmt::Formatter<'_>,
    ) -> core::result::Result<(), core::fmt::Error> {
        fmt.write_str("memory allocation failed")?;
        let reason = match &self {
            TryReserveError::CapacityOverflow => {
                " because the computed capacity exceeded the collection's maximum"
            }
            TryReserveError::AllocError { .. } => " because the memory allocator returned a error",
        };
        fmt.write_str(reason)
    }
}

/// An intermediate trait for specialization of `Extend`.
#[doc(hidden)]
trait SpecExtend<I: IntoIterator> {
    /// Extends `self` with the contents of the given iterator.
    fn spec_extend(&mut self, iter: I);
}
<commit_msg>Rollup merge of #86917 - notriddle:notriddle/from-try-reserve-error, r=JohnTitor<commit_after>//! Collection types.

#![stable(feature = "rust1", since = "1.0.0")]

#[cfg(not(no_global_oom_handling))]
pub mod binary_heap;
#[cfg(not(no_global_oom_handling))]
mod btree;
#[cfg(not(no_global_oom_handling))]
pub mod linked_list;
#[cfg(not(no_global_oom_handling))]
pub mod vec_deque;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_map {
    //! A map based on a B-Tree.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub use super::btree::map::*;
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
pub mod btree_set {
    //! A set based on a B-Tree.
    #[stable(feature = "rust1", since = "1.0.0")]
    pub use super::btree::set::*;
}

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use binary_heap::BinaryHeap;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use btree_map::BTreeMap;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use btree_set::BTreeSet;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use linked_list::LinkedList;

#[cfg(not(no_global_oom_handling))]
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)]
pub use vec_deque::VecDeque;

use crate::alloc::{Layout, LayoutError};
use core::fmt::Display;

/// The error type for `try_reserve` methods.
#[derive(Clone, PartialEq, Eq, Debug)]
#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
pub enum TryReserveError {
    /// Error due to the computed capacity exceeding the collection's maximum
    /// (usually `isize::MAX` bytes).
    CapacityOverflow,

    /// The memory allocator returned an error
    AllocError {
        /// The layout of allocation request that failed
        layout: Layout,

        #[doc(hidden)]
        #[unstable(
            feature = "container_error_extra",
            issue = "none",
            reason = "\
            Enable exposing the allocator’s custom error value \
            if an associated type is added in the future: \
            https://github.com/rust-lang/wg-allocators/issues/23"
        )]
        non_exhaustive: (),
    },
}

#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
impl From<LayoutError> for TryReserveError {
    /// Always evaluates to [`TryReserveError::CapacityOverflow`].
    #[inline]
    fn from(_: LayoutError) -> Self {
        TryReserveError::CapacityOverflow
    }
}

#[unstable(feature = "try_reserve", reason = "new API", issue = "48043")]
impl Display for TryReserveError {
    fn fmt(
        &self,
        fmt: &mut core::fmt::Formatter<'_>,
    ) -> core::result::Result<(), core::fmt::Error> {
        fmt.write_str("memory allocation failed")?;
        let reason = match &self {
            TryReserveError::CapacityOverflow => {
                " because the computed capacity exceeded the collection's maximum"
            }
            TryReserveError::AllocError { .. } => " because the memory allocator returned a error",
        };
        fmt.write_str(reason)
    }
}

/// An intermediate trait for specialization of `Extend`.
#[doc(hidden)]
trait SpecExtend<I: IntoIterator> {
    /// Extends `self` with the contents of the given iterator.
    fn spec_extend(&mut self, iter: I);
}
<|endoftext|>


<commit_before>//These benchmarks should currently not be considered complete, extensive or significant.
//Also indexing is currently too slow. So using them is not really fun.
#![feature(test)]
extern crate rand;
extern crate test;
extern crate perlin;
#[macro_use]
extern crate lazy_static;

mod utils;

use utils::*;

use perlin::index::boolean_index::BooleanIndex;

lazy_static!{
    pub static ref INDICES: [BooleanIndex<usize>; 3] = [
        prepare_index(1_000, 500), //1.000 documents with 500 terms a 8bytes = 4MB
        prepare_index(10_000, 500), //10.000 documents with 500 terms a 8bytes = 40MB
        prepare_index(1_000, 5000), //100.000 documents with 1000 terms a 8bytes = 800MB
    ];
}

macro_rules! bench {
    ($query:expr) =>
    {

        #[bench]
        fn typical_first_ten(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[0].execute_query($query).take(10).count())
            );
        }

        #[bench]
        fn large_collection_first_ten(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[1].execute_query($query).take(10).count())
            );
        }

        #[bench]
        fn large_documents_first_ten(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[2].execute_query($query).take(10).count())
            );
        }

        #[bench]
        fn typical(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[0].execute_query($query).count())
            );
        }

        #[bench]
        fn large_collection(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[1].execute_query($query).count())
            );
        }

        #[bench]
        fn large_documents_collection(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[2].execute_query($query).count())
            );
        }
    }
}

macro_rules! build_bench {
    ($name:ident, $query:expr) => (
        mod $name {
            use super::*;
            use test::Bencher;
            use perlin::index::boolean_index::*;
            use perlin::index::Index;
            use test::black_box;
            bench!{$query}
        }

    )

}

build_bench!(and_seldom_seldom, &QueryBuilder::and(QueryBuilder::atoms(vec![4000, 4002])).build());
build_bench!(and_frequent_seldom, &QueryBuilder::and(QueryBuilder::atoms(vec![4, 4002])).build());
build_bench!(and_frequent_frequent, &QueryBuilder::and(QueryBuilder::atoms(vec![4, 5])).build());
build_bench!(atom_frequent, &QueryBuilder::atom(4).build());
build_bench!(atom_seldom, &QueryBuilder::atom(4000).build());
<commit_msg>further expand benches<commit_after>// These benchmarks should currently not be considered complete, extensive or significant.
// Also indexing is currently too slow. So using them is not really fun.
#![feature(test)]
extern crate rand;
extern crate test;
extern crate perlin;
#[macro_use]
extern crate lazy_static;

mod utils;

use utils::*;

use perlin::index::boolean_index::BooleanIndex;

lazy_static!{
    pub static ref INDICES: [BooleanIndex<usize>; 3] = [
        prepare_index(1_000, 500), //1.000 documents with 500 terms a 8bytes = 4MB
        prepare_index(10_000, 500), //10.000 documents with 500 terms a 8bytes = 40MB
        prepare_index(1_000, 5000), //100.000 documents with 1000 terms a 8bytes = 800MB
    ];
}

macro_rules! bench {
    ($query:expr) =>
    {

        #[bench]
        fn typical_first_ten(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[0].execute_query($query).take(10).count())
            );
        }

        #[bench]
        fn large_collection_first_ten(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[1].execute_query($query).take(10).count())
            );
        }

        #[bench]
        fn large_documents_first_ten(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[2].execute_query($query).take(10).count())
            );
        }

        #[bench]
        fn typical(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[0].execute_query($query).count())
            );
        }

        #[bench]
        fn large_collection(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[1].execute_query($query).count())
            );
        }

        #[bench]
        fn large_documents_collection(b: &mut Bencher) {
            b.iter(||
                black_box(INDICES[2].execute_query($query).count())
            );
        }
    }
}

macro_rules! build_bench {
    ($name:ident, $query:expr) => (
        mod $name {
            use super::*;
            use test::Bencher;
            use perlin::index::boolean_index::*;
            use perlin::index::Index;
            use test::black_box;
            bench!{$query}
        }

    )

}

build_bench!(in_order_seldom,
             &QueryBuilder::in_order(vec![Some(4000), Some(4001), Some(4002)]).build());
build_bench!(in_order_frequent,
             &QueryBuilder::in_order(vec![Some(4), Some(5), Some(6)]).build());
build_bench!(and_seldom_seldom,
             &QueryBuilder::and(QueryBuilder::atoms(vec![4000, 4002])).build());
build_bench!(and_frequent_seldom,
             &QueryBuilder::and(QueryBuilder::atoms(vec![4, 4002])).build());
build_bench!(and_frequent_frequent,
             &QueryBuilder::and(QueryBuilder::atoms(vec![4, 5])).build());
build_bench!(atom_frequent, &QueryBuilder::atom(4).build());
build_bench!(atom_seldom, &QueryBuilder::atom(4000).build());
<|endoftext|>


<commit_before>//! System Mutexes
//!
//! The Windows implementation of mutexes is a little odd and it may not be
//! immediately obvious what's going on. The primary oddness is that SRWLock is
//! used instead of CriticalSection, and this is done because:
//!
//! 1. SRWLock is several times faster than CriticalSection according to
//!    benchmarks performed on both Windows 8 and Windows 7.
//!
//! 2. CriticalSection allows recursive locking while SRWLock deadlocks. The
//!    Unix implementation deadlocks so consistency is preferred. See #19962 for
//!    more details.
//!
//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
//!    is that there are no guarantees of fairness.

use crate::cell::UnsafeCell;
use crate::mem::MaybeUninit;
use crate::sys::c;

pub struct Mutex {
    srwlock: UnsafeCell<c::SRWLOCK>,
}

// Windows SRW Locks are movable (while not borrowed).
// ReentrantMutexes (in Inner) are not, but those are stored indirectly through
// a Box, so do not move when the Mutex it self is moved.
pub type MovableMutex = Mutex;

unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

#[inline]
pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
    m.srwlock.get()
}

impl Mutex {
    pub const fn new() -> Mutex {
        Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
    }
    #[inline]
    pub unsafe fn init(&mut self) {}

    #[inline]
    pub unsafe fn lock(&self) {
        c::AcquireSRWLockExclusive(raw(self));
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        c::TryAcquireSRWLockExclusive(raw(self)) != 0
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        c::ReleaseSRWLockExclusive(raw(self));
    }

    #[inline]
    pub unsafe fn destroy(&self) {
        // SRWLock does not need to be destroyed.
    }
}

pub struct ReentrantMutex {
    inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
}

unsafe impl Send for ReentrantMutex {}
unsafe impl Sync for ReentrantMutex {}

impl ReentrantMutex {
    pub const fn uninitialized() -> ReentrantMutex {
        ReentrantMutex { inner: MaybeUninit::uninit() }
    }

    pub unsafe fn init(&self) {
        c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
    }

    pub unsafe fn lock(&self) {
        c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0
    }

    pub unsafe fn unlock(&self) {
        c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
    }

    pub unsafe fn destroy(&self) {
        c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
    }
}
<commit_msg>Remove outdated comment.<commit_after>//! System Mutexes
//!
//! The Windows implementation of mutexes is a little odd and it may not be
//! immediately obvious what's going on. The primary oddness is that SRWLock is
//! used instead of CriticalSection, and this is done because:
//!
//! 1. SRWLock is several times faster than CriticalSection according to
//!    benchmarks performed on both Windows 8 and Windows 7.
//!
//! 2. CriticalSection allows recursive locking while SRWLock deadlocks. The
//!    Unix implementation deadlocks so consistency is preferred. See #19962 for
//!    more details.
//!
//! 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
//!    is that there are no guarantees of fairness.

use crate::cell::UnsafeCell;
use crate::mem::MaybeUninit;
use crate::sys::c;

pub struct Mutex {
    srwlock: UnsafeCell<c::SRWLOCK>,
}

// Windows SRW Locks are movable (while not borrowed).
pub type MovableMutex = Mutex;

unsafe impl Send for Mutex {}
unsafe impl Sync for Mutex {}

#[inline]
pub unsafe fn raw(m: &Mutex) -> c::PSRWLOCK {
    m.srwlock.get()
}

impl Mutex {
    pub const fn new() -> Mutex {
        Mutex { srwlock: UnsafeCell::new(c::SRWLOCK_INIT) }
    }
    #[inline]
    pub unsafe fn init(&mut self) {}

    #[inline]
    pub unsafe fn lock(&self) {
        c::AcquireSRWLockExclusive(raw(self));
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        c::TryAcquireSRWLockExclusive(raw(self)) != 0
    }

    #[inline]
    pub unsafe fn unlock(&self) {
        c::ReleaseSRWLockExclusive(raw(self));
    }

    #[inline]
    pub unsafe fn destroy(&self) {
        // SRWLock does not need to be destroyed.
    }
}

pub struct ReentrantMutex {
    inner: MaybeUninit<UnsafeCell<c::CRITICAL_SECTION>>,
}

unsafe impl Send for ReentrantMutex {}
unsafe impl Sync for ReentrantMutex {}

impl ReentrantMutex {
    pub const fn uninitialized() -> ReentrantMutex {
        ReentrantMutex { inner: MaybeUninit::uninit() }
    }

    pub unsafe fn init(&self) {
        c::InitializeCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
    }

    pub unsafe fn lock(&self) {
        c::EnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
    }

    #[inline]
    pub unsafe fn try_lock(&self) -> bool {
        c::TryEnterCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr())) != 0
    }

    pub unsafe fn unlock(&self) {
        c::LeaveCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
    }

    pub unsafe fn destroy(&self) {
        c::DeleteCriticalSection(UnsafeCell::raw_get(self.inner.as_ptr()));
    }
}
<|endoftext|>


<commit_before>use std::cell::RefCell;
use std::fmt;

#[deriving(Clone)]
pub enum Global {
    GType(@RefCell<TypeInfo>),
    GComp(@RefCell<CompInfo>),
    GCompDecl(@RefCell<CompInfo>),
    GEnum(@RefCell<EnumInfo>),
    GEnumDecl(@RefCell<EnumInfo>),
    GVar(@RefCell<VarInfo>),
    GFunc(@RefCell<VarInfo>),
    GOther
}

impl Global {
    pub fn compinfo(&self) -> @RefCell<CompInfo> {
        match *self {
            GComp(i) => return i,
            GCompDecl(i) => return i,
            _ => fail!("global_compinfo".to_owned())
        }
    }

    pub fn enuminfo(&self) -> @RefCell<EnumInfo> {
        match *self {
            GEnum(i) => return i,
            GEnumDecl(i) => return i,
            _ => fail!("global_enuminfo".to_owned())
        }
    }

    pub fn typeinfo(&self) -> @RefCell<TypeInfo> {
        match *self {
            GType(i) => return i,
            _ => fail!("global_typeinfo".to_owned())
        }
    }

    pub fn varinfo(&self) -> @RefCell<VarInfo> {
        match *self {
            GVar(i) => i,
            GFunc(i) => i,
            _ => fail!("global_varinfo".to_owned())
        }
    }
}

impl fmt::Show for Global {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GType(ti) => ti.borrow().fmt(f),
            GComp(ci) => ci.borrow().fmt(f),
            GCompDecl(ci) => ci.borrow().fmt(f),
            GEnum(ei) => ei.borrow().fmt(f),
            GEnumDecl(ei) => ei.borrow().fmt(f),
            GVar(vi) => vi.borrow().fmt(f),
            GFunc(vi) => vi.borrow().fmt(f),
            GOther => write!(f.buf, "*"),
        }
    }
}

#[deriving(Clone, Eq)]
pub enum Type {
    TVoid,
    TInt(IKind, Layout),
    TFloat(FKind, Layout),
    TPtr(Box<Type>, bool, Layout),
    TArray(Box<Type>, uint, Layout),
    TFunc(Box<Type>, Vec<(~str, Type)>, bool),
    TNamed(@RefCell<TypeInfo>),
    TComp(@RefCell<CompInfo>),
    TEnum(@RefCell<EnumInfo>)
}

impl Type {
    pub fn size(&self) -> uint {
        match *self {
            TInt(_, l) => l.size,
            TFloat(_, l) => l.size,
            TPtr(_, _, l) => l.size,
            TArray(_, _, l) => l.size,
            TNamed(ref ti) => ti.borrow().ty.size(),
            TComp(ref ci) => ci.borrow().layout.size,
            TEnum(ref ei) => ei.borrow().layout.size,
            TVoid => 0,
            TFunc(..) => 0,
        }
    }

    pub fn align(&self) -> uint {
        match *self {
            TInt(_, l) => l.align,
            TFloat(_, l) => l.align,
            TPtr(_, _, l) => l.align,
            TArray(_, _, l) => l.align,
            TNamed(ref ti) => ti.borrow().ty.align(),
            TComp(ref ci) => ci.borrow().layout.align,
            TEnum(ref ei) => ei.borrow().layout.align,
            TVoid => 0,
            TFunc(..) => 0,
        }
    }
}

#[deriving(Clone, Eq)]
pub struct Layout {
    pub size: uint,
    pub align: uint,
}

impl Layout {
    pub fn new(size: uint, align: uint) -> Layout {
        Layout { size: size, align: align }
    }

    pub fn zero() -> Layout {
        Layout { size: 0, align: 0 }
    }
}

#[deriving(Clone, Eq)]
pub enum IKind {
    IBool,
    ISChar,
    IUChar,
    IShort,
    IUShort,
    IInt,
    IUInt,
    ILong,
    IULong,
    ILongLong,
    IULongLong
}

#[deriving(Clone, Eq)]
pub enum FKind {
    FFloat,
    FDouble
}

#[deriving(Clone, Eq)]
pub struct CompInfo {
    pub cstruct: bool,
    pub name: ~str,
    pub fields: Vec<FieldInfo>,
    pub layout: Layout,
}

impl CompInfo {
    pub fn new(name: ~str, cstruct: bool, fields: Vec<FieldInfo>, layout: Layout) -> CompInfo {
        CompInfo {
            cstruct: cstruct,
            name: name,
            fields: fields,
            layout: layout,
        }
    }
}

impl fmt::Show for CompInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.name.fmt(f)
    }
}

#[deriving(Clone, Eq)]
pub struct FieldInfo {
    pub name: ~str,
    pub ty: Type,
    pub bit: Option<uint>,
}

impl FieldInfo {
    pub fn new(name: ~str, ty: Type, bit: Option<uint>) -> FieldInfo {
        FieldInfo {
            name: name,
            ty: ty,
            bit: bit,
        }
    }
}

#[deriving(Clone, Eq)]
pub struct EnumInfo {
    pub name: ~str,
    pub items: Vec<EnumItem>,
    pub kind: IKind,
    pub layout: Layout,
}

impl EnumInfo {
    pub fn new(name: ~str, kind: IKind, items: Vec<EnumItem>, layout: Layout) -> EnumInfo {
        EnumInfo {
            name: name,
            items: items,
            kind: kind,
            layout: layout,
        }
    }
}

impl fmt::Show for EnumInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.name.fmt(f)
    }
}

#[deriving(Clone, Eq)]
pub struct EnumItem {
    pub name: ~str,
    pub val: i64
}

impl EnumItem {
    pub fn new(name: ~str, val: i64) -> EnumItem {
        EnumItem {
            name: name,
            val: val
        }
    }
}

#[deriving(Clone, Eq)]
pub struct TypeInfo {
    pub name: ~str,
    pub ty: Type
}

impl TypeInfo {
    pub fn new(name: ~str, ty: Type) -> TypeInfo {
        TypeInfo {
            name: name,
            ty: ty
        }
    }
}

impl fmt::Show for TypeInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.name.fmt(f)
    }
}

#[deriving(Clone)]
pub struct VarInfo {
    pub name: ~str,
    pub ty: Type,
    pub is_const: bool
}

impl VarInfo {
    pub fn new(name: ~str, ty: Type) -> VarInfo {
        VarInfo {
            name: name,
            ty: ty,
            is_const: false
        }
    }
}

impl fmt::Show for VarInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.name.fmt(f)
    }
}
<commit_msg>Fix travis build<commit_after>use std::cell::RefCell;
use std::fmt;

#[deriving(Clone)]
pub enum Global {
    GType(@RefCell<TypeInfo>),
    GComp(@RefCell<CompInfo>),
    GCompDecl(@RefCell<CompInfo>),
    GEnum(@RefCell<EnumInfo>),
    GEnumDecl(@RefCell<EnumInfo>),
    GVar(@RefCell<VarInfo>),
    GFunc(@RefCell<VarInfo>),
    GOther
}

impl Global {
    pub fn compinfo(&self) -> @RefCell<CompInfo> {
        match *self {
            GComp(i) => return i,
            GCompDecl(i) => return i,
            _ => fail!("global_compinfo".to_owned())
        }
    }

    pub fn enuminfo(&self) -> @RefCell<EnumInfo> {
        match *self {
            GEnum(i) => return i,
            GEnumDecl(i) => return i,
            _ => fail!("global_enuminfo".to_owned())
        }
    }

    pub fn typeinfo(&self) -> @RefCell<TypeInfo> {
        match *self {
            GType(i) => return i,
            _ => fail!("global_typeinfo".to_owned())
        }
    }

    pub fn varinfo(&self) -> @RefCell<VarInfo> {
        match *self {
            GVar(i) => i,
            GFunc(i) => i,
            _ => fail!("global_varinfo".to_owned())
        }
    }
}

impl fmt::Show for Global {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            GType(ti) => ti.borrow().fmt(f),
            GComp(ci) => ci.borrow().fmt(f),
            GCompDecl(ci) => ci.borrow().fmt(f),
            GEnum(ei) => ei.borrow().fmt(f),
            GEnumDecl(ei) => ei.borrow().fmt(f),
            GVar(vi) => vi.borrow().fmt(f),
            GFunc(vi) => vi.borrow().fmt(f),
            GOther => "*".fmt(f),
        }
    }
}

#[deriving(Clone, Eq)]
pub enum Type {
    TVoid,
    TInt(IKind, Layout),
    TFloat(FKind, Layout),
    TPtr(Box<Type>, bool, Layout),
    TArray(Box<Type>, uint, Layout),
    TFunc(Box<Type>, Vec<(~str, Type)>, bool),
    TNamed(@RefCell<TypeInfo>),
    TComp(@RefCell<CompInfo>),
    TEnum(@RefCell<EnumInfo>)
}

impl Type {
    pub fn size(&self) -> uint {
        match *self {
            TInt(_, l) => l.size,
            TFloat(_, l) => l.size,
            TPtr(_, _, l) => l.size,
            TArray(_, _, l) => l.size,
            TNamed(ref ti) => ti.borrow().ty.size(),
            TComp(ref ci) => ci.borrow().layout.size,
            TEnum(ref ei) => ei.borrow().layout.size,
            TVoid => 0,
            TFunc(..) => 0,
        }
    }

    pub fn align(&self) -> uint {
        match *self {
            TInt(_, l) => l.align,
            TFloat(_, l) => l.align,
            TPtr(_, _, l) => l.align,
            TArray(_, _, l) => l.align,
            TNamed(ref ti) => ti.borrow().ty.align(),
            TComp(ref ci) => ci.borrow().layout.align,
            TEnum(ref ei) => ei.borrow().layout.align,
            TVoid => 0,
            TFunc(..) => 0,
        }
    }
}

#[deriving(Clone, Eq)]
pub struct Layout {
    pub size: uint,
    pub align: uint,
}

impl Layout {
    pub fn new(size: uint, align: uint) -> Layout {
        Layout { size: size, align: align }
    }

    pub fn zero() -> Layout {
        Layout { size: 0, align: 0 }
    }
}

#[deriving(Clone, Eq)]
pub enum IKind {
    IBool,
    ISChar,
    IUChar,
    IShort,
    IUShort,
    IInt,
    IUInt,
    ILong,
    IULong,
    ILongLong,
    IULongLong
}

#[deriving(Clone, Eq)]
pub enum FKind {
    FFloat,
    FDouble
}

#[deriving(Clone, Eq)]
pub struct CompInfo {
    pub cstruct: bool,
    pub name: ~str,
    pub fields: Vec<FieldInfo>,
    pub layout: Layout,
}

impl CompInfo {
    pub fn new(name: ~str, cstruct: bool, fields: Vec<FieldInfo>, layout: Layout) -> CompInfo {
        CompInfo {
            cstruct: cstruct,
            name: name,
            fields: fields,
            layout: layout,
        }
    }
}

impl fmt::Show for CompInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.name.fmt(f)
    }
}

#[deriving(Clone, Eq)]
pub struct FieldInfo {
    pub name: ~str,
    pub ty: Type,
    pub bit: Option<uint>,
}

impl FieldInfo {
    pub fn new(name: ~str, ty: Type, bit: Option<uint>) -> FieldInfo {
        FieldInfo {
            name: name,
            ty: ty,
            bit: bit,
        }
    }
}

#[deriving(Clone, Eq)]
pub struct EnumInfo {
    pub name: ~str,
    pub items: Vec<EnumItem>,
    pub kind: IKind,
    pub layout: Layout,
}

impl EnumInfo {
    pub fn new(name: ~str, kind: IKind, items: Vec<EnumItem>, layout: Layout) -> EnumInfo {
        EnumInfo {
            name: name,
            items: items,
            kind: kind,
            layout: layout,
        }
    }
}

impl fmt::Show for EnumInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.name.fmt(f)
    }
}

#[deriving(Clone, Eq)]
pub struct EnumItem {
    pub name: ~str,
    pub val: i64
}

impl EnumItem {
    pub fn new(name: ~str, val: i64) -> EnumItem {
        EnumItem {
            name: name,
            val: val
        }
    }
}

#[deriving(Clone, Eq)]
pub struct TypeInfo {
    pub name: ~str,
    pub ty: Type
}

impl TypeInfo {
    pub fn new(name: ~str, ty: Type) -> TypeInfo {
        TypeInfo {
            name: name,
            ty: ty
        }
    }
}

impl fmt::Show for TypeInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.name.fmt(f)
    }
}

#[deriving(Clone)]
pub struct VarInfo {
    pub name: ~str,
    pub ty: Type,
    pub is_const: bool
}

impl VarInfo {
    pub fn new(name: ~str, ty: Type) -> VarInfo {
        VarInfo {
            name: name,
            ty: ty,
            is_const: false
        }
    }
}

impl fmt::Show for VarInfo {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.name.fmt(f)
    }
}
<|endoftext|>


<commit_before>use ::bitreader::BitReader;

use std::error::Error;
use std::fmt;
use std::fmt::{ Display, Formatter };
use std::io;
use std::io::Read;
use std::result;

/// Wraps an input stream and provides methods for decompressing.
///
/// # Examples
///
/// extern crate compression;
///
/// use compression::deflate::Decompressor;
/// use std::fs::File;
///
/// let mut f = try!(File::open("compressed.txt.gz"));
/// let mut deflate = Decompressor::new(f);
pub struct Decompressor {
	header: Header,
	state: State,
}

type BFinal = bool;

#[derive(Debug, Clone, PartialEq)]
enum BType {
	NoCompression,
	CompressedWithFixedHuffmanCodes,
	CompressedWithDynamicHuffmanCodes,
}

#[derive(Debug, Clone, PartialEq)]
struct Header {
	bfinal: Option<BFinal>,
	btype: Option<BType>,
}

impl Header {
	fn new() -> Header {
		Header{
			bfinal: None,
			btype: None,
		}
	}
}

#[derive(Debug, Clone, PartialEq)]
enum State {
	HeaderBegin,
	BFinal(BFinal),
	BType(BType),
}

#[derive(Debug, Clone, PartialEq)]
pub enum DecompressorError {
	UnexpectedEOF,
	BlockTypeReserved
}

impl Display for DecompressorError {
	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
		fmt.write_str(self.description())
	}
}

impl Error for DecompressorError {
	fn description(&self) -> &str {
		match self {
			&DecompressorError::UnexpectedEOF => "Encountered unexpected EOF",
			&DecompressorError::BlockTypeReserved => "Reserved block type in deflate header",
		}
	}
}

impl Decompressor {
	pub fn new() -> Decompressor {
		Decompressor{
			header: Header::new(),
			state: State::HeaderBegin,
		}
	}

	fn parse_bfinal<R: Read>(ref mut in_stream: &mut BitReader<R>) -> result::Result<State, DecompressorError> {
		match in_stream.read_bit() {
			Ok(bfinal) => Ok(State::BFinal(bfinal)),
			Err(_) => Err(DecompressorError::UnexpectedEOF),
		}
	}

	fn parse_btype<R: Read>(ref mut in_stream: &mut BitReader<R>) -> result::Result<State, DecompressorError> {
		match in_stream.read_n_bits(2) {
			Ok(btype) => match (btype[1], btype[0]) {
				(false, false) => Ok(State::BType(BType::NoCompression)),
				(false, true) => Ok(State::BType(BType::CompressedWithFixedHuffmanCodes)),
				(true, false) => Ok(State::BType(BType::CompressedWithDynamicHuffmanCodes)),
				(true, true) => Err(DecompressorError::BlockTypeReserved),
			},
			Err(_) => Err(DecompressorError::UnexpectedEOF),
		}
	}

	pub fn decompress<R: Read>(&mut self, ref mut in_stream: &mut BitReader<R>) -> io::Result<Vec<u8>>{
		loop {
			match self.state.clone() {
				State::HeaderBegin => {
					self.state = match Self::parse_bfinal(*in_stream) {
						Ok(state) => state,
						Err(e) => panic!(e),
					}
				},
				State::BFinal(bfinal) => {
					self.header.bfinal = Some(bfinal);
					self.state = match Self::parse_btype(*in_stream) {
						Ok(state) => state,
						Err(e) => panic!(e),
					}
				},
				State::BType(btype) => {
					self.header.btype = Some(btype);

					println!("{:?}", self.header);
					self.state = unimplemented!()
				}
			}
		}
	}
}

	// fn parse_bfinal(ref mut buf: &mut VecDeque<u8>, mut next_bit: &mut u8) -> result::Result<DecompressorSuccess, DecompressorError> {
	// 	if buf.len() < 1 {

	// 		Err(DecompressorError::NeedMoreBytes)
	// 	} else {
	// 		let b = if *next_bit == 7 {
	// 			buf.pop_front().unwrap()
	// 		} else {
	// 			buf[0]
	// 		};
	// 		let bit_mask = 1u8 << *next_bit;

	// 		*next_bit = (*next_bit + 1) % 8;

	// 		Ok(DecompressorSuccess::BFinal(b & bit_mask > 0))
	// 	}
	// }

	// fn parse_btype(ref mut buf: &mut VecDeque<u8>, mut next_bit: &mut u8) -> result::Result<DecompressorSuccess, DecompressorError> {
	// 	if buf.len() < 1 || (buf.len() < 2 && *next_bit == 7) {

	// 		Err(DecompressorError::NeedMoreBytes)
	// 	} else {
	// 		let b0 = if *next_bit == 7 {
	// 			buf.pop_front().unwrap()
	// 		} else {
	// 			buf[0]
	// 		};
	// 		let bit_mask0 = 1u8 << *next_bit;
	// 		*next_bit += 1;

	// 		let b1 = if *next_bit == 7 {
	// 			buf.pop_front().unwrap()
	// 		} else {
	// 			buf[0]
	// 		};
	// 		let bit_mask1 = 1u8 << *next_bit;
	// 		*next_bit += 1;

	// 		match (b1 & bit_mask1, b0 & bit_mask0) {
	// 			(0, 0) => Ok(DecompressorSuccess::BType(BType::NoCompression)),
	// 			(0, _) => Ok(DecompressorSuccess::BType(BType::CompressedWithFixedHuffmanCodes)),
	// 			(_, 0) => Ok(DecompressorSuccess::BType(BType::CompressedWithDynamicHuffmanCodes)),
	// 			(_, _) => Err(DecompressorError::ReservedBType),
	// 		}
	// 	}
	// }

	// fn create_fixed_huffman_codes() -> HuffmanCodes {
	// 	let lengths = [vec!(8; 144), vec!(9; 112), vec!(7; 24), vec!(8; 8)].concat();

	// 	huffman::codes_from_lengths(lengths)
	// }

	// fn parse_next_symbol(&mut self) -> result::Result<DecompressorSuccess, DecompressorError> {
	// 	if self.in_buf.len() < 1 {

	// 		Err(DecompressorError::NeedMoreBytes)
	// 	} else {
	// 		if self.current_symbol == None {

	// 			self.current_symbol = Some(self.huffman_codes.as_ref().unwrap() as *const HuffmanCodes);
	// 		}

	// 		loop {

	// 		}
	// 	}
	// }
<commit_msg>MOD: prepared states for huffman code generation<commit_after>use ::bitreader::BitReader;

use std::error::Error;
use std::fmt;
use std::fmt::{ Display, Formatter };
use std::io;
use std::io::Read;
use std::result;

/// Wraps an input stream and provides methods for decompressing.
///
/// # Examples
///
/// extern crate compression;
///
/// use compression::deflate::Decompressor;
/// use std::fs::File;
///
/// let mut f = try!(File::open("compressed.txt.gz"));
/// let mut deflate = Decompressor::new(f);
pub struct Decompressor {
	header: Header,
	state: State,
}

type BFinal = bool;

#[derive(Debug, Clone, PartialEq)]
enum BType {
	NoCompression,
	CompressedWithFixedHuffmanCodes,
	CompressedWithDynamicHuffmanCodes,
}

#[derive(Debug, Clone, PartialEq)]
struct Header {
	bfinal: Option<BFinal>,
	btype: Option<BType>,
}

impl Header {
	fn new() -> Header {
		Header{
			bfinal: None,
			btype: None,
		}
	}
}

#[derive(Debug, Clone, PartialEq)]
enum State {
	HeaderBegin,
	BFinal(BFinal),
	BType(BType),
	HandlingHuffmanCodes(BType),
}

#[derive(Debug, Clone, PartialEq)]
pub enum DecompressorError {
	UnexpectedEOF,
	BlockTypeReserved
}

impl Display for DecompressorError {
	fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
		fmt.write_str(self.description())
	}
}

impl Error for DecompressorError {
	fn description(&self) -> &str {
		match self {
			&DecompressorError::UnexpectedEOF => "Encountered unexpected EOF",
			&DecompressorError::BlockTypeReserved => "Reserved block type in deflate header",
		}
	}
}

impl Decompressor {
	pub fn new() -> Decompressor {
		Decompressor{
			header: Header::new(),
			state: State::HeaderBegin,
		}
	}

	fn parse_bfinal<R: Read>(ref mut in_stream: &mut BitReader<R>) -> result::Result<State, DecompressorError> {
		match in_stream.read_bit() {
			Ok(bfinal) => Ok(State::BFinal(bfinal)),
			Err(_) => Err(DecompressorError::UnexpectedEOF),
		}
	}

	fn parse_btype<R: Read>(ref mut in_stream: &mut BitReader<R>) -> result::Result<State, DecompressorError> {
		match in_stream.read_n_bits(2) {
			Ok(btype) => match (btype[1], btype[0]) {
				(false, false) => Ok(State::BType(BType::NoCompression)),
				(false, true) => Ok(State::BType(BType::CompressedWithFixedHuffmanCodes)),
				(true, false) => Ok(State::BType(BType::CompressedWithDynamicHuffmanCodes)),
				(true, true) => Err(DecompressorError::BlockTypeReserved),
			},
			Err(_) => Err(DecompressorError::UnexpectedEOF),
		}
	}

	pub fn decompress<R: Read>(&mut self, ref mut in_stream: &mut BitReader<R>) -> io::Result<Vec<u8>>{
		loop {
			match self.state.clone() {
				State::HeaderBegin => {
					self.state = match Self::parse_bfinal(*in_stream) {
						Ok(state) => state,
						Err(e) => panic!(e),
					}
				},
				State::BFinal(bfinal) => {
					self.header.bfinal = Some(bfinal);
					self.state = match Self::parse_btype(*in_stream) {
						Ok(state) => state,
						Err(e) => panic!(e),
					}
				},
				State::BType(btype) => {
					self.header.btype = Some(btype.clone());
					self.state = State::HandlingHuffmanCodes(btype);
				},
				State::HandlingHuffmanCodes(BType::NoCompression) => {
					unimplemented!();
				},
				State::HandlingHuffmanCodes(BType::CompressedWithFixedHuffmanCodes) => {
					// @TODO: do this first!
					unimplemented!();
				},
				State::HandlingHuffmanCodes(BType::CompressedWithDynamicHuffmanCodes) => {
					unimplemented!();
				}
			}
		}
	}
}

	// fn create_fixed_huffman_codes() -> HuffmanCodes {
	// 	let lengths = [vec!(8; 144), vec!(9; 112), vec!(7; 24), vec!(8; 8)].concat();

	// 	huffman::codes_from_lengths(lengths)
	// }

	// fn parse_next_symbol(&mut self) -> result::Result<DecompressorSuccess, DecompressorError> {
	// 	if self.in_buf.len() < 1 {

	// 		Err(DecompressorError::NeedMoreBytes)
	// 	} else {
	// 		if self.current_symbol == None {

	// 			self.current_symbol = Some(self.huffman_codes.as_ref().unwrap() as *const HuffmanCodes);
	// 		}

	// 		loop {

	// 		}
	// 	}
	// }
<|endoftext|>


<commit_before>// Functions for validating certificates on many platforms, with a C abi.
#![deny(warnings)]

extern crate libc;
extern crate certitude;

use std::ffi::CStr;
use std::slice;
use libc::c_char;

pub use certitude::ValidationResult;
use certitude;

/// A C-ABI compatible version of the cert validation function. It does some work to transform the data,
/// and then just calls the cert validation function from certitude.
///
/// Here are the rules for calling this from C.
/// - encoded_certs is an array of pointers to DER-encoded representations of the certificates in the
///   certificate chain. Neither the pointer array nor the DER-encoded representations of the certs
///   are null-terminated.
/// - cert_sizes is an array of lengths for each DER-encoded cert. This array has the exact same length
///   as the array in encoded_certs. These lengths must not include any null-terminators that may be at
///   the end of the DER-encoded certs.
/// - cert_count is the number of elements in both the encoded_certs and cert_sizes array.
/// - hostname is the UTF-8 encoded hostname to validate the cert chain against. This string must be
///   null-terminated.
///
/// Rust takes ownership of none of these objects: where necessary it makes its own copies, but
/// generally speaking it expects all of the data passed to be it to remain valid for the duration
/// of the function call. The caller retains ownership, however, and is responsible for freeing all
/// the relevant data.
///
/// The C header for this function is:
///
/// ```c
/// extern uint32_t validate_cert_chain(uint8_t **encoded_certs,
///                                     size_t *cert_sizes,
///                                     size_t cert_count,
///                                     const char *hostname);
/// ```
#[no_mangle]
pub extern "C" fn validate_cert_chain(encoded_certs: *mut *const u8, cert_sizes: *mut usize, cert_count: usize, hostname: *const c_char) -> u32 {
    // First, turn the hostname into a CStr. CStr explicitly doesn't own the bytes, so we avoid
    // an extra copy here (and then awkwardly freeing the underlying string, which would be Not Good).
    let encoded_hostname = match unsafe { CStr::from_ptr(hostname).to_str() } {
        Ok(h) => h,
        Err(_) => return ValidationResult::MalformedHostname as u32,
    };

    // This works best if we turn the collection of encoded certs into a slice of u8 objects.
    // We can do this in place by being *very* careful.
    // First, convince Rust that we have a slice of pointers to u8.
    // Note that we *must not* use a vector here: vectors own their memory, and so using
    // a vector will cause Rust to do all kinds of crazy stuff.
    let temp_cert_slice = unsafe { slice::from_raw_parts(encoded_certs, cert_count) };
    let cert_sizes = unsafe { slice::from_raw_parts(cert_sizes, cert_count) };

    // Then, build a new slice transforming all the encoded certs into slices of u8.
    // Here we want the backing objects to be slices, but we're ok with their container
    // being a vector (the vector will dealloc the slices, but the slices borrow their
    // memory so the underlying memory should be totally safe).
    let cert_slice = temp_cert_slice.iter()
                                    .zip(cert_sizes)
                                    .map(|(&cert, &size)| unsafe { slice::from_raw_parts(cert, size) })
                                    .collect::<Vec<&[u8]>>();

    // We can now validate the items. We've taken ownership of nothing here.
    certitude::validate_cert_chain(&cert_slice, encoded_hostname) as u32
}<commit_msg>Fixup broken 'use' statement.<commit_after>// Functions for validating certificates on many platforms, with a C abi.
#![deny(warnings)]

extern crate libc;
extern crate certitude;

use std::ffi::CStr;
use std::slice;
use libc::c_char;

pub use certitude::ValidationResult;

/// A C-ABI compatible version of the cert validation function. It does some work to transform the data,
/// and then just calls the cert validation function from certitude.
///
/// Here are the rules for calling this from C.
/// - encoded_certs is an array of pointers to DER-encoded representations of the certificates in the
///   certificate chain. Neither the pointer array nor the DER-encoded representations of the certs
///   are null-terminated.
/// - cert_sizes is an array of lengths for each DER-encoded cert. This array has the exact same length
///   as the array in encoded_certs. These lengths must not include any null-terminators that may be at
///   the end of the DER-encoded certs.
/// - cert_count is the number of elements in both the encoded_certs and cert_sizes array.
/// - hostname is the UTF-8 encoded hostname to validate the cert chain against. This string must be
///   null-terminated.
///
/// Rust takes ownership of none of these objects: where necessary it makes its own copies, but
/// generally speaking it expects all of the data passed to be it to remain valid for the duration
/// of the function call. The caller retains ownership, however, and is responsible for freeing all
/// the relevant data.
///
/// The C header for this function is:
///
/// ```c
/// extern uint32_t validate_cert_chain(uint8_t **encoded_certs,
///                                     size_t *cert_sizes,
///                                     size_t cert_count,
///                                     const char *hostname);
/// ```
#[no_mangle]
pub extern "C" fn validate_cert_chain(encoded_certs: *mut *const u8, cert_sizes: *mut usize, cert_count: usize, hostname: *const c_char) -> u32 {
    // First, turn the hostname into a CStr. CStr explicitly doesn't own the bytes, so we avoid
    // an extra copy here (and then awkwardly freeing the underlying string, which would be Not Good).
    let encoded_hostname = match unsafe { CStr::from_ptr(hostname).to_str() } {
        Ok(h) => h,
        Err(_) => return ValidationResult::MalformedHostname as u32,
    };

    // This works best if we turn the collection of encoded certs into a slice of u8 objects.
    // We can do this in place by being *very* careful.
    // First, convince Rust that we have a slice of pointers to u8.
    // Note that we *must not* use a vector here: vectors own their memory, and so using
    // a vector will cause Rust to do all kinds of crazy stuff.
    let temp_cert_slice = unsafe { slice::from_raw_parts(encoded_certs, cert_count) };
    let cert_sizes = unsafe { slice::from_raw_parts(cert_sizes, cert_count) };

    // Then, build a new slice transforming all the encoded certs into slices of u8.
    // Here we want the backing objects to be slices, but we're ok with their container
    // being a vector (the vector will dealloc the slices, but the slices borrow their
    // memory so the underlying memory should be totally safe).
    let cert_slice = temp_cert_slice.iter()
                                    .zip(cert_sizes)
                                    .map(|(&cert, &size)| unsafe { slice::from_raw_parts(cert, size) })
                                    .collect::<Vec<&[u8]>>();

    // We can now validate the items. We've taken ownership of nothing here.
    certitude::validate_cert_chain(&cert_slice, encoded_hostname) as u32
}<|endoftext|>


<commit_before>extern crate libc;
use libc::{c_char, c_int, uint8_t, uint16_t, uint32_t, c_void, timeval, c_uint, ssize_t, fd_set};

pub const FALSE: c_int = 0;
pub const TRUE: c_int = 1;
pub const OFF: c_int = 0;
pub const ON: c_int = 1;

macro_rules! modbus_enum {
    (pub enum $name:ident { $($variants:tt)* }) => {
        #[allow(non_camel_case_types)]
        #[cfg(target_env = "msvc")]
        pub type $name = i32;
        #[allow(non_camel_case_types)]
        #[cfg(not(target_env = "msvc"))]
        pub type $name = u32;
        modbus_enum!(gen, $name, 0, $($variants)*);
    };
    (pub enum $name:ident: $t:ty { $($variants:tt)* }) => {
        #[allow(non_camel_case_types)]
        pub type $name = $t;
        modbus_enum!(gen, $name, 0, $($variants)*);
    };
    (gen, $name:ident, $val:expr, $variant:ident, $($rest:tt)*) => {
        #[allow(non_camel_case_types)]
        pub const $variant: $name = $val;
        modbus_enum!(gen, $name, $val+1, $($rest)*);
    };
    (gen, $name:ident, $val:expr, $variant:ident = $e:expr, $($rest:tt)*) => {
        #[allow(non_camel_case_types)]
        pub const $variant: $name = $e;
        modbus_enum!(gen, $name, $e+1, $($rest)*);
    };
    (gen, $name:ident, $val:expr, ) => {}
}
modbus_enum! {
    pub enum  modbus_backend_type_t {
        _MODBUS_BACKEND_TYPE_RTU=0,
        _MODBUS_BACKEND_TYPE_TCP,
    }
}

modbus_enum! {
    pub enum modbus_error_recovery_mode {
        MODBUS_ERROR_RECOVERY_NONE          = 0,
        MODBUS_ERROR_RECOVERY_LINK          = (1<<1),
        MODBUS_ERROR_RECOVERY_PROTOCOL      = (1<<2),
    }
}

modbus_enum! {
    pub enum msg_type_t {
        MSG_INDICATION,
        MSG_CONFIRMATION,
    }
}

#[repr(C)]
#[allow(non_camel_case_types)]
pub struct modbus_backend_t {
    backend_type: c_uint,
    header_length: c_uint,
    checksum_length: c_uint,
    max_adu_length: c_uint,
    set_slave: extern fn(ctx: *mut modbus_t, slave: c_int) -> c_int,
    build_request_basis: extern fn(ctx: *mut modbus_t, function: c_int, addr: c_int,
                                nb: c_int, req: *mut uint8_t) -> c_int,
    build_response_basis: extern fn(sft: *mut sft_t, rsp: *mut uint8_t) -> c_int,
    prepare_response_tid: extern fn(req: *const uint8_t, req_length: *mut c_int) -> c_int,
    send_msg_pre: extern fn(req: *mut uint8_t, req_length: c_int) -> c_int,
    send: extern fn(ctx: *mut modbus_t, req: *const uint8_t, req_length: c_int) -> ssize_t,
    receive: extern fn(ctx: *mut modbus_t, req: *mut uint8_t) -> c_int,
    recv: extern fn(ctx: *mut modbus_t, rsp: *mut uint8_t, rsp_length: c_int) -> ssize_t,
    check_integrity: extern fn(ctx: *mut modbus_t, msg: *mut uint8_t,
                            msg_length: *const c_int) -> c_int,
    pre_check_confirmation: extern fn(ctx: *mut modbus_t, req: *const uint8_t,
                                   rsp: *const uint8_t, rsp_length: c_int) -> c_int,
    connect: extern fn(ctx: *mut modbus_t) -> c_int,
    close: extern fn(ctx: *mut modbus_t),
    flush: extern fn(ctx: *mut modbus_t) -> c_int,
    select: extern fn(ctx: *mut modbus_t, rset: *mut fd_set, tv: *mut timeval, msg_length: c_int) -> c_int,
    free: extern fn(ctx: *mut modbus_t),
}

#[repr(C)]
pub struct sft_t {
    slave: c_int,
    function: c_int,
    t_id: c_int,
}

#[repr(C)]
pub struct _modbus {
    /* Slave address */
    slave: c_int,
    /* Socket or file descriptor */
    s: c_int,
    debug: c_int,
    error_recovery: c_int,
    response_timeout: timeval,
    byte_timeout: timeval,
    backend: *const modbus_backend_t,
    backend_data: *mut c_void,
}

#[allow(non_camel_case_types)]
pub type modbus_t = _modbus;

#[repr(C)]
pub struct modbus_mapping_t {
    nb_bits: c_int,
    start_bits: c_int,
    nb_input_bits: c_int,
    start_input_bits: c_int,
    nb_input_registers: c_int,
    start_input_registers: c_int,
    nb_registers: c_int,
    start_registers: c_int,
    tab_bits: *mut uint8_t,
    tab_input_bits: *mut uint8_t,
    tab_input_registers: *mut uint16_t,
    tab_registers: *mut uint16_t,
}

// modbus-rtu.h
pub const MODBUS_RTU_MAX_ADU_LENGTH: c_int = 256;

pub const MODBUS_RTU_RS232: c_int = 0;
pub const MODBUS_RTU_RS485: c_int = 1;

pub const MODBUS_RTU_RTS_NONE: c_int = 0;
pub const MODBUS_RTU_RTS_UP: c_int   = 1;
pub const MODBUS_RTU_RTS_DOWN: c_int = 2;

#[link(name = "modbus")]
extern {
    pub fn modbus_set_slave(ctx: *mut modbus_t, slave: c_int) -> c_int;
    pub fn modbus_set_error_recovery(ctx: *mut modbus_t, error_recovery: modbus_error_recovery_mode) -> c_int;

    pub fn modbus_set_socket(ctx: *mut modbus_t, socket: c_int) -> c_int;
    pub fn modbus_get_socket(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_get_response_timeout(ctx: *mut modbus_t, to_sec: *mut uint32_t, to_usec: *mut uint32_t) -> c_int;
    pub fn modbus_set_response_timeout(ctx: *mut modbus_t, to_sec: uint32_t, to_usec: uint32_t) -> c_int;

    pub fn modbus_get_byte_timeout(ctx: *mut modbus_t, to_sec: *mut uint32_t, to_usec: *mut uint32_t) -> c_int;
    pub fn modbus_set_byte_timeout(ctx: *mut modbus_t, to_sec: uint32_t, to_usec: uint32_t) -> c_int;

    pub fn modbus_get_header_length(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_connect(ctx: *mut modbus_t) -> c_int;
    pub fn modbus_close(ctx: *mut modbus_t);

    pub fn modbus_free(ctx: *mut modbus_t);

    pub fn modbus_flush(ctx: *mut modbus_t) -> c_int;
    pub fn modbus_set_debug(ctx: *mut modbus_t, flag: c_int) -> c_int;

    pub fn modbus_strerror(errnum: c_int) -> *const c_char;

    pub fn modbus_read_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint8_t) -> c_int;
    pub fn modbus_read_input_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint8_t) -> c_int;
    pub fn modbus_read_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint16_t) -> c_int;
    pub fn modbus_read_input_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint16_t) -> c_int;
    pub fn modbus_write_bit(ctx: *mut modbus_t, coil_addr: c_int, status: c_int) -> c_int;
    pub fn modbus_write_register(ctx: *mut modbus_t, reg_addr: c_int, value: c_int) -> c_int;
    pub fn modbus_write_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, data: *const uint8_t) -> c_int;
    pub fn modbus_write_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, data: *const uint16_t) -> c_int;
    pub fn modbus_mask_write_register(ctx: *mut modbus_t, addr: c_int, and_mask: uint16_t, or_mask: uint16_t) -> c_int;
    pub fn modbus_write_and_read_registers(ctx: *mut modbus_t, write_addr: c_int, write_nb: c_int,
                                                   src: *const uint16_t, read_addr: c_int, read_nb: c_int,
                                                   dest: *mut uint16_t) -> c_int;
    pub fn modbus_report_slave_id(ctx: *mut modbus_t, max_dest: c_int, dest: *mut uint8_t) -> c_int;

    pub fn modbus_mapping_new_start_address(
        start_bits: c_uint, nb_bits: c_uint,
        start_input_bits: c_uint, nb_input_bits: c_uint,
        start_registers: c_uint, nb_registers: c_uint,
        start_input_registers: c_uint, nb_input_registers: c_uint) -> *mut modbus_mapping_t;

    pub fn modbus_mapping_new(nb_bits: c_int, nb_input_bits: c_int, nb_registers: c_int, nb_input_registers: c_int)  -> *mut modbus_mapping_t;
    pub fn modbus_mapping_free(mb_mapping: *mut modbus_mapping_t);

    pub fn modbus_send_raw_request(ctx: *mut modbus_t, raw_req: *mut uint8_t, raw_req_length: c_int) -> c_int;

    pub fn modbus_receive(ctx: *mut modbus_t, req: *mut uint8_t) -> c_int;

    pub fn modbus_receive_confirmation(ctx: *mut modbus_t, rsp: *mut uint8_t) -> c_int;

    pub fn modbus_reply(ctx: *mut modbus_t, req: *const uint8_t, req_length: c_int, mb_mapping: *mut modbus_mapping_t) -> c_int;
    pub fn modbus_reply_exception(ctx: *mut modbus_t, req: *const uint8_t, exception_code: c_uint) -> c_int;

    pub fn modbus_new_rtu(device: *const c_char, baud: c_int, parity: c_char, data_bit: c_int, stop_bit: c_int) -> *mut modbus_t;

    // modbus-rtu.h
    pub fn modbus_rtu_set_serial_mode(ctx: *mut modbus_t, mode: c_int) -> c_int;
    pub fn modbus_rtu_get_serial_mode(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_rtu_set_rts(ctx: *mut modbus_t, mode: c_int) -> c_int;
    pub fn modbus_rtu_get_rts(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_rtu_set_custom_rts(ctx: *mut modbus_t, set_rts: extern fn(ctx: *mut modbus_t, on: c_int)) -> c_int;

    pub fn modbus_rtu_set_rts_delay(ctx: *mut modbus_t, us: c_int) -> c_int;
    pub fn modbus_rtu_get_rts_delay(ctx: *mut modbus_t) -> c_int;

}

fn main() {
    let device: *const c_char = std::ffi::CString::new(std::env::args().nth(1).unwrap()).unwrap().as_ptr();
    let slave_id: i32 = std::env::args().nth(2).unwrap().parse().unwrap();

    unsafe {
        let mut tab_reg = vec![0u16; 32];

        let ctx = modbus_new_rtu(device, 9600, 'N' as c_char, 8, 1);
        modbus_set_slave(ctx, slave_id);
        modbus_set_debug(ctx, TRUE);

        modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
        if  modbus_connect(ctx) == -1 {
            modbus_free(ctx);
            panic!("Connection failed!");
        }
        // https://doc.rust-lang.org/std/primitive.pointer.html
        let rc = modbus_read_registers(ctx, 0, 19, tab_reg.as_mut_ptr());
        if rc == -1 {
            println!("Registers could not be read");
        }

        for i in 0..rc {
            println!("register[{}]=[{}] (0x{})", i, &tab_reg[i as usize], &tab_reg[i as usize]);
        }

    }
}
<commit_msg>Add MODBUS_RTU_RTS_DOWN<commit_after>extern crate libc;
use libc::{c_char, c_int, uint8_t, uint16_t, uint32_t, c_void, timeval, c_uint, ssize_t, fd_set};

pub const FALSE: c_int = 0;
pub const TRUE: c_int = 1;
pub const OFF: c_int = 0;
pub const ON: c_int = 1;

macro_rules! modbus_enum {
    (pub enum $name:ident { $($variants:tt)* }) => {
        #[allow(non_camel_case_types)]
        #[cfg(target_env = "msvc")]
        pub type $name = i32;
        #[allow(non_camel_case_types)]
        #[cfg(not(target_env = "msvc"))]
        pub type $name = u32;
        modbus_enum!(gen, $name, 0, $($variants)*);
    };
    (pub enum $name:ident: $t:ty { $($variants:tt)* }) => {
        #[allow(non_camel_case_types)]
        pub type $name = $t;
        modbus_enum!(gen, $name, 0, $($variants)*);
    };
    (gen, $name:ident, $val:expr, $variant:ident, $($rest:tt)*) => {
        #[allow(non_camel_case_types)]
        pub const $variant: $name = $val;
        modbus_enum!(gen, $name, $val+1, $($rest)*);
    };
    (gen, $name:ident, $val:expr, $variant:ident = $e:expr, $($rest:tt)*) => {
        #[allow(non_camel_case_types)]
        pub const $variant: $name = $e;
        modbus_enum!(gen, $name, $e+1, $($rest)*);
    };
    (gen, $name:ident, $val:expr, ) => {}
}
modbus_enum! {
    pub enum  modbus_backend_type_t {
        _MODBUS_BACKEND_TYPE_RTU=0,
        _MODBUS_BACKEND_TYPE_TCP,
    }
}

modbus_enum! {
    pub enum modbus_error_recovery_mode {
        MODBUS_ERROR_RECOVERY_NONE          = 0,
        MODBUS_ERROR_RECOVERY_LINK          = (1<<1),
        MODBUS_ERROR_RECOVERY_PROTOCOL      = (1<<2),
    }
}

modbus_enum! {
    pub enum msg_type_t {
        MSG_INDICATION,
        MSG_CONFIRMATION,
    }
}

#[repr(C)]
#[allow(non_camel_case_types)]
pub struct modbus_backend_t {
    backend_type: c_uint,
    header_length: c_uint,
    checksum_length: c_uint,
    max_adu_length: c_uint,
    set_slave: extern fn(ctx: *mut modbus_t, slave: c_int) -> c_int,
    build_request_basis: extern fn(ctx: *mut modbus_t, function: c_int, addr: c_int,
                                nb: c_int, req: *mut uint8_t) -> c_int,
    build_response_basis: extern fn(sft: *mut sft_t, rsp: *mut uint8_t) -> c_int,
    prepare_response_tid: extern fn(req: *const uint8_t, req_length: *mut c_int) -> c_int,
    send_msg_pre: extern fn(req: *mut uint8_t, req_length: c_int) -> c_int,
    send: extern fn(ctx: *mut modbus_t, req: *const uint8_t, req_length: c_int) -> ssize_t,
    receive: extern fn(ctx: *mut modbus_t, req: *mut uint8_t) -> c_int,
    recv: extern fn(ctx: *mut modbus_t, rsp: *mut uint8_t, rsp_length: c_int) -> ssize_t,
    check_integrity: extern fn(ctx: *mut modbus_t, msg: *mut uint8_t,
                            msg_length: *const c_int) -> c_int,
    pre_check_confirmation: extern fn(ctx: *mut modbus_t, req: *const uint8_t,
                                   rsp: *const uint8_t, rsp_length: c_int) -> c_int,
    connect: extern fn(ctx: *mut modbus_t) -> c_int,
    close: extern fn(ctx: *mut modbus_t),
    flush: extern fn(ctx: *mut modbus_t) -> c_int,
    select: extern fn(ctx: *mut modbus_t, rset: *mut fd_set, tv: *mut timeval, msg_length: c_int) -> c_int,
    free: extern fn(ctx: *mut modbus_t),
}

#[repr(C)]
pub struct sft_t {
    slave: c_int,
    function: c_int,
    t_id: c_int,
}

#[repr(C)]
pub struct _modbus {
    /* Slave address */
    slave: c_int,
    /* Socket or file descriptor */
    s: c_int,
    debug: c_int,
    error_recovery: c_int,
    response_timeout: timeval,
    byte_timeout: timeval,
    backend: *const modbus_backend_t,
    backend_data: *mut c_void,
}

#[allow(non_camel_case_types)]
pub type modbus_t = _modbus;

#[repr(C)]
pub struct modbus_mapping_t {
    nb_bits: c_int,
    start_bits: c_int,
    nb_input_bits: c_int,
    start_input_bits: c_int,
    nb_input_registers: c_int,
    start_input_registers: c_int,
    nb_registers: c_int,
    start_registers: c_int,
    tab_bits: *mut uint8_t,
    tab_input_bits: *mut uint8_t,
    tab_input_registers: *mut uint16_t,
    tab_registers: *mut uint16_t,
}

// modbus-rtu.h
pub const MODBUS_RTU_MAX_ADU_LENGTH: c_int = 256;

pub const MODBUS_RTU_RS232: c_int = 0;
pub const MODBUS_RTU_RS485: c_int = 1;

pub const MODBUS_RTU_RTS_NONE: c_int = 0;
pub const MODBUS_RTU_RTS_UP: c_int   = 1;
pub const MODBUS_RTU_RTS_DOWN: c_int = 2;

#[link(name = "modbus")]
extern {
    pub fn modbus_set_slave(ctx: *mut modbus_t, slave: c_int) -> c_int;
    pub fn modbus_set_error_recovery(ctx: *mut modbus_t, error_recovery: modbus_error_recovery_mode) -> c_int;

    pub fn modbus_set_socket(ctx: *mut modbus_t, socket: c_int) -> c_int;
    pub fn modbus_get_socket(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_get_response_timeout(ctx: *mut modbus_t, to_sec: *mut uint32_t, to_usec: *mut uint32_t) -> c_int;
    pub fn modbus_set_response_timeout(ctx: *mut modbus_t, to_sec: uint32_t, to_usec: uint32_t) -> c_int;

    pub fn modbus_get_byte_timeout(ctx: *mut modbus_t, to_sec: *mut uint32_t, to_usec: *mut uint32_t) -> c_int;
    pub fn modbus_set_byte_timeout(ctx: *mut modbus_t, to_sec: uint32_t, to_usec: uint32_t) -> c_int;

    pub fn modbus_get_header_length(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_connect(ctx: *mut modbus_t) -> c_int;
    pub fn modbus_close(ctx: *mut modbus_t);

    pub fn modbus_free(ctx: *mut modbus_t);

    pub fn modbus_flush(ctx: *mut modbus_t) -> c_int;
    pub fn modbus_set_debug(ctx: *mut modbus_t, flag: c_int) -> c_int;

    pub fn modbus_strerror(errnum: c_int) -> *const c_char;

    pub fn modbus_read_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint8_t) -> c_int;
    pub fn modbus_read_input_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint8_t) -> c_int;
    pub fn modbus_read_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint16_t) -> c_int;
    pub fn modbus_read_input_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, dest: *mut uint16_t) -> c_int;
    pub fn modbus_write_bit(ctx: *mut modbus_t, coil_addr: c_int, status: c_int) -> c_int;
    pub fn modbus_write_register(ctx: *mut modbus_t, reg_addr: c_int, value: c_int) -> c_int;
    pub fn modbus_write_bits(ctx: *mut modbus_t, addr: c_int, nb: c_int, data: *const uint8_t) -> c_int;
    pub fn modbus_write_registers(ctx: *mut modbus_t, addr: c_int, nb: c_int, data: *const uint16_t) -> c_int;
    pub fn modbus_mask_write_register(ctx: *mut modbus_t, addr: c_int, and_mask: uint16_t, or_mask: uint16_t) -> c_int;
    pub fn modbus_write_and_read_registers(ctx: *mut modbus_t, write_addr: c_int, write_nb: c_int,
                                                   src: *const uint16_t, read_addr: c_int, read_nb: c_int,
                                                   dest: *mut uint16_t) -> c_int;
    pub fn modbus_report_slave_id(ctx: *mut modbus_t, max_dest: c_int, dest: *mut uint8_t) -> c_int;

    pub fn modbus_mapping_new_start_address(
        start_bits: c_uint, nb_bits: c_uint,
        start_input_bits: c_uint, nb_input_bits: c_uint,
        start_registers: c_uint, nb_registers: c_uint,
        start_input_registers: c_uint, nb_input_registers: c_uint) -> *mut modbus_mapping_t;

    pub fn modbus_mapping_new(nb_bits: c_int, nb_input_bits: c_int, nb_registers: c_int, nb_input_registers: c_int)  -> *mut modbus_mapping_t;
    pub fn modbus_mapping_free(mb_mapping: *mut modbus_mapping_t);

    pub fn modbus_send_raw_request(ctx: *mut modbus_t, raw_req: *mut uint8_t, raw_req_length: c_int) -> c_int;

    pub fn modbus_receive(ctx: *mut modbus_t, req: *mut uint8_t) -> c_int;

    pub fn modbus_receive_confirmation(ctx: *mut modbus_t, rsp: *mut uint8_t) -> c_int;

    pub fn modbus_reply(ctx: *mut modbus_t, req: *const uint8_t, req_length: c_int, mb_mapping: *mut modbus_mapping_t) -> c_int;
    pub fn modbus_reply_exception(ctx: *mut modbus_t, req: *const uint8_t, exception_code: c_uint) -> c_int;

    pub fn modbus_new_rtu(device: *const c_char, baud: c_int, parity: c_char, data_bit: c_int, stop_bit: c_int) -> *mut modbus_t;

    // modbus-rtu.h
    pub fn modbus_rtu_set_serial_mode(ctx: *mut modbus_t, mode: c_int) -> c_int;
    pub fn modbus_rtu_get_serial_mode(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_rtu_set_rts(ctx: *mut modbus_t, mode: c_int) -> c_int;
    pub fn modbus_rtu_get_rts(ctx: *mut modbus_t) -> c_int;

    pub fn modbus_rtu_set_custom_rts(ctx: *mut modbus_t, set_rts: extern fn(ctx: *mut modbus_t, on: c_int)) -> c_int;

    pub fn modbus_rtu_set_rts_delay(ctx: *mut modbus_t, us: c_int) -> c_int;
    pub fn modbus_rtu_get_rts_delay(ctx: *mut modbus_t) -> c_int;

}

fn main() {
    let device: *const c_char = std::ffi::CString::new(std::env::args().nth(1).unwrap()).unwrap().as_ptr();
    let slave_id: i32 = std::env::args().nth(2).unwrap().parse().unwrap();

    unsafe {
        let mut tab_reg = vec![0u16; 32];

        let ctx = modbus_new_rtu(device, 9600, 'N' as c_char, 8, 1);
        modbus_set_slave(ctx, slave_id);
        modbus_set_debug(ctx, TRUE);

        modbus_rtu_set_serial_mode(ctx, MODBUS_RTU_RS485);
        modbus_rtu_set_rts(ctx, MODBUS_RTU_RTS_DOWN);

        if  modbus_connect(ctx) == -1 {
            modbus_free(ctx);
            panic!("Connection failed!");
        }
        // https://doc.rust-lang.org/std/primitive.pointer.html
        let rc = modbus_read_registers(ctx, 0, 19, tab_reg.as_mut_ptr());
        if rc == -1 {
            println!("Registers could not be read");
        }

        for i in 0..rc {
            println!("register[{}]=[{}] (0x{})", i, &tab_reg[i as usize], &tab_reg[i as usize]);
        }

    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;

use data::packet::Packet;
use data::frame::ArcFrame;

use error::*;
pub use common::CodecList;

pub trait Decoder {
    // TODO support codec configuration using set_option
    // fn open(&mut self) -> Result<()>;
    fn set_extradata(&mut self, extra: &[u8]);
    fn send_packet(&mut self, pkt: &Packet) -> Result<()>;
    fn receive_frame(&mut self) -> Result<ArcFrame>;
    fn configure(&mut self) -> Result<()>;
}

#[derive(Debug)]
pub struct Descr {
    pub codec: &'static str,
    pub name: &'static str,
    pub desc: &'static str,
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

pub struct Context {
    dec: Box<Decoder>,
    // TODO: Queue up packets/frames
}

impl Context {
    // TODO: More constructors
    pub fn by_name(codecs: &Codecs, name: &str) -> Option<Context> {
        if let Some(builder) = codecs.by_name(name) {
            let dec = builder.create();
            Some(Context { dec: dec })
        } else {
            None
        }
    }
    pub fn set_extradata(&mut self, extra: &[u8]) {
        self.dec.set_extradata(extra);
    }
    pub fn send_packet(&mut self, pkt: &Packet) -> Result<()> {
        self.dec.send_packet(pkt)
    }
    pub fn receive_frame(&mut self) -> Result<ArcFrame> {
        self.dec.receive_frame()
    }
    pub fn configure(&mut self) -> Result<()> {
        self.dec.configure()
    }
    // TODO: Explicitly flush the decoder
    // pub fn flush(&mut self) -> Result<()>
}

pub trait Descriptor {
    fn create(&self) -> Box<Decoder>;
    fn describe<'a>(&'a self) -> &'a Descr;
}

pub struct Codecs {
    list: HashMap<&'static str, Vec<&'static Descriptor>>
}

impl CodecList for Codecs {
    type D = Descriptor;

    fn new() -> Codecs {
        Codecs { list: HashMap::new() }
    }

    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Self::D> {
        if let Some(descs) = self.list.get(name) {
            Some(descs[0])
        } else {
            None
        }
    }

    fn append(&mut self, desc: &'static Self::D) {
        let codec_name = desc.describe().codec;

        self.list.entry(codec_name).or_insert(Vec::new()).push(desc);
    }
}

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

    mod dummy {
        use super::super::*;
        use std::rc::Rc;
        use data::pixel::Formaton;

        struct Dec {
            state: usize,
            format: Option<Rc<Formaton>>
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            fn create(&self) -> Box<Decoder> {
                box Dec { state: 0, format: None }
            }
            fn describe<'a>(&'a self) -> &'a Descr {
                &self.descr
            }
        }

        impl Decoder for Dec {
            fn configure(&mut self) -> Result<()> {
                Ok(())
            }
            fn set_extradata(&mut self, extra: &[u8]) {
                if extra.len() > 4 {
                    self.state = 42;
                } else {
                    self.state = 12;
                }
            }
            fn send_packet(&mut self, _packet: &Packet) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_frame(&mut self) -> Result<ArcFrame> {
                unimplemented!()
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy encoder",
                mime: "x-application/dummy",
            }
        };
    }
    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _dec = codecs.by_name("dummy").unwrap();
    }
}
<commit_msg>codec: Add flush() to the decoder as well<commit_after>use std::collections::HashMap;

use data::packet::Packet;
use data::frame::ArcFrame;

use error::*;
pub use common::CodecList;

pub trait Decoder {
    // TODO support codec configuration using set_option
    // fn open(&mut self) -> Result<()>;
    fn set_extradata(&mut self, extra: &[u8]);
    fn send_packet(&mut self, pkt: &Packet) -> Result<()>;
    fn receive_frame(&mut self) -> Result<ArcFrame>;
    fn configure(&mut self) -> Result<()>;
    fn flush(&mut self) -> Result<()>;
}

#[derive(Debug)]
pub struct Descr {
    pub codec: &'static str,
    pub name: &'static str,
    pub desc: &'static str,
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

pub struct Context {
    dec: Box<Decoder>,
    // TODO: Queue up packets/frames
}

impl Context {
    // TODO: More constructors
    pub fn by_name(codecs: &Codecs, name: &str) -> Option<Context> {
        if let Some(builder) = codecs.by_name(name) {
            let dec = builder.create();
            Some(Context { dec: dec })
        } else {
            None
        }
    }
    pub fn set_extradata(&mut self, extra: &[u8]) {
        self.dec.set_extradata(extra);
    }
    pub fn send_packet(&mut self, pkt: &Packet) -> Result<()> {
        self.dec.send_packet(pkt)
    }
    pub fn receive_frame(&mut self) -> Result<ArcFrame> {
        self.dec.receive_frame()
    }
    pub fn configure(&mut self) -> Result<()> {
        self.dec.configure()
    }

    pub fn flush(&mut self) -> Result<()> {
        self.dec.flush()
    }
}

pub trait Descriptor {
    fn create(&self) -> Box<Decoder>;
    fn describe<'a>(&'a self) -> &'a Descr;
}

pub struct Codecs {
    list: HashMap<&'static str, Vec<&'static Descriptor>>
}

impl CodecList for Codecs {
    type D = Descriptor;

    fn new() -> Codecs {
        Codecs { list: HashMap::new() }
    }

    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Self::D> {
        if let Some(descs) = self.list.get(name) {
            Some(descs[0])
        } else {
            None
        }
    }

    fn append(&mut self, desc: &'static Self::D) {
        let codec_name = desc.describe().codec;

        self.list.entry(codec_name).or_insert(Vec::new()).push(desc);
    }
}

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

    mod dummy {
        use super::super::*;
        use std::rc::Rc;
        use data::pixel::Formaton;

        struct Dec {
            state: usize,
            format: Option<Rc<Formaton>>
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            fn create(&self) -> Box<Decoder> {
                box Dec { state: 0, format: None }
            }
            fn describe<'a>(&'a self) -> &'a Descr {
                &self.descr
            }
        }

        impl Decoder for Dec {
            fn configure(&mut self) -> Result<()> {
                Ok(())
            }
            fn set_extradata(&mut self, extra: &[u8]) {
                if extra.len() > 4 {
                    self.state = 42;
                } else {
                    self.state = 12;
                }
            }
            fn send_packet(&mut self, _packet: &Packet) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_frame(&mut self) -> Result<ArcFrame> {
                unimplemented!()
            }
        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy encoder",
                mime: "x-application/dummy",
            }
        };
    }
    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _dec = codecs.by_name("dummy").unwrap();
    }
}
<|endoftext|>


<commit_before><commit_msg>test for blocking thread with semaphore<commit_after><|endoftext|>


<commit_before>#[macro_use]
extern crate korome;

use korome::*;

fn main() {
    // Create a Graphics object, which creates a window with the given title and dimensions
    let graphics = Graphics::new("Just a single static texture", 800, 600);

    // Load a texture, whose bytes have been loaded at compile-time
    let texture = include_texture!(graphics, "planet.png").unwrap();

    // Create a GameManager with the Graphics object
    let mut gm = GameManager::new(graphics);

    // Run the game until the window is closed.
    gm.run(Box::new(Simple{
        texture: texture
    }))

    /*
    while let Some((_, mut drawer)) = gm.next_frame() {
        drawer.clear(0.1, 0., 1.);
        drawer.draw_texture_rigid(&texture, 0., 0.).unwrap();
    }
    */
}

pub struct Simple{
    texture: Texture
}

impl State for Simple{
    fn frame(&mut self, frame: Option<(FrameInfo, Drawer)>) -> StateChange{
        match frame{
            Some((_, mut drawer)) => {
                drawer.clear(0.1, 0., 1.);
                drawer.draw_texture_rigid(&self.texture, 0., 0.).unwrap();
                StateChange::No
            },
            None => StateChange::Close
        }
    }
}
<commit_msg>Don't use states in the "simple" example<commit_after>#[macro_use]
extern crate korome;

use korome::*;

fn main() {
    // Create a Graphics object, which creates a window with the given title and dimensions
    let graphics = Graphics::new("Just a single static texture", 800, 600);

    // Load a texture, whose bytes have been loaded at compile-time
    let texture = include_texture!(graphics, "planet.png").unwrap();

    // Create a GameManager with the Graphics object
    let mut gm = GameManager::new(graphics);

    // Run the game until the window is closed.
    while let Some((_, mut drawer)) = gm.next_frame() {
        drawer.clear(0.1, 0., 1.);
        drawer.draw_texture_rigid(&texture, 0., 0.).unwrap();
    }
}
<|endoftext|>


<commit_before>extern crate ggez;

use ggez::audio;
use ggez::event;
use ggez::graphics;
use ggez::input;
use ggez::nalgebra as na;
use ggez::{Context, GameResult};

use std::env;
use std::path;
use std::time::Duration;

struct MainState {
    sound: audio::Source,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let sound = audio::Source::new(ctx, "/sound.ogg")?;
        let s = MainState { sound };
        Ok(s)
    }

    // To test: play, play_later, play_detached(),
    // set_repeat, set_fade_in, set_pitch,
    // basically every method on Source, actually,
    // then the same ones for `SpatialSource`.

    /// Plays the sound multiple times
    fn play_detached(&mut self, _ctx: &mut Context) {
        // "detached" sounds keep playing even after they are dropped
        let _ = self.sound.play_detached();
    }

    /// Waits until the sound is done playing before playing again.
    fn play_later(&mut self, _ctx: &mut Context) {
        let _ = self.sound.play_later();
    }

    /// Fades the sound in over a second
    /// Which isn't really ideal 'cause the sound is barely a second long, but still.
    fn play_fadein(&mut self, ctx: &mut Context) {
        let mut sound = audio::Source::new(ctx, "/sound.ogg").unwrap();
        sound.set_fade_in(Duration::from_millis(1000));
        sound.play_detached().unwrap();
    }

    fn play_highpitch(&mut self, ctx: &mut Context) {
        let mut sound = audio::Source::new(ctx, "/sound.ogg").unwrap();
        sound.set_pitch(2.0);
        sound.play_detached().unwrap();
    }
    fn play_lowpitch(&mut self, ctx: &mut Context) {
        let mut sound = audio::Source::new(ctx, "/sound.ogg").unwrap();
        sound.set_pitch(0.5);
        sound.play_detached().unwrap();
    }

    /// Plays the sound and prints out stats until it's done.
    fn play_stats(&mut self, _ctx: &mut Context) {
        let _ = self.sound.play();
        while self.sound.playing() {
            println!("Elapsed time: {:?}", self.sound.elapsed())
        }
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());

        graphics::queue_text(
            ctx,
            &graphics::Text::new("Press number keys a sound, or escape to quit."),
            na::Point2::origin(),
            None,
        );
        graphics::draw_queued_text(ctx, (na::Point2::new(100.0, 100.0),))?;

        graphics::present(ctx)?;
        Ok(())
    }

    fn key_down_event(
        &mut self,
        ctx: &mut Context,
        keycode: input::keyboard::KeyCode,
        _keymod: input::keyboard::KeyMods,
        _repeat: bool,
    ) {
        match keycode {
            input::keyboard::KeyCode::Key1 => self.play_detached(ctx),
            input::keyboard::KeyCode::Key2 => self.play_later(ctx),
            input::keyboard::KeyCode::Key3 => self.play_fadein(ctx),
            input::keyboard::KeyCode::Key4 => self.play_highpitch(ctx),
            input::keyboard::KeyCode::Key5 => self.play_lowpitch(ctx),
            input::keyboard::KeyCode::Key6 => self.play_stats(ctx),
            input::keyboard::KeyCode::Escape => ggez::quit(ctx),
            _ => (),
        }
    }
}

pub fn main() -> GameResult {
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("imageview", "ggez").add_resource_path(resource_dir);
    let (ctx, event_loop) = &mut cb.build()?;

    let state = &mut MainState::new(ctx)?;
    event::run(ctx, event_loop, state)
}
<commit_msg>Minor update to sounds example.<commit_after>extern crate ggez;

use ggez::audio;
use ggez::event;
use ggez::graphics;
use ggez::input;
use ggez::nalgebra as na;
use ggez::{Context, GameResult};

use std::env;
use std::path;
use std::time::Duration;

struct MainState {
    sound: audio::Source,
}

impl MainState {
    fn new(ctx: &mut Context) -> GameResult<MainState> {
        let sound = audio::Source::new(ctx, "/sound.ogg")?;
        let s = MainState { sound };
        Ok(s)
    }

    // To test: play, play_later, play_detached(),
    // set_repeat, set_fade_in, set_pitch,
    // basically every method on Source, actually,
    // then the same ones for `SpatialSource`.

    /// Plays the sound multiple times
    fn play_detached(&mut self, _ctx: &mut Context) {
        // "detached" sounds keep playing even after they are dropped
        let _ = self.sound.play_detached();
    }

    /// Waits until the sound is done playing before playing again.
    fn play_later(&mut self, _ctx: &mut Context) {
        let _ = self.sound.play_later();
    }

    /// Fades the sound in over a second
    /// Which isn't really ideal 'cause the sound is barely a second long, but still.
    fn play_fadein(&mut self, ctx: &mut Context) {
        let mut sound = audio::Source::new(ctx, "/sound.ogg").unwrap();
        sound.set_fade_in(Duration::from_millis(1000));
        sound.play_detached().unwrap();
    }

    fn play_highpitch(&mut self, ctx: &mut Context) {
        let mut sound = audio::Source::new(ctx, "/sound.ogg").unwrap();
        sound.set_pitch(2.0);
        sound.play_detached().unwrap();
    }
    fn play_lowpitch(&mut self, ctx: &mut Context) {
        let mut sound = audio::Source::new(ctx, "/sound.ogg").unwrap();
        sound.set_pitch(0.5);
        sound.play_detached().unwrap();
    }

    /// Plays the sound and prints out stats until it's done.
    fn play_stats(&mut self, _ctx: &mut Context) {
        let _ = self.sound.play();
        while self.sound.playing() {
            println!("Elapsed time: {:?}", self.sound.elapsed())
        }
    }
}

impl event::EventHandler for MainState {
    fn update(&mut self, _ctx: &mut Context) -> GameResult {
        Ok(())
    }

    fn draw(&mut self, ctx: &mut Context) -> GameResult {
        graphics::clear(ctx, [0.1, 0.2, 0.3, 1.0].into());

        graphics::queue_text(
            ctx,
            &graphics::Text::new("Press number keys 1-6 to play a sound, or escape to quit."),
            na::Point2::origin(),
            None,
        );
        graphics::draw_queued_text(ctx, (na::Point2::new(100.0, 100.0),))?;

        graphics::present(ctx)?;
        Ok(())
    }

    fn key_down_event(
        &mut self,
        ctx: &mut Context,
        keycode: input::keyboard::KeyCode,
        _keymod: input::keyboard::KeyMods,
        _repeat: bool,
    ) {
        match keycode {
            input::keyboard::KeyCode::Key1 => self.play_detached(ctx),
            input::keyboard::KeyCode::Key2 => self.play_later(ctx),
            input::keyboard::KeyCode::Key3 => self.play_fadein(ctx),
            input::keyboard::KeyCode::Key4 => self.play_highpitch(ctx),
            input::keyboard::KeyCode::Key5 => self.play_lowpitch(ctx),
            input::keyboard::KeyCode::Key6 => self.play_stats(ctx),
            input::keyboard::KeyCode::Escape => ggez::quit(ctx),
            _ => (),
        }
    }
}

pub fn main() -> GameResult {
    let resource_dir = if let Ok(manifest_dir) = env::var("CARGO_MANIFEST_DIR") {
        let mut path = path::PathBuf::from(manifest_dir);
        path.push("resources");
        path
    } else {
        path::PathBuf::from("./resources")
    };

    let cb = ggez::ContextBuilder::new("imageview", "ggez").add_resource_path(resource_dir);
    let (ctx, event_loop) = &mut cb.build()?;

    let state = &mut MainState::new(ctx)?;
    event::run(ctx, event_loop, state)
}
<|endoftext|>


<commit_before>#![feature(libc)]

extern crate rustc_serialize;
extern crate docopt;
extern crate libvterm_sys;
extern crate libc;

use libvterm_sys::*;
use std::io::prelude::*;
use std::slice;

enum Format { Plain, Sgr }

struct Context {
    cols_count: usize,
    rows_count: usize,
    format: Format,
}

fn color_to_index(state: &State, target: &Color) -> isize {
    for i in 0..256 {
        let color = state.get_palette_color(i);
        if color.red == target.red && color.green == target.green && color.blue == target.blue {
            return i as isize
        }
    }
    -1
}

fn dump_cell(state: &State, cell: &ScreenCell, prev_cell: &ScreenCell, context: &Context) {
    match context.format {
        Format::Plain => {},
        Format::Sgr => {
            let mut sgrs: Vec<isize> = vec!();

            if(!prev_cell.attrs.bold && cell.attrs.bold) {
                sgrs.push(1);
            }

            if(prev_cell.attrs.bold && !cell.attrs.bold) {
                sgrs.push(22);
            }

            if(prev_cell.attrs.underline == 0 && cell.attrs.underline != 0) {
                sgrs.push(4);
            }
            if(prev_cell.attrs.underline != 0 && cell.attrs.underline == 0) {
                sgrs.push(24);
            }

            if(!prev_cell.attrs.italic && cell.attrs.italic) {
                sgrs.push(3);
            }
            if(prev_cell.attrs.italic && !cell.attrs.italic) {
                sgrs.push(23);
            }

            if(!prev_cell.attrs.blink && cell.attrs.blink) {
                sgrs.push(5);
            }
            if(prev_cell.attrs.blink && !cell.attrs.blink) {
                sgrs.push(25);
            }

            if(!prev_cell.attrs.reverse && cell.attrs.reverse) {
                sgrs.push(7);
            }
            if(prev_cell.attrs.reverse && !cell.attrs.reverse) {
                sgrs.push(27);
            }

            if(!prev_cell.attrs.strike && cell.attrs.strike) {
                sgrs.push(9);
            }
            if(prev_cell.attrs.strike && !cell.attrs.strike) {
                sgrs.push(29);
            }

            if(prev_cell.attrs.font == 0 && cell.attrs.font != 0) {
                sgrs.push(10 + cell.attrs.font as isize);
            }
            if(prev_cell.attrs.font != 0 && cell.attrs.font == 0) {
                sgrs.push(10);
            }

            if(prev_cell.fg.red   != cell.fg.red   ||
               prev_cell.fg.green != cell.fg.green ||
               prev_cell.fg.blue  != cell.fg.blue) {
                let index = color_to_index(state, &cell.fg);
                if(index == -1) {
                    sgrs.push(39);
                }
                else if(index < 8) {
                    sgrs.push(30 + index);
                }
                else if(index < 16) {
                    sgrs.push(90 + (index - 8));
                }
                else {
                    sgrs.push(38);
                    sgrs.push(5 | (1<<31));
                    sgrs.push(index | (1<<31));
                }
            }

            if(prev_cell.bg.red   != cell.bg.red   ||
               prev_cell.bg.green != cell.bg.green ||
               prev_cell.bg.blue  != cell.bg.blue) {
                let index = color_to_index(state, &cell.bg);
                if(index == -1) {
                    sgrs.push(49);
                }
                else if(index < 8) {
                    sgrs.push(40 + index);
                }
                else if(index < 16) {
                    sgrs.push(100 + (index - 8));
                }
                else {
                    sgrs.push(48);
                    sgrs.push(5 | (1<<31));
                    sgrs.push(index | (1<<31));
                }
            }

            if sgrs.len() != 0 {
                print!("\x1b[");
                for (i, val) in sgrs.iter().enumerate() {
                    // not sure if this is really c7
                    let bare_val = val & !(1<<31);
                    if i == 0 {
                        print!("{}", bare_val);
                    }
                    else if val & (1<<31) != 0 {
                        print!(":{}", bare_val);
                    }
                    else {
                        print!(";{}", bare_val);
                    }
                }
                print!("m");
            }
        }
    }

    std::io::stdout().write_all(&cell.chars_as_utf8_bytes());
}

fn dump_eol(prev_cell: &ScreenCell, context: &Context) {
    match context.format {
        Format::Plain => {},
        Format::Sgr => {
            if(prev_cell.attrs.bold || prev_cell.attrs.underline != 0|| prev_cell.attrs.italic ||
                prev_cell.attrs.blink || prev_cell.attrs.reverse || prev_cell.attrs.strike ||
                prev_cell.attrs.font != 0) {
                print!("\x1b[m");
            }
        }
    }

    print!("\n");
}

fn dump_row(row: usize, vt: &VTerm, context: &Context) {
    let mut prev_cell: ScreenCell = Default::default();
    let (fg, bg) = vt.get_state().get_default_colors();
    prev_cell.fg = fg;
    prev_cell.bg = bg;

    let vts = vt.get_screen();

    let mut pos = Pos { row: row, col: 0 };
    while pos.col < context.cols_count {
        let cell = vts.get_cell(&pos);

        dump_cell(&vt.get_state(), &cell, &prev_cell, context);

        pos.col += cell.width as usize;
        prev_cell = cell;
    }

    dump_eol(&prev_cell, context);
}

const USAGE: &'static str = "
unterm

Usage:
unterm [-c <cols>] [-l <lines>] [-f <format>] <file>

Options:
-c <cols>      number of columns to display
-l <lines>     number of lines in vterm before scrolling
-f <format>    plain or sgr
";

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_c:    usize,
    flag_l:    usize,
    flag_f:    String,
    arg_file:  String,
}

fn main() {
    let mut args: Args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    args.flag_l = if args.flag_l       != 0 { args.flag_l } else { 25 };
    args.flag_c = if args.flag_c       != 0 { args.flag_c } else { 80 };
    args.flag_f = if args.flag_f.len() != 0 { args.flag_f } else { "sgr".to_string() };

    let mut context = Context {
        rows_count:  args.flag_l,
        cols_count:  args.flag_c,
        format:      if args.flag_f == "sgr" { Format::Sgr } else { Format::Plain },
    };

    let mut vt = VTerm::new(context.rows_count, context.cols_count);

    vt.set_utf8(true);

    let rx = vt.receive_screen_events();

    let mut vts: Screen = vt.get_screen();
    vts.reset(true);

    let mut file = std::fs::File::open(args.arg_file).unwrap();
    let mut read_buf = [0 as u8; 1024];
    loop {
        match file.read(&mut read_buf) {
            Ok(0)   => break,
            Ok(num) => { vt.write(&read_buf[0..num]); },
            Err(_)  => panic!("error reading from file")
        }
    }

    while let Ok(event) = rx.try_recv() {
        match event {
            ScreenEvent::Resize{rows: rows, cols: cols} =>  {
                context.rows_count = rows;
                context.cols_count = cols;
            },
            ScreenEvent::SbPushLine{cells: cells} => {
                let (fg, bg) = vt.get_state().get_default_colors();
                let mut prev_cell: ScreenCell = Default::default();
                prev_cell.fg = fg;
                prev_cell.bg = bg;

                for cell in cells {
                    dump_cell(&vt.get_state(), &cell, &prev_cell, &context);
                    prev_cell = cell
                }

                dump_eol(&prev_cell, &context);
            },
            _ => {},
        }
    }

    for row in 0..context.rows_count {
        dump_row(row, &vt, &context);
    }
}
<commit_msg>Cleanup warnings in unterm<commit_after>#![feature(libc)]

extern crate rustc_serialize;
extern crate docopt;
extern crate libvterm_sys;
extern crate libc;

use libvterm_sys::*;
use std::io::prelude::*;

enum Format { Plain, Sgr }

struct Context {
    cols_count: usize,
    rows_count: usize,
    format: Format,
}

fn color_to_index(state: &State, target: &Color) -> isize {
    for i in 0..256 {
        let color = state.get_palette_color(i);
        if color.red == target.red && color.green == target.green && color.blue == target.blue {
            return i as isize
        }
    }
    -1
}

fn dump_cell(state: &State, cell: &ScreenCell, prev_cell: &ScreenCell, context: &Context) {
    match context.format {
        Format::Plain => {},
        Format::Sgr => {
            let mut sgrs: Vec<isize> = vec!();

            if !prev_cell.attrs.bold && cell.attrs.bold {
                sgrs.push(1);
            }

            if prev_cell.attrs.bold && !cell.attrs.bold {
                sgrs.push(22);
            }

            if prev_cell.attrs.underline == 0 && cell.attrs.underline != 0 {
                sgrs.push(4);
            }
            if prev_cell.attrs.underline != 0 && cell.attrs.underline == 0 {
                sgrs.push(24);
            }

            if !prev_cell.attrs.italic && cell.attrs.italic {
                sgrs.push(3);
            }
            if prev_cell.attrs.italic && !cell.attrs.italic {
                sgrs.push(23);
            }

            if !prev_cell.attrs.blink && cell.attrs.blink {
                sgrs.push(5);
            }
            if prev_cell.attrs.blink && !cell.attrs.blink {
                sgrs.push(25);
            }

            if !prev_cell.attrs.reverse && cell.attrs.reverse {
                sgrs.push(7);
            }
            if prev_cell.attrs.reverse && !cell.attrs.reverse {
                sgrs.push(27);
            }

            if !prev_cell.attrs.strike && cell.attrs.strike {
                sgrs.push(9);
            }
            if prev_cell.attrs.strike && !cell.attrs.strike {
                sgrs.push(29);
            }

            if prev_cell.attrs.font == 0 && cell.attrs.font != 0 {
                sgrs.push(10 + cell.attrs.font as isize);
            }
            if prev_cell.attrs.font != 0 && cell.attrs.font == 0 {
                sgrs.push(10);
            }

            if prev_cell.fg.red   != cell.fg.red   ||
               prev_cell.fg.green != cell.fg.green ||
               prev_cell.fg.blue  != cell.fg.blue {
                let index = color_to_index(state, &cell.fg);
                if index == -1 {
                    sgrs.push(39);
                }
                else if index < 8 {
                    sgrs.push(30 + index);
                }
                else if index < 16 {
                    sgrs.push(90 + (index - 8));
                }
                else {
                    sgrs.push(38);
                    sgrs.push(5 | (1<<31));
                    sgrs.push(index | (1<<31));
                }
            }

            if prev_cell.bg.red   != cell.bg.red   ||
               prev_cell.bg.green != cell.bg.green ||
               prev_cell.bg.blue  != cell.bg.blue {
                let index = color_to_index(state, &cell.bg);
                if index == -1 {
                    sgrs.push(49);
                }
                else if index < 8 {
                    sgrs.push(40 + index);
                }
                else if index < 16 {
                    sgrs.push(100 + (index - 8));
                }
                else {
                    sgrs.push(48);
                    sgrs.push(5 | (1<<31));
                    sgrs.push(index | (1<<31));
                }
            }

            if sgrs.len() != 0 {
                print!("\x1b[");
                for (i, val) in sgrs.iter().enumerate() {
                    // not sure if this is really c7
                    let bare_val = val & !(1<<31);
                    if i == 0 {
                        print!("{}", bare_val);
                    }
                    else if val & (1<<31) != 0 {
                        print!(":{}", bare_val);
                    }
                    else {
                        print!(";{}", bare_val);
                    }
                }
                print!("m");
            }
        }
    }

    std::io::stdout().write_all(&cell.chars_as_utf8_bytes())
                     .ok()
                     .expect("failed to write");
}

fn dump_eol(prev_cell: &ScreenCell, context: &Context) {
    match context.format {
        Format::Plain => {},
        Format::Sgr => {
            if prev_cell.attrs.bold || prev_cell.attrs.underline != 0|| prev_cell.attrs.italic ||
               prev_cell.attrs.blink || prev_cell.attrs.reverse || prev_cell.attrs.strike ||
               prev_cell.attrs.font != 0 {
                print!("\x1b[m");
            }
        }
    }

    print!("\n");
}

fn dump_row(row: usize, vt: &VTerm, context: &Context) {
    let mut prev_cell: ScreenCell = Default::default();
    let (fg, bg) = vt.get_state().get_default_colors();
    prev_cell.fg = fg;
    prev_cell.bg = bg;

    let vts = vt.get_screen();

    let mut pos = Pos { row: row, col: 0 };
    while pos.col < context.cols_count {
        let cell = vts.get_cell(&pos);

        dump_cell(&vt.get_state(), &cell, &prev_cell, context);

        pos.col += cell.width as usize;
        prev_cell = cell;
    }

    dump_eol(&prev_cell, context);
}

const USAGE: &'static str = "
unterm

Usage:
unterm [-c <cols>] [-l <lines>] [-f <format>] <file>

Options:
-c <cols>      number of columns to display
-l <lines>     number of lines in vterm before scrolling
-f <format>    plain or sgr
";

#[derive(Debug, RustcDecodable)]
struct Args {
    flag_c:    usize,
    flag_l:    usize,
    flag_f:    String,
    arg_file:  String,
}

fn main() {
    let mut args: Args = docopt::Docopt::new(USAGE)
        .and_then(|d| d.decode())
        .unwrap_or_else(|e| e.exit());

    args.flag_l = if args.flag_l       != 0 { args.flag_l } else { 25 };
    args.flag_c = if args.flag_c       != 0 { args.flag_c } else { 80 };
    args.flag_f = if args.flag_f.len() != 0 { args.flag_f } else { "sgr".to_string() };

    let mut context = Context {
        rows_count:  args.flag_l,
        cols_count:  args.flag_c,
        format:      if args.flag_f == "sgr" { Format::Sgr } else { Format::Plain },
    };

    let mut vt = VTerm::new(context.rows_count, context.cols_count);

    vt.set_utf8(true);

    let rx = vt.receive_screen_events();

    let mut vts: Screen = vt.get_screen();
    vts.reset(true);

    let mut file = std::fs::File::open(args.arg_file).unwrap();
    let mut read_buf = [0 as u8; 1024];
    loop {
        match file.read(&mut read_buf) {
            Ok(0)   => break,
            Ok(num) => { vt.write(&read_buf[0..num]); },
            Err(_)  => panic!("error reading from file")
        }
    }

    while let Ok(event) = rx.try_recv() {
        match event {
            ScreenEvent::Resize{rows, cols} =>  {
                context.rows_count = rows;
                context.cols_count = cols;
            },
            ScreenEvent::SbPushLine{cells} => {
                let (fg, bg) = vt.get_state().get_default_colors();
                let mut prev_cell: ScreenCell = Default::default();
                prev_cell.fg = fg;
                prev_cell.bg = bg;

                for cell in cells {
                    dump_cell(&vt.get_state(), &cell, &prev_cell, &context);
                    prev_cell = cell
                }

                dump_eol(&prev_cell, &context);
            },
            _ => {},
        }
    }

    for row in 0..context.rows_count {
        dump_row(row, &vt, &context);
    }
}
<|endoftext|>