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

#![feature(asm, lang_items, plugin, range_inclusive)]
#![feature(core_intrinsics, core_slice_ext, core_str_ext)]
#![allow(improper_ctypes)]
#![feature(const_fn)]
#![deny(missing_docs)]
#![no_std]

/*!
Zinc is an embedded stack for rust.

Zinc provides a complete embedded stack for application development in rust. It
is provided in a form of library, compiled for a specific MCU, that can be
linked into user's own applications.

### Supported architectures

ARM is the only architecture, supported at the moment. Zinc can be compiled for
"native" architecture as well, which should be useful only for testing the code,
though.

### Supported ARM MCUs

Two MCUs are supported at the moment, specifically

 * NXP LPC1768
 * ST STM32F407
 * ST STM32L152RCT6
 * Freescale MK20DX32
 * TI TM4C123GXL

The code is generic enough to support other MCUs in the same family (LPC17xx and
STM32F403/407).
*/
#![plugin(ioreg)]
#![feature(no_std)]

#[cfg(target_os = "none")]
extern crate rlibc;

#[macro_use] #[no_link] extern crate ioreg;
#[macro_use] extern crate volatile_cell;

#[cfg(test)] extern crate std;

#[cfg(test)] #[macro_use(expect)] extern crate expectest;

pub mod drivers;
pub mod hal;
pub mod util;
pub mod os;

/// Export a subset of `core` as `std.
///
/// This is exported as a temporary convenience as `rustc` still looks
/// for some items in the `std` namespace.
///
/// TODO(farcaller): clean up when fixed.
#[cfg(target_os = "none")]
pub mod std {
  pub use core::cmp;  // used for #[derive(Eq)] until fixed in rust.
  pub use core::option;
  pub use core::num;
  pub use core::marker;
}
<commit_msg>Updated src/lib.rs to no long call cout core_str_ext as a feature. It's been stabalized in nightly<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#![feature(asm, lang_items, plugin, range_inclusive)]
#![feature(core_intrinsics, core_slice_ext)]
#![allow(improper_ctypes)]
#![feature(const_fn)]
#![deny(missing_docs)]
#![no_std]

/*!
Zinc is an embedded stack for rust.

Zinc provides a complete embedded stack for application development in rust. It
is provided in a form of library, compiled for a specific MCU, that can be
linked into user's own applications.

### Supported architectures

ARM is the only architecture, supported at the moment. Zinc can be compiled for
"native" architecture as well, which should be useful only for testing the code,
though.

### Supported ARM MCUs

Two MCUs are supported at the moment, specifically

 * NXP LPC1768
 * ST STM32F407
 * ST STM32L152RCT6
 * Freescale MK20DX32
 * TI TM4C123GXL

The code is generic enough to support other MCUs in the same family (LPC17xx and
STM32F403/407).
*/
#![plugin(ioreg)]
#![feature(no_std)]

#[cfg(target_os = "none")]
extern crate rlibc;

#[macro_use] #[no_link] extern crate ioreg;
#[macro_use] extern crate volatile_cell;

#[cfg(test)] extern crate std;

#[cfg(test)] #[macro_use(expect)] extern crate expectest;

pub mod drivers;
pub mod hal;
pub mod util;
pub mod os;

/// Export a subset of `core` as `std.
///
/// This is exported as a temporary convenience as `rustc` still looks
/// for some items in the `std` namespace.
///
/// TODO(farcaller): clean up when fixed.
#[cfg(target_os = "none")]
pub mod std {
  pub use core::cmp;  // used for #[derive(Eq)] until fixed in rust.
  pub use core::option;
  pub use core::num;
  pub use core::marker;
}
<|endoftext|>


<commit_before>#![cfg(target_os = "linux")]
//! EventFD binding
//!
//! This crate implements a simple binding for Linux eventfd(). See
//! eventfd(2) for specific details of behaviour.

extern crate libc;

use self::libc::{c_int, c_uint, c_void};
use std::io;
use std::os::unix::io::{AsRawFd,RawFd};
use std::thread;
use std::sync::mpsc;

pub struct EventFD {
    fd: u32,
    flags: u32,
}

unsafe impl Send for EventFD {}
unsafe impl Sync for EventFD {}

/// Construct a semaphore-style EventFD.
pub const EFD_SEMAPHORE: u32 = 0x00001; // 00000001

/// In non-blocking mode, reads and writes will return io::Error
/// containing EAGAIN rather than blocking.
pub const EFD_NONBLOCK: u32  = 0x00800; // 00004000

/// Set the close-on-exec flag on the eventfd.
pub const EFD_CLOEXEC: u32   = 0x80000; // 02000000

impl EventFD {
    /// Create a new EventFD. Flags is the bitwise OR of EFD_* constants, or 0 for no flags.
    /// The underlying file descriptor is closed when the EventFD instance's lifetime ends.
    ///
    /// TODO: work out how to integrate this FD into the wider world
    /// of fds. There's currently no way to poll/select on the fd.
    pub fn new(initval: u32, flags: u32) -> io::Result<EventFD> {
        let r = unsafe { eventfd(initval as c_uint, flags as c_int) };

        if r < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(EventFD { fd: r as u32, flags: flags })
        }
    }

    /// Read the current value of the eventfd. This will block until
    /// the value is non-zero. In semaphore mode this will only ever
    /// decrement the count by 1 and return 1; otherwise it atomically
    /// returns the current value and sets it to zero.
    pub fn read(&self) -> io::Result<u64> {
        let mut ret : u64 = 0;
        let r = unsafe {
            let ptr : *mut u64 = &mut ret;
            libc::read(self.fd as c_int, ptr as *mut c_void, std::mem::size_of_val(&ret) as u64)
        };

        if r < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret)
        }
    }

    /// Add to the current value. Blocks if the value would wrap u64.
    pub fn write(&self, val: u64) -> io::Result<()> {
        let r = unsafe {
            let ptr : *const u64 = &val;
            libc::write(self.fd as c_int, ptr as *const c_void, std::mem::size_of_val(&val) as u64)
        };

        if r < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }

    /// Return a stream of events. The channel has a synchronous
    /// sender because there's no point in building up a queue of
    /// events; if this task blocks on send, the event state will
    /// still update.
    ///
    /// The task will exit if the receiver end is shut down.
    ///
    /// This will be a CPU-spin loop if the EventFD is created
    /// non-blocking.
    ///
    /// XXX FIXME This has no way of terminating except if the other
    /// end closes the connection, and only then if we're not blocked
    /// in the read()...
    pub fn events(&self) -> mpsc::Receiver<u64> {
        let (tx, rx) = mpsc::sync_channel(1);
        let c = self.clone();

        thread::spawn(move || {
            loop {
                match c.read() {
                    Ok(v) => match tx.send(v) {
                        Ok(_) => (),
                        Err(_) => break,
                    },
                    Err(e) => panic!("read failed: {}", e),
                }
            }
        });

        rx
    }
}

impl AsRawFd for EventFD {
    /// Return the raw underlying fd. The caller must make sure self's
    /// lifetime is longer than any users of the fd.
    fn as_raw_fd(&self) -> RawFd {
        self.fd as RawFd
    }
}

impl Drop for EventFD {
    fn drop(&mut self) {
        let r = unsafe { libc::close(self.fd as c_int) };
        if r < 0 {
            panic!("eventfd close {} failed", self.fd)
        }
    }
}

/// Construct a linked clone of an existing EventFD. Once created, the
/// new instance interacts with the original in a way that's
/// indistinguishable from the original.
impl Clone for EventFD {
    fn clone(&self) -> EventFD {
        let r = unsafe { libc::dup(self.fd as c_int) };
        if r < 0 {
            panic!("EventFD clone dup failed: {}", io::Error::last_os_error())
        }

        EventFD { fd: r as u32, flags: self.flags }
    }
}

#[link(name = "c")]
extern "C" {
    fn eventfd(initval: c_uint, flags: c_int) -> c_int;
}

#[cfg(test)]
mod test {
    extern crate std;
    use super::{EventFD, EFD_SEMAPHORE, EFD_NONBLOCK};
    use std::thread;

    #[test]
    fn test_basic() {
        let (tx,rx) = std::sync::mpsc::channel();
        let efd = match EventFD::new(10, 0) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let cefd = efd.clone();

        assert_eq!(efd.read().unwrap(), 10);

        thread::spawn(move || {
            assert_eq!(cefd.read().unwrap(), 7);
            assert_eq!(cefd.write(1).unwrap(), ());
            assert_eq!(cefd.write(2).unwrap(), ());
            assert!(tx.send(()).is_ok());
        });

        assert_eq!(efd.write(7).unwrap(), ());
        let _ = rx.recv();
        assert_eq!(efd.read().unwrap(), 3);
    }

    #[test]
    fn test_sema() {
        let efd = match EventFD::new(0, EFD_SEMAPHORE | EFD_NONBLOCK) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        match efd.read() {
            Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }

        assert_eq!(efd.write(5).unwrap(), ());

        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        match efd.read() {
            Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }
    }

    #[test]
    fn test_stream() {
        let efd = match EventFD::new(11, EFD_SEMAPHORE) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let mut count = 0;

        // only take 10 of 11 so the stream task doesn't block in read and hang the test
        for v in efd.events().iter().take(10) {
            assert_eq!(v, 1);
            count += v;
        }

        assert_eq!(count, 10)
    }

    #[test]
    fn test_chan() {
        let (tx,rx) = std::sync::mpsc::channel();
        let efd = match EventFD::new(10, 0) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        assert_eq!(efd.write(1).unwrap(), ());
        assert!(tx.send(efd).is_ok());

        let t = thread::spawn(move || {
            let efd = rx.recv().unwrap();
            assert_eq!(efd.read().unwrap(), 11)
        }).join();

        match t {
            Ok(_) => println!("ok"),
            Err(_) => panic!("failed"),
        }
    }
}
<commit_msg>Move up eventfd()<commit_after>#![cfg(target_os = "linux")]
//! EventFD binding
//!
//! This crate implements a simple binding for Linux eventfd(). See
//! eventfd(2) for specific details of behaviour.

extern crate libc;

use self::libc::{c_int, c_uint, c_void};
use std::io;
use std::os::unix::io::{AsRawFd,RawFd};
use std::thread;
use std::sync::mpsc;

pub struct EventFD {
    fd: u32,
    flags: u32,
}

unsafe impl Send for EventFD {}
unsafe impl Sync for EventFD {}

/// Construct a semaphore-style EventFD.
pub const EFD_SEMAPHORE: u32 = 0x00001; // 00000001

/// In non-blocking mode, reads and writes will return io::Error
/// containing EAGAIN rather than blocking.
pub const EFD_NONBLOCK: u32  = 0x00800; // 00004000

/// Set the close-on-exec flag on the eventfd.
pub const EFD_CLOEXEC: u32   = 0x80000; // 02000000

#[link(name = "c")]
extern "C" {
    fn eventfd(initval: c_uint, flags: c_int) -> c_int;
}

impl EventFD {
    /// Create a new EventFD. Flags is the bitwise OR of EFD_* constants, or 0 for no flags.
    /// The underlying file descriptor is closed when the EventFD instance's lifetime ends.
    ///
    /// TODO: work out how to integrate this FD into the wider world
    /// of fds. There's currently no way to poll/select on the fd.
    pub fn new(initval: u32, flags: u32) -> io::Result<EventFD> {
        let r = unsafe { eventfd(initval as c_uint, flags as c_int) };

        if r < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(EventFD { fd: r as u32, flags: flags })
        }
    }

    /// Read the current value of the eventfd. This will block until
    /// the value is non-zero. In semaphore mode this will only ever
    /// decrement the count by 1 and return 1; otherwise it atomically
    /// returns the current value and sets it to zero.
    pub fn read(&self) -> io::Result<u64> {
        let mut ret : u64 = 0;
        let r = unsafe {
            let ptr : *mut u64 = &mut ret;
            libc::read(self.fd as c_int, ptr as *mut c_void, std::mem::size_of_val(&ret) as u64)
        };

        if r < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(ret)
        }
    }

    /// Add to the current value. Blocks if the value would wrap u64.
    pub fn write(&self, val: u64) -> io::Result<()> {
        let r = unsafe {
            let ptr : *const u64 = &val;
            libc::write(self.fd as c_int, ptr as *const c_void, std::mem::size_of_val(&val) as u64)
        };

        if r < 0 {
            Err(io::Error::last_os_error())
        } else {
            Ok(())
        }
    }

    /// Return a stream of events.
    ///
    /// The channel has a synchronous sender because there's no point in building up a queue of
    /// events; if this task blocks on send, the event state will still update.
    ///
    /// The task will exit if the receiver end is shut down.
    ///
    /// This will be a CPU-spin loop if the EventFD is created non-blocking.
    ///
    /// XXX FIXME This has no way of terminating except if the other end closes the connection, and
    /// only then if we're not blocked in the read()...
    pub fn events(&self) -> mpsc::Receiver<u64> {
        let (tx, rx) = mpsc::sync_channel(1);
        let c = self.clone();

        thread::spawn(move || {
            loop {
                match c.read() {
                    Ok(v) => match tx.send(v) {
                        Ok(_) => (),
                        Err(_) => break,
                    },
                    Err(e) => panic!("read failed: {}", e),
                }
            }
        });

        rx
    }
}

impl AsRawFd for EventFD {
    /// Return the raw underlying fd. The caller must make sure self's
    /// lifetime is longer than any users of the fd.
    fn as_raw_fd(&self) -> RawFd {
        self.fd as RawFd
    }
}

impl Drop for EventFD {
    fn drop(&mut self) {
        let r = unsafe { libc::close(self.fd as c_int) };
        if r < 0 {
            panic!("eventfd close {} failed", self.fd)
        }
    }
}

/// Construct a linked clone of an existing EventFD. Once created, the
/// new instance interacts with the original in a way that's
/// indistinguishable from the original.
impl Clone for EventFD {
    fn clone(&self) -> EventFD {
        let r = unsafe { libc::dup(self.fd as c_int) };
        if r < 0 {
            panic!("EventFD clone dup failed: {}", io::Error::last_os_error())
        }

        EventFD { fd: r as u32, flags: self.flags }
    }
}

#[cfg(test)]
mod test {
    extern crate std;
    use super::{EventFD, EFD_SEMAPHORE, EFD_NONBLOCK};
    use std::thread;

    #[test]
    fn test_basic() {
        let (tx,rx) = std::sync::mpsc::channel();
        let efd = match EventFD::new(10, 0) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let cefd = efd.clone();

        assert_eq!(efd.read().unwrap(), 10);

        thread::spawn(move || {
            assert_eq!(cefd.read().unwrap(), 7);
            assert_eq!(cefd.write(1).unwrap(), ());
            assert_eq!(cefd.write(2).unwrap(), ());
            assert!(tx.send(()).is_ok());
        });

        assert_eq!(efd.write(7).unwrap(), ());
        let _ = rx.recv();
        assert_eq!(efd.read().unwrap(), 3);
    }

    #[test]
    fn test_sema() {
        let efd = match EventFD::new(0, EFD_SEMAPHORE | EFD_NONBLOCK) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        match efd.read() {
            Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }

        assert_eq!(efd.write(5).unwrap(), ());

        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        assert_eq!(efd.read().unwrap(), 1);
        match efd.read() {
            Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => (), // ok
            Err(e) => panic!("unexpected error {}", e),
            Ok(v) => panic!("unexpected success {}", v),
        }
    }

    #[test]
    fn test_stream() {
        let efd = match EventFD::new(11, EFD_SEMAPHORE) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };
        let mut count = 0;

        // only take 10 of 11 so the stream task doesn't block in read and hang the test
        for v in efd.events().iter().take(10) {
            assert_eq!(v, 1);
            count += v;
        }

        assert_eq!(count, 10)
    }

    #[test]
    fn test_chan() {
        let (tx,rx) = std::sync::mpsc::channel();
        let efd = match EventFD::new(10, 0) {
            Err(e) => panic!("new failed {}", e),
            Ok(fd) => fd,
        };

        assert_eq!(efd.write(1).unwrap(), ());
        assert!(tx.send(efd).is_ok());

        let t = thread::spawn(move || {
            let efd = rx.recv().unwrap();
            assert_eq!(efd.read().unwrap(), 11)
        }).join();

        match t {
            Ok(_) => println!("ok"),
            Err(_) => panic!("failed"),
        }
    }
}
<|endoftext|>


<commit_before>extern crate libc;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const libc::c_void, length: usize, name: *const libc::c_char);
}
<commit_msg>Update lib.rs<commit_after>extern crate libc;

use std::ffi::CString;

#[link(name = "rust")]
extern {
  fn klee_make_symbolic(data: *const libc::c_void, length: usize, name: *const libc::c_char);
}

pub fn klee_make_symbolic_any(data: *const libc::c_void, length: usize, name: &str) {
  let name_cstr = CString::new(name).unwrap();
  unsafe {
    klee_make_symbolic(data, length, name_cstr.as_ptr());
  }
}
<|endoftext|>


<commit_before>//! RustDCT is a pure-Rust signal processing library that computes the most common Discrete Cosine Transforms
//!
//! * DCT Type 1
//! * DCT Type 2 (Often called "the" DCT - by far the most common algorithm, used by JPEG image compression and others)
//! * DCT Type 3 (the inverse of the DCT type 2, also used in JPEG)
//! * DCT Type 4
//! * MDCT (Used in audio and video compression such as Ogg and MP3)
//!
//! The recommended way to use RustDCT is to create a [`DCTplanner`](struct.DCTplanner.html) instance, then call its
//! `plan_dct1` or `plan_dct2` or etc methods. Each DCT type has its own method which will choose the best algorithm
//! for the given size.
//!
//! ```rust
//! // Compute a DCT Type 2 of size 1234
//! use std::sync::Arc;
//! use rustdct::DCTplanner;
//!
//! let mut input:  Vec<f32> = vec![0f32; 1234];
//! let mut output: Vec<f32> = vec![0f32; 1234];
//!
//! let mut planner = DCTplanner::new();
//! let dct = planner.plan_dct2(1234);
//! dct.process_dct2(&mut input, &mut output);
//!
//! // The DCT instance returned by the planner is stored behind an `Arc`, so it's cheap to clone
//! let dct_clone = Arc::clone(&dct);
//! ```
//!
//! RustDCT also exposes individual DCT algorithms. For example, if you're writing a JPEG compression library, it's
//! safe to assume you want a DCT2 and DCT3 of size 8. Instead of going through the planner, you can directly create
//! hardcoded DCT instances of size 8.
//! ```rust
//! // Compute a DCT type 2 of size 8, and then compute a DCT type 3 of size 8 on the output.
//! use rustdct::{DCT2, DCT3};
//! use rustdct::dct2::dct2_butterflies::DCT2Butterfly8;
//! use rustdct::dct3::dct3_butterflies::DCT3Butterfly8;
//!
//! let mut input = [0f32; 8];
//! let mut intermediate = [0f32; 8];
//! let mut output = [0f32; 8];
//!
//! let dct2 = DCT2Butterfly8::new();
//! let dct3 = DCT3Butterfly8::new();
//!
//! dct2.process_dct2(&mut input, &mut intermediate);
//! dct3.process_dct3(&mut intermediate, &mut output);
//! ```

pub extern crate rustfft;

#[cfg(test)]
extern crate rand;

pub use rustfft::num_complex;
pub use rustfft::num_traits;

/// Algorithms for computing the Discrete Cosine Transform Type 1
pub mod dct1;

/// Algorithms for computing the Discrete Cosine Transform Type 2
pub mod dct2;

/// Algorithms for computing the Discrete Cosine Transform Type 3
pub mod dct3;

/// Algorithms for computing the Discrete Cosine Transform Type 4
pub mod dct4;

/// Algorithms for computing the Discrete Sine Transforms
pub mod dst;

/// Algorithms for computing the Modified Discrete Cosine Transform
pub mod mdct;

pub mod algorithm;

mod plan;
mod twiddles;
mod common;
pub use common::DCTnum;

pub use self::plan::DCTplanner;

#[cfg(test)]
mod test_utils;

/// An umbrella trait for algorithms which compute the Discrete Cosine Transform Type 1 (DCT1)
pub trait DCT1<T: common::DCTnum>: rustfft::Length {
    /// Computes the DCT Type 1 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dct1(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Cosine Transform Type 2 (DCT2)
pub trait DCT2<T: common::DCTnum>: rustfft::Length {
    /// Computes the DCT Type 2 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dct2(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Cosine Transform Type 3 (DCT3)
pub trait DCT3<T: common::DCTnum>: rustfft::Length {
    /// Computes the DCT Type 3 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dct3(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Cosine Transform Type 4 (DCT4)
pub trait DCT4<T: common::DCTnum>: rustfft::Length {
    /// Computes the DCT Type 4 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dct4(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Sine Transform Type 1 (DST1)
pub trait DST1<T: common::DCTnum>: rustfft::Length {
    /// Computes the DST Type 1 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dst1(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Sine Transform Type 2 (DST2)
pub trait DST2<T: common::DCTnum>: rustfft::Length {
    /// Computes the DST Type 2 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dst2(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Sine Transform Type 3 (DST3)
pub trait DST3<T: common::DCTnum>: rustfft::Length {
    /// Computes the DST Type 3 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dst3(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Sine Transform Type 4 (DST4)
pub trait DST4<T: common::DCTnum>: rustfft::Length {
    /// Computes the DST Type 4 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dst4(&self, input: &mut [T], output: &mut [T]);
}<commit_msg>Make the lib.rs doctests properly run<commit_after>//! RustDCT is a pure-Rust signal processing library that computes the most common Discrete Cosine Transforms
//!
//! * DCT Type 1
//! * DCT Type 2 (Often called "the" DCT - by far the most common algorithm, used by JPEG image compression and others)
//! * DCT Type 3 (the inverse of the DCT type 2, also used in JPEG)
//! * DCT Type 4
//! * MDCT (Used in audio and video compression such as Ogg and MP3)
//!
//! The recommended way to use RustDCT is to create a [`DCTplanner`](struct.DCTplanner.html) instance, then call its
//! `plan_dct1` or `plan_dct2` or etc methods. Each DCT type has its own method which will choose the best algorithm
//! for the given size.
//!
//! ```rust
//! // Compute a DCT Type 2 of size 1234
//! use std::sync::Arc;
//! use rustdct::DCTplanner;
//!
//! let mut input:  Vec<f32> = vec![0f32; 1234];
//! let mut output: Vec<f32> = vec![0f32; 1234];
//!
//! let mut planner = DCTplanner::new();
//! let dct = planner.plan_dct2(1234);
//! dct.process_dct2(&mut input, &mut output);
//!
//! // The DCT instance returned by the planner is stored behind an `Arc`, so it's cheap to clone
//! let dct_clone = Arc::clone(&dct);
//! ```
//!
//! RustDCT also exposes individual DCT algorithms. For example, if you're writing a JPEG compression library, it's
//! safe to assume you want a DCT2 and DCT3 of size 8. Instead of going through the planner, you can directly create
//! hardcoded DCT instances of size 8.
//!
//! ```rust
//! // Compute a DCT type 2 of size 8, and then compute a DCT type 3 of size 8 on the output.
//! use rustdct::{DCT2, DCT3};
//! use rustdct::dct2::dct2_butterflies::DCT2Butterfly8;
//! use rustdct::dct3::dct3_butterflies::DCT3Butterfly8;
//!
//! let mut input = [0f32; 8];
//! let mut intermediate = [0f32; 8];
//! let mut output = [0f32; 8];
//!
//! let dct2 = DCT2Butterfly8::new();
//! let dct3 = DCT3Butterfly8::new();
//!
//! dct2.process_dct2(&mut input, &mut intermediate);
//! dct3.process_dct3(&mut intermediate, &mut output);
//! ```

pub extern crate rustfft;

#[cfg(test)]
extern crate rand;

pub use rustfft::num_complex;
pub use rustfft::num_traits;

/// Algorithms for computing the Discrete Cosine Transform Type 1
pub mod dct1;

/// Algorithms for computing the Discrete Cosine Transform Type 2
pub mod dct2;

/// Algorithms for computing the Discrete Cosine Transform Type 3
pub mod dct3;

/// Algorithms for computing the Discrete Cosine Transform Type 4
pub mod dct4;

/// Algorithms for computing the Discrete Sine Transforms
pub mod dst;

/// Algorithms for computing the Modified Discrete Cosine Transform
pub mod mdct;

pub mod algorithm;

mod plan;
mod twiddles;
mod common;
pub use common::DCTnum;

pub use self::plan::DCTplanner;

#[cfg(test)]
mod test_utils;

/// An umbrella trait for algorithms which compute the Discrete Cosine Transform Type 1 (DCT1)
pub trait DCT1<T: common::DCTnum>: rustfft::Length {
    /// Computes the DCT Type 1 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dct1(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Cosine Transform Type 2 (DCT2)
pub trait DCT2<T: common::DCTnum>: rustfft::Length {
    /// Computes the DCT Type 2 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dct2(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Cosine Transform Type 3 (DCT3)
pub trait DCT3<T: common::DCTnum>: rustfft::Length {
    /// Computes the DCT Type 3 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dct3(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Cosine Transform Type 4 (DCT4)
pub trait DCT4<T: common::DCTnum>: rustfft::Length {
    /// Computes the DCT Type 4 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dct4(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Sine Transform Type 1 (DST1)
pub trait DST1<T: common::DCTnum>: rustfft::Length {
    /// Computes the DST Type 1 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dst1(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Sine Transform Type 2 (DST2)
pub trait DST2<T: common::DCTnum>: rustfft::Length {
    /// Computes the DST Type 2 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dst2(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Sine Transform Type 3 (DST3)
pub trait DST3<T: common::DCTnum>: rustfft::Length {
    /// Computes the DST Type 3 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dst3(&self, input: &mut [T], output: &mut [T]);
}

/// An umbrella trait for algorithms which compute the Discrete Sine Transform Type 4 (DST4)
pub trait DST4<T: common::DCTnum>: rustfft::Length {
    /// Computes the DST Type 4 on the `input` buffer and places the result in the `output` buffer.
    ///
    /// This method uses the `input` buffer as scratch space, so the contents of `input` should be considered garbage
    /// after calling
    fn process_dst4(&self, input: &mut [T], output: &mut [T]);
}<|endoftext|>


<commit_before>#![cfg_attr(all(feature = "bench", test), feature(test))]

extern crate num;

mod butterflies;

use num::{Complex, Zero, One, Float, Num, FromPrimitive, Signed};
use num::traits::cast;
use std::f32;

use butterflies::{butterfly_2, butterfly_3, butterfly_4, butterfly_5};

pub struct FFT<T> {
    factors: Vec<(usize, usize)>,
    twiddles: Vec<Complex<T>>,
    scratch: Vec<Complex<T>>,
    inverse: bool,
}

impl<T> FFT<T> where T: Signed + FromPrimitive + Copy {
    /// Creates a new FFT context that will process signal of length
    /// `len`. If `inverse` is `true`, then this struct will run inverse
    /// FFTs. This implementation of the FFT doesn't do any scaling on both
    /// the forward and backward transforms, so doing a forward then backward
    /// FFT on a signal will scale the signal by its length.
    pub fn new(len: usize, inverse: bool) -> Self {
        let dir = if inverse { 1 } else { -1 };
        let factors = factor(len);
        let max_fft_len = factors.iter().map(|&(a, _)| a).max();
        let scratch = match max_fft_len {
            None | Some(0...5) => vec![Zero::zero(); 0],
            Some(l) => vec![Zero::zero(); l],
        };
        FFT {
            factors: factor(len),
            twiddles: (0..len)
                      .map(|i| dir as f32 * i as f32 * 2.0 * f32::consts::PI / len as f32)
                      .map(|phase| Complex::from_polar(&1.0, &phase))
                      .map(|c| Complex {re: FromPrimitive::from_f32(c.re).unwrap(),
                                        im: FromPrimitive::from_f32(c.im).unwrap()})
                      .collect(),
            scratch: scratch,
            inverse: inverse,
        }
    }

    /// Runs the FFT on the input `signal` buffer, and places the output in the
    /// `spectrum` buffer.
    ///
    /// # Panics
    /// This method will panic if `signal` and `spectrum` are not the length
    /// specified in the struct's constructor.
    pub fn process(&mut self, signal: &[Complex<T>], spectrum: &mut [Complex<T>]) {
        assert!(signal.len() == spectrum.len());
        assert!(signal.len() == self.twiddles.len());
        cooley_tukey(signal, spectrum, 1, &self.twiddles[..], &self.factors[..],
                     &mut self.scratch, self.inverse);
    }
}

fn cooley_tukey<T>(signal: &[Complex<T>],
                   spectrum: &mut [Complex<T>],
                   stride: usize,
                   twiddles: &[Complex<T>],
                   factors: &[(usize, usize)],
                   scratch: &mut [Complex<T>],
                   inverse: bool) where T: Signed + FromPrimitive + Copy {
    if let Some(&(n1, n2)) = factors.first() {
        if n2 == 1 {
            // An FFT of length 1 is just the identity operator
            let mut spectrum_idx = 0usize;
            let mut signal_idx = 0usize;
            while signal_idx < signal.len() {
                unsafe { *spectrum.get_unchecked_mut(spectrum_idx) =
                    *signal.get_unchecked(signal_idx); }
                spectrum_idx += 1;
                signal_idx += stride;
            }
        } else {
            // Recursive call to perform n1 ffts of length n2
            for i in (0..n1) {
                cooley_tukey(&signal[i * stride..],
                             &mut spectrum[i * n2..],
                             stride * n1, twiddles, &factors[1..],
                             scratch, inverse);
            }
        }

        match n1 {
            5 => unsafe { butterfly_5(spectrum, stride, twiddles, n2) },
            4 => unsafe { butterfly_4(spectrum, stride, twiddles, n2, inverse) },
            3 => unsafe { butterfly_3(spectrum, stride, twiddles, n2) },
            2 => unsafe { butterfly_2(spectrum, stride, twiddles, n2) },
            _ => butterfly(spectrum, stride, twiddles, n2, n1, &mut scratch[..n1]),
        }
    }
}

fn butterfly<T: Num + Copy>(data: &mut [Complex<T>], stride: usize,
                            twiddles: &[Complex<T>], num_ffts: usize,
                            fft_len: usize, scratch: &mut [Complex<T>]) {
    // for each fft we have to perform...
    for fft_idx in (0..num_ffts) {

        // copy over data into scratch space
        let mut data_idx = fft_idx;
        for s in scratch.iter_mut() {
            *s = unsafe { *data.get_unchecked(data_idx) };
            data_idx += num_ffts;
        }

        // perfom the butterfly from the scratch space into the original buffer
        let mut data_idx = fft_idx;
        while data_idx < fft_len * num_ffts {
            let out_sample = unsafe { data.get_unchecked_mut(data_idx) };
            *out_sample = Zero::zero();
            let mut twiddle_idx = 0usize;
            for in_sample in scratch.iter() {
                let twiddle = unsafe { twiddles.get_unchecked(twiddle_idx) };
                *out_sample = *out_sample + in_sample * twiddle;
                twiddle_idx += stride * data_idx;
                if twiddle_idx >= twiddles.len() { twiddle_idx -= twiddles.len() }
            }
            data_idx += num_ffts;
        }

    }
}

pub fn dft<T: Float>(signal: &[Complex<T>], spectrum: &mut [Complex<T>]) {
    for (k, spec_bin) in spectrum.iter_mut().enumerate() {
        let mut sum = Zero::zero();
        for (i, &x) in signal.iter().enumerate() {
            let angle = cast::<_, T>(-1 * (i * k) as isize).unwrap()
                * cast(2.0 * f32::consts::PI).unwrap()
                / cast(signal.len()).unwrap();
            let twiddle = Complex::from_polar(&One::one(), &angle);
            sum = sum + twiddle * x;
        }
        *spec_bin = sum;
    }
}

/// Factors an integer into its prime factors.
fn factor(n: usize) -> Vec<(usize, usize)> {
    let mut factors = Vec::new();
    let mut next = n;
    while next > 1 {
        for div in (2..next + 1) {
            if next % div == 0 {
                next = next / div;
                factors.push((div, next));
                break;
            }
        }
    }
    return factors;
}
<commit_msg>Removed unnecessary parentheses.<commit_after>#![cfg_attr(all(feature = "bench", test), feature(test))]

extern crate num;

mod butterflies;

use num::{Complex, Zero, One, Float, Num, FromPrimitive, Signed};
use num::traits::cast;
use std::f32;

use butterflies::{butterfly_2, butterfly_3, butterfly_4, butterfly_5};

pub struct FFT<T> {
    factors: Vec<(usize, usize)>,
    twiddles: Vec<Complex<T>>,
    scratch: Vec<Complex<T>>,
    inverse: bool,
}

impl<T> FFT<T> where T: Signed + FromPrimitive + Copy {
    /// Creates a new FFT context that will process signal of length
    /// `len`. If `inverse` is `true`, then this struct will run inverse
    /// FFTs. This implementation of the FFT doesn't do any scaling on both
    /// the forward and backward transforms, so doing a forward then backward
    /// FFT on a signal will scale the signal by its length.
    pub fn new(len: usize, inverse: bool) -> Self {
        let dir = if inverse { 1 } else { -1 };
        let factors = factor(len);
        let max_fft_len = factors.iter().map(|&(a, _)| a).max();
        let scratch = match max_fft_len {
            None | Some(0...5) => vec![Zero::zero(); 0],
            Some(l) => vec![Zero::zero(); l],
        };
        FFT {
            factors: factor(len),
            twiddles: (0..len)
                      .map(|i| dir as f32 * i as f32 * 2.0 * f32::consts::PI / len as f32)
                      .map(|phase| Complex::from_polar(&1.0, &phase))
                      .map(|c| Complex {re: FromPrimitive::from_f32(c.re).unwrap(),
                                        im: FromPrimitive::from_f32(c.im).unwrap()})
                      .collect(),
            scratch: scratch,
            inverse: inverse,
        }
    }

    /// Runs the FFT on the input `signal` buffer, and places the output in the
    /// `spectrum` buffer.
    ///
    /// # Panics
    /// This method will panic if `signal` and `spectrum` are not the length
    /// specified in the struct's constructor.
    pub fn process(&mut self, signal: &[Complex<T>], spectrum: &mut [Complex<T>]) {
        assert!(signal.len() == spectrum.len());
        assert!(signal.len() == self.twiddles.len());
        cooley_tukey(signal, spectrum, 1, &self.twiddles[..], &self.factors[..],
                     &mut self.scratch, self.inverse);
    }
}

fn cooley_tukey<T>(signal: &[Complex<T>],
                   spectrum: &mut [Complex<T>],
                   stride: usize,
                   twiddles: &[Complex<T>],
                   factors: &[(usize, usize)],
                   scratch: &mut [Complex<T>],
                   inverse: bool) where T: Signed + FromPrimitive + Copy {
    if let Some(&(n1, n2)) = factors.first() {
        if n2 == 1 {
            // An FFT of length 1 is just the identity operator
            let mut spectrum_idx = 0usize;
            let mut signal_idx = 0usize;
            while signal_idx < signal.len() {
                unsafe { *spectrum.get_unchecked_mut(spectrum_idx) =
                    *signal.get_unchecked(signal_idx); }
                spectrum_idx += 1;
                signal_idx += stride;
            }
        } else {
            // Recursive call to perform n1 ffts of length n2
            for i in 0..n1 {
                cooley_tukey(&signal[i * stride..],
                             &mut spectrum[i * n2..],
                             stride * n1, twiddles, &factors[1..],
                             scratch, inverse);
            }
        }

        match n1 {
            5 => unsafe { butterfly_5(spectrum, stride, twiddles, n2) },
            4 => unsafe { butterfly_4(spectrum, stride, twiddles, n2, inverse) },
            3 => unsafe { butterfly_3(spectrum, stride, twiddles, n2) },
            2 => unsafe { butterfly_2(spectrum, stride, twiddles, n2) },
            _ => butterfly(spectrum, stride, twiddles, n2, n1, &mut scratch[..n1]),
        }
    }
}

fn butterfly<T: Num + Copy>(data: &mut [Complex<T>], stride: usize,
                            twiddles: &[Complex<T>], num_ffts: usize,
                            fft_len: usize, scratch: &mut [Complex<T>]) {
    // for each fft we have to perform...
    for fft_idx in 0..num_ffts {

        // copy over data into scratch space
        let mut data_idx = fft_idx;
        for s in scratch.iter_mut() {
            *s = unsafe { *data.get_unchecked(data_idx) };
            data_idx += num_ffts;
        }

        // perfom the butterfly from the scratch space into the original buffer
        let mut data_idx = fft_idx;
        while data_idx < fft_len * num_ffts {
            let out_sample = unsafe { data.get_unchecked_mut(data_idx) };
            *out_sample = Zero::zero();
            let mut twiddle_idx = 0usize;
            for in_sample in scratch.iter() {
                let twiddle = unsafe { twiddles.get_unchecked(twiddle_idx) };
                *out_sample = *out_sample + in_sample * twiddle;
                twiddle_idx += stride * data_idx;
                if twiddle_idx >= twiddles.len() { twiddle_idx -= twiddles.len() }
            }
            data_idx += num_ffts;
        }

    }
}

pub fn dft<T: Float>(signal: &[Complex<T>], spectrum: &mut [Complex<T>]) {
    for (k, spec_bin) in spectrum.iter_mut().enumerate() {
        let mut sum = Zero::zero();
        for (i, &x) in signal.iter().enumerate() {
            let angle = cast::<_, T>(-1 * (i * k) as isize).unwrap()
                * cast(2.0 * f32::consts::PI).unwrap()
                / cast(signal.len()).unwrap();
            let twiddle = Complex::from_polar(&One::one(), &angle);
            sum = sum + twiddle * x;
        }
        *spec_bin = sum;
    }
}

/// Factors an integer into its prime factors.
fn factor(n: usize) -> Vec<(usize, usize)> {
    let mut factors = Vec::new();
    let mut next = n;
    while next > 1 {
        for div in 2..next + 1 {
            if next % div == 0 {
                next = next / div;
                factors.push((div, next));
                break;
            }
        }
    }
    return factors;
}
<|endoftext|>


<commit_before>extern crate libc;
use std::str;
use std::ptr;
use std::ffi::CStr;

#[repr(C)]
struct Loc;
#[repr(C)]
struct Errno;
#[repr(C)]
struct Parser;

#[link(name = "spsps")]
extern{
	//This returns an owned Parser
	fn spsps_new(name: *mut libc::c_char, stream: libc::FILE) -> *mut Parser;
	fn spsps_free(parser: *mut Parser);
	//This returns an owned C string.
	fn spsps_loc_to_string(loc: *mut Loc) -> *mut libc::c_char;
	//This returns a borrowed string
	fn spsps_printchar(xch: libc::c_char) -> *mut libc::c_char;
	fn spsps_consume(parser: *mut Parser) -> libc::c_char;
	fn spsps_consume_n(parser: *mut Parser, n: libc::size_t);
	fn spsps_consume_whitespace(parser: *mut Parser);
	//Not sure what return type to use for bool
	fn spsps_eof(parser: *mut Parser) -> libc::c_int;
	//This returns an owned Loc
	fn spsps_loc(parser: *mut Parser) -> *mut Loc;
	fn spsps_peek(parser: *mut Parser) -> libc::c_char;
	fn spsps_peek_n(parser: *mut Parser, n: libc::size_t) -> *mut libc::c_char;
	fn spsps_peek_str(parser: *mut Parser, next: *mut libc::c_char) -> libc::c_int;
	fn spsps_peek_and_consume(parser: *mut Parser, next: *mut libc::c_char) -> libc::c_int;

}

fn loc_to_string(loc: &mut Loc) -> String{
	let tmp = unsafe { CStr::from_ptr(spsps_loc_to_string(loc)) };
	let retval = str::from_utf8(tmp.to_bytes()).unwrap_or("").to_owned();
	unsafe {libc::free(tmp.as_ptr() as *mut libc::c_void);}
	retval
 }<commit_msg>Capturing progress towards a safe Parser abstraction.<commit_after>extern crate libc;
use std::str;
use std::ptr;
use std::path::Path;
use std::fs::File;
use std::ffi::CStr;
use std::ffi::CString;

#[repr(C)]
struct Loc;
#[repr(C)]
struct Errno;

//This is for the opaque C pointer
enum spsps_parser_ {}
//this will be the safe abstraction
struct Parser{
	ptr: *mut spsps_parser_
}

#[link(name = "spsps")]
extern{
	//This returns an owned Parser
	fn spsps_new(name: *const libc::c_char, stream: *mut libc::FILE) -> *mut spsps_parser_;
	fn spsps_free(parser: *mut Parser);
	//This returns an owned C string.
	fn spsps_loc_to_string(loc: *mut Loc) -> *mut libc::c_char;
	//This returns a borrowed string
	fn spsps_printchar(xch: libc::c_char) -> *mut libc::c_char;
	fn spsps_consume(parser: *mut Parser) -> libc::c_char;
	fn spsps_consume_n(parser: *mut Parser, n: libc::size_t);
	fn spsps_consume_whitespace(parser: *mut Parser);
	//Not sure what return type to use for bool
	fn spsps_eof(parser: *mut Parser) -> libc::c_int;
	//This returns an owned Loc
	fn spsps_loc(parser: *mut Parser) -> *mut Loc;
	fn spsps_peek(parser: *mut Parser) -> libc::c_char;
	fn spsps_peek_n(parser: *mut Parser, n: libc::size_t) -> *mut libc::c_char;
	fn spsps_peek_str(parser: *mut Parser, next: *mut libc::c_char) -> libc::c_int;
	fn spsps_peek_and_consume(parser: *mut Parser, next: *mut libc::c_char) -> libc::c_int;
}

impl Parser{
	fn from_file(name: &str, path: &Path) -> Parser {
		unsafe{
			let path = CString::new(path.to_str().unwrap()).unwrap().as_ptr();
			let fd = libc::funcs::c95::stdio::fopen(path,  CString::new("r").unwrap().as_ptr());
			Parser{ ptr: spsps_new(CString::new(name).unwrap().as_ptr(), fd) }
		 }
	}
}

impl Loc{
	fn loc_to_string(loc: &mut Loc) -> String{
		let tmp = unsafe { CStr::from_ptr(spsps_loc_to_string(loc)) };
		let retval = str::from_utf8(tmp.to_bytes()).unwrap_or("").to_owned();
		unsafe {libc::free(tmp.as_ptr() as *mut libc::c_void);}
		retval
	}
}<|endoftext|>


<commit_before>#[macro_use] extern crate lazy_static;
extern crate regex;

use regex::Regex;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::fmt;
use std::result;

pub type Result<T> = result::Result<T, String>;

lazy_static! {
        pub static ref SUBS: Regex = Regex::new(r"(?x)
            (\d+)
            (\r\n)
            (\d{2}):(\d{2}):(\d{2}),(\d{3})
            \s-->\s
            (\d{2}):(\d{2}):(\d{2}),(\d{3})
            (\r\n)
            ([\S\s]*?)
            (\r\n){2}?").unwrap();
    }

fn read_file(path: &Path) -> Result<String> {
    let mut file = try!(File::open(&path).map_err(|e| e.to_string()));
    let mut content = String::new();
    try!(file.read_to_string(&mut content).map_err(|e| e.to_string()));
    Ok(content)
}

fn parse(content: String, path: &str) -> Subtitles {
    let mut result: Vec<SubLine> = vec![];

    for cap in SUBS.captures_iter(&content) {
        let start_timestamp = [cap.at(3).unwrap().parse::<u32>().unwrap(),
                               cap.at(4).unwrap().parse::<u32>().unwrap(),
                               cap.at(5).unwrap().parse::<u32>().unwrap(),
                               cap.at(6).unwrap().parse::<u32>().unwrap()];
        let end_timestamp = [cap.at(7).unwrap().parse::<u32>().unwrap(),
                             cap.at(8).unwrap().parse::<u32>().unwrap(),
                             cap.at(9).unwrap().parse::<u32>().unwrap(),
                             cap.at(10).unwrap().parse::<u32>().unwrap()];

        let start = to_miliseconds(&start_timestamp);
        let end = to_miliseconds(&end_timestamp);

        let line = SubLine {
            index: cap.at(1).unwrap().parse::<u32>().unwrap(),
            text: cap.at(12).unwrap().to_string(),
            start: start,
            end: end,
        };
        result.push(line)
    }
    Subtitles { field: result, path: path.to_string() }
}

fn to_miliseconds(timestamp: &[u32; 4]) -> u32 {
    let mut result: u32 = 0;
    result += timestamp[3];
    result += timestamp[2] * 1000;
    result += timestamp[1] * 1000 * 60;
    result += timestamp[0] * 1000 * 60 * 60;
    result
}

fn recover_timestamp(miliseconds: &u32) -> [u32;4] {
    let hours = miliseconds / 3600000;
    let minutes = (miliseconds - hours * 3600000) / 60000;
    let seconds = (miliseconds - (hours * 3600000 + minutes * 60000)) / 1000;
    let miliseconds = miliseconds - (hours * 3600000 + minutes * 60000 + seconds * 1000);
    [hours, minutes, seconds, miliseconds]
}

#[derive(Debug, Clone)]
pub struct SubLine {
    text: String,
    index: u32,
    start: u32,
    end: u32,
}

impl fmt::Display for SubLine {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}\n{:?} --> {:?} ({}>>{})\n{}",
               self.index,
               self.start,
               self.end,
               self.start,
               self.end,
               self.text)
    }
}

impl SubLine {
    pub fn get_start(&self) -> u32 {
        self.start
    }

    pub fn get_text(&self) -> String {
        self.text.clone()
    }

    pub fn get_start_timestamp(&self) -> [u32; 4] {
        recover_timestamp(&self.start)
    }

    pub fn get_end_timestamp(&self) -> [u32; 4] {
        recover_timestamp(&self.end)
    }

    pub fn get_index(&self) -> u32 {
        self.index
    }

    pub fn get_end(&self) -> u32 {
        self.end
    }

    pub fn get_duration(&self) -> u32 {
        self.end - self.start
    }

    pub fn shift(&mut self, offset: i32) -> Result<()> {
        if offset > 0 {
            self.start += offset as u32;
            self.end += offset as u32;
            Ok(())
        } else if offset < 0 {
            if (-offset as u32 >= self.start) || (-offset as u32 >= self.end) {
                return Err("start can't be negative".to_string())
            };
            self.start -= -offset as u32;
            self.end -= -offset as u32;
            Ok(())
        } else {
            Err("offset can't be 0".to_string())
        }
    }
}

#[derive(Debug)]
pub struct Subtitles {
    field: Vec<SubLine>,
    path: String,
}

impl fmt::Display for Subtitles {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "length: {}\n{}\n..........\n{}\n",
               self.get_length(),
               self.field.first().unwrap(),
               self.field.last().unwrap())
    }
}

impl IntoIterator for Subtitles {
    type Item = SubLine;
    type IntoIter = ::std::vec::IntoIter<SubLine>;
    fn into_iter(self) -> Self::IntoIter {
        self.field.into_iter()
    }
}

impl Subtitles {
    pub fn get_path(&self) -> String {
        self.path.clone()
    }

    pub fn by_index(&self, index: usize) -> Option<SubLine> {
        self.field.get(index - 1).map(|n| n.clone())
    }

    pub fn get_length(&self) -> usize {
        self.field.len()
    }

    pub fn by_timestamp(&self, timestamp: &[u32; 4]) -> Option<SubLine> {
        let miliseconds = to_miliseconds(&timestamp);
        self.by_miliseconds(miliseconds)
    }

    pub fn by_miliseconds(&self, time: u32) -> Option<SubLine> {
        // binary search
        let mut min = 0;
        let mut max = self.field.len() - 1;
        let mut guess_index;

        while max >= min {
            guess_index = (max + min) / 2;
            let guess = self.field.get(guess_index).unwrap();

            if (guess.start <= time) && (time <= guess.end) {
                return Some(guess.clone());
            } else if time > guess.end {
                min = guess_index + 1;
            } else {
                max = guess_index - 1;
            }
        }
        None
    }

    pub fn mut_by_miliseconds(&mut self, time: u32) -> Option<&mut SubLine> {
        // binary search
        let mut min = 0;
        let mut max = self.field.len() - 1;
        let mut guess_index;
        let mut result: usize = 0;
        let mut state = false;

        while max >= min {
            guess_index = (max + min) / 2;

            let guess = self.field.get(guess_index).unwrap();

            if (guess.start <= time) && (time <= guess.end) {
                result = guess_index;
                state = true;
                break;
            } else if time > guess.end {
                min = guess_index + 1;
            } else {
                max = guess_index - 1;
            }
        }

        if state {
            Some(&mut self.field[result])
        } else { None }
    }

    pub fn mut_by_timestamp(&mut self, timestamp: &[u32; 4]) -> Option<&mut SubLine> {
        let miliseconds = to_miliseconds(&timestamp);
        self.mut_by_miliseconds(miliseconds)
    }

    pub fn mut_by_index(&mut self, index: usize) -> Option<&mut SubLine>{
        self.field.get_mut(index - 1)
    }

    pub fn shift_all(&mut self, offset: i32) -> Result<()> {
        for line in &mut self.field {
            try!(line.shift(offset));
        }
        Ok(())
    }
}

pub fn prepare(path: &str) -> Result<Subtitles> {
    let sub_path = Path::new(path);
    let mut content = try!(read_file(&sub_path).map_err(|e| e.to_string()));

    let eof_empty_lines = Regex::new(r"\S\s*?\z").unwrap();
    let unify_newline_style = Regex::new(r"(?x)
            ([^\n(\r\n)]\r[^\n(\r\n)])|
            ([^\r(\r\n)]\n[^\r(\r\n)])")
        .unwrap();

    content = eof_empty_lines.replace_all(&content, "\r\n\r\n");
    content = unify_newline_style.replace_all(&content, "\r\n");

    if !SUBS.is_match(&content) {
        return Err("Bad srt file".to_string());
    }

    Ok(parse(content, path))
}

#[test]
fn it_works() {
    let path = "ex1";
    let mut subs = prepare(path).unwrap();

    let line = subs.by_index(3).unwrap();
    {
        let another_one = subs.by_miliseconds(261072).unwrap();
        let same_line = subs.by_timestamp(&[0, 4, 22, 500]).unwrap();
        assert_eq!(line.get_index(), same_line.get_index());
        assert_eq!(same_line.get_text(), another_one.get_text());
    }

    println!("{}\n{:?} --> {:?}\n{}\n",
             line.get_index(),
             line.get_start(),
             line.get_end(),
             line.get_text());
    println!("duration: {}", line.get_duration());

    {
        let mut mutline = subs.mut_by_miliseconds(261072).unwrap();
        mutline.shift(-1).unwrap();
    }

    {
        let newline = subs.by_index(3).unwrap();
        assert_eq!(newline.get_start(), line.get_start() - 1);
    }

    subs.shift_all(1).unwrap();

    {
        let newline = subs.by_index(3).unwrap();
        assert_eq!(newline.get_start(), line.get_start());
    }

}<commit_msg>changed interface<commit_after>#[macro_use] extern crate lazy_static;
extern crate regex;

use regex::Regex;
use std::fs::File;
use std::io::prelude::*;
use std::path::Path;
use std::fmt;
use std::result;

pub type Result<T> = result::Result<T, String>;

#[derive(Clone)]
pub struct SubLine {
    text: String,
    index: u32,
    start: u32,
    end: u32,
}

impl fmt::Display for SubLine {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f,
               "{}\n{:?} --> {:?} ({}>>{})\n{}",
               self.index,
               self.start,
               self.end,
               self.start,
               self.end,
               self.text)
    }
}

impl SubLine {
    pub fn get_start(&self) -> u32 {
        self.start
    }

    pub fn get_text(&self) -> String {
        self.text.clone()
    }

    pub fn get_start_timestamp(&self) -> [u32; 4] {
        recover_timestamp(&self.start)
    }

    pub fn get_end_timestamp(&self) -> [u32; 4] {
        recover_timestamp(&self.end)
    }

    pub fn get_index(&self) -> u32 {
        self.index
    }

    pub fn get_end(&self) -> u32 {
        self.end
    }

    pub fn get_duration(&self) -> u32 {
        self.end - self.start
    }

    pub fn shift(&mut self, offset: i32) -> Result<()> {
        if offset > 0 {
            self.start += offset as u32;
            self.end += offset as u32;
            Ok(())
        } else if offset < 0 {
            if (-offset as u32 >= self.start) || (-offset as u32 >= self.end) {
                return Err("start(end) can't be negative".to_string())
            };
            self.start -= -offset as u32;
            self.end -= -offset as u32;
            Ok(())
        } else {
            Err("offset can't be 0".to_string())
        }
    }
}

trait SubLineVector {
    fn by_index(&self, index: usize) -> Option<&SubLine>;
    fn by_index_mut(&mut self, index: usize) -> Option<&mut SubLine>;

    fn by_timestamp(&self, timestamp: &[u32; 4]) -> Option<&SubLine> {
        let miliseconds = to_miliseconds(&timestamp);
        self.by_miliseconds(miliseconds)
    }

    fn by_timestamp_mut(&mut self, timestamp: &[u32; 4]) -> Option<&mut SubLine> {
        let miliseconds = to_miliseconds(&timestamp);
        self.by_miliseconds_mut(miliseconds)
    }

    fn by_miliseconds(&self, time: u32) -> Option<&SubLine>;
    fn by_miliseconds_mut(&mut self, time: u32) -> Option<&mut SubLine>;
}

pub type Subtitles = Vec<SubLine>;

impl SubLineVector for Subtitles {
    fn by_index(&self, index: usize) -> Option<&SubLine> {
        self.get(index - 1)
    }

    fn by_index_mut(&mut self, index: usize) -> Option<&mut SubLine>{
        self.get_mut(index - 1)
    }

    fn by_miliseconds(&self, time: u32) -> Option<&SubLine> {
        // binary search
        let mut min = 0;
        let mut max = self.len() - 1;
        let mut guess_index;

        while max >= min {
            guess_index = (max + min) / 2;
            let guess = self.get(guess_index).unwrap();

            if (guess.start <= time) && (time <= guess.end) {
                return Some(&guess);
            } else if time > guess.end {
                min = guess_index + 1;
            } else {
                max = guess_index - 1;
            }
        }
        None
    }

    fn by_miliseconds_mut(&mut self, time: u32) -> Option<&mut SubLine> {
        // binary search
        let mut min = 0;
        let mut max = self.len() - 1;
        let mut guess_index;
        let mut result: usize = 0;
        let mut state = false;

        while max >= min {
            guess_index = (max + min) / 2;

            let guess = self.get(guess_index).unwrap();

            if (guess.start <= time) && (time <= guess.end) {
                result = guess_index;
                state = true;
                break;
            } else if time > guess.end {
                min = guess_index + 1;
            } else {
                max = guess_index - 1;
            }
        }
        if state {
            Some(&mut self[result])
        } else { None }
    }
}

fn to_miliseconds(timestamp: &[u32; 4]) -> u32 {
    let mut result: u32 = 0;
    result += timestamp[3];
    result += timestamp[2] * 1000;
    result += timestamp[1] * 1000 * 60;
    result += timestamp[0] * 1000 * 60 * 60;
    result
}

fn recover_timestamp(miliseconds: &u32) -> [u32;4] {
    let hours = miliseconds / 3600000;
    let minutes = (miliseconds - hours * 3600000) / 60000;
    let seconds = (miliseconds - (hours * 3600000 + minutes * 60000)) / 1000;
    let miliseconds = miliseconds - (hours * 3600000 + minutes * 60000 + seconds * 1000);
    [hours, minutes, seconds, miliseconds]
}

lazy_static! {
        pub static ref SUBS: Regex = Regex::new(r"(?x)
            (\d+)
            (\r\n)
            (\d{2}):(\d{2}):(\d{2}),(\d{3})
            \s-->\s
            (\d{2}):(\d{2}):(\d{2}),(\d{3})
            (\r\n)
            ([\S\s]*?)
            (\r\n){2}?").unwrap();
    }

fn read_file(path: &Path) -> Result<String> {
    let mut file = try!(File::open(&path).map_err(|e| e.to_string()));
    let mut content = String::new();
    try!(file.read_to_string(&mut content).map_err(|e| e.to_string()));
    Ok(content)
}

fn parse(content: String) -> Subtitles {
    let mut result: Subtitles = Subtitles::new();

    for cap in SUBS.captures_iter(&content) {
        let start_timestamp = [cap.at(3).unwrap().parse::<u32>().unwrap(),
                               cap.at(4).unwrap().parse::<u32>().unwrap(),
                               cap.at(5).unwrap().parse::<u32>().unwrap(),
                               cap.at(6).unwrap().parse::<u32>().unwrap()];
        let end_timestamp = [cap.at(7).unwrap().parse::<u32>().unwrap(),
                             cap.at(8).unwrap().parse::<u32>().unwrap(),
                             cap.at(9).unwrap().parse::<u32>().unwrap(),
                             cap.at(10).unwrap().parse::<u32>().unwrap()];

        let start = to_miliseconds(&start_timestamp);
        let end = to_miliseconds(&end_timestamp);

        let line = SubLine {
            index: cap.at(1).unwrap().parse::<u32>().unwrap(),
            text: cap.at(12).unwrap().to_string(),
            start: start,
            end: end,
        };
        result.push(line)
    }
    result
}

pub fn prepare(path: &str) -> Result<Subtitles> {
    let sub_path = Path::new(path);
    let mut content = try!(read_file(&sub_path).map_err(|e| e.to_string()));

    let eof_empty_lines = Regex::new(r"\S\s*?\z").unwrap();
    let unify_newline_style = Regex::new(r"(?x)
            ([^\n(\r\n)]\r[^\n(\r\n)])|
            ([^\r(\r\n)]\n[^\r(\r\n)])")
        .unwrap();

    content = eof_empty_lines.replace_all(&content, "\r\n\r\n");
    content = unify_newline_style.replace_all(&content, "\r\n");

    if !SUBS.is_match(&content) {
        return Err("Bad srt file".to_string());
    }

    Ok(parse(content))
}

#[test]
fn test1 () {
    let path = "ex1";
    let mut subs = prepare(path).unwrap();
    let test = subs.by_index(3).unwrap().clone();

    {
        let another_one = subs.by_miliseconds(261072).unwrap();
        let same_line = subs.by_timestamp(&[0, 4, 22, 500]).unwrap();
        assert_eq!(test.get_index(), same_line.get_index());
        assert_eq!(same_line.get_index(), another_one.get_index());
    }
    {
        let mut mutline = subs.by_index_mut(3).unwrap();
        mutline.shift(-5).unwrap();
    }
    {
        let changed_line = subs.by_index(3).unwrap();
        assert_eq!(changed_line.get_start(), test.get_start() - 5);
    }
}<|endoftext|>


<commit_before>//! Intrusive structure support in Rust.
//!
//! An intrusive structure is a general-purpose structure directly
//! embedded within a containing structure, in order to add that
//! general-purpose facility to the container. As an example, one
//! might use an intrusive "link" structure to allow objects to be
//! organized in a linked-list:
//!
//! # Example
//!
//! ```test_harness
//! # #[macro_use]
//! # extern crate containerof;
//! # use containerof::*;
//! struct Link {
//!     next: Option<ContainerLink>,
//! }
//! struct List {
//!     head: Option<ContainerLink>,
//!     tail: Option<ContainerLink>,
//! }
//!
//! struct Container {
//!     link: Link,
//! }
//! containerof_intrusive!(ContainerLink = Container:link::Link);
//! ```

#![feature(unsafe_destructor)]
use std::ops;
use std::mem;
use std::marker;

/// Implement C-like `offsetof` macro in Rust. Will become obsolete
/// when-and-if offsetof() is implemented in the core language.
#[macro_export]
#[unstable = "Will go away if-and-when Rust implements this function directly."]
macro_rules! containerof_field_offset {
    ($container:ty : $field:ident) => (unsafe {
        &(*(0usize as *const $container)).$field as *const _ as usize
    })
}

#[macro_export]
#[unstable = "Experimental API."]
macro_rules! containerof_intrusive {
    ($nt:ident = $container:ty : $field:ident :: $fieldtype:ty) => (
        struct $nt($crate::IntrusiveAlias);
        impl $crate::IntrusiveBase for $nt {
            type Container = $container;
            type Field = $fieldtype;
            #[inline]
            fn offset() -> usize {
                containerof_field_offset!($container : $field)
            }
            #[inline]
            unsafe fn new(ia: $crate::IntrusiveAlias) -> $nt {
                $nt(ia)
            }
        }
        )
}

/// Alias that has the same representation as an intrusive type. The
/// idea is to be able to use this alias for intrusive facility
/// implementations, by defining the "true" implementation of the
/// facility to use the single (but type-unsafe) IntrusiveAlias type,
/// while allowing type-safe wrapper implementations to delegate their
/// behavior to the implementation function.
#[derive(PartialEq,Eq,Copy,Clone,Debug)]
#[unstable = "Experimental API"]
pub struct IntrusiveAlias(pub usize);
impl IntrusiveAlias {
    pub fn new(addr: usize) -> IntrusiveAlias {
        IntrusiveAlias(addr)
    }
    pub unsafe fn new_of<T>(addr: &T) -> IntrusiveAlias {
        IntrusiveAlias::new(addr as *const _ as usize)
    }
    pub fn get_address(&self) -> usize {
        self.0
    }
}

// FIXME: this wants to be a linear type.
#[unstable = "Experimental API"]
pub struct OwnBox<T> {
    pointer: IntrusiveAlias,
    marker: marker::PhantomData<T>,
}
impl<T> OwnBox<T> {
    pub fn get_address(&self) -> usize {
        self.pointer.0
    }
    pub unsafe fn from_alias(pointer: IntrusiveAlias) -> OwnBox<T> {
        OwnBox { pointer: pointer, marker: marker::PhantomData }
    }
    pub unsafe fn from_ref(p: &mut T) -> OwnBox<T> {
        OwnBox::from_alias(IntrusiveAlias::new_of(p))
    }
    pub unsafe fn into_alias(self) -> IntrusiveAlias {
        let rval = self.pointer;
        mem::forget(self);
        rval
    }
    pub fn as_alias<'a>(&'a self) -> &'a IntrusiveAlias {
        &self.pointer
    }
    pub unsafe fn from_box(b: Box<T>) -> OwnBox<T> {
        OwnBox { pointer: IntrusiveAlias::new(mem::transmute(b)), marker: marker::PhantomData }
    }
    pub unsafe fn into_box(self) -> Box<T> {
        mem::transmute(self.into_alias().get_address())
    }
}
impl<T> ops::Deref for OwnBox<T> {
    type Target = T;
    fn deref<'a>(&'a self) -> &'a T {
        unsafe { mem::transmute(self.get_address()) }
    }
}
impl<T> ops::DerefMut for OwnBox<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { mem::transmute(self.get_address()) }
    }
}
#[unsafe_destructor]
impl<T> ops::Drop for OwnBox<T> {
    fn drop(&mut self) {
        // should have been consumed via "into_box" or "into_alias".
        //panic!("containerof::OwnBox should be treated as linear!");
    }
}

#[derive(Debug)]
pub struct BorrowBox<'a, T: 'a> {
    pointer: IntrusiveAlias,
    marker: marker::PhantomData<&'a T>,
}
impl<'a, T> BorrowBox<'a, T> where T: Intrusive {
    pub fn new(source: &'a T) -> BorrowBox<'a, T> {
        unsafe { BorrowBox::new_from(IntrusiveAlias::new_of(source), source) }
    }
    pub unsafe fn new_from<U>(pointer: IntrusiveAlias, _lifetime: &'a U) -> BorrowBox<'a, T> {
        BorrowBox {
            pointer: pointer,
            marker: marker::PhantomData,
        }
    }
    pub fn as_target<'b>(&'b self) -> &'b T where 'b: 'a {
        unsafe { Intrusive::of_alias(&self.pointer) }
    }
}

#[derive(Debug)]
pub struct BorrowBoxMut<'a, T: 'a> where T: Intrusive {
    pointer: IntrusiveAlias,
    marker: marker::PhantomData<&'a mut T>,
}
impl<'a, T> BorrowBoxMut<'a, T> where T: Intrusive {
    pub fn new(source: &'a mut T) -> BorrowBoxMut<'a, T> {
        unsafe { BorrowBoxMut::new_from(IntrusiveAlias::new_of(source), source) }
    }
    pub unsafe fn new_from<U>(pointer: IntrusiveAlias, _lifetime: &'a mut U) -> BorrowBoxMut<'a, T> {
        BorrowBoxMut {
            pointer: pointer,
            marker: marker::PhantomData,
        }
    }
    pub fn as_target<'b>(&'b self) -> &'b T where 'a: 'b {
        unsafe { Intrusive::of_alias(&self.pointer) }
    }
    pub fn as_target_mut<'b>(&'b mut self) -> &'b mut T where 'a: 'b {
        unsafe { Intrusive::of_alias_mut(&mut self.pointer) }
    }
}

#[unstable = "Experimental API"]
pub trait IntrusiveBase {
    /// Type of containing structure.
    type Container;
    /// Type of intrusive field within containing structure.
    type Field;
    // TODO: would also like to see an "offset" associated const, but
    // Rust doesn't seem to support these yet.
    /// Returns offset of intrusive field within containing structure.
    fn offset() -> usize;

    /// Ownership-moving translation from generic intrusive pointer
    /// alias to type-safe intrusive pointer.
    unsafe fn new(IntrusiveAlias) -> Self;
}

/// Trait defining routines for translation between containing
/// structure and intrusive field. The only implementors of this type
/// should be the pointer-types defined by the `containerof_intrusive`
/// macro.
#[unstable = "Experimental API"]
pub trait Intrusive: IntrusiveBase {
    /// Ownership-moving translation from generic intrusive pointer
    /// alias to type-safe intrusive pointer.
    unsafe fn from_alias(IntrusiveAlias) -> Self;

    /// Ownership-moving translation from type-safe intrusive pointer
    /// to generic intrusive pointer.
    unsafe fn into_alias(self) -> IntrusiveAlias;

    /// Allow using type-safe intrusive pointer as generic intrusive pointer.
    unsafe fn as_alias<'a>(&'a self) -> &'a IntrusiveAlias;

    /// Allow using type-safe intrusive pointer as mutable generic
    /// intrusive pointer.
    unsafe fn as_alias_mut<'a>(&'a mut self) -> &'a mut IntrusiveAlias;

    /// Allow using generic intrusive pointer as type-safe intrusive
    /// pointer.
    unsafe fn of_alias<'a>(&'a IntrusiveAlias) -> &'a Self;

    /// Allow using generic intrusive pointer as mutable type-safe
    /// intrusive pointer.
    unsafe fn of_alias_mut<'a>(ia: &'a mut IntrusiveAlias) -> &'a mut Self;

    /// Represent ownership of a container as ownership of an Intrusive
    /// pointer type. (Inverse of `into_container`.)
    fn from_container(OwnBox<Self::Container>) -> Self;

    /// Represent ownership of an Intrusive pointer type as ownership of
    /// its container. (Inverse of `from_container`.)
    fn into_container(self) -> OwnBox<Self::Container>;

    fn of_container<'a>(&'a Self::Container) -> BorrowBox<'a, Self>;
    fn of_container_mut<'a>(&'a mut Self::Container) -> BorrowBoxMut<'a, Self>;

    /// Grant referential access to the container of this intrusive
    /// pointer type.
    fn as_container<'a>(&'a self) -> &'a Self::Container;
    /// Grant mutable referential access to the container of this
    /// intrusive pointer type.
    fn as_container_mut<'a>(&'a mut self) -> &'a mut Self::Container;

    /// Assuming the "field" is a field in the container object, take
    /// ownership of the field as an intrusive pointer, allowing
    /// eventual translation back to the container. (Inverse of
    /// `into_field`.)
    unsafe fn from_field(OwnBox<Self::Field>) -> Self;

    /// Represent ownership of the container object as ownership of
    /// the intrusive field in the object. (Inverse of `from_field`.)
    unsafe fn into_field(self) -> OwnBox<Self::Field>;

    unsafe fn of_field<'a>(&'a Self::Field) -> BorrowBox<'a, Self>;
    unsafe fn of_field_mut<'a>(&'a mut Self::Field) -> BorrowBoxMut<'a, Self>;

    /// Grant referential access to the intrusive field represented by
    /// this intrusive pointer.
    fn as_field<'a>(&'a self) -> &'a Self::Field;

    /// Grant mutable referential access to the intrusive field represented by
    /// this intrusive pointer.
    fn as_field_mut<'a>(&'a mut self) -> &'a mut Self::Field;
}

impl<T: IntrusiveBase> Intrusive for T {
    #[inline]
    unsafe fn from_alias(ia: IntrusiveAlias) -> T {
        <T as IntrusiveBase>::new(ia)
    }
    #[inline]
    unsafe fn into_alias(self) -> IntrusiveAlias {
        *self.as_alias()
    }
    #[inline]
    unsafe fn as_alias<'a>(&'a self) -> &'a IntrusiveAlias {
        mem::transmute(self as *const _)
    }
    #[inline]
    unsafe fn as_alias_mut<'a>(&'a mut self) -> &'a mut IntrusiveAlias {
        mem::transmute(self as *const _)
    }
    #[inline]
    unsafe fn of_alias<'a>(ia: &'a IntrusiveAlias) -> &'a T {
        mem::transmute(ia as *const _)
    }
    #[inline]
    unsafe fn of_alias_mut<'a>(ia: &'a mut IntrusiveAlias) -> &'a mut T {
        mem::transmute(ia as *const _)
    }
    #[inline]
    fn from_container(c: OwnBox<T::Container>) -> Self {
        unsafe {
            let addr = c.as_alias().get_address() + <T as IntrusiveBase>::offset();
            mem::forget(c);
            <T as Intrusive>::from_alias(IntrusiveAlias(addr))
        }
    }
    #[inline]
    fn into_container(self) -> OwnBox<T::Container> {
        let fieldptr = unsafe { self.as_alias().get_address() };
        let containerptr = fieldptr - <T as IntrusiveBase>::offset();
        unsafe { OwnBox::from_alias(IntrusiveAlias::new(containerptr)) }
    }
    #[inline]
    fn of_container<'a>(container: &'a T::Container) -> BorrowBox<'a, T> {
        let addr = container as *const _ as usize;
        let fieldptr = addr + <T as IntrusiveBase>::offset();
        unsafe { BorrowBox::new_from(IntrusiveAlias::new(fieldptr), container) }
    }
    #[inline]
    fn of_container_mut<'a>(container: &'a mut T::Container) -> BorrowBoxMut<'a, T> {
        let addr = container as *mut _ as usize;
        let fieldptr = addr + <T as IntrusiveBase>::offset();
        unsafe { BorrowBoxMut::new_from(IntrusiveAlias::new(fieldptr), container) }
    }
    #[inline]
    fn as_container<'a>(&'a self) -> &'a T::Container {
        unsafe {
            let fieldptr = self.as_alias().get_address();
            let containerptr = fieldptr - <T as IntrusiveBase>::offset();
            &*(containerptr as *const T::Container)
        }
    }
    #[inline]
    fn as_container_mut<'a>(&'a mut self) -> &'a mut T::Container {
        unsafe { mem::transmute(self.as_container()) }
    }
    #[inline]
    unsafe fn from_field(c: OwnBox<T::Field>) -> T {
        let addr = c.as_alias().get_address();
        mem::forget(c);
        <T as Intrusive>::from_alias(IntrusiveAlias::new(addr))
    }
    #[inline]
    unsafe fn into_field(self) -> OwnBox<T::Field> {
        OwnBox::from_alias(IntrusiveAlias(self.as_alias().get_address()))
    }
    #[inline]
    unsafe fn of_field<'a>(field: &'a T::Field) -> BorrowBox<'a, T> {
        BorrowBox::new_from(IntrusiveAlias::new_of(field), field)
    }
    #[inline]
    unsafe fn of_field_mut<'a>(field: &'a mut T::Field) -> BorrowBoxMut<'a, T> {
        BorrowBoxMut::new_from(IntrusiveAlias::new_of(field), field)
    }
    #[inline]
    fn as_field<'a>(&'a self) -> &'a T::Field {
        unsafe { &*(self.as_alias().get_address() as *const _) }
    }
    #[inline]
    fn as_field_mut<'a>(&'a mut self) -> &'a mut T::Field {
        unsafe { &mut *(self.as_alias().get_address() as *mut _) }
    }
}
<commit_msg>added "public" intrusive-type definition.<commit_after>//! Intrusive structure support in Rust.
//!
//! An intrusive structure is a general-purpose structure directly
//! embedded within a containing structure, in order to add that
//! general-purpose facility to the container. As an example, one
//! might use an intrusive "link" structure to allow objects to be
//! organized in a linked-list:
//!
//! # Example
//!
//! ```test_harness
//! # #[macro_use]
//! # extern crate containerof;
//! # use containerof::*;
//! struct Link {
//!     next: Option<ContainerLink>,
//! }
//! struct List {
//!     head: Option<ContainerLink>,
//!     tail: Option<ContainerLink>,
//! }
//!
//! struct Container {
//!     link: Link,
//! }
//! containerof_intrusive!(ContainerLink = Container:link::Link);
//! ```

#![feature(unsafe_destructor)]
use std::ops;
use std::mem;
use std::marker;

/// Implement C-like `offsetof` macro in Rust. Will become obsolete
/// when-and-if offsetof() is implemented in the core language.
#[macro_export]
#[unstable = "Will go away if-and-when Rust implements this function directly."]
macro_rules! containerof_field_offset {
    ($container:ty : $field:ident) => (unsafe {
        &(*(0usize as *const $container)).$field as *const _ as usize
    })
}

#[macro_export]
#[unstable = "Experimental API."]
macro_rules! containerof_intrusive {
    ($nt:ident = $container:ty : $field:ident :: $fieldtype:ty) => (
        containerof_intrusive!(_decl $nt);
        containerof_intrusive!(_impl $nt = $container : $field :: $fieldtype);
        );
    (pub $nt:ident = $container:ty : $field:ident :: $fieldtype:ty) => (
        containerof_intrusive!(_decl pub $nt);
        containerof_intrusive!(_impl $nt = $container : $field :: $fieldtype);
        );
    (_decl $nt:ident) => (
        struct $nt($crate::IntrusiveAlias);
        );
    (_decl pub $nt:ident) => (
        pub struct $nt($crate::IntrusiveAlias);
        );
    (_impl $nt:ident = $container:ty : $field:ident :: $fieldtype:ty) => (
        impl $crate::IntrusiveBase for $nt {
            type Container = $container;
            type Field = $fieldtype;
            #[inline]
            fn offset() -> usize {
                containerof_field_offset!($container : $field)
            }
            #[inline]
            unsafe fn new(ia: $crate::IntrusiveAlias) -> $nt {
                $nt(ia)
            }
        }
        );
}

/// Alias that has the same representation as an intrusive type. The
/// idea is to be able to use this alias for intrusive facility
/// implementations, by defining the "true" implementation of the
/// facility to use the single (but type-unsafe) IntrusiveAlias type,
/// while allowing type-safe wrapper implementations to delegate their
/// behavior to the implementation function.
#[derive(PartialEq,Eq,Copy,Clone,Debug)]
#[unstable = "Experimental API"]
pub struct IntrusiveAlias(pub usize);
impl IntrusiveAlias {
    pub fn new(addr: usize) -> IntrusiveAlias {
        IntrusiveAlias(addr)
    }
    pub unsafe fn new_of<T>(addr: &T) -> IntrusiveAlias {
        IntrusiveAlias::new(addr as *const _ as usize)
    }
    pub fn get_address(&self) -> usize {
        self.0
    }
}

// FIXME: this wants to be a linear type.
#[unstable = "Experimental API"]
pub struct OwnBox<T> {
    pointer: IntrusiveAlias,
    marker: marker::PhantomData<T>,
}
impl<T> OwnBox<T> {
    pub fn get_address(&self) -> usize {
        self.pointer.0
    }
    pub unsafe fn from_alias(pointer: IntrusiveAlias) -> OwnBox<T> {
        OwnBox { pointer: pointer, marker: marker::PhantomData }
    }
    pub unsafe fn from_ref(p: &mut T) -> OwnBox<T> {
        OwnBox::from_alias(IntrusiveAlias::new_of(p))
    }
    pub unsafe fn into_alias(self) -> IntrusiveAlias {
        let rval = self.pointer;
        mem::forget(self);
        rval
    }
    pub fn as_alias<'a>(&'a self) -> &'a IntrusiveAlias {
        &self.pointer
    }
    pub unsafe fn from_box(b: Box<T>) -> OwnBox<T> {
        OwnBox { pointer: IntrusiveAlias::new(mem::transmute(b)), marker: marker::PhantomData }
    }
    pub unsafe fn into_box(self) -> Box<T> {
        mem::transmute(self.into_alias().get_address())
    }
}
impl<T> ops::Deref for OwnBox<T> {
    type Target = T;
    fn deref<'a>(&'a self) -> &'a T {
        unsafe { mem::transmute(self.get_address()) }
    }
}
impl<T> ops::DerefMut for OwnBox<T> {
    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
        unsafe { mem::transmute(self.get_address()) }
    }
}
#[unsafe_destructor]
impl<T> ops::Drop for OwnBox<T> {
    fn drop(&mut self) {
        // should have been consumed via "into_box" or "into_alias".
        //panic!("containerof::OwnBox should be treated as linear!");
    }
}

#[derive(Debug)]
pub struct BorrowBox<'a, T: 'a> {
    pointer: IntrusiveAlias,
    marker: marker::PhantomData<&'a T>,
}
impl<'a, T> BorrowBox<'a, T> where T: Intrusive {
    pub fn new(source: &'a T) -> BorrowBox<'a, T> {
        unsafe { BorrowBox::new_from(IntrusiveAlias::new_of(source), source) }
    }
    pub unsafe fn new_from<U>(pointer: IntrusiveAlias, _lifetime: &'a U) -> BorrowBox<'a, T> {
        BorrowBox {
            pointer: pointer,
            marker: marker::PhantomData,
        }
    }
    pub fn as_target<'b>(&'b self) -> &'b T where 'b: 'a {
        unsafe { Intrusive::of_alias(&self.pointer) }
    }
}

#[derive(Debug)]
pub struct BorrowBoxMut<'a, T: 'a> where T: Intrusive {
    pointer: IntrusiveAlias,
    marker: marker::PhantomData<&'a mut T>,
}
impl<'a, T> BorrowBoxMut<'a, T> where T: Intrusive {
    pub fn new(source: &'a mut T) -> BorrowBoxMut<'a, T> {
        unsafe { BorrowBoxMut::new_from(IntrusiveAlias::new_of(source), source) }
    }
    pub unsafe fn new_from<U>(pointer: IntrusiveAlias, _lifetime: &'a mut U) -> BorrowBoxMut<'a, T> {
        BorrowBoxMut {
            pointer: pointer,
            marker: marker::PhantomData,
        }
    }
    pub fn as_target<'b>(&'b self) -> &'b T where 'a: 'b {
        unsafe { Intrusive::of_alias(&self.pointer) }
    }
    pub fn as_target_mut<'b>(&'b mut self) -> &'b mut T where 'a: 'b {
        unsafe { Intrusive::of_alias_mut(&mut self.pointer) }
    }
}

#[unstable = "Experimental API"]
pub trait IntrusiveBase {
    /// Type of containing structure.
    type Container;
    /// Type of intrusive field within containing structure.
    type Field;
    // TODO: would also like to see an "offset" associated const, but
    // Rust doesn't seem to support these yet.
    /// Returns offset of intrusive field within containing structure.
    fn offset() -> usize;

    /// Ownership-moving translation from generic intrusive pointer
    /// alias to type-safe intrusive pointer.
    unsafe fn new(IntrusiveAlias) -> Self;
}

/// Trait defining routines for translation between containing
/// structure and intrusive field. The only implementors of this type
/// should be the pointer-types defined by the `containerof_intrusive`
/// macro.
#[unstable = "Experimental API"]
pub trait Intrusive: IntrusiveBase {
    /// Ownership-moving translation from generic intrusive pointer
    /// alias to type-safe intrusive pointer.
    unsafe fn from_alias(IntrusiveAlias) -> Self;

    /// Ownership-moving translation from type-safe intrusive pointer
    /// to generic intrusive pointer.
    unsafe fn into_alias(self) -> IntrusiveAlias;

    /// Allow using type-safe intrusive pointer as generic intrusive pointer.
    unsafe fn as_alias<'a>(&'a self) -> &'a IntrusiveAlias;

    /// Allow using type-safe intrusive pointer as mutable generic
    /// intrusive pointer.
    unsafe fn as_alias_mut<'a>(&'a mut self) -> &'a mut IntrusiveAlias;

    /// Allow using generic intrusive pointer as type-safe intrusive
    /// pointer.
    unsafe fn of_alias<'a>(&'a IntrusiveAlias) -> &'a Self;

    /// Allow using generic intrusive pointer as mutable type-safe
    /// intrusive pointer.
    unsafe fn of_alias_mut<'a>(ia: &'a mut IntrusiveAlias) -> &'a mut Self;

    /// Represent ownership of a container as ownership of an Intrusive
    /// pointer type. (Inverse of `into_container`.)
    fn from_container(OwnBox<Self::Container>) -> Self;

    /// Represent ownership of an Intrusive pointer type as ownership of
    /// its container. (Inverse of `from_container`.)
    fn into_container(self) -> OwnBox<Self::Container>;

    fn of_container<'a>(&'a Self::Container) -> BorrowBox<'a, Self>;
    fn of_container_mut<'a>(&'a mut Self::Container) -> BorrowBoxMut<'a, Self>;

    /// Grant referential access to the container of this intrusive
    /// pointer type.
    fn as_container<'a>(&'a self) -> &'a Self::Container;
    /// Grant mutable referential access to the container of this
    /// intrusive pointer type.
    fn as_container_mut<'a>(&'a mut self) -> &'a mut Self::Container;

    /// Assuming the "field" is a field in the container object, take
    /// ownership of the field as an intrusive pointer, allowing
    /// eventual translation back to the container. (Inverse of
    /// `into_field`.)
    unsafe fn from_field(OwnBox<Self::Field>) -> Self;

    /// Represent ownership of the container object as ownership of
    /// the intrusive field in the object. (Inverse of `from_field`.)
    unsafe fn into_field(self) -> OwnBox<Self::Field>;

    unsafe fn of_field<'a>(&'a Self::Field) -> BorrowBox<'a, Self>;
    unsafe fn of_field_mut<'a>(&'a mut Self::Field) -> BorrowBoxMut<'a, Self>;

    /// Grant referential access to the intrusive field represented by
    /// this intrusive pointer.
    fn as_field<'a>(&'a self) -> &'a Self::Field;

    /// Grant mutable referential access to the intrusive field represented by
    /// this intrusive pointer.
    fn as_field_mut<'a>(&'a mut self) -> &'a mut Self::Field;
}

impl<T: IntrusiveBase> Intrusive for T {
    #[inline]
    unsafe fn from_alias(ia: IntrusiveAlias) -> T {
        <T as IntrusiveBase>::new(ia)
    }
    #[inline]
    unsafe fn into_alias(self) -> IntrusiveAlias {
        *self.as_alias()
    }
    #[inline]
    unsafe fn as_alias<'a>(&'a self) -> &'a IntrusiveAlias {
        mem::transmute(self as *const _)
    }
    #[inline]
    unsafe fn as_alias_mut<'a>(&'a mut self) -> &'a mut IntrusiveAlias {
        mem::transmute(self as *const _)
    }
    #[inline]
    unsafe fn of_alias<'a>(ia: &'a IntrusiveAlias) -> &'a T {
        mem::transmute(ia as *const _)
    }
    #[inline]
    unsafe fn of_alias_mut<'a>(ia: &'a mut IntrusiveAlias) -> &'a mut T {
        mem::transmute(ia as *const _)
    }
    #[inline]
    fn from_container(c: OwnBox<T::Container>) -> Self {
        unsafe {
            let addr = c.as_alias().get_address() + <T as IntrusiveBase>::offset();
            mem::forget(c);
            <T as Intrusive>::from_alias(IntrusiveAlias(addr))
        }
    }
    #[inline]
    fn into_container(self) -> OwnBox<T::Container> {
        let fieldptr = unsafe { self.as_alias().get_address() };
        let containerptr = fieldptr - <T as IntrusiveBase>::offset();
        unsafe { OwnBox::from_alias(IntrusiveAlias::new(containerptr)) }
    }
    #[inline]
    fn of_container<'a>(container: &'a T::Container) -> BorrowBox<'a, T> {
        let addr = container as *const _ as usize;
        let fieldptr = addr + <T as IntrusiveBase>::offset();
        unsafe { BorrowBox::new_from(IntrusiveAlias::new(fieldptr), container) }
    }
    #[inline]
    fn of_container_mut<'a>(container: &'a mut T::Container) -> BorrowBoxMut<'a, T> {
        let addr = container as *mut _ as usize;
        let fieldptr = addr + <T as IntrusiveBase>::offset();
        unsafe { BorrowBoxMut::new_from(IntrusiveAlias::new(fieldptr), container) }
    }
    #[inline]
    fn as_container<'a>(&'a self) -> &'a T::Container {
        unsafe {
            let fieldptr = self.as_alias().get_address();
            let containerptr = fieldptr - <T as IntrusiveBase>::offset();
            &*(containerptr as *const T::Container)
        }
    }
    #[inline]
    fn as_container_mut<'a>(&'a mut self) -> &'a mut T::Container {
        unsafe { mem::transmute(self.as_container()) }
    }
    #[inline]
    unsafe fn from_field(c: OwnBox<T::Field>) -> T {
        let addr = c.as_alias().get_address();
        mem::forget(c);
        <T as Intrusive>::from_alias(IntrusiveAlias::new(addr))
    }
    #[inline]
    unsafe fn into_field(self) -> OwnBox<T::Field> {
        OwnBox::from_alias(IntrusiveAlias(self.as_alias().get_address()))
    }
    #[inline]
    unsafe fn of_field<'a>(field: &'a T::Field) -> BorrowBox<'a, T> {
        BorrowBox::new_from(IntrusiveAlias::new_of(field), field)
    }
    #[inline]
    unsafe fn of_field_mut<'a>(field: &'a mut T::Field) -> BorrowBoxMut<'a, T> {
        BorrowBoxMut::new_from(IntrusiveAlias::new_of(field), field)
    }
    #[inline]
    fn as_field<'a>(&'a self) -> &'a T::Field {
        unsafe { &*(self.as_alias().get_address() as *const _) }
    }
    #[inline]
    fn as_field_mut<'a>(&'a mut self) -> &'a mut T::Field {
        unsafe { &mut *(self.as_alias().get_address() as *mut _) }
    }
}
<|endoftext|>