<commit_before>//! A module to manage protobuf serialization

use std::io::Write;

use errors::Result;
use message::MessageWrite;

use byteorder::WriteBytesExt;
use byteorder::LittleEndian as LE;

/// A struct to write protobuf messages
///
/// # Examples
///
/// ```rust
/// // an automatically generated module which is in a separate file in general
/// mod foo_bar {
///     # use quick_protobuf::{MessageWrite, Writer, Result};
///     # use std::borrow::Cow;
///     # use std::io::Write;
///     pub struct Foo<'a> { pub name: Option<Cow<'a, str>>, }
///     pub struct Bar { pub id: Option<u32> }
///     pub struct FooBar<'a> { pub foos: Vec<Foo<'a>>, pub bars: Vec<Bar>, }
///     impl<'a> MessageWrite for FooBar<'a> {
///         // implements
///         // fn get_size(&self) -> usize { ... }
///         // fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> { ... }
///         # fn get_size(&self) -> usize { 0 }
///         # fn write_message<W: Write>(&self, _: &mut Writer<W>) -> Result<()> { Ok(()) }
///     }
/// }
///
/// // FooBar is a message generated from a proto file
/// // in parcicular it contains a `write_message` function
/// use foo_bar::{FooBar, Foo, Bar};
/// use std::borrow::Cow;
/// use quick_protobuf::Writer;
///
/// fn main() {
///     // let mut r = File::create("...").expect("Cannot create file");
///     // for the sake of example, we'll use a simpler struct which impl `Write`
///     let mut r = Vec::new();
///     let mut writer = Writer::new(&mut r);
///
///     // manually generates a FooBar for the example
///     let foobar = FooBar {
///         foos: vec![Foo { name: Some(Cow::Borrowed("test!")) }, Foo { name: None }],
///         bars: vec![Bar { id: Some(43) }, Bar { id: None }],
///     };
///
///     // now using the generated module
///     writer.write_message(&foobar).expect("Cannot write FooBar");
/// }
/// ```
pub struct Writer<W> {
    inner: W,
}

impl<W: Write> Writer<W> {

    /// Creates a new `ProtobufWriter`
    pub fn new(w: W) -> Writer<W> {
        Writer { inner: w }
    }

    /// Writes a `varint` (compacted `u64`)
    pub fn write_varint(&mut self, mut v: u64) -> Result<()> {
        while v > 0x7F {
            self.inner.write_u8(((v as u8) & 0x7F) | 0x80)?;
            v >>= 7;
        }
        self.inner.write_u8(v as u8).map_err(|e| e.into())
    }

    /// Writes a tag, which represents both the field number and the wire type
    pub fn write_tag(&mut self, tag: u32) -> Result<()> {
        self.write_varint(tag as u64)
    }

    /// Writes a `int32` which is internally coded as a `varint`
    pub fn write_int32(&mut self, v: i32) -> Result<()> {
        self.write_varint(v as u64)
    }

    /// Writes a `int64` which is internally coded as a `varint`
    pub fn write_int64(&mut self, v: i64) -> Result<()> {
        self.write_varint(v as u64)
    }

    /// Writes a `uint32` which is internally coded as a `varint`
    pub fn write_uint32(&mut self, v: u32) -> Result<()> {
        self.write_varint(v as u64)
    }

    /// Writes a `uint64` which is internally coded as a `varint`
    pub fn write_uint64(&mut self, v: u64) -> Result<()> {
        self.write_varint(v)
    }

    /// Writes a `sint32` which is internally coded as a `varint`
    pub fn write_sint32(&mut self, v: i32) -> Result<()> {
        self.write_varint(((v << 1) ^ (v >> 31)) as u64)
    }

    /// Writes a `sint64` which is internally coded as a `varint`
    pub fn write_sint64(&mut self, v: i64) -> Result<()> {
        self.write_varint(((v << 1) ^ (v >> 63)) as u64)
    }

    /// Writes a `fixed64` which is little endian coded `u64`
    pub fn write_fixed64(&mut self, v: u64) -> Result<()> {
        self.inner.write_u64::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `fixed32` which is little endian coded `u32`
    pub fn write_fixed32(&mut self, v: u32) -> Result<()> {
        self.inner.write_u32::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `sfixed64` which is little endian coded `i64`
    pub fn write_sfixed64(&mut self, v: i64) -> Result<()> {
        self.inner.write_i64::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `sfixed32` which is little endian coded `i32`
    pub fn write_sfixed32(&mut self, v: i32) -> Result<()> {
        self.inner.write_i32::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `float`
    pub fn write_float(&mut self, v: f32) -> Result<()> {
        self.inner.write_f32::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `double`
    pub fn write_double(&mut self, v: f64) -> Result<()> {
        self.inner.write_f64::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `bool` 1 = true, 0 = false
    pub fn write_bool(&mut self, v: bool) -> Result<()> {
        self.write_varint(if v { 1 } else { 0 })
    }

    /// Writes an `enum` converting it to a `i32` first
    pub fn write_enum(&mut self, v: i32) -> Result<()> {
        self.write_int32(v)
    }

    /// Writes `bytes`: length first then the chunk of data
    pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<()> {
        self.write_varint(bytes.len() as u64)?;
        self.inner.write_all(bytes).map_err(|e| e.into())
    }

    /// Writes `string`: length first then the chunk of data
    pub fn write_string(&mut self, s: &str) -> Result<()> {
        self.write_bytes(s.as_bytes())
    }

    /// Writes packed repeated field: length first then the chunk of data
    pub fn write_packed<M, F, S>(&mut self, v: &[M], mut write: F, size: &S) -> Result<()>
        where F: FnMut(&mut Self, &M) -> Result<()>,
              S: Fn(&M) -> usize,
    {
        if v.is_empty() {
            return Ok(());
        }
        let len: usize = v.iter().map(|m| size(m)).sum();
        self.write_varint(len as u64)?;
        for m in v {
            write(self, m)?;
        }
        Ok(())
    }

    /// Writes packed repeated field when we know the size of items
    ///
    /// `item_size` is internally used to compute the total length
    /// As the length is fixed (and the same as rust internal representation, we can directly dump
    /// all data at once
    pub fn write_packed_fixed<M>(&mut self, v: &[M]) -> Result<()> {
        let len = v.len() * ::std::mem::size_of::<M>();
        let bytes = unsafe { ::std::slice::from_raw_parts(v.as_ptr() as *const u8, len) };
        self.write_bytes(bytes)
    }

    /// Writes a message which implements `MessageWrite`
    pub fn write_message<M: MessageWrite>(&mut self, m: &M) -> Result<()> {
        let len = m.get_size();
        self.write_varint(len as u64)?;
        m.write_message(self)
    }

    /// Writes another item prefixed with tag
    pub fn write_with_tag<F>(&mut self, tag: u32, mut write: F) -> Result<()>
        where F: FnMut(&mut Self) -> Result<()>
    {
        self.write_tag(tag)?;
        write(self)
    }

    /// Writes tag then repeated field
    ///
    /// If array is empty, then do nothing (do not even write the tag)
    pub fn write_packed_with_tag<M, F, S>(&mut self,
                                          tag: u32,
                                          v: &[M],
                                          mut write: F,
                                          size: &S) -> Result<()>
        where F: FnMut(&mut Self, &M) -> Result<()>,
              S: Fn(&M) -> usize,
    {
        if v.is_empty() {
            return Ok(());
        }

        self.write_tag(tag)?;
        let len: usize = v.iter().map(|m| size(m)).sum();
        self.write_varint(len as u64)?;
        for m in v {
            write(self, m)?;
        }
        Ok(())
    }

    /// Writes tag then repeated field
    ///
    /// If array is empty, then do nothing (do not even write the tag)
    pub fn write_packed_fixed_with_tag<M>(&mut self, tag: u32, v: &[M]) -> Result<()>
    {
        if v.is_empty() {
            return Ok(());
        }

        self.write_tag(tag)?;
        let len = ::std::mem::size_of::<M>() * v.len();
        let bytes = unsafe { ::std::slice::from_raw_parts(v.as_ptr() as *const u8, len) };
        self.write_bytes(bytes)
    }

    /// Writes tag then repeated field with fixed length item size
    ///
    /// If array is empty, then do nothing (do not even write the tag)
    pub fn write_packed_fixed_size_with_tag<M>(&mut self,
                                               tag: u32,
                                               v: &[M],
                                               item_size: usize) -> Result<()> {
        if v.is_empty() {
            return Ok(());
        }
        self.write_tag(tag)?;
        let len = v.len() * item_size;
        let bytes = unsafe { ::std::slice::from_raw_parts(v as *const [M] as *const M as *const u8, len) };
        self.write_bytes(bytes)
    }

    /// Write entire map
    pub fn write_map<FK, FV>(&mut self, size: usize,
                             tag_key: u32, mut write_key: FK,
                             tag_val: u32, mut write_val: FV) -> Result<()>
        where FK: FnMut(&mut Self) -> Result<()>,
              FV: FnMut(&mut Self) -> Result<()>,
    {
        self.write_varint(size as u64)?;
        self.write_tag(tag_key)?;
        write_key(self)?;
        self.write_tag(tag_val)?;
        write_val(self)
    }
}
<commit_msg>add inlines and avoid varint for bool (#79)<commit_after>//! A module to manage protobuf serialization

use std::io::Write;

use errors::Result;
use message::MessageWrite;

use byteorder::WriteBytesExt;
use byteorder::LittleEndian as LE;

/// A struct to write protobuf messages
///
/// # Examples
///
/// ```rust
/// // an automatically generated module which is in a separate file in general
/// mod foo_bar {
///     # use quick_protobuf::{MessageWrite, Writer, Result};
///     # use std::borrow::Cow;
///     # use std::io::Write;
///     pub struct Foo<'a> { pub name: Option<Cow<'a, str>>, }
///     pub struct Bar { pub id: Option<u32> }
///     pub struct FooBar<'a> { pub foos: Vec<Foo<'a>>, pub bars: Vec<Bar>, }
///     impl<'a> MessageWrite for FooBar<'a> {
///         // implements
///         // fn get_size(&self) -> usize { ... }
///         // fn write_message<W: Write>(&self, r: &mut Writer<W>) -> Result<()> { ... }
///         # fn get_size(&self) -> usize { 0 }
///         # fn write_message<W: Write>(&self, _: &mut Writer<W>) -> Result<()> { Ok(()) }
///     }
/// }
///
/// // FooBar is a message generated from a proto file
/// // in parcicular it contains a `write_message` function
/// use foo_bar::{FooBar, Foo, Bar};
/// use std::borrow::Cow;
/// use quick_protobuf::Writer;
///
/// fn main() {
///     // let mut r = File::create("...").expect("Cannot create file");
///     // for the sake of example, we'll use a simpler struct which impl `Write`
///     let mut r = Vec::new();
///     let mut writer = Writer::new(&mut r);
///
///     // manually generates a FooBar for the example
///     let foobar = FooBar {
///         foos: vec![Foo { name: Some(Cow::Borrowed("test!")) }, Foo { name: None }],
///         bars: vec![Bar { id: Some(43) }, Bar { id: None }],
///     };
///
///     // now using the generated module
///     writer.write_message(&foobar).expect("Cannot write FooBar");
/// }
/// ```
pub struct Writer<W> {
    inner: W,
}

impl<W: Write> Writer<W> {

    /// Creates a new `ProtobufWriter`
    pub fn new(w: W) -> Writer<W> {
        Writer { inner: w }
    }

    /// Writes a `varint` (compacted `u64`)
    pub fn write_varint(&mut self, mut v: u64) -> Result<()> {
        while v > 0x7F {
            self.inner.write_u8(((v as u8) & 0x7F) | 0x80)?;
            v >>= 7;
        }
        self.inner.write_u8(v as u8).map_err(|e| e.into())
    }

    /// Writes a tag, which represents both the field number and the wire type
    #[inline(always)]
    pub fn write_tag(&mut self, tag: u32) -> Result<()> {
        self.write_varint(tag as u64)
    }

    /// Writes a `int32` which is internally coded as a `varint`
    #[inline(always)]
    pub fn write_int32(&mut self, v: i32) -> Result<()> {
        self.write_varint(v as u64)
    }

    /// Writes a `int64` which is internally coded as a `varint`
    #[inline(always)]
    pub fn write_int64(&mut self, v: i64) -> Result<()> {
        self.write_varint(v as u64)
    }

    /// Writes a `uint32` which is internally coded as a `varint`
    #[inline(always)]
    pub fn write_uint32(&mut self, v: u32) -> Result<()> {
        self.write_varint(v as u64)
    }

    /// Writes a `uint64` which is internally coded as a `varint`
    #[inline(always)]
    pub fn write_uint64(&mut self, v: u64) -> Result<()> {
        self.write_varint(v)
    }

    /// Writes a `sint32` which is internally coded as a `varint`
    #[inline(always)]
    pub fn write_sint32(&mut self, v: i32) -> Result<()> {
        self.write_varint(((v << 1) ^ (v >> 31)) as u64)
    }

    /// Writes a `sint64` which is internally coded as a `varint`
    #[inline(always)]
    pub fn write_sint64(&mut self, v: i64) -> Result<()> {
        self.write_varint(((v << 1) ^ (v >> 63)) as u64)
    }

    /// Writes a `fixed64` which is little endian coded `u64`
    #[inline(always)]
    pub fn write_fixed64(&mut self, v: u64) -> Result<()> {
        self.inner.write_u64::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `fixed32` which is little endian coded `u32`
    #[inline(always)]
    pub fn write_fixed32(&mut self, v: u32) -> Result<()> {
        self.inner.write_u32::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `sfixed64` which is little endian coded `i64`
    #[inline(always)]
    pub fn write_sfixed64(&mut self, v: i64) -> Result<()> {
        self.inner.write_i64::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `sfixed32` which is little endian coded `i32`
    #[inline(always)]
    pub fn write_sfixed32(&mut self, v: i32) -> Result<()> {
        self.inner.write_i32::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `float`
    #[inline(always)]
    pub fn write_float(&mut self, v: f32) -> Result<()> {
        self.inner.write_f32::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `double`
    #[inline(always)]
    pub fn write_double(&mut self, v: f64) -> Result<()> {
        self.inner.write_f64::<LE>(v).map_err(|e| e.into())
    }

    /// Writes a `bool` 1 = true, 0 = false
    #[inline(always)]
    pub fn write_bool(&mut self, v: bool) -> Result<()> {
        self.inner.write_u8(if v { 1 } else { 0 }).map_err(|e| e.into())
    }

    /// Writes an `enum` converting it to a `i32` first
    #[inline(always)]
    pub fn write_enum(&mut self, v: i32) -> Result<()> {
        self.write_int32(v)
    }

    /// Writes `bytes`: length first then the chunk of data
    #[inline(always)]
    pub fn write_bytes(&mut self, bytes: &[u8]) -> Result<()> {
        self.write_varint(bytes.len() as u64)?;
        self.inner.write_all(bytes).map_err(|e| e.into())
    }

    /// Writes `string`: length first then the chunk of data
    #[inline(always)]
    pub fn write_string(&mut self, s: &str) -> Result<()> {
        self.write_bytes(s.as_bytes())
    }

    /// Writes packed repeated field: length first then the chunk of data
    pub fn write_packed<M, F, S>(&mut self, v: &[M], mut write: F, size: &S) -> Result<()>
        where F: FnMut(&mut Self, &M) -> Result<()>,
              S: Fn(&M) -> usize,
    {
        if v.is_empty() {
            return Ok(());
        }
        let len: usize = v.iter().map(|m| size(m)).sum();
        self.write_varint(len as u64)?;
        for m in v {
            write(self, m)?;
        }
        Ok(())
    }

    /// Writes packed repeated field when we know the size of items
    ///
    /// `item_size` is internally used to compute the total length
    /// As the length is fixed (and the same as rust internal representation, we can directly dump
    /// all data at once
    #[inline]
    pub fn write_packed_fixed<M>(&mut self, v: &[M]) -> Result<()> {
        let len = v.len() * ::std::mem::size_of::<M>();
        let bytes = unsafe { ::std::slice::from_raw_parts(v.as_ptr() as *const u8, len) };
        self.write_bytes(bytes)
    }

    /// Writes a message which implements `MessageWrite`
    #[inline]
    pub fn write_message<M: MessageWrite>(&mut self, m: &M) -> Result<()> {
        let len = m.get_size();
        self.write_varint(len as u64)?;
        m.write_message(self)
    }

    /// Writes another item prefixed with tag
    #[inline]
    pub fn write_with_tag<F>(&mut self, tag: u32, mut write: F) -> Result<()>
        where F: FnMut(&mut Self) -> Result<()>
    {
        self.write_tag(tag)?;
        write(self)
    }

    /// Writes tag then repeated field
    ///
    /// If array is empty, then do nothing (do not even write the tag)
    pub fn write_packed_with_tag<M, F, S>(&mut self,
                                          tag: u32,
                                          v: &[M],
                                          mut write: F,
                                          size: &S) -> Result<()>
        where F: FnMut(&mut Self, &M) -> Result<()>,
              S: Fn(&M) -> usize,
    {
        if v.is_empty() {
            return Ok(());
        }

        self.write_tag(tag)?;
        let len: usize = v.iter().map(|m| size(m)).sum();
        self.write_varint(len as u64)?;
        for m in v {
            write(self, m)?;
        }
        Ok(())
    }

    /// Writes tag then repeated field
    ///
    /// If array is empty, then do nothing (do not even write the tag)
    pub fn write_packed_fixed_with_tag<M>(&mut self, tag: u32, v: &[M]) -> Result<()>
    {
        if v.is_empty() {
            return Ok(());
        }

        self.write_tag(tag)?;
        let len = ::std::mem::size_of::<M>() * v.len();
        let bytes = unsafe { ::std::slice::from_raw_parts(v.as_ptr() as *const u8, len) };
        self.write_bytes(bytes)
    }

    /// Writes tag then repeated field with fixed length item size
    ///
    /// If array is empty, then do nothing (do not even write the tag)
    pub fn write_packed_fixed_size_with_tag<M>(&mut self,
                                               tag: u32,
                                               v: &[M],
                                               item_size: usize) -> Result<()> {
        if v.is_empty() {
            return Ok(());
        }
        self.write_tag(tag)?;
        let len = v.len() * item_size;
        let bytes = unsafe { ::std::slice::from_raw_parts(v as *const [M] as *const M as *const u8, len) };
        self.write_bytes(bytes)
    }

    /// Write entire map
    pub fn write_map<FK, FV>(&mut self, size: usize,
                             tag_key: u32, mut write_key: FK,
                             tag_val: u32, mut write_val: FV) -> Result<()>
        where FK: FnMut(&mut Self) -> Result<()>,
              FV: FnMut(&mut Self) -> Result<()>,
    {
        self.write_varint(size as u64)?;
        self.write_tag(tag_key)?;
        write_key(self)?;
        self.write_tag(tag_val)?;
        write_val(self)
    }
}
<|endoftext|>


<commit_before>use memory::FrameAllocator;
use memory::paging::ENTRY_COUNT;
use memory::paging::entry::*;
use core::ops::{Index, IndexMut};
use core::marker::PhantomData;

pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;

pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    _phantom: PhantomData<L>,
}

impl<L> Table<L> where L: TableLevel
{
    pub fn zero(&mut self) {
        for entry in self.entries.iter_mut() {
            entry.set_unused();
        }
    }
}

impl<L> Table<L> where L: HierachicalLevel
{
    pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
        self.next_table_address(index).map(|t| unsafe { &*(t as *const _) })
    }

    pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
        self.next_table_address(index).map(|t| unsafe { &mut *(t as *mut _) })
    }

    pub fn next_table_create<A>(&mut self,
                                index: usize,
                                allocator: &mut A)
                                -> &mut Table<L::NextLevel>
        where A: FrameAllocator
    {
        if let None = self.next_table_address(index) {
            assert!(!self.entries[index].flags().contains(HUGE_PAGE),
                    "mapping code does not support huge pages");
            let frame = allocator.allocate_frame().expect("no frames available");
            self.entries[index].set(frame, PRESENT | WRITABLE);
            self.next_table_mut(index).unwrap().zero();
        }
        self.next_table_mut(index).unwrap()
    }

    fn next_table_address(&self, index: usize) -> Option<usize> {
        let entry_flags = self[index].flags();
        if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
            let table_address = self as *const _ as usize;
            Some((table_address << 9) | (index << 12))
        } else {
            None
        }
    }
}

impl<L> Index<usize> for Table<L> where L: TableLevel
{
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

impl<L> IndexMut<usize> for Table<L> where L: TableLevel
{
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}

pub trait TableLevel {}

pub enum Level4 {}
#[allow(dead_code)]
enum Level3 {}
#[allow(dead_code)]
enum Level2 {}
#[allow(dead_code)]
enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

trait HierachicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierachicalLevel for Level4 {
    type NextLevel = Level3;
}

impl HierachicalLevel for Level3 {
    type NextLevel = Level2;
}

impl HierachicalLevel for Level2 {
    type NextLevel = Level1;
}
<commit_msg>Rename PhantomData field<commit_after>use memory::FrameAllocator;
use memory::paging::ENTRY_COUNT;
use memory::paging::entry::*;
use core::ops::{Index, IndexMut};
use core::marker::PhantomData;

pub const P4: *mut Table<Level4> = 0xffffffff_fffff000 as *mut _;

pub struct Table<L: TableLevel> {
    entries: [Entry; ENTRY_COUNT],
    level: PhantomData<L>,
}

impl<L> Table<L> where L: TableLevel
{
    pub fn zero(&mut self) {
        for entry in self.entries.iter_mut() {
            entry.set_unused();
        }
    }
}

impl<L> Table<L> where L: HierachicalLevel
{
    pub fn next_table(&self, index: usize) -> Option<&Table<L::NextLevel>> {
        self.next_table_address(index).map(|t| unsafe { &*(t as *const _) })
    }

    pub fn next_table_mut(&mut self, index: usize) -> Option<&mut Table<L::NextLevel>> {
        self.next_table_address(index).map(|t| unsafe { &mut *(t as *mut _) })
    }

    pub fn next_table_create<A>(&mut self,
                                index: usize,
                                allocator: &mut A)
                                -> &mut Table<L::NextLevel>
        where A: FrameAllocator
    {
        if let None = self.next_table_address(index) {
            assert!(!self.entries[index].flags().contains(HUGE_PAGE),
                    "mapping code does not support huge pages");
            let frame = allocator.allocate_frame().expect("no frames available");
            self.entries[index].set(frame, PRESENT | WRITABLE);
            self.next_table_mut(index).unwrap().zero();
        }
        self.next_table_mut(index).unwrap()
    }

    fn next_table_address(&self, index: usize) -> Option<usize> {
        let entry_flags = self[index].flags();
        if entry_flags.contains(PRESENT) && !entry_flags.contains(HUGE_PAGE) {
            let table_address = self as *const _ as usize;
            Some((table_address << 9) | (index << 12))
        } else {
            None
        }
    }
}

impl<L> Index<usize> for Table<L> where L: TableLevel
{
    type Output = Entry;

    fn index(&self, index: usize) -> &Entry {
        &self.entries[index]
    }
}

impl<L> IndexMut<usize> for Table<L> where L: TableLevel
{
    fn index_mut(&mut self, index: usize) -> &mut Entry {
        &mut self.entries[index]
    }
}

pub trait TableLevel {}

pub enum Level4 {}
#[allow(dead_code)]
enum Level3 {}
#[allow(dead_code)]
enum Level2 {}
#[allow(dead_code)]
enum Level1 {}

impl TableLevel for Level4 {}
impl TableLevel for Level3 {}
impl TableLevel for Level2 {}
impl TableLevel for Level1 {}

trait HierachicalLevel: TableLevel {
    type NextLevel: TableLevel;
}

impl HierachicalLevel for Level4 {
    type NextLevel = Level3;
}

impl HierachicalLevel for Level3 {
    type NextLevel = Level2;
}

impl HierachicalLevel for Level2 {
    type NextLevel = Level1;
}
<|endoftext|>


<commit_before>use byteorder::{BigEndian, WriteBytesExt};
use generic_array::{ArrayLength, GenericArray};
use std::io::{Result, Error, ErrorKind, Read, Write};
use std::mem::size_of;

pub trait Message {
    fn hash(&self) -> i64 { 0 }
    fn encode(&self, buffer: &mut Write) -> Result<()>;
    fn decode(&mut self, buffer: &mut Read) -> Result<()> { Err(Error::new(ErrorKind::Other, "Unimplemented")) }
    fn size(&self) -> usize;
}

impl Message for bool {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let value : i8 = match *self {
            true => 1,
            false => 0
        };
        value.encode(buffer)
    }

    fn size(&self) -> usize {
        size_of::<i8>()
    }
}

impl Message for u8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u8(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i8(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i16 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f32::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f64::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for str {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let len : i32 = self.len() as i32 + 1;
        len.encode(buffer)?;
        for &b in self.as_bytes() {
            b.encode(buffer)?;
        }
        (1 as u8).encode(buffer)?;
        Ok(())
    }

    fn size(&self) -> usize {
        size_of::<i32>() + self.len() + 1
    }
}

impl<T> Message for Vec<T> where
    T : Message {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        for val in self.iter() {
            val.encode(buffer)?;
        }
        Ok(())
    }

    fn size(&self) -> usize {
        self.iter().map(Message::size).sum()
    }
}

impl<T,N> Message for GenericArray<T, N> where
    T : Message, N : ArrayLength<T> {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        for val in self.iter() {
            val.encode(buffer)?;
        }
        Ok(())
    }

    fn size(&self) -> usize {
        self.iter().map(Message::size).sum()
    }
}
<commit_msg>Fix null terminator for string.<commit_after>use byteorder::{BigEndian, WriteBytesExt};
use generic_array::{ArrayLength, GenericArray};
use std::io::{Result, Error, ErrorKind, Read, Write};
use std::mem::size_of;

pub trait Message {
    fn hash(&self) -> i64 { 0 }
    fn encode(&self, buffer: &mut Write) -> Result<()>;
    fn decode(&mut self, buffer: &mut Read) -> Result<()> { Err(Error::new(ErrorKind::Other, "Unimplemented")) }
    fn size(&self) -> usize;
}

impl Message for bool {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let value : i8 = match *self {
            true => 1,
            false => 0
        };
        value.encode(buffer)
    }

    fn size(&self) -> usize {
        size_of::<i8>()
    }
}

impl Message for u8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u8(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i8(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i16 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f32::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f64::<BigEndian>(*self)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for String {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let len : i32 = self.len() as i32 + 1;
        len.encode(buffer)?;
        for &b in self.as_bytes() {
            b.encode(buffer)?;
        }
        (0 as u8).encode(buffer)?;
        Ok(())
    }

    fn size(&self) -> usize {
        size_of::<i32>() + self.len() + 1
    }
}

impl<T> Message for Vec<T> where
    T : Message {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        for val in self.iter() {
            val.encode(buffer)?;
        }
        Ok(())
    }

    fn size(&self) -> usize {
        self.iter().map(Message::size).sum()
    }
}

impl<T,N> Message for GenericArray<T, N> where
    T : Message, N : ArrayLength<T> {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        for val in self.iter() {
            val.encode(buffer)?;
        }
        Ok(())
    }

    fn size(&self) -> usize {
        self.iter().map(Message::size).sum()
    }
}
<|endoftext|>


<commit_before>/*!
 * Hello World server in Rust
 * Binds REP socket to tcp://*:5555
 * Expects "Hello" from client, replies with "World"
 */

extern mod zmq;

use std::rt;

fn main() {
#[fixed_stack_segment];

    let context = zmq::Context::new();
    let responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new();
    loop {
        responder.recv(&mut msg, 0);
        do msg.with_str |s| {
            printfln!("Received %s", s);
        }
        responder.send_str("World", 0);
        let timer = ~rt::io::Timer::new();
        do timer.map_move |mut t| { t.sleep(1000) };
    }
}
<commit_msg>std::rt now has a standalone sleep() function<commit_after>/*!
 * Hello World server in Rust
 * Binds REP socket to tcp://*:5555
 * Expects "Hello" from client, replies with "World"
 */

extern mod zmq;

use std::rt;

fn main() {
#[fixed_stack_segment];

    let context = zmq::Context::new();
    let responder = context.socket(zmq::REP).unwrap();

    assert!(responder.bind("tcp://*:5555").is_ok());

    let mut msg = zmq::Message::new();
    loop {
        responder.recv(&mut msg, 0);
        do msg.with_str |s| {
            printfln!("Received %s", s);
        }
        responder.send_str("World", 0);
        rt::io::timer::sleep(1000);
    }
}
<|endoftext|>


<commit_before>//! This module contains the concept of a DICOM data dictionary.
//!
//! The standard data dictionary is available in the `dicom-std-dict` crate.

pub mod stub;

use crate::header::{Tag, VR};
use std::fmt::Debug;

/** Type trait for a dictionary of DICOM attributes. Attribute dictionaries provide the
 * means to convert a tag to an alias and vice versa, as well as a form of retrieving
 * additional information about the attribute.
 *
 * The methods herein have no generic parameters, so as to enable being
 * used as a trait object.
 */
pub trait DataDictionary: Debug {
    /// The type of the dictionary entry.
    type Entry: DictionaryEntry;

    /// Fetch an entry by its usual alias (e.g. "PatientName" or "SOPInstanceUID").
    /// Aliases are usually case sensitive and not separated by spaces.
    fn by_name(&self, name: &str) -> Option<&Self::Entry>;

    /// Fetch an entry by its tag.
    fn by_tag(&self, tag: Tag) -> Option<&Self::Entry>;
}

/// The dictionary entry data type, representing a DICOM attribute.
pub trait DictionaryEntry {
    /// The attribute tag.
    fn tag(&self) -> Tag;
    /// The alias of the attribute, with no spaces, usually in UpperCamelCase.
    fn alias(&self) -> &str;
    /// The _typical_ value representation of the attribute.
    /// In some edge cases, an element might not have this VR.
    fn vr(&self) -> VR;
}

/// A data type for a dictionary entry with full ownership.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct DictionaryEntryBuf {
    /// The attribute tag
    pub tag: Tag,
    /// The alias of the attribute, with no spaces, usually InCapitalizedCamelCase
    pub alias: String,
    /// The _typical_  value representation of the attribute
    pub vr: VR,
}

impl DictionaryEntry for DictionaryEntryBuf {
    fn tag(&self) -> Tag {
        self.tag
    }
    fn alias(&self) -> &str {
        self.alias.as_str()
    }
    fn vr(&self) -> VR {
        self.vr
    }
}

/// A data type for a dictionary entry with a string slice for its alias.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct DictionaryEntryRef<'a> {
    /// The attribute tag
    pub tag: Tag,
    /// The alias of the attribute, with no spaces, usually InCapitalizedCamelCase
    pub alias: &'a str,
    /// The _typical_  value representation of the attribute
    pub vr: VR,
}

impl<'a> DictionaryEntry for DictionaryEntryRef<'a> {
    fn tag(&self) -> Tag {
        self.tag
    }
    fn alias(&self) -> &str {
        self.alias
    }
    fn vr(&self) -> VR {
        self.vr
    }
}

/// Utility data structure that resolves to a DICOM attribute tag
/// at a later time.
#[derive(Debug)]
pub struct TagByName<N: AsRef<str>, D: DataDictionary> {
    dict: D,
    name: N,
}

impl<N: AsRef<str>, D: DataDictionary> TagByName<N, D> {
    /// Create a tag resolver by name using the given dictionary.
    pub fn new(dictionary: D, name: N) -> TagByName<N, D> {
        TagByName {
            dict: dictionary,
            name: name,
        }
    }
}

impl<N: AsRef<str>, D: DataDictionary> From<TagByName<N, D>> for Option<Tag> {
    fn from(tag: TagByName<N, D>) -> Option<Tag> {
        tag.dict.by_name(tag.name.as_ref()).map(|e| e.tag())
    }
}
<commit_msg>[core] add TagRange struct<commit_after>//! This module contains the concept of a DICOM data dictionary.
//!
//! The standard data dictionary is available in the `dicom-std-dict` crate.

pub mod stub;

use crate::header::{Tag, VR};
use std::fmt::Debug;
use std::str::FromStr;

/// Specification of a range of tags pertaining to an attribute.
/// Very often, the dictionary of attributes indicates a unique `(group,elem)`
/// for a specific attribute, but occasionally a range of groups or elements
/// is indicated instead (e.g. _Pixel Data_ is associated with ).
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum TagRange {
    /// Only a specific tag
    Single(Tag),
    /// The two rightmost digits of the _group_ portion are open:
    /// `(GGxx,EEEE)`
    Group100(Tag),
    /// The two rightmost digits of the _element_ portion are open:
    /// `(GGGG,EExx)`
    Element100(Tag),
}

impl TagRange {
    /// Retrieve the inner tag representation of this range.
    pub fn inner(self) -> Tag {
        match self {
            TagRange::Single(tag) => tag,
            TagRange::Group100(tag) => tag,
            TagRange::Element100(tag) => tag,
        }
    }
}

/// An error returned when parsing an invalid tag range.
#[derive(Debug, Default, Copy, Clone, Eq, PartialEq)]
pub struct TagRangeParseError(&'static str);

impl FromStr for TagRange {
    type Err = TagRangeParseError;

    fn from_str(mut s: &str) -> Result<Self, Self::Err> {
        if s.starts_with('(') && s.ends_with(')') {
            s = &s[1 .. s.len() - 1];
        }
        let mut parts = s.split(',');
        let group = parts.next().ok_or(TagRangeParseError("not enough tag components, expected `group,element`"))?;
        let elem = parts.next().ok_or(TagRangeParseError("not enough tag components, expected `element`"))?;
        if group.len() != 4 {
            return Err(TagRangeParseError("tag component `group` has an invalid length, must be 4"));
        }
        if elem.len() != 4 {
            return Err(TagRangeParseError("tag component `element` has an invalid length, must be 4"));
        }

        match (&group.as_bytes()[2..], &elem.as_bytes()[2..]) {
            (b"xx", b"xx") => {
                return Err(TagRangeParseError("unsupported tag range"));
            },
            (b"xx", _) => {
                // Group100
                let group = u16::from_str_radix(&group[..2], 16)
                    .map_err(|_e| TagRangeParseError("Invalid component `group`"))? << 8;
                let elem = u16::from_str_radix(elem, 16)
                    .map_err(|_e| TagRangeParseError("Invalid component `element`"))?;
                Ok(TagRange::Group100(Tag(group, elem)))
            },
            (_, b"xx") => {
                // Element100
                let group = u16::from_str_radix(group, 16)
                    .map_err(|_e| TagRangeParseError("Invalid component `group`"))?;
                let elem = u16::from_str_radix(&elem[..2], 16)
                    .map_err(|_e| TagRangeParseError("Invalid component `element`"))? << 8;
                Ok(TagRange::Element100(Tag(group, elem)))
            },
            (_, _) => {
                // single element
                let group = u16::from_str_radix(group, 16)
                    .map_err(|_e| TagRangeParseError("Invalid component `group`"))?;
                let elem = u16::from_str_radix(elem, 16)
                    .map_err(|_e| TagRangeParseError("Invalid component `element`"))?;
                Ok(TagRange::Single(Tag(group, elem)))
            }
        }
    }
}

/** Type trait for a dictionary of DICOM attributes. Attribute dictionaries provide the
 * means to convert a tag to an alias and vice versa, as well as a form of retrieving
 * additional information about the attribute.
 *
 * The methods herein have no generic parameters, so as to enable being
 * used as a trait object.
 */
pub trait DataDictionary: Debug {
    /// The type of the dictionary entry.
    type Entry: DictionaryEntry;

    /// Fetch an entry by its usual alias (e.g. "PatientName" or "SOPInstanceUID").
    /// Aliases are usually case sensitive and not separated by spaces.
    fn by_name(&self, name: &str) -> Option<&Self::Entry>;

    /// Fetch an entry by its tag.
    fn by_tag(&self, tag: Tag) -> Option<&Self::Entry>;
}

/// The dictionary entry data type, representing a DICOM attribute.
pub trait DictionaryEntry {
    /// The attribute tag.
    fn tag(&self) -> Tag;
    /// The alias of the attribute, with no spaces, usually in UpperCamelCase.
    fn alias(&self) -> &str;
    /// The _typical_ value representation of the attribute.
    /// In some edge cases, an element might not have this VR.
    fn vr(&self) -> VR;
}

/// A data type for a dictionary entry with full ownership.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct DictionaryEntryBuf {
    /// The attribute tag
    pub tag: Tag,
    /// The alias of the attribute, with no spaces, usually InCapitalizedCamelCase
    pub alias: String,
    /// The _typical_  value representation of the attribute
    pub vr: VR,
}

impl DictionaryEntry for DictionaryEntryBuf {
    fn tag(&self) -> Tag {
        self.tag
    }
    fn alias(&self) -> &str {
        self.alias.as_str()
    }
    fn vr(&self) -> VR {
        self.vr
    }
}

/// A data type for a dictionary entry with a string slice for its alias.
#[derive(Debug, PartialEq, Eq, Clone)]
pub struct DictionaryEntryRef<'a> {
    /// The attribute tag
    pub tag: Tag,
    /// The alias of the attribute, with no spaces, usually InCapitalizedCamelCase
    pub alias: &'a str,
    /// The _typical_  value representation of the attribute
    pub vr: VR,
}

impl<'a> DictionaryEntry for DictionaryEntryRef<'a> {
    fn tag(&self) -> Tag {
        self.tag
    }
    fn alias(&self) -> &str {
        self.alias
    }
    fn vr(&self) -> VR {
        self.vr
    }
}

/// Utility data structure that resolves to a DICOM attribute tag
/// at a later time.
#[derive(Debug)]
pub struct TagByName<N: AsRef<str>, D: DataDictionary> {
    dict: D,
    name: N,
}

impl<N: AsRef<str>, D: DataDictionary> TagByName<N, D> {
    /// Create a tag resolver by name using the given dictionary.
    pub fn new(dictionary: D, name: N) -> TagByName<N, D> {
        TagByName {
            dict: dictionary,
            name: name,
        }
    }
}

impl<N: AsRef<str>, D: DataDictionary> From<TagByName<N, D>> for Option<Tag> {
    fn from(tag: TagByName<N, D>) -> Option<Tag> {
        tag.dict.by_name(tag.name.as_ref()).map(|e| e.tag())
    }
}

#[cfg(test)]
mod tests {
    use crate::header::Tag;
    use super::TagRange;

    #[test]
    fn test_parse_tag_range() {
        let tag: TagRange = "(1234,5678)".parse().unwrap();
        assert_eq!(tag, TagRange::Single(Tag(0x1234, 0x5678)));

        let tag: TagRange = "1234,5678".parse().unwrap();
        assert_eq!(tag, TagRange::Single(Tag(0x1234, 0x5678)));

        let tag: TagRange = "12xx,5678".parse().unwrap();
        assert_eq!(tag, TagRange::Group100(Tag(0x1200, 0x5678)));

        let tag: TagRange = "1234,56xx".parse().unwrap();
        assert_eq!(tag, TagRange::Element100(Tag(0x1234, 0x5600)));
    }
}<|endoftext|>


<commit_before>#[derive(Debug, PartialEq)]
pub struct NumericLiteral(pub f64);

#[derive(Debug, PartialEq)]
pub struct StringLiteral<'a>(pub &'a str);

pub mod parsing {

    use nom::{IResult, digit, hex_digit, oct_digit};
    use parser::helpers::parsing::*;
    use parser::js::terminals::*;

    named!(pub numeric_literal<&str, NumericLiteral>, conv!(NumericLiteral(do_parse!(
        take_while_s!(is_whitespace) >>
        numeric_literal: alt!(
            decimal_literal
            |
            hex_integer_literal
            |
            octal_integer_literal
        ) >>
        (numeric_literal)
    ))));

    named!(decimal_literal<&str, f64>, do_parse!(
        dec_lit: recognize!(alt!(
            do_parse!(
                decimal_integer_literal >>
                do_parse!(
                    opt!(complete!(do_parse!(
                        tag_s!(".") >>
                        opt!(complete!(digit)) >>
                        ()
                    ))) >>
                    opt!(complete!(exponential_part)) >>
                    ()
                ) >>
                ()
            )
            |
            do_parse!(
                tag_s!(".") >>
                complete!(digit) >>
                opt!(complete!(exponential_part)) >>
                ()
            )
        )) >>
        (dec_lit.parse::<f64>().unwrap())
    ));

    named!(decimal_integer_literal<&str, &str>, recognize!(alt!(
        do_parse!(
            tag_s!("0") >>
            not!(digit) >>
            not!(tag_s!("x")) >>
            not!(tag_s!("X")) >>
            ()
        )
        |
        do_parse!(
            not!(tag_s!("0")) >>
            digit >>
            ()
        )
    )));

    named!(exponential_part<&str, &str>, recognize!(do_parse!(
        alt!(tag_s!("e") | tag_s!("E")) >>
        opt!(alt!(tag_s!("+") | tag_s!("-"))) >>
        digit >>
        ()
    )));

    named!(hex_integer_literal<&str, f64>, do_parse!(
        alt!(tag_s!("0x") | tag_s!("0X")) >>
        hex: hex_digit >>
        (i64::from_str_radix(hex, 16).unwrap() as f64)
    ));

    named!(octal_integer_literal<&str, f64>, do_parse!(
        tag_s!("0") >>
        octal: oct_digit >>
        (i64::from_str_radix(octal, 8).unwrap() as f64)
    ));

    named!(pub string_literal<&str, StringLiteral>, do_parse!(
        delimiter: alt!(
            keyword!("\"")
            |
            keyword!("'")
        ) >>
        string: take_until_s!(delimiter) >> // TODO: escape chars
        keyword!(delimiter) >>
        (StringLiteral(string))
    ));

    named!(pub identifier<&str, &str>, do_parse!(
        take_while_s!(is_whitespace) >>
        identifier: recognize!(do_parse!(
            xid_start >>
            many0!(xid_continue) >>
            ()
        )) >>
        (identifier)
    ));

    named!(pub js_identifier<&str, &str>, alt!(
        keyword!("property")
        |
        keyword!("signal")
        |
        keyword!("readonly")
        |
        keyword!("on")
        |
        keyword!("get")
        |
        keyword!("set")
        |
        identifier
    ));

    named!(pub reserved_identifier<&str, &str>, alt!(
        keyword!("break")
        |
        keyword!("case")
        |
        keyword!("catch")
        |
        keyword!("continue")
        |
        keyword!("default")
        |
        keyword!("delete")
        |
        keyword!("do")
        |
        keyword!("else")
        |
        keyword!("false")
        |
        keyword!("finally")
        |
        keyword!("for")
        |
        keyword!("function")
        |
        keyword!("if")
        |
        keyword!("in")
        |
        keyword!("instanceof")
        |
        keyword!("new")
        |
        keyword!("null")
        |
        keyword!("return")
        |
        keyword!("switch")
        |
        keyword!("this")
        |
        keyword!("throw")
        |
        keyword!("true")
        |
        keyword!("try")
        |
        keyword!("typeof")
        |
        keyword!("var")
        |
        keyword!("void")
        |
        keyword!("while")
        |
        keyword!("const")
        |
        keyword!("debugger")
        |
        keyword!("with")
    ));

    named!(pub property_identifier<&str, &str>, alt!(
        reserved_identifier
        |
        js_identifier
    ));

    named!(pub assignment_operator<&str, &str>, alt!(
        keyword!("=")
        |
        keyword!("*=")
        |
        keyword!("/=")
        |
        keyword!("%=")
        |
        keyword!("+=")
        |
        keyword!("-=")
        |
        keyword!("<<=")
        |
        keyword!(">>>=")
        |
        keyword!(">>=")
        |
        keyword!("&=")
        |
        keyword!("^=")
        |
        keyword!("|=")
    ));

    named!(pub automatic_semicolon<&str, &str>, alt!(
        keyword!(";")
        |
        peek!(line_terminator)
        |
        peek!(keyword!("}"))
        |
        eof
    ));

    fn eof(i: &str) -> IResult<&str, &str> {
        eof!(i,)
    }

    named!(pub line_terminator<&str, &str>, alt!(
        tag_s!("\r\n")
        |
        tag_s!("\n")
        |
        tag_s!("\u{2028}")
        |
        tag_s!("\u{2029}")
    ));

    #[cfg(test)]
    mod tests {
        use nom::{ErrorKind, Needed};
        use super::*;

        #[test]
        fn numeric_literal() {
            assert_eq!(super::numeric_literal(""), IResult::Incomplete(Needed::Size(1)));

            // Decimal
            assert_eq!(super::numeric_literal("42"), IResult::Done("", NumericLiteral(42_f64)));
            assert_eq!(super::numeric_literal(" 42"), IResult::Done("", NumericLiteral(42_f64)));
            assert_eq!(super::numeric_literal("0"), IResult::Done("", NumericLiteral(0_f64)));
            assert_eq!(super::numeric_literal("42.42e-4"), IResult::Done("", NumericLiteral(42.42e-4_f64)));
            assert_eq!(super::numeric_literal(".42"), IResult::Done("", NumericLiteral(0.42_f64)));
            assert_eq!(super::numeric_literal("42."), IResult::Done("", NumericLiteral(42_f64)));

            assert_eq!(super::numeric_literal("+42"), IResult::Error(ErrorKind::Alt)); // Identity is unary expression
            assert_eq!(super::numeric_literal("-42"), IResult::Error(ErrorKind::Alt)); // Negation is unary expression
            assert_eq!(super::numeric_literal("."), IResult::Error(ErrorKind::Alt));

            // Octal
            assert_eq!(super::numeric_literal("042"), IResult::Done("", NumericLiteral(34_f64)));

            // Hex
            assert_eq!(super::numeric_literal("0x42"), IResult::Done("", NumericLiteral(66_f64)));
            assert_eq!(super::numeric_literal("0X42"), IResult::Done("", NumericLiteral(66_f64)));
        }

        #[test]
        fn string_literal() {
            assert_eq!(super::string_literal("\"hi\""), IResult::Done("", StringLiteral("hi")));
            assert_eq!(super::string_literal(" 'hi'"), IResult::Done("", StringLiteral("hi")));

            assert_eq!(super::string_literal(""), IResult::Incomplete(Needed::Size(1)));

            assert_eq!(super::string_literal("\"hi"), IResult::Error(ErrorKind::TakeUntil)); // FIXME: https://github.com/Geal/nom/issues/397
            assert_eq!(super::string_literal("'hi"), IResult::Error(ErrorKind::TakeUntil));
        }

        #[test]
        fn identifier() {
            assert_eq!(super::identifier("foo"), IResult::Done("", "foo"));
            assert_eq!(super::identifier(" foo"), IResult::Done("", "foo"));
            assert_eq!(super::identifier("foo bar"), IResult::Done(" bar", "foo"));

            assert_eq!(super::identifier(""), IResult::Incomplete(Needed::Size(1)));

            assert_eq!(super::identifier("42foo"), IResult::Error(ErrorKind::Verify));
        }
    }
}<commit_msg>Add some checks for literal tests<commit_after>#[derive(Debug, PartialEq)]
pub struct NumericLiteral(pub f64);

#[derive(Debug, PartialEq)]
pub struct StringLiteral<'a>(pub &'a str);

pub mod parsing {

    use nom::{IResult, digit, hex_digit, oct_digit};
    use parser::helpers::parsing::*;
    use parser::js::terminals::*;

    named!(pub numeric_literal<&str, NumericLiteral>, conv!(NumericLiteral(do_parse!(
        take_while_s!(is_whitespace) >>
        numeric_literal: alt!(
            decimal_literal
            |
            hex_integer_literal
            |
            octal_integer_literal
        ) >>
        (numeric_literal)
    ))));

    named!(decimal_literal<&str, f64>, do_parse!(
        dec_lit: recognize!(alt!(
            do_parse!(
                decimal_integer_literal >>
                do_parse!(
                    opt!(complete!(do_parse!(
                        tag_s!(".") >>
                        opt!(complete!(digit)) >>
                        ()
                    ))) >>
                    opt!(complete!(exponential_part)) >>
                    ()
                ) >>
                ()
            )
            |
            do_parse!(
                tag_s!(".") >>
                complete!(digit) >>
                opt!(complete!(exponential_part)) >>
                ()
            )
        )) >>
        (dec_lit.parse::<f64>().unwrap())
    ));

    named!(decimal_integer_literal<&str, &str>, recognize!(alt!(
        do_parse!(
            tag_s!("0") >>
            not!(digit) >>
            not!(tag_s!("x")) >>
            not!(tag_s!("X")) >>
            ()
        )
        |
        do_parse!(
            not!(tag_s!("0")) >>
            digit >>
            ()
        )
    )));

    named!(exponential_part<&str, &str>, recognize!(do_parse!(
        alt!(tag_s!("e") | tag_s!("E")) >>
        opt!(alt!(tag_s!("+") | tag_s!("-"))) >>
        digit >>
        ()
    )));

    named!(hex_integer_literal<&str, f64>, do_parse!(
        alt!(tag_s!("0x") | tag_s!("0X")) >>
        hex: hex_digit >>
        (i64::from_str_radix(hex, 16).unwrap() as f64)
    ));

    named!(octal_integer_literal<&str, f64>, do_parse!(
        tag_s!("0") >>
        octal: oct_digit >>
        (i64::from_str_radix(octal, 8).unwrap() as f64)
    ));

    named!(pub string_literal<&str, StringLiteral>, do_parse!(
        delimiter: alt!(
            keyword!("\"")
            |
            keyword!("'")
        ) >>
        string: take_until_s!(delimiter) >> // TODO: escape chars
        keyword!(delimiter) >>
        (StringLiteral(string))
    ));

    named!(pub identifier<&str, &str>, do_parse!(
        take_while_s!(is_whitespace) >>
        identifier: recognize!(do_parse!(
            xid_start >>
            many0!(xid_continue) >>
            ()
        )) >>
        (identifier)
    ));

    named!(pub js_identifier<&str, &str>, alt!(
        keyword!("property")
        |
        keyword!("signal")
        |
        keyword!("readonly")
        |
        keyword!("on")
        |
        keyword!("get")
        |
        keyword!("set")
        |
        identifier
    ));

    named!(pub reserved_identifier<&str, &str>, alt!(
        keyword!("break")
        |
        keyword!("case")
        |
        keyword!("catch")
        |
        keyword!("continue")
        |
        keyword!("default")
        |
        keyword!("delete")
        |
        keyword!("do")
        |
        keyword!("else")
        |
        keyword!("false")
        |
        keyword!("finally")
        |
        keyword!("for")
        |
        keyword!("function")
        |
        keyword!("if")
        |
        keyword!("in")
        |
        keyword!("instanceof")
        |
        keyword!("new")
        |
        keyword!("null")
        |
        keyword!("return")
        |
        keyword!("switch")
        |
        keyword!("this")
        |
        keyword!("throw")
        |
        keyword!("true")
        |
        keyword!("try")
        |
        keyword!("typeof")
        |
        keyword!("var")
        |
        keyword!("void")
        |
        keyword!("while")
        |
        keyword!("const")
        |
        keyword!("debugger")
        |
        keyword!("with")
    ));

    named!(pub property_identifier<&str, &str>, alt!(
        reserved_identifier
        |
        js_identifier
    ));

    named!(pub assignment_operator<&str, &str>, alt!(
        keyword!("=")
        |
        keyword!("*=")
        |
        keyword!("/=")
        |
        keyword!("%=")
        |
        keyword!("+=")
        |
        keyword!("-=")
        |
        keyword!("<<=")
        |
        keyword!(">>>=")
        |
        keyword!(">>=")
        |
        keyword!("&=")
        |
        keyword!("^=")
        |
        keyword!("|=")
    ));

    named!(pub automatic_semicolon<&str, &str>, alt!(
        keyword!(";")
        |
        peek!(line_terminator)
        |
        peek!(keyword!("}"))
        |
        eof
    ));

    fn eof(i: &str) -> IResult<&str, &str> {
        eof!(i,)
    }

    named!(pub line_terminator<&str, &str>, alt!(
        tag_s!("\r\n")
        |
        tag_s!("\n")
        |
        tag_s!("\u{2028}")
        |
        tag_s!("\u{2029}")
    ));

    #[cfg(test)]
    mod tests {
        use nom::{ErrorKind, Needed};
        use super::*;

        #[test]
        fn numeric_literal() {
            assert_eq!(super::numeric_literal(""), IResult::Incomplete(Needed::Size(1)));

            // Decimal
            assert_eq!(super::numeric_literal("42"), IResult::Done("", NumericLiteral(42_f64)));
            assert_eq!(super::numeric_literal(" 42 "), IResult::Done(" ", NumericLiteral(42_f64)));
            assert_eq!(super::numeric_literal("0"), IResult::Done("", NumericLiteral(0_f64)));
            assert_eq!(super::numeric_literal("42.42e-4"), IResult::Done("", NumericLiteral(42.42e-4_f64)));
            assert_eq!(super::numeric_literal(".42"), IResult::Done("", NumericLiteral(0.42_f64)));
            assert_eq!(super::numeric_literal("42."), IResult::Done("", NumericLiteral(42_f64)));

            assert_eq!(super::numeric_literal("+42"), IResult::Error(ErrorKind::Alt)); // Identity is unary expression
            assert_eq!(super::numeric_literal("-42"), IResult::Error(ErrorKind::Alt)); // Negation is unary expression
            assert_eq!(super::numeric_literal("."), IResult::Error(ErrorKind::Alt));

            // Octal
            assert_eq!(super::numeric_literal("042"), IResult::Done("", NumericLiteral(34_f64)));

            // Hex
            assert_eq!(super::numeric_literal("0x42"), IResult::Done("", NumericLiteral(66_f64)));
            assert_eq!(super::numeric_literal("0X42"), IResult::Done("", NumericLiteral(66_f64)));
        }

        #[test]
        fn string_literal() {
            assert_eq!(super::string_literal("\"hi\""), IResult::Done("", StringLiteral("hi")));
            assert_eq!(super::string_literal(" 'hi' "), IResult::Done(" ", StringLiteral("hi")));

            assert_eq!(super::string_literal(""), IResult::Incomplete(Needed::Size(1)));

            assert_eq!(super::string_literal("\"hi"), IResult::Error(ErrorKind::TakeUntil)); // FIXME: https://github.com/Geal/nom/issues/397
            assert_eq!(super::string_literal("'hi"), IResult::Error(ErrorKind::TakeUntil));
        }

        #[test]
        fn identifier() {
            assert_eq!(super::identifier("foo"), IResult::Done("", "foo"));
            assert_eq!(super::identifier(" foo"), IResult::Done("", "foo"));
            assert_eq!(super::identifier("foo bar"), IResult::Done(" bar", "foo"));

            assert_eq!(super::identifier(""), IResult::Incomplete(Needed::Size(1)));

            assert_eq!(super::identifier("42foo"), IResult::Error(ErrorKind::Verify));
        }
    }
}<|endoftext|>


<commit_before><commit_msg>Add consts, const-ify magic numbers<commit_after><|endoftext|>


<commit_before>use std::sync::Arc;
use std::io::{Read, Write};
use std::collections::HashMap;
use bincode::{self, serde};
use euclid::Point2D;
use calx_resource::ResourceStore;
use calx_ecs::Entity;
use calx_grid::Dir6;
use field::Field;
use spatial::{Place, Spatial};
use flags::Flags;
use location::{Location, Portal};
use components;
use stats;
use terrain;
use query::Query;
use command::{Command, CommandResult};
use mutate::Mutate;
use terraform::{Terraform, TerrainQuery};

pub const GAME_VERSION: &'static str = "0.1.0";

Ecs! {
    desc: components::Desc,
    map_memory: components::MapMemory,
    health: components::Health,
    brain: components::Brain,
    item: components::Item,
    composite_stats: components::CompositeStats,
    stats: stats::Stats,
}

/// Toplevel game state object.
#[derive(RustcEncodable, RustcDecodable)]
pub struct World {
    /// Game version. Not mutable in the slightest, but the simplest way to
    /// get versioned save files is to just drop it here.
    version: String,
    /// Entity component system.
    ecs: Ecs,
    /// Terrain data.
    terrain: Field<u8>,
    /// Optional portals between map zones.
    portals: HashMap<Location, Portal>,
    /// Spatial index for game entities.
    spatial: Spatial,
    /// Global gamestate flags.
    flags: Flags,
}

impl<'a> World {
    pub fn new(seed: u32) -> World {
        let mut ret = World {
            version: GAME_VERSION.to_string(),
            ecs: Ecs::new(),
            terrain: Field::new(0),
            portals: HashMap::new(),
            spatial: Spatial::new(),
            flags: Flags::new(seed),
        };

        ret.init_level(1);

        ret
    }

    /* TODO: Reactivate for rustc-serialize

    pub fn load<R: Read>(reader: &mut R) -> serde::DeserializeResult<World> {
        let ret: serde::DeserializeResult<World> =
            serde::deserialize_from(reader, bincode::SizeLimit::Infinite);
        if let &Ok(ref x) = &ret {
            if &x.version != GAME_VERSION {
                panic!("Save game version {} does not match current version \
                        {}",
                       x.version,
                       GAME_VERSION);
            }
        }
        ret
    }

    pub fn save<W: Write>(&self, writer: &mut W) -> serde::SerializeResult<()> {
        serde::serialize_into(writer, self, bincode::SizeLimit::Infinite)
    }
    */

    fn default_terrain_id(&self, loc: Location) -> u8 {
        terrain::Id::Rock as u8
    }
}

impl TerrainQuery for World {
    fn is_valid_location(&self, loc: Location) -> bool {
        ::on_screen(Point2D::new(loc.x as i32, loc.y as i32))
    }

    fn terrain(&self, loc: Location) -> Arc<terrain::Tile> {
        let mut idx = self.terrain.get(loc);

        if idx == 0 {
            idx = self.default_terrain_id(loc);
        }

        terrain::Tile::get_resource(&idx).unwrap()

        // TODO: Add open/closed door mapping to terrain data, closed door terrain should have a field
        // that contains the terrain index of the corresponding open door tile.

        // TODO: Support terrain with brush variant distributions, like the grass case below that
        // occasionlly emits a fancier brush. The distribution needs to be embedded in the Tile struct.
        // The sampling needs loc noise, but is probably better done at the point where terrain is
        // being drawn than here, since we'll want to still have just one immutable terrain id
        // corresponding to all the variants.
        // Mobs standing on doors make the doors open.

        // if ret == TerrainType::Door && self.has_mobs(loc) {
        //     ret = TerrainType::OpenDoor;
        // }
        // // Grass is only occasionally fancy.
        // if ret == TerrainType::Grass {
        //     if loc.noise() > 0.85 {
        //         ret = TerrainType::Grass2;
        //     }
        // }
    }

    fn portal(&self, loc: Location) -> Option<Location> { self.portals.get(&loc).map(|&p| loc + p) }

    fn is_untouched(&self, loc: Location) -> bool {
        !self.terrain.overrides(loc)
    }
}

impl Query for World {
    fn location(&self, e: Entity) -> Option<Location> {
        match self.spatial.get(e) {
            Some(Place::At(loc)) => Some(loc),
            Some(Place::In(container, _)) => self.location(container),
            _ => None,
        }
    }

    fn player(&self) -> Option<Entity> {
        if let Some(p) = self.flags.player {
            if self.is_alive(p) {
                return Some(p);
            }
        }

        None
    }

    fn tick(&self) -> u64 { self.flags.tick }

    fn rng_seed(&self) -> u32 { self.flags.seed }

    fn entities_at(&self, loc: Location) -> Vec<Entity> { self.spatial.entities_at(loc) }

    fn ecs<'a>(&'a self) -> &'a Ecs { &self.ecs }
}

impl Mutate for World {
    fn next_tick(&mut self) -> CommandResult {
        // TODO: Run AI
        // TODO: Clean dead
        self.flags.tick += 1;
        Ok(())
    }

    fn set_entity_location(&mut self, e: Entity, loc: Location) { self.spatial.insert_at(e, loc); }

    fn set_player(&mut self, player: Entity) { self.flags.player = Some(player); }

    fn spawn(&mut self, loadout: &Loadout) -> Entity { loadout.make(&mut self.ecs) }
}

impl Command for World {
    fn step(&mut self, dir: Dir6) -> CommandResult {
        let player = try!(self.player().ok_or(()));
        try!(self.entity_step(player, dir));
        self.next_tick()
    }

    fn melee(&mut self, dir: Dir6) -> CommandResult {
        let player = try!(self.player().ok_or(()));
        try!(self.entity_melee(player, dir));
        self.next_tick()
    }

    fn pass(&mut self) -> CommandResult { self.next_tick() }
}

impl Terraform for World {
    fn set_terrain(&mut self, loc: Location, terrain: u8) {
        self.terrain.set(loc, terrain);
    }

    fn set_portal(&mut self, loc: Location, mut portal: Portal) {
        let target_loc = loc + portal;
        // Don't create portal chains, if the target cell has another portal, just direct to its
        // destination.
        if let Some(&p) = self.portals.get(&target_loc) {
            portal = portal + p;
        }

        if portal.dx == 0 && portal.dy == 0 && portal.z == loc.z {
            self.portals.remove(&loc);
        } else {
            self.portals.insert(loc, portal);
        }
    }

    fn remove_portal(&mut self, loc: Location) { self.portals.remove(&loc); }
}
<commit_msg>Walking through door opens it<commit_after>use std::sync::Arc;
use std::io::{Read, Write};
use std::collections::HashMap;
use bincode::{self, serde};
use euclid::Point2D;
use calx_resource::ResourceStore;
use calx_ecs::Entity;
use calx_grid::Dir6;
use field::Field;
use spatial::{Place, Spatial};
use flags::Flags;
use location::{Location, Portal};
use components;
use stats;
use terrain;
use query::Query;
use command::{Command, CommandResult};
use mutate::Mutate;
use terraform::{Terraform, TerrainQuery};

pub const GAME_VERSION: &'static str = "0.1.0";

Ecs! {
    desc: components::Desc,
    map_memory: components::MapMemory,
    health: components::Health,
    brain: components::Brain,
    item: components::Item,
    composite_stats: components::CompositeStats,
    stats: stats::Stats,
}

/// Toplevel game state object.
#[derive(RustcEncodable, RustcDecodable)]
pub struct World {
    /// Game version. Not mutable in the slightest, but the simplest way to
    /// get versioned save files is to just drop it here.
    version: String,
    /// Entity component system.
    ecs: Ecs,
    /// Terrain data.
    terrain: Field<u8>,
    /// Optional portals between map zones.
    portals: HashMap<Location, Portal>,
    /// Spatial index for game entities.
    spatial: Spatial,
    /// Global gamestate flags.
    flags: Flags,
}

impl<'a> World {
    pub fn new(seed: u32) -> World {
        let mut ret = World {
            version: GAME_VERSION.to_string(),
            ecs: Ecs::new(),
            terrain: Field::new(0),
            portals: HashMap::new(),
            spatial: Spatial::new(),
            flags: Flags::new(seed),
        };

        ret.init_level(1);

        ret
    }

    /* TODO: Reactivate for rustc-serialize

    pub fn load<R: Read>(reader: &mut R) -> serde::DeserializeResult<World> {
        let ret: serde::DeserializeResult<World> =
            serde::deserialize_from(reader, bincode::SizeLimit::Infinite);
        if let &Ok(ref x) = &ret {
            if &x.version != GAME_VERSION {
                panic!("Save game version {} does not match current version \
                        {}",
                       x.version,
                       GAME_VERSION);
            }
        }
        ret
    }

    pub fn save<W: Write>(&self, writer: &mut W) -> serde::SerializeResult<()> {
        serde::serialize_into(writer, self, bincode::SizeLimit::Infinite)
    }
    */

    fn default_terrain_id(&self, loc: Location) -> u8 {
        terrain::Id::Rock as u8
    }
}

impl TerrainQuery for World {
    fn is_valid_location(&self, loc: Location) -> bool {
        ::on_screen(Point2D::new(loc.x as i32, loc.y as i32))
    }

    fn terrain(&self, loc: Location) -> Arc<terrain::Tile> {
        let mut idx = self.terrain.get(loc);

        if idx == 0 {
            idx = self.default_terrain_id(loc);
        }

        if idx == terrain::Id::Door as u8 {
            // Standing in the doorway opens the door.
            if self.has_mobs(loc) {
                idx = terrain::Id::OpenDoor as u8;
            }
        }

        terrain::Tile::get_resource(&idx).unwrap()

        // TODO: Add open/closed door mapping to terrain data, closed door terrain should have a field
        // that contains the terrain index of the corresponding open door tile.

        // TODO: Support terrain with brush variant distributions, like the grass case below that
        // occasionlly emits a fancier brush. The distribution needs to be embedded in the Tile struct.
        // The sampling needs loc noise, but is probably better done at the point where terrain is
        // being drawn than here, since we'll want to still have just one immutable terrain id
        // corresponding to all the variants.
        // Mobs standing on doors make the doors open.

        // if ret == TerrainType::Door && self.has_mobs(loc) {
        //     ret = TerrainType::OpenDoor;
        // }
        // // Grass is only occasionally fancy.
        // if ret == TerrainType::Grass {
        //     if loc.noise() > 0.85 {
        //         ret = TerrainType::Grass2;
        //     }
        // }
    }

    fn portal(&self, loc: Location) -> Option<Location> { self.portals.get(&loc).map(|&p| loc + p) }

    fn is_untouched(&self, loc: Location) -> bool {
        !self.terrain.overrides(loc)
    }
}

impl Query for World {
    fn location(&self, e: Entity) -> Option<Location> {
        match self.spatial.get(e) {
            Some(Place::At(loc)) => Some(loc),
            Some(Place::In(container, _)) => self.location(container),
            _ => None,
        }
    }

    fn player(&self) -> Option<Entity> {
        if let Some(p) = self.flags.player {
            if self.is_alive(p) {
                return Some(p);
            }
        }

        None
    }

    fn tick(&self) -> u64 { self.flags.tick }

    fn rng_seed(&self) -> u32 { self.flags.seed }

    fn entities_at(&self, loc: Location) -> Vec<Entity> { self.spatial.entities_at(loc) }

    fn ecs<'a>(&'a self) -> &'a Ecs { &self.ecs }
}

impl Mutate for World {
    fn next_tick(&mut self) -> CommandResult {
        // TODO: Run AI
        // TODO: Clean dead
        self.flags.tick += 1;
        Ok(())
    }

    fn set_entity_location(&mut self, e: Entity, loc: Location) { self.spatial.insert_at(e, loc); }

    fn set_player(&mut self, player: Entity) { self.flags.player = Some(player); }

    fn spawn(&mut self, loadout: &Loadout) -> Entity { loadout.make(&mut self.ecs) }
}

impl Command for World {
    fn step(&mut self, dir: Dir6) -> CommandResult {
        let player = try!(self.player().ok_or(()));
        try!(self.entity_step(player, dir));
        self.next_tick()
    }

    fn melee(&mut self, dir: Dir6) -> CommandResult {
        let player = try!(self.player().ok_or(()));
        try!(self.entity_melee(player, dir));
        self.next_tick()
    }

    fn pass(&mut self) -> CommandResult { self.next_tick() }
}

impl Terraform for World {
    fn set_terrain(&mut self, loc: Location, terrain: u8) {
        self.terrain.set(loc, terrain);
    }

    fn set_portal(&mut self, loc: Location, mut portal: Portal) {
        let target_loc = loc + portal;
        // Don't create portal chains, if the target cell has another portal, just direct to its
        // destination.
        if let Some(&p) = self.portals.get(&target_loc) {
            portal = portal + p;
        }

        if portal.dx == 0 && portal.dy == 0 && portal.z == loc.z {
            self.portals.remove(&loc);
        } else {
            self.portals.insert(loc, portal);
        }
    }

    fn remove_portal(&mut self, loc: Location) { self.portals.remove(&loc); }
}
<|endoftext|>


<commit_before>/*
    Example code is copied verbatim from:
    https://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/
*/

extern crate cgmath;
extern crate rand;
extern crate three;

use std::f32::consts::PI;
use cgmath::prelude::*;

struct Cloud {
    group: three::Group,
    meshes: Vec<three::Mesh>,
}

impl Cloud {
    fn new<R: rand::Rng>(rng: &mut R,
        factory: &mut three::Factory,
        scene: &mut three::Scene,
        parent: &three::Group,
    ) -> Self {
        let mut cloud = Cloud {
            group: factory.group(),
            meshes: Vec::new()
        };
        cloud.group.attach(scene, Some(parent));
        let geo = three::Geometry::new_box(20.0, 20.0, 20.0);
        let material = three::Material::MeshBasic{ color: 0xFFFFFF };
        for i in 0 .. rng.gen_range(3, 6) {
            let mut m = factory.mesh(geo.clone(), material.clone());
            let rot: three::Orientation = rng.gen();
            *m.transform_mut() = three::Transform {
                scale: rng.gen_range(0.1, 1.0),
                rot: rot.normalize(),
                disp: cgmath::vec3(i as f32 * 15.0, rng.next_f32() * 10.0, rng.next_f32() * 10.0),
            };
            m.attach(scene, Some(&cloud.group));
            cloud.meshes.push(m);
        }
        cloud
    }
}

struct Sky {
    group: three::Group,
    clouds: Vec<Cloud>,
}

impl Sky {
    fn new<R: rand::Rng>(rng: &mut R,
        factory: &mut three::Factory,
        scene: &mut three::Scene,
    ) -> Self {
        let mut sky = Sky {
            group: factory.group(),
            clouds: Vec::new(),
        };
        sky.group.attach(scene, None);
        let num = 20i32;
        let step_angle = PI * 2.0 / num as f32;
        for i in 0 .. num {
            let mut c = Cloud::new(rng, factory, scene, &sky.group);
            let angle = cgmath::Rad(i as f32 * step_angle);
            let dist = rng.gen_range(750.0, 950.0);
            *c.group.transform_mut() = three::Transform {
                scale: rng.gen_range(1.0, 3.0),
                rot: three::Orientation::from_angle_z(angle + cgmath::Rad::turn_div_4()),
                disp: cgmath::vec3(angle.cos() * dist,
                                   angle.sin() * dist,
                                   rng.gen_range(-800.0, -400.0)),
            };
            sky.clouds.push(c);
        }
        sky
    }
}

struct AirPlane {
    group: three::Group,
    _cockpit: three::Mesh,
    _engine: three::Mesh,
    _tail: three::Mesh,
    _wing: three::Mesh,
    propeller_group: three::Group,
    _propeller: three::Mesh,
    _blade: three::Mesh,
}

impl AirPlane {
    fn new(
        factory: &mut three::Factory,
        scene: &mut three::Scene,
    ) -> Self {
        let mut group = factory.group();
        group.attach(scene, None);

        let mut cockpit = factory.mesh(
            three::Geometry::new_box(60.0, 50.0, 50.0),
            three::Material::MeshBasic{ color: 0xFF0000 }
        );
        let mut engine = factory.mesh(
            three::Geometry::new_box(20.0, 50.0, 50.0),
            three::Material::MeshBasic{ color: 0xFFFFFF }
        );
        engine.transform_mut().disp.x = 40.0;
        let mut tail = factory.mesh(
            three::Geometry::new_box(15.0, 20.0, 5.0),
            three::Material::MeshBasic{ color: 0xFF0000 }
        );
        tail.transform_mut().disp = cgmath::vec3(-35.0, 25.0, 0.0);
        let mut wing = factory.mesh(
            three::Geometry::new_box(40.0, 8.0, 150.0),
            three::Material::MeshBasic{ color: 0xFF0000 }
        );

        let mut propeller_group = factory.group();
        propeller_group.transform_mut().disp = cgmath::vec3(50.0, 0.0, 0.0);
        propeller_group.attach(scene, Some(&group));
        let mut propeller = factory.mesh(
            three::Geometry::new_box(20.0, 10.0, 10.0),
            three::Material::MeshBasic{ color: 0xa52a2a }
        );
        propeller.attach(scene, Some(&propeller_group));
        let mut blade = factory.mesh(
            three::Geometry::new_box(1.0, 100.0, 20.0),
            three::Material::MeshBasic{ color: 0x23190f }
        );
        blade.transform_mut().disp = cgmath::vec3(8.0, 0.0, 0.0);
        blade.attach(scene, Some(&propeller_group));

        for mesh in [&mut cockpit, &mut engine, &mut tail, &mut wing].iter_mut() {
            mesh.attach(scene, Some(&group));
        }

        AirPlane {
            group,
            _cockpit: cockpit,
            _engine: engine,
            _tail: tail,
            _wing: wing,
            propeller_group,
            _propeller: propeller,
            _blade: blade,
        }
    }

    fn update(&mut self, dt: f32, target: (f32, f32)) {
        let mut pt = self.propeller_group.transform_mut();
        pt.rot = pt.rot * three::Orientation::from_angle_x(cgmath::Rad(0.3 * dt));
        self.group.transform_mut().disp =
            cgmath::vec3(0.0 + target.0 * 100.0, 100.0 + target.1 * 75.0, 0.0);
    }
}

fn main() {
    let mut rng = rand::thread_rng();
    let mut cam = three::PerspectiveCamera::new(60.0, 0.0, 1.0, 1000.0);
    cam.position = three::Position::new(0.0, 100.0, 200.0);
    let mut win = three::Window::new("Three-rs box mesh drawing example", cam);

    //TODO: win.scene.fog = Some(three::Fog::new(...));
    //TODO: create lights
    //TODO: Phong materials
    //TODO: cast/receive shadows

    let mut sea = {
        let geo = three::Geometry::new_cylinder(600.0, 600.0, 800.0, 40);
        let material = three::Material::MeshBasic{ color: 0x0000FF };
        win.factory.mesh(geo, material)
    };
    *sea.transform_mut() = three::Transform {
        scale: 1.0,
        rot: three::Orientation::from_angle_x(-cgmath::Rad::turn_div_4()),
        disp: cgmath::vec3(0.0, -600.0, 0.0),
    };
    sea.attach(&mut win.scene, None);

    let mut sky = Sky::new(&mut rng, &mut win.factory, &mut win.scene);
    sky.group.transform_mut().disp.y = -600.0;

    let mut airplane = AirPlane::new(&mut win.factory, &mut win.scene);
    *airplane.group.transform_mut() = three::Transform {
        scale: 0.25,
        rot: three::Orientation::one(),
        disp: cgmath::vec3(0.0, 100.0, 0.0),
    };

    while let Some(events) = win.update() {
        // assume the original velocities are given for 60fps
        let dt = events.time_delta * 60.0;

        airplane.update(dt, events.mouse_pos);

        if let (mut t, 0) = (sea.transform_mut(), 0) {
            t.rot = t.rot * three::Orientation::from_angle_y(cgmath::Rad(0.005 * dt));
        }
        if let (mut t, 0) = (sky.group.transform_mut(), 0) {
            t.rot = t.rot * three::Orientation::from_angle_z(cgmath::Rad(0.01 * dt));
        }

        win.render();
    }
}
<commit_msg>Aviator cockpit deformation<commit_after>/*
    Example code is copied verbatim from:
    https://tympanus.net/codrops/2016/04/26/the-aviator-animating-basic-3d-scene-threejs/
*/

extern crate cgmath;
extern crate rand;
extern crate three;

use std::f32::consts::PI;
use cgmath::prelude::*;

struct Cloud {
    group: three::Group,
    meshes: Vec<three::Mesh>,
}

impl Cloud {
    fn new<R: rand::Rng>(rng: &mut R,
        factory: &mut three::Factory,
        scene: &mut three::Scene,
        parent: &three::Group,
    ) -> Self {
        let mut cloud = Cloud {
            group: factory.group(),
            meshes: Vec::new()
        };
        cloud.group.attach(scene, Some(parent));
        let geo = three::Geometry::new_box(20.0, 20.0, 20.0);
        let material = three::Material::MeshBasic{ color: 0xFFFFFF };
        for i in 0 .. rng.gen_range(3, 6) {
            let mut m = factory.mesh(geo.clone(), material.clone());
            let rot: three::Orientation = rng.gen();
            *m.transform_mut() = three::Transform {
                scale: rng.gen_range(0.1, 1.0),
                rot: rot.normalize(),
                disp: cgmath::vec3(i as f32 * 15.0, rng.next_f32() * 10.0, rng.next_f32() * 10.0),
            };
            m.attach(scene, Some(&cloud.group));
            cloud.meshes.push(m);
        }
        cloud
    }
}

struct Sky {
    group: three::Group,
    clouds: Vec<Cloud>,
}

impl Sky {
    fn new<R: rand::Rng>(rng: &mut R,
        factory: &mut three::Factory,
        scene: &mut three::Scene,
    ) -> Self {
        let mut sky = Sky {
            group: factory.group(),
            clouds: Vec::new(),
        };
        sky.group.attach(scene, None);
        let num = 20i32;
        let step_angle = PI * 2.0 / num as f32;
        for i in 0 .. num {
            let mut c = Cloud::new(rng, factory, scene, &sky.group);
            let angle = cgmath::Rad(i as f32 * step_angle);
            let dist = rng.gen_range(750.0, 950.0);
            *c.group.transform_mut() = three::Transform {
                scale: rng.gen_range(1.0, 3.0),
                rot: three::Orientation::from_angle_z(angle + cgmath::Rad::turn_div_4()),
                disp: cgmath::vec3(angle.cos() * dist,
                                   angle.sin() * dist,
                                   rng.gen_range(-800.0, -400.0)),
            };
            sky.clouds.push(c);
        }
        sky
    }
}

struct AirPlane {
    group: three::Group,
    _cockpit: three::Mesh,
    _engine: three::Mesh,
    _tail: three::Mesh,
    _wing: three::Mesh,
    propeller_group: three::Group,
    _propeller: three::Mesh,
    _blade: three::Mesh,
}

impl AirPlane {
    fn new(
        factory: &mut three::Factory,
        scene: &mut three::Scene,
    ) -> Self {
        let mut group = factory.group();
        group.attach(scene, None);

        let mut cockpit = {
            let mut geo = three::Geometry::new_box(80.0, 50.0, 50.0);
            geo.vertices[3] += cgmath::vec3(0.0, -10.0, 20.0);
            geo.vertices[2] += cgmath::vec3(0.0, -10.0,  -20.0);
            geo.vertices[1] += cgmath::vec3(0.0, 30.0, 20.0);
            geo.vertices[0] += cgmath::vec3(0.0, 30.0, -20.0);
            factory.mesh(geo, three::Material::MeshBasic{ color: 0xFF0000 })
        };
        let mut engine = factory.mesh(
            three::Geometry::new_box(20.0, 50.0, 50.0),
            three::Material::MeshBasic{ color: 0xFFFFFF }
        );
        engine.transform_mut().disp.x = 40.0;
        let mut tail = factory.mesh(
            three::Geometry::new_box(15.0, 20.0, 5.0),
            three::Material::MeshBasic{ color: 0xFF0000 }
        );
        tail.transform_mut().disp = cgmath::vec3(-35.0, 25.0, 0.0);
        let mut wing = factory.mesh(
            three::Geometry::new_box(40.0, 8.0, 150.0),
            three::Material::MeshBasic{ color: 0xFF0000 }
        );

        let mut propeller_group = factory.group();
        propeller_group.transform_mut().disp = cgmath::vec3(50.0, 0.0, 0.0);
        propeller_group.attach(scene, Some(&group));
        let mut propeller = factory.mesh(
            three::Geometry::new_box(20.0, 10.0, 10.0),
            three::Material::MeshBasic{ color: 0xa52a2a }
        );
        propeller.attach(scene, Some(&propeller_group));
        let mut blade = factory.mesh(
            three::Geometry::new_box(1.0, 100.0, 20.0),
            three::Material::MeshBasic{ color: 0x23190f }
        );
        blade.transform_mut().disp = cgmath::vec3(8.0, 0.0, 0.0);
        blade.attach(scene, Some(&propeller_group));

        for mesh in [&mut cockpit, &mut engine, &mut tail, &mut wing].iter_mut() {
            mesh.attach(scene, Some(&group));
        }

        AirPlane {
            group,
            _cockpit: cockpit,
            _engine: engine,
            _tail: tail,
            _wing: wing,
            propeller_group,
            _propeller: propeller,
            _blade: blade,
        }
    }

    fn update(&mut self, dt: f32, target: (f32, f32)) {
        let mut pt = self.propeller_group.transform_mut();
        pt.rot = pt.rot * three::Orientation::from_angle_x(cgmath::Rad(0.3 * dt));
        self.group.transform_mut().disp =
            cgmath::vec3(0.0 + target.0 * 100.0, 100.0 + target.1 * 75.0, 0.0);
    }
}

fn main() {
    let mut rng = rand::thread_rng();
    let mut cam = three::PerspectiveCamera::new(60.0, 0.0, 1.0, 1000.0);
    cam.position = three::Position::new(0.0, 100.0, 200.0);
    let mut win = three::Window::new("Three-rs box mesh drawing example", cam);

    //TODO: win.scene.fog = Some(three::Fog::new(...));
    //TODO: create lights
    //TODO: Phong materials
    //TODO: cast/receive shadows

    let mut sea = {
        let geo = three::Geometry::new_cylinder(600.0, 600.0, 800.0, 40);
        let material = three::Material::MeshBasic{ color: 0x0000FF };
        win.factory.mesh(geo, material)
    };
    *sea.transform_mut() = three::Transform {
        scale: 1.0,
        rot: three::Orientation::from_angle_x(-cgmath::Rad::turn_div_4()),
        disp: cgmath::vec3(0.0, -600.0, 0.0),
    };
    sea.attach(&mut win.scene, None);

    let mut sky = Sky::new(&mut rng, &mut win.factory, &mut win.scene);
    sky.group.transform_mut().disp.y = -600.0;

    let mut airplane = AirPlane::new(&mut win.factory, &mut win.scene);
    *airplane.group.transform_mut() = three::Transform {
        scale: 0.25,
        rot: three::Orientation::one(),
        disp: cgmath::vec3(0.0, 100.0, 0.0),
    };

    while let Some(events) = win.update() {
        // assume the original velocities are given for 60fps
        let dt = events.time_delta * 60.0;

        airplane.update(dt, events.mouse_pos);

        if let (mut t, 0) = (sea.transform_mut(), 0) {
            t.rot = three::Orientation::from_angle_z(cgmath::Rad(0.005 * dt)) * t.rot;
        }
        if let (mut t, 0) = (sky.group.transform_mut(), 0) {
            t.rot = t.rot * three::Orientation::from_angle_z(cgmath::Rad(0.01 * dt));
        }

        win.render();
    }
}
<|endoftext|>


<commit_before>extern crate arrayfire as af;

use af::*;

#[allow(unused_must_use)]
fn test_backend(){
  info();

  let num_rows: u64 = 10;
  let num_cols: u64 = 10;
  let dims = Dim4::new(&[num_rows, num_cols, 1, 1]);

  println!("Create a 10-by-10 matrix of random floats on the compute device");
  let a = match randu(dims, Aftype::F32) {
    Ok(value) => value,
    Err(error) => panic!("{}", error),
  };
  print(&a);
}

#[allow(unused_must_use)]
fn main() {
  println!("There are {:?} available backends", get_backend_count().unwrap());
  let available = get_available_backends().unwrap();

  if available.contains(&AfBackend::AF_BACKEND_CPU){
    println!("Evaluating CPU Backend...");
    println!("There are {} CPU compute devices", device_count().unwrap());
    let err = set_backend(AfBackend::AF_BACKEND_CPU);
      match err {
        Ok(_)  => test_backend(),
        Err(e) => println!("CPU backend error: {}", e),
    };
  }

  if available.contains(&AfBackend::AF_BACKEND_CUDA){
    println!("Evaluating CUDA Backend...");
    println!("There are {} CUDA compute devices", device_count().unwrap());
    let err = set_backend(AfBackend::AF_BACKEND_CUDA);
      match err {
        Ok(_)  => test_backend(),
        Err(e) => println!("CUDA backend error: {}", e),
    };
  }

  if available.contains(&AfBackend::AF_BACKEND_OPENCL){
    println!("Evaluating OpenCL Backend...");
    println!("There are {} OpenCL compute devices", device_count().unwrap());
    let err = set_backend(AfBackend::AF_BACKEND_OPENCL);
      match err {
        Ok(_)  => test_backend(),
        Err(e) => println!("OpenCL backend error: {}", e),
    };
  }
}
<commit_msg>the get backend count should go after the set backend<commit_after>extern crate arrayfire as af;

use af::*;

#[allow(unused_must_use)]
fn test_backend(){
  info();

  let num_rows: u64 = 10;
  let num_cols: u64 = 10;
  let dims = Dim4::new(&[num_rows, num_cols, 1, 1]);

  println!("Create a 10-by-10 matrix of random floats on the compute device");
  let a = match randu(dims, Aftype::F32) {
    Ok(value) => value,
    Err(error) => panic!("{}", error),
  };
  print(&a);
}

#[allow(unused_must_use)]
fn main() {
  println!("There are {:?} available backends", get_backend_count().unwrap());
  let available = get_available_backends().unwrap();

  if available.contains(&AfBackend::AF_BACKEND_CPU){
    println!("Evaluating CPU Backend...");
    let err = set_backend(AfBackend::AF_BACKEND_CPU);
    println!("There are {} CPU compute devices", device_count().unwrap());
      match err {
        Ok(_)  => test_backend(),
        Err(e) => println!("CPU backend error: {}", e),
    };
  }

  if available.contains(&AfBackend::AF_BACKEND_CUDA){
    println!("Evaluating CUDA Backend...");
    let err = set_backend(AfBackend::AF_BACKEND_CUDA);
    println!("There are {} CUDA compute devices", device_count().unwrap());
      match err {
        Ok(_)  => test_backend(),
        Err(e) => println!("CUDA backend error: {}", e),
    };
  }

  if available.contains(&AfBackend::AF_BACKEND_OPENCL){
    println!("Evaluating OpenCL Backend...");
    let err = set_backend(AfBackend::AF_BACKEND_OPENCL);
    println!("There are {} OpenCL compute devices", device_count().unwrap());
      match err {
        Ok(_)  => test_backend(),
        Err(e) => println!("OpenCL backend error: {}", e),
    };
  }
}
<|endoftext|>


<commit_before>//! Various utilities for working with Cairo image surfaces.
use std::ops::DerefMut;

use cairo;

pub mod iterators;
pub mod shared_surface;

/// A pixel consisting of R, G, B and A values.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct Pixel {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}

/// Modes which specify how the values of out of bounds pixels are computed.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum EdgeMode {
    /// The nearest inbounds pixel value is returned.
    Duplicate,
    /// The image is extended by taking the color values from the opposite of the image.
    ///
    /// Imagine the image being tiled infinitely, with the original image at the origin.
    Wrap,
    /// Zero RGBA values are returned.
    None,
}

/// Extension methods for `cairo::ImageSurfaceData`.
pub trait ImageSurfaceDataExt: DerefMut<Target = [u8]> {
    /// Sets the pixel at the given coordinates.
    #[inline]
    fn set_pixel(&mut self, stride: usize, pixel: Pixel, x: u32, y: u32) {
        let value = ((pixel.a as u32) << 24)
            | ((pixel.r as u32) << 16)
            | ((pixel.g as u32) << 8)
            | (pixel.b as u32);
        unsafe {
            *(&mut self[y as usize * stride + x as usize * 4] as *mut u8 as *mut u32) = value;
        }
    }
}

impl<'a> ImageSurfaceDataExt for cairo::ImageSurfaceData<'a> {}
<commit_msg>Add Pixel::{un,}premultiply()<commit_after>//! Various utilities for working with Cairo image surfaces.
use std::ops::DerefMut;

use cairo;

pub mod iterators;
pub mod shared_surface;

/// A pixel consisting of R, G, B and A values.
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash)]
pub struct Pixel {
    pub r: u8,
    pub g: u8,
    pub b: u8,
    pub a: u8,
}

/// Modes which specify how the values of out of bounds pixels are computed.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum EdgeMode {
    /// The nearest inbounds pixel value is returned.
    Duplicate,
    /// The image is extended by taking the color values from the opposite of the image.
    ///
    /// Imagine the image being tiled infinitely, with the original image at the origin.
    Wrap,
    /// Zero RGBA values are returned.
    None,
}

/// Extension methods for `cairo::ImageSurfaceData`.
pub trait ImageSurfaceDataExt: DerefMut<Target = [u8]> {
    /// Sets the pixel at the given coordinates.
    #[inline]
    fn set_pixel(&mut self, stride: usize, pixel: Pixel, x: u32, y: u32) {
        let value = ((pixel.a as u32) << 24)
            | ((pixel.r as u32) << 16)
            | ((pixel.g as u32) << 8)
            | (pixel.b as u32);
        unsafe {
            *(&mut self[y as usize * stride + x as usize * 4] as *mut u8 as *mut u32) = value;
        }
    }
}

impl Pixel {
    /// Returns an unpremultiplied value of this pixel.
    #[inline]
    pub fn unpremultiply(self) -> Self {
        if self.a == 0 {
            self
        } else {
            let alpha = f64::from(self.a) / 255.0;
            let unpremultiply = |x| (f64::from(x) / alpha).round() as u8;

            Self {
                r: unpremultiply(self.r),
                g: unpremultiply(self.g),
                b: unpremultiply(self.b),
                a: self.a,
            }
        }
    }

    /// Returns a premultiplied value of this pixel.
    #[inline]
    pub fn premultiply(self) -> Self {
        let alpha = f64::from(self.a) / 255.0;
        let premultiply = |x| (f64::from(x) * alpha).round() as u8;

        Self {
            r: premultiply(self.r),
            g: premultiply(self.g),
            b: premultiply(self.b),
            a: self.a,
        }
    }
}

impl<'a> ImageSurfaceDataExt for cairo::ImageSurfaceData<'a> {}
<|endoftext|>