<commit_before>#![no_std]

//! The `array-vec` crate allows you to initialize arrays
//! with an initializer closure that will be called
//! once for each element until the array is filled.
//!
//! This way you do not need to default-fill an array
//! before running initializers. Rust currently only
//! lets you either specify all initializers at once,
//! individually (`[a(), b(), c(), ...]`), or specify
//! one initializer for a `Copy` type (`[a(); N]`),
//! which will be called once with the result copied over.
//!
//! # Examples:
//! ```rust
//! # #![allow(unused)]
//! # extern crate array_init;
//!
//! // Initialize an array of length 10 containing
//! // successive squares
//!
//! let arr: [u32; 50] = array_init::array_init(|i| (i*i) as u32);
//!
//! // Initialize an array from an iterator
//! // producing an array of [1,2,3,4] repeated
//!
//! let four = [1u32,2,3,4];
//! let mut iter = four.iter().cloned().cycle();
//! let arr: [u32; 50] = array_init::from_iter(iter).unwrap();
//!
//! // Closures can also mutate state. We guarantee that they will be called
//! // in order from lower to higher indices.
//!
//! let mut last = 1u64;
//! let mut secondlast = 0;
//! let fibonacci: [u64; 50] = array_init::array_init(|_| {
//!     let this = last + secondlast;
//!     secondlast = last;
//!     last = this;
//!     this
//! });
//! ```
//!
//! Currently, using `from_iter` and `array_init` will incur additional
//! memcpys, which may be undesirable for a large array. This can be eliminated
//! by using the nightly feature of this crate, which uses unions to provide
//! panic-safety. Alternatively, if your array only contains `Copy` types,
//! you can use `array_init_copy` and `from_iter_copy`.
//!
//! Sadly, cannot guarantee right now that any of these solutions will completely
//! eliminate a memcpy.
//!

extern crate nodrop;

use nodrop::NoDrop;
use core::mem;

/// Trait for things which are actually arrays
///
/// Probably shouldn't implement this yourself,
/// but you can
pub unsafe trait IsArray {
    type Item;
    /// Must assume self is uninitialized.
    fn set(&mut self, idx: usize, value: Self::Item);
    fn len() -> usize;
}

#[inline]
/// Initialize an array given an initializer expression
///
/// The initializer is given the index of the element. It is allowed
/// to mutate external state; we will always initialize the elements in order.
///
/// Without the nightly feature it is very likely that this will cause memcpys.
/// For panic safety, we internally use NoDrop, which will ensure that panics
/// in the initializer will not cause the array to be prematurely dropped.
/// If you are using a Copy type, prefer using `array_init_copy` since
/// it does not need the panic safety stuff and is more likely to have no
/// memcpys.
///
/// If your initializer panics, any elements that have been initialized
/// will be leaked.
///
/// # Examples
///
/// ```rust
/// # #![allow(unused)]
/// # extern crate array_init;
///
/// // Initialize an array of length 10 containing
/// // successive squares
///
/// let arr: [u32; 50] = array_init::array_init(|i| (i*i) as u32);
///
/// // Initialize an array from an iterator
/// // producing an array of [1,2,3,4] repeated
///
/// let four = [1u32,2,3,4];
/// let mut iter = four.iter().cloned().cycle();
/// let arr: [u32; 50] = array_init::from_iter(iter).unwrap();
///
/// ```
///
pub fn array_init<Array, F>(mut initializer: F) -> Array where Array: IsArray,
                                                               F: FnMut(usize) -> Array::Item {
    // NoDrop makes this panic-safe
    // We are sure to initialize the whole array here,
    // and we do not read from the array till then, so this is safe.
    let mut ret: NoDrop<Array> = NoDrop::new(unsafe { mem::uninitialized() });
    for i in 0..Array::len() {
        Array::set(&mut ret, i, initializer(i));
    }
    ret.into_inner()
}

#[inline]
/// Initialize an array given an iterator
///
/// We will iterate until the array is full or the iterator is exhausted. Returns
/// None if the iterator is exhausted before we can fill the array.
///
/// Without the nightly feature it is very likely that this will cause memcpys.
/// For panic safety, we internally use NoDrop, which will ensure that panics
/// in the initializer will not cause the array to be prematurely dropped.
/// If you are using a Copy type, prefer using `from_iter_copy` since
/// it does not need the panic safety stuff and is more likely to have no
/// memcpys.
///
/// # Examples
///
/// ```rust
/// # #![allow(unused)]
/// # extern crate array_init;
///
/// // Initialize an array from an iterator
/// // producing an array of [1,2,3,4] repeated
///
/// let four = [1u32,2,3,4];
/// let mut iter = four.iter().cloned().cycle();
/// let arr: [u32; 50] = array_init::from_iter_copy(iter).unwrap();
/// ```
///
pub fn from_iter<Array, I>(iter: I) -> Option<Array>
    where I: IntoIterator<Item = Array::Item>,
          Array: IsArray {
    // NoDrop makes this panic-safe
    // We are sure to initialize the whole array here,
    // and we do not read from the array till then, so this is safe.
    let mut ret: NoDrop<Array> = NoDrop::new(unsafe { mem::uninitialized() });
    let mut count = 0;
    for item in iter.into_iter().take(Array::len()) {
        Array::set(&mut ret, count, item);
        count += 1;
    }
    // crucial for safety!
    if count == Array::len() {
        Some(ret.into_inner())
    } else {
        None
    }
}

#[inline]
/// Initialize an array of `Copy` elements given an initializer expression
///
/// The initializer is given the index of the element. It is allowed
/// to mutate external state; we will always initialize the elements in order.
///
/// This is preferred over `array_init` if you have a `Copy` type
///
/// # Examples
///
/// ```rust
/// # #![allow(unused)]
/// # extern crate array_init;
///
/// // Initialize an array of length 10 containing
/// // successive squares
///
/// let arr: [u32; 50] = array_init::array_init_copy(|i| (i*i) as u32);
///
///
/// // Closures can also mutate state. We guarantee that they will be called
/// // in order from lower to higher indices.
///
/// let mut last = 1u64;
/// let mut secondlast = 0;
/// let fibonacci: [u64; 50] = array_init::array_init_copy(|_| {
///     let this = last + secondlast;
///     secondlast = last;
///     last = this;
///     this
/// });
/// ```
///
pub fn array_init_copy<Array, F>(mut initializer: F) -> Array where Array: IsArray,
                                                                    F: FnMut(usize) -> Array::Item,
                                                                    Array::Item : Copy {
    // We are sure to initialize the whole array here,
    // and we do not read from the array till then, so this is safe.
    let mut ret: Array = unsafe { mem::uninitialized() };
    for i in 0..Array::len() {
        Array::set(&mut ret, i, initializer(i));
    }
    ret
}

#[inline]
/// Initialize an array given an iterator
///
/// We will iterate until the array is full or the iterator is exhausted. Returns
/// None if the iterator is exhausted before we can fill the array.
///
/// This is preferred over `from_iter_copy` if you have a `Copy` type
///
/// # Examples
///
/// ```rust
/// # #![allow(unused)]
/// # extern crate array_init;
///
/// // Initialize an array from an iterator
/// // producing an array of [1,2,3,4] repeated
///
/// let four = [1u32,2,3,4];
/// let mut iter = four.iter().cloned().cycle();
/// let arr: [u32; 50] = array_init::from_iter_copy(iter).unwrap();
/// ```
pub fn from_iter_copy<Array, I>(iter: I) -> Option<Array>
    where I: IntoIterator<Item = Array::Item>,
          Array: IsArray,
          Array::Item : Copy {
    // We are sure to initialize the whole array here,
    // and we do not read from the array till then, so this is safe.
    let mut ret: Array = unsafe { mem::uninitialized() };
    let mut count = 0;
    for item in iter.into_iter().take(Array::len()) {
        Array::set(&mut ret, count, item);
        count += 1;
    }
    // crucial for safety!
    if count == Array::len() {
        Some(ret)
    } else {
        None
    }
}

macro_rules! impl_is_array {
    ($($size:expr)+) => ($(
        unsafe impl<T> IsArray for [T; $size] {
            type Item = T;
            #[inline]
            fn set(&mut self, idx: usize, value: Self::Item) {
                mem::forget(mem::replace(&mut self[idx], value));
            }

            #[inline]
            fn len() -> usize {
                $size
            }
        }
    )+)
}

// lol

impl_is_array! {
     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
    16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
    32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
    48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
    64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
    80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    96 97 98 99 100 101 102 103 104 105 106 107 108
    109 110 111 112 113 114 115 116 117 118 119 120
    121 122 123 124 125 126 127 128
}
<commit_msg>Extended is_array! call up to 512<commit_after>#![no_std]

//! The `array-vec` crate allows you to initialize arrays
//! with an initializer closure that will be called
//! once for each element until the array is filled.
//!
//! This way you do not need to default-fill an array
//! before running initializers. Rust currently only
//! lets you either specify all initializers at once,
//! individually (`[a(), b(), c(), ...]`), or specify
//! one initializer for a `Copy` type (`[a(); N]`),
//! which will be called once with the result copied over.
//!
//! # Examples:
//! ```rust
//! # #![allow(unused)]
//! # extern crate array_init;
//!
//! // Initialize an array of length 10 containing
//! // successive squares
//!
//! let arr: [u32; 50] = array_init::array_init(|i| (i*i) as u32);
//!
//! // Initialize an array from an iterator
//! // producing an array of [1,2,3,4] repeated
//!
//! let four = [1u32,2,3,4];
//! let mut iter = four.iter().cloned().cycle();
//! let arr: [u32; 50] = array_init::from_iter(iter).unwrap();
//!
//! // Closures can also mutate state. We guarantee that they will be called
//! // in order from lower to higher indices.
//!
//! let mut last = 1u64;
//! let mut secondlast = 0;
//! let fibonacci: [u64; 50] = array_init::array_init(|_| {
//!     let this = last + secondlast;
//!     secondlast = last;
//!     last = this;
//!     this
//! });
//! ```
//!
//! Currently, using `from_iter` and `array_init` will incur additional
//! memcpys, which may be undesirable for a large array. This can be eliminated
//! by using the nightly feature of this crate, which uses unions to provide
//! panic-safety. Alternatively, if your array only contains `Copy` types,
//! you can use `array_init_copy` and `from_iter_copy`.
//!
//! Sadly, cannot guarantee right now that any of these solutions will completely
//! eliminate a memcpy.
//!

extern crate nodrop;

use nodrop::NoDrop;
use core::mem;

/// Trait for things which are actually arrays
///
/// Probably shouldn't implement this yourself,
/// but you can
pub unsafe trait IsArray {
    type Item;
    /// Must assume self is uninitialized.
    fn set(&mut self, idx: usize, value: Self::Item);
    fn len() -> usize;
}

#[inline]
/// Initialize an array given an initializer expression
///
/// The initializer is given the index of the element. It is allowed
/// to mutate external state; we will always initialize the elements in order.
///
/// Without the nightly feature it is very likely that this will cause memcpys.
/// For panic safety, we internally use NoDrop, which will ensure that panics
/// in the initializer will not cause the array to be prematurely dropped.
/// If you are using a Copy type, prefer using `array_init_copy` since
/// it does not need the panic safety stuff and is more likely to have no
/// memcpys.
///
/// If your initializer panics, any elements that have been initialized
/// will be leaked.
///
/// # Examples
///
/// ```rust
/// # #![allow(unused)]
/// # extern crate array_init;
///
/// // Initialize an array of length 10 containing
/// // successive squares
///
/// let arr: [u32; 50] = array_init::array_init(|i| (i*i) as u32);
///
/// // Initialize an array from an iterator
/// // producing an array of [1,2,3,4] repeated
///
/// let four = [1u32,2,3,4];
/// let mut iter = four.iter().cloned().cycle();
/// let arr: [u32; 50] = array_init::from_iter(iter).unwrap();
///
/// ```
///
pub fn array_init<Array, F>(mut initializer: F) -> Array where Array: IsArray,
                                                               F: FnMut(usize) -> Array::Item {
    // NoDrop makes this panic-safe
    // We are sure to initialize the whole array here,
    // and we do not read from the array till then, so this is safe.
    let mut ret: NoDrop<Array> = NoDrop::new(unsafe { mem::uninitialized() });
    for i in 0..Array::len() {
        Array::set(&mut ret, i, initializer(i));
    }
    ret.into_inner()
}

#[inline]
/// Initialize an array given an iterator
///
/// We will iterate until the array is full or the iterator is exhausted. Returns
/// None if the iterator is exhausted before we can fill the array.
///
/// Without the nightly feature it is very likely that this will cause memcpys.
/// For panic safety, we internally use NoDrop, which will ensure that panics
/// in the initializer will not cause the array to be prematurely dropped.
/// If you are using a Copy type, prefer using `from_iter_copy` since
/// it does not need the panic safety stuff and is more likely to have no
/// memcpys.
///
/// # Examples
///
/// ```rust
/// # #![allow(unused)]
/// # extern crate array_init;
///
/// // Initialize an array from an iterator
/// // producing an array of [1,2,3,4] repeated
///
/// let four = [1u32,2,3,4];
/// let mut iter = four.iter().cloned().cycle();
/// let arr: [u32; 50] = array_init::from_iter_copy(iter).unwrap();
/// ```
///
pub fn from_iter<Array, I>(iter: I) -> Option<Array>
    where I: IntoIterator<Item = Array::Item>,
          Array: IsArray {
    // NoDrop makes this panic-safe
    // We are sure to initialize the whole array here,
    // and we do not read from the array till then, so this is safe.
    let mut ret: NoDrop<Array> = NoDrop::new(unsafe { mem::uninitialized() });
    let mut count = 0;
    for item in iter.into_iter().take(Array::len()) {
        Array::set(&mut ret, count, item);
        count += 1;
    }
    // crucial for safety!
    if count == Array::len() {
        Some(ret.into_inner())
    } else {
        None
    }
}

#[inline]
/// Initialize an array of `Copy` elements given an initializer expression
///
/// The initializer is given the index of the element. It is allowed
/// to mutate external state; we will always initialize the elements in order.
///
/// This is preferred over `array_init` if you have a `Copy` type
///
/// # Examples
///
/// ```rust
/// # #![allow(unused)]
/// # extern crate array_init;
///
/// // Initialize an array of length 10 containing
/// // successive squares
///
/// let arr: [u32; 50] = array_init::array_init_copy(|i| (i*i) as u32);
///
///
/// // Closures can also mutate state. We guarantee that they will be called
/// // in order from lower to higher indices.
///
/// let mut last = 1u64;
/// let mut secondlast = 0;
/// let fibonacci: [u64; 50] = array_init::array_init_copy(|_| {
///     let this = last + secondlast;
///     secondlast = last;
///     last = this;
///     this
/// });
/// ```
///
pub fn array_init_copy<Array, F>(mut initializer: F) -> Array where Array: IsArray,
                                                                    F: FnMut(usize) -> Array::Item,
                                                                    Array::Item : Copy {
    // We are sure to initialize the whole array here,
    // and we do not read from the array till then, so this is safe.
    let mut ret: Array = unsafe { mem::uninitialized() };
    for i in 0..Array::len() {
        Array::set(&mut ret, i, initializer(i));
    }
    ret
}

#[inline]
/// Initialize an array given an iterator
///
/// We will iterate until the array is full or the iterator is exhausted. Returns
/// None if the iterator is exhausted before we can fill the array.
///
/// This is preferred over `from_iter_copy` if you have a `Copy` type
///
/// # Examples
///
/// ```rust
/// # #![allow(unused)]
/// # extern crate array_init;
///
/// // Initialize an array from an iterator
/// // producing an array of [1,2,3,4] repeated
///
/// let four = [1u32,2,3,4];
/// let mut iter = four.iter().cloned().cycle();
/// let arr: [u32; 50] = array_init::from_iter_copy(iter).unwrap();
/// ```
pub fn from_iter_copy<Array, I>(iter: I) -> Option<Array>
    where I: IntoIterator<Item = Array::Item>,
          Array: IsArray,
          Array::Item : Copy {
    // We are sure to initialize the whole array here,
    // and we do not read from the array till then, so this is safe.
    let mut ret: Array = unsafe { mem::uninitialized() };
    let mut count = 0;
    for item in iter.into_iter().take(Array::len()) {
        Array::set(&mut ret, count, item);
        count += 1;
    }
    // crucial for safety!
    if count == Array::len() {
        Some(ret)
    } else {
        None
    }
}

macro_rules! impl_is_array {
    ($($size:expr)+) => ($(
        unsafe impl<T> IsArray for [T; $size] {
            type Item = T;
            #[inline]
            fn set(&mut self, idx: usize, value: Self::Item) {
                mem::forget(mem::replace(&mut self[idx], value));
            }

            #[inline]
            fn len() -> usize {
                $size
            }
        }
    )+)
}

// lol

impl_is_array! {
     0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
    16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
    32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47
    48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
    64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
    80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    96 97 98 99 100 101 102 103 104 105 106 107 108
    109 110 111 112 113 114 115 116 117 118 119 120
    121 122 123 124 125 126 127 128 129 130 131 132
    133 134 135 136 137 138 139 140 141 142 143 144
    145 146 147 148 149 150 151 152 153 154 155 156
    157 158 159 160 161 162 163 164 165 166 167 168
    169 170 171 172 173 174 175 176 177 178 179 180
    181 182 183 184 185 186 187 188 189 190 191 192
    193 194 195 196 197 198 199 200 201 202 203 204
    205 206 207 208 209 210 211 212 213 214 215 216
    217 218 219 220 221 222 223 224 225 226 227 228
    229 230 231 232 233 234 235 236 237 238 239 240
    241 242 243 244 245 246 247 248 249 250 251 252
    253 254 255 256 257 258 259 260 261 262 263 264
    265 266 267 268 269 270 271 272 273 274 275 276
    277 278 279 280 281 282 283 284 285 286 287 288
    289 290 291 292 293 294 295 296 297 298 299 300
    301 302 303 304 305 306 307 308 309 310 311 312
    313 314 315 316 317 318 319 320 321 322 323 324
    325 326 327 328 329 330 331 332 333 334 335 336
    337 338 339 340 341 342 343 344 345 346 347 348
    349 350 351 352 353 354 355 356 357 358 359 360
    361 362 363 364 365 366 367 368 369 370 371 372
    373 374 375 376 377 378 379 380 381 382 383 384
    385 386 387 388 389 390 391 392 393 394 395 396
    397 398 399 400 401 402 403 404 405 406 407 408
    409 410 411 412 413 414 415 416 417 418 419 420
    421 422 423 424 425 426 427 428 429 430 431 432
    433 434 435 436 437 438 439 440 441 442 443 444
    445 446 447 448 449 450 451 452 453 454 455 456
    457 458 459 460 461 462 463 464 465 466 467 468
    469 470 471 472 473 474 475 476 477 478 479 480
    481 482 483 484 485 486 487 488 489 490 491 492
    493 494 495 496 497 498 499 500 501 502 503 504
    505 506 507 508 509 510 511 512
}
<|endoftext|>


<commit_before>#![feature(step_by)]

extern crate libc;
pub extern crate nix;
#[macro_use] extern crate bitflags;

use nix::sys::ptrace;
pub use nix::sys::ptrace::ptrace::*;
use nix::sys::signal;
use std::ptr;
use std::default::Default;
use std::vec::Vec;
use std::mem;

pub type Address = usize;
pub type Word = usize;

#[derive(Clone, Copy, Default, Debug)]
pub struct Registers {
    pub r15: Word,
    pub r14: Word,
    pub r13: Word,
    pub r12: Word,
    pub rbp: Word,
    pub rbx: Word,
    pub r11: Word,
    pub r10: Word,
    pub r9: Word,
    pub r8: Word,
    pub rax: Word,
    pub rcx: Word,
    pub rdx: Word,
    pub rsi: Word,
    pub rdi: Word,
    pub orig_rax: Word,
    pub rip: Word,
    pub cs: Word,
    pub eflags: Word,
    pub rsp: Word,
    pub ss: Word,
    pub fs_base: Word,
    pub gs_base: Word,
    pub ds: Word,
    pub es: Word,
    pub fs: Word,
    pub gs: Word
}

fn ptrace_raw(request: PtraceRequest, pid: libc::pid_t, addr: *mut libc::c_void, data: *mut libc::c_void) -> Result<libc::c_long, i32> {
    match ptrace::ptrace(request, pid, addr, data) {
        Ok(v) => Ok(v),
        Err(e) => match e {
            nix::Error::Sys(errno) => Err(errno as i32),
            nix::Error::InvalidPath => panic!("nix InvalidPath caught"),
        },
    }
}
pub fn setoptions(pid: libc::pid_t, options: PtraceOptions) -> Result<(), i32> {
    match ptrace::ptrace_setoptions(pid, options) {
        Ok(v) => Ok(v),
        Err(e) => match e {
            nix::Error::Sys(errno) => Err(errno as i32),
            nix::Error::InvalidPath => panic!("nix InvalidPath caught"),
        },
    }
}

pub fn getregs(pid: libc::pid_t) -> Result<Registers, i32> {
    let mut buf: Registers = Default::default();
    let buf_mut: *mut Registers = &mut buf;

    match ptrace_raw(PTRACE_GETREGS, pid, ptr::null_mut(), buf_mut as *mut libc::c_void) {
        Ok(_) => Ok(buf),
        Err(e) => Err(e)
    }
}

pub fn setregs(pid: libc::pid_t, regs: &Registers) -> Result<libc::c_long, i32> {
    let buf: *mut libc::c_void = unsafe { mem::transmute(regs) };
    ptrace_raw(PTRACE_SETREGS, pid, ptr::null_mut(), buf)
}

pub fn seize(pid: libc::pid_t) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_SEIZE, pid, ptr::null_mut(), ptr::null_mut())
}

pub fn attach(pid: libc::pid_t) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_ATTACH, pid, ptr::null_mut(), ptr::null_mut())
}

pub fn release(pid: libc::pid_t, signal: Option<signal::Signal>) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_DETACH, pid, ptr::null_mut(), signal.map_or(0, |s| s as u32) as *mut libc::c_void)
}

pub fn cont(pid: libc::pid_t, signal: Option<signal::Signal>) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_CONT, pid, ptr::null_mut(), signal.map_or(0, |s| s as u32) as *mut libc::c_void)
}

pub fn cont_syscall(pid: libc::pid_t, signal: Option<signal::Signal>) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_SYSCALL, pid, ptr::null_mut(), signal.map_or(0, |s| s as u32) as *mut libc::c_void)
}

pub fn traceme() -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_TRACEME, 0, ptr::null_mut(), ptr::null_mut())
}

#[derive(Clone, Copy, Debug)]
pub struct Syscall {
    pub args: [Word; 6],
    pub call: Word,
    pub pid: libc::pid_t,
    pub return_val: Word
}

impl Syscall {
    pub fn from_pid(pid: libc::pid_t) -> Result<Syscall, i32> {
        match getregs(pid) {
            Ok(regs) =>
                Ok(Syscall {
                    pid: pid,
                    call: regs.orig_rax,
                    args: [regs.rdi, regs.rsi, regs.rdx, regs.rcx, regs.r8, regs.r9],
                    return_val: 0
                }),
            Err(e) => Err(e)
        }
    }

    pub fn write(&self) -> Result<libc::c_long, i32> {
        match getregs(self.pid) {
            Ok(mut regs) => {
                regs.rdi = self.args[0];
                regs.rsi = self.args[1];
                regs.rdx = self.args[2];
                regs.rcx = self.args[3];
                regs.r8 = self.args[4];
                regs.r9 = self.args[5];
                regs.orig_rax = self.call;
                regs.rax = self.return_val;
                setregs(self.pid, &regs)
            },
            Err(e) => Err(e)
        }
    }
}

#[derive(Clone, Copy)]
pub struct Reader {
    pub pid: libc::pid_t
}

#[derive(Clone, Copy)]
pub struct Writer {
    pub pid: libc::pid_t
}

impl Writer {
    pub fn new(pid: libc::pid_t) -> Self {
        Writer {
            pid: pid
        }
    }

    pub fn poke_data(&self, address: Address, data: Word) -> Result<Word, i32> {
        match ptrace_raw(PTRACE_POKEDATA, self.pid, address as *mut libc::c_void,
                             data as *mut libc::c_void) {
            Err(e) => Err(e),
            Ok(r) => Ok(r as Word)
        }
    }

    pub fn write_object<T: Sized>(&self, address: Address, data: &T) -> Result<(), usize> {
        let mut buf = Vec::with_capacity(mem::size_of::<T>());
        unsafe {
            let tptr: *const T = data;
            let p: *const u8 = mem::transmute(tptr);
            for i in 0..buf.capacity() {
                buf.push(*p.offset(i as isize));
            }
        }

        Ok(())
    }

    pub fn write_data(&self, address: Address, buf: &Vec<u8>) -> Result<(), i32> {
        // The end of our range
        let max_addr = address + buf.len() as Address;
        // The last word we can completely overwrite
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        for write_addr in (address..align_end).step_by(mem::size_of::<Word>() as Address) {
            let mut d: Word = 0;
            let buf_idx = (write_addr - address) as usize;
            for word_idx in 0..mem::size_of::<Word>() {
                d = set_byte(d, word_idx, buf[buf_idx + word_idx]);
            }
            match self.poke_data(write_addr, d) {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }
        // Handle a partial word overwrite
        if max_addr > align_end {
            let buf_start = buf.len() - (max_addr - align_end) as usize;
            let r = Reader::new(self.pid);
            let mut d = match r.peek_data(align_end) {
                Ok(v) => v,
                Err(e) => return Err(e)
            };
            for word_idx in 0..mem::size_of::<Word>() - 2 {
                let buf_idx = buf_start + word_idx;
                d = set_byte(d, word_idx, buf[buf_idx]);
            }
            match self.poke_data(align_end, d) {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }
        Ok(())
    }
}

impl Reader {
    pub fn new(pid: libc::pid_t) -> Reader {
        Reader {
            pid: pid
        }
    }

    pub fn peek_data(&self, address: Address) -> Result<Word, i32> {
        match ptrace_raw(PTRACE_PEEKDATA, self.pid, address as *mut libc::c_void, ptr::null_mut()) {
            Ok(v) => Ok(v as Word),
            Err(e) => Err(e),
        }
    }

    pub fn read_string(&self, address: Address) -> Result<Vec<u8>, i32> {
        let mut end_of_str = false;
        let mut buf: Vec<u8> = Vec::with_capacity(1024);
        let max_addr = address + buf.capacity() as Address;
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        'finish: for read_addr in (address..align_end).step_by(mem::size_of::<Word>() as Address) {
            let d;
            match self.peek_data(read_addr) {
                Ok(v) => d = v,
                Err(e) => return Err(e)
            }
            for word_idx in 0..mem::size_of::<Word>() {
                let chr = get_byte(d, word_idx);
                if chr == 0 {
                    end_of_str = true;
                    break 'finish;
                }
                buf.push(chr);
            }
        }
        if !end_of_str {
            let d;
            match self.peek_data(align_end) {
                Ok(v) => d = v,
                Err(e) => return Err(e)
            }
            for word_idx in 0..mem::size_of::<Word>() {
                let chr = get_byte(d, word_idx);
                if chr == 0 {
                    break;
                }
                buf.push(chr);
            }
        }
        return Ok(buf);
    }
}

fn get_byte(d: Word, byte_idx: usize) -> u8 {
    assert!(byte_idx < mem::size_of::<Word>());
    ((d >> (byte_idx * 8)) & 0xff) as u8
}

fn set_byte(d: Word, byte_idx: usize, value: u8) -> Word {
    assert!(byte_idx < mem::size_of::<Word>());
    let shift = mem::size_of::<u8>() * 8 * byte_idx;
    let mask = 0xff << shift;
    (d & !mask) | (((value as Word) << shift) & mask)
}

#[test]
pub fn test_set_byte() {
    assert_eq!(set_byte(0, 0, 0), 0);
    assert_eq!(set_byte(0xffffffffffff, 0, 0xff), 0xffffffffffff);
    assert_eq!(set_byte(0xffffffffffff, 0, 0),    0xffffffffff00);
    assert_eq!(set_byte(0xffffffffffff, 0, 0xaa), 0xffffffffffaa);
    assert_eq!(set_byte(0xffffffffffff, 1, 0x00), 0xffffffff00ff);
    assert_eq!(set_byte(0xffffffffffff, 4, 0xaa), 0xffaaffffffff);
}

#[test]
pub fn test_get_byte() {
    assert_eq!(get_byte(0, 0), 0);
    assert_eq!(get_byte(0xffffffffffff, 0), 0xff);
    assert_eq!(get_byte(0xffffffffffaa, 0), 0xaa);
    assert_eq!(get_byte(0x0123456789ab, 1), 0x89);
    assert_eq!(get_byte(0x0123456789ab, 4), 0x23);
}
<commit_msg>Implement return value for syscalls<commit_after>#![feature(step_by)]

extern crate libc;
pub extern crate nix;
#[macro_use] extern crate bitflags;

use nix::sys::ptrace;
pub use nix::sys::ptrace::ptrace::*;
use nix::sys::signal;
use std::ptr;
use std::default::Default;
use std::vec::Vec;
use std::mem;

pub type Address = usize;
pub type Word = usize;
pub type IWord = isize;

#[derive(Clone, Copy, Default, Debug)]
pub struct Registers {
    pub r15: Word,
    pub r14: Word,
    pub r13: Word,
    pub r12: Word,
    pub rbp: Word,
    pub rbx: Word,
    pub r11: Word,
    pub r10: Word,
    pub r9: Word,
    pub r8: Word,
    pub rax: Word,
    pub rcx: Word,
    pub rdx: Word,
    pub rsi: Word,
    pub rdi: Word,
    pub orig_rax: Word,
    pub rip: Word,
    pub cs: Word,
    pub eflags: Word,
    pub rsp: Word,
    pub ss: Word,
    pub fs_base: Word,
    pub gs_base: Word,
    pub ds: Word,
    pub es: Word,
    pub fs: Word,
    pub gs: Word
}

fn ptrace_raw(request: PtraceRequest, pid: libc::pid_t, addr: *mut libc::c_void, data: *mut libc::c_void) -> Result<libc::c_long, i32> {
    match ptrace::ptrace(request, pid, addr, data) {
        Ok(v) => Ok(v),
        Err(e) => match e {
            nix::Error::Sys(errno) => Err(errno as i32),
            nix::Error::InvalidPath => panic!("nix InvalidPath caught"),
        },
    }
}
pub fn setoptions(pid: libc::pid_t, options: PtraceOptions) -> Result<(), i32> {
    match ptrace::ptrace_setoptions(pid, options) {
        Ok(v) => Ok(v),
        Err(e) => match e {
            nix::Error::Sys(errno) => Err(errno as i32),
            nix::Error::InvalidPath => panic!("nix InvalidPath caught"),
        },
    }
}

pub fn getregs(pid: libc::pid_t) -> Result<Registers, i32> {
    let mut buf: Registers = Default::default();
    let buf_mut: *mut Registers = &mut buf;

    match ptrace_raw(PTRACE_GETREGS, pid, ptr::null_mut(), buf_mut as *mut libc::c_void) {
        Ok(_) => Ok(buf),
        Err(e) => Err(e)
    }
}

pub fn setregs(pid: libc::pid_t, regs: &Registers) -> Result<libc::c_long, i32> {
    let buf: *mut libc::c_void = unsafe { mem::transmute(regs) };
    ptrace_raw(PTRACE_SETREGS, pid, ptr::null_mut(), buf)
}

pub fn seize(pid: libc::pid_t) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_SEIZE, pid, ptr::null_mut(), ptr::null_mut())
}

pub fn attach(pid: libc::pid_t) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_ATTACH, pid, ptr::null_mut(), ptr::null_mut())
}

pub fn release(pid: libc::pid_t, signal: Option<signal::Signal>) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_DETACH, pid, ptr::null_mut(), signal.map_or(0, |s| s as u32) as *mut libc::c_void)
}

pub fn cont(pid: libc::pid_t, signal: Option<signal::Signal>) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_CONT, pid, ptr::null_mut(), signal.map_or(0, |s| s as u32) as *mut libc::c_void)
}

pub fn cont_syscall(pid: libc::pid_t, signal: Option<signal::Signal>) -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_SYSCALL, pid, ptr::null_mut(), signal.map_or(0, |s| s as u32) as *mut libc::c_void)
}

pub fn traceme() -> Result<libc::c_long, i32> {
    ptrace_raw(PTRACE_TRACEME, 0, ptr::null_mut(), ptr::null_mut())
}

#[derive(Clone, Copy, Debug)]
pub struct Syscall {
    pub args: [Word; 6],
    pub call: Word,
    pub pid: libc::pid_t,
    pub return_val: IWord
}

impl Syscall {
    pub fn from_pid(pid: libc::pid_t) -> Result<Syscall, i32> {
        match getregs(pid) {
            Ok(regs) =>
                Ok(Syscall {
                    pid: pid,
                    call: regs.orig_rax,
                    args: [regs.rdi, regs.rsi, regs.rdx, regs.rcx, regs.r8, regs.r9],
                    return_val: regs.rax as IWord
                }),
            Err(e) => Err(e)
        }
    }

    pub fn write(&self) -> Result<libc::c_long, i32> {
        match getregs(self.pid) {
            Ok(mut regs) => {
                regs.rdi = self.args[0];
                regs.rsi = self.args[1];
                regs.rdx = self.args[2];
                regs.rcx = self.args[3];
                regs.r8 = self.args[4];
                regs.r9 = self.args[5];
                regs.orig_rax = self.call;
                regs.rax = self.return_val as Word;
                setregs(self.pid, &regs)
            },
            Err(e) => Err(e)
        }
    }
}

#[derive(Clone, Copy)]
pub struct Reader {
    pub pid: libc::pid_t
}

#[derive(Clone, Copy)]
pub struct Writer {
    pub pid: libc::pid_t
}

impl Writer {
    pub fn new(pid: libc::pid_t) -> Self {
        Writer {
            pid: pid
        }
    }

    pub fn poke_data(&self, address: Address, data: Word) -> Result<Word, i32> {
        match ptrace_raw(PTRACE_POKEDATA, self.pid, address as *mut libc::c_void,
                             data as *mut libc::c_void) {
            Err(e) => Err(e),
            Ok(r) => Ok(r as Word)
        }
    }

    pub fn write_object<T: Sized>(&self, address: Address, data: &T) -> Result<(), usize> {
        let mut buf = Vec::with_capacity(mem::size_of::<T>());
        unsafe {
            let tptr: *const T = data;
            let p: *const u8 = mem::transmute(tptr);
            for i in 0..buf.capacity() {
                buf.push(*p.offset(i as isize));
            }
        }

        Ok(())
    }

    pub fn write_data(&self, address: Address, buf: &Vec<u8>) -> Result<(), i32> {
        // The end of our range
        let max_addr = address + buf.len() as Address;
        // The last word we can completely overwrite
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        for write_addr in (address..align_end).step_by(mem::size_of::<Word>() as Address) {
            let mut d: Word = 0;
            let buf_idx = (write_addr - address) as usize;
            for word_idx in 0..mem::size_of::<Word>() {
                d = set_byte(d, word_idx, buf[buf_idx + word_idx]);
            }
            match self.poke_data(write_addr, d) {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }
        // Handle a partial word overwrite
        if max_addr > align_end {
            let buf_start = buf.len() - (max_addr - align_end) as usize;
            let r = Reader::new(self.pid);
            let mut d = match r.peek_data(align_end) {
                Ok(v) => v,
                Err(e) => return Err(e)
            };
            for word_idx in 0..mem::size_of::<Word>() - 2 {
                let buf_idx = buf_start + word_idx;
                d = set_byte(d, word_idx, buf[buf_idx]);
            }
            match self.poke_data(align_end, d) {
                Ok(_) => {},
                Err(e) => return Err(e)
            }
        }
        Ok(())
    }
}

impl Reader {
    pub fn new(pid: libc::pid_t) -> Reader {
        Reader {
            pid: pid
        }
    }

    pub fn peek_data(&self, address: Address) -> Result<Word, i32> {
        match ptrace_raw(PTRACE_PEEKDATA, self.pid, address as *mut libc::c_void, ptr::null_mut()) {
            Ok(v) => Ok(v as Word),
            Err(e) => Err(e),
        }
    }

    pub fn read_string(&self, address: Address) -> Result<Vec<u8>, i32> {
        let mut end_of_str = false;
        let mut buf: Vec<u8> = Vec::with_capacity(1024);
        let max_addr = address + buf.capacity() as Address;
        let align_end = max_addr - (max_addr % mem::size_of::<Word>() as Address);
        'finish: for read_addr in (address..align_end).step_by(mem::size_of::<Word>() as Address) {
            let d;
            match self.peek_data(read_addr) {
                Ok(v) => d = v,
                Err(e) => return Err(e)
            }
            for word_idx in 0..mem::size_of::<Word>() {
                let chr = get_byte(d, word_idx);
                if chr == 0 {
                    end_of_str = true;
                    break 'finish;
                }
                buf.push(chr);
            }
        }
        if !end_of_str {
            let d;
            match self.peek_data(align_end) {
                Ok(v) => d = v,
                Err(e) => return Err(e)
            }
            for word_idx in 0..mem::size_of::<Word>() {
                let chr = get_byte(d, word_idx);
                if chr == 0 {
                    break;
                }
                buf.push(chr);
            }
        }
        return Ok(buf);
    }
}

fn get_byte(d: Word, byte_idx: usize) -> u8 {
    assert!(byte_idx < mem::size_of::<Word>());
    ((d >> (byte_idx * 8)) & 0xff) as u8
}

fn set_byte(d: Word, byte_idx: usize, value: u8) -> Word {
    assert!(byte_idx < mem::size_of::<Word>());
    let shift = mem::size_of::<u8>() * 8 * byte_idx;
    let mask = 0xff << shift;
    (d & !mask) | (((value as Word) << shift) & mask)
}

#[test]
pub fn test_set_byte() {
    assert_eq!(set_byte(0, 0, 0), 0);
    assert_eq!(set_byte(0xffffffffffff, 0, 0xff), 0xffffffffffff);
    assert_eq!(set_byte(0xffffffffffff, 0, 0),    0xffffffffff00);
    assert_eq!(set_byte(0xffffffffffff, 0, 0xaa), 0xffffffffffaa);
    assert_eq!(set_byte(0xffffffffffff, 1, 0x00), 0xffffffff00ff);
    assert_eq!(set_byte(0xffffffffffff, 4, 0xaa), 0xffaaffffffff);
}

#[test]
pub fn test_get_byte() {
    assert_eq!(get_byte(0, 0), 0);
    assert_eq!(get_byte(0xffffffffffff, 0), 0xff);
    assert_eq!(get_byte(0xffffffffffaa, 0), 0xaa);
    assert_eq!(get_byte(0x0123456789ab, 1), 0x89);
    assert_eq!(get_byte(0x0123456789ab, 4), 0x23);
}
<|endoftext|>


<commit_before>#![feature(unsafe_destructor)]

extern crate "ogg-sys" as ogg_sys;
extern crate "vorbis-sys" as vorbis_sys;
extern crate "vorbisfile-sys" as vorbisfile_sys;
extern crate libc;

/// Allows you to decode a sound file stream into packets.
pub struct Decoder<R> where R: Reader + Seek {
    // further informations are boxed so that a pointer can be passed to callbacks
    data: Box<DecoderData<R>>,
}

///
pub struct PacketsIter<'a, R: 'a + Reader + Seek>(&'a mut DecoderData<R>);

/// Errors that can happen while decoding
#[derive(Show, PartialEq, Eq)]
pub enum VorbisError {
    ReadError(std::io::IoError),
    NotVorbis,
    VersionMismatch,
    BadHeader,
    InitialFileHeadersCorrupt,
}

impl std::error::Error for VorbisError {
    fn description(&self) -> &str {
        match self {
            &VorbisError::ReadError(_) => "A read from media returned an error",
            &VorbisError::NotVorbis => "Bitstream does not contain any Vorbis data",
            &VorbisError::VersionMismatch => "Vorbis version mismatch",
            &VorbisError::BadHeader => "Invalid Vorbis bitstream header",
            &VorbisError::InitialFileHeadersCorrupt => "Initial file headers are corrupt",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match self {
            &VorbisError::ReadError(ref err) => Some(err as &std::error::Error),
            _ => None
        }
    }
}

impl std::fmt::String for VorbisError {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(fmt, "{}", std::error::Error::description(self))
    }
}

impl std::error::FromError<std::io::IoError> for VorbisError {
    fn from_error(err: std::io::IoError) -> VorbisError {
        VorbisError::ReadError(err)
    }
}

struct DecoderData<R> where R: Reader + Seek {
    vorbis: vorbisfile_sys::OggVorbis_File,
    reader: R,
    current_logical_bitstream: libc::c_int,
    read_error: Option<std::io::IoError>,
}

unsafe impl<R: Reader + Seek + Send> Send for DecoderData<R> {}

/// Packet of data.
///
/// Each sample is an `i16` ranging from I16_MIN to I16_MAX.
///
/// The channels are interleaved in the data. For example if you have two channels, you will
/// get a sample from channel 1, then a sample from channel 2, than a sample from channel 1, etc.
#[derive(Clone, Show)]
pub struct Packet {
    pub data: Vec<i16>,
    pub channels: u16,
    pub rate: u64,
    pub bitrate_upper: u64,
    pub bitrate_nominal: u64,
    pub bitrate_lower: u64,
    pub bitrate_window: u64,
}

impl<R> Decoder<R> where R: Reader + Seek {
    pub fn new(input: R) -> Result<Decoder<R>, VorbisError> {
        extern fn read_func<R>(ptr: *mut libc::c_void, size: libc::size_t, nmemb: libc::size_t,
            datasource: *mut libc::c_void) -> libc::size_t where R: Reader + Seek
        {
            use std::slice;

            let mut ptr = ptr as *mut u8;

            let data: &mut DecoderData<R> = unsafe { std::mem::transmute(datasource) };

            loop {
                let buffer = ptr.clone();
                let buffer = unsafe { slice::from_raw_mut_buf(&buffer, size as usize * nmemb as usize) };

                match data.reader.read(buffer) {
                    Ok(0) => continue,
                    Ok(nb) => {
                        if buffer.len() == nb {
                            return nmemb;
                        } else {
                            unsafe { ptr = ptr.offset(nb as isize) };
                        }
                    },
                    Err(ref e) if e.kind == std::io::EndOfFile => {
                        return 0
                    },
                    Err(e) => {
                        data.read_error = Some(e);
                        return 0;
                    }
                };
            }
        }

        extern fn seek_func<R>(datasource: *mut libc::c_void, offset: ogg_sys::ogg_int64_t,
            whence: libc::c_int) -> libc::c_int where R: Reader + Seek
        {
            let data: &mut DecoderData<R> = unsafe { std::mem::transmute(datasource) };

            let result = match whence {
                libc::SEEK_SET => data.reader.seek(offset, std::io::SeekSet),
                libc::SEEK_CUR => data.reader.seek(offset, std::io::SeekCur),
                libc::SEEK_END => data.reader.seek(offset, std::io::SeekEnd),
                _ => unreachable!()
            };

            match result {
                Ok(_) => 0,
                Err(_) => -1
            }
        }

        extern fn tell_func<R>(datasource: *mut libc::c_void) -> libc::c_long
            where R: Reader + Seek
        {
            let data: &mut DecoderData<R> = unsafe { std::mem::transmute(datasource) };
            data.reader.tell().unwrap_or(-1) as libc::c_long
        }

        let callbacks = {
            let mut callbacks: vorbisfile_sys::ov_callbacks = unsafe { std::mem::zeroed() };
            callbacks.read_func = read_func::<R>;
            callbacks.seek_func = seek_func::<R>;
            callbacks.tell_func = tell_func::<R>;
            callbacks
        };

        let mut data = Box::new(DecoderData {
            vorbis: unsafe { std::mem::uninitialized() },
            reader: input,
            current_logical_bitstream: 0,
            read_error: None,
        });

        // initializing
        unsafe {
            let data_ptr = &mut *data as *mut DecoderData<R>;
            let data_ptr = data_ptr as *mut libc::c_void;
            try!(check_errors(vorbisfile_sys::ov_open_callbacks(data_ptr, &mut data.vorbis,
                std::ptr::null(), 0, callbacks)));
        }

        Ok(Decoder {
            data: data,
        })
    }

    pub fn packets(&mut self) -> PacketsIter<R> {
        PacketsIter(&mut *self.data)
    }
}

impl<'a, R> Iterator for PacketsIter<'a, R> where R: 'a + Reader + Seek {
    type Item = Result<Packet, VorbisError>;

    fn next(&mut self) -> Option<Result<Packet, VorbisError>> {
        let mut buffer = std::iter::repeat(0i16).take(2048).collect::<Vec<_>>();
        let buffer_len = buffer.len() * 2;

        match unsafe {
            vorbisfile_sys::ov_read(&mut self.0.vorbis, buffer.as_mut_ptr() as *mut i8,
                buffer_len as libc::c_int, 0, 2, 1, &mut self.0.current_logical_bitstream)
        } {
            0 => {
                match self.0.read_error.take() {
                    Some(err) => Some(Err(VorbisError::ReadError(err))),
                    None => None,
                }
            },

            err if err < 0 => {
                match check_errors(err as libc::c_int) {
                    Err(e) => Some(Err(e)),
                    Ok(_) => unreachable!()
                }
            },

            len => {
                buffer.truncate(len as usize);

                let infos = unsafe { vorbisfile_sys::ov_info(&mut self.0.vorbis,
                    self.0.current_logical_bitstream) };

                let infos: &vorbis_sys::vorbis_info = unsafe { std::mem::transmute(infos) };

                Some(Ok(Packet {
                    data: buffer,
                    channels: infos.channels as u16,
                    rate: infos.rate as u64,
                    bitrate_upper: infos.bitrate_upper as u64,
                    bitrate_nominal: infos.bitrate_nominal as u64,
                    bitrate_lower: infos.bitrate_lower as u64,
                    bitrate_window: infos.bitrate_window as u64,
                }))
            }
        }
    }
}

#[unsafe_destructor]
impl<R> Drop for Decoder<R> where R: Reader + Seek {
    fn drop(&mut self) {
        unsafe {
            vorbisfile_sys::ov_clear(&mut self.data.vorbis);
        }
    }
}

fn check_errors(code: libc::c_int) -> Result<(), VorbisError> {
    match code {
        0 => Ok(()),

        vorbis_sys::OV_ENOTVORBIS => Err(VorbisError::NotVorbis),
        vorbis_sys::OV_EVERSION => Err(VorbisError::VersionMismatch),
        vorbis_sys::OV_EBADHEADER => Err(VorbisError::BadHeader),
        vorbis_sys::OV_EINVAL => Err(VorbisError::InitialFileHeadersCorrupt),

        vorbis_sys::OV_EREAD => unimplemented!(),

        // indicates a bug or heap/stack corruption
        vorbis_sys::OV_EFAULT => panic!("Internal libvorbis error"),
        _ => panic!("Unknown vorbis error")
    }
}
<commit_msg>Updated to build with latest rustc nightly.<commit_after>#![feature(unsafe_destructor, io, libc, core)]

extern crate "ogg-sys" as ogg_sys;
extern crate "vorbis-sys" as vorbis_sys;
extern crate "vorbisfile-sys" as vorbisfile_sys;
extern crate libc;

/// Allows you to decode a sound file stream into packets.
pub struct Decoder<R> where R: Reader + Seek {
    // further informations are boxed so that a pointer can be passed to callbacks
    data: Box<DecoderData<R>>,
}

///
pub struct PacketsIter<'a, R: 'a + Reader + Seek>(&'a mut DecoderData<R>);

/// Errors that can happen while decoding
#[derive(Debug, PartialEq, Eq)]
pub enum VorbisError {
    ReadError(std::old_io::IoError),
    NotVorbis,
    VersionMismatch,
    BadHeader,
    InitialFileHeadersCorrupt,
}

impl std::error::Error for VorbisError {
    fn description(&self) -> &str {
        match self {
            &VorbisError::ReadError(_) => "A read from media returned an error",
            &VorbisError::NotVorbis => "Bitstream does not contain any Vorbis data",
            &VorbisError::VersionMismatch => "Vorbis version mismatch",
            &VorbisError::BadHeader => "Invalid Vorbis bitstream header",
            &VorbisError::InitialFileHeadersCorrupt => "Initial file headers are corrupt",
        }
    }

    fn cause(&self) -> Option<&std::error::Error> {
        match self {
            &VorbisError::ReadError(ref err) => Some(err as &std::error::Error),
            _ => None
        }
    }
}

impl std::fmt::Display for VorbisError {
    fn fmt(&self, fmt: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        write!(fmt, "{}", std::error::Error::description(self))
    }
}

impl std::error::FromError<std::old_io::IoError> for VorbisError {
    fn from_error(err: std::old_io::IoError) -> VorbisError {
        VorbisError::ReadError(err)
    }
}

struct DecoderData<R> where R: Reader + Seek {
    vorbis: vorbisfile_sys::OggVorbis_File,
    reader: R,
    current_logical_bitstream: libc::c_int,
    read_error: Option<std::old_io::IoError>,
}

unsafe impl<R: Reader + Seek + Send> Send for DecoderData<R> {}

/// Packet of data.
///
/// Each sample is an `i16` ranging from I16_MIN to I16_MAX.
///
/// The channels are interleaved in the data. For example if you have two channels, you will
/// get a sample from channel 1, then a sample from channel 2, than a sample from channel 1, etc.
#[derive(Clone, Debug)]
pub struct Packet {
    pub data: Vec<i16>,
    pub channels: u16,
    pub rate: u64,
    pub bitrate_upper: u64,
    pub bitrate_nominal: u64,
    pub bitrate_lower: u64,
    pub bitrate_window: u64,
}

impl<R> Decoder<R> where R: Reader + Seek {
    pub fn new(input: R) -> Result<Decoder<R>, VorbisError> {
        extern fn read_func<R>(ptr: *mut libc::c_void, size: libc::size_t, nmemb: libc::size_t,
            datasource: *mut libc::c_void) -> libc::size_t where R: Reader + Seek
        {
            use std::slice;

            let mut ptr = ptr as *mut u8;

            let data: &mut DecoderData<R> = unsafe { std::mem::transmute(datasource) };

            loop {
                let buffer = ptr.clone();
                let buffer = unsafe { slice::from_raw_mut_buf(&buffer, size as usize * nmemb as usize) };

                match data.reader.read(buffer) {
                    Ok(0) => continue,
                    Ok(nb) => {
                        if buffer.len() == nb {
                            return nmemb;
                        } else {
                            unsafe { ptr = ptr.offset(nb as isize) };
                        }
                    },
                    Err(ref e) if e.kind == std::old_io::EndOfFile => {
                        return 0
                    },
                    Err(e) => {
                        data.read_error = Some(e);
                        return 0;
                    }
                };
            }
        }

        extern fn seek_func<R>(datasource: *mut libc::c_void, offset: ogg_sys::ogg_int64_t,
            whence: libc::c_int) -> libc::c_int where R: Reader + Seek
        {
            let data: &mut DecoderData<R> = unsafe { std::mem::transmute(datasource) };

            let result = match whence {
                libc::SEEK_SET => data.reader.seek(offset, std::old_io::SeekSet),
                libc::SEEK_CUR => data.reader.seek(offset, std::old_io::SeekCur),
                libc::SEEK_END => data.reader.seek(offset, std::old_io::SeekEnd),
                _ => unreachable!()
            };

            match result {
                Ok(_) => 0,
                Err(_) => -1
            }
        }

        extern fn tell_func<R>(datasource: *mut libc::c_void) -> libc::c_long
            where R: Reader + Seek
        {
            let data: &mut DecoderData<R> = unsafe { std::mem::transmute(datasource) };
            data.reader.tell().unwrap_or(-1) as libc::c_long
        }

        let callbacks = {
            let mut callbacks: vorbisfile_sys::ov_callbacks = unsafe { std::mem::zeroed() };
            callbacks.read_func = read_func::<R>;
            callbacks.seek_func = seek_func::<R>;
            callbacks.tell_func = tell_func::<R>;
            callbacks
        };

        let mut data = Box::new(DecoderData {
            vorbis: unsafe { std::mem::uninitialized() },
            reader: input,
            current_logical_bitstream: 0,
            read_error: None,
        });

        // initializing
        unsafe {
            let data_ptr = &mut *data as *mut DecoderData<R>;
            let data_ptr = data_ptr as *mut libc::c_void;
            try!(check_errors(vorbisfile_sys::ov_open_callbacks(data_ptr, &mut data.vorbis,
                std::ptr::null(), 0, callbacks)));
        }

        Ok(Decoder {
            data: data,
        })
    }

    pub fn packets(&mut self) -> PacketsIter<R> {
        PacketsIter(&mut *self.data)
    }
}

impl<'a, R> Iterator for PacketsIter<'a, R> where R: 'a + Reader + Seek {
    type Item = Result<Packet, VorbisError>;

    fn next(&mut self) -> Option<Result<Packet, VorbisError>> {
        let mut buffer = std::iter::repeat(0i16).take(2048).collect::<Vec<_>>();
        let buffer_len = buffer.len() * 2;

        match unsafe {
            vorbisfile_sys::ov_read(&mut self.0.vorbis, buffer.as_mut_ptr() as *mut i8,
                buffer_len as libc::c_int, 0, 2, 1, &mut self.0.current_logical_bitstream)
        } {
            0 => {
                match self.0.read_error.take() {
                    Some(err) => Some(Err(VorbisError::ReadError(err))),
                    None => None,
                }
            },

            err if err < 0 => {
                match check_errors(err as libc::c_int) {
                    Err(e) => Some(Err(e)),
                    Ok(_) => unreachable!()
                }
            },

            len => {
                buffer.truncate(len as usize);

                let infos = unsafe { vorbisfile_sys::ov_info(&mut self.0.vorbis,
                    self.0.current_logical_bitstream) };

                let infos: &vorbis_sys::vorbis_info = unsafe { std::mem::transmute(infos) };

                Some(Ok(Packet {
                    data: buffer,
                    channels: infos.channels as u16,
                    rate: infos.rate as u64,
                    bitrate_upper: infos.bitrate_upper as u64,
                    bitrate_nominal: infos.bitrate_nominal as u64,
                    bitrate_lower: infos.bitrate_lower as u64,
                    bitrate_window: infos.bitrate_window as u64,
                }))
            }
        }
    }
}

#[unsafe_destructor]
impl<R> Drop for Decoder<R> where R: Reader + Seek {
    fn drop(&mut self) {
        unsafe {
            vorbisfile_sys::ov_clear(&mut self.data.vorbis);
        }
    }
}

fn check_errors(code: libc::c_int) -> Result<(), VorbisError> {
    match code {
        0 => Ok(()),

        vorbis_sys::OV_ENOTVORBIS => Err(VorbisError::NotVorbis),
        vorbis_sys::OV_EVERSION => Err(VorbisError::VersionMismatch),
        vorbis_sys::OV_EBADHEADER => Err(VorbisError::BadHeader),
        vorbis_sys::OV_EINVAL => Err(VorbisError::InitialFileHeadersCorrupt),

        vorbis_sys::OV_EREAD => unimplemented!(),

        // indicates a bug or heap/stack corruption
        vorbis_sys::OV_EFAULT => panic!("Internal libvorbis error"),
        _ => panic!("Unknown vorbis error")
    }
}
<|endoftext|>


<commit_before>//! The graylog crate provides graylog (https://www.graylog.org/) compatible logging based on
//! the log crate and its logging facade (https://doc.rust-lang.org/log/log/index.html).
//!
//! # Examples
//!
//! ```
//! #[macro_use] extern crate log;
//! extern crate graylog;
//!
//! fn main() {
//!   graylog::logger::init("192.168.99.100:5555", log::LogLevel::Debug);
//!   info!("The logger macros now use the graylog logging backend");
//! }
//! ```

// Needed to derive `Serialize` on ServiceProperties
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
// #![warn(missing_docs)]
extern crate serde_json;
#[macro_use]
extern crate log;
extern crate flate2;
extern crate chrono;
extern crate byteorder;

pub mod logger;
<commit_msg>doc comment formatting<commit_after>//! The graylog crate provides graylog (https://www.graylog.org/) compatible logging based on
//! the log crate and its logging facade (https://doc.rust-lang.org/log/log/index.html).
//!
//! # Examples
//!
//! ```rust
//! #[macro_use]
//! extern crate log;
//! extern crate graylog;
//!
//! fn main() {
//!   graylog::logger::init("192.168.99.100:5555", log::LogLevel::Debug);
//!   info!("The logger macros now use the graylog logging backend");
//! }
//! ```

// Needed to derive `Serialize` on ServiceProperties
#![feature(custom_derive, plugin)]
#![plugin(serde_macros)]
// #![warn(missing_docs)]
extern crate serde_json;
#[macro_use]
extern crate log;
extern crate flate2;
extern crate chrono;
extern crate byteorder;

pub mod logger;
<|endoftext|>


<commit_before>// Module for parsing ISO Base Media Format aka video/mp4 streams.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

/// Basic ISO box structure.
pub struct BoxHeader {
    /// Four character box type
pub name: u32,
    /// Size of the box in bytes
pub size: u64,
    /// Offset to the start of the contained data (or header size).
pub offset: u64,
}

/// File type box 'ftyp'.
pub struct FileTypeBox {
    name: u32,
    size: u64,
    major_brand: u32,
    minor_version: u32,
    compatible_brands: Vec<u32>,
}

/// Movie header box 'mvhd'.
pub struct MovieHeaderBox {
    pub name: u32,
    pub size: u64,
    pub timescale: u32,
    pub duration: u64,
    // Ignore other fields.
}

pub struct TrackHeaderBox {
    pub name: u32,
    pub size: u64,
    pub track_id: u32,
    pub duration: u64,
    pub width: u32,
    pub height: u32,
}

extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{Error, ErrorKind, Read, Result, Seek, SeekFrom, Take};
use std::io::Cursor;

/// Parse a box out of a data buffer.
pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Result<BoxHeader> {
    let tmp_size = try!(src.read_u32::<BigEndian>());
    let name = try!(src.read_u32::<BigEndian>());
    let size = match tmp_size {
        1 => try!(src.read_u64::<BigEndian>()),
        _ => tmp_size as u64,
    };
    assert!(size >= 8);
    if tmp_size == 1 {
        assert!(size >= 16);
    }
    let offset = match tmp_size {
        1 => 4 + 4 + 8,
        _ => 4 + 4,
    };
    assert!(offset <= size);
    Ok(BoxHeader{
      name: name,
      size: size,
      offset: offset,
    })
}

/// Parse the extra header fields for a full box.
fn read_fullbox_extra<T: ReadBytesExt>(src: &mut T) -> (u8, u32) {
    let version = src.read_u8().unwrap();
    let flags_a = src.read_u8().unwrap();
    let flags_b = src.read_u8().unwrap();
    let flags_c = src.read_u8().unwrap();
    (version, (flags_a as u32) << 16 |
              (flags_b as u32) <<  8 |
              (flags_c as u32))
}

/// Skip over the contents of a box.
pub fn skip_box_content<T: ReadBytesExt + Seek>
  (src: &mut T, header: &BoxHeader)
  -> std::io::Result<u64>
{
    src.seek(SeekFrom::Current((header.size - header.offset) as i64))
}

/// Helper to construct a Take over the contents of a box.
fn limit<'a, T: Read>(f: &'a mut T, h: &BoxHeader) -> Take<&'a mut T> {
    f.take(h.size - h.offset)
}

/// Helper to construct a Cursor over the contents of a box.
fn recurse<T: Read>(f: &mut T, h: &BoxHeader) -> Result<()> {
    println!("{} -- recursing", h);
    // FIXME: I couldn't figure out how to do this without copying.
    // We use Seek on the Read we return in skip_box_content, but
    // that trait isn't implemented for a Take like our limit()
    // returns. Slurping the buffer and wrapping it in a Cursor
    // functions as a work around.
    let buf: Vec<u8> = limit(f, &h)
        .bytes()
        .map(|u| u.unwrap())
        .collect();
    let mut content = Cursor::new(buf);
    loop {
        match read_box(&mut content) {
            Ok(_) => {},
            Err(e) => {
                println!("Error '{:?}' reading box", e.kind());
                return Err(e);
            },
        }
    }
    println!("{} -- end", h);
    Ok(())
}

/// Read the contents of a box, including sub boxes.
/// Right now it just prints the box value rather than
/// returning anything.
pub fn read_box<T: Read + Seek>(f: &mut T) -> Result<()> {
    read_box_header(f).and_then(|h| {
        match &(fourcc_to_string(h.name))[..] {
            "ftyp" => {
                let mut content = limit(f, &h);
                let ftyp = read_ftyp(&mut content, &h).unwrap();
                println!("{}", ftyp);
            },
            "moov" => try!(recurse(f, &h)),
            "mvhd" => {
                let mut content = limit(f, &h);
                let mvhd = try!(read_mvhd(&mut content, &h));
                println!("  {}", mvhd);
            },
            "trak" => try!(recurse(f, &h)),
            "tkhd" => {
                let mut content = limit(f, &h);
                let tkhd = try!(read_tkhd(&mut content, &h));
                println!("  {}", tkhd);
            },
            _ => {
                // Skip the contents of unknown chunks.
                println!("{} (skipped)", h);
                try!(skip_box_content(f, &h).and(Ok(())));
            },
        };
        Ok(()) // and_then needs a Result to return.
    })
}

/// Entry point for C language callers.
/// Take a buffer and call read_box() on it.
#[no_mangle]
pub unsafe extern fn read_box_from_buffer(buffer: *const u8, size: usize)
  -> bool {
    use std::slice;
    use std::thread;

    // Validate arguments from C.
    if buffer.is_null() || size < 8 {
        return false;
    }

    // Wrap the buffer we've been give in a slice.
    let b = slice::from_raw_parts(buffer, size);
    let mut c = Cursor::new(b);

    // Parse in a subthread.
    let task = thread::spawn(move || {
        read_box(&mut c).unwrap();
    });
    // Catch any panics.
    task.join().is_ok()
}

/// Parse an ftype box.
pub fn read_ftyp<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Option<FileTypeBox> {
    let major = src.read_u32::<BigEndian>().unwrap();
    let minor = src.read_u32::<BigEndian>().unwrap();
    let brand_count = (head.size - 8 - 8) /4;
    let mut brands = Vec::new();
    for _ in 0..brand_count {
        brands.push(src.read_u32::<BigEndian>().unwrap());
    }
    Some(FileTypeBox{
        name: head.name,
        size: head.size,
        major_brand: major,
        minor_version: minor,
        compatible_brands: brands,
    })
}

/// Parse an mvhd box.
pub fn read_mvhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Result<MovieHeaderBox> {
    let (version, _) = read_fullbox_extra(src);
    match version {
        1 => {
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 16];
            let r = try!(src.read(&mut skip));
            assert!(r == skip.len());
        },
        0 => {
            // 32 bit creation and modification times.
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 8];
            let r = try!(src.read(&mut skip));
            assert!(r == skip.len());
        },
        _ => panic!("invalid mhdr version"),
    }
    let timescale = src.read_u32::<BigEndian>().unwrap();
    let duration = match version {
        1 => try!(src.read_u64::<BigEndian>()),
        0 => try!(src.read_u32::<BigEndian>()) as u64,
        _ => panic!("invalid mhdr version"),
    };
    // Skip remaining fields.
    let mut skip: Vec<u8> = vec![0; 80];
    let r = try!(src.read(&mut skip));
    assert!(r == skip.len());
    Ok(MovieHeaderBox {
        name: head.name,
        size: head.size,
        timescale: timescale,
        duration: duration,
    })
}

/// Parse a tkhd box.
pub fn read_tkhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Result<TrackHeaderBox> {
    let (version, flags) = read_fullbox_extra(src);
    if flags & 0x1u32 == 0 || flags & 0x2u32 == 0 {
        return Err(Error::new(ErrorKind::Other, "Track is disabled"));
    }
    match version {
        1 => {
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 16];
            let r = try!(src.read(&mut skip));
            assert!(r == skip.len());
        },
        0 => {
            // 32 bit creation and modification times.
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 8];
            let r = try!(src.read(&mut skip));
            assert!(r == skip.len());
        },
        _ => panic!("invalid tkhd version"),
    }
    let track_id = try!(src.read_u32::<BigEndian>());
    let _reserved = try!(src.read_u32::<BigEndian>());
    assert!(_reserved == 0);
    let duration = match version {
        1 => {
            try!(src.read_u64::<BigEndian>())
        },
        0 => try!(src.read_u32::<BigEndian>()) as u64,
        _ => panic!("invalid tkhd version"),
    };
    let _reserved = try!(src.read_u32::<BigEndian>());
    let _reserved = try!(src.read_u32::<BigEndian>());
    // Skip uninterested fields.
    let mut skip: Vec<u8> = vec![0; 44];
    let r = try!(src.read(&mut skip));
    assert!(r == skip.len());
    let width = try!(src.read_u32::<BigEndian>());
    let height = try!(src.read_u32::<BigEndian>());
    Ok(TrackHeaderBox {
        name: head.name,
        size: head.size,
        track_id: track_id,
        duration: duration,
        width: width,
        height: height,
    })
}

/// Convert the iso box type or other 4-character value to a string.
fn fourcc_to_string(name: u32) -> String {
    let u32_to_vec = |u| {
        vec!((u >> 24 & 0xffu32) as u8,
             (u >> 16 & 0xffu32) as u8,
             (u >>  8 & 0xffu32) as u8,
             (u & 0xffu32) as u8)
    };
    let name_bytes = u32_to_vec(name);
    String::from_utf8_lossy(&name_bytes).into_owned()
}

use std::fmt;
impl fmt::Display for BoxHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "'{}' {} bytes", fourcc_to_string(self.name), self.size)
    }
}

impl fmt::Display for FileTypeBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        let brand = fourcc_to_string(self.major_brand);
        write!(f, "'{}' {} bytes '{}' v{}", name, self.size,
            brand, self.minor_version)
    }
}

impl fmt::Display for MovieHeaderBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        write!(f, "'{}' {} bytes duration {}s", name, self.size,
            (self.duration as f64)/(self.timescale as f64))
    }
}

use std::u16;
impl fmt::Display for TrackHeaderBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        // Dimensions are 16.16 fixed-point.
        let base = u16::MAX as f64 + 1.0;
        let width = (self.width as f64) / base;
        let height = (self.height as f64) / base;
        write!(f, "'{}' {} bytes duration {} id {} {}x{}",
            name, self.size, self.duration, self.track_id,
            width, height)
    }
}

#[test]
fn test_read_box_header() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 8];  // minimal box length
    write!(&mut test, "test").unwrap(); // box type
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1952805748);
    assert_eq!(parsed.size, 8);
    println!("box {}", parsed);
}

#[test]
fn test_read_box_header_long() {
    use std::io::Cursor;
    let mut test: Vec<u8> = vec![0, 0, 0, 1]; // long box extension code
    test.extend("long".to_string().into_bytes()); // box type
    test.extend(vec![0, 0, 0, 0, 0, 0, 16, 0]); // 64 bit size
    // Skip generating box content.
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1819242087);
    assert_eq!(parsed.size, 4096);
    println!("box {}", parsed);
}

#[test]
fn test_read_ftyp() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 24]; // size
    write!(&mut test, "ftyp").unwrap(); // type
    write!(&mut test, "mp42").unwrap(); // major brand
    test.extend(vec![0, 0, 0, 0]);      // minor version
    write!(&mut test, "isom").unwrap(); // compatible brands...
    write!(&mut test, "mp42").unwrap();
    assert_eq!(test.len(), 24);

    let mut stream = Cursor::new(test);
    let header = read_box_header(&mut stream).unwrap();
    let parsed = read_ftyp(&mut stream, &header).unwrap();
    assert_eq!(parsed.name, 1718909296);
    assert_eq!(parsed.size, 24);
    assert_eq!(parsed.major_brand, 1836069938);
    assert_eq!(parsed.minor_version, 0);
    assert_eq!(parsed.compatible_brands.len(), 2);
    println!("box {}", parsed);
}
<commit_msg>Return Result from read_ftyp.<commit_after>// Module for parsing ISO Base Media Format aka video/mp4 streams.

// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

/// Basic ISO box structure.
pub struct BoxHeader {
    /// Four character box type
pub name: u32,
    /// Size of the box in bytes
pub size: u64,
    /// Offset to the start of the contained data (or header size).
pub offset: u64,
}

/// File type box 'ftyp'.
pub struct FileTypeBox {
    name: u32,
    size: u64,
    major_brand: u32,
    minor_version: u32,
    compatible_brands: Vec<u32>,
}

/// Movie header box 'mvhd'.
pub struct MovieHeaderBox {
    pub name: u32,
    pub size: u64,
    pub timescale: u32,
    pub duration: u64,
    // Ignore other fields.
}

pub struct TrackHeaderBox {
    pub name: u32,
    pub size: u64,
    pub track_id: u32,
    pub duration: u64,
    pub width: u32,
    pub height: u32,
}

extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};
use std::io::{Error, ErrorKind, Read, Result, Seek, SeekFrom, Take};
use std::io::Cursor;

/// Parse a box out of a data buffer.
pub fn read_box_header<T: ReadBytesExt>(src: &mut T) -> Result<BoxHeader> {
    let tmp_size = try!(src.read_u32::<BigEndian>());
    let name = try!(src.read_u32::<BigEndian>());
    let size = match tmp_size {
        1 => try!(src.read_u64::<BigEndian>()),
        _ => tmp_size as u64,
    };
    assert!(size >= 8);
    if tmp_size == 1 {
        assert!(size >= 16);
    }
    let offset = match tmp_size {
        1 => 4 + 4 + 8,
        _ => 4 + 4,
    };
    assert!(offset <= size);
    Ok(BoxHeader{
      name: name,
      size: size,
      offset: offset,
    })
}

/// Parse the extra header fields for a full box.
fn read_fullbox_extra<T: ReadBytesExt>(src: &mut T) -> (u8, u32) {
    let version = src.read_u8().unwrap();
    let flags_a = src.read_u8().unwrap();
    let flags_b = src.read_u8().unwrap();
    let flags_c = src.read_u8().unwrap();
    (version, (flags_a as u32) << 16 |
              (flags_b as u32) <<  8 |
              (flags_c as u32))
}

/// Skip over the contents of a box.
pub fn skip_box_content<T: ReadBytesExt + Seek>
  (src: &mut T, header: &BoxHeader)
  -> std::io::Result<u64>
{
    src.seek(SeekFrom::Current((header.size - header.offset) as i64))
}

/// Helper to construct a Take over the contents of a box.
fn limit<'a, T: Read>(f: &'a mut T, h: &BoxHeader) -> Take<&'a mut T> {
    f.take(h.size - h.offset)
}

/// Helper to construct a Cursor over the contents of a box.
fn recurse<T: Read>(f: &mut T, h: &BoxHeader) -> Result<()> {
    println!("{} -- recursing", h);
    // FIXME: I couldn't figure out how to do this without copying.
    // We use Seek on the Read we return in skip_box_content, but
    // that trait isn't implemented for a Take like our limit()
    // returns. Slurping the buffer and wrapping it in a Cursor
    // functions as a work around.
    let buf: Vec<u8> = limit(f, &h)
        .bytes()
        .map(|u| u.unwrap())
        .collect();
    let mut content = Cursor::new(buf);
    loop {
        match read_box(&mut content) {
            Ok(_) => {},
            Err(e) => {
                println!("Error '{:?}' reading box", e.kind());
                return Err(e);
            },
        }
    }
    println!("{} -- end", h);
    Ok(())
}

/// Read the contents of a box, including sub boxes.
/// Right now it just prints the box value rather than
/// returning anything.
pub fn read_box<T: Read + Seek>(f: &mut T) -> Result<()> {
    read_box_header(f).and_then(|h| {
        match &(fourcc_to_string(h.name))[..] {
            "ftyp" => {
                let mut content = limit(f, &h);
                let ftyp = try!(read_ftyp(&mut content, &h));
                println!("{}", ftyp);
            },
            "moov" => try!(recurse(f, &h)),
            "mvhd" => {
                let mut content = limit(f, &h);
                let mvhd = try!(read_mvhd(&mut content, &h));
                println!("  {}", mvhd);
            },
            "trak" => try!(recurse(f, &h)),
            "tkhd" => {
                let mut content = limit(f, &h);
                let tkhd = try!(read_tkhd(&mut content, &h));
                println!("  {}", tkhd);
            },
            _ => {
                // Skip the contents of unknown chunks.
                println!("{} (skipped)", h);
                try!(skip_box_content(f, &h).and(Ok(())));
            },
        };
        Ok(()) // and_then needs a Result to return.
    })
}

/// Entry point for C language callers.
/// Take a buffer and call read_box() on it.
#[no_mangle]
pub unsafe extern fn read_box_from_buffer(buffer: *const u8, size: usize)
  -> bool {
    use std::slice;
    use std::thread;

    // Validate arguments from C.
    if buffer.is_null() || size < 8 {
        return false;
    }

    // Wrap the buffer we've been give in a slice.
    let b = slice::from_raw_parts(buffer, size);
    let mut c = Cursor::new(b);

    // Parse in a subthread.
    let task = thread::spawn(move || {
        read_box(&mut c).unwrap();
    });
    // Catch any panics.
    task.join().is_ok()
}

/// Parse an ftype box.
pub fn read_ftyp<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Result<FileTypeBox> {
    let major = try!(src.read_u32::<BigEndian>());
    let minor = try!(src.read_u32::<BigEndian>());
    let brand_count = (head.size - 8 - 8) /4;
    let mut brands = Vec::new();
    for _ in 0..brand_count {
        brands.push( try!(src.read_u32::<BigEndian>()) );
    }
    Ok(FileTypeBox{
        name: head.name,
        size: head.size,
        major_brand: major,
        minor_version: minor,
        compatible_brands: brands,
    })
}

/// Parse an mvhd box.
pub fn read_mvhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Result<MovieHeaderBox> {
    let (version, _) = read_fullbox_extra(src);
    match version {
        1 => {
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 16];
            let r = try!(src.read(&mut skip));
            assert!(r == skip.len());
        },
        0 => {
            // 32 bit creation and modification times.
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 8];
            let r = try!(src.read(&mut skip));
            assert!(r == skip.len());
        },
        _ => panic!("invalid mhdr version"),
    }
    let timescale = src.read_u32::<BigEndian>().unwrap();
    let duration = match version {
        1 => try!(src.read_u64::<BigEndian>()),
        0 => try!(src.read_u32::<BigEndian>()) as u64,
        _ => panic!("invalid mhdr version"),
    };
    // Skip remaining fields.
    let mut skip: Vec<u8> = vec![0; 80];
    let r = try!(src.read(&mut skip));
    assert!(r == skip.len());
    Ok(MovieHeaderBox {
        name: head.name,
        size: head.size,
        timescale: timescale,
        duration: duration,
    })
}

/// Parse a tkhd box.
pub fn read_tkhd<T: ReadBytesExt>(src: &mut T, head: &BoxHeader)
  -> Result<TrackHeaderBox> {
    let (version, flags) = read_fullbox_extra(src);
    if flags & 0x1u32 == 0 || flags & 0x2u32 == 0 {
        return Err(Error::new(ErrorKind::Other, "Track is disabled"));
    }
    match version {
        1 => {
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 16];
            let r = try!(src.read(&mut skip));
            assert!(r == skip.len());
        },
        0 => {
            // 32 bit creation and modification times.
            // 64 bit creation and modification times.
            let mut skip: Vec<u8> = vec![0; 8];
            let r = try!(src.read(&mut skip));
            assert!(r == skip.len());
        },
        _ => panic!("invalid tkhd version"),
    }
    let track_id = try!(src.read_u32::<BigEndian>());
    let _reserved = try!(src.read_u32::<BigEndian>());
    assert!(_reserved == 0);
    let duration = match version {
        1 => {
            try!(src.read_u64::<BigEndian>())
        },
        0 => try!(src.read_u32::<BigEndian>()) as u64,
        _ => panic!("invalid tkhd version"),
    };
    let _reserved = try!(src.read_u32::<BigEndian>());
    let _reserved = try!(src.read_u32::<BigEndian>());
    // Skip uninterested fields.
    let mut skip: Vec<u8> = vec![0; 44];
    let r = try!(src.read(&mut skip));
    assert!(r == skip.len());
    let width = try!(src.read_u32::<BigEndian>());
    let height = try!(src.read_u32::<BigEndian>());
    Ok(TrackHeaderBox {
        name: head.name,
        size: head.size,
        track_id: track_id,
        duration: duration,
        width: width,
        height: height,
    })
}

/// Convert the iso box type or other 4-character value to a string.
fn fourcc_to_string(name: u32) -> String {
    let u32_to_vec = |u| {
        vec!((u >> 24 & 0xffu32) as u8,
             (u >> 16 & 0xffu32) as u8,
             (u >>  8 & 0xffu32) as u8,
             (u & 0xffu32) as u8)
    };
    let name_bytes = u32_to_vec(name);
    String::from_utf8_lossy(&name_bytes).into_owned()
}

use std::fmt;
impl fmt::Display for BoxHeader {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "'{}' {} bytes", fourcc_to_string(self.name), self.size)
    }
}

impl fmt::Display for FileTypeBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        let brand = fourcc_to_string(self.major_brand);
        write!(f, "'{}' {} bytes '{}' v{}", name, self.size,
            brand, self.minor_version)
    }
}

impl fmt::Display for MovieHeaderBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        write!(f, "'{}' {} bytes duration {}s", name, self.size,
            (self.duration as f64)/(self.timescale as f64))
    }
}

use std::u16;
impl fmt::Display for TrackHeaderBox {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let name = fourcc_to_string(self.name);
        // Dimensions are 16.16 fixed-point.
        let base = u16::MAX as f64 + 1.0;
        let width = (self.width as f64) / base;
        let height = (self.height as f64) / base;
        write!(f, "'{}' {} bytes duration {} id {} {}x{}",
            name, self.size, self.duration, self.track_id,
            width, height)
    }
}

#[test]
fn test_read_box_header() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 8];  // minimal box length
    write!(&mut test, "test").unwrap(); // box type
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1952805748);
    assert_eq!(parsed.size, 8);
    println!("box {}", parsed);
}

#[test]
fn test_read_box_header_long() {
    use std::io::Cursor;
    let mut test: Vec<u8> = vec![0, 0, 0, 1]; // long box extension code
    test.extend("long".to_string().into_bytes()); // box type
    test.extend(vec![0, 0, 0, 0, 0, 0, 16, 0]); // 64 bit size
    // Skip generating box content.
    let mut stream = Cursor::new(test);
    let parsed = read_box_header(&mut stream).unwrap();
    assert_eq!(parsed.name, 1819242087);
    assert_eq!(parsed.size, 4096);
    println!("box {}", parsed);
}

#[test]
fn test_read_ftyp() {
    use std::io::Cursor;
    use std::io::Write;
    let mut test: Vec<u8> = vec![0, 0, 0, 24]; // size
    write!(&mut test, "ftyp").unwrap(); // type
    write!(&mut test, "mp42").unwrap(); // major brand
    test.extend(vec![0, 0, 0, 0]);      // minor version
    write!(&mut test, "isom").unwrap(); // compatible brands...
    write!(&mut test, "mp42").unwrap();
    assert_eq!(test.len(), 24);

    let mut stream = Cursor::new(test);
    let header = read_box_header(&mut stream).unwrap();
    let parsed = read_ftyp(&mut stream, &header).unwrap();
    assert_eq!(parsed.name, 1718909296);
    assert_eq!(parsed.size, 24);
    assert_eq!(parsed.major_brand, 1836069938);
    assert_eq!(parsed.minor_version, 0);
    assert_eq!(parsed.compatible_brands.len(), 2);
    println!("box {}", parsed);
}
<|endoftext|>


<commit_before>#![feature(proc_macro)]

extern crate proc_macro;
extern crate syn;

#[macro_use]
extern crate quote;

use proc_macro::TokenStream;

fn output_struct(name: &syn::Ident) -> quote::Tokens {
    quote! {
        struct #name (u8);
        impl #name {
            pub fn get_bit() {

            }
        }
    }
}

#[derive(Debug)]
enum BitField {
    Single(u8),
    Range(std::ops::Range<u8>)
}

#[proc_macro_attribute]
pub fn register(_: TokenStream, input: TokenStream) -> TokenStream {
    println!("{}", input);

    let s = input.to_string();
    let ast = syn::parse_derive_input(&s).unwrap();

    println!("ident: {}", ast.ident);

    let fields = match ast.body {
        syn::Body::Enum(_) => panic!("enum not supported"),
        syn::Body::Struct(x) => match x {
            syn::VariantData::Struct(fields) => fields,
            _ => panic!("tuple and unit not supported")
        }
    };

    for field in &fields {
        let ident = field.ident.clone().unwrap();
        let ty = match field.clone().ty {
            syn::Ty::Path(_, path) => path.segments[0].ident.clone(),
            _ => panic!("only path types supported"),
        };

        let mut bitfield: Option<BitField> = None;

        for attr in &field.attrs {
            if let syn::MetaItem::List(attr_ident, attr_nest) = attr.clone().value {
                println!("found attribute: {}", attr_ident);
                if attr_ident == "bitfield" {
                    println!("found bitfield attribute: {:?}", attr_nest);
                }
            }
        }

        bitfield = match 1 {
            0 => Some(BitField::Single(10)),
            1 => Some(BitField::Range(std::ops::Range{start: 3, end: 5})),
            _ => panic!("wrong bitfield position"),
        };

        println!("field {} @{:?}: {}", ident, bitfield, ty);
    }

    // return input;
    return output_struct(&ast.ident).parse().unwrap();
}

/*
Struct(
    Struct([
        Field {
            ident: Some(Ident("foo")),
            vis: Inherited,
            attrs: [
                Attribute {
                    style: Outer,
                    value: List(
                        Ident("bitfield"),
                        [MetaItem(NameValue(Ident("at"), Int(0, Unsuffixed)))]
                    ),
                    is_sugared_doc: false
                }
            ],
            ty: Path(
                None,
                Path {
                    global: false,
                    segments: [
                        PathSegment {
                            ident: Ident("u8"),
                            parameters: AngleBracketed(
                                AngleBracketedParameterData {
                                    lifetimes: [],
                                    types: [],
                                    bindings: []
                                }
                            )
                        }
                    ]
                }
            )
        }
    ])
)
*/<commit_msg>full parser<commit_after>#![feature(proc_macro)]

extern crate proc_macro;
extern crate syn;

#[macro_use]
extern crate quote;

use proc_macro::TokenStream;

fn output_struct(name: &syn::Ident) -> quote::Tokens {
    quote! {
        struct #name (u8);
        impl #name {
            pub fn get_bit() {

            }
        }
    }
}

#[derive(Debug)]
enum BitField {
    Single(u8),
    Range(std::ops::Range<u8>)
}

#[proc_macro_attribute]
pub fn register(_: TokenStream, input: TokenStream) -> TokenStream {
    use syn::*;

    println!("{}", input);

    let s = input.to_string();
    let ast = parse_derive_input(&s).unwrap();

    println!("ident: {}", ast.ident);

    let fields = match ast.body {
        Body::Enum(_) => panic!("enum not supported"),
        Body::Struct(x) => match x {
            VariantData::Struct(fields) => fields,
            _ => panic!("tuple and unit not supported")
        }
    };

    for field in &fields {
        let ident = field.ident.clone().unwrap();
        let ty = match field.clone().ty {
            Ty::Path(_, path) => path.segments[0].ident.clone(),
            _ => panic!("only path types supported"),
        };

        let mut from: Option<u8> = None;
        let mut to: Option<u8> = None;
        let mut at: Option<u8> = None;

        for attr in &field.attrs {
            if let MetaItem::List(attr_ident, attr_nest) = attr.clone().value {
                if attr_ident == "bitfield" {
                    for attr_nest_item in &attr_nest {
                        if let NestedMetaItem::MetaItem(nest_metaitem) = attr_nest_item.clone() {
                            if let MetaItem::NameValue(nv_ident, nv_lit) = nest_metaitem.clone() {
                                if let Lit::Int(nv_value, _) = nv_lit {
                                    match nv_ident.as_ref() {
                                        "at" => (at = Some(nv_value as u8)),
                                        "from" => (from = Some(nv_value as u8)),
                                        "to" => (to = Some(nv_value as u8)),
                                        _ => panic!("unsupported param name (use 'at' or 'from'/'to')"),
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        if (from.is_some() || to.is_some()) && at.is_some() {
            panic!("select 'at' or 'from'/'to' parameters, not both");
        }

        if from.is_some() ^ to.is_some() {
            panic!("select 'from' and 'to' parameters together");
        }

        if from.is_none() && to.is_none() && at.is_none() {
            panic!("select bit parameters (use #[bitfield(at=x or from=x to=y)])");
        }

        let bitfield: BitField = if from.is_some() && to.is_some() {
            BitField::Range(std::ops::Range{start: from.unwrap(), end: to.unwrap()})
        } else {
            BitField::Single(at.unwrap())
        };

        println!("field {} @{:?}: {}", ident, bitfield, ty);
    }

    // return input;
    return output_struct(&ast.ident).parse().unwrap();
}

/*
Struct(
    Struct([
        Field {
            ident: Some(Ident("foo")),
            vis: Inherited,
            attrs: [
                Attribute {
                    style: Outer,
                    value: List(
                        Ident("bitfield"),
                        [
                            MetaItem(
                                NameValue(
                                    Ident("at"), Int(0, Unsuffixed)
                                )
                            )
                        ]
                    ),
                    is_sugared_doc: false
                }
            ],
            ty: Path(
                None,
                Path {
                    global: false,
                    segments: [
                        PathSegment {
                            ident: Ident("u8"),
                            parameters: AngleBracketed(
                                AngleBracketedParameterData {
                                    lifetimes: [],
                                    types: [],
                                    bindings: []
                                }
                            )
                        }
                    ]
                }
            )
        }
    ])
)
*/<|endoftext|>


<commit_before>
pub fn puzzle(input: &str) -> usize {
    0
}

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

}
<commit_msg>Start a bot struct<commit_after>
pub fn puzzle(input: &str) -> usize {
    0
}

pub struct Bot {
    chip1: Option<usize>,
    chip2: Option<usize>,
}

impl Bot {
    pub fn new() -> Bot {
        Bot { chip1: None, chip2: None }
    }

    pub fn has_two_chips(&self) -> bool {
        match (self.chip1, self.chip2) {
            (Some(_), Some(_)) => true,
            _ => false,
        }
    }
}

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

    #[test]
    fn new_bot_does_not_have_two_chips() {
        let bot = Bot::new();
        assert!( ! bot.has_two_chips() );
    }
}
<|endoftext|>


<commit_before>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,no_run
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,no_run
//! # #[macro_use]
//! # extern crate text_io;
//! # fn main() {
//! let i: i32 = read!("The answer: {}!");
//! # }
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    () => { read!("{}") };
    ($text:expr) => {{
        let value;
        scan!($text, value);
        value
    }};
    ($text:expr, $input:expr) => {{
        let value;
        scan!($input => $text, value);
        value
    }};
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $text, $($arg),*) ;
        format_args!($text, $($arg),*);
    };
    ($input:expr => $text:expr, $($arg:expr),*) => {{
        use ::std::io::Read;
        use ::std::str::FromStr;
        // typesafe macros :)
        let text: &'static str = $text;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut text = text.bytes();
        $(
        loop { match text.next() {
            Some(b'{') => match text.next() {
                Some(b'{') => assert_eq!(Some(b'{'), stdin.next()),
                Some(b'}') => {
                    static WHITESPACES: &'static [u8] = b"\t\r\n ";
                    let s: Vec<u8> = match text.next() {
                        Some(c) => stdin.take_while(|&ch| ch != c).collect(),
                        None => stdin
                            .skip_while(|ch| WHITESPACES.contains(ch))
                            .take_while(|ch| !WHITESPACES.contains(ch))
                            .collect(),
                    };
                    let s = match ::std::str::from_utf8(&s) {
                        Ok(s) => s,
                        Err(e) => {
                            let n = e.valid_up_to();
                            if n == 0 {
                                panic!("input was not valid utf8: {:?}", s);
                            } else {
                                panic!("input was only partially valid utf8: \"{}\" followed by {:?}",
                                       ::std::str::from_utf8(&s[..n]).unwrap(), &s[n..]);
                            }
                        }
                    };
                    $arg = FromStr::from_str(s).expect(&format!("could not parse {} as target type of {}", s, stringify!($arg)));
                    break;
                }
                Some(_) => panic!("found bad curly brace"),
                None => panic!("found single open curly brace at the end of the format string"),
            },
            Some(c) => assert_eq!(Some(c), stdin.next()),
            None => panic!("Bad read! format string: did not contain {{}}"),
        } }
        )*
        for c in text {
            assert_eq!(Some(c), stdin.next());
        }
        format_args!($text, $($arg),*);
    }};
);
<commit_msg>Fix warning from unused Read trait import when not using stdin<commit_after>//! This crate allows one-liners to read from a terminal
//! A minimal example to get an i32 from the command line is
//!
//! ```rust,no_run
//! #[macro_use] extern crate text_io;
//! fn main() {
//!     let i: i32 = read!();
//! }
//! ```
//!
//! The `read!()` macro will always read until the next ascii whitespace character
//! (`\n`, `\r`, `\t` or space).
//!
//! Any type that implements the `FromStr` trait can be read with the `read!` macro.
//!
//! # Advanced
//! Text parsing can be done similar to `println!` by adding a format string
//! to the macro:
//!
//! ```rust,no_run
//! # #[macro_use]
//! # extern crate text_io;
//! # fn main() {
//! let i: i32 = read!("The answer: {}!");
//! # }
//! ```
//!
//! This will read `"The answer: "`, then an integer, then an exclamation mark. Any deviation from
//! the format string will result in a panic.
//!
//! Note: only a single value can be read per `read!` invocation.

/// All text input is handled through this macro
#[macro_export]
macro_rules! read(
    () => { read!("{}") };
    ($text:expr) => {{
        let value;
        scan!($text, value);
        value
    }};
    ($text:expr, $input:expr) => {{
        let value;
        scan!($input => $text, value);
        value
    }};
);

/// This macro allows to pass several variables so multiple values can be read
#[macro_export]
macro_rules! scan(
    ($text:expr, $($arg:expr),*) => {
        use ::std::io::Read;
        scan!(::std::io::stdin().bytes().map(|c| c.unwrap()) => $text, $($arg),*) ;
        format_args!($text, $($arg),*);
    };
    ($input:expr => $text:expr, $($arg:expr),*) => {{
        use ::std::str::FromStr;
        // typesafe macros :)
        let text: &'static str = $text;
        let stdin: &mut Iterator<Item = u8> = &mut ($input);

        let mut text = text.bytes();
        $(
        loop { match text.next() {
            Some(b'{') => match text.next() {
                Some(b'{') => assert_eq!(Some(b'{'), stdin.next()),
                Some(b'}') => {
                    static WHITESPACES: &'static [u8] = b"\t\r\n ";
                    let s: Vec<u8> = match text.next() {
                        Some(c) => stdin.take_while(|&ch| ch != c).collect(),
                        None => stdin
                            .skip_while(|ch| WHITESPACES.contains(ch))
                            .take_while(|ch| !WHITESPACES.contains(ch))
                            .collect(),
                    };
                    let s = match ::std::str::from_utf8(&s) {
                        Ok(s) => s,
                        Err(e) => {
                            let n = e.valid_up_to();
                            if n == 0 {
                                panic!("input was not valid utf8: {:?}", s);
                            } else {
                                panic!("input was only partially valid utf8: \"{}\" followed by {:?}",
                                       ::std::str::from_utf8(&s[..n]).unwrap(), &s[n..]);
                            }
                        }
                    };
                    $arg = FromStr::from_str(s).expect(&format!("could not parse {} as target type of {}", s, stringify!($arg)));
                    break;
                }
                Some(_) => panic!("found bad curly brace"),
                None => panic!("found single open curly brace at the end of the format string"),
            },
            Some(c) => assert_eq!(Some(c), stdin.next()),
            None => panic!("Bad read! format string: did not contain {{}}"),
        } }
        )*
        for c in text {
            assert_eq!(Some(c), stdin.next());
        }
        format_args!($text, $($arg),*);
    }};
);
<|endoftext|>