<commit_before>//! Implement pull-based [`Read`] trait for both compressing and decompressing.
use std::io::{self, BufRead, BufReader, Read};

#[cfg(feature = "tokio")]
use tokio_io::AsyncRead;

use crate::dict::{DecoderDictionary, EncoderDictionary};
use crate::stream::{raw, zio};
use zstd_safe;

#[cfg(test)]
#[cfg(feature = "tokio")]
mod async_tests;

#[cfg(test)]
mod tests;

/// 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: BufRead> {
    reader: zio::Reader<R, raw::Decoder>,
}

/// An encoder that compress input data from another `Read`.
pub struct Encoder<R: BufRead> {
    reader: zio::Reader<R, raw::Encoder>,
}

impl<R: Read> Decoder<BufReader<R>> {
    /// Creates a new decoder.
    pub fn new(reader: R) -> io::Result<Self> {
        let buffer_size = zstd_safe::dstream_in_size();

        Self::with_buffer(BufReader::with_capacity(buffer_size, reader))
    }
}

impl<R: BufRead> Decoder<R> {
    /// Creates a new decoder around a `BufRead`.
    pub fn with_buffer(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.reader.set_single_frame();
        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 decoder = raw::Decoder::with_dictionary(dictionary)?;
        let reader = zio::Reader::new(reader, decoder);

        Ok(Decoder { reader })
    }

    /// 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 decoder = raw::Decoder::with_prepared_dictionary(dictionary)?;
        let reader = zio::Reader::new(reader, decoder);

        Ok(Decoder { reader })
    }

    /// 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.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 {
        self.reader.reader_mut()
    }

    /// 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.into_inner()
    }
}

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

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

impl<R: Read> Encoder<BufReader<R>> {
    /// Creates a new encoder.
    pub fn new(reader: R, level: i32) -> io::Result<Self> {
        let buffer_size = zstd_safe::dstream_in_size();

        Self::with_buffer(BufReader::with_capacity(buffer_size, reader), level)
    }
}

impl<R: BufRead> Encoder<R> {
    /// Creates a new encoder around a `BufRead`.
    pub fn with_buffer(reader: R, level: i32) -> io::Result<Self> {
        Self::with_dictionary(reader, level, &[])
    }

    /// Creates a new encoder, using an existing dictionary.
    ///
    /// The dictionary must be the same as the one used during compression.
    pub fn with_dictionary(
        reader: R,
        level: i32,
        dictionary: &[u8],
    ) -> io::Result<Self> {
        let encoder = raw::Encoder::with_dictionary(level, dictionary)?;
        let reader = zio::Reader::new(reader, encoder);

        Ok(Encoder { reader })
    }

    /// Creates a new encoder, using an existing `EncoderDictionary`.
    ///
    /// The dictionary must be the same as the one used during compression.
    pub fn with_prepared_dictionary(
        reader: R,
        dictionary: &EncoderDictionary<'_>,
    ) -> io::Result<Self> {
        let encoder = raw::Encoder::with_prepared_dictionary(dictionary)?;
        let reader = zio::Reader::new(reader, encoder);

        Ok(Encoder { reader })
    }

    /// 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.reader()
    }

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

    /// 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.into_inner()
    }
}

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

#[cfg(feature = "tokio")]
impl<R: AsyncRead + BufRead> AsyncRead for Encoder<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())));
    _assert_send(Encoder::new(Cursor::new(Vec::new()), 1));
}
<commit_msg>Add options to read::Encoder as well<commit_after>//! Implement pull-based [`Read`] trait for both compressing and decompressing.
use std::io::{self, BufRead, BufReader, Read};

#[cfg(feature = "tokio")]
use tokio_io::AsyncRead;

use crate::dict::{DecoderDictionary, EncoderDictionary};
use crate::stream::{raw, zio};
use zstd_safe;

#[cfg(test)]
#[cfg(feature = "tokio")]
mod async_tests;

#[cfg(test)]
mod tests;

/// 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: BufRead> {
    reader: zio::Reader<R, raw::Decoder>,
}

/// An encoder that compress input data from another `Read`.
pub struct Encoder<R: BufRead> {
    reader: zio::Reader<R, raw::Encoder>,
}

impl<R: Read> Decoder<BufReader<R>> {
    /// Creates a new decoder.
    pub fn new(reader: R) -> io::Result<Self> {
        let buffer_size = zstd_safe::dstream_in_size();

        Self::with_buffer(BufReader::with_capacity(buffer_size, reader))
    }
}

impl<R: BufRead> Decoder<R> {
    /// Creates a new decoder around a `BufRead`.
    pub fn with_buffer(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.reader.set_single_frame();
        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 decoder = raw::Decoder::with_dictionary(dictionary)?;
        let reader = zio::Reader::new(reader, decoder);

        Ok(Decoder { reader })
    }

    /// 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 decoder = raw::Decoder::with_prepared_dictionary(dictionary)?;
        let reader = zio::Reader::new(reader, decoder);

        Ok(Decoder { reader })
    }

    /// 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.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 {
        self.reader.reader_mut()
    }

    /// 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.into_inner()
    }
}

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

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

impl<R: Read> Encoder<BufReader<R>> {
    /// Creates a new encoder.
    pub fn new(reader: R, level: i32) -> io::Result<Self> {
        let buffer_size = zstd_safe::dstream_in_size();

        Self::with_buffer(BufReader::with_capacity(buffer_size, reader), level)
    }
}

impl<R: BufRead> Encoder<R> {
    /// Creates a new encoder around a `BufRead`.
    pub fn with_buffer(reader: R, level: i32) -> io::Result<Self> {
        Self::with_dictionary(reader, level, &[])
    }

    /// Creates a new encoder, using an existing dictionary.
    ///
    /// The dictionary must be the same as the one used during compression.
    pub fn with_dictionary(
        reader: R,
        level: i32,
        dictionary: &[u8],
    ) -> io::Result<Self> {
        let encoder = raw::Encoder::with_dictionary(level, dictionary)?;
        let reader = zio::Reader::new(reader, encoder);

        Ok(Encoder { reader })
    }

    /// Creates a new encoder, using an existing `EncoderDictionary`.
    ///
    /// The dictionary must be the same as the one used during compression.
    pub fn with_prepared_dictionary(
        reader: R,
        dictionary: &EncoderDictionary<'_>,
    ) -> io::Result<Self> {
        let encoder = raw::Encoder::with_prepared_dictionary(dictionary)?;
        let reader = zio::Reader::new(reader, encoder);

        Ok(Encoder { reader })
    }

    /// 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.reader()
    }

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

    /// 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.into_inner()
    }

    /// Controls whether zstd should include a content checksum at the end of each frame.
    pub fn include_checksum(
        &mut self,
        include_checksum: bool,
    ) -> io::Result<()> {
        self.reader.operation_mut().set_parameter(
            zstd_safe::CParameter::ChecksumFlag(include_checksum),
        )
    }

    /// Enables multithreaded compression
    ///
    /// * If `n_workers == 0` (default), then multithreaded will be disabled.
    /// * If `n_workers >= 1`, then compression will be done in separate threads.
    ///   So even `n_workers = 1` may increase performance by separating IO and compression.
    pub fn multithread(&mut self, n_workers: u32) -> io::Result<()> {
        self.reader
            .operation_mut()
            .set_parameter(zstd_safe::CParameter::NbWorkers(n_workers))
    }
}

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

#[cfg(feature = "tokio")]
impl<R: AsyncRead + BufRead> AsyncRead for Encoder<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())));
    _assert_send(Encoder::new(Cursor::new(Vec::new()), 1));
}
<|endoftext|>


<commit_before>//! Color managemement.
//!
//! # Example
//!
//! ```rust
//! use termion::{color, style};
//!
//! use std::io;
//!
//! fn main() {
//!     println!("{}Red", color::Fg(color::Red));
//!     println!("{}Blue", color::Fg(color::Blue));
//!     println!("{}Back again", color::Fg(color::Reset));
//! }
//! ```

use std::fmt;

/// A terminal color.
pub trait Color {
    /// Write the foreground version of this color.
    fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result;
    /// Write the background version of this color.
    fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result;
}

macro_rules! derive_color {
    ($doc:expr, $name:ident, $value:expr) => {
        #[doc = $doc]
        #[derive(Copy, Clone)]
        pub struct $name;

        impl Color for $name {
            #[inline]
            fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, csi!("38;5;", $value, "m"))
            }

            #[inline]
            fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, csi!("48;5;", $value, "m"))
            }
        }
    };
}

derive_color!("Black.", Black, "0");
derive_color!("Red.", Red, "1");
derive_color!("Green.", Green, "2");
derive_color!("Yellow.", Yellow, "3");
derive_color!("Blue.", Blue, "4");
derive_color!("Magenta.", Magenta, "5");
derive_color!("Cyan.", Cyan, "6");
derive_color!("White.", White, "7");
derive_color!("High-intensity light black.", LightBlack, "8");
derive_color!("High-intensity light red.", LightRed, "9");
derive_color!("High-intensity light green.", LightGreen, "10");
derive_color!("High-intensity light yellow.", LightYellow, "11");
derive_color!("High-intensity light blue.", LightBlue, "12");
derive_color!("High-intensity light magenta.", LightMagenta, "13");
derive_color!("High-intensity light cyan.", LightCyan, "14");
derive_color!("High-intensity light white.", LightWhite, "15");

/// An arbitrary ANSI color value.
#[derive(Clone, Copy)]
pub struct AnsiValue(pub u8);

impl AnsiValue {
    /// 216-color (r, g, b ≤ 5) RGB.
    pub fn rgb(r: u8, g: u8, b: u8) -> AnsiValue {
        debug_assert!(r <= 5, "Red color fragment (r = {}) is out of bound. Make sure r ≤ 5.", r);
        debug_assert!(g <= 5, "Green color fragment (g = {}) is out of bound. Make sure g ≤ 5.", g);
        debug_assert!(b <= 5, "Blue color fragment (b = {}) is out of bound. Make sure b ≤ 5.", b);

        AnsiValue(16 + 36 * r + 6 * g + b)
    }

    /// Grayscale color.
    ///
    /// There are 24 shades of gray.
    pub fn grayscale(shade: u8) -> AnsiValue {
        // Unfortunately, there are a little less than fifty shades.
        debug_assert!(shade < 24, "Grayscale out of bound (shade = {}). There are only 24 shades of \
                      gray.", shade);

        AnsiValue(0xE8 + shade)
    }
}

impl Color for AnsiValue {
    #[inline]
    fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("38;5;{}m"), self.0)
    }

    #[inline]
    fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("48;5;{}m"), self.0)
    }
}

/// A truecolor RGB.
pub struct Rgb(pub u8, pub u8, pub u8);

impl Color for Rgb {
    #[inline]
    fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("38;2;{};{};{}m"), self.0, self.1, self.2)
    }

    #[inline]
    fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("48;2;{};{};{}m"), self.0, self.1, self.2)
    }
}

/// Reset colors to defaults.
pub struct Reset;

impl Color for Reset {
    #[inline]
    fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("39m"))
    }

    #[inline]
    fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("49m"))
    }
}

/// A foreground color.
pub struct Fg<C: Color>(pub C);

impl<C: Color> fmt::Display for Fg<C> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.write_fg(f)
    }
}

/// A background color.
pub struct Bg<C: Color>(pub C);

impl<C: Color> fmt::Display for Bg<C> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.write_bg(f)
    }
}
<commit_msg>Add Debug to color structs and Clone to Rgb / Fg / Bg (#51)<commit_after>//! Color managemement.
//!
//! # Example
//!
//! ```rust
//! use termion::{color, style};
//!
//! use std::io;
//!
//! fn main() {
//!     println!("{}Red", color::Fg(color::Red));
//!     println!("{}Blue", color::Fg(color::Blue));
//!     println!("{}Back again", color::Fg(color::Reset));
//! }
//! ```

use std::fmt;

/// A terminal color.
pub trait Color {
    /// Write the foreground version of this color.
    fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result;
    /// Write the background version of this color.
    fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result;
}

macro_rules! derive_color {
    ($doc:expr, $name:ident, $value:expr) => {
        #[doc = $doc]
        #[derive(Copy, Clone, Debug)]
        pub struct $name;

        impl Color for $name {
            #[inline]
            fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, csi!("38;5;", $value, "m"))
            }

            #[inline]
            fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, csi!("48;5;", $value, "m"))
            }
        }
    };
}

derive_color!("Black.", Black, "0");
derive_color!("Red.", Red, "1");
derive_color!("Green.", Green, "2");
derive_color!("Yellow.", Yellow, "3");
derive_color!("Blue.", Blue, "4");
derive_color!("Magenta.", Magenta, "5");
derive_color!("Cyan.", Cyan, "6");
derive_color!("White.", White, "7");
derive_color!("High-intensity light black.", LightBlack, "8");
derive_color!("High-intensity light red.", LightRed, "9");
derive_color!("High-intensity light green.", LightGreen, "10");
derive_color!("High-intensity light yellow.", LightYellow, "11");
derive_color!("High-intensity light blue.", LightBlue, "12");
derive_color!("High-intensity light magenta.", LightMagenta, "13");
derive_color!("High-intensity light cyan.", LightCyan, "14");
derive_color!("High-intensity light white.", LightWhite, "15");

/// An arbitrary ANSI color value.
#[derive(Clone, Copy, Debug)]
pub struct AnsiValue(pub u8);

impl AnsiValue {
    /// 216-color (r, g, b ≤ 5) RGB.
    pub fn rgb(r: u8, g: u8, b: u8) -> AnsiValue {
        debug_assert!(r <= 5, "Red color fragment (r = {}) is out of bound. Make sure r ≤ 5.", r);
        debug_assert!(g <= 5, "Green color fragment (g = {}) is out of bound. Make sure g ≤ 5.", g);
        debug_assert!(b <= 5, "Blue color fragment (b = {}) is out of bound. Make sure b ≤ 5.", b);

        AnsiValue(16 + 36 * r + 6 * g + b)
    }

    /// Grayscale color.
    ///
    /// There are 24 shades of gray.
    pub fn grayscale(shade: u8) -> AnsiValue {
        // Unfortunately, there are a little less than fifty shades.
        debug_assert!(shade < 24, "Grayscale out of bound (shade = {}). There are only 24 shades of \
                      gray.", shade);

        AnsiValue(0xE8 + shade)
    }
}

impl Color for AnsiValue {
    #[inline]
    fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("38;5;{}m"), self.0)
    }

    #[inline]
    fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("48;5;{}m"), self.0)
    }
}

/// A truecolor RGB.
#[derive(Debug, Clone)]
pub struct Rgb(pub u8, pub u8, pub u8);

impl Color for Rgb {
    #[inline]
    fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("38;2;{};{};{}m"), self.0, self.1, self.2)
    }

    #[inline]
    fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("48;2;{};{};{}m"), self.0, self.1, self.2)
    }
}

/// Reset colors to defaults.
#[derive(Debug)]
pub struct Reset;

impl Color for Reset {
    #[inline]
    fn write_fg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("39m"))
    }

    #[inline]
    fn write_bg(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, csi!("49m"))
    }
}

/// A foreground color.
#[derive(Debug, Clone)]
pub struct Fg<C: Color>(pub C);

impl<C: Color> fmt::Display for Fg<C> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.write_fg(f)
    }
}

/// A background color.
#[derive(Debug, Clone)]
pub struct Bg<C: Color>(pub C);

impl<C: Color> fmt::Display for Bg<C> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.0.write_bg(f)
    }
}
<|endoftext|>


<commit_before>//! Provides helpers for generating colors for use in HexViewBuilder printing,
//! as well as some reexports of the underlying color crate, `termcolor`

use std::io::{self, Write};
use std::ops::Range;

use termcolor::WriteColor;

pub use termcolor::Color as Color;
pub use termcolor::ColorSpec as Spec;

/// A vector of `(ColorSpec, Range)` values to print
pub type Colors = Vec<(Spec, Range<usize>)>;

pub struct ColorlessString(pub String);

impl Write for ColorlessString {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        use std::str;
        let string = str::from_utf8(buf).unwrap();
        self.0 += string;
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl WriteColor for ColorlessString {
    fn supports_color(&self) -> bool {
        false
    }
    fn set_color(&mut self, _spec: &Spec) -> io::Result<()> {
        Ok(())
    }
    fn reset (&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub struct ColorRange<'a> {
    colors: &'a Colors,
    offset: usize,
    idx: usize,
}

impl<'a> Clone for ColorRange<'a> {
    fn clone(&self) -> Self {
        ColorRange {
            colors: self.colors,
            offset: self.offset,
            idx: self.idx,
        }
    }
}

impl<'a> ColorRange<'a> {
    pub fn new(colors: &'a Colors) -> Self {
        ColorRange {
            colors: colors,
            offset: 0,
            idx: 0,
        }
    }
    pub fn update_offset(&mut self, offset: usize) {
        self.offset = offset;
    }
    pub fn get(&mut self, idx: usize) -> Option<Spec> {
        while self.idx < self.colors.len() {
            let (rgb, range) = self.colors[self.idx].clone();
            let offset = self.offset + idx;
            if offset >= range.start && offset < range.end {
                return Some(rgb)
            } else if offset <= range.start { // for non-contiguous colors
                return None
            } else {
                self.idx += 1;
            }
        }
        None
    }
}

macro_rules! make_color {
    ($name:ident, $name_bold:ident, $color:ident) => {
        /// Creates the appropriate ColorSpec
        pub fn $name() -> Spec {
            Spec::new().set_bold(false).set_fg(Some(Color::$color)).clone()
        }
        /// Creates the appropriate ColorSpec, in bold
        pub fn $name_bold () -> Spec {
            Spec::new().set_bold(true).set_fg(Some(Color::$color)).clone()
        }
    }
}

make_color!(red, red_bold, Red);
make_color!(blue, blue_bold, Blue);
make_color!(green, green_bold, Green);
make_color!(yellow, yellow_bold, Yellow);
make_color!(magenta, magenta_bold, Magenta);
make_color!(black, black_bold, Black);
make_color!(cyan, cyan_bold, Cyan);
make_color!(white, white_bold, White);
<commit_msg>Fix ColorRange's `get` implementation<commit_after>//! Provides helpers for generating colors for use in HexViewBuilder printing,
//! as well as some reexports of the underlying color crate, `termcolor`

use std::io::{self, Write};
use std::ops::Range;

use termcolor::WriteColor;

pub use termcolor::Color as Color;
pub use termcolor::ColorSpec as Spec;

/// A vector of `(ColorSpec, Range)` values to print
pub type Colors = Vec<(Spec, Range<usize>)>;

pub struct ColorlessString(pub String);

impl Write for ColorlessString {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        use std::str;
        let string = str::from_utf8(buf).unwrap();
        self.0 += string;
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

impl WriteColor for ColorlessString {
    fn supports_color(&self) -> bool {
        false
    }
    fn set_color(&mut self, _spec: &Spec) -> io::Result<()> {
        Ok(())
    }
    fn reset (&mut self) -> io::Result<()> {
        Ok(())
    }
}

pub struct ColorRange<'a> {
    colors: &'a Colors,
    offset: usize,
}

impl<'a> Clone for ColorRange<'a> {
    fn clone(&self) -> Self {
        ColorRange {
            colors: self.colors,
            offset: self.offset,
        }
    }
}

impl<'a> ColorRange<'a> {
    pub fn new(colors: &'a Colors) -> Self {
        ColorRange {
            colors: colors,
            offset: 0,
        }
    }
    pub fn update_offset(&mut self, offset: usize) {
        self.offset = offset;
    }
    pub fn get(&self, idx: usize) -> Option<Spec> {
        let mut i = 0;
        while i < self.colors.len() {
            let (rgb, range) = self.colors[i].clone();
            let offset = self.offset + idx;
            if offset >= range.start && offset < range.end {
                return Some(rgb)
            } else if offset <= range.start { // for non-contiguous colors
                return None
            } else {
                i += 1;
            }
        }
        None
    }
}

macro_rules! make_color {
    ($name:ident, $name_bold:ident, $color:ident) => {
        /// Creates the appropriate ColorSpec
        pub fn $name() -> Spec {
            Spec::new().set_bold(false).set_fg(Some(Color::$color)).clone()
        }
        /// Creates the appropriate ColorSpec, in bold
        pub fn $name_bold () -> Spec {
            Spec::new().set_bold(true).set_fg(Some(Color::$color)).clone()
        }
    }
}

make_color!(red, red_bold, Red);
make_color!(blue, blue_bold, Blue);
make_color!(green, green_bold, Green);
make_color!(yellow, yellow_bold, Yellow);
make_color!(magenta, magenta_bold, Magenta);
make_color!(black, black_bold, Black);
make_color!(cyan, cyan_bold, Cyan);
make_color!(white, white_bold, White);
<|endoftext|>


<commit_before>//! TODO Documentation

use Output;
use render::Texture;
use wlroots_sys::{wlr_backend, wlr_render_colored_ellipse, wlr_render_colored_quad,
                  wlr_render_texture_create, wlr_render_with_matrix, wlr_renderer,
                  wlr_renderer_begin, wlr_renderer_destroy, wlr_renderer_end,
                  wlr_gles2_renderer_create};

/// A generic interface for rendering to the screen.
///
/// Note that it will technically be possible to have multiple renderers
/// at the same time.
#[derive(Debug)]
pub struct GenericRenderer {
    renderer: *mut wlr_renderer
}

/// The state machine type that allows you to manipulate a screen and
/// its buffer.
///
/// When this structure is dropped it automatically calls wlr_renderer_end
/// and swaps the buffers.
#[derive(Debug)]
pub struct Renderer<'output> {
    renderer: *mut wlr_renderer,
    pub output: &'output mut Output
}

impl GenericRenderer {
    /// Make a gles2 renderer.
    pub(crate) unsafe fn gles2_renderer(backend: *mut wlr_backend) -> Self {
        let renderer = wlr_gles2_renderer_create(backend);
        if renderer.is_null() {
            panic!("Could not construct GLES2 renderer");
        }
        GenericRenderer { renderer }
    }

    /// Make the `Renderer` state machine type.
    ///
    /// This automatically makes the given output the current output.
    pub fn render<'output>(&mut self, output: &'output mut Output) -> Renderer<'output> {
        unsafe {
            output.make_current();
            wlr_renderer_begin(self.renderer, output.as_ptr());
            Renderer { renderer: self.renderer,
                       output }
        }
    }

    /// Create a texture using this renderer.
    pub fn create_texture(&mut self) -> Option<Texture> {
        unsafe { create_texture(self.renderer) }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_renderer {
        self.renderer
    }
}

impl Drop for GenericRenderer {
    fn drop(&mut self) {
        unsafe { wlr_renderer_destroy(self.renderer) }
    }
}

impl<'output> Renderer<'output> {
    /// Create a texture using this renderer
    pub fn create_texture(&mut self) -> Option<Texture> {
        unsafe { create_texture(self.renderer) }
    }

    /// Renders the requested texture using the provided matrix. A typical texture
    /// rendering goes like so:
    ///
    /// TODO FIXME Show how the typical rendering goes in Rust.
    ///
    /// ```c
    /// struct wlr_renderer *renderer;
    /// struct wlr_texture *texture;
    /// float projection[16];
    /// float matrix[16];
    /// wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
    /// wlr_render_with_matrix(renderer, texture, &matrix);
    /// ```
    ///
    /// This will render the texture at <123, 321>.
    pub fn render_with_matrix(&mut self, texture: &Texture, matrix: &[f32; 16]) -> bool {
        unsafe { wlr_render_with_matrix(self.renderer, texture.as_ptr(), matrix) }
    }

    /// Renders a solid quad in the specified color.
    pub fn render_colored_quad(&mut self, color: &[f32; 4], matrix: &[f32; 16]) {
        unsafe { wlr_render_colored_quad(self.renderer, color, matrix) }
    }

    /// Renders a solid ellipse in the specified color.
    pub fn render_colored_ellipse(&mut self, color: &[f32; 4], matrix: &[f32; 16]) {
        unsafe { wlr_render_colored_ellipse(self.renderer, color, matrix) }
    }
}

impl<'output> Drop for Renderer<'output> {
    fn drop(&mut self) {
        unsafe {
            wlr_renderer_end(self.renderer);
            // TODO What about damage tracking?
            self.output.swap_buffers(None, None);
        }
    }
}

unsafe fn create_texture(renderer: *mut wlr_renderer) -> Option<Texture> {
    let texture = wlr_render_texture_create(renderer);
    if texture.is_null() {
        wlr_log!(L_ERROR, "Could not create texture");
        None
    } else {
        Some(Texture::from_ptr(texture))
    }
}
<commit_msg>Added Renderer::clear<commit_after>//! TODO Documentation

use Output;
use render::Texture;
use wlroots_sys::{wlr_backend, wlr_render_colored_ellipse, wlr_render_colored_quad,
                  wlr_render_texture_create, wlr_render_with_matrix, wlr_renderer,
                  wlr_renderer_begin, wlr_renderer_clear, wlr_renderer_destroy, wlr_renderer_end,
                  wlr_gles2_renderer_create};

/// A generic interface for rendering to the screen.
///
/// Note that it will technically be possible to have multiple renderers
/// at the same time.
#[derive(Debug)]
pub struct GenericRenderer {
    renderer: *mut wlr_renderer
}

/// The state machine type that allows you to manipulate a screen and
/// its buffer.
///
/// When this structure is dropped it automatically calls wlr_renderer_end
/// and swaps the buffers.
#[derive(Debug)]
pub struct Renderer<'output> {
    renderer: *mut wlr_renderer,
    pub output: &'output mut Output
}

impl GenericRenderer {
    /// Make a gles2 renderer.
    pub(crate) unsafe fn gles2_renderer(backend: *mut wlr_backend) -> Self {
        let renderer = wlr_gles2_renderer_create(backend);
        if renderer.is_null() {
            panic!("Could not construct GLES2 renderer");
        }
        GenericRenderer { renderer }
    }

    /// Make the `Renderer` state machine type.
    ///
    /// This automatically makes the given output the current output.
    pub fn render<'output>(&mut self, output: &'output mut Output) -> Renderer<'output> {
        unsafe {
            output.make_current();
            wlr_renderer_begin(self.renderer, output.as_ptr());
            Renderer { renderer: self.renderer,
                       output }
        }
    }

    /// Create a texture using this renderer.
    pub fn create_texture(&mut self) -> Option<Texture> {
        unsafe { create_texture(self.renderer) }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_renderer {
        self.renderer
    }
}

impl Drop for GenericRenderer {
    fn drop(&mut self) {
        unsafe { wlr_renderer_destroy(self.renderer) }
    }
}

impl<'output> Renderer<'output> {
    /// Create a texture using this renderer
    pub fn create_texture(&mut self) -> Option<Texture> {
        unsafe { create_texture(self.renderer) }
    }

    pub fn clear(&mut self, float: [f32; 4]) {
        unsafe { wlr_renderer_clear(self.renderer, &float) }
    }

    /// Renders the requested texture using the provided matrix. A typical texture
    /// rendering goes like so:
    ///
    /// TODO FIXME Show how the typical rendering goes in Rust.
    ///
    /// ```c
    /// struct wlr_renderer *renderer;
    /// struct wlr_texture *texture;
    /// float projection[16];
    /// float matrix[16];
    /// wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
    /// wlr_render_with_matrix(renderer, texture, &matrix);
    /// ```
    ///
    /// This will render the texture at <123, 321>.
    pub fn render_with_matrix(&mut self, texture: &Texture, matrix: &[f32; 16]) -> bool {
        unsafe { wlr_render_with_matrix(self.renderer, texture.as_ptr(), matrix) }
    }

    /// Renders a solid quad in the specified color.
    pub fn render_colored_quad(&mut self, color: &[f32; 4], matrix: &[f32; 16]) {
        unsafe { wlr_render_colored_quad(self.renderer, color, matrix) }
    }

    /// Renders a solid ellipse in the specified color.
    pub fn render_colored_ellipse(&mut self, color: &[f32; 4], matrix: &[f32; 16]) {
        unsafe { wlr_render_colored_ellipse(self.renderer, color, matrix) }
    }
}

impl<'output> Drop for Renderer<'output> {
    fn drop(&mut self) {
        unsafe {
            wlr_renderer_end(self.renderer);
            // TODO What about damage tracking?
            self.output.swap_buffers(None, None);
        }
    }
}

unsafe fn create_texture(renderer: *mut wlr_renderer) -> Option<Texture> {
    let texture = wlr_render_texture_create(renderer);
    if texture.is_null() {
        wlr_log!(L_ERROR, "Could not create texture");
        None
    } else {
        Some(Texture::from_ptr(texture))
    }
}
<|endoftext|>


<commit_before>//! TODO Documentation

use std::time::Duration;

use libc::{c_float, c_int, c_void};

use {Output, PixmanRegion};
use render::Texture;
use wlroots_sys::{wl_shm_format, wlr_backend, wlr_backend_get_egl, wlr_render_ellipse_with_matrix,
                  wlr_render_quad_with_matrix, wlr_render_texture, wlr_render_texture_with_matrix,
                  wlr_renderer, wlr_renderer_begin, wlr_renderer_clear, wlr_renderer_destroy,
                  wlr_renderer_end, wlr_texture_from_pixels, wlr_gles2_renderer_create};

/// A generic interface for rendering to the screen.
///
/// Note that it will technically be possible to have multiple renderers
/// at the same time.
#[derive(Debug)]
pub struct GenericRenderer {
    renderer: *mut wlr_renderer
}

/// The state machine type that allows you to manipulate a screen and
/// its buffer.
///
/// When this structure is dropped it automatically calls wlr_renderer_end
/// and swaps the buffers.
#[derive(Debug)]
pub struct Renderer<'output> {
    renderer: *mut wlr_renderer,
    pub damage: Option<(PixmanRegion, Duration)>,
    pub output: &'output mut Output
}

impl GenericRenderer {
    /// Make a gles2 renderer.
    pub(crate) unsafe fn gles2_renderer(backend: *mut wlr_backend) -> Self {
        let egl = wlr_backend_get_egl(backend);
        if egl.is_null() {
            panic!("EGL not available for this backend");
        }
        let renderer = wlr_gles2_renderer_create(egl);
        if renderer.is_null() {
            panic!("Could not construct GLES2 renderer");
        }
        GenericRenderer { renderer }
    }

    /// Make the `Renderer` state machine type.
    ///
    /// This automatically makes the given output the current output.
    pub fn render<'output>(&mut self,
                           output: &'output mut Output,
                           damage: Option<(PixmanRegion, Duration)>)
                           -> Renderer<'output> {
        unsafe {
            output.make_current();
            let (width, height) = output.size();
            wlr_renderer_begin(self.renderer, width, height);
            Renderer { renderer: self.renderer,
                       damage,
                       output }
        }
    }

    /// Create a texture using this renderer.
    pub fn create_texture_from_pixels(&mut self,
                                      format: wl_shm_format,
                                      stride: u32,
                                      width: u32,
                                      height: u32,
                                      data: &[u8])
                                      -> Option<Texture> {
        unsafe {
            create_texture_from_pixels(self.renderer,
                                       format,
                                       stride,
                                       width,
                                       height,
                                       data.as_ptr() as _)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_renderer {
        self.renderer
    }
}

impl Drop for GenericRenderer {
    fn drop(&mut self) {
        unsafe { wlr_renderer_destroy(self.renderer) }
    }
}

impl<'output> Renderer<'output> {
    pub fn clear(&mut self, float: [f32; 4]) {
        unsafe { wlr_renderer_clear(self.renderer, float.as_ptr()) }
    }

    /// Renders the requseted texture.
    pub fn render_texture(&mut self,
                          texture: &Texture,
                          projection: [f32; 9],
                          x: c_int,
                          y: c_int,
                          alpha: c_float)
                          -> bool {
        unsafe {
            wlr_render_texture(self.renderer,
                               texture.as_ptr(),
                               projection.as_ptr(),
                               x,
                               y,
                               alpha)
        }
    }

    /// Renders the requested texture using the provided matrix. A typical texture
    /// rendering goes like so:
    ///
    /// TODO FIXME Show how the typical rendering goes in Rust.
    ///
    /// ```c
    /// struct wlr_renderer *renderer;
    /// struct wlr_texture *texture;
    /// float projection[16];
    /// float matrix[16];
    /// wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
    /// wlr_render_texture_with_matrix(renderer, texture, &matrix);
    /// ```
    ///
    /// This will render the texture at <123, 321>.
    pub fn render_texture_with_matrix(&mut self, texture: &Texture, matrix: [f32; 9]) -> bool {
        // TODO FIXME Add alpha as param
        unsafe {
            wlr_render_texture_with_matrix(self.renderer, texture.as_ptr(), matrix.as_ptr(), 1.0)
        }
    }

    /// Renders a solid quad in the specified color.
    pub fn render_colored_quad(&mut self, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_quad_with_matrix(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }

    /// Renders a solid ellipse in the specified color.
    pub fn render_colored_ellipse(&mut self, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_ellipse_with_matrix(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }
}

impl<'output> Drop for Renderer<'output> {
    fn drop(&mut self) {
        unsafe {
            wlr_renderer_end(self.renderer);
            if let Some((mut damage, when)) = self.damage.take() {
                self.output.swap_buffers(Some(when), Some(&mut damage));
            } else {
                self.output.swap_buffers(None, None);
            }
        }
    }
}

unsafe fn create_texture_from_pixels(renderer: *mut wlr_renderer,
                                     format: wl_shm_format,
                                     stride: u32,
                                     width: u32,
                                     height: u32,
                                     // TODO Slice of u8? It's a void*, hmm
                                     data: *const c_void)
                                     -> Option<Texture> {
    let texture = wlr_texture_from_pixels(renderer, format, stride, width, height, data);
    if texture.is_null() {
        None
    } else {
        Some(Texture::from_ptr(texture))
    }
}
<commit_msg>Added render_colored_rect<commit_after>//! TODO Documentation

use std::time::Duration;

use libc::{c_float, c_int, c_void};

use {Area, Output, PixmanRegion};
use render::Texture;
use wlroots_sys::{wl_shm_format, wlr_backend, wlr_backend_get_egl, wlr_render_ellipse_with_matrix,
                  wlr_render_quad_with_matrix, wlr_render_rect, wlr_render_texture,
                  wlr_render_texture_with_matrix, wlr_renderer, wlr_renderer_begin,
                  wlr_renderer_clear, wlr_renderer_destroy, wlr_renderer_end,
                  wlr_texture_from_pixels, wlr_gles2_renderer_create};

/// A generic interface for rendering to the screen.
///
/// Note that it will technically be possible to have multiple renderers
/// at the same time.
#[derive(Debug)]
pub struct GenericRenderer {
    renderer: *mut wlr_renderer
}

/// The state machine type that allows you to manipulate a screen and
/// its buffer.
///
/// When this structure is dropped it automatically calls wlr_renderer_end
/// and swaps the buffers.
#[derive(Debug)]
pub struct Renderer<'output> {
    renderer: *mut wlr_renderer,
    pub damage: Option<(PixmanRegion, Duration)>,
    pub output: &'output mut Output
}

impl GenericRenderer {
    /// Make a gles2 renderer.
    pub(crate) unsafe fn gles2_renderer(backend: *mut wlr_backend) -> Self {
        let egl = wlr_backend_get_egl(backend);
        if egl.is_null() {
            panic!("EGL not available for this backend");
        }
        let renderer = wlr_gles2_renderer_create(egl);
        if renderer.is_null() {
            panic!("Could not construct GLES2 renderer");
        }
        GenericRenderer { renderer }
    }

    /// Make the `Renderer` state machine type.
    ///
    /// This automatically makes the given output the current output.
    pub fn render<'output>(&mut self,
                           output: &'output mut Output,
                           damage: Option<(PixmanRegion, Duration)>)
                           -> Renderer<'output> {
        unsafe {
            output.make_current();
            let (width, height) = output.size();
            wlr_renderer_begin(self.renderer, width, height);
            Renderer { renderer: self.renderer,
                       damage,
                       output }
        }
    }

    /// Create a texture using this renderer.
    pub fn create_texture_from_pixels(&mut self,
                                      format: wl_shm_format,
                                      stride: u32,
                                      width: u32,
                                      height: u32,
                                      data: &[u8])
                                      -> Option<Texture> {
        unsafe {
            create_texture_from_pixels(self.renderer,
                                       format,
                                       stride,
                                       width,
                                       height,
                                       data.as_ptr() as _)
        }
    }

    pub(crate) unsafe fn as_ptr(&self) -> *mut wlr_renderer {
        self.renderer
    }
}

impl Drop for GenericRenderer {
    fn drop(&mut self) {
        unsafe { wlr_renderer_destroy(self.renderer) }
    }
}

impl<'output> Renderer<'output> {
    pub fn clear(&mut self, float: [f32; 4]) {
        unsafe { wlr_renderer_clear(self.renderer, float.as_ptr()) }
    }

    /// Renders the requseted texture.
    pub fn render_texture(&mut self,
                          texture: &Texture,
                          projection: [f32; 9],
                          x: c_int,
                          y: c_int,
                          alpha: c_float)
                          -> bool {
        unsafe {
            wlr_render_texture(self.renderer,
                               texture.as_ptr(),
                               projection.as_ptr(),
                               x,
                               y,
                               alpha)
        }
    }

    /// Renders the requested texture using the provided matrix. A typical texture
    /// rendering goes like so:
    ///
    /// TODO FIXME Show how the typical rendering goes in Rust.
    ///
    /// ```c
    /// struct wlr_renderer *renderer;
    /// struct wlr_texture *texture;
    /// float projection[16];
    /// float matrix[16];
    /// wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
    /// wlr_render_texture_with_matrix(renderer, texture, &matrix);
    /// ```
    ///
    /// This will render the texture at <123, 321>.
    pub fn render_texture_with_matrix(&mut self, texture: &Texture, matrix: [f32; 9]) -> bool {
        // TODO FIXME Add alpha as param
        unsafe {
            wlr_render_texture_with_matrix(self.renderer, texture.as_ptr(), matrix.as_ptr(), 1.0)
        }
    }

    /// Renders a solid quad in the specified color.
    pub fn render_colored_quad(&mut self, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_quad_with_matrix(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }

    /// Renders a solid ellipse in the specified color.
    pub fn render_colored_ellipse(&mut self, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_ellipse_with_matrix(self.renderer, color.as_ptr(), matrix.as_ptr()) }
    }

    /// Renders a solid rectangle in the specified color.
    pub fn render_colored_rect(&mut self, area: Area, color: [f32; 4], matrix: [f32; 9]) {
        unsafe { wlr_render_rect(self.renderer, &area.into(), color.as_ptr(), matrix.as_ptr()) }
    }
}

impl<'output> Drop for Renderer<'output> {
    fn drop(&mut self) {
        unsafe {
            wlr_renderer_end(self.renderer);
            if let Some((mut damage, when)) = self.damage.take() {
                self.output.swap_buffers(Some(when), Some(&mut damage));
            } else {
                self.output.swap_buffers(None, None);
            }
        }
    }
}

unsafe fn create_texture_from_pixels(renderer: *mut wlr_renderer,
                                     format: wl_shm_format,
                                     stride: u32,
                                     width: u32,
                                     height: u32,
                                     // TODO Slice of u8? It's a void*, hmm
                                     data: *const c_void)
                                     -> Option<Texture> {
    let texture = wlr_texture_from_pixels(renderer, format, stride, width, height, data);
    if texture.is_null() {
        None
    } else {
        Some(Texture::from_ptr(texture))
    }
}
<|endoftext|>


<commit_before>use smallvec::{smallvec, SmallVec};
use std::ffi::{CStr, CString, NulError};

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub struct SmallCString(smallvec::SmallVec<[u8; 16]>);

impl SmallCString {
    #[inline]
    pub fn new(s: &str) -> Result<Self, NulError> {
        if s.as_bytes().contains(&0u8) {
            return Err(Self::fabricate_nul_error(s));
        }
        let mut buf = SmallVec::with_capacity(s.len() + 1);
        buf.extend_from_slice(s.as_bytes());
        buf.push(0);
        Ok(Self(buf))
    }

    #[inline]
    pub fn as_str(&self) -> &str {
        debug_assert!(std::str::from_utf8(&self.as_bytes_without_nul()).is_ok());
        // Constructor takes a &str so this is safe.
        unsafe { std::str::from_utf8_unchecked(&self.as_bytes_without_nul()) }
    }

    #[inline]
    pub fn as_bytes_without_nul(&self) -> &[u8] {
        &self.0[..self.0.len() - 1]
    }

    #[inline]
    pub fn len(&self) -> usize {
        debug_assert_ne!(self.0.len(), 0);
        self.0.len() - 1
    }

    #[inline]
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    #[inline]
    pub fn as_cstr(&self) -> &CStr {
        debug_assert!(CStr::from_bytes_with_nul(&self.0).is_ok());
        unsafe { CStr::from_bytes_with_nul_unchecked(&self.0) }
    }

    #[cold]
    fn fabricate_nul_error(b: &str) -> NulError {
        CString::new(b).unwrap_err()
    }
}

impl Default for SmallCString {
    #[inline]
    fn default() -> Self {
        Self(smallvec![0])
    }
}

impl std::fmt::Debug for SmallCString {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("SmallCString").field(&self.as_str()).finish()
    }
}

impl std::ops::Deref for SmallCString {
    type Target = CStr;
    #[inline]
    fn deref(&self) -> &CStr {
        self.as_cstr()
    }
}

impl PartialEq<SmallCString> for str {
    #[inline]
    fn eq(&self, s: &SmallCString) -> bool {
        s.as_bytes_without_nul() == self.as_bytes()
    }
}

impl PartialEq<str> for SmallCString {
    #[inline]
    fn eq(&self, s: &str) -> bool {
        self.as_bytes_without_nul() == s.as_bytes()
    }
}

impl std::borrow::Borrow<str> for SmallCString {
    #[inline]
    fn borrow(&self) -> &str {
        self.as_str()
    }
}

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

    #[test]
    fn test_small_cstring() {
        // We don't go through the normal machinery for default, so make sure
        // things work.
        assert_eq!(SmallCString::default().0, SmallCString::new("").unwrap().0);
        assert_eq!(SmallCString::new("foo").unwrap().len(), 3);
        assert_eq!(SmallCString::new("foo").unwrap().0.as_slice(), b"foo\0");
        assert_eq!(
            SmallCString::new("foo").unwrap().as_bytes_without_nul(),
            b"foo",
        );

        assert_eq!(SmallCString::new("😀").unwrap().len(), 4);
        assert_eq!(
            SmallCString::new("😀").unwrap().0.as_slice(),
            b"\xf0\x9f\x98\x80\0",
        );
        assert_eq!(
            SmallCString::new("😀").unwrap().as_bytes_without_nul(),
            b"\xf0\x9f\x98\x80",
        );

        assert_eq!(SmallCString::new("").unwrap().len(), 0);
        assert!(SmallCString::new("").unwrap().is_empty());

        assert_eq!(SmallCString::new("").unwrap().0.as_slice(), b"\0");
        assert_eq!(SmallCString::new("").unwrap().as_bytes_without_nul(), b"");

        assert!(SmallCString::new("\0").is_err());
        assert!(SmallCString::new("\0abc").is_err());
        assert!(SmallCString::new("abc\0").is_err());
    }
}
<commit_msg>Better docs and cleaner SmallCString<commit_after>use smallvec::{smallvec, SmallVec};
use std::ffi::{CStr, CString, NulError};

/// Similar to std::ffi::CString, but avoids heap allocating if the string is
/// small enough. Also guarantees it's input is UTF-8 -- used for cases where we
/// need to pass a NUL-terminated string to SQLite, and we have a `&str`.
#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct SmallCString(smallvec::SmallVec<[u8; 16]>);

impl SmallCString {
    #[inline]
    pub fn new(s: &str) -> Result<Self, NulError> {
        if s.as_bytes().contains(&0u8) {
            return Err(Self::fabricate_nul_error(s));
        }
        let mut buf = SmallVec::with_capacity(s.len() + 1);
        buf.extend_from_slice(s.as_bytes());
        buf.push(0);
        let res = Self(buf);
        res.debug_checks();
        Ok(res)
    }

    #[inline]
    pub fn as_str(&self) -> &str {
        self.debug_checks();
        // Constructor takes a &str so this is safe.
        unsafe { std::str::from_utf8_unchecked(self.as_bytes_without_nul()) }
    }

    /// Get the bytes not including the NUL terminator. E.g. the bytes which
    /// make up our `str`:
    /// - `SmallCString::new("foo").as_bytes_without_nul() == b"foo"`
    /// - `SmallCString::new("foo").as_bytes_with_nul() == b"foo\0"
    #[inline]
    pub fn as_bytes_without_nul(&self) -> &[u8] {
        self.debug_checks();
        &self.0[..self.len()]
    }

    /// Get the bytes behind this str *including* the NUL terminator. This
    /// should never return an empty slice.
    #[inline]
    pub fn as_bytes_with_nul(&self) -> &[u8] {
        self.debug_checks();
        &self.0
    }

    #[inline]
    #[cfg(debug_assertions)]
    fn debug_checks(&self) {
        debug_assert_ne!(self.0.len(), 0);
        debug_assert_eq!(self.0[self.0.len() - 1], 0);
        let strbytes = &self.0[..(self.0.len() - 1)];
        debug_assert!(!strbytes.contains(&0));
        debug_assert!(std::str::from_utf8(strbytes).is_ok());
    }

    #[inline]
    #[cfg(not(debug_assertions))]
    fn debug_checks(&self) {}

    #[inline]
    pub fn len(&self) -> usize {
        debug_assert_ne!(self.0.len(), 0);
        self.0.len() - 1
    }

    #[inline]
    #[allow(unused)] // clippy wants this function.
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }

    #[inline]
    pub fn as_cstr(&self) -> &CStr {
        let bytes = self.as_bytes_with_nul();
        debug_assert!(CStr::from_bytes_with_nul(bytes).is_ok());
        unsafe { CStr::from_bytes_with_nul_unchecked(bytes) }
    }

    #[cold]
    fn fabricate_nul_error(b: &str) -> NulError {
        CString::new(b).unwrap_err()
    }
}

impl Default for SmallCString {
    #[inline]
    fn default() -> Self {
        Self(smallvec![0])
    }
}

impl std::fmt::Debug for SmallCString {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_tuple("SmallCString").field(&self.as_str()).finish()
    }
}

impl std::ops::Deref for SmallCString {
    type Target = CStr;
    #[inline]
    fn deref(&self) -> &CStr {
        self.as_cstr()
    }
}

impl PartialEq<SmallCString> for str {
    #[inline]
    fn eq(&self, s: &SmallCString) -> bool {
        s.as_bytes_without_nul() == self.as_bytes()
    }
}

impl PartialEq<str> for SmallCString {
    #[inline]
    fn eq(&self, s: &str) -> bool {
        self.as_bytes_without_nul() == s.as_bytes()
    }
}

impl std::borrow::Borrow<str> for SmallCString {
    #[inline]
    fn borrow(&self) -> &str {
        self.as_str()
    }
}

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

    #[test]
    fn test_small_cstring() {
        // We don't go through the normal machinery for default, so make sure
        // things work.
        assert_eq!(SmallCString::default().0, SmallCString::new("").unwrap().0);
        assert_eq!(SmallCString::new("foo").unwrap().len(), 3);
        assert_eq!(
            SmallCString::new("foo").unwrap().as_bytes_with_nul(),
            b"foo\0"
        );
        assert_eq!(
            SmallCString::new("foo").unwrap().as_bytes_without_nul(),
            b"foo",
        );

        assert_eq!(SmallCString::new("😀").unwrap().len(), 4);
        assert_eq!(
            SmallCString::new("😀").unwrap().0.as_slice(),
            b"\xf0\x9f\x98\x80\0",
        );
        assert_eq!(
            SmallCString::new("😀").unwrap().as_bytes_without_nul(),
            b"\xf0\x9f\x98\x80",
        );

        assert_eq!(SmallCString::new("").unwrap().len(), 0);
        assert!(SmallCString::new("").unwrap().is_empty());

        assert_eq!(SmallCString::new("").unwrap().0.as_slice(), b"\0");
        assert_eq!(SmallCString::new("").unwrap().as_bytes_without_nul(), b"");

        assert!(SmallCString::new("\0").is_err());
        assert!(SmallCString::new("\0abc").is_err());
        assert!(SmallCString::new("abc\0").is_err());
    }
}
<|endoftext|>


<commit_before>//! Crate documentation builder
//!
//! This module is extremely similar to cargo install operation, except it's building
//! documentation of a crate and not installing anything.

use std::path::{Path, PathBuf};
use std::env;
use std::sync::Arc;

use cargo::core::{SourceId, Dependency, Registry, Source, Package, Workspace};
use cargo::util::{CargoResult, Config, human, Filesystem};
use cargo::sources::SourceConfigMap;
use cargo::ops::{self, Packages, DefaultExecutor};

use utils::{get_current_versions, parse_rustc_version};
use error::Result;

use Metadata;

/// Builds documentation of a crate and version.
///
/// Crate will be built into current working directory/crate-version.
///
/// It will build latest version, if no version is given.
// idea is to make cargo to download
// and build a crate and its documentation
// instead of doing it manually like in the previous version of cratesfyi
pub fn build_doc(name: &str, vers: Option<&str>, target: Option<&str>) -> Result<Package> {
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    // update crates.io-index registry
    try!(source.update());

    let dep = try!(Dependency::parse_no_deprecated(name, vers, &source_id));
    let deps = try!(source.query(&dep));
    let pkg = try!(deps.iter().map(|p| p.package_id()).max()
                   // FIXME: This is probably not a rusty way to handle options and results
                   //        or maybe it is who knows...
                   .map(|pkgid| source.download(pkgid))
                   .unwrap_or(Err(human("PKG download error"))));

    let current_dir = try!(env::current_dir());
    let target_dir = PathBuf::from(current_dir).join("cratesfyi");

    let metadata = Metadata::from_package(&pkg).map_err(|e| human(e.description()))?;

    // This is only way to pass rustc_args to cargo.
    // CompileOptions::target_rustc_args is used only for the current crate,
    // and since docs.rs never runs rustc on the current crate, we assume rustc_args
    // will be used for the dependencies. That is why we are creating RUSTFLAGS environment
    // variable instead of using target_rustc_args.
    if let Some(rustc_args) = metadata.rustc_args {
        env::set_var("RUSTFLAGS", rustc_args.join(" "));
    }

    // since https://github.com/rust-lang/rust/pull/48511 we can pass --resource-suffix to
    // add correct version numbers to css and javascript files
    let mut rustdoc_args: Vec<String> =
        vec!["-Z".to_string(), "unstable-options".to_string(),
             "--resource-suffix".to_string(),
             format!("-{}", parse_rustc_version(get_current_versions()?.0)?)];
    if let Some(package_rustdoc_args) = metadata.rustdoc_args {
        rustdoc_args.append(&mut package_rustdoc_args.iter().map(|s| s.to_owned()).collect());
    }

    let opts = ops::CompileOptions {
        config: &config,
        jobs: None,
        target: target,
        features: &metadata.features.unwrap_or(Vec::new()),
        all_features: metadata.all_features,
        no_default_features: metadata.no_default_features,
        spec: Packages::Packages(&[]),
        mode: ops::CompileMode::Doc { deps: false },
        release: false,
        message_format: ops::MessageFormat::Human,
        filter: ops::CompileFilter::new(true,
                                        &[], false,
                                        &[], false,
                                        &[], false,
                                        &[], false),
        target_rustc_args: None,
        target_rustdoc_args: Some(rustdoc_args.as_slice()),
    };

    let ws = try!(Workspace::ephemeral(pkg, &config, Some(Filesystem::new(target_dir)), false));
    try!(ops::compile_ws(&ws, Some(source), &opts, Arc::new(DefaultExecutor)));

    Ok(try!(ws.current()).clone())
}

/// Downloads a crate and returns Cargo Package.
pub fn get_package(name: &str, vers: Option<&str>) -> CargoResult<Package> {
    debug!("Getting package with cargo");
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    let dep = try!(Dependency::parse_no_deprecated(name, vers, &source_id));
    let deps = try!(source.query(&dep));
    let pkg = try!(deps.iter().map(|p| p.package_id()).max()
                   // FIXME: This is probably not a rusty way to handle options and results
                   //        or maybe it is who knows...
                   .map(|pkgid| source.download(pkgid))
                   .unwrap_or(Err(human("PKG download error"))));

    Ok(pkg)
}

/// Updates central crates-io.index repository
pub fn update_sources() -> CargoResult<()> {
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    source.update()
}

/// Gets source path of a downloaded package.
pub fn source_path(pkg: &Package) -> Option<&Path> {
    // parent of the manifest file is where source codes are stored
    pkg.manifest_path().parent()
}

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

    #[test]
    fn test_get_package() {
        let pkg = get_package("rand", None);
        assert!(pkg.is_ok());

        let pkg = pkg.unwrap();

        let manifest = pkg.manifest();
        assert_eq!(manifest.name(), "rand");
    }

    #[test]
    fn test_source_path() {
        let pkg = get_package("rand", None).unwrap();
        let source_path = source_path(&pkg).unwrap();
        assert!(source_path.is_dir());

        let cargo_toml_path = Path::new(source_path).join("Cargo.toml");
        assert!(cargo_toml_path.exists());
        assert!(cargo_toml_path.is_file());

        let src_path = Path::new(source_path).join("src");
        assert!(src_path.exists());
        assert!(src_path.is_dir());
    }
}
<commit_msg>Always update sources even in get_package<commit_after>//! Crate documentation builder
//!
//! This module is extremely similar to cargo install operation, except it's building
//! documentation of a crate and not installing anything.

use std::path::{Path, PathBuf};
use std::env;
use std::sync::Arc;

use cargo::core::{SourceId, Dependency, Registry, Source, Package, Workspace};
use cargo::util::{CargoResult, Config, human, Filesystem};
use cargo::sources::SourceConfigMap;
use cargo::ops::{self, Packages, DefaultExecutor};

use utils::{get_current_versions, parse_rustc_version};
use error::Result;

use Metadata;

/// Builds documentation of a crate and version.
///
/// Crate will be built into current working directory/crate-version.
///
/// It will build latest version, if no version is given.
// idea is to make cargo to download
// and build a crate and its documentation
// instead of doing it manually like in the previous version of cratesfyi
pub fn build_doc(name: &str, vers: Option<&str>, target: Option<&str>) -> Result<Package> {
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    // update crates.io-index registry
    try!(source.update());

    let dep = try!(Dependency::parse_no_deprecated(name, vers, &source_id));
    let deps = try!(source.query(&dep));
    let pkg = try!(deps.iter().map(|p| p.package_id()).max()
                   // FIXME: This is probably not a rusty way to handle options and results
                   //        or maybe it is who knows...
                   .map(|pkgid| source.download(pkgid))
                   .unwrap_or(Err(human("PKG download error"))));

    let current_dir = try!(env::current_dir());
    let target_dir = PathBuf::from(current_dir).join("cratesfyi");

    let metadata = Metadata::from_package(&pkg).map_err(|e| human(e.description()))?;

    // This is only way to pass rustc_args to cargo.
    // CompileOptions::target_rustc_args is used only for the current crate,
    // and since docs.rs never runs rustc on the current crate, we assume rustc_args
    // will be used for the dependencies. That is why we are creating RUSTFLAGS environment
    // variable instead of using target_rustc_args.
    if let Some(rustc_args) = metadata.rustc_args {
        env::set_var("RUSTFLAGS", rustc_args.join(" "));
    }

    // since https://github.com/rust-lang/rust/pull/48511 we can pass --resource-suffix to
    // add correct version numbers to css and javascript files
    let mut rustdoc_args: Vec<String> =
        vec!["-Z".to_string(), "unstable-options".to_string(),
             "--resource-suffix".to_string(),
             format!("-{}", parse_rustc_version(get_current_versions()?.0)?)];
    if let Some(package_rustdoc_args) = metadata.rustdoc_args {
        rustdoc_args.append(&mut package_rustdoc_args.iter().map(|s| s.to_owned()).collect());
    }

    let opts = ops::CompileOptions {
        config: &config,
        jobs: None,
        target: target,
        features: &metadata.features.unwrap_or(Vec::new()),
        all_features: metadata.all_features,
        no_default_features: metadata.no_default_features,
        spec: Packages::Packages(&[]),
        mode: ops::CompileMode::Doc { deps: false },
        release: false,
        message_format: ops::MessageFormat::Human,
        filter: ops::CompileFilter::new(true,
                                        &[], false,
                                        &[], false,
                                        &[], false,
                                        &[], false),
        target_rustc_args: None,
        target_rustdoc_args: Some(rustdoc_args.as_slice()),
    };

    let ws = try!(Workspace::ephemeral(pkg, &config, Some(Filesystem::new(target_dir)), false));
    try!(ops::compile_ws(&ws, Some(source), &opts, Arc::new(DefaultExecutor)));

    Ok(try!(ws.current()).clone())
}

/// Downloads a crate and returns Cargo Package.
pub fn get_package(name: &str, vers: Option<&str>) -> CargoResult<Package> {
    debug!("Getting package with cargo");
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    try!(source.update());

    let dep = try!(Dependency::parse_no_deprecated(name, vers, &source_id));
    let deps = try!(source.query(&dep));
    let pkg = try!(deps.iter().map(|p| p.package_id()).max()
                   // FIXME: This is probably not a rusty way to handle options and results
                   //        or maybe it is who knows...
                   .map(|pkgid| source.download(pkgid))
                   .unwrap_or(Err(human("PKG download error"))));

    Ok(pkg)
}

/// Updates central crates-io.index repository
pub fn update_sources() -> CargoResult<()> {
    let config = try!(Config::default());
    let source_id = try!(SourceId::crates_io(&config));

    let source_map = try!(SourceConfigMap::new(&config));
    let mut source = try!(source_map.load(&source_id));

    source.update()
}

/// Gets source path of a downloaded package.
pub fn source_path(pkg: &Package) -> Option<&Path> {
    // parent of the manifest file is where source codes are stored
    pkg.manifest_path().parent()
}

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

    #[test]
    fn test_get_package() {
        let pkg = get_package("rand", None);
        assert!(pkg.is_ok());

        let pkg = pkg.unwrap();

        let manifest = pkg.manifest();
        assert_eq!(manifest.name(), "rand");
    }

    #[test]
    fn test_source_path() {
        let pkg = get_package("rand", None).unwrap();
        let source_path = source_path(&pkg).unwrap();
        assert!(source_path.is_dir());

        let cargo_toml_path = Path::new(source_path).join("Cargo.toml");
        assert!(cargo_toml_path.exists());
        assert!(cargo_toml_path.is_file());

        let src_path = Path::new(source_path).join("src");
        assert!(src_path.exists());
        assert!(src_path.is_dir());
    }
}
<|endoftext|>


<commit_before>extern crate websocket;

use broadcaster;
use control_nexus::{ControlInfo, ControlNexus, ControlUpdateProcessor};
use controls;
use json;
use serde_json::Value;
use std::sync::{Arc, Mutex};
use std::thread;
use websocket::message::Message;
use websocket::sync::{Client, Server};
use websocket::OwnedMessage;

pub fn start<'a>(
  guistring: &str,
  cup: Box<dyn ControlUpdateProcessor>,
  ip: &str,
  websockets_port: &str,
  block: bool,
) -> Result<ControlNexus, Box<dyn std::error::Error>> {
  let guival = serde_json::from_str(guistring)?;

  let root = try!(json::deserialize_root(&guival));

  println!(
    "starting websocket server for control page: {} ",
    root.title
  );

  // from control tree, make a map of ids->controls.
  let mapp = controls::make_control_map(&*root.root_control);
  let cnm = controls::control_map_to_name_map(&mapp);

  let ci = ControlInfo {
    cm: mapp,
    cnm: cnm,
    guijson: String::new() + guistring,
  };

  let cmshare = Arc::new(Mutex::new(ci));
  let bc = broadcaster::Broadcaster::new();

  let cn_ret = ControlNexus {
    ci: cmshare,
    bc: bc,
  };
  let cn_ws = cn_ret.clone();

  let mut websockets_ip = String::from(ip);
  websockets_ip.push_str(":");
  websockets_ip.push_str(&websockets_port);

  if block {
    match websockets_main(websockets_ip, cn_ws, Arc::new(Mutex::new(cup))) {
      Ok(_) => (),
      Err(e) => println!(
        "error in webso
        ckets_main: {:?}", e),
    }
  } else {
    // Spawn a thread for the websockets handler.
    thread::spawn(move || {
      match websockets_main(websockets_ip, cn_ws, Arc::new(Mutex::new(cup))) {
        Ok(_) => (),
        Err(e) => println!("error in websockets_main: {:?}", e),
      }
    });
  }

  Ok(cn_ret)
}

fn sendcontrols(
  ci: &Arc<Mutex<ControlInfo>>,
  client: &mut Client<std::net::TcpStream>,
) -> Result<(), Box<dyn std::error::Error>> {
  let sci = ci.lock().unwrap();

  let updarray = controls::cm_to_update_array(&sci.cm);

  // build json message containing both guijson and the updarray.
  let mut updvals = Vec::new();

  for upd in updarray {
    let um = json::encode_update_message(&upd);
    updvals.push(um);
  }

  let mut guival: Value = serde_json::from_str(&sci.guijson[..])?;

  match guival.as_object_mut() {
    Some(obj) => {
      obj.insert("state".to_string(), Value::Array(updvals));
      ()
    }
    None => (),
  }

  let guistring = serde_json::ser::to_string(&guival)?;
  let message = Message::text(guistring);
  client.send_message(&message)?;
  Ok(())
}

fn websockets_main(
  ipaddr: String,
  acn: ControlNexus,
  cup: Arc<Mutex<Box<dyn ControlUpdateProcessor>>>,
) -> Result<(), Box<dyn std::error::Error>> {
  println!("websockets address {:?}", ipaddr);
  let server = Server::bind(&ipaddr[..])?;
  for request in server.filter_map(Result::ok) {
    let mut scn = acn.clone();
    let cup = cup.clone();
    // Spawn a new thread for each connection.
    thread::spawn(move || {
      if !request.protocols().contains(&"rust-websocket".to_string()) {
        request.reject().unwrap();
        return;
      }

      let mut client: Client<std::net::TcpStream> =
        request.use_protocol("rust-websocket").accept().unwrap();

      let ip = client.peer_addr().unwrap();
      println!("Connection from {}", ip);

      // send up controls.
      match sendcontrols(&scn.ci, &mut client) {
        Err(e) => println!("error sending controls to client: {}", e),
        Ok(_) => (),
      }

      //(websocket::receiver::Reader<std::net::TcpStream>, websocket::sender::Writer<std::net::TcpStream> )
      let (mut receiver, sender) = client.split().unwrap();

      let sendmeh = Arc::new(Mutex::new(sender));
      scn.bc.register(sendmeh.clone());

      for message in receiver.incoming_messages() {
        let message = message.unwrap();

        match message {
          OwnedMessage::Close(_) => {
            let message = OwnedMessage::Close(None);
            let mut s = sendmeh.lock().unwrap();
            s.send_message(&message).unwrap();
            println!("Client {} disconnected", ip);
            return;
          }
          OwnedMessage::Ping(ping) => {
            let message = OwnedMessage::Pong(ping);
            let mut s = sendmeh.lock().unwrap();
            s.send_message(&message).unwrap();
          }
          OwnedMessage::Text(txt) => {
            // let message = OwnedMessage::Pong(ping);
            // sender.send_message(&message).unwrap();
            match serde_json::from_str(txt.as_str()) {
              Err(e) => println!("error {:?}", e),
              Ok(jsonval) => {
                let s_um = json::decode_update_message(&jsonval);
                match s_um {
                  Some(updmsg) => {
                    {
                      let mut sci = scn.ci.lock().unwrap();
                      {
                        let mbcntrl = sci.cm.get_mut(controls::get_um_id(&updmsg));
                        match mbcntrl {
                          Some(cntrl) => {
                            (*cntrl).update(&updmsg);
                            scn.bc.broadcast_others(&ip, Message::text(txt.clone()));
                            ()
                          }
                          None => println!("none"),
                        }
                      }
                    }

let mut scup = cup.lock().unwrap();
/*
                    let mut sci = match scn.ci.lock() {
                      Ok(sci) => sci,
                      Err(poisoned) => poisoned.into_inner(),
                    };
*/
                    // scup.on_update_received(&updmsg, &mut *sci);
                    scup.on_update_received(&updmsg, &mut scn);
                  }
                  _ => println!("decode_update_message failed on websockets msg: {:?}", txt),
                }
              }
            }
          }
          _ => {
            println!("unrecognized message type: {:?}", message);
          }
        }
      }
    });
  }

  Ok(())
}
<commit_msg>more cleanup, formatting<commit_after>extern crate websocket;

use broadcaster;
use control_nexus::{ControlInfo, ControlNexus, ControlUpdateProcessor};
use controls;
use json;
use serde_json::Value;
use std::sync::{Arc, Mutex};
use std::thread;
use websocket::message::Message;
use websocket::sync::{Client, Server};
use websocket::OwnedMessage;

pub fn start<'a>(
  guistring: &str,
  cup: Box<dyn ControlUpdateProcessor>,
  ip: &str,
  websockets_port: &str,
  block: bool,
) -> Result<ControlNexus, Box<dyn std::error::Error>> {
  let guival = serde_json::from_str(guistring)?;

  let root = try!(json::deserialize_root(&guival));

  println!(
    "starting websocket server for control page: {} ",
    root.title
  );

  // from control tree, make a map of ids->controls.
  let mapp = controls::make_control_map(&*root.root_control);
  let cnm = controls::control_map_to_name_map(&mapp);

  let ci = ControlInfo {
    cm: mapp,
    cnm: cnm,
    guijson: String::new() + guistring,
  };

  let cmshare = Arc::new(Mutex::new(ci));
  let bc = broadcaster::Broadcaster::new();

  let cn_ret = ControlNexus {
    ci: cmshare,
    bc: bc,
  };
  let cn_ws = cn_ret.clone();

  let mut websockets_ip = String::from(ip);
  websockets_ip.push_str(":");
  websockets_ip.push_str(&websockets_port);

  if block {
    match websockets_main(websockets_ip, cn_ws, Arc::new(Mutex::new(cup))) {
      Ok(_) => (),
      Err(e) => println!("error in websockets_main: {:?}", e),
    }
  } else {
    // Spawn a thread for the websockets handler.
    thread::spawn(
      move || match websockets_main(websockets_ip, cn_ws, Arc::new(Mutex::new(cup))) {
        Ok(_) => (),
        Err(e) => println!("error in websockets_main: {:?}", e),
      },
    );
  }

  Ok(cn_ret)
}

fn sendcontrols(
  ci: &Arc<Mutex<ControlInfo>>,
  client: &mut Client<std::net::TcpStream>,
) -> Result<(), Box<dyn std::error::Error>> {
  let sci = ci.lock().unwrap();

  let updarray = controls::cm_to_update_array(&sci.cm);

  // build json message containing both guijson and the updarray.
  let mut updvals = Vec::new();

  for upd in updarray {
    let um = json::encode_update_message(&upd);
    updvals.push(um);
  }

  let mut guival: Value = serde_json::from_str(&sci.guijson[..])?;

  match guival.as_object_mut() {
    Some(obj) => {
      obj.insert("state".to_string(), Value::Array(updvals));
      ()
    }
    None => (),
  }

  let guistring = serde_json::ser::to_string(&guival)?;
  let message = Message::text(guistring);
  client.send_message(&message)?;
  Ok(())
}

fn websockets_main(
  ipaddr: String,
  acn: ControlNexus,
  cup: Arc<Mutex<Box<dyn ControlUpdateProcessor>>>,
) -> Result<(), Box<dyn std::error::Error>> {
  println!("websockets address {:?}", ipaddr);
  let server = Server::bind(&ipaddr[..])?;
  for request in server.filter_map(Result::ok) {
    let mut scn = acn.clone();
    let cup = cup.clone();
    // Spawn a new thread for each connection.
    thread::spawn(move || {
      if !request.protocols().contains(&"rust-websocket".to_string()) {
        request.reject().unwrap();
        return;
      }

      let mut client: Client<std::net::TcpStream> =
        request.use_protocol("rust-websocket").accept().unwrap();

      let ip = client.peer_addr().unwrap();
      println!("Connection from {}", ip);

      // send up controls.
      match sendcontrols(&scn.ci, &mut client) {
        Err(e) => println!("error sending controls to client: {}", e),
        Ok(_) => (),
      }

      //(websocket::receiver::Reader<std::net::TcpStream>, websocket::sender::Writer<std::net::TcpStream> )
      let (mut receiver, sender) = client.split().unwrap();

      let sendmeh = Arc::new(Mutex::new(sender));
      scn.bc.register(sendmeh.clone());

      for message in receiver.incoming_messages() {
        let message = message.unwrap();

        match message {
          OwnedMessage::Close(_) => {
            let message = OwnedMessage::Close(None);
            let mut s = sendmeh.lock().unwrap();
            s.send_message(&message).unwrap();
            println!("Client {} disconnected", ip);
            return;
          }
          OwnedMessage::Ping(ping) => {
            let message = OwnedMessage::Pong(ping);
            let mut s = sendmeh.lock().unwrap();
            s.send_message(&message).unwrap();
          }
          OwnedMessage::Text(txt) => match serde_json::from_str(txt.as_str()) {
            Err(e) => println!("error {:?}", e),
            Ok(jsonval) => {
              let s_um = json::decode_update_message(&jsonval);
              match s_um {
                Some(updmsg) => {
                  {
                    let mut sci = scn.ci.lock().unwrap();
                    {
                      let mbcntrl = sci.cm.get_mut(controls::get_um_id(&updmsg));
                      match mbcntrl {
                        Some(cntrl) => {
                          (*cntrl).update(&updmsg);
                          scn.bc.broadcast_others(&ip, Message::text(txt.clone()));
                          ()
                        }
                        None => println!("none"),
                      }
                    }
                  }

                  let mut scup = cup.lock().unwrap();
                  scup.on_update_received(&updmsg, &mut scn);
                }
                _ => println!("decode_update_message failed on websockets msg: {:?}", txt),
              }
            }
          },
          _ => {
            println!("unrecognized message type: {:?}", message);
          }
        }
      }
    });
  }

  Ok(())
}
<|endoftext|>


<commit_before>/* rustdoc: rust -> markdown translator
 * Copyright 2011 Google Inc.
 */

// Some utility interfaces
import doc::item;
import doc::util;

#[doc = "A single operation on the document model"]
type pass = {
    name: str,
    f: fn~(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc
};

fn run_passes(
    srv: astsrv::srv,
    doc: doc::cratedoc,
    passes: [pass]
) -> doc::cratedoc {

    #[doc(
        brief =
        "Run a series of passes over the document",
        args(
            srv =
            "The AST service to provide to the passes",
            doc =
            "The document to transform",
            passes =
            "The list of passes used to transform the document"
        ),
        return =
        "The transformed document that results from folding the \
         original through each pass"
    )];

    let passno = 0;
    vec::foldl(doc, passes) {|doc, pass|
        log(debug, #fmt("pass #%d", passno));
        passno += 1;
        log(debug, doc);
        time(pass.name) {||
            pass.f(srv, doc)
        }
    }
}

#[test]
fn test_run_passes() {
    fn pass1(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        {
            topmod: {
                item: {
                    name: doc.topmod.name() + "two"
                    with doc.topmod.item
                },
                items: []
            }
        }
    }
    fn pass2(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        {
            topmod: {
                item: {
                    name: doc.topmod.name() + "three"
                    with doc.topmod.item
                },
                items: []
            }
        }
    }
    let source = "";
    astsrv::from_str(source) {|srv|
        let passes = [
            {
                name: "",
                f: pass1
            },
            {
                name: "",
                f: pass2
            }
        ];
        let doc = extract::from_srv(srv, "one");
        let doc = run_passes(srv, doc, passes);
        assert doc.topmod.name() == "onetwothree";
    }
}

fn main(argv: [str]) {

    if vec::contains(argv, "-h") {
        config::usage();
        ret;
    }

    if vec::len(argv) != 2u {
        std::io::println(#fmt("usage: %s <input>", argv[0]));
        ret;
    }

    let source_file = argv[1];
    run(source_file);
}

fn time<T>(what: str, f: fn() -> T) -> T {
    let start = std::time::precise_time_s();
    let rv = f();
    let end = std::time::precise_time_s();
    #info("time: %3.3f s    %s", end - start, what);
    ret rv;
}

#[doc = "Runs rustdoc over the given file"]
fn run(source_file: str) {

    let default_name = source_file;
    astsrv::from_file(source_file) {|srv|
        time("wait_ast") {||
            astsrv::exec(srv) {|_ctxt| () }
        };
        let doc = time("extract") {||
            extract::from_srv(srv, default_name)
        };
        run_passes(srv, doc, [
            reexport_pass::mk_pass(),
            prune_unexported_pass::mk_pass(),
            tystr_pass::mk_pass(),
            path_pass::mk_pass(),
            attr_pass::mk_pass(),
            prune_undoc_details_pass::mk_pass(),
            // FIXME: This pass should be optional
            // prune_undoc_items_pass::mk_pass(),
            desc_to_brief_pass::mk_pass(),
            trim_pass::mk_pass(),
            unindent_pass::mk_pass(),
            sort_item_name_pass::mk_pass(),
            sort_item_type_pass::mk_pass(),
            markdown_pass::mk_pass {|f| f(std::io:: stdout()) }
        ]);
    }
}<commit_msg>rustdoc: Parse command line opts<commit_after>/* rustdoc: rust -> markdown translator
 * Copyright 2011 Google Inc.
 */

// Some utility interfaces
import doc::item;
import doc::util;

#[doc = "A single operation on the document model"]
type pass = {
    name: str,
    f: fn~(srv: astsrv::srv, doc: doc::cratedoc) -> doc::cratedoc
};

fn run_passes(
    srv: astsrv::srv,
    doc: doc::cratedoc,
    passes: [pass]
) -> doc::cratedoc {

    #[doc(
        brief =
        "Run a series of passes over the document",
        args(
            srv =
            "The AST service to provide to the passes",
            doc =
            "The document to transform",
            passes =
            "The list of passes used to transform the document"
        ),
        return =
        "The transformed document that results from folding the \
         original through each pass"
    )];

    let passno = 0;
    vec::foldl(doc, passes) {|doc, pass|
        log(debug, #fmt("pass #%d", passno));
        passno += 1;
        log(debug, doc);
        time(pass.name) {||
            pass.f(srv, doc)
        }
    }
}

#[test]
fn test_run_passes() {
    fn pass1(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        {
            topmod: {
                item: {
                    name: doc.topmod.name() + "two"
                    with doc.topmod.item
                },
                items: []
            }
        }
    }
    fn pass2(
        _srv: astsrv::srv,
        doc: doc::cratedoc
    ) -> doc::cratedoc {
        {
            topmod: {
                item: {
                    name: doc.topmod.name() + "three"
                    with doc.topmod.item
                },
                items: []
            }
        }
    }
    let source = "";
    astsrv::from_str(source) {|srv|
        let passes = [
            {
                name: "",
                f: pass1
            },
            {
                name: "",
                f: pass2
            }
        ];
        let doc = extract::from_srv(srv, "one");
        let doc = run_passes(srv, doc, passes);
        assert doc.topmod.name() == "onetwothree";
    }
}

fn main(args: [str]) {

    if vec::contains(args, "-h") {
        config::usage();
        ret;
    }

    let config = alt config::parse_config(args) {
      result::ok(config) { config }
      result::err(err) {
        std::io::println(#fmt("error: %s", err));
        ret;
      }
    };

    run(config.input_crate);
}

fn time<T>(what: str, f: fn() -> T) -> T {
    let start = std::time::precise_time_s();
    let rv = f();
    let end = std::time::precise_time_s();
    #info("time: %3.3f s    %s", end - start, what);
    ret rv;
}

#[doc = "Runs rustdoc over the given file"]
fn run(source_file: str) {

    let default_name = source_file;
    astsrv::from_file(source_file) {|srv|
        time("wait_ast") {||
            astsrv::exec(srv) {|_ctxt| () }
        };
        let doc = time("extract") {||
            extract::from_srv(srv, default_name)
        };
        run_passes(srv, doc, [
            reexport_pass::mk_pass(),
            prune_unexported_pass::mk_pass(),
            tystr_pass::mk_pass(),
            path_pass::mk_pass(),
            attr_pass::mk_pass(),
            prune_undoc_details_pass::mk_pass(),
            // FIXME: This pass should be optional
            // prune_undoc_items_pass::mk_pass(),
            desc_to_brief_pass::mk_pass(),
            trim_pass::mk_pass(),
            unindent_pass::mk_pass(),
            sort_item_name_pass::mk_pass(),
            sort_item_type_pass::mk_pass(),
            markdown_pass::mk_pass {|f| f(std::io:: stdout()) }
        ]);
    }
}<|endoftext|>