<commit_before>//!  Decoding of DDS images
//!
//!  DDS (DirectDraw Surface) is a container format for storing DXT (S3TC) compressed images.
//!
//!  # Related Links
//!  * <https://docs.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide> - Description of the DDS format.

use std::io::Read;

use byteorder::{LittleEndian, ReadBytesExt};

use crate::color::ColorType;
use crate::dxt::{DxtDecoder, DXTReader, DXTVariant};
use crate::error::{
    DecodingError, ImageError, ImageResult, UnsupportedError, UnsupportedErrorKind,
};
use crate::image::{ImageDecoder, ImageFormat};

/// Header used by DDS image files
#[derive(Debug)]
struct Header {
    flags: u32,
    height: u32,
    width: u32,
    pitch_or_linear_size: u32,
    depth: u32,
    mipmap_count: u32,
    pixel_format: PixelFormat,
    caps: u32,
    caps2: u32,
}

/// DDS pixel format
#[derive(Debug)]
struct PixelFormat {
    flags: u32,
    fourcc: [u8; 4],
    rgb_bit_count: u32,
    r_bit_mask: u32,
    g_bit_mask: u32,
    b_bit_mask: u32,
    a_bit_mask: u32,
}

impl PixelFormat {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let size = r.read_u32::<LittleEndian>()?;
        if size != 32 {
            return Err(ImageError::Decoding(DecodingError::with_message(
                ImageFormat::Dds.into(),
                "Invalid DDS PixelFormat size",
            )));
        }

        Ok(Self {
            flags: r.read_u32::<LittleEndian>()?,
            fourcc: {
                let mut v = [0; 4];
                r.read_exact(&mut v)?;
                v
            },
            rgb_bit_count: r.read_u32::<LittleEndian>()?,
            r_bit_mask: r.read_u32::<LittleEndian>()?,
            g_bit_mask: r.read_u32::<LittleEndian>()?,
            b_bit_mask: r.read_u32::<LittleEndian>()?,
            a_bit_mask: r.read_u32::<LittleEndian>()?,
        })
    }
}

impl Header {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let size = r.read_u32::<LittleEndian>()?;
        if size != 124 {
            return Err(ImageError::Decoding(DecodingError::with_message(
                ImageFormat::Dds.into(),
                "Invalid DDS header size",
            )));
        }

        const REQUIRED_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x1000;
        const VALID_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x8 | 0x1000 | 0x20000 | 0x80000 | 0x800000;
        let flags = r.read_u32::<LittleEndian>()?;
        if flags & (REQUIRED_FLAGS | !VALID_FLAGS) != REQUIRED_FLAGS {
            return Err(ImageError::Decoding(DecodingError::with_message(
                ImageFormat::Dds.into(),
                "Invalid DDS header flags",
            )));
        }

        let height = r.read_u32::<LittleEndian>()?;
        let width = r.read_u32::<LittleEndian>()?;
        let pitch_or_linear_size = r.read_u32::<LittleEndian>()?;
        let depth = r.read_u32::<LittleEndian>()?;
        let mipmap_count = r.read_u32::<LittleEndian>()?;
        // Skip `dwReserved1`
        {
            let mut skipped = [0; 4 * 11];
            r.read_exact(&mut skipped)?;
        }
        let pixel_format = PixelFormat::from_reader(r)?;
        let caps = r.read_u32::<LittleEndian>()?;
        let caps2 = r.read_u32::<LittleEndian>()?;
        // Skip `dwCaps3`, `dwCaps4`, `dwReserved2` (unused)
        {
            let mut skipped = [0; 4 + 4 + 4];
            r.read_exact(&mut skipped)?;
        }

        Ok(Self {
            flags,
            height,
            width,
            pitch_or_linear_size,
            depth,
            mipmap_count,
            pixel_format,
            caps,
            caps2,
        })
    }
}

/// The representation of a DDS decoder
pub struct DdsDecoder<R: Read> {
    inner: DxtDecoder<R>,
}

impl<R: Read> DdsDecoder<R> {
    /// Create a new decoder that decodes from the stream `r`
    pub fn new(mut r: R) -> ImageResult<Self> {
        let mut magic = [0; 4];
        r.read_exact(&mut magic)?;
        if magic != b"DDS "[..] {
            return Err(ImageError::Decoding(DecodingError::with_message(
                ImageFormat::Dds.into(),
                "DDS signature not found".to_string(),
            )));
        }

        let header = Header::from_reader(&mut r)?;

        if header.pixel_format.flags & 0x4 != 0 {
            let variant = match &header.pixel_format.fourcc {
                b"DXT1" => DXTVariant::DXT1,
                b"DXT3" => DXTVariant::DXT3,
                b"DXT5" => DXTVariant::DXT5,
                fourcc => {
                    return Err(ImageError::Unsupported(
                        UnsupportedError::from_format_and_kind(
                            ImageFormat::Dds.into(),
                            UnsupportedErrorKind::GenericFeature(format!(
                                "Unsupported DDS FourCC {:?}",
                                fourcc
                            )),
                        ),
                    ))
                }
            };
            let inner = DxtDecoder::new(r, header.width, header.height, variant)?;
            Ok(Self { inner })
        } else {
            // For now, supports only DXT variants
            Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Dds.into(),
                    UnsupportedErrorKind::GenericFeature("DDS format not supported".to_string()),
                ),
            ))
        }
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for DdsDecoder<R> {
    type Reader = DXTReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        self.inner.dimensions()
    }

    fn color_type(&self) -> ColorType {
        self.inner.color_type()
    }

    fn scanline_bytes(&self) -> u64 {
        self.inner.scanline_bytes()
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        self.inner.into_reader()
    }

    fn read_image(self, buf: &mut [u8]) -> ImageResult<()> {
        self.inner.read_image(buf)
    }
}

<commit_msg>Destringrypify DDS decoder<commit_after>//!  Decoding of DDS images
//!
//!  DDS (DirectDraw Surface) is a container format for storing DXT (S3TC) compressed images.
//!
//!  # Related Links
//!  * <https://docs.microsoft.com/en-us/windows/win32/direct3ddds/dx-graphics-dds-pguide> - Description of the DDS format.

use std::{error, fmt};
use std::io::Read;

use byteorder::{LittleEndian, ReadBytesExt};

use crate::color::ColorType;
use crate::dxt::{DxtDecoder, DXTReader, DXTVariant};
use crate::error::{
    DecodingError, ImageError, ImageFormatHint, ImageResult, UnsupportedError, UnsupportedErrorKind,
};
use crate::image::{ImageDecoder, ImageFormat};

/// Errors that can occur during decoding and parsing a DDS image
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, PartialOrd, Ord)]
enum DecoderError {
    /// Wrong DDS channel width
    PixelFormatSizeInvalid(u32),
    /// Wrong DDS header size
    HeaderSizeInvalid(u32),
    /// Wrong DDS header flags
    HeaderFlagsInvalid(u32),

    /// DDS "DDS " signature invalid or missing
    DdsSignatureInvalid,
}

impl fmt::Display for DecoderError {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            DecoderError::PixelFormatSizeInvalid(s) =>
                f.write_fmt(format_args!("Invalid DDS PixelFormat size: {}", s)),
            DecoderError::HeaderSizeInvalid(s) =>
                f.write_fmt(format_args!("Invalid DDS header size: {}", s)),
            DecoderError::HeaderFlagsInvalid(fs) =>
                f.write_fmt(format_args!("Invalid DDS header flags: {:#010x}", fs)),
            DecoderError::DdsSignatureInvalid =>
                f.write_str("DDS signature not found"),
        }
    }
}

impl error::Error for DecoderError {}

/// Header used by DDS image files
#[derive(Debug)]
struct Header {
    flags: u32,
    height: u32,
    width: u32,
    pitch_or_linear_size: u32,
    depth: u32,
    mipmap_count: u32,
    pixel_format: PixelFormat,
    caps: u32,
    caps2: u32,
}

/// DDS pixel format
#[derive(Debug)]
struct PixelFormat {
    flags: u32,
    fourcc: [u8; 4],
    rgb_bit_count: u32,
    r_bit_mask: u32,
    g_bit_mask: u32,
    b_bit_mask: u32,
    a_bit_mask: u32,
}

impl PixelFormat {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let size = r.read_u32::<LittleEndian>()?;
        if size != 32 {
            return Err(ImageError::Decoding(DecodingError::new(
                ImageFormat::Dds.into(),
                DecoderError::PixelFormatSizeInvalid(size),
            )));
        }

        Ok(Self {
            flags: r.read_u32::<LittleEndian>()?,
            fourcc: {
                let mut v = [0; 4];
                r.read_exact(&mut v)?;
                v
            },
            rgb_bit_count: r.read_u32::<LittleEndian>()?,
            r_bit_mask: r.read_u32::<LittleEndian>()?,
            g_bit_mask: r.read_u32::<LittleEndian>()?,
            b_bit_mask: r.read_u32::<LittleEndian>()?,
            a_bit_mask: r.read_u32::<LittleEndian>()?,
        })
    }
}

impl Header {
    fn from_reader(r: &mut dyn Read) -> ImageResult<Self> {
        let size = r.read_u32::<LittleEndian>()?;
        if size != 124 {
            return Err(ImageError::Decoding(DecodingError::new(
                ImageFormat::Dds.into(),
                DecoderError::HeaderSizeInvalid(size),
            )));
        }

        const REQUIRED_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x1000;
        const VALID_FLAGS: u32 = 0x1 | 0x2 | 0x4 | 0x8 | 0x1000 | 0x20000 | 0x80000 | 0x800000;
        let flags = r.read_u32::<LittleEndian>()?;
        if flags & (REQUIRED_FLAGS | !VALID_FLAGS) != REQUIRED_FLAGS {
            return Err(ImageError::Decoding(DecodingError::new(
                ImageFormat::Dds.into(),
                DecoderError::HeaderFlagsInvalid(flags)
            )));
        }

        let height = r.read_u32::<LittleEndian>()?;
        let width = r.read_u32::<LittleEndian>()?;
        let pitch_or_linear_size = r.read_u32::<LittleEndian>()?;
        let depth = r.read_u32::<LittleEndian>()?;
        let mipmap_count = r.read_u32::<LittleEndian>()?;
        // Skip `dwReserved1`
        {
            let mut skipped = [0; 4 * 11];
            r.read_exact(&mut skipped)?;
        }
        let pixel_format = PixelFormat::from_reader(r)?;
        let caps = r.read_u32::<LittleEndian>()?;
        let caps2 = r.read_u32::<LittleEndian>()?;
        // Skip `dwCaps3`, `dwCaps4`, `dwReserved2` (unused)
        {
            let mut skipped = [0; 4 + 4 + 4];
            r.read_exact(&mut skipped)?;
        }

        Ok(Self {
            flags,
            height,
            width,
            pitch_or_linear_size,
            depth,
            mipmap_count,
            pixel_format,
            caps,
            caps2,
        })
    }
}

/// The representation of a DDS decoder
pub struct DdsDecoder<R: Read> {
    inner: DxtDecoder<R>,
}

impl<R: Read> DdsDecoder<R> {
    /// Create a new decoder that decodes from the stream `r`
    pub fn new(mut r: R) -> ImageResult<Self> {
        let mut magic = [0; 4];
        r.read_exact(&mut magic)?;
        if magic != b"DDS "[..] {
            return Err(ImageError::Decoding(DecodingError::new(
                ImageFormat::Dds.into(),
                DecoderError::DdsSignatureInvalid,
            )));
        }

        let header = Header::from_reader(&mut r)?;

        if header.pixel_format.flags & 0x4 != 0 {
            let variant = match &header.pixel_format.fourcc {
                b"DXT1" => DXTVariant::DXT1,
                b"DXT3" => DXTVariant::DXT3,
                b"DXT5" => DXTVariant::DXT5,
                fourcc => {
                    return Err(ImageError::Unsupported(
                        UnsupportedError::from_format_and_kind(
                            ImageFormat::Dds.into(),
                            UnsupportedErrorKind::GenericFeature(format!("DDS FourCC {:?}", fourcc)),
                        ),
                    ))
                }
            };
            let inner = DxtDecoder::new(r, header.width, header.height, variant)?;
            Ok(Self { inner })
        } else {
            // For now, supports only DXT variants
            Err(ImageError::Unsupported(
                UnsupportedError::from_format_and_kind(
                    ImageFormat::Dds.into(),
                    UnsupportedErrorKind::Format(ImageFormatHint::Name("DDS".to_string())),
                ),
            ))
        }
    }
}

impl<'a, R: 'a + Read> ImageDecoder<'a> for DdsDecoder<R> {
    type Reader = DXTReader<R>;

    fn dimensions(&self) -> (u32, u32) {
        self.inner.dimensions()
    }

    fn color_type(&self) -> ColorType {
        self.inner.color_type()
    }

    fn scanline_bytes(&self) -> u64 {
        self.inner.scanline_bytes()
    }

    fn into_reader(self) -> ImageResult<Self::Reader> {
        self.inner.into_reader()
    }

    fn read_image(self, buf: &mut [u8]) -> ImageResult<()> {
        self.inner.read_image(buf)
    }
}

<|endoftext|>


<commit_before>use atom::*;
use number::*;
use env::Env;
use errors::*;
use symbol::*;
use parser::*;
use funcs::*;
use self::Instruction::*;

#[derive (Debug)]
struct Function2 {
    program: Vec<Instruction>,
    env: Env,
    arity: u8
}

#[derive (Debug)]
struct Frame {
    program: Function2,
    env: Env
}

#[derive (Debug)]
pub struct VirtualMachine {
    stack: Vec<Atom>,
    program: Vec<Instruction>,
    frames: Vec<Frame>,
    env: Env,
    pc: usize,
    fp: usize,
    sp: usize,
}

#[derive (Debug, Clone, PartialEq)]
pub enum Instruction {
    CONST(Atom),
    LOAD(InternedStr),
    STORE,
    DEFINE,
    FUNCTION,
    JUMP,
    CALL(Function, usize),
}

fn compile_node(node: Atom, out: &mut Vec<Instruction>) -> Result<Atom, Error> {
    match node {
        Atom::Symbol(sym) => {
            out.push(Instruction::LOAD(sym))
        },
        Atom::List(ref list) => {
            for n in list.iter() {
                try!(compile(n.clone(), out));
            }
        },
        // handle constants
        _ => {
            out.push(Instruction::CONST(node.clone()));
        }
    }
    Ok(Atom::Nil)
}

pub fn compile(node: Atom, out: &mut Vec<Instruction>) -> Result<Atom, Error> {
    match node {
        Atom::List(ref list) => {
            if list.is_empty() {
                out.push(Instruction::CONST(node.clone()));
                return Ok(Atom::Nil)
            }
            ()
        },
        _ => return compile_node(node, out)
    }

    let list = try!(node.as_list());

    match list[0] {
        Atom::Form(f) => {
            match f {
                Form::Set => {
                },
                Form::Def => {
                },
                Form::Do => {
                    for i in list.iter().skip(1) {
                        try!(compile(i.clone(), out));
                    }
                    return Ok(Atom::Nil)
                }
                _ => {
                    return Err(Error::NotImplemented)
                }
            }
        },
        Atom::Function(ref func) => {
            for n in list.iter().skip(1) {
                try!(compile(n.clone(), out));
            }
            match *func {
                Function::Native(_) => {
                    out.push(Instruction::CALL(func.clone(), list.len() -1));
                    return Ok(Atom::Nil)
                },
                _ => {
                    return Err(Error::NotImplemented)
                }
            }
        },
        _ => {
            return Err(Error::NotAFunction)
        }
    }

    Err(Error::InvalidArguments)
}

impl VirtualMachine {
    pub fn new() -> VirtualMachine {
        VirtualMachine {
            stack: vec![],
            program: vec![],
            frames: vec![],
            env: Env::new(None),
            pc: 0,
            sp: 0,
            fp: 0
        }
    }

    fn current_instruction(&self) -> Instruction {
        // self.frames[self.fp].program.program[self.pc].clone()
        self.program[self.pc].clone()
    }

    pub fn run(&mut self) -> AtomResult {
        loop {
            use self::Instruction::*;
            match self.current_instruction() {
                CONST(ref atom) => {
                    self.push(atom.clone())
                },
                CALL(func, arity) => {
                    match func {
                        Function::Native(n) => {
                            let len = self.stack.len();
                            let r = try!(eval_native(n, &self.stack[len-arity..], &mut self.env));
                            for _ in 1..arity {
                                self.pop();
                            }
                            self.push(r);
                        },
                        _ => {
                            return Err(Error::NotImplemented)
                        }
                    }
                },
                _ => ()
            }
            self.pc += 1;
        }
        Ok(self.pop())
    }

    fn push(&mut self, a: Atom)  {
        self.stack.push(a);
        self.sp += 1
    }

    fn pop(&mut self) -> Atom {
        self.sp -= 1;
        self.stack.pop().unwrap()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use parser::*;
    use atom::*;
    #[test]
    fn test() {
        let p = tokenize("(+ (+ 2 2) 2)").unwrap();

        let mut out = vec![];

        compile(p, &mut out).unwrap();

        let mut vm = VirtualMachine::new();

        vm.program = out;

        let result = vm.run().unwrap();

        assert_eq!(Atom::from(6), result);
    }
}
<commit_msg>start of thsi thing<commit_after>use atom::*;
use env::Env;
use errors::*;
use symbol::*;
use funcs::*;
use self::Instruction::*;

#[derive (Debug)]
struct Function2 {
    program: Vec<Instruction>,
    env: Env,
    arity: u8
}

#[derive (Debug)]
struct Frame {
    program: Function2,
    env: Env
}

#[derive (Debug)]
pub struct VirtualMachine {
    stack: Vec<Atom>,
    program: Vec<Instruction>,
    frames: Vec<Frame>,
    env: Env,
    pc: usize,
    fp: usize,
    sp: usize,
}

#[derive (Debug, Clone, PartialEq)]
pub enum Instruction {
    CONST(Atom),
    LOAD(InternedStr),
    STORE,
    DEFINE,
    FUNCTION,
    JUMP,
    CALL(Function, usize),
}

fn compile_node(node: Atom, out: &mut Vec<Instruction>) -> Result<Atom, Error> {
    match node {
        Atom::Symbol(sym) => {
            out.push(Instruction::LOAD(sym))
        },
        Atom::List(ref list) => {
            for n in list.iter() {
                try!(compile(n.clone(), out));
            }
        },
        // handle constants
        _ => {
            out.push(Instruction::CONST(node.clone()));
        }
    }
    Ok(Atom::Nil)
}

pub fn compile(node: Atom, out: &mut Vec<Instruction>) -> Result<Atom, Error> {
    match node {
        Atom::List(ref list) => {
            if list.is_empty() {
                out.push(Instruction::CONST(node.clone()));
                return Ok(Atom::Nil)
            }
            ()
        },
        _ => return compile_node(node, out)
    }

    let list = try!(node.as_list());

    match list[0] {
        Atom::Form(f) => {
            match f {
                Form::Set => {
                },
                Form::Def => {
                },
                Form::Do => {
                    for i in list.iter().skip(1) {
                        try!(compile(i.clone(), out));
                    }
                    return Ok(Atom::Nil)
                }
                _ => {
                    return Err(Error::NotImplemented)
                }
            }
        },
        Atom::Function(ref func) => {
            for n in list.iter().skip(1) {
                try!(compile(n.clone(), out));
            }
            match *func {
                Function::Native(_) => {
                    out.push(Instruction::CALL(func.clone(), list.len() -1));
                    return Ok(Atom::Nil)
                },
                _ => {
                    return Err(Error::NotImplemented)
                }
            }
        },
        _ => {
            return Err(Error::NotAFunction)
        }
    }

    Err(Error::InvalidArguments)
}

impl VirtualMachine {
    pub fn new() -> VirtualMachine {
        VirtualMachine {
            stack: vec![],
            program: vec![],
            frames: vec![],
            env: Env::new(None),
            pc: 0,
            sp: 0,
            fp: 0
        }
    }

    fn current_instruction(&self) -> Instruction {
        // self.frames[self.fp].program.program[self.pc].clone()
        self.program[self.pc].clone()
    }

    pub fn run(&mut self) -> AtomResult {
        loop {
            if self.pc >= self.program.len() {
                break;
            }
            match self.current_instruction() {
                CONST(ref atom) => {
                    self.push(atom.clone())
                },
                CALL(func, arity) => {
                    match func {
                        Function::Native(n) => {
                            let len = self.stack.len();
                            let r = try!(eval_native(n, &self.stack[len-arity..], &mut self.env));
                            for _ in 1..arity {
                                self.pop();
                            }
                            self.push(r);
                        },
                        _ => {
                            return Err(Error::NotImplemented)
                        }
                    }
                },
                _ => ()
            }
            self.pc += 1;
        }
        Ok(self.pop())
    }

    fn push(&mut self, a: Atom)  {
        self.stack.push(a);
        self.sp += 1
    }

    fn pop(&mut self) -> Atom {
        self.sp -= 1;
        self.stack.pop().unwrap()
    }
}

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

    fn run_expr(s: &str) -> Atom {
        let p = tokenize(s).unwrap();
        let mut out = Vec::new();
        compile(p, &mut out).unwrap();

        let mut vm = VirtualMachine::new();
        vm.program = out;

        vm.run().unwrap()
    }

    #[test]
    fn test() {
        assert_eq!(Atom::from(6), run_expr("(+ (+ 2 2) 2)"));
    }
}
<|endoftext|>


<commit_before>//! Simple graphviz dot file format output.

use std::fmt::{self, Display, Write};
use {
    Graph,
    EdgeType,
    GraphMap,
};
use super::graph::IndexType;
use graphmap::NodeTrait;
use std::collections::HashMap;

/// `Dot` implements output to graphviz .dot format for a graph.
///
/// Formatting and options are rather simple, this is mostly intended
/// for debugging. Exact output may change.
pub struct Dot<'a, G: 'a> {
    graph: &'a G,
    config: &'a [Config],
}

static TYPE: [&'static str; 2] = ["graph", "digraph"];
static EDGE: [&'static str; 2] = ["--", "->"];
static INDENT: &'static str = "    ";

impl<'a, G> Dot<'a, G> {
    /// Create a `Dot` formatting wrapper with default configuration.
    pub fn new(graph: &'a G) -> Self {
        Self::with_config(graph, &[])
    }

    /// Create a `Dot` formatting wrapper with custom configuration.
    pub fn with_config(graph: &'a G, config: &'a [Config]) -> Self {
        Dot {
            graph: graph,
            config: config,
        }
    }
}

/// `Dot` configuration.
///
/// This enum does not have an exhaustive definition (will be expanded)
#[derive(Debug, PartialEq, Eq)]
pub enum Config {
    /// Use indices for node labels.
    NodeIndexLabel,
    /// Use indices for edge labels.
    EdgeIndexLabel,
    /// Use no edge labels.
    EdgeNoLabel,
    #[doc(hidden)]
    Other
}

impl<'a, N, E, Ty, Ix> Dot<'a, Graph<N, E, Ty, Ix>>
    where Ty: EdgeType,
          Ix: IndexType,
{
    fn graph_fmt<F, G>(&self, f: &mut fmt::Formatter,
                       mut node_fmt: F, mut edge_fmt: G) -> fmt::Result
        where F: FnMut(&N, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
              G: FnMut(&E, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
{
        let g = self.graph;
        try!(writeln!(f, "{} {{", TYPE[g.is_directed() as usize]));

        // output all labels
        for index in g.node_indices() {
            try!(write!(f, "{}{}", INDENT, index.index()));
            if self.config.contains(&Config::NodeIndexLabel) {
                try!(writeln!(f, ""));
            } else {
                try!(write!(f, " [label=\""));
                try!(node_fmt(&g[index], &mut |d| write!(f, "{}", Escaped(d))));
                try!(writeln!(f, "\"]"));
            }

        }
        // output all edges
        for (i, edge) in g.raw_edges().iter().enumerate() {
            try!(write!(f, "{}{} {} {}",
                        INDENT,
                        edge.source().index(),
                        EDGE[g.is_directed() as usize],
                        edge.target().index()));
            if self.config.contains(&Config::EdgeNoLabel) {
                try!(writeln!(f, ""));
            } else if self.config.contains(&Config::EdgeIndexLabel) {
                try!(writeln!(f, " [label=\"{}\"]", i));
            } else {
                try!(write!(f, " [label=\""));
                try!(edge_fmt(&edge.weight, &mut |d| write!(f, "{}", Escaped(d))));
                try!(writeln!(f, "\"]"));
            }
        }

        try!(writeln!(f, "}}"));
        Ok(())
    }
}

impl<'a, N, E, Ty, Ix> fmt::Display for Dot<'a, Graph<N, E, Ty, Ix>>
    where N: fmt::Display,
          E: fmt::Display,
          Ty: EdgeType,
          Ix: IndexType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graph_fmt(f, |n, cb| cb(n), |e, cb| cb(e))
    }
}

impl<'a, N, E, Ty, Ix> fmt::Debug for Dot<'a, Graph<N, E, Ty, Ix>>
    where N: fmt::Debug,
          E: fmt::Debug,
          Ty: EdgeType,
          Ix: IndexType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graph_fmt(f,
                       |n, cb| cb(&format_args!("{:?}", n)),
                       |e, cb| cb(&format_args!("{:?}", e)))
    }
}

impl<'a, N, E> Dot<'a, GraphMap<N, E>>
    where N: NodeTrait,
{
    fn graphmap_fmt<F, G>(&self, f: &mut fmt::Formatter,
                          mut node_fmt: F, mut edge_fmt: G) -> fmt::Result
        where F: FnMut(&N, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
              G: FnMut(&E, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
    {
        let g = self.graph;
        try!(writeln!(f, "{} {{", TYPE[0]));

        let mut labels = HashMap::new();

        // output all labels
        for (i, node) in g.nodes().enumerate() {
            labels.insert(node, i);
            try!(write!(f, "{}{}", INDENT, i));
            if self.config.contains(&Config::NodeIndexLabel) {
                try!(writeln!(f, ""));
            } else {
                try!(write!(f, " [label=\""));
                try!(node_fmt(&node, &mut |d| write!(f, "{}", Escaped(d))));
                try!(writeln!(f, "\"]"));
            }
        }
        // output all edges
        for (i, ((a, b), edge_weight)) in g.all_edges().enumerate() {
            try!(write!(f, "{}{} {} {}",
                        INDENT,
                        labels[&a],
                        EDGE[0],
                        labels[&b]));
            if self.config.contains(&Config::EdgeNoLabel) {
                try!(writeln!(f, ""));
            } else if self.config.contains(&Config::EdgeIndexLabel) {
                try!(writeln!(f, " [label=\"{}\"]", i));
            } else {
                try!(write!(f, " [label=\""));
                try!(edge_fmt(&edge_weight, &mut |d| write!(f, "{}", Escaped(d))));
                try!(writeln!(f, "\"]"));
            }
        }

        try!(writeln!(f, "}}"));
        Ok(())
    }
}
impl<'a, N, E> fmt::Display for Dot<'a, GraphMap<N, E>>
    where N: fmt::Display + NodeTrait,
          E: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graphmap_fmt(f, |n, cb| cb(n), |e, cb| cb(e))
    }
}

impl<'a, N, E> fmt::Debug for Dot<'a, GraphMap<N, E>>
    where N: fmt::Debug + NodeTrait,
          E: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graphmap_fmt(f,
                          |n, cb| cb(&format_args!("{:?}", n)),
                          |e, cb| cb(&format_args!("{:?}", e)))
    }
}

/// For Graphviz, we only need to escape double quotes in labels
struct Escaper<W>(W);

impl<W> fmt::Write for Escaper<W>
    where W: fmt::Write
{
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for c in s.chars() {
            try!(self.write_char(c));
        }
        Ok(())
    }

    fn write_char(&mut self, c: char) -> fmt::Result {
        match c {
            '"' => try!(self.0.write_char('\\')),
            _   => { }
        }
        self.0.write_char(c)
    }
}

/// Pass Display and Debug through simple escaping filter
struct Escaped<T>(T);

impl<T> fmt::Display for Escaped<T>
    where T: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(&mut Escaper(f), "{}", &self.0)
    }
}

impl<T> fmt::Debug for Escaped<T>
    where T: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(&mut Escaper(f), "{:?}", &self.0)
    }
}
<commit_msg>Renname dot::Config's dummy variant<commit_after>//! Simple graphviz dot file format output.

use std::fmt::{self, Display, Write};
use {
    Graph,
    EdgeType,
    GraphMap,
};
use super::graph::IndexType;
use graphmap::NodeTrait;
use std::collections::HashMap;

/// `Dot` implements output to graphviz .dot format for a graph.
///
/// Formatting and options are rather simple, this is mostly intended
/// for debugging. Exact output may change.
pub struct Dot<'a, G: 'a> {
    graph: &'a G,
    config: &'a [Config],
}

static TYPE: [&'static str; 2] = ["graph", "digraph"];
static EDGE: [&'static str; 2] = ["--", "->"];
static INDENT: &'static str = "    ";

impl<'a, G> Dot<'a, G> {
    /// Create a `Dot` formatting wrapper with default configuration.
    pub fn new(graph: &'a G) -> Self {
        Self::with_config(graph, &[])
    }

    /// Create a `Dot` formatting wrapper with custom configuration.
    pub fn with_config(graph: &'a G, config: &'a [Config]) -> Self {
        Dot {
            graph: graph,
            config: config,
        }
    }
}

/// `Dot` configuration.
///
/// This enum does not have an exhaustive definition (will be expanded)
#[derive(Debug, PartialEq, Eq)]
pub enum Config {
    /// Use indices for node labels.
    NodeIndexLabel,
    /// Use indices for edge labels.
    EdgeIndexLabel,
    /// Use no edge labels.
    EdgeNoLabel,
    #[doc(hidden)]
    _Incomplete(()),
}

impl<'a, N, E, Ty, Ix> Dot<'a, Graph<N, E, Ty, Ix>>
    where Ty: EdgeType,
          Ix: IndexType,
{
    fn graph_fmt<F, G>(&self, f: &mut fmt::Formatter,
                       mut node_fmt: F, mut edge_fmt: G) -> fmt::Result
        where F: FnMut(&N, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
              G: FnMut(&E, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
{
        let g = self.graph;
        try!(writeln!(f, "{} {{", TYPE[g.is_directed() as usize]));

        // output all labels
        for index in g.node_indices() {
            try!(write!(f, "{}{}", INDENT, index.index()));
            if self.config.contains(&Config::NodeIndexLabel) {
                try!(writeln!(f, ""));
            } else {
                try!(write!(f, " [label=\""));
                try!(node_fmt(&g[index], &mut |d| write!(f, "{}", Escaped(d))));
                try!(writeln!(f, "\"]"));
            }

        }
        // output all edges
        for (i, edge) in g.raw_edges().iter().enumerate() {
            try!(write!(f, "{}{} {} {}",
                        INDENT,
                        edge.source().index(),
                        EDGE[g.is_directed() as usize],
                        edge.target().index()));
            if self.config.contains(&Config::EdgeNoLabel) {
                try!(writeln!(f, ""));
            } else if self.config.contains(&Config::EdgeIndexLabel) {
                try!(writeln!(f, " [label=\"{}\"]", i));
            } else {
                try!(write!(f, " [label=\""));
                try!(edge_fmt(&edge.weight, &mut |d| write!(f, "{}", Escaped(d))));
                try!(writeln!(f, "\"]"));
            }
        }

        try!(writeln!(f, "}}"));
        Ok(())
    }
}

impl<'a, N, E, Ty, Ix> fmt::Display for Dot<'a, Graph<N, E, Ty, Ix>>
    where N: fmt::Display,
          E: fmt::Display,
          Ty: EdgeType,
          Ix: IndexType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graph_fmt(f, |n, cb| cb(n), |e, cb| cb(e))
    }
}

impl<'a, N, E, Ty, Ix> fmt::Debug for Dot<'a, Graph<N, E, Ty, Ix>>
    where N: fmt::Debug,
          E: fmt::Debug,
          Ty: EdgeType,
          Ix: IndexType,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graph_fmt(f,
                       |n, cb| cb(&format_args!("{:?}", n)),
                       |e, cb| cb(&format_args!("{:?}", e)))
    }
}

impl<'a, N, E> Dot<'a, GraphMap<N, E>>
    where N: NodeTrait,
{
    fn graphmap_fmt<F, G>(&self, f: &mut fmt::Formatter,
                          mut node_fmt: F, mut edge_fmt: G) -> fmt::Result
        where F: FnMut(&N, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
              G: FnMut(&E, &mut FnMut(&Display) -> fmt::Result) -> fmt::Result,
    {
        let g = self.graph;
        try!(writeln!(f, "{} {{", TYPE[0]));

        let mut labels = HashMap::new();

        // output all labels
        for (i, node) in g.nodes().enumerate() {
            labels.insert(node, i);
            try!(write!(f, "{}{}", INDENT, i));
            if self.config.contains(&Config::NodeIndexLabel) {
                try!(writeln!(f, ""));
            } else {
                try!(write!(f, " [label=\""));
                try!(node_fmt(&node, &mut |d| write!(f, "{}", Escaped(d))));
                try!(writeln!(f, "\"]"));
            }
        }
        // output all edges
        for (i, ((a, b), edge_weight)) in g.all_edges().enumerate() {
            try!(write!(f, "{}{} {} {}",
                        INDENT,
                        labels[&a],
                        EDGE[0],
                        labels[&b]));
            if self.config.contains(&Config::EdgeNoLabel) {
                try!(writeln!(f, ""));
            } else if self.config.contains(&Config::EdgeIndexLabel) {
                try!(writeln!(f, " [label=\"{}\"]", i));
            } else {
                try!(write!(f, " [label=\""));
                try!(edge_fmt(&edge_weight, &mut |d| write!(f, "{}", Escaped(d))));
                try!(writeln!(f, "\"]"));
            }
        }

        try!(writeln!(f, "}}"));
        Ok(())
    }
}
impl<'a, N, E> fmt::Display for Dot<'a, GraphMap<N, E>>
    where N: fmt::Display + NodeTrait,
          E: fmt::Display,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graphmap_fmt(f, |n, cb| cb(n), |e, cb| cb(e))
    }
}

impl<'a, N, E> fmt::Debug for Dot<'a, GraphMap<N, E>>
    where N: fmt::Debug + NodeTrait,
          E: fmt::Debug,
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        self.graphmap_fmt(f,
                          |n, cb| cb(&format_args!("{:?}", n)),
                          |e, cb| cb(&format_args!("{:?}", e)))
    }
}

/// For Graphviz, we only need to escape double quotes in labels
struct Escaper<W>(W);

impl<W> fmt::Write for Escaper<W>
    where W: fmt::Write
{
    fn write_str(&mut self, s: &str) -> fmt::Result {
        for c in s.chars() {
            try!(self.write_char(c));
        }
        Ok(())
    }

    fn write_char(&mut self, c: char) -> fmt::Result {
        match c {
            '"' => try!(self.0.write_char('\\')),
            _   => { }
        }
        self.0.write_char(c)
    }
}

/// Pass Display and Debug through simple escaping filter
struct Escaped<T>(T);

impl<T> fmt::Display for Escaped<T>
    where T: fmt::Display
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(&mut Escaper(f), "{}", &self.0)
    }
}

impl<T> fmt::Debug for Escaped<T>
    where T: fmt::Debug
{
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(&mut Escaper(f), "{:?}", &self.0)
    }
}
<|endoftext|>


<commit_before>use bindings::*;
use context::Context;
use function::Function;
use libc::c_uint;
use util::NativeRef;
use std::fmt::Show;
use std::kinds::marker::ContravariantLifetime;
use std::mem::transmute;
use std::iter::Iterator;
use std::c_str::ToCStr;
use std::string::raw::from_buf;
/// An ELF dependency iterator
pub struct Needed<'a> {
    _reader: jit_readelf_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Needed<'a> {
    #[inline(always)]
    fn new(read:&ReadElf<'a>) -> Needed<'a> {
        unsafe {
            Needed {
                _reader: read.as_ptr(),
                index: 0 as c_uint,
                length: jit_readelf_num_needed(read.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<String> for Needed<'a> {
    fn next(&mut self) -> Option<String> {
        let index = self.index;
        self.index += 1;
        unsafe {
            if index < self.length {
                let c_name = jit_readelf_get_needed(self._reader, index);
                let name = from_buf(transmute(c_name));
                Some(name)
            } else {
                None
            }
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<String> {
        self.index += n as c_uint;
        self.next()
    }
}
/// An ELF binary reader
native_ref!(ReadElf, _reader, jit_readelf_t, ContravariantLifetime)
impl<'a> ReadElf<'a> {
    /// Open a new ELF binary
    pub fn new<S:ToCStr+Show>(filename:S) -> ReadElf<'a> {
        unsafe {
            let mut this = RawPtr::null();
            let code = filename.with_c_str(|c_name|
                jit_readelf_open(&mut this, c_name, 0)
            );
            if this.is_null() {
                fail!("'{}' couldn't be opened due to {}", filename, code);
            } else {
                NativeRef::from_ptr(this)
            }
        }
    }
    #[inline]
    /// Get the name of this ELF binary
    pub fn get_name(&self) -> String {
        unsafe {
            from_buf(transmute(jit_readelf_get_name(self.as_ptr())))
        }
    }
    #[inline]
    pub fn add_to_context(&self, ctx:&Context<'a>) {
        unsafe {
            jit_readelf_add_to_context(self.as_ptr(), ctx.as_ptr())
        }
    }
    #[inline]
    /// Get a symbol in the ELF binary
    pub unsafe fn get_symbol<T, S:ToCStr>(&self, symbol:S) -> &'a mut T {
        symbol.with_c_str(|c_symbol|
            transmute(jit_readelf_get_symbol(self.as_ptr(), c_symbol))
        )
    }
    #[inline]
    /// Iterate over the needed libraries
    pub fn needed<'a>(&'a self) -> Needed<'a> {
        Needed::new(self)
    }
}
#[unsafe_destructor]
impl<'a> Drop for ReadElf<'a> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            jit_readelf_close(self.as_ptr())
        }
    }
}

/// An ELF binary reader
native_ref!(WriteElf, _writer, jit_writeelf_t, ContravariantLifetime)
impl<'a> WriteElf<'a> {
    #[inline]
    /// Create a new ELF binary reader
    pub fn new<S:ToCStr>(lib_name:S) -> WriteElf<'a> {
        lib_name.with_c_str(|c_lib_name| unsafe {
            NativeRef::from_ptr(jit_writeelf_create(c_lib_name))
        })
    }
    #[inline]
    /// Write to the filename given (not implemented by LibJIT yet)
    pub fn write<S:ToCStr>(&self, filename:S) -> bool {
        filename.with_c_str(|c_filename| unsafe {
            jit_writeelf_write(self.as_ptr(), c_filename) != 0
        })
    }
    #[inline]
    /// Add a function to the ELF
    pub fn add_function<S:ToCStr>(&self, func:&Function<'a>, name:S) -> bool {
        name.with_c_str(|c_name| unsafe {
            jit_writeelf_add_function(self.as_ptr(), func.as_ptr(), c_name) != 0
        })
    }
    #[inline]
    /// Add a dependency to the ELF
    pub fn add_needed<S:ToCStr>(&self, lib_name:S) -> bool {
        lib_name.with_c_str(|c_lib_name| unsafe {
            jit_writeelf_add_needed(self.as_ptr(), c_lib_name) != 0
        })
    }
}
#[unsafe_destructor]
impl<'a> Drop for WriteElf<'a> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            jit_writeelf_destroy(self.as_ptr())
        }
    }
}<commit_msg>Replace `fail!` with `panic!`<commit_after>use bindings::*;
use context::Context;
use function::Function;
use libc::c_uint;
use util::NativeRef;
use std::fmt::Show;
use std::kinds::marker::ContravariantLifetime;
use std::mem::transmute;
use std::iter::Iterator;
use std::c_str::ToCStr;
use std::string::raw::from_buf;
/// An ELF dependency iterator
pub struct Needed<'a> {
    _reader: jit_readelf_t,
    index: c_uint,
    length: c_uint,
    marker: ContravariantLifetime<'a>
}
impl<'a> Needed<'a> {
    #[inline(always)]
    fn new(read:&ReadElf<'a>) -> Needed<'a> {
        unsafe {
            Needed {
                _reader: read.as_ptr(),
                index: 0 as c_uint,
                length: jit_readelf_num_needed(read.as_ptr()),
                marker: ContravariantLifetime::<'a>
            }
        }
    }
}
impl<'a> Iterator<String> for Needed<'a> {
    fn next(&mut self) -> Option<String> {
        let index = self.index;
        self.index += 1;
        unsafe {
            if index < self.length {
                let c_name = jit_readelf_get_needed(self._reader, index);
                let name = from_buf(transmute(c_name));
                Some(name)
            } else {
                None
            }
        }
    }
    #[inline]
    fn size_hint(&self) -> (uint, Option<uint>) {
        ((self.length - self.index) as uint, None)
    }
    #[inline]
    fn count(&mut self) -> uint {
        let count = self.length - self.index;
        self.index = self.length;
        count as uint
    }
    #[inline]
    fn nth(&mut self, n:uint) -> Option<String> {
        self.index += n as c_uint;
        self.next()
    }
}
/// An ELF binary reader
native_ref!(ReadElf, _reader, jit_readelf_t, ContravariantLifetime)
impl<'a> ReadElf<'a> {
    /// Open a new ELF binary
    pub fn new<S:ToCStr+Show>(filename:S) -> ReadElf<'a> {
        unsafe {
            let mut this = RawPtr::null();
            let code = filename.with_c_str(|c_name|
                jit_readelf_open(&mut this, c_name, 0)
            );
            if this.is_null() {
                panic!("'{}' couldn't be opened due to {}", filename, code);
            } else {
                NativeRef::from_ptr(this)
            }
        }
    }
    #[inline]
    /// Get the name of this ELF binary
    pub fn get_name(&self) -> String {
        unsafe {
            from_buf(transmute(jit_readelf_get_name(self.as_ptr())))
        }
    }
    #[inline]
    pub fn add_to_context(&self, ctx:&Context<'a>) {
        unsafe {
            jit_readelf_add_to_context(self.as_ptr(), ctx.as_ptr())
        }
    }
    #[inline]
    /// Get a symbol in the ELF binary
    pub unsafe fn get_symbol<T, S:ToCStr>(&self, symbol:S) -> &'a mut T {
        symbol.with_c_str(|c_symbol|
            transmute(jit_readelf_get_symbol(self.as_ptr(), c_symbol))
        )
    }
    #[inline]
    /// Iterate over the needed libraries
    pub fn needed<'a>(&'a self) -> Needed<'a> {
        Needed::new(self)
    }
}
#[unsafe_destructor]
impl<'a> Drop for ReadElf<'a> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            jit_readelf_close(self.as_ptr())
        }
    }
}

/// An ELF binary reader
native_ref!(WriteElf, _writer, jit_writeelf_t, ContravariantLifetime)
impl<'a> WriteElf<'a> {
    #[inline]
    /// Create a new ELF binary reader
    pub fn new<S:ToCStr>(lib_name:S) -> WriteElf<'a> {
        lib_name.with_c_str(|c_lib_name| unsafe {
            NativeRef::from_ptr(jit_writeelf_create(c_lib_name))
        })
    }
    #[inline]
    /// Write to the filename given (not implemented by LibJIT yet)
    pub fn write<S:ToCStr>(&self, filename:S) -> bool {
        filename.with_c_str(|c_filename| unsafe {
            jit_writeelf_write(self.as_ptr(), c_filename) != 0
        })
    }
    #[inline]
    /// Add a function to the ELF
    pub fn add_function<S:ToCStr>(&self, func:&Function<'a>, name:S) -> bool {
        name.with_c_str(|c_name| unsafe {
            jit_writeelf_add_function(self.as_ptr(), func.as_ptr(), c_name) != 0
        })
    }
    #[inline]
    /// Add a dependency to the ELF
    pub fn add_needed<S:ToCStr>(&self, lib_name:S) -> bool {
        lib_name.with_c_str(|c_lib_name| unsafe {
            jit_writeelf_add_needed(self.as_ptr(), c_lib_name) != 0
        })
    }
}
#[unsafe_destructor]
impl<'a> Drop for WriteElf<'a> {
    #[inline]
    fn drop(&mut self) {
        unsafe {
            jit_writeelf_destroy(self.as_ptr())
        }
    }
}<|endoftext|>


<commit_before>/*
Tristen Horton
tristen@tristenhorton.com
2017-04-03 23:50
*/

use channel;
use regex::Regex;

pub fn detect_connected(message: &String) -> bool {

	match message.split(":").nth(2) {
		Some("You are in a maze of twisty passages, all alike.") => true,
		_ => false
	}
}

pub fn detect_new_subscriber(
	irc: &String,
	channels: &Vec<channel::Channel>
) -> Option<String> {

	for chan in channels {
		match read_type(irc, chan.name()) {
			Some(rtype) => {

				if irc.split("!").nth(0).unwrap() == ":twitchnotify" &&
					rtype == "PRIVMSG" &&
					(irc.contains("just subscribed!") ||
						irc.to_lowercase().contains("just subscriber with twitch prime!")
					)
				{
					return Some(chan.name().clone());
				}
			}
			_ => {}
		}
	}

	None
}

pub fn read_type(irc: &String, channel: &String) -> Option<String> {

	if irc.contains(" ") {

		let mut found = false;
		for word in irc.split(" ") {
			if word.chars().nth(0).unwrap() == '#' {
				if word == format!("#{}", channel) {
					found = true;
				}
			}
		}
		if found {
			// TODO: Clean this up because this is messy as heck
			let reg = Regex::new(format!(" #{}", channel).as_ref()).unwrap();
			let mut split_a = reg.split(irc);
			let mut split_a_0 = split_a.nth(0).unwrap().to_owned();
			let mut type_wrap = split_a_0.split(" ");
			let mut type_copy = type_wrap.clone();
			let wrap_count = type_wrap.count();
			let ret = type_copy.nth(wrap_count - 1).unwrap().to_owned();
			return Some(ret);
		}
		else {
			if irc.split(" ").count() > 1 && irc.split(" ").nth(1).unwrap() == String::from("NOTICE") {
				return Some(String::from("NOTICE"));
			}
		}
	}

	None
}
<commit_msg>added more irc message detection functions<commit_after>/*
Tristen Horton
tristen@tristenhorton.com
2017-04-03 23:50
*/

use message::ChatMessage;
use channel;
use regex::Regex;

pub fn detect_connected(message: &String) -> bool {

	match message.split(":").nth(2) {
		Some("You are in a maze of twisty passages, all alike.") => true,
		_ => false
	}
}

pub fn detect_new_subscriber(
	irc: &String,
	channels: &Vec<channel::Channel>
) -> Option<String> {

	for chan in channels {
		match read_type(irc, chan.name()) {
			Some(rtype) => {

				if rtype == "PRIVMSG" &&
					irc.split("!").nth(0).unwrap_or("") == ":twitchnotify" &&
					(
						irc.contains("just subscribed!") ||
						irc.to_lowercase().contains("just subscriber with twitch prime!")
					)
				{
					return Some(chan.name().clone());
				}
			}
			_ => {}
		}
	}

	None
}

pub fn detect_message_received(
	irc: &String,
	channels: &Vec<channel::Channel>
) -> Option<String> {

	for chan in channels {
		match read_type(irc, chan.name()) {
			Some(rtype) => {

				if rtype == "PRIVMSG" &&
					irc.split("!").nth(0).unwrap_or("") != ":twitchnotify"
				{
					return Some(chan.name().clone());
				}
			}
			_ => {}
		}
	}

	None
}

pub fn detect_command_received(
	bot_username: &String,
	irc: &String,
	channels: &Vec<channel::Channel>,
	emotes: &Vec<String>,
	replace_emotes: &bool,
	cmd_identifiers: &Vec<String>
) -> Option<String> {

	for chan in channels {
		match read_type(irc, chan.name()) {
			Some(rtype) => {
				if rtype == "PRIVMSG" {
					let chat_msg = ChatMessage::from(
						bot_username.clone(),
						irc.clone(),
						emotes,
						replace_emotes.clone()
					);
					if cmd_identifiers.iter()
						.map(|x| chat_msg.text().starts_with(x))
						.any(|x| x)
					{
						return Some(chan.name().clone());
					}
				}
			}
			_ => {}
		}
	}

	None
}

pub fn detect_user_joined(
	irc: &String,
	channels: &Vec<channel::Channel>
) -> Option<String> {

	for chan in channels {
		match read_type(irc, chan.name()) {
			Some(rtype) => {
				if rtype == "PART" {
					return Some(chan.name().clone());
				}
			}
			_ => {}
		}
	}

	None
}

pub fn detect_moderator_joined(
	irc: &String,
	channels: &Vec<channel::Channel>
) -> Option<String> {

	for chan in channels {
		match read_type(irc, chan.name()) {
			Some(rtype) => {
				if rtype == "MODE" &&
					irc.contains(" ") &&
					irc.split(" ").nth(3).unwrap_or("") == "+o"
				{
					return Some(chan.name().clone());
				}
			}
			_ => {}
		}
	}

	None
}

pub fn detect_incorrect_login(irc: &String) -> bool {
	irc.contains(":") &&
		irc.split(":").nth(2).unwrap_or("") == "Login authentication failed"
}

pub fn detect_malformed_oauth(
	irc: &String,
	channels: &Vec<channel::Channel>
) -> Option<String> {

	for chan in channels {
		match read_type(irc, chan.name()) {
			Some(rtype) => {
				if rtype == "NOTICE" &&
					irc.contains("Improperly formatted auth")
				{
					return Some(chan.name().clone());
				}
			}
			_ => {}
		}
	}
	None
}

pub fn detect_host_left(
	irc: &String,
	channels: &Vec<channel::Channel>
) -> Option<String> {

	for chan in channels {
		match read_type(irc, chan.name()) {
			Some(rtype) => {
				if rtype == "NOTICE" &&
					irc.contains("has gone offline")
				{
					return Some(chan.name().clone());
				}
			}
			_ => {}
		}
	}
	None
}

pub fn read_type(irc: &String, channel: &String) -> Option<String> {

	if irc.contains(" ") {

		let mut found = false;
		for word in irc.split(" ") {
			if word.chars().nth(0).unwrap() == '#' {
				if word == format!("#{}", channel) {
					found = true;
				}
			}
		}
		if found {
			// TODO: Clean this up because this is messy as heck
			let reg = Regex::new(format!(" #{}", channel).as_ref()).unwrap();
			let mut split_a = reg.split(irc);
			let mut split_a_0 = split_a.nth(0).unwrap().to_owned();
			let mut type_wrap = split_a_0.split(" ");
			let mut type_copy = type_wrap.clone();
			let wrap_count = type_wrap.count();
			let ret = type_copy.nth(wrap_count - 1).unwrap().to_owned();
			return Some(ret);
		}
		else {
			if irc.split(" ").count() > 1 && irc.split(" ").nth(1).unwrap() == String::from("NOTICE") {
				return Some(String::from("NOTICE"));
			}
		}
	}

	None
}
<|endoftext|>


<commit_before>//! A crate with utilities to determine the number of CPUs available on the
//! current system.
//!
//! Sometimes the CPU will exaggerate the number of CPUs it contains, because it can use
//! [processor tricks] to deliver increased performance when there are more threads. This
//! crate provides methods to get both the logical and physical numbers of cores.
//!
//! This information can be used as a guide to how many tasks can be run in parallel.
//! There are many properties of the system architecture that will affect parallelism,
//! for example memory access speeds (for all the caches and RAM) and the physical
//! architecture of the processor, so the number of CPUs should be used as a rough guide
//! only.
//!
//!
//! ## Examples
//!
//! Fetch the number of logical CPUs.
//!
//! ```
//! let cpus = num_cpus::get();
//! ```
//!
//! See [`rayon::Threadpool`] for an example of where the number of CPUs could be
//! used when setting up parallel jobs (Where the threadpool example uses a fixed
//! number 8, it could use the number of CPUs).
//!
//! [processor tricks]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
//! [`rayon::ThreadPool`]: https://docs.rs/rayon/0.8.2/rayon/struct.ThreadPool.html
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/num_cpus/1.7.0")]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of available CPUs of the current system.
///
/// This function will get the number of logical cores. Sometimes this is different from the number
/// of physical cores (See [Simultaneous multithreading on Wikipedia][smt]).
///
/// # Examples
///
/// ```
/// let cpus = num_cpus::get();
/// if cpus > 1 {
///     println!("We are on a multicore system with {} CPUs", cpus);
/// } else {
///     println!("We are on a single core system");
/// }
/// ```
///
/// # Note
///
/// This will check [sched affinity] on Linux, showing a lower number of CPUs if the current
/// thread does not have access to all the computer's CPUs.
///
/// [smt]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
/// [sched affinity]: http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current system.
///
/// # Note
///
/// Physical count is supported only on Linux, mac OS and Windows platforms.
/// On other platforms, or if the physical count fails on supported platforms,
/// this function returns the same as [`get()`], which is the number of logical
/// CPUS.
///
/// # Examples
///
/// ```
/// let logical_cpus = num_cpus::get();
/// let physical_cpus = num_cpus::get_physical();
/// if logical_cpus > physical_cpus {
///     println!("We have simultaneous multithreading with about {:.2} \
///               logical cores to 1 physical core.",
///               (logical_cpus as f64) / (physical_cpus as f64));
/// } else if logical_cpus == physical_cpus {
///     println!("Either we don't have simultaneous multithreading, or our \
///               system doesn't support getting the number of physical CPUs.");
/// } else {
///     println!("We have less logical CPUs than physical CPUs, maybe we only have access to \
///               some of the CPUs on our system.");
/// }
/// ```
///
/// [`get()`]: fn.get.html
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(any(target_os = "linux", target_os = "windows", target_os="macos")))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fall back
    get_num_cpus()
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus() -> usize {
    match get_num_physical_cpus_windows() {
        Some(num) => num,
        None => get_num_cpus()
    }
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus_windows() -> Option<usize> {
    // Inspired by https://msdn.microsoft.com/en-us/library/ms683194

    use std::ptr;
    use std::mem;

    #[allow(non_upper_case_globals)]
    const RelationProcessorCore: u32 = 0;

    #[repr(C)]
    #[allow(non_camel_case_types)]
    struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
        mask: usize,
        relationship: u32,
        _unused: [u64; 2]
    }

    extern "system" {
        fn GetLogicalProcessorInformation(
            info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
            length: &mut u32
        ) -> u32;
    }

    // First we need to determine how much space to reserve.

    // The required size of the buffer, in bytes.
    let mut needed_size = 0;

    unsafe {
        GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
    }

    let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;

    // Could be 0, or some other bogus size.
    if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
        return None;
    }

    let count = needed_size / struct_size;

    // Allocate some memory where we will store the processor info.
    let mut buf = Vec::with_capacity(count as usize);

    let result;

    unsafe {
        result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
    }

    // Failed for any reason.
    if result == 0 {
        return None;
    }

    let count = needed_size / struct_size;

    unsafe {
        buf.set_len(count as usize);
    }

    let phys_proc_count = buf.iter()
        // Only interested in processor packages (physical processors.)
        .filter(|proc_info| proc_info.relationship == RelationProcessorCore)
        .count();

    if phys_proc_count == 0 {
        None
    } else {
        Some(phys_proc_count)
    }
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashSet;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut set = HashSet::new();
    let mut coreid: u32 = 0;
    let mut physid: u32 = 0;
    let mut chgcount = 0;
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" || parts[0] == "physical id" {
            let value = match parts[1].trim().parse() {
              Ok(val) => val,
              Err(_) => break,
            };
            match parts[0] {
                "core id"     => coreid = value,
                "physical id" => physid = value,
                _ => {},
            }
            chgcount += 1;
        }
        if chgcount == 2 {
            set.insert((physid, coreid));
            chgcount = 0;
        }
    }
    let count = set.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "macos")]
fn get_num_physical_cpus() -> usize {
    use std::ffi::CStr;
    use std::ptr;

    let mut cpus: i32 = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    let sysctl_name = CStr::from_bytes_with_nul(b"hw.physicalcpu\0")
        .expect("byte literal is missing NUL");

    unsafe {
        if 0 != libc::sysctlbyname(sysctl_name.as_ptr(),
                                   &mut cpus as *mut _ as *mut _,
                                   &mut cpus_size as *mut _ as *mut _,
                                   ptr::null_mut(),
                                   0) {
            return get_num_cpus();
        }
    }
    cpus as usize
}

#[cfg(target_os = "linux")]
fn get_num_cpus() -> usize {
    let mut set:  libc::cpu_set_t = unsafe { std::mem::zeroed() };
    if unsafe { libc::sched_getaffinity(0, std::mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
        let mut count: u32 = 0;
        for i in 0..libc::CPU_SETSIZE as usize {
            if unsafe { libc::CPU_ISSET(i, &set) } {
                count += 1
            }
        }
        count as usize
    } else {
        let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
        if cpus < 1 {
            1
        } else {
            cpus as usize
        }
    }
}

#[cfg(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "fuchsia")
)]
fn get_num_cpus() -> usize {
    // On ARM targets, processors could be turned off to save power.
    // Use `_SC_NPROCESSORS_CONF` to get the real number.
    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_CONF;
    #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_ONLN;

    let cpus = unsafe { libc::sysconf(CONF_NAME) };
    if cpus < 1 {
        1
    } else {
        cpus as usize
    }
}

#[cfg(any(target_os = "emscripten", target_os = "redox", target_os = "haiku"))]
fn get_num_cpus() -> usize {
    1
}

#[cfg(test)]
mod tests {
    fn env_var(name: &'static str) -> Option<usize> {
        ::std::env::var(name).ok().map(|val| val.parse().unwrap())
    }

    #[test]
    fn test_get() {
        let num = super::get();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }

    #[test]
    fn test_get_physical() {
        let num = super::get_physical();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }
}
<commit_msg>added dummy wasm-unknown-unknown backend<commit_after>//! A crate with utilities to determine the number of CPUs available on the
//! current system.
//!
//! Sometimes the CPU will exaggerate the number of CPUs it contains, because it can use
//! [processor tricks] to deliver increased performance when there are more threads. This
//! crate provides methods to get both the logical and physical numbers of cores.
//!
//! This information can be used as a guide to how many tasks can be run in parallel.
//! There are many properties of the system architecture that will affect parallelism,
//! for example memory access speeds (for all the caches and RAM) and the physical
//! architecture of the processor, so the number of CPUs should be used as a rough guide
//! only.
//!
//!
//! ## Examples
//!
//! Fetch the number of logical CPUs.
//!
//! ```
//! let cpus = num_cpus::get();
//! ```
//!
//! See [`rayon::Threadpool`] for an example of where the number of CPUs could be
//! used when setting up parallel jobs (Where the threadpool example uses a fixed
//! number 8, it could use the number of CPUs).
//!
//! [processor tricks]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
//! [`rayon::ThreadPool`]: https://docs.rs/rayon/0.8.2/rayon/struct.ThreadPool.html
#![cfg_attr(test, deny(warnings))]
#![deny(missing_docs)]
#![doc(html_root_url = "https://docs.rs/num_cpus/1.7.0")]
#![allow(non_snake_case)]

#[cfg(not(windows))]
extern crate libc;

/// Returns the number of available CPUs of the current system.
///
/// This function will get the number of logical cores. Sometimes this is different from the number
/// of physical cores (See [Simultaneous multithreading on Wikipedia][smt]).
///
/// # Examples
///
/// ```
/// let cpus = num_cpus::get();
/// if cpus > 1 {
///     println!("We are on a multicore system with {} CPUs", cpus);
/// } else {
///     println!("We are on a single core system");
/// }
/// ```
///
/// # Note
///
/// This will check [sched affinity] on Linux, showing a lower number of CPUs if the current
/// thread does not have access to all the computer's CPUs.
///
/// [smt]: https://en.wikipedia.org/wiki/Simultaneous_multithreading
/// [sched affinity]: http://www.gnu.org/software/libc/manual/html_node/CPU-Affinity.html
#[inline]
pub fn get() -> usize {
    get_num_cpus()
}

/// Returns the number of physical cores of the current system.
///
/// # Note
///
/// Physical count is supported only on Linux, mac OS and Windows platforms.
/// On other platforms, or if the physical count fails on supported platforms,
/// this function returns the same as [`get()`], which is the number of logical
/// CPUS.
///
/// # Examples
///
/// ```
/// let logical_cpus = num_cpus::get();
/// let physical_cpus = num_cpus::get_physical();
/// if logical_cpus > physical_cpus {
///     println!("We have simultaneous multithreading with about {:.2} \
///               logical cores to 1 physical core.",
///               (logical_cpus as f64) / (physical_cpus as f64));
/// } else if logical_cpus == physical_cpus {
///     println!("Either we don't have simultaneous multithreading, or our \
///               system doesn't support getting the number of physical CPUs.");
/// } else {
///     println!("We have less logical CPUs than physical CPUs, maybe we only have access to \
///               some of the CPUs on our system.");
/// }
/// ```
///
/// [`get()`]: fn.get.html
#[inline]
pub fn get_physical() -> usize {
    get_num_physical_cpus()
}

#[cfg(not(any(target_os = "linux", target_os = "windows", target_os="macos")))]
#[inline]
fn get_num_physical_cpus() -> usize {
    // Not implemented, fall back
    get_num_cpus()
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus() -> usize {
    match get_num_physical_cpus_windows() {
        Some(num) => num,
        None => get_num_cpus()
    }
}

#[cfg(target_os = "windows")]
fn get_num_physical_cpus_windows() -> Option<usize> {
    // Inspired by https://msdn.microsoft.com/en-us/library/ms683194

    use std::ptr;
    use std::mem;

    #[allow(non_upper_case_globals)]
    const RelationProcessorCore: u32 = 0;

    #[repr(C)]
    #[allow(non_camel_case_types)]
    struct SYSTEM_LOGICAL_PROCESSOR_INFORMATION {
        mask: usize,
        relationship: u32,
        _unused: [u64; 2]
    }

    extern "system" {
        fn GetLogicalProcessorInformation(
            info: *mut SYSTEM_LOGICAL_PROCESSOR_INFORMATION,
            length: &mut u32
        ) -> u32;
    }

    // First we need to determine how much space to reserve.

    // The required size of the buffer, in bytes.
    let mut needed_size = 0;

    unsafe {
        GetLogicalProcessorInformation(ptr::null_mut(), &mut needed_size);
    }

    let struct_size = mem::size_of::<SYSTEM_LOGICAL_PROCESSOR_INFORMATION>() as u32;

    // Could be 0, or some other bogus size.
    if needed_size == 0 || needed_size < struct_size || needed_size % struct_size != 0 {
        return None;
    }

    let count = needed_size / struct_size;

    // Allocate some memory where we will store the processor info.
    let mut buf = Vec::with_capacity(count as usize);

    let result;

    unsafe {
        result = GetLogicalProcessorInformation(buf.as_mut_ptr(), &mut needed_size);
    }

    // Failed for any reason.
    if result == 0 {
        return None;
    }

    let count = needed_size / struct_size;

    unsafe {
        buf.set_len(count as usize);
    }

    let phys_proc_count = buf.iter()
        // Only interested in processor packages (physical processors.)
        .filter(|proc_info| proc_info.relationship == RelationProcessorCore)
        .count();

    if phys_proc_count == 0 {
        None
    } else {
        Some(phys_proc_count)
    }
}

#[cfg(target_os = "linux")]
fn get_num_physical_cpus() -> usize {
    use std::io::BufReader;
    use std::io::BufRead;
    use std::fs::File;
    use std::collections::HashSet;

    let file = match File::open("/proc/cpuinfo") {
        Ok(val) => val,
        Err(_) => {return get_num_cpus()},
    };
    let reader = BufReader::new(file);
    let mut set = HashSet::new();
    let mut coreid: u32 = 0;
    let mut physid: u32 = 0;
    let mut chgcount = 0;
    for line in reader.lines().filter_map(|result| result.ok()) {
        let parts: Vec<&str> = line.split(':').map(|s| s.trim()).collect();
        if parts.len() != 2 {
            continue
        }
        if parts[0] == "core id" || parts[0] == "physical id" {
            let value = match parts[1].trim().parse() {
              Ok(val) => val,
              Err(_) => break,
            };
            match parts[0] {
                "core id"     => coreid = value,
                "physical id" => physid = value,
                _ => {},
            }
            chgcount += 1;
        }
        if chgcount == 2 {
            set.insert((physid, coreid));
            chgcount = 0;
        }
    }
    let count = set.len();
    if count == 0 { get_num_cpus() } else { count }
}

#[cfg(windows)]
fn get_num_cpus() -> usize {
    #[repr(C)]
    struct SYSTEM_INFO {
        wProcessorArchitecture: u16,
        wReserved: u16,
        dwPageSize: u32,
        lpMinimumApplicationAddress: *mut u8,
        lpMaximumApplicationAddress: *mut u8,
        dwActiveProcessorMask: *mut u8,
        dwNumberOfProcessors: u32,
        dwProcessorType: u32,
        dwAllocationGranularity: u32,
        wProcessorLevel: u16,
        wProcessorRevision: u16,
    }

    extern "system" {
        fn GetSystemInfo(lpSystemInfo: *mut SYSTEM_INFO);
    }

    unsafe {
        let mut sysinfo: SYSTEM_INFO = std::mem::uninitialized();
        GetSystemInfo(&mut sysinfo);
        sysinfo.dwNumberOfProcessors as usize
    }
}

#[cfg(any(target_os = "freebsd",
          target_os = "dragonfly",
          target_os = "bitrig",
          target_os = "netbsd"))]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    unsafe {
        cpus = libc::sysconf(libc::_SC_NPROCESSORS_ONLN) as libc::c_uint;
    }
    if cpus < 1 {
        let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];
        unsafe {
            libc::sysctl(mib.as_mut_ptr(),
                         2,
                         &mut cpus as *mut _ as *mut _,
                         &mut cpus_size as *mut _ as *mut _,
                         0 as *mut _,
                         0);
        }
        if cpus < 1 {
            cpus = 1;
        }
    }
    cpus as usize
}

#[cfg(target_os = "openbsd")]
fn get_num_cpus() -> usize {
    let mut cpus: libc::c_uint = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);
    let mut mib = [libc::CTL_HW, libc::HW_NCPU, 0, 0];

    unsafe {
        libc::sysctl(mib.as_mut_ptr(),
                     2,
                     &mut cpus as *mut _ as *mut _,
                     &mut cpus_size as *mut _ as *mut _,
                     0 as *mut _,
                     0);
    }
    if cpus < 1 {
        cpus = 1;
    }
    cpus as usize
}

#[cfg(target_os = "macos")]
fn get_num_physical_cpus() -> usize {
    use std::ffi::CStr;
    use std::ptr;

    let mut cpus: i32 = 0;
    let mut cpus_size = std::mem::size_of_val(&cpus);

    let sysctl_name = CStr::from_bytes_with_nul(b"hw.physicalcpu\0")
        .expect("byte literal is missing NUL");

    unsafe {
        if 0 != libc::sysctlbyname(sysctl_name.as_ptr(),
                                   &mut cpus as *mut _ as *mut _,
                                   &mut cpus_size as *mut _ as *mut _,
                                   ptr::null_mut(),
                                   0) {
            return get_num_cpus();
        }
    }
    cpus as usize
}

#[cfg(target_os = "linux")]
fn get_num_cpus() -> usize {
    let mut set:  libc::cpu_set_t = unsafe { std::mem::zeroed() };
    if unsafe { libc::sched_getaffinity(0, std::mem::size_of::<libc::cpu_set_t>(), &mut set) } == 0 {
        let mut count: u32 = 0;
        for i in 0..libc::CPU_SETSIZE as usize {
            if unsafe { libc::CPU_ISSET(i, &set) } {
                count += 1
            }
        }
        count as usize
    } else {
        let cpus = unsafe { libc::sysconf(libc::_SC_NPROCESSORS_ONLN) };
        if cpus < 1 {
            1
        } else {
            cpus as usize
        }
    }
}

#[cfg(any(
    target_os = "nacl",
    target_os = "macos",
    target_os = "ios",
    target_os = "android",
    target_os = "solaris",
    target_os = "fuchsia")
)]
fn get_num_cpus() -> usize {
    // On ARM targets, processors could be turned off to save power.
    // Use `_SC_NPROCESSORS_CONF` to get the real number.
    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_CONF;
    #[cfg(not(any(target_arch = "arm", target_arch = "aarch64")))]
    const CONF_NAME: libc::c_int = libc::_SC_NPROCESSORS_ONLN;

    let cpus = unsafe { libc::sysconf(CONF_NAME) };
    if cpus < 1 {
        1
    } else {
        cpus as usize
    }
}

#[cfg(any(target_os = "emscripten", target_os = "redox", target_os = "haiku"))]
fn get_num_cpus() -> usize {
    1
}

#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
fn get_num_cpus() -> usize {
    1
}

#[cfg(test)]
mod tests {
    fn env_var(name: &'static str) -> Option<usize> {
        ::std::env::var(name).ok().map(|val| val.parse().unwrap())
    }

    #[test]
    fn test_get() {
        let num = super::get();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }

    #[test]
    fn test_get_physical() {
        let num = super::get_physical();
        if let Some(n) = env_var("NUM_CPUS_TEST_GET_PHYSICAL") {
            assert_eq!(num, n);
        } else {
            assert!(num > 0);
            assert!(num < 236_451);
        }
    }
}
<|endoftext|>


<commit_before>//! An SVG parser.

#![feature(collections)]
#![cfg_attr(test, feature(core))]

mod reader;
pub mod path;

#[derive(Debug)]
pub struct Error {
    pub line: usize,
    pub column: usize,
    pub message: String,
}

pub type Result<T> = std::result::Result<T, Error>;
<commit_msg>Implement Debug for Error<commit_after>//! An SVG parser.

#![feature(collections)]
#![cfg_attr(test, feature(core))]

mod reader;
pub mod path;

pub struct Error {
    pub line: usize,
    pub column: usize,
    pub message: String,
}

pub type Result<T> = std::result::Result<T, Error>;

impl std::fmt::Debug for Error {
    fn fmt(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(formatter, "{} (line {}, column {})", self.message, self.line, self.column)
    }
}
<|endoftext|>


<commit_before>//! This library provides an API client for [Diffbot](https://www.diffbot.com)
//!
//! See also [the diffbot documentation](https://www.diffbot.com/dev/docs/).
//!
//! # Example
//!
//! ```
//! extern crate diffbot;
//! use diffbot::*;
//!
//! fn main() {
//!     let client = Diffbot::v3("insert_your_token_here");
//!     match client.call(API::Analyze, "http://www.diffbot.com") {
//!         Ok(result) => println!("{:?}", result),
//!         Err(Error::Api(code, msg)) => println!("API returned error {}: {}", code, msg),
//!         Err(err) => println!("Other error: {:?}", err),
//!     };
//! }
//! ```

extern crate url;
extern crate hyper;
extern crate rustc_serialize;

use hyper::header::ContentType;
use hyper::mime::{Mime,TopLevel,SubLevel};

use std::error::{self, Error as StdError};
use std::io;
use std::fmt;

use rustc_serialize::json;

/// Diffbot API client.
///
/// # Example
///
/// ```
/// # extern crate diffbot;
/// # use diffbot::*;
/// # fn main() {
/// let diffbot = Diffbot::v3("token");
/// let result = diffbot.call(API::Analyze, "http://diffbot.com");
/// # println!("{:?}", result);
/// # }
/// ```
pub struct Diffbot {
    token: String,
    version: u32,

    client: hyper::Client,
}

/// One of the possible diffbot API.
///
/// See [the diffbot documentation](https://www.diffbot.com/dev/docs/).
pub enum API {
    /// The analyze API automatically detects the page type.
    Analyze,
    /// The article API for news article.
    Article,
    /// The product API for products in online shops.
    Product,
    /// The discussion API for forums.
    Discussion,
    /// The image API for image-central pages.
    Image,
    /// The video API for video pages (youtube, ...).
    Video,
}

impl API {
    fn get_str(&self) -> &'static str {
        match self {
            &API::Analyze => "analyze",
            &API::Article => "article",
            &API::Product => "product",
            &API::Discussion => "discussion",
            &API::Image => "image",
            &API::Video => "video",
        }
    }

    fn get_url(&self) -> String {
        format!("https://diffbot.com/api/{}", self.get_str())
    }
}

/// Error occuring during a call.
#[derive(Debug)]
pub enum Error {
    /// The API returned an error.
    Api(u32,String),
    /// An error occured when decoding JSON from the API.
    Json,
    /// An error occured with the network.
    Io(io::Error),
    // TODO: don't expose hyper
    /// An HTTP error occured with the webserver.
    Http(hyper::Error),
}

impl From<json::ParserError> for Error {
    fn from(err: json::ParserError) -> Self {
        match err {
            json::ParserError::SyntaxError(_,_,_) => Error::Json,
            json::ParserError::IoError(err) => Error::Io(err),
        }
    }
}

impl From<hyper::Error> for Error {
    fn from(err: hyper::Error) -> Self {
        Error::Http(err)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Api(_, ref msg) => msg,
            &Error::Json => "invalid JSON",
            &Error::Io(ref err) => err.description(),
            &Error::Http(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::Api(_,_) => None,
            &Error::Json => None,
            &Error::Io(ref err) => Some(err),
            &Error::Http(ref err) => Some(err),
        }
    }
}

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

/// Result from a call.
pub type DiffbotResult = Result<json::Object, Error>;

impl Diffbot {
    /// Returns a Diffbot client that uses the given token and version.
    ///
    /// Valid versions: `1`, `2`, `3`.
    pub fn new<S: ToString>(token: S, version: u32) -> Self {
        Diffbot {
            token: token.to_string(),
            version: version,
            client: hyper::Client::new(),
        }
    }

    /// Convenient method to use a v1 client.
    pub fn v1<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 1)
    }

    /// Convenient method to use a v2 client.
    pub fn v2<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 2)
    }

    /// Convenient method to use a v3 client (recommended).
    pub fn v3<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 3)
    }

    /// Makes an API call without extra options.
    ///
    /// Just calls `call_with_options` with an empty option list.
    pub fn call(&self, api: API, target_url: &str) -> DiffbotResult {
        self.call_with_options::<String>(api, target_url, &[])
    }

    /// Makes an API call
    ///
    /// Runs `target_url` through the diffbot endpoint specified by `api`.
    /// Add each (key,value) pair in `options` to the query string.
    /// Read the [diffbot documentation](https://www.diffbot.com/dev/docs/)
    /// for information on supported values.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}",
    /// diffbot.call_with_options(API::Article,
    ///                           "http://diffbot.com",
    ///                           &[("paging", "false")])
    /// # );
    /// # }
    /// ```
    pub fn call_with_options<S: ToString>(&self,
                                          api: API, target_url: &str,
                                          options: &[(S,S)]) -> DiffbotResult {
        let url = self.prepare_url(api, target_url, options);

        let builder = self.client.get(url);
        Diffbot::process_request(builder)
    }

    /// Posti an entire html body to the API, without extra options.
    ///
    /// See `call_with_options` for information on the arguments.
    ///
    /// `target_url` here is the URL the page would have. It doesn't have to be accessible, but
    /// will be used when resolving links.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}", {
    /// let body = b"<html>...</html>";
    /// diffbot.post_body(API::Article,
    ///                   "http://my.website.com",
    ///                   body)
    /// # } );
    /// # }
    /// ```
    pub fn post_body(&self, api: API, target_url: &str, body: &[u8]) -> DiffbotResult {
        self.post_body_with_options::<String>(api, target_url, body, &[])
    }

    /// Posti an entire html body to the API.
    ///
    /// See `call_with_options` for information on the arguments.
    ///
    /// `target_url` here is the URL the page would have. It doesn't have to be accessible, but
    /// will be used when resolving links.
    pub fn post_body_with_options<S: ToString>(&self,
                                               api: API, target_url: &str,
                                               body: &[u8],
                                               options: &[(S,S)]) -> DiffbotResult {
        let url = self.prepare_url(api, target_url, options);

        let header = ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]));
        let builder = self.client.post(url).body(body).header(header);
        Diffbot::process_request(builder)
    }

    // Process a request and analyze the result
    fn process_request(builder: hyper::client::RequestBuilder) -> DiffbotResult {
        let mut result = try!(builder.send());

        let json_result = match try!(json::Json::from_reader(&mut result)) {
            json::Json::Object(obj) => obj,
            _ => return Err(Error::Json),
        };

        if json_result.contains_key("error") {
            let error_code = json_result.get("errorCode")
                .and_then(|c| c.as_u64())
                .unwrap_or(0u64);
            let error = json_result["error"].as_string().unwrap_or("");
            return Err(Error::Api(error_code as u32, error.to_string()));
        }

        Ok(json_result)
    }

    // Returns the diffbot URL for the given call
    fn prepare_url<S: ToString>(&self,
                                api: API, target_url: &str,
                                options: &[(S,S)]) -> hyper::Url {

        let mut params = Vec::<(String,String)>::new();
        params.push(("token".to_string(), self.token.clone()));
        params.push(("version".to_string(), self.version.to_string()));
        params.push(("url".to_string(), target_url.to_string()));
        for &(ref key, ref value) in options.iter() {
            params.push((key.to_string(), value.to_string()));
        }

        // We control the URL, it should always be valid.
        let mut url = hyper::Url::parse(&api.get_url()).unwrap();
        url.set_query_from_pairs(&params);

        url
    }
}

#[test]
fn test_call() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.call(API::Analyze, "http://diffbot.com"));
}

#[test]
fn test_call_with_options() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.call_with_options(API::Analyze,
                                               "http://diffbot.com",
                                               &[("fields", "links,meta")]));
}

#[test]
fn test_post() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    let res = diffbot.post_body(API::Article, "http://my.website.com", br#"

        <title>My Website</title>

My Website

This is a fake website, yet we will analyze its content.
           Isn't it interesting?

"#);

    println!("{:?}", res);
}
<commit_msg>Add search API<commit_after>//! This library provides an API client for [Diffbot](https://www.diffbot.com)
//!
//! See also [the diffbot documentation](https://www.diffbot.com/dev/docs/).
//!
//! # Example
//!
//! ```
//! extern crate diffbot;
//! use diffbot::*;
//!
//! fn main() {
//!     let client = Diffbot::v3("insert_your_token_here");
//!     match client.call(API::Analyze, "http://www.diffbot.com") {
//!         Ok(result) => println!("{:?}", result),
//!         Err(Error::Api(code, msg)) => println!("API returned error {}: {}", code, msg),
//!         Err(err) => println!("Other error: {:?}", err),
//!     };
//! }
//! ```

extern crate url;
extern crate hyper;
extern crate rustc_serialize;

use hyper::header::ContentType;
use hyper::mime::{Mime,TopLevel,SubLevel};

use std::error::{self, Error as StdError};
use std::io;
use std::fmt;

use rustc_serialize::json;

/// Diffbot API client.
///
/// # Example
///
/// ```
/// # extern crate diffbot;
/// # use diffbot::*;
/// # fn main() {
/// let diffbot = Diffbot::v3("token");
/// let result = diffbot.call(API::Analyze, "http://diffbot.com");
/// # println!("{:?}", result);
/// # }
/// ```
pub struct Diffbot {
    token: String,
    version: u32,

    client: hyper::Client,
}

/// One of the possible diffbot API.
///
/// See [the diffbot documentation](https://www.diffbot.com/dev/docs/).
pub enum API {
    /// The analyze API automatically detects the page type.
    Analyze,
    /// The article API for news article.
    Article,
    /// The product API for products in online shops.
    Product,
    /// The discussion API for forums.
    Discussion,
    /// The image API for image-central pages.
    Image,
    /// The video API for video pages (youtube, ...).
    Video,
}

impl API {
    fn get_str(&self) -> &'static str {
        match self {
            &API::Analyze => "analyze",
            &API::Article => "article",
            &API::Product => "product",
            &API::Discussion => "discussion",
            &API::Image => "image",
            &API::Video => "video",
        }
    }

    fn get_url(&self) -> String {
        format!("https://diffbot.com/api/{}", self.get_str())
    }
}

/// Error occuring during a call.
#[derive(Debug)]
pub enum Error {
    /// The API returned an error.
    Api(u32,String),
    /// An error occured when decoding JSON from the API.
    Json,
    /// An error occured with the network.
    Io(io::Error),
    // TODO: don't expose hyper
    /// An HTTP error occured with the webserver.
    Http(hyper::Error),
}

impl From<json::ParserError> for Error {
    fn from(err: json::ParserError) -> Self {
        match err {
            json::ParserError::SyntaxError(_,_,_) => Error::Json,
            json::ParserError::IoError(err) => Error::Io(err),
        }
    }
}

impl From<hyper::Error> for Error {
    fn from(err: hyper::Error) -> Self {
        Error::Http(err)
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        match self {
            &Error::Api(_, ref msg) => msg,
            &Error::Json => "invalid JSON",
            &Error::Io(ref err) => err.description(),
            &Error::Http(ref err) => err.description(),
        }
    }

    fn cause(&self) -> Option<&error::Error> {
        match self {
            &Error::Api(_,_) => None,
            &Error::Json => None,
            &Error::Io(ref err) => Some(err),
            &Error::Http(ref err) => Some(err),
        }
    }
}

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

/// Result from a call.
pub type DiffbotResult = Result<json::Object, Error>;

impl Diffbot {
    /// Returns a Diffbot client that uses the given token and version.
    ///
    /// Valid versions: `1`, `2`, `3`.
    pub fn new<S: ToString>(token: S, version: u32) -> Self {
        Diffbot {
            token: token.to_string(),
            version: version,
            client: hyper::Client::new(),
        }
    }

    /// Convenient method to use a v1 client.
    pub fn v1<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 1)
    }

    /// Convenient method to use a v2 client.
    pub fn v2<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 2)
    }

    /// Convenient method to use a v3 client (recommended).
    pub fn v3<S: ToString>(token: S) -> Self {
        Diffbot::new(token, 3)
    }

    /// Makes an API call without extra options.
    ///
    /// Just calls `call_with_options` with an empty option list.
    pub fn call(&self, api: API, target_url: &str) -> DiffbotResult {
        self.call_with_options::<String>(api, target_url, &[])
    }

    /// Makes an API call
    ///
    /// Runs `target_url` through the diffbot endpoint specified by `api`.
    /// Add each (key,value) pair in `options` to the query string.
    /// Read the [diffbot documentation](https://www.diffbot.com/dev/docs/)
    /// for information on supported values.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}",
    /// diffbot.call_with_options(API::Article,
    ///                           "http://diffbot.com",
    ///                           &[("paging", "false")])
    /// # );
    /// # }
    /// ```
    pub fn call_with_options<S: ToString>(&self,
                                          api: API, target_url: &str,
                                          options: &[(S,S)]) -> DiffbotResult {
        let url = self.prepare_url(api, target_url, options);

        let builder = self.client.get(url);
        Diffbot::process_request(builder)
    }

    /// Posti an entire html body to the API, without extra options.
    ///
    /// See `call_with_options` for information on the arguments.
    ///
    /// `target_url` here is the URL the page would have. It doesn't have to be accessible, but
    /// will be used when resolving links.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}", {
    /// let body = b"<html>...</html>";
    /// diffbot.post_body(API::Article,
    ///                   "http://my.website.com",
    ///                   body)
    /// # } );
    /// # }
    /// ```
    pub fn post_body(&self, api: API, target_url: &str, body: &[u8]) -> DiffbotResult {
        self.post_body_with_options::<String>(api, target_url, body, &[])
    }

    /// Posti an entire html body to the API.
    ///
    /// See `call_with_options` for information on the arguments.
    ///
    /// `target_url` here is the URL the page would have.
    /// It doesn't have to be accessible, but will be used when resolving links.
    pub fn post_body_with_options<S: ToString>(&self,
                                               api: API, target_url: &str,
                                               body: &[u8],
                                               options: &[(S,S)]) -> DiffbotResult {
        let url = self.prepare_url(api, target_url, options);

        let header = ContentType(Mime(TopLevel::Text, SubLevel::Html, vec![]));
        let builder = self.client.post(url).body(body).header(header);
        Diffbot::process_request(builder)
    }

    /// Run a search in a diffbot collection without extra options.
    ///
    /// Use `col` = `GLOBAL-INDEX` for the global search collection.
    ///
    /// # Example
    ///
    /// ```
    /// # extern crate diffbot;
    /// # use diffbot::*;
    /// # fn main() {
    /// # let diffbot = Diffbot::v3("token");
    /// # println!("{:?}",
    /// diffbot.search("GLOBAL-INDEX", "diffbot")
    /// # );
    /// # }
    /// ```
    pub fn search(&self, col: &str, query: &str) -> DiffbotResult {
        self.search_with_options::<String>(col, query, &[])
    }

    /// Run a search in a diffbot collection.
    ///
    /// Use `col` = `GLOBAL-INDEX` for the global search collection.
    pub fn search_with_options<S: ToString>(&self,
                                            col: &str, query: &str,
                                            options: &[(S,S)]) -> DiffbotResult {
        let url = self.prepare_search_url(col, query, options);

        let builder = self.client.get(url);
        Diffbot::process_request(builder)
    }

    // TODO: add crawlbot API

    // Process a request and analyze the result
    fn process_request(builder: hyper::client::RequestBuilder) -> DiffbotResult {
        let mut result = try!(builder.send());

        let json_result = match try!(json::Json::from_reader(&mut result)) {
            json::Json::Object(obj) => obj,
            _ => return Err(Error::Json),
        };

        if json_result.contains_key("error") {
            let error_code = json_result.get("errorCode")
                .and_then(|c| c.as_u64())
                .unwrap_or(0u64);
            let error = json_result["error"].as_string().unwrap_or("");
            return Err(Error::Api(error_code as u32, error.to_string()));
        }

        Ok(json_result)
    }

    fn prepare_search_url<S: ToString>(&self,
                                       col: &str, query: &str,
                                       options: &[(S,S)]) -> hyper::Url {
        let mut params = Vec::<(String,String)>::new();
        params.push(("token".to_string(), self.token.clone()));
        params.push(("version".to_string(), self.version.to_string()));
        params.push(("col".to_string(), col.to_string()));
        params.push(("query".to_string(), query.to_string()));
        for &(ref key, ref value) in options.iter() {
            params.push((key.to_string(), value.to_string()));
        }

        // We control the URL, it should always be valid.
        let mut url = hyper::Url::parse("https://diffbot.com/api/search").unwrap();
        url.set_query_from_pairs(&params);

        url
    }

    // Returns the diffbot URL for the given call
    fn prepare_url<S: ToString>(&self,
                                api: API, target_url: &str,
                                options: &[(S,S)]) -> hyper::Url {

        let mut params = Vec::<(String,String)>::new();
        params.push(("token".to_string(), self.token.clone()));
        params.push(("version".to_string(), self.version.to_string()));
        params.push(("url".to_string(), target_url.to_string()));
        for &(ref key, ref value) in options.iter() {
            params.push((key.to_string(), value.to_string()));
        }

        // We control the URL, it should always be valid.
        let mut url = hyper::Url::parse(&api.get_url()).unwrap();
        url.set_query_from_pairs(&params);

        url
    }
}

#[test]
fn test_search() {
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.search("GLOBAL-INDEX", "diffbot"));
}

#[test]
fn test_search_with_options() {
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.search_with_options("GLOBAL-INDEX", "diffbot", &[("num","20")]));
}

#[test]
fn test_call() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.call(API::Analyze, "http://diffbot.com"));
}

#[test]
fn test_call_with_options() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    println!("{:?}", diffbot.call_with_options(API::Analyze,
                                               "http://diffbot.com",
                                               &[("fields", "links,meta")]));
}

#[test]
fn test_post() {
    // Use `cargo test -- --nocapture` to see the output
    let diffbot = Diffbot::v3("insert_your_token_here");
    let res = diffbot.post_body(API::Article, "http://my.website.com", br#"

        <title>My Website</title>

My Website

This is a fake website, yet we will analyze its content.
           Isn't it interesting?

"#);

    println!("{:?}", res);
}
<|endoftext|>


<commit_before>#![feature(plugin_registrar)]
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use syntax::ast::TokenTree;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacExpr, MacResult};
use syntax::ext::build::AstBuilder;

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("speculate", expand_speculate);
}

fn expand_speculate(cx: &mut ExtCtxt, sp: Span, _args: &[TokenTree]) -> Box<MacResult + 'static> {
    MacExpr::new(cx.expr_uint(sp, 0))
}
<commit_msg>Return an empty `mod` from `speculate!` using quasi-quoting macros.<commit_after>#![feature(plugin_registrar, quote)]
extern crate rustc;
extern crate syntax;

use rustc::plugin::Registry;
use syntax::ast::TokenTree;
use syntax::codemap::Span;
use syntax::ext::base::{ExtCtxt, MacItems, MacResult};

#[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_macro("speculate", expand_speculate);
}

fn expand_speculate(cx: &mut ExtCtxt, _sp: Span, _args: &[TokenTree]) -> Box<MacResult + 'static> {
    let module = quote_item!(cx,
        mod sup {
        }
    ).expect("failed to create item!");

    MacItems::new(Some(module).into_iter())
}
<|endoftext|>