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

use prelude::v1::*;
use io::prelude::*;

use cmp;
use fmt;
use io::lazy::Lazy;
use io::{self, BufReader, LineWriter};
use sync::{Arc, Mutex, MutexGuard};
use sys::stdio;

/// A handle to a raw instance of the standard input stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdin_raw` function.
pub struct StdinRaw(stdio::Stdin);

/// A handle to a raw instance of the standard output stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdout_raw` function.
pub struct StdoutRaw(stdio::Stdout);

/// A handle to a raw instance of the standard output stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stderr_raw` function.
pub struct StderrRaw(stdio::Stderr);

/// Construct a new raw handle to the standard input of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
/// handles is **not** available to raw handles returned from this function.
///
/// The returned handle has no external synchronization or buffering.
pub fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }

/// Construct a new raw handle to the standard input stream of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdout`. Note that data is buffered by the
/// `std::io::stdin` handles so writes which happen via this raw handle may
/// appear before previous writes.
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
pub fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }

/// Construct a new raw handle to the standard input stream of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdout`.
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
pub fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) }

impl Read for StdinRaw {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
}
impl Write for StdoutRaw {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
impl Write for StderrRaw {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

/// A handle to the standard input stream of a process.
///
/// Each handle is a shared reference to a global buffer of input data to this
/// process. A handle can be `lock`'d to gain full access to `BufRead` methods
/// (e.g. `.lines()`). Writes to this handle are otherwise locked with respect
/// to other writes.
///
/// This handle implements the `Read` trait, but beware that concurrent reads
/// of `Stdin` must be executed with care.
pub struct Stdin {
    inner: Arc<Mutex<BufReader<StdinRaw>>>,
}

/// A locked reference to the a `Stdin` handle.
///
/// This handle implements both the `Read` and `BufRead` traits and is
/// constructed via the `lock` method on `Stdin`.
pub struct StdinLock<'a> {
    inner: MutexGuard<'a, BufReader<StdinRaw>>,
}

/// Create a new handle to the global standard input stream of this process.
///
/// The handle returned refers to a globally shared buffer between all threads.
/// Access is synchronized and can be explicitly controlled with the `lock()`
/// method.
///
/// The `Read` trait is implemented for the returned value but the `BufRead`
/// trait is not due to the global nature of the standard input stream. The
/// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
///
/// To avoid locking and buffering altogether, it is recommended to use the
/// `stdin_raw` constructor.
pub fn stdin() -> Stdin {
    static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = lazy_init!(stdin_init);
    return Stdin {
        inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
    };

    fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
        // The default buffer capacity is 64k, but apparently windows
        // doesn't like 64k reads on stdin. See #13304 for details, but the
        // idea is that on windows we use a slightly smaller buffer that's
        // been seen to be acceptable.
        Arc::new(Mutex::new(if cfg!(windows) {
            BufReader::with_capacity(8 * 1024, stdin_raw())
        } else {
            BufReader::new(stdin_raw())
        }))
    }
}

impl Stdin {
    /// Lock this handle to the standard input stream, returning a readable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Read` and `BufRead` traits for
    /// accessing the underlying data.
    pub fn lock(&self) -> StdinLock {
        StdinLock { inner: self.inner.lock().unwrap() }
    }
}

impl Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.lock().read(buf)
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> {
        self.lock().read_to_end(buf)
    }

    fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> {
        self.lock().read_to_string(buf)
    }
}

impl<'a> Read for StdinLock<'a> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        // Flush stdout so that weird issues like a print!'d prompt not being
        // shown until after the user hits enter.
        drop(stdout().flush());
        self.inner.read(buf)
    }
}
impl<'a> BufRead for StdinLock<'a> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
    fn consume(&mut self, n: usize) { self.inner.consume(n) }
}

// As with stdin on windows, stdout often can't handle writes of large
// sizes. For an example, see #14940. For this reason, don't try to
// write the entire output buffer on windows. On unix we can just
// write the whole buffer all at once.
//
// For some other references, it appears that this problem has been
// encountered by others [1] [2]. We choose the number 8KB just because
// libuv does the same.
//
// [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
// [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
#[cfg(windows)]
const OUT_MAX: usize = 8192;
#[cfg(unix)]
const OUT_MAX: usize = ::usize::MAX;

/// A handle to the global standard output stream of the current process.
///
/// Each handle shares a global buffer of data to be written to the standard
/// output stream. Access is also synchronized via a lock and explicit control
/// over locking is available via the `lock` method.
pub struct Stdout {
    // FIXME: this should be LineWriter or BufWriter depending on the state of
    //        stdout (tty or not). Note that if this is not line buffered it
    //        should also flush-on-panic or some form of flush-on-abort.
    inner: Arc<Mutex<LineWriter<StdoutRaw>>>,
}

/// A locked reference to the a `Stdout` handle.
///
/// This handle implements the `Write` trait and is constructed via the `lock`
/// method on `Stdout`.
pub struct StdoutLock<'a> {
    inner: MutexGuard<'a, LineWriter<StdoutRaw>>,
}

/// Constructs a new reference to the standard output of the current process.
///
/// Each handle returned is a reference to a shared global buffer whose access
/// is synchronized via a mutex. Explicit control over synchronization is
/// provided via the `lock` method.
///
/// The returned handle implements the `Write` trait.
///
/// To avoid locking and buffering altogether, it is recommended to use the
/// `stdout_raw` constructor.
pub fn stdout() -> Stdout {
    static INSTANCE: Lazy<Mutex<LineWriter<StdoutRaw>>> = lazy_init!(stdout_init);
    return Stdout {
        inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
    };

    fn stdout_init() -> Arc<Mutex<LineWriter<StdoutRaw>>> {
        Arc::new(Mutex::new(LineWriter::new(stdout_raw())))
    }
}

impl Stdout {
    /// Lock this handle to the standard output stream, returning a writable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Write` trait for writing data.
    pub fn lock(&self) -> StdoutLock {
        StdoutLock { inner: self.inner.lock().unwrap() }
    }
}

impl Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.lock().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.lock().flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.lock().write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.lock().write_fmt(fmt)
    }
}
impl<'a> Write for StdoutLock<'a> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
    }
    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
}

/// A handle to the standard error stream of a process.
///
/// For more information, see `stderr`
pub struct Stderr {
    inner: Arc<Mutex<StderrRaw>>,
}

/// A locked reference to the a `Stderr` handle.
///
/// This handle implements the `Write` trait and is constructed via the `lock`
/// method on `Stderr`.
pub struct StderrLock<'a> {
    inner: MutexGuard<'a, StderrRaw>,
}

/// Constructs a new reference to the standard error stream of a process.
///
/// Each returned handle is synchronized amongst all other handles created from
/// this function. No handles are buffered, however.
///
/// The returned handle implements the `Write` trait.
///
/// To avoid locking altogether, it is recommended to use the `stderr_raw`
/// constructor.
pub fn stderr() -> Stderr {
    static INSTANCE: Lazy<Mutex<StderrRaw>> = lazy_init!(stderr_init);
    return Stderr {
        inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
    };

    fn stderr_init() -> Arc<Mutex<StderrRaw>> {
        Arc::new(Mutex::new(stderr_raw()))
    }
}

impl Stderr {
    /// Lock this handle to the standard error stream, returning a writable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Write` trait for writing data.
    pub fn lock(&self) -> StderrLock {
        StderrLock { inner: self.inner.lock().unwrap() }
    }
}

impl Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.lock().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.lock().flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.lock().write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.lock().write_fmt(fmt)
    }
}
impl<'a> Write for StderrLock<'a> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
    }
    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
}
<commit_msg>Fix an easy to trigger deadlock in std::io::stdio<commit_after>// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use prelude::v1::*;
use io::prelude::*;

use cmp;
use fmt;
use io::lazy::Lazy;
use io::{self, BufReader, LineWriter};
use sync::{Arc, Mutex, MutexGuard};
use sys::stdio;

/// A handle to a raw instance of the standard input stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdin_raw` function.
pub struct StdinRaw(stdio::Stdin);

/// A handle to a raw instance of the standard output stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stdout_raw` function.
pub struct StdoutRaw(stdio::Stdout);

/// A handle to a raw instance of the standard output stream of this process.
///
/// This handle is not synchronized or buffered in any fashion. Constructed via
/// the `std::io::stderr_raw` function.
pub struct StderrRaw(stdio::Stderr);

/// Construct a new raw handle to the standard input of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdin`. Data buffered by the `std::io::stdin`
/// handles is **not** available to raw handles returned from this function.
///
/// The returned handle has no external synchronization or buffering.
pub fn stdin_raw() -> StdinRaw { StdinRaw(stdio::Stdin::new()) }

/// Construct a new raw handle to the standard input stream of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdout`. Note that data is buffered by the
/// `std::io::stdin` handles so writes which happen via this raw handle may
/// appear before previous writes.
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
pub fn stdout_raw() -> StdoutRaw { StdoutRaw(stdio::Stdout::new()) }

/// Construct a new raw handle to the standard input stream of this process.
///
/// The returned handle does not interact with any other handles created nor
/// handles returned by `std::io::stdout`.
///
/// The returned handle has no external synchronization or buffering layered on
/// top.
pub fn stderr_raw() -> StderrRaw { StderrRaw(stdio::Stderr::new()) }

impl Read for StdinRaw {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { self.0.read(buf) }
}
impl Write for StdoutRaw {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
impl Write for StderrRaw {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.write(buf) }
    fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

/// A handle to the standard input stream of a process.
///
/// Each handle is a shared reference to a global buffer of input data to this
/// process. A handle can be `lock`'d to gain full access to `BufRead` methods
/// (e.g. `.lines()`). Writes to this handle are otherwise locked with respect
/// to other writes.
///
/// This handle implements the `Read` trait, but beware that concurrent reads
/// of `Stdin` must be executed with care.
pub struct Stdin {
    inner: Arc<Mutex<BufReader<StdinRaw>>>,
}

/// A locked reference to the a `Stdin` handle.
///
/// This handle implements both the `Read` and `BufRead` traits and is
/// constructed via the `lock` method on `Stdin`.
pub struct StdinLock<'a> {
    inner: MutexGuard<'a, BufReader<StdinRaw>>,
}

/// Create a new handle to the global standard input stream of this process.
///
/// The handle returned refers to a globally shared buffer between all threads.
/// Access is synchronized and can be explicitly controlled with the `lock()`
/// method.
///
/// The `Read` trait is implemented for the returned value but the `BufRead`
/// trait is not due to the global nature of the standard input stream. The
/// locked version, `StdinLock`, implements both `Read` and `BufRead`, however.
///
/// To avoid locking and buffering altogether, it is recommended to use the
/// `stdin_raw` constructor.
pub fn stdin() -> Stdin {
    static INSTANCE: Lazy<Mutex<BufReader<StdinRaw>>> = lazy_init!(stdin_init);
    return Stdin {
        inner: INSTANCE.get().expect("cannot access stdin during shutdown"),
    };

    fn stdin_init() -> Arc<Mutex<BufReader<StdinRaw>>> {
        // The default buffer capacity is 64k, but apparently windows
        // doesn't like 64k reads on stdin. See #13304 for details, but the
        // idea is that on windows we use a slightly smaller buffer that's
        // been seen to be acceptable.
        Arc::new(Mutex::new(if cfg!(windows) {
            BufReader::with_capacity(8 * 1024, stdin_raw())
        } else {
            BufReader::new(stdin_raw())
        }))
    }
}

impl Stdin {
    /// Lock this handle to the standard input stream, returning a readable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Read` and `BufRead` traits for
    /// accessing the underlying data.
    pub fn lock(&self) -> StdinLock {
        StdinLock { inner: self.inner.lock().unwrap() }
    }
}

impl Read for Stdin {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.lock().read(buf)
    }

    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> {
        self.lock().read_to_end(buf)
    }

    fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> {
        self.lock().read_to_string(buf)
    }
}

impl<'a> Read for StdinLock<'a> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
        self.inner.read(buf)
    }
}
impl<'a> BufRead for StdinLock<'a> {
    fn fill_buf(&mut self) -> io::Result<&[u8]> { self.inner.fill_buf() }
    fn consume(&mut self, n: usize) { self.inner.consume(n) }
}

// As with stdin on windows, stdout often can't handle writes of large
// sizes. For an example, see #14940. For this reason, don't try to
// write the entire output buffer on windows. On unix we can just
// write the whole buffer all at once.
//
// For some other references, it appears that this problem has been
// encountered by others [1] [2]. We choose the number 8KB just because
// libuv does the same.
//
// [1]: https://tahoe-lafs.org/trac/tahoe-lafs/ticket/1232
// [2]: http://www.mail-archive.com/log4net-dev@logging.apache.org/msg00661.html
#[cfg(windows)]
const OUT_MAX: usize = 8192;
#[cfg(unix)]
const OUT_MAX: usize = ::usize::MAX;

/// A handle to the global standard output stream of the current process.
///
/// Each handle shares a global buffer of data to be written to the standard
/// output stream. Access is also synchronized via a lock and explicit control
/// over locking is available via the `lock` method.
pub struct Stdout {
    // FIXME: this should be LineWriter or BufWriter depending on the state of
    //        stdout (tty or not). Note that if this is not line buffered it
    //        should also flush-on-panic or some form of flush-on-abort.
    inner: Arc<Mutex<LineWriter<StdoutRaw>>>,
}

/// A locked reference to the a `Stdout` handle.
///
/// This handle implements the `Write` trait and is constructed via the `lock`
/// method on `Stdout`.
pub struct StdoutLock<'a> {
    inner: MutexGuard<'a, LineWriter<StdoutRaw>>,
}

/// Constructs a new reference to the standard output of the current process.
///
/// Each handle returned is a reference to a shared global buffer whose access
/// is synchronized via a mutex. Explicit control over synchronization is
/// provided via the `lock` method.
///
/// The returned handle implements the `Write` trait.
///
/// To avoid locking and buffering altogether, it is recommended to use the
/// `stdout_raw` constructor.
pub fn stdout() -> Stdout {
    static INSTANCE: Lazy<Mutex<LineWriter<StdoutRaw>>> = lazy_init!(stdout_init);
    return Stdout {
        inner: INSTANCE.get().expect("cannot access stdout during shutdown"),
    };

    fn stdout_init() -> Arc<Mutex<LineWriter<StdoutRaw>>> {
        Arc::new(Mutex::new(LineWriter::new(stdout_raw())))
    }
}

impl Stdout {
    /// Lock this handle to the standard output stream, returning a writable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Write` trait for writing data.
    pub fn lock(&self) -> StdoutLock {
        StdoutLock { inner: self.inner.lock().unwrap() }
    }
}

impl Write for Stdout {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.lock().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.lock().flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.lock().write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.lock().write_fmt(fmt)
    }
}
impl<'a> Write for StdoutLock<'a> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
    }
    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
}

/// A handle to the standard error stream of a process.
///
/// For more information, see `stderr`
pub struct Stderr {
    inner: Arc<Mutex<StderrRaw>>,
}

/// A locked reference to the a `Stderr` handle.
///
/// This handle implements the `Write` trait and is constructed via the `lock`
/// method on `Stderr`.
pub struct StderrLock<'a> {
    inner: MutexGuard<'a, StderrRaw>,
}

/// Constructs a new reference to the standard error stream of a process.
///
/// Each returned handle is synchronized amongst all other handles created from
/// this function. No handles are buffered, however.
///
/// The returned handle implements the `Write` trait.
///
/// To avoid locking altogether, it is recommended to use the `stderr_raw`
/// constructor.
pub fn stderr() -> Stderr {
    static INSTANCE: Lazy<Mutex<StderrRaw>> = lazy_init!(stderr_init);
    return Stderr {
        inner: INSTANCE.get().expect("cannot access stderr during shutdown"),
    };

    fn stderr_init() -> Arc<Mutex<StderrRaw>> {
        Arc::new(Mutex::new(stderr_raw()))
    }
}

impl Stderr {
    /// Lock this handle to the standard error stream, returning a writable
    /// guard.
    ///
    /// The lock is released when the returned lock goes out of scope. The
    /// returned guard also implements the `Write` trait for writing data.
    pub fn lock(&self) -> StderrLock {
        StderrLock { inner: self.inner.lock().unwrap() }
    }
}

impl Write for Stderr {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.lock().write(buf)
    }
    fn flush(&mut self) -> io::Result<()> {
        self.lock().flush()
    }
    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
        self.lock().write_all(buf)
    }
    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
        self.lock().write_fmt(fmt)
    }
}
impl<'a> Write for StderrLock<'a> {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        self.inner.write(&buf[..cmp::min(buf.len(), OUT_MAX)])
    }
    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::error::Error;
use std::fmt;
use std::fmt::{ Display, Formatter };
use std::io;
use std::io::Read;
use std::result;
use std::vec::Vec;

const BYTE_IDENTIFIER1_GZIP: u8 = 0x1f;
const BYTE_IDENTIFIER2_GZIP: u8 = 0x8b;
const BYTE_COMPRESSION_METHOD_DEFLATE: u8 = 0x08;

/// Wraps an input stream and provides methods for decompressing.
///
/// # Examples
///
/// extern crate compression;
///
/// use compression::gzip::Decompressor;
/// use std::fs::File;
///
/// let mut f = try!(File::open("compressed.txt.gz"));
/// let mut gzip = Decompressor::new(f);
pub struct Decompressor<R> {
	buf: VecDeque<u8>,
	extra_flags: Option<ExtraFlags>,
	flags: Option<Flags>,
	in_buf: Vec<u8>,
	in_stream: R,
	mtime: Option<u32>,
	os: Option<u8>,
	state: State,
}

#[derive(Debug, Clone, PartialEq)]
enum DecompressorError {
	InvalidOS,
	NeedMoreBytes,
	NonZeroReservedFlag,
	NonZeroReservedExtraFlag,
	UnknownIdentifier,
	UnknownCompressionMethod,
}

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

impl Error for DecompressorError {
	fn description(&self) -> &str {
		match self {
			&DecompressorError::InvalidOS => "Invalid OS identifier in gzip header",
			&DecompressorError::NeedMoreBytes => "Need more bytes",
			&DecompressorError::NonZeroReservedFlag => "Non-zero reserved flag in gzip header",
			&DecompressorError::NonZeroReservedExtraFlag => "Non-zero reserved extra-flag in gzip header",
			&DecompressorError::UnknownCompressionMethod => "Unknown compression method in gzip header",
			&DecompressorError::UnknownIdentifier => "Unknown identifier in gzip header (not a gzip file)",
		}
	}
}

#[derive(Debug, Clone, PartialEq)]
enum State {
	Error(DecompressorError),
	Initialized,
	Identification(Identification1, Identification2),
	CompressionMethod(CompressionMethod),
	Flags{
		ftext: bool,
		fhcrc: bool,
		fextra: bool,
		fname: bool,
		fcomment: bool,
	},
	MTime(u32),
	ExtraFlags{
		maximum_compression: bool,
		fastest_algorithm: bool,
	},
	OS(u8),
	FlagFExtra(bool),
	XLen(u16),
	FlagFName(bool),
	FlagFComment(bool),
	FlagFHCRC(bool),
}

#[derive(Debug, Clone, PartialEq)]
enum Identification1 {
	Gzip
}

#[derive(Debug, Clone, PartialEq)]
enum Identification2 {
	Gzip
}

#[derive(Debug, Clone, PartialEq)]
enum CompressionMethod {
	Deflate
}

struct Flags{
	ftext: bool,
	fhcrc: bool,
	fextra: bool,
	fname: bool,
	fcomment: bool,
}

struct ExtraFlags{
	maximum_compression: bool,
	fastest_algorithm: bool,
}

impl<R: Read> Decompressor<R> {
	pub fn new(in_stream: R) -> Decompressor<R> {
		Decompressor{
			buf: VecDeque::new(),
			extra_flags: None,
			flags: None,
			in_buf: Vec::new(),
			in_stream: in_stream,
			mtime: None,
			os: None,
			state: State::Initialized,
		}
	}

	fn get_state(&self) -> State {
		return self.state.clone();
	}

	fn read_identification(&mut self) {
		let mut buf = &mut [0u8, 0u8];

		match (self.in_stream.read(buf), (buf[0], buf[1])) {
			(Ok(2), (BYTE_IDENTIFIER1_GZIP, BYTE_IDENTIFIER2_GZIP)) => self.state = State::Identification(Identification1::Gzip, Identification2::Gzip),
			(Ok(2), (_, _)) => self.state = State::Error(DecompressorError::UnknownIdentifier),
			(Ok(_), (_, _)) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), (_, _)) => panic!(e),
		};
	}

	fn read_compression_method(&mut self) {
		let mut buf = &mut[0u8];

		match (self.in_stream.read(buf), buf[0]) {
			(Ok(1), BYTE_COMPRESSION_METHOD_DEFLATE) => self.state = State::CompressionMethod(CompressionMethod::Deflate),
			(Ok(1), _) => self.state = State::Error(DecompressorError::UnknownCompressionMethod),
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		};
	}

	fn read_flags(&mut self) {
		let mut buf = &mut[0u8];

		match (self.in_stream.read(buf), buf[0]) {
			(Ok(1), flags) => {
				if flags & 0b11100000 > 0 {

					self.state = State::Error(DecompressorError::NonZeroReservedFlag);
				} else {
					self.state = State::Flags{
						ftext:    flags &  1 > 0,
						fhcrc:    flags &  2 > 0,
						fextra:   flags &  4 > 0,
						fname:    flags &  8 > 0,
						fcomment: flags & 16 > 0,
					};
				}
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_mtime(&mut self) {
		let mut buf = &mut[0u8, 0u8, 0u8, 0u8];

		match (self.in_stream.read(buf), (buf[0], buf[1], buf[2], buf[3])) {
			(Ok(4), (mtime24, mtime16, mtime8, mtime0)) => {
				self.state = State::MTime(
					mtime0 as u32 | ((mtime8 as u32) << 8) | ((mtime16 as u32) << 16) | ((mtime24 as u32) << 24)
				);
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_extra_flags(&mut self) {
		let mut buf = &mut[0u8];

		match (self.in_stream.read(buf), buf[0]) {
			(Ok(1), flags) => {
				if flags & 0b11111001 > 0 {

					self.state = State::Error(DecompressorError::NonZeroReservedExtraFlag);
				} else {
					self.state = State::ExtraFlags{
						maximum_compression: flags &  2 > 0,
						fastest_algorithm:   flags &  4 > 0,
					};
				}
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_os(&mut self) {
		let mut buf = &mut[0u8];

		match (self.in_stream.read(buf), buf[0]) {
			(Ok(1), os) => {
				if os > 13 && os < 255 {
					self.state = State::Error(DecompressorError::InvalidOS,);
				} else {
					self.state = State::OS(os);
				}
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_xlen(&mut self) {
		let mut buf = &mut[0u8, 0u8];

		match (self.in_stream.read(buf), (buf[0], buf[1])) {
			(Ok(2), (xlen8, xlen0)) => {
				self.state = State::XLen(xlen0 as u16 | ((xlen8 as u16) << 8));
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_extra_field(&mut self, len: u16) {
		let mut buf = &mut vec![0u8; len as usize];

		match self.in_stream.read(buf) {
			Ok(bytes) if bytes == len as usize => {
				self.state = State::FlagFName(self.flags.unwrap().fname);
			},
			Ok(_) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			Err(e) => panic!(e),
		}
	}

	fn decompress(&mut self) -> result::Result<usize, DecompressorError> {
		loop {
			match self.get_state() {
				State::Initialized => self.read_identification(),
				State::Identification(id1, id2) => {
					assert_eq!((Identification1::Gzip, Identification2::Gzip), (id1, id2));
					self.read_compression_method();
				},
				State::CompressionMethod(cm) => {
					assert_eq!(CompressionMethod::Deflate, cm);
					self.read_flags();
				},
				State::Flags{ftext, fhcrc, fextra, fname, fcomment} => {
					self.flags = Some(Flags{
						ftext: ftext,
						fhcrc: fhcrc,
						fextra: fextra,
						fname: fname,
						fcomment: fcomment,
					});
					self.read_mtime();
				},
				State::MTime(mtime) => {
					self.mtime = Some(mtime);
					self.read_extra_flags();
				},
				State::ExtraFlags{ maximum_compression, fastest_algorithm } => {
					self.extra_flags = Some(ExtraFlags{
						maximum_compression: maximum_compression,
						fastest_algorithm: fastest_algorithm,
					});
					self.read_os();
				},
				State::OS(os) => {
					self.os = Some(os);
					self.state = State::FlagFExtra(self.flags.unwrap().fextra);
				},
				State::FlagFExtra(true) => {
					self.read_xlen();
				},
				State::XLen(xlen) => {
					self.read_extra_field(xlen);
				},
				State::FlagFExtra(false) => {
					self.state = State::FlagFName(self.flags.unwrap().fname);
				},
				State::FlagFName(true) => {
					panic!("Read file name now");
				},
				State::FlagFName(false) => {
					panic!("Do NOT read file name now");
				},
				State::FlagFComment(true) => {
					panic!("Read comment now");
				},
				State::FlagFComment(false) => {
					panic!("Do NOT read comment now");
				},
				State::FlagFHCRC(true) => {
					panic!("Read CRC16 now");
				},
				State::FlagFHCRC(false) => {
					panic!("Do NOT read CRC16 now");
				},
				State::Error(ref e) => {
					panic!(e.clone())
				}
			};
		}

		Ok(0)
	}
}

impl<R: Read> Read for Decompressor<R> {
	fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
		if self.buf.len() == 0 {
			match self.decompress() {
				Err(e) => panic!(e),
				Ok(_) => {},
			}
		}

		let l = if self.buf.len() < buf.len() {

			self.buf.len()
		} else {

			buf.len()
		};

		for i in 0..l {

			buf[i] = self.buf.pop_front().unwrap();
		}

		Ok(l)
	}
}<commit_msg>MOD: finished Gzip header<commit_after>use std::collections::VecDeque;
use std::error::Error;
use std::fmt;
use std::fmt::{ Display, Formatter };
use std::io;
use std::io::Read;
use std::result;
use std::string::String;
use std::vec::Vec;

const BYTE_IDENTIFIER1_GZIP: u8 = 0x1f;
const BYTE_IDENTIFIER2_GZIP: u8 = 0x8b;
const BYTE_COMPRESSION_METHOD_DEFLATE: u8 = 0x08;

/// Wraps an input stream and provides methods for decompressing.
///
/// # Examples
///
/// extern crate compression;
///
/// use compression::gzip::Decompressor;
/// use std::fs::File;
///
/// let mut f = try!(File::open("compressed.txt.gz"));
/// let mut gzip = Decompressor::new(f);
pub struct Decompressor<R> {
	buf: VecDeque<u8>,
	comment: Option<String>,
	crc16: Option<u16>,
	extra_flags: Option<ExtraFlags>,
	filename: Option<String>,
	flags: Option<Flags>,
	in_buf: Vec<u8>,
	in_stream: R,
	mtime: Option<u32>,
	os: Option<u8>,
	state: State,
}

#[derive(Debug, Clone, PartialEq)]
enum DecompressorError {
	InvalidOS,
	NeedMoreBytes,
	NonZeroReservedFlag,
	NonZeroReservedExtraFlag,
	UnknownIdentifier,
	UnknownCompressionMethod,
}

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

impl Error for DecompressorError {
	fn description(&self) -> &str {
		match self {
			&DecompressorError::InvalidOS => "Invalid OS identifier in gzip header",
			&DecompressorError::NeedMoreBytes => "Need more bytes",
			&DecompressorError::NonZeroReservedFlag => "Non-zero reserved flag in gzip header",
			&DecompressorError::NonZeroReservedExtraFlag => "Non-zero reserved extra-flag in gzip header",
			&DecompressorError::UnknownCompressionMethod => "Unknown compression method in gzip header",
			&DecompressorError::UnknownIdentifier => "Unknown identifier in gzip header (not a gzip file)",
		}
	}
}

#[derive(Debug, Clone, PartialEq)]
enum State {
	Error(DecompressorError),
	Initialized,
	Identification(Identification1, Identification2),
	CompressionMethod(CompressionMethod),
	Flags{
		ftext: bool,
		fhcrc: bool,
		fextra: bool,
		fname: bool,
		fcomment: bool,
	},
	MTime(u32),
	ExtraFlags{
		maximum_compression: bool,
		fastest_algorithm: bool,
	},
	OS(u8),
	FlagFExtra,
	XLen(u16),
	ExtraField(usize),
	FlagFName(bool),
	Filename(String),
	FlagFComment(bool),
	Comment(String),
	FlagFHCRC(bool),
	CRC16(u16),
}

#[derive(Debug, Clone, PartialEq)]
enum Identification1 {
	Gzip
}

#[derive(Debug, Clone, PartialEq)]
enum Identification2 {
	Gzip
}

#[derive(Debug, Clone, PartialEq)]
enum CompressionMethod {
	Deflate
}

struct Flags{
	ftext: bool,
	fhcrc: bool,
	fextra: bool,
	fname: bool,
	fcomment: bool,
}

struct ExtraFlags{
	maximum_compression: bool,
	fastest_algorithm: bool,
}

impl<R: Read> Decompressor<R> {
	pub fn new(in_stream: R) -> Decompressor<R> {
		Decompressor{
			buf: VecDeque::new(),
			comment: None,
			crc16: None,
			extra_flags: None,
			filename: None,
			flags: None,
			in_buf: Vec::new(),
			in_stream: in_stream,
			mtime: None,
			os: None,
			state: State::Initialized,
		}
	}

	fn get_state(&self) -> State {
		return self.state.clone();
	}

	fn read_identification(&mut self) {
		let mut buf = &mut [0u8, 0u8];

		match (self.in_stream.read(buf), (buf[0], buf[1])) {
			(Ok(2), (BYTE_IDENTIFIER1_GZIP, BYTE_IDENTIFIER2_GZIP)) => self.state = State::Identification(Identification1::Gzip, Identification2::Gzip),
			(Ok(2), (_, _)) => self.state = State::Error(DecompressorError::UnknownIdentifier),
			(Ok(_), (_, _)) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), (_, _)) => panic!(e),
		};
	}

	fn read_compression_method(&mut self) {
		let mut buf = &mut[0u8];

		match (self.in_stream.read(buf), buf[0]) {
			(Ok(1), BYTE_COMPRESSION_METHOD_DEFLATE) => self.state = State::CompressionMethod(CompressionMethod::Deflate),
			(Ok(1), _) => self.state = State::Error(DecompressorError::UnknownCompressionMethod),
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		};
	}

	fn read_flags(&mut self) {
		let mut buf = &mut[0u8];

		match (self.in_stream.read(buf), buf[0]) {
			(Ok(1), flags) => {
				if flags & 0b11100000 > 0 {

					self.state = State::Error(DecompressorError::NonZeroReservedFlag);
				} else {
					self.state = State::Flags{
						ftext:    flags &  1 > 0,
						fhcrc:    flags &  2 > 0,
						fextra:   flags &  4 > 0,
						fname:    flags &  8 > 0,
						fcomment: flags & 16 > 0,
					};
				}
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_mtime(&mut self) {
		let mut buf = &mut[0u8, 0u8, 0u8, 0u8];

		match (self.in_stream.read(buf), (buf[0], buf[1], buf[2], buf[3])) {
			(Ok(4), (mtime24, mtime16, mtime8, mtime0)) => {
				self.state = State::MTime(
					mtime0 as u32 | ((mtime8 as u32) << 8) | ((mtime16 as u32) << 16) | ((mtime24 as u32) << 24)
				);
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_extra_flags(&mut self) {
		let mut buf = &mut[0u8];

		match (self.in_stream.read(buf), buf[0]) {
			(Ok(1), flags) => {
				if flags & 0b11111001 > 0 {

					self.state = State::Error(DecompressorError::NonZeroReservedExtraFlag);
				} else {
					self.state = State::ExtraFlags{
						maximum_compression: flags &  2 > 0,
						fastest_algorithm:   flags &  4 > 0,
					};
				}
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_os(&mut self) {
		let mut buf = &mut[0u8];

		match (self.in_stream.read(buf), buf[0]) {
			(Ok(1), os) => {
				if os > 13 && os < 255 {
					self.state = State::Error(DecompressorError::InvalidOS,);
				} else {
					self.state = State::OS(os);
				}
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_xlen(&mut self) {
		let mut buf = &mut[0u8, 0u8];

		match (self.in_stream.read(buf), (buf[0], buf[1])) {
			(Ok(2), (xlen8, xlen0)) => {
				self.state = State::XLen(xlen0 as u16 | ((xlen8 as u16) << 8));
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn read_extra_field(&mut self, len: u16) {
		let mut buf = &mut vec![0u8; len as usize];

		match self.in_stream.read(buf) {
			Ok(bytes) if bytes == len as usize => {
				self.state = State::ExtraField(bytes);
			},
			Ok(_) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			Err(e) => panic!(e),
		}
	}

	fn read_filename(&mut self) {
		let mut buf  = &mut vec![0u8];
		let mut v = Vec::new();

		loop {
			match (self.in_stream.read(buf), buf[0]) {
				(Ok(1), 0) => break,
				(Ok(1), byte) => {
					v.push(byte);
				},
				(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
				(Err(e), _) => panic!(e),
			}
		}

		self.state = State::Filename(String::from_utf8(v).unwrap());
	}

	fn read_comment(&mut self) {
		let mut buf  = &mut vec![0u8];
		let mut v = Vec::new();

		loop {
			match (self.in_stream.read(buf), buf[0]) {
				(Ok(1), 0) => break,
				(Ok(1), byte) => {
					v.push(byte);
				},
				(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
				(Err(e), _) => panic!(e),
			}
		}

		self.state = State::Comment(String::from_utf8(v).unwrap());
	}

	fn read_crc16(&mut self) {
		let mut buf = &mut[0u8, 0u8];

		match (self.in_stream.read(buf), (buf[0], buf[1])) {
			(Ok(2), (crc168, crc160)) => {
				self.state = State::CRC16(crc160 as u16 | ((crc168 as u16) << 8));
			},
			(Ok(_), _) => self.state = State::Error(DecompressorError::NeedMoreBytes),
			(Err(e), _) => panic!(e),
		}
	}

	fn process_compressed_blocks(&mut self) {

		panic!("I guess I actually have to decompress now…");
	}

	fn decompress(&mut self) -> result::Result<usize, DecompressorError> {
		loop {
			match self.get_state() {
				State::Initialized => self.read_identification(),
				State::Identification(id1, id2) => {
					assert_eq!((Identification1::Gzip, Identification2::Gzip), (id1, id2));
					self.read_compression_method();
				},
				State::CompressionMethod(cm) => {
					assert_eq!(CompressionMethod::Deflate, cm);
					self.read_flags();
				},
				State::Flags{ftext, fhcrc, fextra, fname, fcomment} => {
					self.flags = Some(Flags{
						ftext: ftext,
						fhcrc: fhcrc,
						fextra: fextra,
						fname: fname,
						fcomment: fcomment,
					});
					self.read_mtime();
				},
				State::MTime(mtime) => {
					self.mtime = Some(mtime);
					self.read_extra_flags();
				},
				State::ExtraFlags{ maximum_compression, fastest_algorithm } => {
					self.extra_flags = Some(ExtraFlags{
						maximum_compression: maximum_compression,
						fastest_algorithm: fastest_algorithm,
					});
					self.read_os();
				},
				State::OS(os) => {
					self.os = Some(os);
					self.state = State::FlagFExtra;
				},
				State::FlagFExtra => {
					if self.flags.as_ref().unwrap().fextra {

						self.read_xlen();
					} else {

						self.state = State::FlagFName(self.flags.as_ref().unwrap().fname);
					}
				},
				State::XLen(xlen) => {

					self.read_extra_field(xlen);
				},
				State::ExtraField(xlen) => {

					self.state = State::FlagFName(self.flags.as_ref().unwrap().fname);
				},
				State::FlagFName(true) => {

					self.read_filename();
				},
				State::Filename(filename) => {
					self.filename = Some(filename);
					self.state = State::FlagFComment(self.flags.as_ref().unwrap().fcomment);
				},
				State::FlagFName(false) => {

					self.state = State::FlagFComment(self.flags.as_ref().unwrap().fcomment);
				},
				State::FlagFComment(true) => {

					self.read_comment();
				},
				State::Comment(comment) => {
					self.comment = Some(comment);
					self.state = State::FlagFHCRC(self.flags.as_ref().unwrap().fcomment);
				}
				State::FlagFComment(false) => {

					self.state = State::FlagFHCRC(self.flags.as_ref().unwrap().fhcrc);
				},
				State::FlagFHCRC(true) => {

					self.read_crc16()
				},
				State::CRC16(crc16) => {
					self.crc16 = Some(crc16);
					self.process_compressed_blocks();
				},
				State::FlagFHCRC(false) => {

					self.process_compressed_blocks();
				},
				State::Error(ref e) => {

					panic!(e.clone())
				},
			};
		}

		Ok(0)
	}
}

impl<R: Read> Read for Decompressor<R> {
	fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
		if self.buf.len() == 0 {
			match self.decompress() {
				Err(e) => panic!(e),
				Ok(_) => {},
			}
		}

		let l = if self.buf.len() < buf.len() {

			self.buf.len()
		} else {

			buf.len()
		};

		for i in 0..l {

			buf[i] = self.buf.pop_front().unwrap();
		}

		Ok(l)
	}
}<|endoftext|>


<commit_before>//! Basic types to build the parsers

use self::IResult::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
  /// to a contained `Done` value, leaving `Error` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
  /// to a contained `Error` value, leaving `Done` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
   where F: FnOnce(Err<I, E>) -> Err<I, N> {
    match self {
      Error(e)      => Error(f(e)),
      Incomplete(n) => Incomplete(n),
      Done(i, o)    => Done(i, o),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}

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

  #[test]
  fn iresult_map() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map(|x| x * 2), IResult::Done(&b""[..], 10));
    assert_eq!(error.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(incomplete.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
  }

  #[test]
  fn iresult_map_err() {
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct Error(u32);

    let error_kind = Err::Code(ErrorKind::Custom(Error(5)));

    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_err(|x| error_kind.clone()), IResult::Error(error_kind.clone()));
    assert_eq!(incomplete.map_err(|x| error_kind.clone()), IResult::Incomplete(Needed::Unknown));
  }
}
<commit_msg>Added map (and is_known) function for enum Needed<commit_after>//! Basic types to build the parsers

use self::IResult::*;
use self::Needed::*;
use util::ErrorKind;

#[cfg(feature = "core")]
use std::prelude::v1::*;
use std::boxed::Box;

/// Contains the error that a parser can return
///
/// It can represent a linked list of errors, indicating the path taken in the parsing tree, with corresponding position in the input data.
/// It depends on P, the input position (for a &[u8] parser, it would be a &[u8]), and E, the custom error type (by default, u32)
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum Err<P,E=u32>{
  /// An error code, represented by an ErrorKind, which can contain a custom error code represented by E
  Code(ErrorKind<E>),
  /// An error code, and the next error
  Node(ErrorKind<E>, Box<Err<P,E>>),
  /// An error code, and the input position
  Position(ErrorKind<E>, P),
  /// An error code, the input position and the next error
  NodePosition(ErrorKind<E>, P, Box<Err<P,E>>)
}

/// Contains information on needed data if a parser returned `Incomplete`
#[derive(Debug,PartialEq,Eq,Clone,Copy)]
pub enum Needed {
  /// needs more data, but we do not know how much
  Unknown,
  /// contains the required data size
  Size(usize)
}

impl Needed {
  pub fn is_known(&self) -> bool {
    *self != Unknown
  }

  /// Maps a `Needed` to `Needed` by appling a function to a contained `Size` value.
  #[inline]
  pub fn map<F: FnOnce(usize) -> usize>(self, f: F) -> Needed {
    match self {
      Unknown => Unknown,
      Size(n) => Size(f(n)),
    }
  }
}

/// Holds the result of parsing functions
///
/// It depends on I, the input type, O, the output type, and E, the error type (by default u32)
///
#[derive(Debug,PartialEq,Eq,Clone)]
pub enum IResult<I,O,E=u32> {
   /// indicates a correct parsing, the first field containing the rest of the unparsed data, the second field contains the parsed data
  Done(I,O),
  /// contains a Err, an enum that can indicate an error code, a position in the input, and a pointer to another error, making a list of errors in the parsing tree
  Error(Err<I,E>),
  /// Incomplete contains a Needed, an enum than can represent a known quantity of input data, or unknown
  Incomplete(Needed)
}

impl<I,O,E> IResult<I,O,E> {
  pub fn is_done(&self) -> bool {
    match *self {
      Done(_,_) => true,
      _         => false
    }
  }

  pub fn is_err(&self) -> bool {
    match *self {
      Error(_) => true,
      _        => false
    }
  }

  pub fn is_incomplete(&self) -> bool {
    match *self {
      Incomplete(_) => true,
      _             => false
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, N, E>` by appling a function
  /// to a contained `Done` value, leaving `Error` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map<N, F: FnOnce(O) -> N>(self, f: F) -> IResult<I, N, E> {
    match self {
      Done(i, o)    => Done(i, f(o)),
      Error(e)      => Error(e),
      Incomplete(n) => Incomplete(n),
    }
  }

  /// Maps a `IResult<I, O, E>` to `IResult<I, O, N>` by appling a function
  /// to a contained `Error` value, leaving `Done` and `Incomplete` value
  /// untouched.
  #[inline]
  pub fn map_err<N, F>(self, f: F) -> IResult<I, O, N>
   where F: FnOnce(Err<I, E>) -> Err<I, N> {
    match self {
      Error(e)      => Error(f(e)),
      Incomplete(n) => Incomplete(n),
      Done(i, o)    => Done(i, o),
    }
  }
}

pub trait GetInput<I> {
  fn remaining_input(&self) -> Option<I>;
}

pub trait GetOutput<O> {
  fn output(&self) -> Option<O>;
}

impl<'a,I,O,E> GetInput<&'a[I]> for IResult<&'a[I],O,E> {
  fn remaining_input(&self) -> Option<&'a[I]> {
    match *self {
      Done(ref i,_) => Some(*i),
      _             => None
    }
  }
}

impl<O,E> GetInput<()> for IResult<(),O,E> {
  fn remaining_input(&self) -> Option<()> {
    match *self {
      Done((),_) => Some(()),
      _          => None
    }
  }
}

impl<'a,O,E> GetInput<&'a str> for IResult<&'a str,O,E> {
  fn remaining_input(&self) -> Option<&'a str> {
    match *self {
      Done(ref i,_) => Some(*i),
      _          => None
    }
  }
}

impl<'a,I,O,E> GetOutput<&'a[O]> for IResult<I,&'a[O],E> {
  fn output(&self) -> Option<&'a[O]> {
    match *self {
      Done(_, ref o) => Some(*o),
      _              => None
    }
  }
}

impl<I,E> GetOutput<()> for IResult<I,(),E> {
  fn output(&self) -> Option<()> {
    match *self {
      Done(_,()) => Some(()),
      _          => None
    }
  }
}

impl<'a,I,E> GetOutput<&'a str> for IResult<I,&'a str,E> {
  fn output(&self) -> Option<&'a str> {
    match *self {
      Done(_,ref o) => Some(*o),
      _          => None
    }
  }
}

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

  #[test]
  fn needed_map() {
    let unknown = Needed::Unknown;
    let size = Needed::Size(5);

    assert_eq!(size.map(|x| x * 2), Needed::Size(10));
    assert_eq!(unknown.map(|x| x * 2), Needed::Unknown);
  }

  #[test]
  fn iresult_map() {
    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map(|x| x * 2), IResult::Done(&b""[..], 10));
    assert_eq!(error.map(|x| x * 2), IResult::Error(Err::Code(ErrorKind::Tag)));
    assert_eq!(incomplete.map(|x| x * 2), IResult::Incomplete(Needed::Unknown));
  }

  #[test]
  fn iresult_map_err() {
    #[derive(Clone, Copy, Debug, PartialEq, Eq)]
    struct Error(u32);

    let error_kind = Err::Code(ErrorKind::Custom(Error(5)));

    let done: IResult<&[u8], u32> = IResult::Done(&b""[..], 5);
    let error: IResult<&[u8], u32> = IResult::Error(Err::Code(ErrorKind::Tag));
    let incomplete: IResult<&[u8], u32> = IResult::Incomplete(Needed::Unknown);

    assert_eq!(done.map_err(|_| error_kind.clone()), IResult::Done(&b""[..], 5));
    assert_eq!(error.map_err(|x| error_kind.clone()), IResult::Error(error_kind.clone()));
    assert_eq!(incomplete.map_err(|x| error_kind.clone()), IResult::Incomplete(Needed::Unknown));
  }
}
<|endoftext|>


<commit_before>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::fmt;
use std::fs::OpenOptions;
use std::io;
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::sleep;
use std::time::Duration;

use libc;

use crate::gpio::{Error, Level, Mode, PullUpDown, Result};
use crate::system::DeviceInfo;

// The BCM2835 has 41 32-bit registers related to the GPIO (datasheet @ 6.1).
const GPIO_MEM_REGISTERS: usize = 41;
const GPIO_MEM_SIZE: usize = GPIO_MEM_REGISTERS * std::mem::size_of::<u32>();

const GPFSEL0: usize = 0x00;
const GPSET0: usize = 0x1c / std::mem::size_of::<u32>();
const GPCLR0: usize = 0x28 / std::mem::size_of::<u32>();
const GPLEV0: usize = 0x34 / std::mem::size_of::<u32>();
const GPPUD: usize = 0x94 / std::mem::size_of::<u32>();
const GPPUDCLK0: usize = 0x98 / std::mem::size_of::<u32>();

pub struct GpioMem {
    mem_ptr: *mut u32,
    locks: [AtomicBool; GPIO_MEM_REGISTERS],
}

impl fmt::Debug for GpioMem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("GpioMem")
            .field("mem_ptr", &self.mem_ptr)
            .field("locks", &format_args!("{{ .. }}"))
            .finish()
    }
}

impl GpioMem {
    pub fn open() -> Result<GpioMem> {
        // Try /dev/gpiomem first. If that fails, try /dev/mem instead. If neither works,
        // report back the error that's the most relevant.
        let mem_ptr = match Self::map_devgpiomem() {
            Ok(ptr) => ptr,
            Err(gpiomem_err) => match Self::map_devmem() {
                Ok(ptr) => ptr,
                Err(Error::Io(ref e)) if e.kind() == io::ErrorKind::PermissionDenied => {
                    return Err(Error::PermissionDenied)
                }
                Err(Error::UnknownSoC) => return Err(Error::UnknownSoC),
                _ => return Err(gpiomem_err),
            },
        };

        let locks = init_array!(AtomicBool::new(false), GPIO_MEM_REGISTERS);

        Ok(GpioMem { mem_ptr, locks })
    }

    fn map_devgpiomem() -> Result<*mut u32> {
        // Open /dev/gpiomem with read/write/sync flags. This might fail if
        // /dev/gpiomem doesn't exist (< Raspbian Jessie), or /dev/gpiomem
        // doesn't have the appropriate permissions, or the current user is
        // not a member of the gpio group.
        let gpiomem_file = OpenOptions::new()
            .read(true)
            .write(true)
            .custom_flags(libc::O_SYNC)
            .open("/dev/gpiomem")?;

        // Memory-map /dev/gpiomem at offset 0
        let gpiomem_ptr = unsafe {
            libc::mmap(
                ptr::null_mut(),
                GPIO_MEM_SIZE,
                libc::PROT_READ | libc::PROT_WRITE,
                libc::MAP_SHARED,
                gpiomem_file.as_raw_fd(),
                0,
            )
        };

        if gpiomem_ptr == libc::MAP_FAILED {
            return Err(Error::Io(io::Error::last_os_error()));
        }

        Ok(gpiomem_ptr as *mut u32)
    }

    fn map_devmem() -> Result<*mut u32> {
        // Identify which SoC we're using, so we know what offset to start at
        let device_info = DeviceInfo::new().map_err(|_| Error::UnknownSoC)?;

        let mem_file = OpenOptions::new()
            .read(true)
            .write(true)
            .custom_flags(libc::O_SYNC)
            .open("/dev/mem")?;

        // Memory-map /dev/mem at the appropriate offset for our SoC
        let mem_ptr = unsafe {
            libc::mmap(
                ptr::null_mut(),
                GPIO_MEM_SIZE,
                libc::PROT_READ | libc::PROT_WRITE,
                libc::MAP_SHARED,
                mem_file.as_raw_fd(),
                (device_info.peripheral_base() + device_info.gpio_offset()) as libc::off_t,
            )
        };

        if mem_ptr == libc::MAP_FAILED {
            return Err(Error::Io(io::Error::last_os_error()));
        }

        Ok(mem_ptr as *mut u32)
    }

    fn read(&self, offset: usize) -> u32 {
        loop {
            if !self.locks[offset].compare_and_swap(false, true, Ordering::SeqCst) {
                break;
            }
        }

        let reg_value = unsafe { ptr::read_volatile(self.mem_ptr.add(offset)) };

        self.locks[offset].store(false, Ordering::SeqCst);

        reg_value
    }

    fn write(&self, offset: usize, value: u32) {
        loop {
            if !self.locks[offset].compare_and_swap(false, true, Ordering::SeqCst) {
                break;
            }
        }

        unsafe {
            ptr::write_volatile(self.mem_ptr.add(offset), value);
        }

        self.locks[offset].store(false, Ordering::SeqCst);
    }

    pub fn set_high(&self, pin: u8) {
        let offset = GPSET0 + pin as usize / 32;
        let shift = pin % 32;
        self.write(offset, 1 << shift);
    }

    pub fn set_low(&self, pin: u8) {
        let offset = GPCLR0 + pin as usize / 32;
        let shift = pin % 32;
        self.write(offset, 1 << shift);
    }

    pub fn level(&self, pin: u8) -> Level {
        let offset = GPLEV0 + pin as usize / 32;
        let shift = pin % 32;

        let reg_value = self.read(offset);

        unsafe { std::mem::transmute((reg_value >> shift) as u8 & 0b1) }
    }

    pub fn mode(&self, pin: u8) -> Mode {
        let offset = GPFSEL0 + pin as usize / 10;
        let shift = (pin % 10) * 3;

        let reg_value = self.read(offset);

        unsafe { std::mem::transmute((reg_value >> shift) as u8 & 0b111) }
    }

    pub fn set_mode(&self, pin: u8, mode: Mode) {
        let offset = GPFSEL0 + pin as usize / 10;
        let shift = (pin % 10) * 3;

        loop {
            if !self.locks[offset].compare_and_swap(false, true, Ordering::SeqCst) {
                break;
            }
        }

        unsafe {
            let mem_ptr = self.mem_ptr.add(offset);
            let reg_value = ptr::read_volatile(mem_ptr);
            ptr::write_volatile(
                mem_ptr,
                (reg_value & !(0b111 << shift)) | ((mode as u32) << shift),
            );
        }

        self.locks[offset].store(false, Ordering::SeqCst);
    }

    /// Configures the built-in GPIO pull-up/pull-down resistors.
    pub fn set_pullupdown(&self, pin: u8, pud: PullUpDown) {
        let offset = GPPUDCLK0 + pin as usize / 32;
        let shift = pin % 32;

        loop {
            if !self.locks[GPPUD].compare_and_swap(false, true, Ordering::SeqCst) {
                if !self.locks[offset].compare_and_swap(false, true, Ordering::SeqCst) {
                    break;
                } else {
                    self.locks[GPPUD].store(false, Ordering::SeqCst);
                }
            }
        }

        // Set the control signal in GPPUD, while leaving the other 30
        // bits unchanged.
        unsafe {
            let mem_ptr = self.mem_ptr.add(GPPUD);
            let reg_value = ptr::read_volatile(mem_ptr);
            ptr::write_volatile(mem_ptr, (reg_value & !0b11) | ((pud as u32) & 0b11));
        }

        // Set-up time for the control signal.
        sleep(Duration::new(0, 20000)); // >= 20µs

        // Clock the control signal into the selected pin.
        unsafe {
            let mem_ptr = self.mem_ptr.add(offset);
            ptr::write_volatile(mem_ptr, 1 << shift);
        }

        // Hold time for the control signal.
        sleep(Duration::new(0, 20000)); // >= 20µs

        // Remove the control signal and clock.
        unsafe {
            let mem_ptr = self.mem_ptr.add(GPPUD);
            let reg_value = ptr::read_volatile(mem_ptr);
            ptr::write_volatile(mem_ptr, reg_value & !0b11);
        }

        unsafe {
            let mem_ptr = self.mem_ptr.add(offset);
            ptr::write_volatile(mem_ptr, 0 << shift);
        }

        self.locks[offset].store(false, Ordering::SeqCst);
        self.locks[GPPUD].store(false, Ordering::SeqCst);
    }
}

impl Drop for GpioMem {
    fn drop(&mut self) {
        unsafe {
            libc::munmap(
                self.mem_ptr as *mut libc::c_void,
                GPIO_MEM_SIZE as libc::size_t,
            );
        }
    }
}

// Required because of the raw pointer to our memory-mapped file
unsafe impl Send for GpioMem {}
unsafe impl Sync for GpioMem {}
<commit_msg>Store GpioMem locks in static variable<commit_after>// Copyright (c) 2017-2018 Rene van der Meer
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the "Software"),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
// and/or sell copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

use std::fmt;
use std::fs::OpenOptions;
use std::io;
use std::os::unix::fs::OpenOptionsExt;
use std::os::unix::io::AsRawFd;
use std::ptr;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread::sleep;
use std::time::Duration;

use lazy_static::lazy_static;
use libc;

use crate::gpio::{Error, Level, Mode, PullUpDown, Result};
use crate::system::DeviceInfo;

// The BCM2835 has 41 32-bit registers related to the GPIO (datasheet @ 6.1).
const GPIO_MEM_REGISTERS: usize = 41;
const GPIO_MEM_SIZE: usize = GPIO_MEM_REGISTERS * std::mem::size_of::<u32>();

const GPFSEL0: usize = 0x00;
const GPSET0: usize = 0x1c / std::mem::size_of::<u32>();
const GPCLR0: usize = 0x28 / std::mem::size_of::<u32>();
const GPLEV0: usize = 0x34 / std::mem::size_of::<u32>();
const GPPUD: usize = 0x94 / std::mem::size_of::<u32>();
const GPPUDCLK0: usize = 0x98 / std::mem::size_of::<u32>();

// Keep track of locks across multiple GpioMem instances. This is necessary
// in situations where a pin is kept around after Gpio goes out of scope, and
// then another Gpio is created from which additional pins are retrieved. At
// some point all Gpio/GpioMem static variables should probably be combined into
// a single static struct.
lazy_static! {
    static ref GPIOMEM_LOCKS: [AtomicBool; GPIO_MEM_REGISTERS] =
        init_array!(AtomicBool::new(false), GPIO_MEM_REGISTERS);
}

pub struct GpioMem {
    mem_ptr: *mut u32,
}

impl fmt::Debug for GpioMem {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("GpioMem")
            .field("mem_ptr", &self.mem_ptr)
            .finish()
    }
}

impl GpioMem {
    pub fn open() -> Result<GpioMem> {
        // Try /dev/gpiomem first. If that fails, try /dev/mem instead. If neither works,
        // report back the error that's the most relevant.
        let mem_ptr = match Self::map_devgpiomem() {
            Ok(ptr) => ptr,
            Err(gpiomem_err) => match Self::map_devmem() {
                Ok(ptr) => ptr,
                Err(Error::Io(ref e)) if e.kind() == io::ErrorKind::PermissionDenied => {
                    return Err(Error::PermissionDenied)
                }
                Err(Error::UnknownSoC) => return Err(Error::UnknownSoC),
                _ => return Err(gpiomem_err),
            },
        };

        Ok(GpioMem { mem_ptr })
    }

    fn map_devgpiomem() -> Result<*mut u32> {
        // Open /dev/gpiomem with read/write/sync flags. This might fail if
        // /dev/gpiomem doesn't exist (< Raspbian Jessie), or /dev/gpiomem
        // doesn't have the appropriate permissions, or the current user is
        // not a member of the gpio group.
        let gpiomem_file = OpenOptions::new()
            .read(true)
            .write(true)
            .custom_flags(libc::O_SYNC)
            .open("/dev/gpiomem")?;

        // Memory-map /dev/gpiomem at offset 0
        let gpiomem_ptr = unsafe {
            libc::mmap(
                ptr::null_mut(),
                GPIO_MEM_SIZE,
                libc::PROT_READ | libc::PROT_WRITE,
                libc::MAP_SHARED,
                gpiomem_file.as_raw_fd(),
                0,
            )
        };

        if gpiomem_ptr == libc::MAP_FAILED {
            return Err(Error::Io(io::Error::last_os_error()));
        }

        Ok(gpiomem_ptr as *mut u32)
    }

    fn map_devmem() -> Result<*mut u32> {
        // Identify which SoC we're using, so we know what offset to start at
        let device_info = DeviceInfo::new().map_err(|_| Error::UnknownSoC)?;

        let mem_file = OpenOptions::new()
            .read(true)
            .write(true)
            .custom_flags(libc::O_SYNC)
            .open("/dev/mem")?;

        // Memory-map /dev/mem at the appropriate offset for our SoC
        let mem_ptr = unsafe {
            libc::mmap(
                ptr::null_mut(),
                GPIO_MEM_SIZE,
                libc::PROT_READ | libc::PROT_WRITE,
                libc::MAP_SHARED,
                mem_file.as_raw_fd(),
                (device_info.peripheral_base() + device_info.gpio_offset()) as libc::off_t,
            )
        };

        if mem_ptr == libc::MAP_FAILED {
            return Err(Error::Io(io::Error::last_os_error()));
        }

        Ok(mem_ptr as *mut u32)
    }

    fn read(&self, offset: usize) -> u32 {
        loop {
            if !GPIOMEM_LOCKS[offset].compare_and_swap(false, true, Ordering::SeqCst) {
                break;
            }
        }

        let reg_value = unsafe { ptr::read_volatile(self.mem_ptr.add(offset)) };

        GPIOMEM_LOCKS[offset].store(false, Ordering::SeqCst);

        reg_value
    }

    fn write(&self, offset: usize, value: u32) {
        loop {
            if !GPIOMEM_LOCKS[offset].compare_and_swap(false, true, Ordering::SeqCst) {
                break;
            }
        }

        unsafe {
            ptr::write_volatile(self.mem_ptr.add(offset), value);
        }

        GPIOMEM_LOCKS[offset].store(false, Ordering::SeqCst);
    }

    pub fn set_high(&self, pin: u8) {
        let offset = GPSET0 + pin as usize / 32;
        let shift = pin % 32;
        self.write(offset, 1 << shift);
    }

    pub fn set_low(&self, pin: u8) {
        let offset = GPCLR0 + pin as usize / 32;
        let shift = pin % 32;
        self.write(offset, 1 << shift);
    }

    pub fn level(&self, pin: u8) -> Level {
        let offset = GPLEV0 + pin as usize / 32;
        let shift = pin % 32;

        let reg_value = self.read(offset);

        unsafe { std::mem::transmute((reg_value >> shift) as u8 & 0b1) }
    }

    pub fn mode(&self, pin: u8) -> Mode {
        let offset = GPFSEL0 + pin as usize / 10;
        let shift = (pin % 10) * 3;

        let reg_value = self.read(offset);

        unsafe { std::mem::transmute((reg_value >> shift) as u8 & 0b111) }
    }

    pub fn set_mode(&self, pin: u8, mode: Mode) {
        let offset = GPFSEL0 + pin as usize / 10;
        let shift = (pin % 10) * 3;

        loop {
            if !GPIOMEM_LOCKS[offset].compare_and_swap(false, true, Ordering::SeqCst) {
                break;
            }
        }

        unsafe {
            let mem_ptr = self.mem_ptr.add(offset);
            let reg_value = ptr::read_volatile(mem_ptr);
            ptr::write_volatile(
                mem_ptr,
                (reg_value & !(0b111 << shift)) | ((mode as u32) << shift),
            );
        }

        GPIOMEM_LOCKS[offset].store(false, Ordering::SeqCst);
    }

    /// Configures the built-in GPIO pull-up/pull-down resistors.
    pub fn set_pullupdown(&self, pin: u8, pud: PullUpDown) {
        let offset = GPPUDCLK0 + pin as usize / 32;
        let shift = pin % 32;

        loop {
            if !GPIOMEM_LOCKS[GPPUD].compare_and_swap(false, true, Ordering::SeqCst) {
                if !GPIOMEM_LOCKS[offset].compare_and_swap(false, true, Ordering::SeqCst) {
                    break;
                } else {
                    GPIOMEM_LOCKS[GPPUD].store(false, Ordering::SeqCst);
                }
            }
        }

        // Set the control signal in GPPUD, while leaving the other 30
        // bits unchanged.
        unsafe {
            let mem_ptr = self.mem_ptr.add(GPPUD);
            let reg_value = ptr::read_volatile(mem_ptr);
            ptr::write_volatile(mem_ptr, (reg_value & !0b11) | ((pud as u32) & 0b11));
        }

        // Set-up time for the control signal.
        sleep(Duration::new(0, 20000)); // >= 20µs

        // Clock the control signal into the selected pin.
        unsafe {
            let mem_ptr = self.mem_ptr.add(offset);
            ptr::write_volatile(mem_ptr, 1 << shift);
        }

        // Hold time for the control signal.
        sleep(Duration::new(0, 20000)); // >= 20µs

        // Remove the control signal and clock.
        unsafe {
            let mem_ptr = self.mem_ptr.add(GPPUD);
            let reg_value = ptr::read_volatile(mem_ptr);
            ptr::write_volatile(mem_ptr, reg_value & !0b11);
        }

        unsafe {
            let mem_ptr = self.mem_ptr.add(offset);
            ptr::write_volatile(mem_ptr, 0 << shift);
        }

        GPIOMEM_LOCKS[offset].store(false, Ordering::SeqCst);
        GPIOMEM_LOCKS[GPPUD].store(false, Ordering::SeqCst);
    }
}

impl Drop for GpioMem {
    fn drop(&mut self) {
        unsafe {
            libc::munmap(
                self.mem_ptr as *mut libc::c_void,
                GPIO_MEM_SIZE as libc::size_t,
            );
        }
    }
}

// Required because of the raw pointer to our memory-mapped file
unsafe impl Send for GpioMem {}
unsafe impl Sync for GpioMem {}
<|endoftext|>


<commit_before>#[derive(Debug, PartialEq)]
pub enum Error {
    EmptyBuffer,
    FullBuffer,
}

pub struct CircularBuffer<T: Default + Clone> {
    buffer: Vec<T>,
    size: usize,
    start: usize,
    end: usize,
}

impl<T: Default + Clone> CircularBuffer<T> {
    // this circular buffer keeps an unallocated slot between the start and the end
    // when the buffer is full.
    pub fn new(size: usize) -> CircularBuffer<T> {
        CircularBuffer {
            buffer: vec![T::default(); size + 1],
            size: size + 1,
            start: 0,
            end: 0,
        }
    }

    pub fn read(&mut self) -> Result<T, Error> {
        if self.is_empty() {
            return Err(Error::EmptyBuffer);
        }

        let v = self.buffer.get(self.start).unwrap().clone();
        self.advance_start();
        Ok(v)
    }

    pub fn write(&mut self, byte: T) -> Result<(), Error> {
        if self.is_full() {
            return Err(Error::FullBuffer);
        }

        self.buffer[self.end] = byte;
        self.advance_end();
        Ok(())
    }

    pub fn overwrite(&mut self, byte: T) {
        if self.is_full() {
            self.advance_start();
        }

        self.buffer[self.end] = byte;
        self.advance_end();
    }

    pub fn clear(&mut self) {
        self.start = 0;
        self.end = 0;
    }

    pub fn is_empty(&self) -> bool {
        self.start == self.end
    }

    pub fn is_full(&self) -> bool {
        (self.end + 1) % self.size == self.start
    }

    fn advance_start(&mut self) {
        self.start = (self.start + 1) % self.size;
    }

    fn advance_end(&mut self) {
        self.end = (self.end + 1) % self.size;
    }
}
<commit_msg>circular-buffer: Use `[]` instead of `get().unwrap()`<commit_after>#[derive(Debug, PartialEq)]
pub enum Error {
    EmptyBuffer,
    FullBuffer,
}

pub struct CircularBuffer<T: Default + Clone> {
    buffer: Vec<T>,
    size: usize,
    start: usize,
    end: usize,
}

impl<T: Default + Clone> CircularBuffer<T> {
    // this circular buffer keeps an unallocated slot between the start and the end
    // when the buffer is full.
    pub fn new(size: usize) -> CircularBuffer<T> {
        CircularBuffer {
            buffer: vec![T::default(); size + 1],
            size: size + 1,
            start: 0,
            end: 0,
        }
    }

    pub fn read(&mut self) -> Result<T, Error> {
        if self.is_empty() {
            return Err(Error::EmptyBuffer);
        }

        let v = self.buffer[self.start].clone();
        self.advance_start();
        Ok(v)
    }

    pub fn write(&mut self, byte: T) -> Result<(), Error> {
        if self.is_full() {
            return Err(Error::FullBuffer);
        }

        self.buffer[self.end] = byte;
        self.advance_end();
        Ok(())
    }

    pub fn overwrite(&mut self, byte: T) {
        if self.is_full() {
            self.advance_start();
        }

        self.buffer[self.end] = byte;
        self.advance_end();
    }

    pub fn clear(&mut self) {
        self.start = 0;
        self.end = 0;
    }

    pub fn is_empty(&self) -> bool {
        self.start == self.end
    }

    pub fn is_full(&self) -> bool {
        (self.end + 1) % self.size == self.start
    }

    fn advance_start(&mut self) {
        self.start = (self.start + 1) % self.size;
    }

    fn advance_end(&mut self) {
        self.end = (self.end + 1) % self.size;
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Bruno Medeiros
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>.
// This file may not be copied, modified, or distributed
// except according to those terms.

// WARNING: Rust newbie code ahead (-_-)'

#![allow(non_upper_case_globals)]

extern crate serde_json;

use self::serde_json::Map;
use self::serde_json::Value;

//use ::util::core::*;

/* ----------------- deserialize helpers ----------------- */

fn unwrap_object(ob: ObjectBuilder) -> Map<String, Value> {
    match ob.unwrap() {
    	Value::Object(o) => o ,
    	_ => { panic!() },
    }
}

trait JsonDeserializerHelper {

	fn new_request_deserialization_error(&self) -> JsonRpcError;

	fn obtain_Value(&mut self, mut json_map : &mut Map<String, Value>, key: & str) -> result::Result<Value, JsonRpcError> {
		let value = json_map.remove(key);
		match value {
			Some(value) => { Ok(value) },
			None => { return Err(self.new_request_deserialization_error()) }
		}
	}

	fn obtain_String(&mut self, json_map : &mut Map<String, Value>, key: &str) -> result::Result<String, JsonRpcError> {
		let value = try!(self.obtain_Value(json_map, key));
		match value {
			Value::String(string) => Ok(string),
			_ => { return Err(self.new_request_deserialization_error()) },
		}
	}

	fn obtain_Map(&mut self, json_map : &mut Map<String, Value>, key: &str) -> result::Result<Map<String, Value>, JsonRpcError> {
		let value = try!(self.obtain_Value(json_map, key));
		match value {
			Value::Object(map) => Ok(map),
			_ => { return Err(self.new_request_deserialization_error()) },
		}
	}

	fn obtain_u32(&mut self, json_map: &mut Map<String, Value>, key: &str) -> result::Result<u32, JsonRpcError> {
		let value = try!(self.obtain_Value(json_map, key));
		match value {
			Value::I64(num) => Ok(num as u32), // TODO: check for truncation
			Value::U64(num) => Ok(num as u32), // TODO: check for truncation
			_ => { return Err(self.new_request_deserialization_error()) },
		}
	}

}

struct JsonRequestDeserializerHelper {

}

//impl<JsonRpcError> JsonDeserializerHelper<JsonRpcError> for JsonRequestDeserializerHelper {
//
//}

impl JsonDeserializerHelper for JsonRequestDeserializerHelper {

	fn new_request_deserialization_error(&self) -> JsonRpcError {
		return JSON_RPC_InvalidRequest;
	}

}

/* ----------------- JSON RPC ----------------- */

#[derive(Debug, PartialEq)]
pub struct JsonRpcRequest {
	pub jsonrpc : String,
	pub id : u32,
	pub method : String,
	pub params : Map<String, Value>,
}

pub const JSON_RPC_ParseError : JsonRpcError =
	JsonRpcError{code: -32700, message: "Invalid JSON was received by the server." };
pub const JSON_RPC_InvalidRequest : JsonRpcError =
	JsonRpcError{code: -32600, message: "The JSON sent is not a valid Request object." };
pub const JSON_RPC_MethodNotFound : JsonRpcError =
	JsonRpcError{code: -32601, message: "The method does not exist / is not available." };
pub const JSON_RPC_InvalidParams : JsonRpcError =
	JsonRpcError{code: -32602, message: "Invalid method parameter(s)." };
#[allow(dead_code)]
pub const JSON_RPC_InternalError : JsonRpcError =
	JsonRpcError{code: -32603, message: "Internal JSON-RPC error." };

use std::result;

pub type JsonRpcResult<T> = result::Result<T, JsonRpcError>;

pub fn parse_jsonrpc_request(message: &str) -> JsonRpcResult<JsonRpcRequest> {
	let mut json_result : Value = match
		serde_json::from_str(message)
	{
		Ok(ok) => { ok }
		Err(error) => {
			return Err(JSON_RPC_ParseError);
		}
	};

    parse_jsonrpc_request_json(&mut json_result)
}

pub fn parse_jsonrpc_request_json(request_json: &mut Value) -> JsonRpcResult<JsonRpcRequest> {

    let mut json_request_map : &mut Map<String, Value> =
    match request_json {
    	&mut Value::Object(ref mut map) => map ,
    	_ => { return Err(JSON_RPC_InvalidRequest) },
    };
    parse_jsonrpc_request_jsonObject(&mut json_request_map)
}

pub fn parse_jsonrpc_request_jsonObject(mut request_map: &mut Map<String, Value>) -> JsonRpcResult<JsonRpcRequest> {

    let mut helper = JsonRequestDeserializerHelper { };

    let jsonrpc = try!(helper.obtain_String(&mut request_map, "jsonrpc"));
    let id = try!(helper.obtain_u32(&mut request_map, "id"));
    let method = try!(helper.obtain_String(&mut request_map, "method"));
    let params = helper.obtain_Map(&mut request_map, "params");
//    let params = match params {
//    	Ok(ok) => { ok }
//    	Err(error) => {
//
//    	}
//    }

    let params = try!(params);

    let jsonrpc_request = JsonRpcRequest { jsonrpc : jsonrpc, id : id, method : method, params : params};

    Ok(jsonrpc_request)
}

use std::io;
use self::serde_json::builder::ObjectBuilder;

#[derive(Debug, PartialEq)]
pub struct JsonRpcError {
	pub code : i32,
	pub message : &'static str,
}

impl JsonRpcError {

	pub fn to_string(&self) -> String {
	    let value = ObjectBuilder::new()
	        .insert("code", self.code)
	        .insert("message", self.message)
	        .unwrap()
        ;
        // TODO: test
        return serde_json::to_string(&value).unwrap();
	}

	pub fn write_out(&self, out: &mut io::Write) -> io::Result<()> {
		try!(out.write_all(self.to_string().as_bytes()));
		Ok(())
	}

}

/* -----------------  ----------------- */

use std::collections::HashMap;

pub struct JsonRpcDispatcher {
	pub dispatcher_map : HashMap<String, Box<Fn(&Map<String, Value>)>>,
}

impl JsonRpcDispatcher {

	pub fn new() -> JsonRpcDispatcher {
		JsonRpcDispatcher { dispatcher_map : HashMap::new() }
	}

	pub fn dispatch(&self, request: &JsonRpcRequest) -> JsonRpcResult<()> {
		match
			self.dispatcher_map.get(&request.method)
		{
			Some(dispatcher_fn) => {
				dispatcher_fn(& request.params);
				Ok(())
			}
			None => {
				Err(JSON_RPC_MethodNotFound)
			}
		}
	}

}

/* ----------------- Test ----------------- */

#[test]
fn parse_jsonrpc_request_json_Test() {

	use self::serde_json::builder::ObjectBuilder;

	let sample_params = unwrap_object(ObjectBuilder::new()
	    .insert("param", "2.0")
        .insert("foo", 123)
    );

	// Test invalid JSON
	assert_eq!(parse_jsonrpc_request("{" ).unwrap_err(), JSON_RPC_ParseError);

	// Test invalid JsonRpcRequest
    let mut invalid_request = ObjectBuilder::new()
	    .insert("jsonrpc", "2.0")
        .insert("id", 1)
        .insert("params", sample_params.clone())
        .unwrap();

    let result = parse_jsonrpc_request_json(&mut invalid_request).unwrap_err();
	assert_eq!(result, JSON_RPC_InvalidRequest);

    // Test basic JsonRpcRequest
    let mut request = ObjectBuilder::new()
	    .insert("jsonrpc", "2.0")
        .insert("id", 1)
        .insert("method", "myMethod")
        .insert("params", sample_params.clone())
        .unwrap();

    let result = parse_jsonrpc_request_json(&mut request).unwrap();

	assert_eq!(result, JsonRpcRequest {
			jsonrpc : "2.0".to_string(),
			id : 1,
			method : "myMethod".to_string(),
			params : sample_params.clone(),
	});

	// Test basic JsonRpcRequest, no params
    let mut request = ObjectBuilder::new()
	    .insert("jsonrpc", "2.0")
        .insert("id", 1)
        .insert("method", "myMethod")
//       .insert("params", sample_params.clone())
        .unwrap();

	let result = parse_jsonrpc_request_json(&mut request).unwrap();
    assert_eq!(result, JsonRpcRequest {
			jsonrpc : "2.0".to_string(),
			id : 1,
			method : "myMethod".to_string(),
			params : unwrap_object(ObjectBuilder::new())
	});

}<commit_msg>Fix test failure<commit_after>// Copyright 2016 Bruno Medeiros
//
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0>.
// This file may not be copied, modified, or distributed
// except according to those terms.

// WARNING: Rust newbie code ahead (-_-)'

#![allow(non_upper_case_globals)]

extern crate serde_json;

use self::serde_json::Map;
use self::serde_json::Value;

//use ::util::core::*;

/* ----------------- deserialize helpers ----------------- */

fn unwrap_object(ob: ObjectBuilder) -> Map<String, Value> {
    match ob.unwrap() {
    	Value::Object(o) => o ,
    	_ => { panic!() },
    }
}

trait JsonDeserializerHelper {

	fn new_request_deserialization_error(&self) -> JsonRpcError;

	fn obtain_Value(&mut self, mut json_map : &mut Map<String, Value>, key: & str) -> result::Result<Value, JsonRpcError> {
		let value = json_map.remove(key);
		match value {
			Some(value) => { Ok(value) },
			None => { return Err(self.new_request_deserialization_error()) }
		}
	}

	fn obtain_Value_or(&mut self, mut json_map : &mut Map<String, Value>, key: & str, default: & Fn() -> Value)
		-> Value
	{
		if let Some(value) = json_map.remove(key) {
			value
		} else {
			default()
		}
	}

	fn as_String(&mut self, value: Value) -> result::Result<String, JsonRpcError> {
		match value {
			Value::String(string) => Ok(string),
			_ => Err(self.new_request_deserialization_error()),
		}
	}

	fn as_Map(&mut self, value: Value) -> result::Result<Map<String, Value>, JsonRpcError> {
		match value {
			Value::Object(map) => Ok(map),
			_ => Err(self.new_request_deserialization_error()),
		}
	}

	fn as_u32(&mut self, value: Value) -> result::Result<u32, JsonRpcError> {
		match value {
			Value::I64(num) => Ok(num as u32), // TODO: check for truncation
			Value::U64(num) => Ok(num as u32), // TODO: check for truncation
			_ => Err(self.new_request_deserialization_error()) ,
		}
	}

	fn obtain_String(&mut self, json_map : &mut Map<String, Value>, key: &str)
		-> result::Result<String, JsonRpcError>
	{
		let value = try!(self.obtain_Value(json_map, key));
		self.as_String(value)
	}

	fn obtain_Map(&mut self, json_map : &mut Map<String, Value>, key: &str) -> result::Result<Map<String, Value>, JsonRpcError> {
		let value = try!(self.obtain_Value(json_map, key));
		self.as_Map(value)
	}

	fn obtain_Map_or(&mut self, json_map : &mut Map<String, Value>, key: &str, default: & Fn() -> Map<String, Value>)
		-> result::Result<Map<String, Value>, JsonRpcError>
	{
		let value = self.obtain_Value_or(json_map, key, &|| { Value::Object(default()) });
		self.as_Map(value)
	}

	fn obtain_u32(&mut self, json_map: &mut Map<String, Value>, key: &str) -> result::Result<u32, JsonRpcError> {
		let value = try!(self.obtain_Value(json_map, key));
		self.as_u32(value)
	}

}

struct JsonRequestDeserializerHelper {

}

//impl<JsonRpcError> JsonDeserializerHelper<JsonRpcError> for JsonRequestDeserializerHelper {
//
//}

impl JsonDeserializerHelper for JsonRequestDeserializerHelper {

	fn new_request_deserialization_error(&self) -> JsonRpcError {
		return JSON_RPC_InvalidRequest;
	}

}

/* ----------------- JSON RPC ----------------- */

#[derive(Debug, PartialEq)]
pub struct JsonRpcRequest {
	pub jsonrpc : String,
	pub id : u32,
	pub method : String,
	pub params : Map<String, Value>,
}

pub const JSON_RPC_ParseError : JsonRpcError =
	JsonRpcError{code: -32700, message: "Invalid JSON was received by the server." };
pub const JSON_RPC_InvalidRequest : JsonRpcError =
	JsonRpcError{code: -32600, message: "The JSON sent is not a valid Request object." };
pub const JSON_RPC_MethodNotFound : JsonRpcError =
	JsonRpcError{code: -32601, message: "The method does not exist / is not available." };
pub const JSON_RPC_InvalidParams : JsonRpcError =
	JsonRpcError{code: -32602, message: "Invalid method parameter(s)." };
#[allow(dead_code)]
pub const JSON_RPC_InternalError : JsonRpcError =
	JsonRpcError{code: -32603, message: "Internal JSON-RPC error." };

use std::result;

pub type JsonRpcResult<T> = result::Result<T, JsonRpcError>;

pub fn parse_jsonrpc_request(message: &str) -> JsonRpcResult<JsonRpcRequest> {
	let mut json_result : Value = match
		serde_json::from_str(message)
	{
		Ok(ok) => { ok }
		Err(error) => {
			return Err(JSON_RPC_ParseError);
		}
	};

    parse_jsonrpc_request_json(&mut json_result)
}

pub fn parse_jsonrpc_request_json(request_json: &mut Value) -> JsonRpcResult<JsonRpcRequest> {

    let mut json_request_map : &mut Map<String, Value> =
    match request_json {
    	&mut Value::Object(ref mut map) => map ,
    	_ => { return Err(JSON_RPC_InvalidRequest) },
    };
    parse_jsonrpc_request_jsonObject(&mut json_request_map)
}

pub fn parse_jsonrpc_request_jsonObject(mut request_map: &mut Map<String, Value>) -> JsonRpcResult<JsonRpcRequest> {

    let mut helper = JsonRequestDeserializerHelper { };

    let jsonrpc = try!(helper.obtain_String(&mut request_map, "jsonrpc"));
    let id = try!(helper.obtain_u32(&mut request_map, "id"));
    let method = try!(helper.obtain_String(&mut request_map, "method"));
    let params = try!(helper.obtain_Map_or(&mut request_map, "params", &|| unwrap_object(ObjectBuilder::new())));

    let jsonrpc_request = JsonRpcRequest { jsonrpc : jsonrpc, id : id, method : method, params : params};

    Ok(jsonrpc_request)
}

use std::io;
use self::serde_json::builder::ObjectBuilder;

#[derive(Debug, PartialEq)]
pub struct JsonRpcError {
	pub code : i32,
	pub message : &'static str,
}

impl JsonRpcError {

	pub fn to_string(&self) -> String {
	    let value = ObjectBuilder::new()
	        .insert("code", self.code)
	        .insert("message", self.message)
	        .unwrap()
        ;
        // TODO: test
        return serde_json::to_string(&value).unwrap();
	}

	pub fn write_out(&self, out: &mut io::Write) -> io::Result<()> {
		try!(out.write_all(self.to_string().as_bytes()));
		Ok(())
	}

}

/* -----------------  ----------------- */

use std::collections::HashMap;

pub struct JsonRpcDispatcher {
	pub dispatcher_map : HashMap<String, Box<Fn(&Map<String, Value>)>>,
}

impl JsonRpcDispatcher {

	pub fn new() -> JsonRpcDispatcher {
		JsonRpcDispatcher { dispatcher_map : HashMap::new() }
	}

	pub fn dispatch(&self, request: &JsonRpcRequest) -> JsonRpcResult<()> {
		match
			self.dispatcher_map.get(&request.method)
		{
			Some(dispatcher_fn) => {
				dispatcher_fn(& request.params);
				Ok(())
			}
			None => {
				Err(JSON_RPC_MethodNotFound)
			}
		}
	}

}

/* ----------------- Test ----------------- */

#[test]
fn parse_jsonrpc_request_json_Test() {

	use self::serde_json::builder::ObjectBuilder;

	let sample_params = unwrap_object(ObjectBuilder::new()
	    .insert("param", "2.0")
        .insert("foo", 123)
    );

	// Test invalid JSON
	assert_eq!(parse_jsonrpc_request("{" ).unwrap_err(), JSON_RPC_ParseError);

	// Test invalid JsonRpcRequest
    let mut invalid_request = ObjectBuilder::new()
	    .insert("jsonrpc", "2.0")
        .insert("id", 1)
        .insert("params", sample_params.clone())
        .unwrap();

    let result = parse_jsonrpc_request_json(&mut invalid_request).unwrap_err();
	assert_eq!(result, JSON_RPC_InvalidRequest);

    // Test basic JsonRpcRequest
    let mut request = ObjectBuilder::new()
	    .insert("jsonrpc", "2.0")
        .insert("id", 1)
        .insert("method", "myMethod")
        .insert("params", sample_params.clone())
        .unwrap();

    let result = parse_jsonrpc_request_json(&mut request).unwrap();

	assert_eq!(result, JsonRpcRequest {
			jsonrpc : "2.0".to_string(),
			id : 1,
			method : "myMethod".to_string(),
			params : sample_params.clone(),
	});

	// Test basic JsonRpcRequest, no params
    let mut request = ObjectBuilder::new()
	    .insert("jsonrpc", "2.0")
        .insert("id", 1)
        .insert("method", "myMethod")
//       .insert("params", sample_params.clone())
        .unwrap();

	let result = parse_jsonrpc_request_json(&mut request).unwrap();
    assert_eq!(result, JsonRpcRequest {
			jsonrpc : "2.0".to_string(),
			id : 1,
			method : "myMethod".to_string(),
			params : unwrap_object(ObjectBuilder::new())
	});

}<|endoftext|>


<commit_before>use super::{elf,Tag};
use core::mem;

#[derive(Debug)]
#[repr(packed)]
pub struct SectionsTag { tag: Tag
                        , pub n_sections: u32
                        , section_size: u32
                        , stringtable_idx: u32
                        , first_section: Section
                        }

impl SectionsTag {
    pub fn sections(&'static self) -> Sections {
        Sections { curr: &self.first_section
                 , remaining: self.n_sections - 1
                 , size: self.section_size
                 }
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct Section { name: u32
                   , ty: elf::SectionType
                   , pub flags: u64
                   , pub address: u64
                   , offset: u64
                   , pub length: u64
                   , link: u32
                   , address_align: u32
                   , entry_length: u64
                   }

#[derive(Clone,Debug)]
pub struct Sections { curr: &'static Section
                    , remaining: u32
                    , size: u32
                    }

impl Iterator for Sections {
    type Item = &'static Section;
    fn next(&mut self) -> Option<&'static Section> {
        if self.remaining == 0 {
            None
        } else {
            let current = self.curr;
            self.curr = &unsafe {
                *((ptr!(current) as u32 + self.size) as *const Section)
            };
            self.remaining -= 1;
            if current.ty == elf::SectionType::Null {
                self.next()
            } else {
                Some(current)
            }
        }
    }
}
<commit_msg>Fix move out of raw pointer deref<commit_after>use super::{elf,Tag};
use core::mem;

#[derive(Debug)]
#[repr(packed)]
pub struct SectionsTag { tag: Tag
                        , pub n_sections: u32
                        , section_size: u32
                        , stringtable_idx: u32
                        , first_section: Section
                        }

impl SectionsTag {
    pub fn sections(&'static self) -> Sections {
        Sections { curr: &self.first_section
                 , remaining: self.n_sections - 1
                 , size: self.section_size
                 }
    }
}

#[derive(Debug)]
#[repr(C)]
pub struct Section { name: u32
                   , ty: elf::SectionType
                   , pub flags: u64
                   , pub address: u64
                   , offset: u64
                   , pub length: u64
                   , link: u32
                   , address_align: u32
                   , entry_length: u64
                   }

#[derive(Clone,Debug)]
pub struct Sections { curr: &'static Section
                    , remaining: u32
                    , size: u32
                    }

impl Iterator for Sections {
    type Item = &'static Section;
    fn next(&mut self) -> Option<&'static Section> {
        if self.remaining == 0 {
            None
        } else {
            let current = self.curr;
            self.curr = unsafe {
                &*((ptr!(current) as u32 + self.size) as *const Section)
            };
            self.remaining -= 1;
            if current.ty == elf::SectionType::Null {
                self.next()
            } else {
                Some(current)
            }
        }
    }
}
<|endoftext|>