<commit_before>use parse_code;
use std::io::{self, Read};
use dict::DecoderDictionary;
#[cfg(feature = "tokio")]
use tokio_io::AsyncRead;
use zstd_safe;

/// Extra bit of information that is stored along `RefillBuffer` state.
/// It describes the context in which refill was requested.
#[derive(PartialEq, Copy, Clone)]
enum RefillBufferHint {
    /// Refill was requested during regular read operation,
    /// no extra actions are required.
    None,
    /// We've reached the end of buffer and zstd wants more data in this
    /// circumstances refill must return more data, otherwise this is an error.
    FailIfEmpty,
    /// We've reached the end of current frame, if refill brings more data
    /// we'll start new frame and complete reading otherwise
    EndOfFrame,
}

enum DecoderState {
    Completed,
    Active,
    RefillBuffer(RefillBufferHint),
}

/// A decoder that decompress input data from another `Read`.
///
/// This allows to read a stream of compressed data
/// (good for files or heavy network stream).
pub struct Decoder<R: Read> {
    // input reader (compressed data)
    reader: R,
    // input buffer
    buffer: Vec<u8>,
    // we already read everything in the buffer up to that point
    offset: usize,
    // decompression context
    context: zstd_safe::DStream,

    // `true` if we should stop after the first frame.
    single_frame: bool,

    // current state of the decoder
    state: DecoderState,
}

impl<R: Read> Decoder<R> {
    /// Creates a new decoder.
    pub fn new(reader: R) -> io::Result<Self> {
        Self::with_dictionary(reader, &[])
    }

    /// Sets this `Decoder` to stop after the first frame.
    ///
    /// By default, it keeps concatenating frames until EOF is reached.
    pub fn single_frame(mut self) -> Self {
        self.single_frame = true;
        self
    }

    /// Creates a new decoder, using an existing dictionary.
    ///
    /// The dictionary must be the same as the one used during compression.
    pub fn with_dictionary(reader: R, dictionary: &[u8]) -> io::Result<Self> {

        let buffer_size = zstd_safe::dstream_in_size();

        let mut context = zstd_safe::create_dstream();
        parse_code(
            zstd_safe::init_dstream_using_dict(&mut context, dictionary),
        )?;

        let decoder = Decoder {
            reader,
            buffer: Vec::with_capacity(buffer_size),
            offset: 0,
            context,
            single_frame: false,
            state: DecoderState::RefillBuffer(RefillBufferHint::None),
        };

        Ok(decoder)
    }

    /// Creates a new decoder, using an existing `DecoderDictionary`.
    ///
    /// The dictionary must be the same as the one used during compression.
    pub fn with_prepared_dictionary(
        reader: R,
        dictionary: &DecoderDictionary,
    ) -> io::Result<Self> {
        let buffer_size = zstd_safe::dstream_in_size();

        let mut context = zstd_safe::create_dstream();
        parse_code(
            zstd_safe::init_dstream_using_ddict(&mut context, dictionary.as_ddict()),
        )?;

        let decoder = Decoder {
            reader,
            buffer: Vec::with_capacity(buffer_size),
            offset: 0,
            context,
            single_frame: false,
            state: DecoderState::RefillBuffer(RefillBufferHint::None),
        };

        Ok(decoder)
    }

    // Prepares the context for another stream, whith minimal re-allocation.
    fn reinit(&mut self) -> io::Result<()> {
        parse_code(zstd_safe::reset_dstream(&mut self.context))?;
        Ok(())
    }

    /// Recommendation for the size of the output buffer.
    pub fn recommended_output_size() -> usize {
        zstd_safe::dstream_out_size()
    }

    /// Acquire a reference to the underlying reader.
    pub fn get_ref(&self) -> &R {
        &self.reader
    }

    /// Acquire a mutable reference to the underlying reader.
    ///
    /// Note that mutation of the reader may result in surprising results if
    /// this decoder is continued to be used.
    pub fn get_mut(&mut self) -> &mut R {
        &mut self.reader
    }

    /// Return the inner `Read`.
    ///
    /// Calling `finish()` is not *required* after reading a stream -
    /// just use it if you need to get the `Read` back.
    pub fn finish(self) -> R {
        self.reader
    }

    // Attemps to refill the input buffer.
    //
    // Returns the number of bytes read.
    fn refill_buffer(&mut self) -> io::Result<usize> {
        // At this point it's safe to discard anything in `self.buffer`.

        // We need moar data!
        // Make a nice clean buffer
        let buffer_size = self.buffer.capacity();
        unsafe {
            self.buffer.set_len(buffer_size);
        }

        // And FILL IT!
        let read = self.read_with_retry()?;
        unsafe {
            self.buffer.set_len(read);
        }

        self.offset = 0;

        // If we can't read anything, it means input is exhausted.
        Ok(read)
    }

    // Read and retry on Interrupted errors.
    fn read_with_retry(&mut self) -> Result<usize, io::Error> {
        loop {
            match self.reader.read(&mut self.buffer) {
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                otherwise => return otherwise,
            }
        }
    }
}

impl<R: Read> Decoder<R> {
    /// This function handles buffer_refill state of the read operation
    ///
    /// It returns true if read operation should be stopped and false otherwise
    fn handle_refill(
        &mut self,
        hint: RefillBufferHint,
        out_buffer: &mut zstd_safe::OutBuffer,
    ) -> Result<bool, io::Error> {

        // refilled = false if we reached the end of the input.
        let refilled = match self.refill_buffer() {
            Err(ref err)
                if out_buffer.pos > 0 &&
                    err.kind() == io::ErrorKind::WouldBlock =>
            {
                // The underlying reader was blocked, but we've already
                // put some data into the output buffer.
                // We need to stop this read operation so data won' be lost.
                return Ok(true);
            }
            // We are refilled if we were able to read anything
            otherwise => otherwise.map(|read| read > 0),
        }?;

        match hint {
            RefillBufferHint::None => {
                // Nothing special, we can read again
                self.state = DecoderState::Active
            }
            RefillBufferHint::FailIfEmpty => {
                if refilled {
                    // We can read again
                    self.state = DecoderState::Active;
                } else {
                    // zstd keeps asking for more, but we're short on data!
                    return Err(io::Error::new(
                        io::ErrorKind::UnexpectedEof,
                        "incomplete frame",
                    ));
                }
            }
            RefillBufferHint::EndOfFrame => {
                // at the end of frame
                if refilled {
                    // There is data to process - start new frame
                    self.reinit()?;
                    self.state = DecoderState::Active;
                } else {
                    // no more data - we are done
                    self.state = DecoderState::Completed;
                    return Ok(true);
                }
            }
        }

        Ok(false)
    }

    /// Main read loop.
    ///
    /// This function handles Active state in the read operation.
    ///
    /// It returns true if read operation should be stopped and false otherwise
    fn handle_active(
        &mut self,
        out_buffer: &mut zstd_safe::OutBuffer,
    ) -> Result<bool, io::Error> {

        let mut in_buffer = zstd_safe::InBuffer {
            src: &self.buffer,
            pos: self.offset,
        };

        // As long as we can keep writing...
        while out_buffer.pos < out_buffer.dst.len() {
            if in_buffer.pos == in_buffer.src.len() {
                self.state =
                    DecoderState::RefillBuffer(RefillBufferHint::None);
                // refill buffer and continue reading
                return Ok(false);
            }

            // Let's use the hint from ZSTD to detect end of frames.
            let is_end_of_frame = {
                let code = zstd_safe::decompress_stream(
                    &mut self.context,
                    out_buffer,
                    &mut in_buffer,
                );
                let res = parse_code(code)?;
                res == 0
            };

            // Record what we've consumed.
            self.offset = in_buffer.pos;

            if is_end_of_frame && self.single_frame {
                // We're at the end of the frame,
                // and we know that this frame is the only one.
                // Stop.
                self.state = DecoderState::Completed;
                return Ok(true);
            }

            if in_buffer.pos == in_buffer.src.len() {
                let hint = if is_end_of_frame {
                    // If the frame is over, it's fine to stop there.
                    RefillBufferHint::EndOfFrame
                } else {
                    // If it's not, then we need more data!
                    RefillBufferHint::FailIfEmpty
                };
                // Refill the buffer and continue
                self.state = DecoderState::RefillBuffer(hint);
                return Ok(false);
            }
        }
        Ok(true)
    }
}

impl<R: Read> Read for Decoder<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {

        // Self-contained buffer pointer, size and offset

        let mut out_buffer = zstd_safe::OutBuffer { dst: buf, pos: 0 };

        loop {
            let should_stop = match self.state {
                DecoderState::Completed => {
                    return Ok(0);
                }
                DecoderState::RefillBuffer(action) => {
                    self.handle_refill(action, &mut out_buffer)?
                }
                DecoderState::Active => self.handle_active(&mut out_buffer)?,
            };
            if should_stop {
                break;
            }
        }

        Ok(out_buffer.pos)
    }
}

#[cfg(feature = "tokio")]
impl<R: AsyncRead> AsyncRead for Decoder<R> {
    unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [u8]) -> bool {
        false
    }
}

fn _assert_traits() {
    use std::io::Cursor;

    fn _assert_send<T: Send>(_: T) {}

    _assert_send(Decoder::new(Cursor::new(Vec::new())));
}

#[cfg(test)]
#[cfg(feature = "tokio")]
mod async_tests {
    use futures::Future;
    use partial_io::{GenInterruptedWouldBlock, PartialAsyncRead,
                     PartialWithErrors};
    use quickcheck::quickcheck;
    use std::io::{self, Cursor};
    use tokio_io::{io as tokio_io, AsyncRead, AsyncWrite};

    #[test]
    fn test_async_read() {
        use stream::encode_all;

        let source = "abc".repeat(1024 * 10).into_bytes();
        let encoded = encode_all(&source[..], 1).unwrap();
        let writer =
            test_async_read_worker(&encoded[..], Cursor::new(Vec::new()))
                .unwrap();
        let output = writer.into_inner();
        assert_eq!(source, output);
    }

    #[test]
    fn test_async_read_partial() {
        quickcheck(test as fn(_) -> _);

        fn test(encode_ops: PartialWithErrors<GenInterruptedWouldBlock>) {
            use stream::encode_all;

            let source = "abc".repeat(1024 * 10).into_bytes();
            let encoded = encode_all(&source[..], 1).unwrap();
            let reader = PartialAsyncRead::new(&encoded[..], encode_ops);
            let writer =
                test_async_read_worker(reader, Cursor::new(Vec::new()))
                    .unwrap();
            let output = writer.into_inner();
            assert_eq!(source, output);
        }
    }

    fn test_async_read_worker<R: AsyncRead, W: AsyncWrite>(
        r: R,
        w: W,
    ) -> io::Result<W> {
        use super::Decoder;

        let decoder = Decoder::new(r).unwrap();
        let (_, _, w) = tokio_io::copy(decoder, w).wait()?;
        Ok(w)
    }
}
<commit_msg>Removed unnecessary double `impl Decoder`<commit_after>use parse_code;
use std::io::{self, Read};
use dict::DecoderDictionary;
#[cfg(feature = "tokio")]
use tokio_io::AsyncRead;
use zstd_safe;

/// Extra bit of information that is stored along `RefillBuffer` state.
/// It describes the context in which refill was requested.
#[derive(PartialEq, Copy, Clone)]
enum RefillBufferHint {
    /// Refill was requested during regular read operation,
    /// no extra actions are required.
    None,
    /// We've reached the end of buffer and zstd wants more data in this
    /// circumstances refill must return more data, otherwise this is an error.
    FailIfEmpty,
    /// We've reached the end of current frame, if refill brings more data
    /// we'll start new frame and complete reading otherwise
    EndOfFrame,
}

enum DecoderState {
    Completed,
    Active,
    RefillBuffer(RefillBufferHint),
}

/// A decoder that decompress input data from another `Read`.
///
/// This allows to read a stream of compressed data
/// (good for files or heavy network stream).
pub struct Decoder<R: Read> {
    // input reader (compressed data)
    reader: R,
    // input buffer
    buffer: Vec<u8>,
    // we already read everything in the buffer up to that point
    offset: usize,
    // decompression context
    context: zstd_safe::DStream,

    // `true` if we should stop after the first frame.
    single_frame: bool,

    // current state of the decoder
    state: DecoderState,
}

impl<R: Read> Decoder<R> {
    /// Creates a new decoder.
    pub fn new(reader: R) -> io::Result<Self> {
        Self::with_dictionary(reader, &[])
    }

    /// Sets this `Decoder` to stop after the first frame.
    ///
    /// By default, it keeps concatenating frames until EOF is reached.
    pub fn single_frame(mut self) -> Self {
        self.single_frame = true;
        self
    }

    /// Creates a new decoder, using an existing dictionary.
    ///
    /// The dictionary must be the same as the one used during compression.
    pub fn with_dictionary(reader: R, dictionary: &[u8]) -> io::Result<Self> {

        let buffer_size = zstd_safe::dstream_in_size();

        let mut context = zstd_safe::create_dstream();
        parse_code(
            zstd_safe::init_dstream_using_dict(&mut context, dictionary),
        )?;

        let decoder = Decoder {
            reader,
            buffer: Vec::with_capacity(buffer_size),
            offset: 0,
            context,
            single_frame: false,
            state: DecoderState::RefillBuffer(RefillBufferHint::None),
        };

        Ok(decoder)
    }

    /// Creates a new decoder, using an existing `DecoderDictionary`.
    ///
    /// The dictionary must be the same as the one used during compression.
    pub fn with_prepared_dictionary(
        reader: R,
        dictionary: &DecoderDictionary,
    ) -> io::Result<Self> {
        let buffer_size = zstd_safe::dstream_in_size();

        let mut context = zstd_safe::create_dstream();
        parse_code(
            zstd_safe::init_dstream_using_ddict(&mut context, dictionary.as_ddict()),
        )?;

        let decoder = Decoder {
            reader,
            buffer: Vec::with_capacity(buffer_size),
            offset: 0,
            context,
            single_frame: false,
            state: DecoderState::RefillBuffer(RefillBufferHint::None),
        };

        Ok(decoder)
    }

    // Prepares the context for another stream, whith minimal re-allocation.
    fn reinit(&mut self) -> io::Result<()> {
        parse_code(zstd_safe::reset_dstream(&mut self.context))?;
        Ok(())
    }

    /// Recommendation for the size of the output buffer.
    pub fn recommended_output_size() -> usize {
        zstd_safe::dstream_out_size()
    }

    /// Acquire a reference to the underlying reader.
    pub fn get_ref(&self) -> &R {
        &self.reader
    }

    /// Acquire a mutable reference to the underlying reader.
    ///
    /// Note that mutation of the reader may result in surprising results if
    /// this decoder is continued to be used.
    pub fn get_mut(&mut self) -> &mut R {
        &mut self.reader
    }

    /// Return the inner `Read`.
    ///
    /// Calling `finish()` is not *required* after reading a stream -
    /// just use it if you need to get the `Read` back.
    pub fn finish(self) -> R {
        self.reader
    }

    // Attemps to refill the input buffer.
    //
    // Returns the number of bytes read.
    fn refill_buffer(&mut self) -> io::Result<usize> {
        // At this point it's safe to discard anything in `self.buffer`.

        // We need moar data!
        // Make a nice clean buffer
        let buffer_size = self.buffer.capacity();
        unsafe {
            self.buffer.set_len(buffer_size);
        }

        // And FILL IT!
        let read = self.read_with_retry()?;
        unsafe {
            self.buffer.set_len(read);
        }

        self.offset = 0;

        // If we can't read anything, it means input is exhausted.
        Ok(read)
    }

    // Read and retry on Interrupted errors.
    fn read_with_retry(&mut self) -> Result<usize, io::Error> {
        loop {
            match self.reader.read(&mut self.buffer) {
                Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {}
                otherwise => return otherwise,
            }
        }
    }

    /// This function handles buffer_refill state of the read operation
    ///
    /// It returns true if read operation should be stopped and false otherwise
    fn handle_refill(
        &mut self,
        hint: RefillBufferHint,
        out_buffer: &mut zstd_safe::OutBuffer,
    ) -> Result<bool, io::Error> {

        // refilled = false if we reached the end of the input.
        let refilled = match self.refill_buffer() {
            Err(ref err)
                if out_buffer.pos > 0 &&
                    err.kind() == io::ErrorKind::WouldBlock =>
            {
                // The underlying reader was blocked, but we've already
                // put some data into the output buffer.
                // We need to stop this read operation so data won' be lost.
                return Ok(true);
            }
            // We are refilled if we were able to read anything
            otherwise => otherwise.map(|read| read > 0),
        }?;

        match hint {
            RefillBufferHint::None => {
                // Nothing special, we can read again
                self.state = DecoderState::Active
            }
            RefillBufferHint::FailIfEmpty => {
                if refilled {
                    // We can read again
                    self.state = DecoderState::Active;
                } else {
                    // zstd keeps asking for more, but we're short on data!
                    return Err(io::Error::new(
                        io::ErrorKind::UnexpectedEof,
                        "incomplete frame",
                    ));
                }
            }
            RefillBufferHint::EndOfFrame => {
                // at the end of frame
                if refilled {
                    // There is data to process - start new frame
                    self.reinit()?;
                    self.state = DecoderState::Active;
                } else {
                    // no more data - we are done
                    self.state = DecoderState::Completed;
                    return Ok(true);
                }
            }
        }

        Ok(false)
    }

    /// Main read loop.
    ///
    /// This function handles Active state in the read operation.
    ///
    /// It returns true if read operation should be stopped and false otherwise
    fn handle_active(
        &mut self,
        out_buffer: &mut zstd_safe::OutBuffer,
    ) -> Result<bool, io::Error> {

        let mut in_buffer = zstd_safe::InBuffer {
            src: &self.buffer,
            pos: self.offset,
        };

        // As long as we can keep writing...
        while out_buffer.pos < out_buffer.dst.len() {
            if in_buffer.pos == in_buffer.src.len() {
                self.state =
                    DecoderState::RefillBuffer(RefillBufferHint::None);
                // refill buffer and continue reading
                return Ok(false);
            }

            // Let's use the hint from ZSTD to detect end of frames.
            let is_end_of_frame = {
                let code = zstd_safe::decompress_stream(
                    &mut self.context,
                    out_buffer,
                    &mut in_buffer,
                );
                let res = parse_code(code)?;
                res == 0
            };

            // Record what we've consumed.
            self.offset = in_buffer.pos;

            if is_end_of_frame && self.single_frame {
                // We're at the end of the frame,
                // and we know that this frame is the only one.
                // Stop.
                self.state = DecoderState::Completed;
                return Ok(true);
            }

            if in_buffer.pos == in_buffer.src.len() {
                let hint = if is_end_of_frame {
                    // If the frame is over, it's fine to stop there.
                    RefillBufferHint::EndOfFrame
                } else {
                    // If it's not, then we need more data!
                    RefillBufferHint::FailIfEmpty
                };
                // Refill the buffer and continue
                self.state = DecoderState::RefillBuffer(hint);
                return Ok(false);
            }
        }
        Ok(true)
    }
}

impl<R: Read> Read for Decoder<R> {
    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {

        // Self-contained buffer pointer, size and offset

        let mut out_buffer = zstd_safe::OutBuffer { dst: buf, pos: 0 };

        loop {
            let should_stop = match self.state {
                DecoderState::Completed => {
                    return Ok(0);
                }
                DecoderState::RefillBuffer(action) => {
                    self.handle_refill(action, &mut out_buffer)?
                }
                DecoderState::Active => self.handle_active(&mut out_buffer)?,
            };
            if should_stop {
                break;
            }
        }

        Ok(out_buffer.pos)
    }
}

#[cfg(feature = "tokio")]
impl<R: AsyncRead> AsyncRead for Decoder<R> {
    unsafe fn prepare_uninitialized_buffer(&self, _buf: &mut [u8]) -> bool {
        false
    }
}

fn _assert_traits() {
    use std::io::Cursor;

    fn _assert_send<T: Send>(_: T) {}

    _assert_send(Decoder::new(Cursor::new(Vec::new())));
}

#[cfg(test)]
#[cfg(feature = "tokio")]
mod async_tests {
    use futures::Future;
    use partial_io::{GenInterruptedWouldBlock, PartialAsyncRead,
                     PartialWithErrors};
    use quickcheck::quickcheck;
    use std::io::{self, Cursor};
    use tokio_io::{io as tokio_io, AsyncRead, AsyncWrite};

    #[test]
    fn test_async_read() {
        use stream::encode_all;

        let source = "abc".repeat(1024 * 10).into_bytes();
        let encoded = encode_all(&source[..], 1).unwrap();
        let writer =
            test_async_read_worker(&encoded[..], Cursor::new(Vec::new()))
                .unwrap();
        let output = writer.into_inner();
        assert_eq!(source, output);
    }

    #[test]
    fn test_async_read_partial() {
        quickcheck(test as fn(_) -> _);

        fn test(encode_ops: PartialWithErrors<GenInterruptedWouldBlock>) {
            use stream::encode_all;

            let source = "abc".repeat(1024 * 10).into_bytes();
            let encoded = encode_all(&source[..], 1).unwrap();
            let reader = PartialAsyncRead::new(&encoded[..], encode_ops);
            let writer =
                test_async_read_worker(reader, Cursor::new(Vec::new()))
                    .unwrap();
            let output = writer.into_inner();
            assert_eq!(source, output);
        }
    }

    fn test_async_read_worker<R: AsyncRead, W: AsyncWrite>(
        r: R,
        w: W,
    ) -> io::Result<W> {
        use super::Decoder;

        let decoder = Decoder::new(r).unwrap();
        let (_, _, w) = tokio_io::copy(decoder, w).wait()?;
        Ok(w)
    }
}
<|endoftext|>


<commit_before>use crate::error::{Error, Result};
use crate::gen::fs;
use crate::Project;
use std::env;
use std::ffi::OsString;
use std::path::{Path, PathBuf};

pub(crate) enum TargetDir {
    Path(PathBuf),
    Unknown,
}

pub(crate) fn out_dir() -> Result<PathBuf> {
    env::var_os("OUT_DIR")
        .map(PathBuf::from)
        .ok_or(Error::MissingOutDir)
}

pub(crate) fn cc_build(prj: &Project) -> cc::Build {
    let mut build = cc::Build::new();
    build.include(include_dir(prj));
    build
}

// Symlink the header file into a predictable place. The header generated from
// path/to/mod.rs gets linked to target/cxxbridge/path/to/mod.rs.h.
pub(crate) fn symlink_header(prj: &Project, path: &Path, original: &Path) {
    if let TargetDir::Unknown = prj.target_dir {
        return;
    }
    let _ = try_symlink_header(prj, path, original);
}

fn try_symlink_header(prj: &Project, path: &Path, original: &Path) -> Result<()> {
    let mut dst = include_dir(prj);
    dst.extend(package_name());
    dst.push(original);

    let parent = dst.parent().unwrap();
    fs::create_dir_all(parent)?;
    let _ = fs::remove_file(&dst);
    symlink_or_copy(path, &dst)?;

    let mut file_name = dst.file_name().unwrap().to_os_string();
    file_name.push(".h");
    let ref dst2 = dst.with_file_name(file_name);
    symlink_or_copy(path, dst2)?;

    Ok(())
}

pub(crate) fn out_with_extension(prj: &Project, rel_path: &Path, ext: &str) -> PathBuf {
    let mut file_name = rel_path.file_name().unwrap().to_owned();
    file_name.push(ext);

    let mut res = prj.out_dir.clone();
    res.push("cxxbridge");
    res.extend(package_name());
    res.push(rel_path);
    res.with_file_name(file_name)
}

pub(crate) fn include_dir(prj: &Project) -> PathBuf {
    match &prj.target_dir {
        TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
        TargetDir::Unknown => prj.out_dir.join("cxxbridge"),
    }
}

fn package_name() -> Option<OsString> {
    env::var_os("CARGO_PKG_NAME")
}

pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
    // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
    // handle in includes.
    // https://github.com/rust-lang/rust/issues/42869
    // https://github.com/alexcrichton/cc-rs/issues/169
    let mut also_try_canonical = cfg!(not(windows));

    let mut dir = out_dir.to_owned();
    loop {
        let is_target = dir.ends_with("target");
        let parent_contains_cargo_toml = dir.with_file_name("Cargo.toml").exists();
        if is_target && parent_contains_cargo_toml {
            return TargetDir::Path(dir);
        }
        if dir.pop() {
            continue;
        }
        if also_try_canonical {
            if let Ok(canonical_dir) = out_dir.canonicalize() {
                dir = canonical_dir;
                also_try_canonical = false;
                continue;
            }
        }
        return TargetDir::Unknown;
    }
}

#[cfg(unix)]
use self::fs::symlink_file as symlink_or_copy;

#[cfg(windows)]
fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
    // require Developer Mode. If it fails, fall back to copying the file.
    if fs::symlink_file(src, dst).is_err() {
        fs::copy(src, dst)?;
    }
    Ok(())
}

#[cfg(not(any(unix, windows)))]
use self::fs::copy as symlink_or_copy;
<commit_msg>Include manifest dir<commit_after>use crate::error::{Error, Result};
use crate::gen::fs;
use crate::Project;
use std::env;
use std::ffi::OsString;
use std::path::{Path, PathBuf};

pub(crate) enum TargetDir {
    Path(PathBuf),
    Unknown,
}

pub(crate) fn out_dir() -> Result<PathBuf> {
    env::var_os("OUT_DIR")
        .map(PathBuf::from)
        .ok_or(Error::MissingOutDir)
}

pub(crate) fn cc_build(prj: &Project) -> cc::Build {
    let mut build = cc::Build::new();
    build.include(include_dir(prj));
    if let Some(manifest_dir) = env::var_os("CARGO_MANIFEST_DIR") {
        build.include(manifest_dir);
    }
    build
}

// Symlink the header file into a predictable place. The header generated from
// path/to/mod.rs gets linked to target/cxxbridge/path/to/mod.rs.h.
pub(crate) fn symlink_header(prj: &Project, path: &Path, original: &Path) {
    if let TargetDir::Unknown = prj.target_dir {
        return;
    }
    let _ = try_symlink_header(prj, path, original);
}

fn try_symlink_header(prj: &Project, path: &Path, original: &Path) -> Result<()> {
    let mut dst = include_dir(prj);
    dst.extend(package_name());
    dst.push(original);

    let parent = dst.parent().unwrap();
    fs::create_dir_all(parent)?;
    let _ = fs::remove_file(&dst);
    symlink_or_copy(path, &dst)?;

    let mut file_name = dst.file_name().unwrap().to_os_string();
    file_name.push(".h");
    let ref dst2 = dst.with_file_name(file_name);
    symlink_or_copy(path, dst2)?;

    Ok(())
}

pub(crate) fn out_with_extension(prj: &Project, rel_path: &Path, ext: &str) -> PathBuf {
    let mut file_name = rel_path.file_name().unwrap().to_owned();
    file_name.push(ext);

    let mut res = prj.out_dir.clone();
    res.push("cxxbridge");
    res.extend(package_name());
    res.push(rel_path);
    res.with_file_name(file_name)
}

pub(crate) fn include_dir(prj: &Project) -> PathBuf {
    match &prj.target_dir {
        TargetDir::Path(target_dir) => target_dir.join("cxxbridge"),
        TargetDir::Unknown => prj.out_dir.join("cxxbridge"),
    }
}

fn package_name() -> Option<OsString> {
    env::var_os("CARGO_PKG_NAME")
}

pub(crate) fn search_parents_for_target_dir(out_dir: &Path) -> TargetDir {
    // fs::canonicalize on Windows produces UNC paths which cl.exe is unable to
    // handle in includes.
    // https://github.com/rust-lang/rust/issues/42869
    // https://github.com/alexcrichton/cc-rs/issues/169
    let mut also_try_canonical = cfg!(not(windows));

    let mut dir = out_dir.to_owned();
    loop {
        let is_target = dir.ends_with("target");
        let parent_contains_cargo_toml = dir.with_file_name("Cargo.toml").exists();
        if is_target && parent_contains_cargo_toml {
            return TargetDir::Path(dir);
        }
        if dir.pop() {
            continue;
        }
        if also_try_canonical {
            if let Ok(canonical_dir) = out_dir.canonicalize() {
                dir = canonical_dir;
                also_try_canonical = false;
                continue;
            }
        }
        return TargetDir::Unknown;
    }
}

#[cfg(unix)]
use self::fs::symlink_file as symlink_or_copy;

#[cfg(windows)]
fn symlink_or_copy(src: &Path, dst: &Path) -> Result<()> {
    // Pre-Windows 10, symlinks require admin privileges. Since Windows 10, they
    // require Developer Mode. If it fails, fall back to copying the file.
    if fs::symlink_file(src, dst).is_err() {
        fs::copy(src, dst)?;
    }
    Ok(())
}

#[cfg(not(any(unix, windows)))]
use self::fs::copy as symlink_or_copy;
<|endoftext|>


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

use std::collections::BTreeMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::io;
use std::io::ErrorKind;
use std::cmp::min;
use std::fmt;

use devicemapper::{DM, Device, DmFlags, DevId, DM_SUSPEND};

use types::{Sectors, SectorOffset, FroyoError, FroyoResult};
use blockdev::{LinearDev, LinearDevSave};
use consts::*;
use util::{setup_dm_dev, teardown_dm_dev};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidDevSave {
    pub stripe_sectors: Sectors,
    pub region_sectors: Sectors,
    pub length: Sectors,
    pub member_count: usize,
    pub members: BTreeMap<String, LinearDevSave>,
}

#[derive(Debug, Clone)]
pub struct RaidDev {
    pub id: String,
    dev: Device,
    dm_name: String,
    pub stripe_sectors: Sectors,
    pub region_sectors: Sectors,
    pub length: Sectors,
    pub members: Vec<RaidMember>,
    used: BTreeMap<SectorOffset, Sectors>,
}

#[derive(Debug, Clone, Copy)]
pub enum RaidStatus {
    Good,
    Degraded(usize),
    Failed,
}

#[derive(Debug, Clone, Copy)]
pub enum RaidAction {
    Idle,
    Frozen,
    Resync,
    Recover,
    Check,
    Repair,
    Reshape,
    Unknown,
}

#[derive(Debug, Clone)]
pub enum RaidMember {
    Present(Rc<RefCell<LinearDev>>),
    Absent,
}

impl RaidMember {
    pub fn present(&self) -> Option<Rc<RefCell<LinearDev>>> {
        match *self {
            RaidMember::Present(ref x) => Some(x.clone()),
            RaidMember::Absent => None,
        }
    }
}

impl RaidDev {

    fn make_raid_params(
        devs: &[RaidMember],
        stripe: Sectors,
        region: Sectors)
        -> String {

        let raid_texts: Vec<_> = devs.iter()
            .map(|dev|
                 match *dev {
                     RaidMember::Present(ref dev) => {
                         format!("{}:{} {}:{}",
                                 RefCell::borrow(dev).meta_dev.major,
                                 RefCell::borrow(dev).meta_dev.minor,
                                 RefCell::borrow(dev).data_dev.major,
                                 RefCell::borrow(dev).data_dev.minor)
                     },
                     RaidMember::Absent => "- -".to_owned(),
                 })
            .collect();

        format!("raid5_ls 3 {} region_size {} {} {}",
                *stripe,
                *region,
                raid_texts.len(),
                raid_texts.join(" "))
    }

    pub fn setup(dm: &DM, name: &str, id: String, devs: Vec<RaidMember>,
                 stripe: Sectors, region: Sectors)
                 -> FroyoResult<RaidDev> {
        let present_devs = devs.iter().filter_map(|ref x| x.present()).count();
        if present_devs < (devs.len() - REDUNDANCY) {
            return Err(FroyoError::Io(io::Error::new(
                ErrorKind::InvalidInput,
                format!(
                    "Too many missing devs to create raid: {}. Need at least {} of {}",
                    devs.len() - present_devs, devs.len() - REDUNDANCY,
                    devs.len()))))
        }

        let first_present_dev = devs.iter()
            .filter_map(|ref x| x.present())
            .next()
            .unwrap();
        let first_present_dev_len = first_present_dev.borrow().data_length();

        // Verify all present devs are the same length
        if !devs.iter().filter_map(|x| x.present()).all(
            |x| x.borrow().data_length() == first_present_dev_len) {
            return Err(FroyoError::Io(io::Error::new(
                ErrorKind::InvalidInput, "RAID member device sizes differ")))
        }

        let target_length = first_present_dev_len
            * Sectors::new((devs.len() - REDUNDANCY) as u64);

        let params = Self::make_raid_params(&devs, stripe, region);
        let raid_table = [(0u64, *target_length, "raid", params)];
        let dm_name = format!("froyo-raid5-{}-{}", name, id);
        let raid_dev = try!(setup_dm_dev(dm, &dm_name, &raid_table));

        Ok(RaidDev {
            id: id,
            dev: raid_dev,
            dm_name: dm_name,
            stripe_sectors: stripe,
            region_sectors: region,
            length: target_length,
            members: devs,
            used: BTreeMap::new()
        })
    }

    pub fn teardown(&mut self, dm: &DM) -> FroyoResult<()> {
        try!(teardown_dm_dev(dm, &self.dm_name));
        for member in &self.members {
            if let RaidMember::Present(ref linear) = *member {
                try!(RefCell::borrow_mut(linear).teardown(dm))
            }
        }

        Ok(())
    }

    pub fn reload(&mut self, dm: &DM) -> FroyoResult<()> {
        let params = Self::make_raid_params(
            &self.members, self.stripe_sectors, self.region_sectors);
        let raid_table = [(0u64, *self.length, "raid", params)];
        let id = &DevId::Name(&self.dm_name);

        try!(dm.table_load(id, &raid_table));
        try!(dm.device_suspend(id, DM_SUSPEND));
        try!(dm.device_suspend(id, DmFlags::empty()));

        Ok(())
    }

    pub fn to_save(&self) -> RaidDevSave {
        RaidDevSave {
            stripe_sectors: self.stripe_sectors,
            region_sectors: self.region_sectors,
            length: self.length,
            member_count: self.members.len(),
            members: self.members.iter().enumerate()
                .filter_map(|(position, dev)| {
                    if let RaidMember::Present(ref x) = *dev {
                        Some((position.to_string(), RefCell::borrow(x).to_save()))
                    } else {
                        None
                    }
                })
                .collect(),
        }
    }

    fn used_areas(&self)-> Vec<(SectorOffset, Sectors)> {
        self.used.iter()
            .map(|(key, val)| {
                (*key, *val)
            })
            .collect()
    }

    fn avail_areas(&self) -> Vec<(SectorOffset, Sectors)> {
        let mut used_vec = self.used_areas();

        used_vec.sort();
        // Insert an entry to mark the end of the raiddev so the fold works
        // correctly
        used_vec.push((SectorOffset::new(*self.length), Sectors::new(0)));

        let mut avail_vec = Vec::new();
        used_vec.iter()
            .fold(SectorOffset::new(0), |prev_end, &(start, len)| {
                if prev_end < start {
                    avail_vec.push((prev_end, Sectors::new(*start-*prev_end)));
                }
                start + SectorOffset::new(*len)
            });

        avail_vec
    }

    pub fn avail_sectors(&self) -> Sectors {
        self.avail_areas().into_iter()
            .map(|(_, len)| len)
            .sum()
    }

    // Find some sector ranges that could be allocated. If more
    // sectors are needed than our capacity, return partial results.
    pub fn get_some_space(&self, size: Sectors) -> (Sectors, Vec<(SectorOffset, Sectors)>) {
        let mut segs = Vec::new();
        let mut needed = size;

        for (start, len) in self.avail_areas() {
            if needed == Sectors::new(0) {
                break
            }

            let to_use = min(needed, len);

            segs.push((start, to_use));
            needed = needed - to_use;
        }

        (size - needed, segs)
    }

    pub fn status(&self) -> FroyoResult<(RaidStatus, RaidAction)> {
        let dm = try!(DM::new());

        let (_, mut status) = try!(dm.table_status(&DevId::Name(&self.dm_name), DmFlags::empty()));

        if status.len() != 1 {
            return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidData,
                "Expected 1 line from raid status")))
        }

        // See kernel's dm-raid.txt "Status Output"
        let status_line = status.pop().unwrap().3;
        let status_vals = status_line.split(' ').collect::<Vec<_>>();
        if status_vals.len() < 5 {
            return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidData,
                "Kernel returned too few values from raid status")))
        }

        let mut bad = 0;
        for c in status_vals[2].chars() {
            match c {
                'A' => {},
                'a' => {},
                'D' => bad += 1,
                x => return Err(FroyoError::Io(io::Error::new(
                    ErrorKind::InvalidData,
                    format!("Kernel returned unknown raid health char '{}'", x)))),
            }
        }

        let raid_status = match bad {
            0 => RaidStatus::Good,
            x @ 1...REDUNDANCY => RaidStatus::Degraded(x),
            _ => RaidStatus::Failed,
        };

        let raid_action = match status_vals[4] {
            "idle" => RaidAction::Idle,
            "frozen" => RaidAction::Frozen,
            "resync" => RaidAction::Resync,
            "recover" => RaidAction::Recover,
            "check" => RaidAction::Check,
            "repair" => RaidAction::Repair,
            "reshape" => RaidAction::Reshape,
            _ => RaidAction::Unknown,
        };

        Ok((raid_status, raid_action))
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidSegmentSave {
    pub start: SectorOffset,
    pub length: Sectors,
    pub parent: String,  // RaidDev id
}

#[derive(Clone)]
pub struct RaidSegment {
    pub start: SectorOffset,
    pub length: Sectors,
    pub parent: Rc<RefCell<RaidDev>>,
}

impl fmt::Debug for RaidSegment {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {})", *self.start, *self.length,
               RefCell::borrow(&self.parent).id)
    }
}

impl RaidSegment {
    pub fn new(start: SectorOffset, length: Sectors, parent: &Rc<RefCell<RaidDev>>)
           -> RaidSegment {
        let rs = RaidSegment {
            start: start,
            length: length,
            parent: parent.clone(),
        };
        RefCell::borrow_mut(parent).used.insert(start, length);

        // RaidSegments are forever. If not, then don't forget to
        // update parent RaidDev's used vec

        rs
    }

    pub fn to_save(&self) -> RaidSegmentSave {
        RaidSegmentSave {
            start: self.start,
            length: self.length,
            parent: RefCell::borrow(&self.parent).id.clone(),
        }
    }
}

impl Drop for RaidSegment {
    fn drop(&mut self) {
        self.parent.borrow_mut().used.remove(&self.start);
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidLinearDevSave {
    pub id: String,
    pub segments: Vec<RaidSegmentSave>,
}

#[derive(Debug, Clone)]
pub struct RaidLinearDev {
    id: String,
    pub dm_name: String,
    pub dev: Device,
    pub segments: Vec<RaidSegment>,
}

impl RaidLinearDev {
    pub fn dm_table(segments: &[RaidSegment])
                    -> Vec<(u64, u64, String, String)> {
        let mut table = Vec::new();
        let mut offset = SectorOffset::new(0);
        for seg in segments {
            let line = (*offset, *seg.length, "linear".to_owned(),
                        format!("{}:{} {}",
                                RefCell::borrow(&seg.parent).dev.major,
                                RefCell::borrow(&seg.parent).dev.minor,
                                *seg.start));
            table.push(line);
            offset = offset + SectorOffset::new(*seg.length);
        }

        table
    }

    pub fn new(dm: &DM, name: &str, id: &str,
               segments: Vec<RaidSegment>)
               -> FroyoResult<RaidLinearDev> {
        Self::setup(dm, name, id, segments)
    }

    pub fn setup(dm: &DM, name: &str, id: &str,
                  segments: Vec<RaidSegment>)
              -> FroyoResult<RaidLinearDev> {

        let table = Self::dm_table(&segments);
        let dm_name = format!("froyo-raid-linear-{}", name);
        let linear_dev = try!(setup_dm_dev(dm, &dm_name, &table));

        Ok(RaidLinearDev {
            id: id.to_owned(),
            dm_name: dm_name,
            dev: linear_dev,
            segments: segments,
        })
    }

    pub fn teardown(&mut self, dm: &DM) -> FroyoResult<()> {
        teardown_dm_dev(dm, &self.dm_name)
    }

    pub fn to_save(&self) -> RaidLinearDevSave {
        RaidLinearDevSave {
            id: self.id.clone(),
            segments: self.segments.iter()
                .map(|x| x.to_save())
                .collect()
        }
    }

    pub fn length(&self) -> Sectors {
        self.segments.iter().map(|x| x.length).sum()
    }

    pub fn extend(&mut self, segs: Vec<RaidSegment>)
        -> FroyoResult<()> {

        // last existing and first new may be contiguous
        let coalesced_new_first = {
            let mut old_last = self.segments.last_mut().unwrap();
            let new_first = segs.first().unwrap();
            let mut coal = false;
            if old_last.parent.borrow().id == new_first.parent.borrow().id
                && (old_last.start + SectorOffset::new(*old_last.length)
                    == new_first.start) {
                    old_last.length = old_last.length + new_first.length;
                    coal = true;
                }
            coal
        };

        if coalesced_new_first {
            self.segments.extend(segs.into_iter().skip(1));
        } else {
            self.segments.extend(segs);
        }

        let table = RaidLinearDev::dm_table(&self.segments);

        let dm = try!(DM::new());
        let id = &DevId::Name(&self.dm_name);

        try!(dm.table_load(id, &table));
        try!(dm.device_suspend(id, DM_SUSPEND));
        try!(dm.device_suspend(id, DmFlags::empty()));

        Ok(())
    }
}
<commit_msg>Raid: Report missing members in raid status<commit_after>// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

use std::collections::BTreeMap;
use std::rc::Rc;
use std::cell::RefCell;
use std::io;
use std::io::ErrorKind;
use std::cmp::min;
use std::fmt;

use devicemapper::{DM, Device, DmFlags, DevId, DM_SUSPEND};

use types::{Sectors, SectorOffset, FroyoError, FroyoResult};
use blockdev::{LinearDev, LinearDevSave};
use consts::*;
use util::{setup_dm_dev, teardown_dm_dev};

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidDevSave {
    pub stripe_sectors: Sectors,
    pub region_sectors: Sectors,
    pub length: Sectors,
    pub member_count: usize,
    pub members: BTreeMap<String, LinearDevSave>,
}

#[derive(Debug, Clone)]
pub struct RaidDev {
    pub id: String,
    dev: Device,
    dm_name: String,
    pub stripe_sectors: Sectors,
    pub region_sectors: Sectors,
    pub length: Sectors,
    pub members: Vec<RaidMember>,
    used: BTreeMap<SectorOffset, Sectors>,
}

#[derive(Debug, Clone, Copy)]
pub enum RaidStatus {
    Good,
    Degraded(usize),
    Failed,
}

#[derive(Debug, Clone, Copy)]
pub enum RaidAction {
    Idle,
    Frozen,
    Resync,
    Recover,
    Check,
    Repair,
    Reshape,
    Unknown,
}

#[derive(Debug, Clone)]
pub enum RaidMember {
    Present(Rc<RefCell<LinearDev>>),
    Absent,
}

impl RaidMember {
    pub fn present(&self) -> Option<Rc<RefCell<LinearDev>>> {
        match *self {
            RaidMember::Present(ref x) => Some(x.clone()),
            RaidMember::Absent => None,
        }
    }
}

impl RaidDev {

    fn make_raid_params(
        devs: &[RaidMember],
        stripe: Sectors,
        region: Sectors)
        -> String {

        let raid_texts: Vec<_> = devs.iter()
            .map(|dev|
                 match *dev {
                     RaidMember::Present(ref dev) => {
                         format!("{}:{} {}:{}",
                                 RefCell::borrow(dev).meta_dev.major,
                                 RefCell::borrow(dev).meta_dev.minor,
                                 RefCell::borrow(dev).data_dev.major,
                                 RefCell::borrow(dev).data_dev.minor)
                     },
                     RaidMember::Absent => "- -".to_owned(),
                 })
            .collect();

        format!("raid5_ls 3 {} region_size {} {} {}",
                *stripe,
                *region,
                raid_texts.len(),
                raid_texts.join(" "))
    }

    pub fn setup(dm: &DM, name: &str, id: String, devs: Vec<RaidMember>,
                 stripe: Sectors, region: Sectors)
                 -> FroyoResult<RaidDev> {
        let present_devs = devs.iter().filter_map(|ref x| x.present()).count();
        if present_devs < (devs.len() - REDUNDANCY) {
            return Err(FroyoError::Io(io::Error::new(
                ErrorKind::InvalidInput,
                format!(
                    "Too many missing devs to create raid: {}. Need at least {} of {}",
                    devs.len() - present_devs, devs.len() - REDUNDANCY,
                    devs.len()))))
        }

        let first_present_dev = devs.iter()
            .filter_map(|ref x| x.present())
            .next()
            .unwrap();
        let first_present_dev_len = first_present_dev.borrow().data_length();

        // Verify all present devs are the same length
        if !devs.iter().filter_map(|x| x.present()).all(
            |x| x.borrow().data_length() == first_present_dev_len) {
            return Err(FroyoError::Io(io::Error::new(
                ErrorKind::InvalidInput, "RAID member device sizes differ")))
        }

        let target_length = first_present_dev_len
            * Sectors::new((devs.len() - REDUNDANCY) as u64);

        let params = Self::make_raid_params(&devs, stripe, region);
        let raid_table = [(0u64, *target_length, "raid", params)];
        let dm_name = format!("froyo-raid5-{}-{}", name, id);
        let raid_dev = try!(setup_dm_dev(dm, &dm_name, &raid_table));

        Ok(RaidDev {
            id: id,
            dev: raid_dev,
            dm_name: dm_name,
            stripe_sectors: stripe,
            region_sectors: region,
            length: target_length,
            members: devs,
            used: BTreeMap::new()
        })
    }

    pub fn teardown(&mut self, dm: &DM) -> FroyoResult<()> {
        try!(teardown_dm_dev(dm, &self.dm_name));
        for member in &self.members {
            if let RaidMember::Present(ref linear) = *member {
                try!(RefCell::borrow_mut(linear).teardown(dm))
            }
        }

        Ok(())
    }

    pub fn reload(&mut self, dm: &DM) -> FroyoResult<()> {
        let params = Self::make_raid_params(
            &self.members, self.stripe_sectors, self.region_sectors);
        let raid_table = [(0u64, *self.length, "raid", params)];
        let id = &DevId::Name(&self.dm_name);

        try!(dm.table_load(id, &raid_table));
        try!(dm.device_suspend(id, DM_SUSPEND));
        try!(dm.device_suspend(id, DmFlags::empty()));

        Ok(())
    }

    pub fn to_save(&self) -> RaidDevSave {
        RaidDevSave {
            stripe_sectors: self.stripe_sectors,
            region_sectors: self.region_sectors,
            length: self.length,
            member_count: self.members.len(),
            members: self.members.iter().enumerate()
                .filter_map(|(position, dev)| {
                    if let RaidMember::Present(ref x) = *dev {
                        Some((position.to_string(), RefCell::borrow(x).to_save()))
                    } else {
                        None
                    }
                })
                .collect(),
        }
    }

    fn used_areas(&self)-> Vec<(SectorOffset, Sectors)> {
        self.used.iter()
            .map(|(key, val)| {
                (*key, *val)
            })
            .collect()
    }

    fn avail_areas(&self) -> Vec<(SectorOffset, Sectors)> {
        let mut used_vec = self.used_areas();

        used_vec.sort();
        // Insert an entry to mark the end of the raiddev so the fold works
        // correctly
        used_vec.push((SectorOffset::new(*self.length), Sectors::new(0)));

        let mut avail_vec = Vec::new();
        used_vec.iter()
            .fold(SectorOffset::new(0), |prev_end, &(start, len)| {
                if prev_end < start {
                    avail_vec.push((prev_end, Sectors::new(*start-*prev_end)));
                }
                start + SectorOffset::new(*len)
            });

        avail_vec
    }

    pub fn avail_sectors(&self) -> Sectors {
        self.avail_areas().into_iter()
            .map(|(_, len)| len)
            .sum()
    }

    // Find some sector ranges that could be allocated. If more
    // sectors are needed than our capacity, return partial results.
    pub fn get_some_space(&self, size: Sectors) -> (Sectors, Vec<(SectorOffset, Sectors)>) {
        let mut segs = Vec::new();
        let mut needed = size;

        for (start, len) in self.avail_areas() {
            if needed == Sectors::new(0) {
                break
            }

            let to_use = min(needed, len);

            segs.push((start, to_use));
            needed = needed - to_use;
        }

        (size - needed, segs)
    }

    pub fn status(&self) -> FroyoResult<(RaidStatus, RaidAction)> {
        let dm = try!(DM::new());

        let (_, mut status) = try!(dm.table_status(&DevId::Name(&self.dm_name), DmFlags::empty()));

        if status.len() != 1 {
            return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidData,
                "Expected 1 line from raid status")))
        }

        // See kernel's dm-raid.txt "Status Output"
        let status_line = status.pop().unwrap().3;
        let status_vals = status_line.split(' ').collect::<Vec<_>>();
        if status_vals.len() < 5 {
            return Err(FroyoError::Io(io::Error::new(
                io::ErrorKind::InvalidData,
                "Kernel returned too few values from raid status")))
        }

        let mut bad = 0;
        for c in status_vals[2].chars() {
            match c {
                'A' => {},
                'a' => {},
                'D' => bad += 1,
                x => return Err(FroyoError::Io(io::Error::new(
                    ErrorKind::InvalidData,
                    format!("Kernel returned unknown raid health char '{}'", x)))),
            }
        }

        // Status characters indicate if a drive is faulty, but not if
        // the raid was configured with missing devices. Add them.
        bad += self.members.iter().
            filter(|rm| rm.present().is_none())
            .count();

        let raid_status = match bad {
            0 => RaidStatus::Good,
            x @ 1...REDUNDANCY => RaidStatus::Degraded(x),
            _ => RaidStatus::Failed,
        };

        let raid_action = match status_vals[4] {
            "idle" => RaidAction::Idle,
            "frozen" => RaidAction::Frozen,
            "resync" => RaidAction::Resync,
            "recover" => RaidAction::Recover,
            "check" => RaidAction::Check,
            "repair" => RaidAction::Repair,
            "reshape" => RaidAction::Reshape,
            _ => RaidAction::Unknown,
        };

        Ok((raid_status, raid_action))
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidSegmentSave {
    pub start: SectorOffset,
    pub length: Sectors,
    pub parent: String,  // RaidDev id
}

#[derive(Clone)]
pub struct RaidSegment {
    pub start: SectorOffset,
    pub length: Sectors,
    pub parent: Rc<RefCell<RaidDev>>,
}

impl fmt::Debug for RaidSegment {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "({}, {}, {})", *self.start, *self.length,
               RefCell::borrow(&self.parent).id)
    }
}

impl RaidSegment {
    pub fn new(start: SectorOffset, length: Sectors, parent: &Rc<RefCell<RaidDev>>)
           -> RaidSegment {
        let rs = RaidSegment {
            start: start,
            length: length,
            parent: parent.clone(),
        };
        RefCell::borrow_mut(parent).used.insert(start, length);

        // RaidSegments are forever. If not, then don't forget to
        // update parent RaidDev's used vec

        rs
    }

    pub fn to_save(&self) -> RaidSegmentSave {
        RaidSegmentSave {
            start: self.start,
            length: self.length,
            parent: RefCell::borrow(&self.parent).id.clone(),
        }
    }
}

impl Drop for RaidSegment {
    fn drop(&mut self) {
        self.parent.borrow_mut().used.remove(&self.start);
    }
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RaidLinearDevSave {
    pub id: String,
    pub segments: Vec<RaidSegmentSave>,
}

#[derive(Debug, Clone)]
pub struct RaidLinearDev {
    id: String,
    pub dm_name: String,
    pub dev: Device,
    pub segments: Vec<RaidSegment>,
}

impl RaidLinearDev {
    pub fn dm_table(segments: &[RaidSegment])
                    -> Vec<(u64, u64, String, String)> {
        let mut table = Vec::new();
        let mut offset = SectorOffset::new(0);
        for seg in segments {
            let line = (*offset, *seg.length, "linear".to_owned(),
                        format!("{}:{} {}",
                                RefCell::borrow(&seg.parent).dev.major,
                                RefCell::borrow(&seg.parent).dev.minor,
                                *seg.start));
            table.push(line);
            offset = offset + SectorOffset::new(*seg.length);
        }

        table
    }

    pub fn new(dm: &DM, name: &str, id: &str,
               segments: Vec<RaidSegment>)
               -> FroyoResult<RaidLinearDev> {
        Self::setup(dm, name, id, segments)
    }

    pub fn setup(dm: &DM, name: &str, id: &str,
                  segments: Vec<RaidSegment>)
              -> FroyoResult<RaidLinearDev> {

        let table = Self::dm_table(&segments);
        let dm_name = format!("froyo-raid-linear-{}", name);
        let linear_dev = try!(setup_dm_dev(dm, &dm_name, &table));

        Ok(RaidLinearDev {
            id: id.to_owned(),
            dm_name: dm_name,
            dev: linear_dev,
            segments: segments,
        })
    }

    pub fn teardown(&mut self, dm: &DM) -> FroyoResult<()> {
        teardown_dm_dev(dm, &self.dm_name)
    }

    pub fn to_save(&self) -> RaidLinearDevSave {
        RaidLinearDevSave {
            id: self.id.clone(),
            segments: self.segments.iter()
                .map(|x| x.to_save())
                .collect()
        }
    }

    pub fn length(&self) -> Sectors {
        self.segments.iter().map(|x| x.length).sum()
    }

    pub fn extend(&mut self, segs: Vec<RaidSegment>)
        -> FroyoResult<()> {

        // last existing and first new may be contiguous
        let coalesced_new_first = {
            let mut old_last = self.segments.last_mut().unwrap();
            let new_first = segs.first().unwrap();
            let mut coal = false;
            if old_last.parent.borrow().id == new_first.parent.borrow().id
                && (old_last.start + SectorOffset::new(*old_last.length)
                    == new_first.start) {
                    old_last.length = old_last.length + new_first.length;
                    coal = true;
                }
            coal
        };

        if coalesced_new_first {
            self.segments.extend(segs.into_iter().skip(1));
        } else {
            self.segments.extend(segs);
        }

        let table = RaidLinearDev::dm_table(&self.segments);

        let dm = try!(DM::new());
        let id = &DevId::Name(&self.dm_name);

        try!(dm.table_load(id, &table));
        try!(dm.device_suspend(id, DM_SUSPEND));
        try!(dm.device_suspend(id, DmFlags::empty()));

        Ok(())
    }
}
<|endoftext|>


<commit_before>//! Implementation of [`Distribution`] for various structs.

use crate::{
    date::{MAX_YEAR, MIN_YEAR},
    hack, util, Date, Duration, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset, Weekday,
};
use rand::{
    distributions::{Distribution, Standard},
    Rng,
};

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<Time> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Time {
        Time {
            hour: rng.gen_range(0, 24),
            minute: rng.gen_range(0, 60),
            second: rng.gen_range(0, 60),
            nanosecond: rng.gen_range(0, 1_000_000_000),
            padding: hack::Padding::Optimize,
        }
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<Date> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Date {
        let min_date = Date::from_ordinal_date_unchecked(MIN_YEAR, 1);
        let max_date = Date::from_ordinal_date_unchecked(MAX_YEAR, util::days_in_year(MAX_YEAR));

        match Date::from_julian_day(
            rng.gen_range(min_date.to_julian_day(), max_date.to_julian_day() + 1),
        ) {
            Ok(date) => date,
            Err(_) => unreachable!("The value is guaranteed to be in the range of valid dates."),
        }
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<UtcOffset> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> UtcOffset {
        let hours = rng.gen_range(-23, 24);
        let mut minutes = rng.gen_range(0, 60);
        let mut seconds = rng.gen_range(0, 60);

        if hours < 0 {
            minutes *= 1;
            seconds *= 1;
        }

        UtcOffset {
            hours,
            minutes,
            seconds,
        }
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<PrimitiveDateTime> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PrimitiveDateTime {
        PrimitiveDateTime::new(Self.sample(rng), Self.sample(rng))
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<OffsetDateTime> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> OffsetDateTime {
        let date_time: PrimitiveDateTime = Self.sample(rng);
        date_time.assume_offset(Self.sample(rng))
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<Duration> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Duration {
        let seconds = Self.sample(rng);
        Duration {
            seconds,
            nanoseconds: seconds.signum() as i32 * rng.gen_range(0, 1_000_000_000),
        }
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<Weekday> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Weekday {
        use Weekday::*;

        match rng.gen_range(0, 7) {
            0 => Monday,
            1 => Tuesday,
            2 => Wednesday,
            3 => Thursday,
            4 => Friday,
            5 => Saturday,
            _ => Sunday,
        }
    }
}
<commit_msg>Fix rand implementation for UtcOffset<commit_after>//! Implementation of [`Distribution`] for various structs.

use crate::{
    date::{MAX_YEAR, MIN_YEAR},
    hack, util, Date, Duration, OffsetDateTime, PrimitiveDateTime, Time, UtcOffset, Weekday,
};
use rand::{
    distributions::{Distribution, Standard},
    Rng,
};

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<Time> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Time {
        Time {
            hour: rng.gen_range(0, 24),
            minute: rng.gen_range(0, 60),
            second: rng.gen_range(0, 60),
            nanosecond: rng.gen_range(0, 1_000_000_000),
            padding: hack::Padding::Optimize,
        }
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<Date> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Date {
        let min_date = Date::from_ordinal_date_unchecked(MIN_YEAR, 1);
        let max_date = Date::from_ordinal_date_unchecked(MAX_YEAR, util::days_in_year(MAX_YEAR));

        match Date::from_julian_day(
            rng.gen_range(min_date.to_julian_day(), max_date.to_julian_day() + 1),
        ) {
            Ok(date) => date,
            Err(_) => unreachable!("The value is guaranteed to be in the range of valid dates."),
        }
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<UtcOffset> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> UtcOffset {
        let hours = rng.gen_range(-23, 24);
        let mut minutes = rng.gen_range(0, 60);
        let mut seconds = rng.gen_range(0, 60);

        if hours < 0 {
            minutes *= -1;
            seconds *= -1;
        }

        UtcOffset {
            hours,
            minutes,
            seconds,
        }
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<PrimitiveDateTime> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> PrimitiveDateTime {
        PrimitiveDateTime::new(Self.sample(rng), Self.sample(rng))
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<OffsetDateTime> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> OffsetDateTime {
        let date_time: PrimitiveDateTime = Self.sample(rng);
        date_time.assume_offset(Self.sample(rng))
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<Duration> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Duration {
        let seconds = Self.sample(rng);
        Duration {
            seconds,
            nanoseconds: seconds.signum() as i32 * rng.gen_range(0, 1_000_000_000),
        }
    }
}

#[cfg_attr(__time_03_docs, doc(cfg(feature = "rand")))]
impl Distribution<Weekday> for Standard {
    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Weekday {
        use Weekday::*;

        match rng.gen_range(0, 7) {
            0 => Monday,
            1 => Tuesday,
            2 => Wednesday,
            3 => Thursday,
            4 => Friday,
            5 => Saturday,
            _ => Sunday,
        }
    }
}
<|endoftext|>


<commit_before>use std::{mem, ptr, int};
use alloc::heap;

/// A preallocated chunk of memory for storing objects of the same type.
pub struct Slab<T> {
    // Chunk of memory
    mem: *mut Entry<T>,
    // Number of elements currently in the slab
    len: int,
    // The total number of elements that the slab can hold
    cap: int,
    // Offset of the next available slot in the slab. Set to the slab's
    // capacity when the slab is full.
    nxt: int,
    // The total number of slots that were initialized
    init: int,
}

static MAX: uint = int::MAX as uint;

// When Entry.nxt is set to this, the entry is in use
static IN_USE: int = -1;

impl<T> Slab<T> {
    pub fn new(cap: uint) -> Slab<T> {
        assert!(cap <= MAX, "capacity too large");
        // TODO:
        // - Use a power of 2 capacity
        // - Ensure that mem size is less than uint::MAX

        let size = cap.checked_mul(&mem::size_of::<Entry<T>>())
            .expect("capacity overflow");

        let ptr = unsafe { heap::allocate(size, mem::min_align_of::<Entry<T>>()) };

        Slab {
            mem: ptr as *mut Entry<T>,
            cap: cap as int,
            len: 0,
            nxt: 0,
            init: 0
        }
    }

    #[inline]
    pub fn count(&self) -> uint {
        self.len as uint
    }

    #[inline]
    pub fn remaining(&self) -> uint {
        (self.cap - self.len) as uint
    }

    #[inline]
    pub fn has_remaining(&self) -> bool {
        self.remaining() > 0
    }

    /// Returns true if the slab contains a value at the given index.
    pub fn exists(&self, idx: uint) -> bool {
        if idx > int::MAX as uint {
            return false;
        }

        let idx = idx as int;
        idx < self.init && self.entry(idx).in_use()
    }

    pub fn insert(&mut self, val: T) -> Result<uint, T> {
        let idx = self.nxt;

        if idx == self.init {
            // Using an uninitialized entry
            if idx == self.cap {
                // No more capacity
                debug!("slab out of capacity; cap={}", self.cap);
                return Err(val);
            }

            self.mut_entry(idx).put(val);

            self.init += 1;
            self.len = self.init;
            self.nxt = self.init;

            debug!("inserting into new slot; idx={}", idx);
        }
        else {
            self.len += 1;
            self.nxt = self.mut_entry(idx).put(val);

            debug!("inserting into reused slot; idx={}", idx);
        }

        Ok(idx as uint)
    }

    /// Releases the given slot
    pub fn remove(&mut self, idx: uint) -> Option<T> {
        debug!("removing value; idx={}", idx);

        if idx > MAX {
            return None;
        }

        let idx = idx as int;

        // Ensure index is within capacity of slab
        if idx >= self.cap {
            return None;
        }

        let nxt = self.nxt;

        match self.mut_entry(idx).remove(nxt) {
            Some(v) => {
                self.nxt = idx;
                self.len -= 1;
                Some(v)
            }
            None => None
        }
    }

    #[inline]
    fn entry(&self, idx: int) -> &Entry<T> {
        unsafe { &*self.mem.offset(idx) }
    }

    #[inline]
    fn mut_entry(&mut self, idx: int) -> &mut Entry<T> {
        unsafe { &mut *self.mem.offset(idx) }
    }

    #[inline]
    fn validate_idx(&self, idx: uint) -> int {
        if idx <= MAX {
            let idx = idx as int;

            if idx < self.cap {
                return idx;
            }
        }

        fail!("invalid index {} -- greater than capacity {}", idx, self.cap);
    }
}

impl<T> Index<uint, T> for Slab<T> {
    fn index<'a>(&'a self, idx: &uint) -> &'a T {
        let idx = self.validate_idx(*idx);

        let e = self.entry(idx);

        if !e.in_use() {
            fail!("invalid index; idx={}", idx);
        }

        &e.val
    }
}

impl<T> IndexMut<uint, T> for Slab<T> {
    fn index_mut<'a>(&'a mut self, idx: &uint) -> &'a mut T {
        let idx = self.validate_idx(*idx);

        let e = self.mut_entry(idx);

        if !e.in_use() {
            fail!("invalid index; idx={}", idx);
        }

        &mut e.val
    }
}

#[unsafe_destructor]
impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        // TODO: check whether or not this is needed with intrinsics::needs_drop
        let mut i = 0;

        while i < self.init {
            self.mut_entry(i).release();
            i += 1;
        }
    }
}

// Holds the values in the slab.
struct Entry<T> {
    nxt: int,
    val: T
}

impl<T> Entry<T> {
    #[inline]
    fn put(&mut self, val: T) -> int {
        assert!(self.nxt != IN_USE);

        let ret = self.nxt;

        unsafe { ptr::write(&mut self.val as *mut T, val); }
        self.nxt = IN_USE;

        // Could be uninitialized memory, but the caller (Slab) should guard
        // not use the return value in those cases.
        ret
    }

    fn remove(&mut self, nxt: int) -> Option<T> {
        if self.in_use() {
            self.nxt = nxt;
            Some(unsafe { ptr::read(&self.val as *const T) })
        } else {
            None
        }
    }

    fn release(&mut self) {
        if self.in_use() {
            let _ = Some(unsafe { ptr::read(&self.val as *const T) });
        }
    }

    #[inline]
    fn in_use(&self) -> bool {
        self.nxt == IN_USE
    }
}

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

    #[test]
    fn test_insertion() {
        let mut slab = Slab::new(1);
        let token = slab.insert(10u).ok().expect("Failed to insert");
        assert_eq!(slab[token], 10u);
    }

    #[test]
    fn test_repeated_insertion() {
        let mut slab = Slab::new(10);

        for i in range(0u, 10u) {
            let token = slab.insert(i + 10u).ok().expect("Failed to insert");
            assert_eq!(slab[token], i + 10u);
        }

        slab.insert(20).err().expect("Inserted when full");
    }

    #[test]
    fn test_repeated_insertion_and_removal() {
        let mut slab = Slab::new(10);
        let mut tokens = vec![];

        for i in range(0u, 10u) {
            let token = slab.insert(i + 10u).ok().expect("Failed to insert");
            tokens.push(token);
            assert_eq!(slab[token], i + 10u);
        }

        for &i in tokens.iter() {
            slab.remove(i);
        }

        slab.insert(20).ok().expect("Failed to insert in newly empty slab");
    }

    #[test]
    fn test_insertion_when_full() {
        let mut slab = Slab::new(1);
        slab.insert(10u).ok().expect("Failed to insert");
        slab.insert(10u).err().expect("Inserted into a full slab");
    }

    #[test]
    fn test_removal_is_successful() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert(10u).ok().expect("Failed to insert");
        slab.remove(t1);
        let t2 = slab.insert(20u).ok().expect("Failed to insert");
        assert_eq!(slab[t2], 20u);
    }

    #[test]
    fn test_mut_retrieval() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert("foo".to_string()).ok().expect("Failed to insert");

        slab[t1].push_str("bar");

        assert_eq!(slab[t1].as_slice(), "foobar");
    }

    #[test]
    #[should_fail]
    fn test_reusing_slots_1() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123u).unwrap();
        let t1 = slab.insert(456u).unwrap();

        assert!(slab.count() == 2);
        assert!(slab.remaining() == 14);

        slab.remove(t0);

        assert!(slab.count() == 1, "actual={}", slab.count());
        assert!(slab.remaining() == 15);

        slab.remove(t1);

        assert!(slab.count() == 0);
        assert!(slab.remaining() == 16);

        let _ = slab[t1];
    }

    #[test]
    fn test_reusing_slots_2() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123u).unwrap();

        assert!(slab[t0] == 123u);
        assert!(slab.remove(t0) == Some(123u));

        let t0 = slab.insert(456u).unwrap();

        assert!(slab[t0] == 456u);

        let t1 = slab.insert(789u).unwrap();

        assert!(slab[t0] == 456u);
        assert!(slab[t1] == 789u);

        assert!(slab.remove(t0).unwrap() == 456u);
        assert!(slab.remove(t1).unwrap() == 789u);

        assert!(slab.count() == 0);
    }
}
<commit_msg>Fix slab insertion assert bug<commit_after>use std::{mem, ptr, int};
use alloc::heap;

/// A preallocated chunk of memory for storing objects of the same type.
pub struct Slab<T> {
    // Chunk of memory
    mem: *mut Entry<T>,
    // Number of elements currently in the slab
    len: int,
    // The total number of elements that the slab can hold
    cap: int,
    // Offset of the next available slot in the slab. Set to the slab's
    // capacity when the slab is full.
    nxt: int,
    // The total number of slots that were initialized
    init: int,
}

static MAX: uint = int::MAX as uint;

// When Entry.nxt is set to this, the entry is in use
static IN_USE: int = -1;

impl<T> Slab<T> {
    pub fn new(cap: uint) -> Slab<T> {
        assert!(cap <= MAX, "capacity too large");
        // TODO:
        // - Use a power of 2 capacity
        // - Ensure that mem size is less than uint::MAX

        let size = cap.checked_mul(&mem::size_of::<Entry<T>>())
            .expect("capacity overflow");

        let ptr = unsafe { heap::allocate(size, mem::min_align_of::<Entry<T>>()) };

        Slab {
            mem: ptr as *mut Entry<T>,
            cap: cap as int,
            len: 0,
            nxt: 0,
            init: 0
        }
    }

    #[inline]
    pub fn count(&self) -> uint {
        self.len as uint
    }

    #[inline]
    pub fn remaining(&self) -> uint {
        (self.cap - self.len) as uint
    }

    #[inline]
    pub fn has_remaining(&self) -> bool {
        self.remaining() > 0
    }

    /// Returns true if the slab contains a value at the given index.
    pub fn exists(&self, idx: uint) -> bool {
        if idx > int::MAX as uint {
            return false;
        }

        let idx = idx as int;
        idx < self.init && self.entry(idx).in_use()
    }

    pub fn insert(&mut self, val: T) -> Result<uint, T> {
        let idx = self.nxt;

        if idx == self.init {
            // Using an uninitialized entry
            if idx == self.cap {
                // No more capacity
                debug!("slab out of capacity; cap={}", self.cap);
                return Err(val);
            }

            self.mut_entry(idx).put(val, true);

            self.init += 1;
            self.len = self.init;
            self.nxt = self.init;

            debug!("inserting into new slot; idx={}", idx);
        }
        else {
            self.len += 1;
            self.nxt = self.mut_entry(idx).put(val, false);

            debug!("inserting into reused slot; idx={}", idx);
        }

        Ok(idx as uint)
    }

    /// Releases the given slot
    pub fn remove(&mut self, idx: uint) -> Option<T> {
        debug!("removing value; idx={}", idx);

        if idx > MAX {
            return None;
        }

        let idx = idx as int;

        // Ensure index is within capacity of slab
        if idx >= self.cap {
            return None;
        }

        let nxt = self.nxt;

        match self.mut_entry(idx).remove(nxt) {
            Some(v) => {
                self.nxt = idx;
                self.len -= 1;
                Some(v)
            }
            None => None
        }
    }

    #[inline]
    fn entry(&self, idx: int) -> &Entry<T> {
        unsafe { &*self.mem.offset(idx) }
    }

    #[inline]
    fn mut_entry(&mut self, idx: int) -> &mut Entry<T> {
        unsafe { &mut *self.mem.offset(idx) }
    }

    #[inline]
    fn validate_idx(&self, idx: uint) -> int {
        if idx <= MAX {
            let idx = idx as int;

            if idx < self.cap {
                return idx;
            }
        }

        fail!("invalid index {} -- greater than capacity {}", idx, self.cap);
    }
}

impl<T> Index<uint, T> for Slab<T> {
    fn index<'a>(&'a self, idx: &uint) -> &'a T {
        let idx = self.validate_idx(*idx);

        let e = self.entry(idx);

        if !e.in_use() {
            fail!("invalid index; idx={}", idx);
        }

        &e.val
    }
}

impl<T> IndexMut<uint, T> for Slab<T> {
    fn index_mut<'a>(&'a mut self, idx: &uint) -> &'a mut T {
        let idx = self.validate_idx(*idx);

        let e = self.mut_entry(idx);

        if !e.in_use() {
            fail!("invalid index; idx={}", idx);
        }

        &mut e.val
    }
}

#[unsafe_destructor]
impl<T> Drop for Slab<T> {
    fn drop(&mut self) {
        // TODO: check whether or not this is needed with intrinsics::needs_drop
        let mut i = 0;

        while i < self.init {
            self.mut_entry(i).release();
            i += 1;
        }
    }
}

// Holds the values in the slab.
struct Entry<T> {
    nxt: int,
    val: T
}

impl<T> Entry<T> {
    #[inline]
    fn put(&mut self, val: T, init: bool) -> int {
        assert!(init || self.nxt != IN_USE);

        let ret = self.nxt;

        unsafe { ptr::write(&mut self.val as *mut T, val); }
        self.nxt = IN_USE;

        // Could be uninitialized memory, but the caller (Slab) should guard
        // not use the return value in those cases.
        ret
    }

    fn remove(&mut self, nxt: int) -> Option<T> {
        if self.in_use() {
            self.nxt = nxt;
            Some(unsafe { ptr::read(&self.val as *const T) })
        } else {
            None
        }
    }

    fn release(&mut self) {
        if self.in_use() {
            let _ = Some(unsafe { ptr::read(&self.val as *const T) });
        }
    }

    #[inline]
    fn in_use(&self) -> bool {
        self.nxt == IN_USE
    }
}

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

    #[test]
    fn test_insertion() {
        let mut slab = Slab::new(1);
        let token = slab.insert(10u).ok().expect("Failed to insert");
        assert_eq!(slab[token], 10u);
    }

    #[test]
    fn test_repeated_insertion() {
        let mut slab = Slab::new(10);

        for i in range(0u, 10u) {
            let token = slab.insert(i + 10u).ok().expect("Failed to insert");
            assert_eq!(slab[token], i + 10u);
        }

        slab.insert(20).err().expect("Inserted when full");
    }

    #[test]
    fn test_repeated_insertion_and_removal() {
        let mut slab = Slab::new(10);
        let mut tokens = vec![];

        for i in range(0u, 10u) {
            let token = slab.insert(i + 10u).ok().expect("Failed to insert");
            tokens.push(token);
            assert_eq!(slab[token], i + 10u);
        }

        for &i in tokens.iter() {
            slab.remove(i);
        }

        slab.insert(20).ok().expect("Failed to insert in newly empty slab");
    }

    #[test]
    fn test_insertion_when_full() {
        let mut slab = Slab::new(1);
        slab.insert(10u).ok().expect("Failed to insert");
        slab.insert(10u).err().expect("Inserted into a full slab");
    }

    #[test]
    fn test_removal_is_successful() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert(10u).ok().expect("Failed to insert");
        slab.remove(t1);
        let t2 = slab.insert(20u).ok().expect("Failed to insert");
        assert_eq!(slab[t2], 20u);
    }

    #[test]
    fn test_mut_retrieval() {
        let mut slab = Slab::new(1);
        let t1 = slab.insert("foo".to_string()).ok().expect("Failed to insert");

        slab[t1].push_str("bar");

        assert_eq!(slab[t1].as_slice(), "foobar");
    }

    #[test]
    #[should_fail]
    fn test_reusing_slots_1() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123u).unwrap();
        let t1 = slab.insert(456u).unwrap();

        assert!(slab.count() == 2);
        assert!(slab.remaining() == 14);

        slab.remove(t0);

        assert!(slab.count() == 1, "actual={}", slab.count());
        assert!(slab.remaining() == 15);

        slab.remove(t1);

        assert!(slab.count() == 0);
        assert!(slab.remaining() == 16);

        let _ = slab[t1];
    }

    #[test]
    fn test_reusing_slots_2() {
        let mut slab = Slab::new(16);

        let t0 = slab.insert(123u).unwrap();

        assert!(slab[t0] == 123u);
        assert!(slab.remove(t0) == Some(123u));

        let t0 = slab.insert(456u).unwrap();

        assert!(slab[t0] == 456u);

        let t1 = slab.insert(789u).unwrap();

        assert!(slab[t0] == 456u);
        assert!(slab[t1] == 789u);

        assert!(slab.remove(t0).unwrap() == 456u);
        assert!(slab.remove(t1).unwrap() == 789u);

        assert!(slab.count() == 0);
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::io::fs;
use std::io::fs::PathExtensions;
use std::io::process::Command;
use std::fmt::{Show, Formatter, Error};

use app_result::{AppResult, app_err};

use dirs::{
   tags_dir,
   git_src_dir,
   crates_io_src_dir,
   glob_path
};

pub struct Tags
{
   /// the root directory of the source code
   /// for which the tags have been created
   pub src_dir: Path,

   /// the tags file of the sources in `src_dir`
   pub tags_file: Path,

   /// indicates if the tags file is already existing
   /// and the cached tags file is returned
   pub cached: bool
}

/// Checks if there's already a tags file for `lib_name` and `commit_hash`
/// and if not it's creating a new tags file and returning it.
pub fn update_git_tags(lib_name: &String, commit_hash: &String) -> AppResult<Tags>
{
   let mut lib_tags = lib_name.clone();
   lib_tags.push('-');
   lib_tags.push_str(&**commit_hash);

   let mut tags_file = try!(tags_dir());
   tags_file.push(&lib_tags);

   let mut lib_src = lib_name.clone();
   lib_src.push_str("-*");

   let mut src_dir = try!(git_src_dir());
   src_dir.push(&lib_src);
   src_dir.push("master");

   let mut src_paths = glob_path(&src_dir);
   for src_path in src_paths {
      let src_commit_hash = try!(get_commit_hash(&src_path));
      if *commit_hash == src_commit_hash {
         let mut cached = true;
         if ! tags_file.is_file() {
            try!(create_tags(&src_path, &tags_file));
            cached = false;
         }

         return Ok(Tags { src_dir: src_path.clone(), tags_file: tags_file, cached: cached });
      }
   }

   Err(app_err(format!("
   Couldn't find git repository of the dependency '{}'!
   Have you run 'cargo build' at least once after adding the dependency?", lib_name)))
}

/// Checks if there's already a tags file for `lib_name` and `version`
/// and if not it's creating a new tags file and returning it.
pub fn update_crates_io_tags(lib_name: &String, version: &String) -> AppResult<Tags>
{
   let mut lib_tags = lib_name.clone();
   lib_tags.push('-');
   lib_tags.push_str(&**version);

   let mut tags_file = try!(tags_dir());
   tags_file.push(&lib_tags);

   let mut src_dir = try!(crates_io_src_dir());
   src_dir.push(&lib_tags);

   if ! src_dir.is_dir() {
      return Err(app_err(format!("
   Couldn't find source code of the dependency '{}'!
   Have you run 'cargo build' at least once after adding the dependency?", lib_name)));
   }

   let mut cached = true;
   if ! tags_file.is_file() {
      try!(create_tags(&src_dir, &tags_file));
      cached = false;
   }

   Ok(Tags { src_dir: src_dir, tags_file: tags_file, cached: cached })
}

/// merges `tag_files` into `merged_tag_file`
pub fn merge_tags(tag_files: &Vec<Path>, merged_tag_file: &Path) -> AppResult<()>
{
   let mut file_contents: Vec<String> = Vec::new();
   for file in tag_files.iter() {
      file_contents.push(try!(io::File::open(file).read_to_string()));
   }

   let mut merged_lines: Vec<&str> = Vec::with_capacity(100_000);
   for content in file_contents.iter() {
      for line in content.as_slice().lines_any() {
         if ! line.is_empty() && line.char_at(0) != '!' {
            merged_lines.push(line);
         }
      }
   }

   merged_lines.sort();

   let mut tag_file = try!(io::File::open_mode(merged_tag_file, io::Truncate, io::ReadWrite));
   try!(tag_file.write_line("!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;\" to lines/"));
   try!(tag_file.write_line("!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/"));

   for line in merged_lines.iter() {
      try!(tag_file.write_line(*line));
   }

   Ok(())
}

/// creates tags recursive for the directory hierarchy starting at `src_dir`
/// and writes them to `tags_file`
pub fn create_tags(src_dir: &Path, tags_file: &Path) -> AppResult<()>
{
   let mut cmd = Command::new("ctags");
   cmd.arg("--recurse")
      .arg("--langdef=Rust")
      .arg("--langmap=Rust:.rs")
      .arg("--regex-Rust=/^[ \\t]*(#\\[[^\\]]\\][ \\t]*)*(pub[ \\t]+)?(extern[ \\t]+)?(\"[^\"]+\"[ \\t]+)?(unsafe[ \\t]+)?fn[ \\t]+([a-zA-Z0-9_]+)/\\6/f,functions,function definitions/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?type[ \\t]+([a-zA-Z0-9_]+)/\\2/T,types,type definitions/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?enum[ \\t]+([a-zA-Z0-9_]+)/\\2/g,enum,enumeration names/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?struct[ \\t]+([a-zA-Z0-9_]+)/\\2/s,structure names/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?mod[ \\t]+([a-zA-Z0-9_]+)/\\2/m,modules,module names/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?static[ \\t]+([a-zA-Z0-9_]+)/\\2/c,consts,static constants/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?trait[ \\t]+([a-zA-Z0-9_]+)/\\2/t,traits,traits/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?impl([ \\t\\n]*<[^>]*>)?[ \\t]+(([a-zA-Z0-9_:]+)[ \\t]*(<[^>]*>)?[ \\t]+(for)[ \\t]+)?([a-zA-Z0-9_]+)/\\4 \\6 \\7/i,impls,trait implementations/")
      .arg("--regex-Rust=/^[ \\t]*macro_rules![ \\t]+([a-zA-Z0-9_]+)/\\1/d,macros,macro definitions/")
      .arg("-o")
      .arg(tags_file)
      .arg(src_dir);

   try!(cmd.output());

   Ok(())
}

/// get the commit hash of the current `HEAD` of the git repository located at `git_dir`
fn get_commit_hash(git_dir: &Path) -> AppResult<String>
{
   let mut cmd = Command::new("git");
   cmd.cwd(git_dir)
      .arg("rev-parse")
      .arg("HEAD");

   let out = try!(cmd.output());
   String::from_utf8(out.output)
      .map(|s| s.as_slice().trim().to_string())
      .map_err(|_| app_err("Couldn't convert git output to utf8!".to_string()))
}

impl Show for Tags
{
   fn fmt(&self, f: &mut Formatter) -> Result<(), Error>
   {
      write!(f, "Tags ( src_dir: {}, tags_file: {}, cached: {} )",
             self.src_dir.display(), self.tags_file.display(), self.cached)
   }
}
<commit_msg>Handle libraries which name differs from their git repo name<commit_after>use std::io;
use std::io::fs;
use std::io::fs::PathExtensions;
use std::io::process::Command;
use std::fmt::{Show, Formatter, Error};

use app_result::{AppResult, app_err};

use dirs::{
   tags_dir,
   git_src_dir,
   crates_io_src_dir,
   glob_path
};

pub struct Tags
{
   /// the root directory of the source code
   /// for which the tags have been created
   pub src_dir: Path,

   /// the tags file of the sources in `src_dir`
   pub tags_file: Path,

   /// indicates if the tags file is already existing
   /// and the cached tags file is returned
   pub cached: bool
}

/// Checks if there's already a tags file for `lib_name` and `commit_hash`
/// and if not it's creating a new tags file and returning it.
pub fn update_git_tags(lib_name: &String, commit_hash: &String) -> AppResult<Tags>
{
   let mut lib_tags = lib_name.clone();
   lib_tags.push('-');
   lib_tags.push_str(&**commit_hash);

   let mut tags_file = try!(tags_dir());
   tags_file.push(&lib_tags);

   let mut lib_src = lib_name.clone();
   lib_src.push_str("-*");

   let mut src_dir = try!(git_src_dir());
   src_dir.push(&lib_src);
   src_dir.push("master");

   let mut src_paths = glob_path(&src_dir);
   for src_path in src_paths {
      let src_commit_hash = try!(get_commit_hash(&src_path));
      if *commit_hash == src_commit_hash {
         let mut cached = true;
         if ! tags_file.is_file() {
            try!(create_tags(&src_path, &tags_file));
            cached = false;
         }

         return Ok(Tags { src_dir: src_path.clone(), tags_file: tags_file, cached: cached });
      }
   }

   // the git repository name hasn't to match the name of the library,
   // so here we're just going through all git directories and searching
   // for the one with a matching commit hash
   let mut src_dir = try!(git_src_dir());
   src_dir.push("*");
   src_dir.push("master");

   let mut src_paths = glob_path(&src_dir);
   for src_path in src_paths {
      let src_commit_hash = try!(get_commit_hash(&src_path));
      if *commit_hash == src_commit_hash {
         let mut cached = true;
         if ! tags_file.is_file() {
            try!(create_tags(&src_path, &tags_file));
            cached = false;
         }

         return Ok(Tags { src_dir: src_path.clone(), tags_file: tags_file, cached: cached });
      }
   }

   Err(app_err(format!("
   Couldn't find git repository of the dependency '{}'!
   Have you run 'cargo build' at least once after adding the dependency?", lib_name)))
}

/// Checks if there's already a tags file for `lib_name` and `version`
/// and if not it's creating a new tags file and returning it.
pub fn update_crates_io_tags(lib_name: &String, version: &String) -> AppResult<Tags>
{
   let mut lib_tags = lib_name.clone();
   lib_tags.push('-');
   lib_tags.push_str(&**version);

   let mut tags_file = try!(tags_dir());
   tags_file.push(&lib_tags);

   let mut src_dir = try!(crates_io_src_dir());
   src_dir.push(&lib_tags);

   if ! src_dir.is_dir() {
      return Err(app_err(format!("
   Couldn't find source code of the dependency '{}'!
   Have you run 'cargo build' at least once after adding the dependency?", lib_name)));
   }

   let mut cached = true;
   if ! tags_file.is_file() {
      try!(create_tags(&src_dir, &tags_file));
      cached = false;
   }

   Ok(Tags { src_dir: src_dir, tags_file: tags_file, cached: cached })
}

/// merges `tag_files` into `merged_tag_file`
pub fn merge_tags(tag_files: &Vec<Path>, merged_tag_file: &Path) -> AppResult<()>
{
   let mut file_contents: Vec<String> = Vec::new();
   for file in tag_files.iter() {
      file_contents.push(try!(io::File::open(file).read_to_string()));
   }

   let mut merged_lines: Vec<&str> = Vec::with_capacity(100_000);
   for content in file_contents.iter() {
      for line in content.as_slice().lines_any() {
         if ! line.is_empty() && line.char_at(0) != '!' {
            merged_lines.push(line);
         }
      }
   }

   merged_lines.sort();

   let mut tag_file = try!(io::File::open_mode(merged_tag_file, io::Truncate, io::ReadWrite));
   try!(tag_file.write_line("!_TAG_FILE_FORMAT	2	/extended format; --format=1 will not append ;\" to lines/"));
   try!(tag_file.write_line("!_TAG_FILE_SORTED	1	/0=unsorted, 1=sorted, 2=foldcase/"));

   for line in merged_lines.iter() {
      try!(tag_file.write_line(*line));
   }

   Ok(())
}

/// creates tags recursive for the directory hierarchy starting at `src_dir`
/// and writes them to `tags_file`
pub fn create_tags(src_dir: &Path, tags_file: &Path) -> AppResult<()>
{
   let mut cmd = Command::new("ctags");
   cmd.arg("--recurse")
      .arg("--langdef=Rust")
      .arg("--langmap=Rust:.rs")
      .arg("--regex-Rust=/^[ \\t]*(#\\[[^\\]]\\][ \\t]*)*(pub[ \\t]+)?(extern[ \\t]+)?(\"[^\"]+\"[ \\t]+)?(unsafe[ \\t]+)?fn[ \\t]+([a-zA-Z0-9_]+)/\\6/f,functions,function definitions/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?type[ \\t]+([a-zA-Z0-9_]+)/\\2/T,types,type definitions/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?enum[ \\t]+([a-zA-Z0-9_]+)/\\2/g,enum,enumeration names/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?struct[ \\t]+([a-zA-Z0-9_]+)/\\2/s,structure names/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?mod[ \\t]+([a-zA-Z0-9_]+)/\\2/m,modules,module names/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?static[ \\t]+([a-zA-Z0-9_]+)/\\2/c,consts,static constants/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?trait[ \\t]+([a-zA-Z0-9_]+)/\\2/t,traits,traits/")
      .arg("--regex-Rust=/^[ \\t]*(pub[ \\t]+)?impl([ \\t\\n]*<[^>]*>)?[ \\t]+(([a-zA-Z0-9_:]+)[ \\t]*(<[^>]*>)?[ \\t]+(for)[ \\t]+)?([a-zA-Z0-9_]+)/\\4 \\6 \\7/i,impls,trait implementations/")
      .arg("--regex-Rust=/^[ \\t]*macro_rules![ \\t]+([a-zA-Z0-9_]+)/\\1/d,macros,macro definitions/")
      .arg("-o")
      .arg(tags_file)
      .arg(src_dir);

   try!(cmd.output());

   Ok(())
}

/// get the commit hash of the current `HEAD` of the git repository located at `git_dir`
fn get_commit_hash(git_dir: &Path) -> AppResult<String>
{
   let mut cmd = Command::new("git");
   cmd.cwd(git_dir)
      .arg("rev-parse")
      .arg("HEAD");

   let out = try!(cmd.output());
   String::from_utf8(out.output)
      .map(|s| s.as_slice().trim().to_string())
      .map_err(|_| app_err("Couldn't convert git output to utf8!".to_string()))
}

impl Show for Tags
{
   fn fmt(&self, f: &mut Formatter) -> Result<(), Error>
   {
      write!(f, "Tags ( src_dir: {}, tags_file: {}, cached: {} )",
             self.src_dir.display(), self.tags_file.display(), self.cached)
   }
}
<|endoftext|>