<commit_before>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

use sys::component::Component;
use sys::process::*;
use sys::processor::*;
use sys::Disk;
use sys::Networks;
use LoadAvg;
use Pid;
use User;
use {RefreshKind, SystemExt};

use std::collections::HashMap;

/// Structs containing system's information.
pub struct System {
    processes_list: HashMap<Pid, Process>,
    networks: Networks,
    global_processor: Processor,
}

impl SystemExt for System {
    fn new_with_specifics(_: RefreshKind) -> System {
        System {
            processes_list: Default::default(),
            networks: Networks::new(),
            global_processor: Processor::new(),
        }
    }

    fn refresh_memory(&mut self) {}

    fn refresh_cpu(&mut self) {}

    fn refresh_components_list(&mut self) {}

    fn refresh_processes(&mut self) {}

    fn refresh_process(&mut self, _pid: Pid) -> bool {
        false
    }

    fn refresh_disks_list(&mut self) {}

    fn refresh_users_list(&mut self) {}

    // COMMON PART
    //
    // Need to be moved into a "common" file to avoid duplication.

    fn get_processes(&self) -> &HashMap<Pid, Process> {
        &self.processes_list
    }

    fn get_process(&self, _pid: Pid) -> Option<&Process> {
        None
    }

    fn get_networks(&self) -> &Networks {
        &self.networks
    }

    fn get_networks_mut(&mut self) -> &mut Networks {
        &mut self.networks
    }

    fn get_global_processor_info(&self) -> &Processor {
        &self.global_processor
    }

    fn get_processors(&self) -> &[Processor] {
        &[]
    }

    fn get_total_memory(&self) -> u64 {
        0
    }

    fn get_free_memory(&self) -> u64 {
        0
    }

    fn get_available_memory(&self) -> u64 {
        0
    }

    fn get_used_memory(&self) -> u64 {
        0
    }

    fn get_total_swap(&self) -> u64 {
        0
    }

    fn get_free_swap(&self) -> u64 {
        0
    }

    fn get_used_swap(&self) -> u64 {
        0
    }

    fn get_components(&self) -> &[Component] {
        &[]
    }

    fn get_components_mut(&mut self) -> &mut [Component] {
        &mut []
    }

    fn get_disks(&self) -> &[Disk] {
        &[]
    }

    fn get_disks_mut(&mut self) -> &mut [Disk] {
        &mut []
    }

    fn get_uptime(&self) -> u64 {
        0
    }

    fn get_boot_time(&self) -> u64 {
        0
    }

    fn get_load_average(&self) -> LoadAvg {
        LoadAvg {
            one: 0.,
            five: 0.,
            fifteen: 0.,
        }
    }

    fn get_users(&self) -> &[User] {
        &[]
    }
}

impl Default for System {
    fn default() -> System {
        System::new()
    }
}
<commit_msg>Add System::get_name and System::get_version on unsupported systems<commit_after>//
// Sysinfo
//
// Copyright (c) 2015 Guillaume Gomez
//

use sys::component::Component;
use sys::process::*;
use sys::processor::*;
use sys::Disk;
use sys::Networks;
use LoadAvg;
use Pid;
use User;
use {RefreshKind, SystemExt};

use std::collections::HashMap;

/// Structs containing system's information.
pub struct System {
    processes_list: HashMap<Pid, Process>,
    networks: Networks,
    global_processor: Processor,
}

impl SystemExt for System {
    fn new_with_specifics(_: RefreshKind) -> System {
        System {
            processes_list: Default::default(),
            networks: Networks::new(),
            global_processor: Processor::new(),
        }
    }

    fn refresh_memory(&mut self) {}

    fn refresh_cpu(&mut self) {}

    fn refresh_components_list(&mut self) {}

    fn refresh_processes(&mut self) {}

    fn refresh_process(&mut self, _pid: Pid) -> bool {
        false
    }

    fn refresh_disks_list(&mut self) {}

    fn refresh_users_list(&mut self) {}

    // COMMON PART
    //
    // Need to be moved into a "common" file to avoid duplication.

    fn get_processes(&self) -> &HashMap<Pid, Process> {
        &self.processes_list
    }

    fn get_process(&self, _pid: Pid) -> Option<&Process> {
        None
    }

    fn get_networks(&self) -> &Networks {
        &self.networks
    }

    fn get_networks_mut(&mut self) -> &mut Networks {
        &mut self.networks
    }

    fn get_global_processor_info(&self) -> &Processor {
        &self.global_processor
    }

    fn get_processors(&self) -> &[Processor] {
        &[]
    }

    fn get_total_memory(&self) -> u64 {
        0
    }

    fn get_free_memory(&self) -> u64 {
        0
    }

    fn get_available_memory(&self) -> u64 {
        0
    }

    fn get_used_memory(&self) -> u64 {
        0
    }

    fn get_total_swap(&self) -> u64 {
        0
    }

    fn get_free_swap(&self) -> u64 {
        0
    }

    fn get_used_swap(&self) -> u64 {
        0
    }

    fn get_components(&self) -> &[Component] {
        &[]
    }

    fn get_components_mut(&mut self) -> &mut [Component] {
        &mut []
    }

    fn get_disks(&self) -> &[Disk] {
        &[]
    }

    fn get_disks_mut(&mut self) -> &mut [Disk] {
        &mut []
    }

    fn get_uptime(&self) -> u64 {
        0
    }

    fn get_boot_time(&self) -> u64 {
        0
    }

    fn get_load_average(&self) -> LoadAvg {
        LoadAvg {
            one: 0.,
            five: 0.,
            fifteen: 0.,
        }
    }

    fn get_users(&self) -> &[User] {
        &[]
    }

    fn get_name(&self) -> Option<String> {
        None
    }

    fn get_version(&self) -> Option<String> {
        None
    }
}

impl Default for System {
    fn default() -> System {
        System::new()
    }
}
<|endoftext|>


<commit_before>extern crate serde;
#[macro_use] extern crate serde_derive;

use std::collections::HashMap;

#[derive(Debug, Serialize)]
pub enum AMQPType {
    Boolean,
    ShortShortInt,
    ShortShortUInt,
    ShortInt,
    ShortUInt,
    LongInt,
    LongUInt,
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    ShortString,
    LongString,
    FieldArray,
    TimeStamp,
    FieldTable,
    Void,
}

impl AMQPType {
    pub fn from_id(id: char) -> AMQPType {
        match id {
            't' => AMQPType::Boolean,
            'b' => AMQPType::ShortShortInt,
            'B' => AMQPType::ShortShortUInt,
            'U' => AMQPType::ShortInt,
            'u' => AMQPType::ShortUInt,
            'I' => AMQPType::LongInt,
            'i' => AMQPType::LongUInt,
            'L' => AMQPType::LongLongInt,
            'l' => AMQPType::LongLongUInt,
            'f' => AMQPType::Float,
            'd' => AMQPType::Double,
            'D' => AMQPType::DecimalValue,
            's' => AMQPType::ShortString,
            'S' => AMQPType::LongString,
            'A' => AMQPType::FieldArray,
            'T' => AMQPType::TimeStamp,
            'F' => AMQPType::FieldTable,
            'V' => AMQPType::Void,
            _ => panic!("Unknown type id {}", id), /*FIXME: don't panic*/
        }
    }

    pub fn get_id(&self) -> char {
        match *self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            AMQPType::ShortInt => 'U',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            AMQPType::LongLongInt => 'L',
            AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            AMQPType::ShortString => 's',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::TimeStamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::Void => 'V',
        }
    }

    pub fn to_string(&self) -> String {
        format!("{:?}", self)
    }
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type DecimalValue   = i64;    /* FIXME: find out what this is exactly */
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type TimeStamp      = u64;
pub type FieldTable     = HashMap<String, AMQPValue>;
pub type Void           = ();

#[derive(Debug, Serialize)]
pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    TimeStamp(TimeStamp),
    FieldTable(FieldTable),
    Void(Void),
}
<commit_msg>types: derive PartialEq<commit_after>extern crate serde;
#[macro_use] extern crate serde_derive;

use std::collections::HashMap;

#[derive(Debug, PartialEq, Serialize)]
pub enum AMQPType {
    Boolean,
    ShortShortInt,
    ShortShortUInt,
    ShortInt,
    ShortUInt,
    LongInt,
    LongUInt,
    LongLongInt,
    LongLongUInt,
    Float,
    Double,
    DecimalValue,
    ShortString,
    LongString,
    FieldArray,
    TimeStamp,
    FieldTable,
    Void,
}

impl AMQPType {
    pub fn from_id(id: char) -> AMQPType {
        match id {
            't' => AMQPType::Boolean,
            'b' => AMQPType::ShortShortInt,
            'B' => AMQPType::ShortShortUInt,
            'U' => AMQPType::ShortInt,
            'u' => AMQPType::ShortUInt,
            'I' => AMQPType::LongInt,
            'i' => AMQPType::LongUInt,
            'L' => AMQPType::LongLongInt,
            'l' => AMQPType::LongLongUInt,
            'f' => AMQPType::Float,
            'd' => AMQPType::Double,
            'D' => AMQPType::DecimalValue,
            's' => AMQPType::ShortString,
            'S' => AMQPType::LongString,
            'A' => AMQPType::FieldArray,
            'T' => AMQPType::TimeStamp,
            'F' => AMQPType::FieldTable,
            'V' => AMQPType::Void,
            _ => panic!("Unknown type id {}", id), /*FIXME: don't panic*/
        }
    }

    pub fn get_id(&self) -> char {
        match *self {
            AMQPType::Boolean => 't',
            AMQPType::ShortShortInt => 'b',
            AMQPType::ShortShortUInt => 'B',
            AMQPType::ShortInt => 'U',
            AMQPType::ShortUInt => 'u',
            AMQPType::LongInt => 'I',
            AMQPType::LongUInt => 'i',
            AMQPType::LongLongInt => 'L',
            AMQPType::LongLongUInt => 'l',
            AMQPType::Float => 'f',
            AMQPType::Double => 'd',
            AMQPType::DecimalValue => 'D',
            AMQPType::ShortString => 's',
            AMQPType::LongString => 'S',
            AMQPType::FieldArray => 'A',
            AMQPType::TimeStamp => 'T',
            AMQPType::FieldTable => 'F',
            AMQPType::Void => 'V',
        }
    }

    pub fn to_string(&self) -> String {
        format!("{:?}", self)
    }
}

pub type Boolean        = bool;
pub type ShortShortInt  = i8;
pub type ShortShortUInt = u8;
pub type ShortInt       = i16;
pub type ShortUInt      = u16;
pub type LongInt        = i32;
pub type LongUInt       = u32;
pub type LongLongInt    = i64;
pub type LongLongUInt   = u64;
pub type Float          = f32;
pub type Double         = f64;
pub type DecimalValue   = i64;    /* FIXME: find out what this is exactly */
pub type ShortString    = String; /* TODO: don't allow size >= 255 */
pub type LongString     = String;
pub type FieldArray     = Vec<AMQPValue>;
pub type TimeStamp      = u64;
pub type FieldTable     = HashMap<String, AMQPValue>;
pub type Void           = ();

#[derive(Debug, PartialEq, Serialize)]
pub enum AMQPValue {
    Boolean(Boolean),
    ShortShortInt(ShortShortInt),
    ShortShortUInt(ShortShortUInt),
    ShortInt(ShortInt),
    ShortUInt(ShortUInt),
    LongInt(LongInt),
    LongUInt(LongUInt),
    LongLongInt(LongLongInt),
    LongLongUInt(LongLongUInt),
    Float(Float),
    Double(Double),
    DecimalValue(DecimalValue),
    ShortString(ShortString),
    LongString(LongString),
    FieldArray(FieldArray),
    TimeStamp(TimeStamp),
    FieldTable(FieldTable),
    Void(Void),
}
<|endoftext|>


<commit_before>
use ::{
    Direction,
    Incoming,
};

use visit::{
    GraphBase,
    GraphRef,
    IntoNodeIdentifiers,
    IntoNodeReferences,
    IntoNeighbors,
    IntoNeighborsDirected,
    IntoEdgeReferences,
    NodeCompactIndexable,
    NodeCount,
    NodeIndexable,
    Visitable,
    EdgeRef,
    Data,
    GraphProp,
};

/// Wrapper type for walking the graph as if all edges are reversed.
#[derive(Copy, Clone, Debug)]
pub struct Reversed<G>(pub G);

impl<G: GraphBase> GraphBase for Reversed<G> {
    type NodeId = G::NodeId;
    type EdgeId = G::EdgeId;
}

impl<G: GraphRef> GraphRef for Reversed<G> { }

Data!{delegate_impl [[G], G, Reversed<G>, access0]}

impl<G> IntoNeighbors for Reversed<G>
    where G: IntoNeighborsDirected
{
    type Neighbors = G::NeighborsDirected;
    fn neighbors(self, n: G::NodeId) -> G::NeighborsDirected
    {
        self.0.neighbors_directed(n, Incoming)
    }
}

impl<G> IntoNeighborsDirected for Reversed<G>
    where G: IntoNeighborsDirected
{
    type NeighborsDirected = G::NeighborsDirected;
    fn neighbors_directed(self, n: G::NodeId, d: Direction)
        -> G::NeighborsDirected
    {
        self.0.neighbors_directed(n, d.opposite())
    }
}

impl<G: Visitable> Visitable for Reversed<G>
{
    type Map = G::Map;
    fn visit_map(&self) -> G::Map {
        self.0.visit_map()
    }
    fn reset_map(&self, map: &mut Self::Map) {
        self.0.reset_map(map);
    }
}

/// An edge reference for `Reversed`.
#[derive(Copy, Clone, Debug)]
pub struct ReversedEdgeReference<R>(R);

/// An edge reference
impl<R> EdgeRef for ReversedEdgeReference<R>
    where R: EdgeRef,
{
    type NodeId = R::NodeId;
    type EdgeId = R::EdgeId;
    type Weight = R::Weight;
    fn source(&self) -> Self::NodeId {
        self.0.target()
    }
    fn target(&self) -> Self::NodeId {
        self.0.source()
    }
    fn weight(&self) -> &Self::Weight {
        self.0.weight()
    }
    fn id(&self) -> Self::EdgeId {
        self.0.id()
    }
}

impl<G> IntoEdgeReferences for Reversed<G>
    where G: IntoEdgeReferences
{
    type EdgeRef = ReversedEdgeReference<G::EdgeRef>;
    type EdgeReferences = ReversedEdgeReferences<G::EdgeReferences>;
    fn edge_references(self) -> Self::EdgeReferences {
        ReversedEdgeReferences {
            iter: self.0.edge_references(),
        }
    }
}

/// An iterator of edge references for `Reversed`.
pub struct ReversedEdgeReferences<I> {
    iter: I,
}

impl<I> Iterator for ReversedEdgeReferences<I>
    where I: Iterator,
          I::Item: EdgeRef,
{
    type Item = ReversedEdgeReference<I::Item>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(ReversedEdgeReference)
    }
}

macro_rules! access0 {
    ($e:expr) => ($e.0)
}

NodeIndexable!{delegate_impl [[G], G, Reversed<G>, access0]}
NodeCompactIndexable!{delegate_impl [[G], G, Reversed<G>, access0]}
IntoNodeIdentifiers!{delegate_impl [[G], G, Reversed<G>, access0]}
IntoNodeReferences!{delegate_impl [[G], G, Reversed<G>, access0]}
GraphProp!{delegate_impl [[G], G, Reversed<G>, access0]}
NodeCount!{delegate_impl [[G], G, Reversed<G>, access0]}

<commit_msg>Update reversed doc<commit_after>
use ::{
    Direction,
    Incoming,
};

use visit::{
    GraphBase,
    GraphRef,
    IntoNodeIdentifiers,
    IntoNodeReferences,
    IntoNeighbors,
    IntoNeighborsDirected,
    IntoEdgeReferences,
    NodeCompactIndexable,
    NodeCount,
    NodeIndexable,
    Visitable,
    EdgeRef,
    Data,
    GraphProp,
};

/// Edge-reversing graph adaptor.
///
/// All edges have the opposite direction with `Reversed`.
#[derive(Copy, Clone, Debug)]
pub struct Reversed<G>(pub G);

impl<G: GraphBase> GraphBase for Reversed<G> {
    type NodeId = G::NodeId;
    type EdgeId = G::EdgeId;
}

impl<G: GraphRef> GraphRef for Reversed<G> { }

Data!{delegate_impl [[G], G, Reversed<G>, access0]}

impl<G> IntoNeighbors for Reversed<G>
    where G: IntoNeighborsDirected
{
    type Neighbors = G::NeighborsDirected;
    fn neighbors(self, n: G::NodeId) -> G::NeighborsDirected
    {
        self.0.neighbors_directed(n, Incoming)
    }
}

impl<G> IntoNeighborsDirected for Reversed<G>
    where G: IntoNeighborsDirected
{
    type NeighborsDirected = G::NeighborsDirected;
    fn neighbors_directed(self, n: G::NodeId, d: Direction)
        -> G::NeighborsDirected
    {
        self.0.neighbors_directed(n, d.opposite())
    }
}

impl<G: Visitable> Visitable for Reversed<G>
{
    type Map = G::Map;
    fn visit_map(&self) -> G::Map {
        self.0.visit_map()
    }
    fn reset_map(&self, map: &mut Self::Map) {
        self.0.reset_map(map);
    }
}

/// An edge reference for `Reversed`.
#[derive(Copy, Clone, Debug)]
pub struct ReversedEdgeReference<R>(R);

/// An edge reference
impl<R> EdgeRef for ReversedEdgeReference<R>
    where R: EdgeRef,
{
    type NodeId = R::NodeId;
    type EdgeId = R::EdgeId;
    type Weight = R::Weight;
    fn source(&self) -> Self::NodeId {
        self.0.target()
    }
    fn target(&self) -> Self::NodeId {
        self.0.source()
    }
    fn weight(&self) -> &Self::Weight {
        self.0.weight()
    }
    fn id(&self) -> Self::EdgeId {
        self.0.id()
    }
}

impl<G> IntoEdgeReferences for Reversed<G>
    where G: IntoEdgeReferences
{
    type EdgeRef = ReversedEdgeReference<G::EdgeRef>;
    type EdgeReferences = ReversedEdgeReferences<G::EdgeReferences>;
    fn edge_references(self) -> Self::EdgeReferences {
        ReversedEdgeReferences {
            iter: self.0.edge_references(),
        }
    }
}

/// An iterator of edge references for `Reversed`.
pub struct ReversedEdgeReferences<I> {
    iter: I,
}

impl<I> Iterator for ReversedEdgeReferences<I>
    where I: Iterator,
          I::Item: EdgeRef,
{
    type Item = ReversedEdgeReference<I::Item>;
    fn next(&mut self) -> Option<Self::Item> {
        self.iter.next().map(ReversedEdgeReference)
    }
}

macro_rules! access0 {
    ($e:expr) => ($e.0)
}

NodeIndexable!{delegate_impl [[G], G, Reversed<G>, access0]}
NodeCompactIndexable!{delegate_impl [[G], G, Reversed<G>, access0]}
IntoNodeIdentifiers!{delegate_impl [[G], G, Reversed<G>, access0]}
IntoNodeReferences!{delegate_impl [[G], G, Reversed<G>, access0]}
GraphProp!{delegate_impl [[G], G, Reversed<G>, access0]}
NodeCount!{delegate_impl [[G], G, Reversed<G>, access0]}

<|endoftext|>


<commit_before>use byteorder::{LittleEndian, ReadBytesExt};
use crate::internal::prelude::*;
use audiopus::{
    Channels,
    coder::Decoder as OpusDecoder,
    Result as OpusResult,
};
use parking_lot::Mutex;
use serde_json;
use std::{
    ffi::OsStr,
    fs::File,
    io::{BufReader, ErrorKind as IoErrorKind, Read, Result as IoResult},
    process::{Child, Command, Stdio},
    result::Result as StdResult,
    sync::Arc,
};
use super::{AudioSource, AudioType, DcaError, DcaMetadata, VoiceError, audio};
use log::{debug, warn};
use crate::prelude::SerenityError;

struct ChildContainer(Child);

impl Read for ChildContainer {
    fn read(&mut self, buffer: &mut [u8]) -> IoResult<usize> {
        self.0.stdout.as_mut().unwrap().read(buffer)
    }
}

impl Drop for ChildContainer {
    fn drop (&mut self) {
        if let Err(e) = self.0.kill() {
            debug!("[Voice] Error awaiting child process: {:?}", e);
        }
    }
}

// Since each audio item needs its own decoder, we need to
// work around the fact that OpusDecoders aint sendable.
struct SendDecoder(OpusDecoder);

impl SendDecoder {
    fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> OpusResult<usize> {
        let &mut SendDecoder(ref mut sd) = self;
        sd.decode_float(input, output, fec)
    }
}

unsafe impl Send for SendDecoder {}

struct InputSource<R: Read + Send + 'static> {
    stereo: bool,
    reader: R,
    kind: AudioType,
    decoder: Option<Arc<Mutex<SendDecoder>>>,
}

impl<R: Read + Send> AudioSource for InputSource<R> {
    fn is_stereo(&mut self) -> bool { self.stereo }

    fn get_type(&self) -> AudioType { self.kind }

    fn read_pcm_frame(&mut self, buffer: &mut [i16]) -> Option<usize> {
        for (i, v) in buffer.iter_mut().enumerate() {
            *v = match self.reader.read_i16::<LittleEndian>() {
                Ok(v) => v,
                Err(ref e) => {
                    return if e.kind() == IoErrorKind::UnexpectedEof {
                        Some(i)
                    } else {
                        None
                    }
                },
            }
        }

        Some(buffer.len())
    }

    fn read_opus_frame(&mut self) -> Option<Vec<u8>> {
        match self.reader.read_i16::<LittleEndian>() {
            Ok(size) => {
                if size <= 0 {
                    warn!("Invalid opus frame size: {}", size);
                    return None;
                }

                let mut frame = Vec::with_capacity(size as usize);

                {
                    let reader = self.reader.by_ref();

                    if reader.take(size as u64).read_to_end(&mut frame).is_err() {
                        return None;
                    }
                }

                Some(frame)
            },
            Err(ref e) => if e.kind() == IoErrorKind::UnexpectedEof {
                Some(Vec::new())
            } else {
                None
            },
        }
    }

    fn decode_and_add_opus_frame(&mut self, float_buffer: &mut [f32; 1920], volume: f32) -> Option<usize> {
        let decoder_lock = self.decoder.as_mut()?.clone();
        let frame = self.read_opus_frame()?;
        let mut local_buf = [0f32; 960 * 2];

        let count = {
            let mut decoder = decoder_lock.lock();

            decoder.decode_float(frame.as_slice(), &mut local_buf, false).ok()?
        };

        for (i, float_buffer_element) in float_buffer.iter_mut().enumerate().take(1920) {
            *float_buffer_element += local_buf[i] * volume;
        }

        Some(count)
    }
}

/// Opens an audio file through `ffmpeg` and creates an audio source.
pub fn ffmpeg<P: AsRef<OsStr>>(path: P) -> Result<Box<dyn AudioSource>> {
    _ffmpeg(path.as_ref())
}

fn _ffmpeg(path: &OsStr) -> Result<Box<dyn AudioSource>> {
    // Will fail if the path is not to a file on the fs. Likely a YouTube URI.
    let is_stereo = is_stereo(path).unwrap_or(false);
    let stereo_val = if is_stereo { "2" } else { "1" };

    _ffmpeg_optioned(path, &[
        "-f",
        "s16le",
        "-ac",
        stereo_val,
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ], Some(is_stereo))
}

/// Opens an audio file through `ffmpeg` and creates an audio source, with
/// user-specified arguments to pass to ffmpeg.
///
/// Note that this does _not_ build on the arguments passed by the [`ffmpeg`]
/// function.
///
/// # Examples
///
/// Pass options to create a custom ffmpeg streamer:
///
/// ```rust,no_run
/// use serenity::voice;
///
/// let stereo_val = "2";
///
/// let streamer = voice::ffmpeg_optioned("./some_file.mp3", &[
///     "-f",
///     "s16le",
///     "-ac",
///     stereo_val,
///     "-ar",
///     "48000",
///     "-acodec",
///     "pcm_s16le",
///     "-",
/// ]);
pub fn ffmpeg_optioned<P: AsRef<OsStr>>(
    path: P,
    args: &[&str],
) -> Result<Box<dyn AudioSource>> {
    _ffmpeg_optioned(path.as_ref(), args, None)
}

fn _ffmpeg_optioned(path: &OsStr, args: &[&str], is_stereo_known: Option<bool>) -> Result<Box<dyn AudioSource>> {
    let is_stereo = is_stereo_known
        .or_else(|| is_stereo(path).ok())
        .unwrap_or(false);

    let command = Command::new("ffmpeg")
        .arg("-i")
        .arg(path)
        .args(args)
        .stderr(Stdio::null())
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(is_stereo, ChildContainer(command)))
}

/// Creates a streamed audio source from a DCA file.
/// Currently only accepts the DCA1 format.
pub fn dca<P: AsRef<OsStr>>(path: P) -> StdResult<Box<dyn AudioSource>, DcaError> {
    _dca(path.as_ref())
}

fn _dca(path: &OsStr) -> StdResult<Box<dyn AudioSource>, DcaError> {
    let file = File::open(path).map_err(DcaError::IoError)?;

    let mut reader = BufReader::new(file);

    let mut header = [0u8; 4];

    // Read in the magic number to verify it's a DCA file.
    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    if header != b"DCA1"[..] {
        return Err(DcaError::InvalidHeader);
    }

    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    let size = (&header[..]).read_i32::<LittleEndian>().unwrap();

    // Sanity check
    if size < 2 {
        return Err(DcaError::InvalidSize(size));
    }

    let mut raw_json = Vec::with_capacity(size as usize);

    {
        let json_reader = reader.by_ref();
        json_reader
            .take(size as u64)
            .read_to_end(&mut raw_json)
            .map_err(DcaError::IoError)?;
    }

    let metadata = serde_json::from_slice::<DcaMetadata>(raw_json.as_slice())
        .map_err(DcaError::InvalidMetadata)?;

    Ok(opus(metadata.is_stereo(), reader))
}

/// Creates an Opus audio source. This makes certain assumptions: namely, that the input stream
/// is composed ONLY of opus frames of the variety that Discord expects.
///
/// If you want to decode a `.opus` file, use [`ffmpeg`]
///
/// [`ffmpeg`]: fn.ffmpeg.html
pub fn opus<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<dyn AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader,
        kind: AudioType::Opus,
        decoder: Some(
            Arc::new(Mutex::new(
                // We always want to decode *to* stereo, for mixing reasons.
                SendDecoder(OpusDecoder::new(audio::SAMPLE_RATE, Channels::Stereo).unwrap())
            ))
        ),
    })
}

/// Creates a PCM audio source.
pub fn pcm<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<dyn AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader,
        kind: AudioType::Pcm,
        decoder: None,
    })
}

/// Creates a streamed audio source with `youtube-dl` and `ffmpeg`.
pub fn ytdl(uri: &str) -> Result<Box<dyn AudioSource>> {
    let ytdl_args = [
        "-f",
        "webm[abr>0]/bestaudio/best",
        "--no-playlist",
        "--ignore-config",
        uri,
        "-o",
        "-"
    ];

    let ffmpeg_args = [
        "-f",
        "s16le",
        "-ac",
        "2",
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ];

    let youtube_dl = Command::new("youtube-dl")
        .args(&ytdl_args)
        .stdin(Stdio::null())
        .stderr(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    let ffmpeg = Command::new("ffmpeg")
        .arg("-re")
        .arg("-i")
        .arg("-")
        .args(&ffmpeg_args)
        .stdin(youtube_dl.stdout.ok_or(SerenityError::Other("Failed to open youtube-dl stdout"))?)
        .stderr(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(true, ChildContainer(ffmpeg)))
}

fn is_stereo(path: &OsStr) -> Result<bool> {
    let args = ["-v", "quiet", "-of", "json", "-show-streams", "-i"];

    let out = Command::new("ffprobe")
        .args(&args)
        .arg(path)
        .stdin(Stdio::null())
        .output()?;

    let value: Value = serde_json::from_reader(&out.stdout[..])?;

    let streams = value
        .as_object()
        .and_then(|m| m.get("streams"))
        .and_then(|v| v.as_array())
        .ok_or(Error::Voice(VoiceError::Streams))?;

    let check = streams.iter().any(|stream| {
        let channels = stream
            .as_object()
            .and_then(|m| m.get("channels").and_then(|v| v.as_i64()));

        channels == Some(2)
    });

    Ok(check)
}
<commit_msg>Voice: add infinite retry arg to ytdl for rst packets (#578)<commit_after>use byteorder::{LittleEndian, ReadBytesExt};
use crate::internal::prelude::*;
use audiopus::{
    Channels,
    coder::Decoder as OpusDecoder,
    Result as OpusResult,
};
use parking_lot::Mutex;
use serde_json;
use std::{
    ffi::OsStr,
    fs::File,
    io::{BufReader, ErrorKind as IoErrorKind, Read, Result as IoResult},
    process::{Child, Command, Stdio},
    result::Result as StdResult,
    sync::Arc,
};
use super::{AudioSource, AudioType, DcaError, DcaMetadata, VoiceError, audio};
use log::{debug, warn};
use crate::prelude::SerenityError;

struct ChildContainer(Child);

impl Read for ChildContainer {
    fn read(&mut self, buffer: &mut [u8]) -> IoResult<usize> {
        self.0.stdout.as_mut().unwrap().read(buffer)
    }
}

impl Drop for ChildContainer {
    fn drop (&mut self) {
        if let Err(e) = self.0.kill() {
            debug!("[Voice] Error awaiting child process: {:?}", e);
        }
    }
}

// Since each audio item needs its own decoder, we need to
// work around the fact that OpusDecoders aint sendable.
struct SendDecoder(OpusDecoder);

impl SendDecoder {
    fn decode_float(&mut self, input: &[u8], output: &mut [f32], fec: bool) -> OpusResult<usize> {
        let &mut SendDecoder(ref mut sd) = self;
        sd.decode_float(input, output, fec)
    }
}

unsafe impl Send for SendDecoder {}

struct InputSource<R: Read + Send + 'static> {
    stereo: bool,
    reader: R,
    kind: AudioType,
    decoder: Option<Arc<Mutex<SendDecoder>>>,
}

impl<R: Read + Send> AudioSource for InputSource<R> {
    fn is_stereo(&mut self) -> bool { self.stereo }

    fn get_type(&self) -> AudioType { self.kind }

    fn read_pcm_frame(&mut self, buffer: &mut [i16]) -> Option<usize> {
        for (i, v) in buffer.iter_mut().enumerate() {
            *v = match self.reader.read_i16::<LittleEndian>() {
                Ok(v) => v,
                Err(ref e) => {
                    return if e.kind() == IoErrorKind::UnexpectedEof {
                        Some(i)
                    } else {
                        None
                    }
                },
            }
        }

        Some(buffer.len())
    }

    fn read_opus_frame(&mut self) -> Option<Vec<u8>> {
        match self.reader.read_i16::<LittleEndian>() {
            Ok(size) => {
                if size <= 0 {
                    warn!("Invalid opus frame size: {}", size);
                    return None;
                }

                let mut frame = Vec::with_capacity(size as usize);

                {
                    let reader = self.reader.by_ref();

                    if reader.take(size as u64).read_to_end(&mut frame).is_err() {
                        return None;
                    }
                }

                Some(frame)
            },
            Err(ref e) => if e.kind() == IoErrorKind::UnexpectedEof {
                Some(Vec::new())
            } else {
                None
            },
        }
    }

    fn decode_and_add_opus_frame(&mut self, float_buffer: &mut [f32; 1920], volume: f32) -> Option<usize> {
        let decoder_lock = self.decoder.as_mut()?.clone();
        let frame = self.read_opus_frame()?;
        let mut local_buf = [0f32; 960 * 2];

        let count = {
            let mut decoder = decoder_lock.lock();

            decoder.decode_float(frame.as_slice(), &mut local_buf, false).ok()?
        };

        for (i, float_buffer_element) in float_buffer.iter_mut().enumerate().take(1920) {
            *float_buffer_element += local_buf[i] * volume;
        }

        Some(count)
    }
}

/// Opens an audio file through `ffmpeg` and creates an audio source.
pub fn ffmpeg<P: AsRef<OsStr>>(path: P) -> Result<Box<dyn AudioSource>> {
    _ffmpeg(path.as_ref())
}

fn _ffmpeg(path: &OsStr) -> Result<Box<dyn AudioSource>> {
    // Will fail if the path is not to a file on the fs. Likely a YouTube URI.
    let is_stereo = is_stereo(path).unwrap_or(false);
    let stereo_val = if is_stereo { "2" } else { "1" };

    _ffmpeg_optioned(path, &[
        "-f",
        "s16le",
        "-ac",
        stereo_val,
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ], Some(is_stereo))
}

/// Opens an audio file through `ffmpeg` and creates an audio source, with
/// user-specified arguments to pass to ffmpeg.
///
/// Note that this does _not_ build on the arguments passed by the [`ffmpeg`]
/// function.
///
/// # Examples
///
/// Pass options to create a custom ffmpeg streamer:
///
/// ```rust,no_run
/// use serenity::voice;
///
/// let stereo_val = "2";
///
/// let streamer = voice::ffmpeg_optioned("./some_file.mp3", &[
///     "-f",
///     "s16le",
///     "-ac",
///     stereo_val,
///     "-ar",
///     "48000",
///     "-acodec",
///     "pcm_s16le",
///     "-",
/// ]);
pub fn ffmpeg_optioned<P: AsRef<OsStr>>(
    path: P,
    args: &[&str],
) -> Result<Box<dyn AudioSource>> {
    _ffmpeg_optioned(path.as_ref(), args, None)
}

fn _ffmpeg_optioned(path: &OsStr, args: &[&str], is_stereo_known: Option<bool>) -> Result<Box<dyn AudioSource>> {
    let is_stereo = is_stereo_known
        .or_else(|| is_stereo(path).ok())
        .unwrap_or(false);

    let command = Command::new("ffmpeg")
        .arg("-i")
        .arg(path)
        .args(args)
        .stderr(Stdio::null())
        .stdin(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(is_stereo, ChildContainer(command)))
}

/// Creates a streamed audio source from a DCA file.
/// Currently only accepts the DCA1 format.
pub fn dca<P: AsRef<OsStr>>(path: P) -> StdResult<Box<dyn AudioSource>, DcaError> {
    _dca(path.as_ref())
}

fn _dca(path: &OsStr) -> StdResult<Box<dyn AudioSource>, DcaError> {
    let file = File::open(path).map_err(DcaError::IoError)?;

    let mut reader = BufReader::new(file);

    let mut header = [0u8; 4];

    // Read in the magic number to verify it's a DCA file.
    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    if header != b"DCA1"[..] {
        return Err(DcaError::InvalidHeader);
    }

    reader.read_exact(&mut header).map_err(DcaError::IoError)?;

    let size = (&header[..]).read_i32::<LittleEndian>().unwrap();

    // Sanity check
    if size < 2 {
        return Err(DcaError::InvalidSize(size));
    }

    let mut raw_json = Vec::with_capacity(size as usize);

    {
        let json_reader = reader.by_ref();
        json_reader
            .take(size as u64)
            .read_to_end(&mut raw_json)
            .map_err(DcaError::IoError)?;
    }

    let metadata = serde_json::from_slice::<DcaMetadata>(raw_json.as_slice())
        .map_err(DcaError::InvalidMetadata)?;

    Ok(opus(metadata.is_stereo(), reader))
}

/// Creates an Opus audio source. This makes certain assumptions: namely, that the input stream
/// is composed ONLY of opus frames of the variety that Discord expects.
///
/// If you want to decode a `.opus` file, use [`ffmpeg`]
///
/// [`ffmpeg`]: fn.ffmpeg.html
pub fn opus<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<dyn AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader,
        kind: AudioType::Opus,
        decoder: Some(
            Arc::new(Mutex::new(
                // We always want to decode *to* stereo, for mixing reasons.
                SendDecoder(OpusDecoder::new(audio::SAMPLE_RATE, Channels::Stereo).unwrap())
            ))
        ),
    })
}

/// Creates a PCM audio source.
pub fn pcm<R: Read + Send + 'static>(is_stereo: bool, reader: R) -> Box<dyn AudioSource> {
    Box::new(InputSource {
        stereo: is_stereo,
        reader,
        kind: AudioType::Pcm,
        decoder: None,
    })
}

/// Creates a streamed audio source with `youtube-dl` and `ffmpeg`.
pub fn ytdl(uri: &str) -> Result<Box<dyn AudioSource>> {
    let ytdl_args = [
        "-f",
        "webm[abr>0]/bestaudio/best",
        "-R",
        "infinite",
        "--no-playlist",
        "--ignore-config",
        uri,
        "-o",
        "-"
    ];

    let ffmpeg_args = [
        "-f",
        "s16le",
        "-ac",
        "2",
        "-ar",
        "48000",
        "-acodec",
        "pcm_s16le",
        "-",
    ];

    let youtube_dl = Command::new("youtube-dl")
        .args(&ytdl_args)
        .stdin(Stdio::null())
        .stderr(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    let ffmpeg = Command::new("ffmpeg")
        .arg("-re")
        .arg("-i")
        .arg("-")
        .args(&ffmpeg_args)
        .stdin(youtube_dl.stdout.ok_or(SerenityError::Other("Failed to open youtube-dl stdout"))?)
        .stderr(Stdio::null())
        .stdout(Stdio::piped())
        .spawn()?;

    Ok(pcm(true, ChildContainer(ffmpeg)))
}

fn is_stereo(path: &OsStr) -> Result<bool> {
    let args = ["-v", "quiet", "-of", "json", "-show-streams", "-i"];

    let out = Command::new("ffprobe")
        .args(&args)
        .arg(path)
        .stdin(Stdio::null())
        .output()?;

    let value: Value = serde_json::from_reader(&out.stdout[..])?;

    let streams = value
        .as_object()
        .and_then(|m| m.get("streams"))
        .and_then(|v| v.as_array())
        .ok_or(Error::Voice(VoiceError::Streams))?;

    let check = streams.iter().any(|stream| {
        let channels = stream
            .as_object()
            .and_then(|m| m.get("channels").and_then(|v| v.as_i64()));

        channels == Some(2)
    });

    Ok(check)
}
<|endoftext|>


<commit_before>use protobuf::*;

use super::test_tokio_bytes_default_value_pb::*;

#[test]
fn test_default_values() {
    assert_eq!(
        "sss",
        TestTokioBytesDefaultValues::default_instance().get_s()
    );
    assert_eq!(
        b"bbb",
        TestTokioBytesDefaultValues::default_instance().get_b()
    );
    assert_eq!(&""[..], &**TestTokioBytesDefaultValues::new().mut_s());
    assert_eq!(&b""[..], &**TestTokioBytesDefaultValues::new().mut_b());
}
<commit_msg>Fix tests with bytes feature enabled<commit_after>use protobuf::*;

use super::test_tokio_bytes_default_value_pb::*;

#[test]
fn test_default_values() {
    assert_eq!("sss", TestTokioBytesDefaultValues::default_instance().s());
    assert_eq!(b"bbb", TestTokioBytesDefaultValues::default_instance().b());
    assert_eq!(&""[..], &**TestTokioBytesDefaultValues::new().mut_s());
    assert_eq!(&b""[..], &**TestTokioBytesDefaultValues::new().mut_b());
}
<|endoftext|>


<commit_before>use std::collections::{HashMap, HashSet};
use frontend::radeco_containers::RadecoFunction;
use middle::ir::MOpcode;
use middle::ssa::utils;
use middle::ssa::ssastorage::{NodeData, SSAStorage};
use middle::ssa::ssa_traits::{SSA, SSAExtra, SSAMod, SSAWalk, ValueInfo};
use middle::ssa::cfg_traits::CFG;
use super::c_simple_ast::{ValueNode, SimpleCAST};
use super::c_simple;
use petgraph::visit::EdgeRef;
use petgraph::graph::{Graph, NodeIndex, EdgeIndex, Edges, EdgeReference};
use petgraph::{EdgeDirection, Direction, Directed};

pub struct CASTDataGraph<'a> {
    rfn: &'a RadecoFunction,
    ssa: &'a SSAStorage,
    // Hashmap from node of SSAStorage to one of self.data_graph
    // a map from node of data_graph to one of SimpleCAST's value
    pub var_map: HashMap<NodeIndex, NodeIndex>,
    // a map from node of data_graph to one of SimpleCAST's register
    pub reg_map: HashMap<String, NodeIndex>,
    pub consts: HashSet<String>,
    seen: HashSet<NodeIndex>,
}

impl<'a> CASTDataGraph<'a> {
    pub fn new(rfn: &'a RadecoFunction) -> CASTDataGraph<'a> {
        CASTDataGraph {
            ssa: rfn.ssa(),
            rfn: rfn,
            var_map: HashMap::new(),
            reg_map: HashMap::new(),
            consts: HashSet::new(),
            seen: HashSet::new(),
        }
    }

    // Returns data map from SSAStorage's NodeIndex to SimpleCAST's NodeIndex
    // pub fn yo(ast: &'a mut SimpleCAST, ssa: &'a SSAStorage) -> HashMap<NodeIndex, NodeIndex> {
    pub fn yo(rfn: &'a RadecoFunction, ast: &mut SimpleCAST) -> Self {
        let mut s = Self::new(rfn);
        s.prepare_consts(ast);
        s.prepare_regs(ast);
        s.recover_data(ast);
        s
    }

    fn handle_binop(&mut self, ret_node: NodeIndex, ops: Vec<NodeIndex>,
                    expr: c_simple::Expr, ast: &mut SimpleCAST) {
        // XXX for debbuging, do not use filter_map
        let ops_mapped = ops.iter()
            .map(|op| self.var_map.get(op).map(|n| *n).unwrap_or(ast.unknown))
            .collect::<Vec<_>>();
        assert!(ops.len() == ops_mapped.len());
        let expr_node = ast.expr(ops_mapped.as_slice(), expr.clone());
        radeco_trace!("Add {:?} to {:?}, Operator: {:?}", ret_node, expr_node, expr);
        self.var_map.insert(ret_node, expr_node);
    }

    fn handle_uniop(&mut self, ret_node: NodeIndex, op: NodeIndex,
                    expr: c_simple::Expr, ast: &mut SimpleCAST) {
        if let Some(&n) = self.var_map.get(&op) {
            let expr_node = ast.expr(&[n], expr);
            self.var_map.insert(ret_node, expr_node);
        } else {
            radeco_warn!("Operand not found: {:?}", op);
        }
    }

    fn deref(&self, node: NodeIndex, ast: &mut SimpleCAST) -> NodeIndex {
        radeco_trace!("DeRef {:?}", node);
        let n = self.var_map.get(&node).expect("Cannot be None");
        ast.deref(*n)
    }

    fn handle_phi(&mut self, node: NodeIndex) {
        assert!(self.ssa.is_phi(node));
        radeco_trace!("CASTBuilder::handle_phi {:?}", node);
        if self.seen.contains(&node) {
            return;
        }
        let ops = self.ssa.operands_of(node);
        // TODO
        // XXX
        if let Some(&head) = ops.into_iter()
           .filter_map(|n| self.var_map.get(&n))
           .next() {
           self.var_map.insert(node, head);
        }
    }

    fn update_values(&mut self, ret_node: NodeIndex, ast: &mut SimpleCAST) {
        assert!(self.ssa.is_expr(ret_node));
        radeco_trace!("CASTBuilder::update_values {:?}", ret_node);
        if self.seen.contains(&ret_node) {
            return;
        }
        self.seen.insert(ret_node);
        let ops = self.ssa.operands_of(ret_node);

        radeco_trace!("CASTBuilder::update_values opcode: {:?}", self.ssa.opcode(ret_node));
        // TODO update
        match self.ssa.opcode(ret_node).unwrap_or(MOpcode::OpInvalid) {
            MOpcode::OpStore => {
                assert!(ops.len() == 3);
                let deref_node = self.deref(ops[1], ast);
            }
            MOpcode::OpLoad => {
                radeco_trace!("OpLoad: {:?}", ops);
                let deref_node = self.deref(ops[1], ast);
                self.var_map.insert(ret_node, deref_node);
            },
            MOpcode::OpAdd => self.handle_binop(ret_node, ops, c_simple::Expr::Add, ast),
            MOpcode::OpAnd => self.handle_binop(ret_node, ops, c_simple::Expr::And, ast),
            MOpcode::OpDiv => self.handle_binop(ret_node, ops, c_simple::Expr::Div, ast),
            MOpcode::OpEq => self.handle_binop(ret_node, ops, c_simple::Expr::Eq, ast),
            MOpcode::OpGt => self.handle_binop(ret_node, ops, c_simple::Expr::Gt, ast),
            // XXX Shl might be wrong operator
            MOpcode::OpLsl => self.handle_binop(ret_node, ops, c_simple::Expr::Shl, ast),
            // XXX Shr might be wrong operator
            MOpcode::OpLsr => self.handle_binop(ret_node, ops, c_simple::Expr::Shr, ast),
            MOpcode::OpLt => self.handle_binop(ret_node, ops, c_simple::Expr::Lt, ast),
            MOpcode::OpMod => self.handle_binop(ret_node, ops, c_simple::Expr::Mod, ast),
            MOpcode::OpMul => self.handle_binop(ret_node, ops, c_simple::Expr::Mul, ast),
            // TODO Add `Narrow` info
            MOpcode::OpNarrow(size) => self.handle_uniop(ret_node, ops[0],
                                                         c_simple::Expr::Cast(size as usize), ast),
            MOpcode::OpNot => self.handle_binop(ret_node, ops, c_simple::Expr::Not, ast),
            MOpcode::OpOr => self.handle_binop(ret_node, ops, c_simple::Expr::Or, ast),
            MOpcode::OpRol => unimplemented!(),
            MOpcode::OpRor => unimplemented!(),
            // TODO Add `SignExt`
            MOpcode::OpSignExt(size) => self.handle_uniop(ret_node, ops[0],
                                                          c_simple::Expr::Cast(size as usize), ast),
            MOpcode::OpSub => self.handle_binop(ret_node, ops, c_simple::Expr::Sub, ast),
            MOpcode::OpXor => self.handle_binop(ret_node, ops, c_simple::Expr::Xor, ast),
            // TODO Add `ZeroExt`
            MOpcode::OpZeroExt(size) => self.handle_uniop(ret_node, ops[0],
                                                          c_simple::Expr::Cast(size as usize), ast),
            MOpcode::OpCall => {
                self.update_data_graph_by_call(ret_node);
            },
            _ => {},
        }
    }
    fn update_data_graph_by_call(&mut self, call_node: NodeIndex) {
        radeco_trace!("CASTBuilder::update_data_graph_by_call {:?}", call_node);
        let reg_map = utils::call_rets(call_node, self.ssa);
        for (idx, (node, vt)) in reg_map.into_iter() {
            let name = self.ssa.regfile.get_name(idx).unwrap_or("mem").to_string();
            // TODO
        }
    }

    fn prepare_consts(&mut self, ast: &mut SimpleCAST) {
        for (&val, &node) in self.ssa.constants.iter() {
            if let Ok(n) = self.ssa.node_data(node) {
                // TODO add type
                let ast_node = ast.constant(&val.to_string(), None);
                self.consts.insert(val.to_string());
                self.var_map.insert(node, ast_node);
            } else {
                radeco_warn!("Invalid constant");
            }
        }
    }

    fn prepare_regs(&mut self, ast: &mut SimpleCAST) {
        let entry_node = self.ssa.entry_node();
        if entry_node.is_none() {
            radeco_warn!("Entry node not found");
            return;
        }
        for walk_node in self.ssa.inorder_walk() {
            // TODO avoid unwrap
            let reg_state = self.ssa.registers_in(walk_node);
            if reg_state.is_none() {
                radeco_warn!("RegisterState not found");
                return;
            }
            let reg_map = utils::register_state_info(reg_state.unwrap(), self.ssa);
            for (idx, (node, vt)) in reg_map.into_iter() {
                let name = self.ssa.regfile.get_name(idx).unwrap_or("mem").to_string();
                // XXX
                let ast_node = ast.constant(&name, None);
                // XXX
                self.reg_map.insert(name, ast_node);
                radeco_trace!("Add register {:?}", node);
                self.var_map.insert(node, ast_node);
            }
        }
    }

    fn recover_data(&mut self, ast: &mut SimpleCAST) {
        for node in self.ssa.inorder_walk() {
            if self.ssa.is_phi(node) {
                self.handle_phi(node);
            } else if self.ssa.is_expr(node) {
                self.update_values(node, ast);
            }
        }
    }

}

<commit_msg>replace some ssa nodes with register nodes<commit_after>use std::collections::{HashMap, HashSet};
use frontend::radeco_containers::RadecoFunction;
use middle::ir::MOpcode;
use middle::ssa::utils;
use middle::ssa::ssastorage::{NodeData, SSAStorage};
use middle::ssa::ssa_traits::{SSA, SSAExtra, SSAMod, SSAWalk, ValueInfo};
use middle::ssa::cfg_traits::CFG;
use super::c_simple_ast::{ValueNode, SimpleCAST};
use super::c_simple;
use petgraph::visit::EdgeRef;
use petgraph::graph::{Graph, NodeIndex, EdgeIndex, Edges, EdgeReference};
use petgraph::{EdgeDirection, Direction, Directed};

pub struct CASTDataGraph<'a> {
    rfn: &'a RadecoFunction,
    ssa: &'a SSAStorage,
    // Hashmap from node of SSAStorage to one of self.data_graph
    // a map from node of data_graph to one of SimpleCAST's value
    pub var_map: HashMap<NodeIndex, NodeIndex>,
    // a map from node of data_graph to one of SimpleCAST's register
    pub reg_map: HashMap<String, NodeIndex>,
    pub consts: HashSet<String>,
    seen: HashSet<NodeIndex>,
}

impl<'a> CASTDataGraph<'a> {
    pub fn new(rfn: &'a RadecoFunction) -> CASTDataGraph<'a> {
        CASTDataGraph {
            ssa: rfn.ssa(),
            rfn: rfn,
            var_map: HashMap::new(),
            reg_map: HashMap::new(),
            consts: HashSet::new(),
            seen: HashSet::new(),
        }
    }

    // Returns data map from SSAStorage's NodeIndex to SimpleCAST's NodeIndex
    // pub fn yo(ast: &'a mut SimpleCAST, ssa: &'a SSAStorage) -> HashMap<NodeIndex, NodeIndex> {
    pub fn yo(rfn: &'a RadecoFunction, ast: &mut SimpleCAST) -> Self {
        let mut s = Self::new(rfn);
        s.prepare_consts(ast);
        s.prepare_regs(ast);
        s.recover_data(ast);
        s
    }

    fn handle_binop(&mut self, ret_node: NodeIndex, ops: Vec<NodeIndex>,
                    expr: c_simple::Expr, ast: &mut SimpleCAST) {
        // XXX for debbuging, do not use filter_map
        let ops_mapped = ops.iter()
            .map(|op| self.var_map.get(op).map(|n| *n).unwrap_or(ast.unknown))
            .collect::<Vec<_>>();
        assert!(ops.len() == ops_mapped.len());
        let expr_node = ast.expr(ops_mapped.as_slice(), expr.clone());
        radeco_trace!("Add {:?} to {:?}, Operator: {:?}", ret_node, expr_node, expr);
        self.var_map.insert(ret_node, expr_node);
    }

    fn handle_uniop(&mut self, ret_node: NodeIndex, op: NodeIndex,
                    expr: c_simple::Expr, ast: &mut SimpleCAST) {
        if let Some(&n) = self.var_map.get(&op) {
            let expr_node = ast.expr(&[n], expr);
            self.var_map.insert(ret_node, expr_node);
        } else {
            radeco_warn!("Operand not found: {:?}", op);
        }
    }

    fn deref(&self, node: NodeIndex, ast: &mut SimpleCAST) -> NodeIndex {
        radeco_trace!("DeRef {:?}", node);
        let n = self.var_map.get(&node).expect("Cannot be None");
        ast.deref(*n)
    }

    fn handle_phi(&mut self, node: NodeIndex) {
        assert!(self.ssa.is_phi(node));
        radeco_trace!("CASTBuilder::handle_phi {:?}", node);
        if self.seen.contains(&node) {
            return;
        }
        let ops = self.ssa.operands_of(node);
        // TODO
        // XXX
        if let Some(&head) = ops.into_iter()
           .filter_map(|n| self.var_map.get(&n))
           .next() {
           self.var_map.insert(node, head);
        }
    }

    fn update_values(&mut self, ret_node: NodeIndex, ast: &mut SimpleCAST) {
        assert!(self.ssa.is_expr(ret_node));
        radeco_trace!("CASTBuilder::update_values {:?}", ret_node);
        if self.seen.contains(&ret_node) {
            return;
        }
        self.seen.insert(ret_node);
        let regs = self.ssa.registers(ret_node);
        if regs.len() > 0 {
            let ast_node = ast.constant(&regs[0], None);
            self.var_map.insert(ret_node, ast_node);
            return;
        }
        let ops = self.ssa.operands_of(ret_node);

        radeco_trace!("CASTBuilder::update_values opcode: {:?}", self.ssa.opcode(ret_node));
        // TODO update
        match self.ssa.opcode(ret_node).unwrap_or(MOpcode::OpInvalid) {
            MOpcode::OpStore => {
                assert!(ops.len() == 3);
                let deref_node = self.deref(ops[1], ast);
            }
            MOpcode::OpLoad => {
                radeco_trace!("OpLoad: {:?}", ops);
                let deref_node = self.deref(ops[1], ast);
                self.var_map.insert(ret_node, deref_node);
            },
            MOpcode::OpAdd => self.handle_binop(ret_node, ops, c_simple::Expr::Add, ast),
            MOpcode::OpAnd => self.handle_binop(ret_node, ops, c_simple::Expr::And, ast),
            MOpcode::OpDiv => self.handle_binop(ret_node, ops, c_simple::Expr::Div, ast),
            MOpcode::OpEq => self.handle_binop(ret_node, ops, c_simple::Expr::Eq, ast),
            MOpcode::OpGt => self.handle_binop(ret_node, ops, c_simple::Expr::Gt, ast),
            // XXX Shl might be wrong operator
            MOpcode::OpLsl => self.handle_binop(ret_node, ops, c_simple::Expr::Shl, ast),
            // XXX Shr might be wrong operator
            MOpcode::OpLsr => self.handle_binop(ret_node, ops, c_simple::Expr::Shr, ast),
            MOpcode::OpLt => self.handle_binop(ret_node, ops, c_simple::Expr::Lt, ast),
            MOpcode::OpMod => self.handle_binop(ret_node, ops, c_simple::Expr::Mod, ast),
            MOpcode::OpMul => self.handle_binop(ret_node, ops, c_simple::Expr::Mul, ast),
            // TODO Add `Narrow` info
            MOpcode::OpNarrow(size) => self.handle_uniop(ret_node, ops[0],
                                                         c_simple::Expr::Cast(size as usize), ast),
            MOpcode::OpNot => self.handle_binop(ret_node, ops, c_simple::Expr::Not, ast),
            MOpcode::OpOr => self.handle_binop(ret_node, ops, c_simple::Expr::Or, ast),
            MOpcode::OpRol => unimplemented!(),
            MOpcode::OpRor => unimplemented!(),
            // TODO Add `SignExt`
            MOpcode::OpSignExt(size) => self.handle_uniop(ret_node, ops[0],
                                                          c_simple::Expr::Cast(size as usize), ast),
            MOpcode::OpSub => self.handle_binop(ret_node, ops, c_simple::Expr::Sub, ast),
            MOpcode::OpXor => self.handle_binop(ret_node, ops, c_simple::Expr::Xor, ast),
            // TODO Add `ZeroExt`
            MOpcode::OpZeroExt(size) => self.handle_uniop(ret_node, ops[0],
                                                          c_simple::Expr::Cast(size as usize), ast),
            MOpcode::OpCall => {
                self.update_data_graph_by_call(ret_node);
            },
            _ => {},
        }
    }
    fn update_data_graph_by_call(&mut self, call_node: NodeIndex) {
        radeco_trace!("CASTBuilder::update_data_graph_by_call {:?}", call_node);
        let reg_map = utils::call_rets(call_node, self.ssa);
        for (idx, (node, vt)) in reg_map.into_iter() {
            let name = self.ssa.regfile.get_name(idx).unwrap_or("mem").to_string();
            // TODO
        }
    }

    fn prepare_consts(&mut self, ast: &mut SimpleCAST) {
        for (&val, &node) in self.ssa.constants.iter() {
            if let Ok(n) = self.ssa.node_data(node) {
                // TODO add type
                let ast_node = ast.constant(&val.to_string(), None);
                self.consts.insert(val.to_string());
                self.var_map.insert(node, ast_node);
            } else {
                radeco_warn!("Invalid constant");
            }
        }
    }

    fn prepare_regs(&mut self, ast: &mut SimpleCAST) {
        for walk_node in self.ssa.inorder_walk() {
            // TODO avoid unwrap
            let reg_state = self.ssa.registers_in(walk_node);
            if reg_state.is_none() {
                continue;
            }
            let reg_map = utils::register_state_info(reg_state.unwrap(), self.ssa);
            for (idx, (node, vt)) in reg_map.into_iter() {
                let name = self.ssa.regfile.get_name(idx).unwrap_or("mem").to_string();
                // XXX
                let ast_node = ast.constant(&name, None);
                // XXX
                self.reg_map.insert(name, ast_node);
                radeco_trace!("Add register {:?}", node);
                self.var_map.insert(node, ast_node);
            }
        }
    }

    fn recover_data(&mut self, ast: &mut SimpleCAST) {
        for node in self.ssa.inorder_walk() {
            if self.ssa.is_phi(node) {
                self.handle_phi(node);
            } else if self.ssa.is_expr(node) {
                self.update_values(node, ast);
            }
        }
    }

}

<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::collections::hash_map::Entry;

const LIBRARY: [char; 4] = ['A', 'C', 'G', 'T'];

pub fn count(c: char, seq: &str) -> Result<usize, String> {
    if LIBRARY.contains(&c) && seq.chars().all(|x| LIBRARY.contains(&x)) {
        Ok(seq.chars().filter(|x| x == &c).count())
    } else {
        Err("Not a nucleotide!".to_owned())
    }
}

pub fn nucleotide_counts(seq: &str) -> Result<HashMap<char, usize>, String> {
    let mut result = HashMap::new();
    result.insert(LIBRARY[0], 0);
    result.insert(LIBRARY[1], 0);
    result.insert(LIBRARY[2], 0);
    result.insert(LIBRARY[3], 0);

    for c in seq.chars() {
        match result.entry(c) {
            Entry::Occupied(mut entry) => *entry.get_mut() += 1,
            _ => return Err("Non-nucleotide in sequence!".to_owned()),
        }
    };

    Ok(result)
}
<commit_msg>Improve nucleotide code by only iterating sequence once instead of twice in count()<commit_after>use std::collections::HashMap;
use std::collections::hash_map::Entry;

const LIBRARY: [char; 4] = ['A', 'C', 'G', 'T'];

pub fn count(c: char, seq: &str) -> Result<usize, String> {
    if !LIBRARY.contains(&c) {
        return Err("Not a nucleotide!".to_owned());
    }

    let mut count = 0;
    for x in seq.chars() {
        if !LIBRARY.contains(&x) {
            return Err("Non-nucleotide in sequence!".to_owned());
        }

        if x == c {
            count += 1;
        }
    }
    Ok(count)
}

pub fn nucleotide_counts(seq: &str) -> Result<HashMap<char, usize>, String> {
    let mut result = HashMap::new();
    result.insert(LIBRARY[0], 0);
    result.insert(LIBRARY[1], 0);
    result.insert(LIBRARY[2], 0);
    result.insert(LIBRARY[3], 0);

    for c in seq.chars() {
        match result.entry(c) {
            Entry::Occupied(mut entry) => *entry.get_mut() += 1,
            _ => return Err("Non-nucleotide in sequence!".to_owned()),
        }
    }

    Ok(result)
}
<|endoftext|>


<commit_before>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::ops::BitOr;
use vk;

/// Describes how an image is going to be used. This is **not** an optimization.
///
/// If you try to use an image in a way that you didn't declare, a panic will happen.
///
/// If `transient_attachment` is true, then only `color_attachment`, `depth_stencil_attachment`
/// and `input_attachment` can be true as well. The rest must be false or an error will be returned
/// when creating the image.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ImageUsage {
    /// Can be used a source for transfers. Includes blits.
    pub transfer_source: bool,

    /// Can be used a destination for transfers. Includes blits.
    pub transfer_dest: bool,

    /// Can be sampled from a shader.
    pub sampled: bool,

    /// Can be used as an image storage in a shader.
    pub storage: bool,

    /// Can be attached as a color attachment to a framebuffer.
    pub color_attachment: bool,

    /// Can be attached as a depth, stencil or depth-stencil attachment to a framebuffer.
    pub depth_stencil_attachment: bool,

    /// Indicates that this image will only ever be used as a temporary framebuffer attachment.
    /// As soon as you leave a render pass, the content of transient images becomes undefined.
    ///
    /// This is a hint to the Vulkan implementation that it may not need allocate any memory for
    /// this image if the image can live entirely in some cache.
    pub transient_attachment: bool,

    /// Can be used as an input attachment. In other words, you can draw to it in a subpass then
    /// read from it in a following pass.
    pub input_attachment: bool,
}

impl ImageUsage {
    /// Builds a `ImageUsage` with all values set to true. Note that using the returned value will
    /// produce an error because of `transient_attachment` being true.
    #[inline]
    pub fn all() -> ImageUsage {
        ImageUsage {
            transfer_source: true,
            transfer_dest: true,
            sampled: true,
            storage: true,
            color_attachment: true,
            depth_stencil_attachment: true,
            transient_attachment: true,
            input_attachment: true,
        }
    }

    /// Builds a `ImageUsage` with all values set to false. Useful as a default value.
    ///
    /// # Example
    ///
    /// ```rust
    /// use vulkano::image::ImageUsage as ImageUsage;
    ///
    /// let _usage = ImageUsage {
    ///     transfer_dest: true,
    ///     sampled: true,
    ///     .. ImageUsage::none()
    /// };
    /// ```
    #[inline]
    pub fn none() -> ImageUsage {
        ImageUsage {
            transfer_source: false,
            transfer_dest: false,
            sampled: false,
            storage: false,
            color_attachment: false,
            depth_stencil_attachment: false,
            transient_attachment: false,
            input_attachment: false,
        }
    }

    #[doc(hidden)]
    #[inline]
    pub fn to_usage_bits(&self) -> vk::ImageUsageFlagBits {
        let mut result = 0;
        if self.transfer_source { result |= vk::IMAGE_USAGE_TRANSFER_SRC_BIT; }
        if self.transfer_dest { result |= vk::IMAGE_USAGE_TRANSFER_DST_BIT; }
        if self.sampled { result |= vk::IMAGE_USAGE_SAMPLED_BIT; }
        if self.storage { result |= vk::IMAGE_USAGE_STORAGE_BIT; }
        if self.color_attachment { result |= vk::IMAGE_USAGE_COLOR_ATTACHMENT_BIT; }
        if self.depth_stencil_attachment { result |= vk::IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; }
        if self.transient_attachment { result |= vk::IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; }
        if self.input_attachment { result |= vk::IMAGE_USAGE_INPUT_ATTACHMENT_BIT; }
        result
    }

    #[inline]
    #[doc(hidden)]
    pub fn from_bits(val: u32) -> ImageUsage {
        ImageUsage {
            transfer_source: (val & vk::IMAGE_USAGE_TRANSFER_SRC_BIT) != 0,
            transfer_dest: (val & vk::IMAGE_USAGE_TRANSFER_DST_BIT) != 0,
            sampled: (val & vk::IMAGE_USAGE_SAMPLED_BIT) != 0,
            storage: (val & vk::IMAGE_USAGE_STORAGE_BIT) != 0,
            color_attachment: (val & vk::IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0,
            depth_stencil_attachment: (val & vk::IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0,
            transient_attachment: (val & vk::IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0,
            input_attachment: (val & vk::IMAGE_USAGE_INPUT_ATTACHMENT_BIT) != 0,
        }
    }
}

impl BitOr for ImageUsage {
    type Output = Self;

    #[inline]
    fn bitor(self, rhs: Self) -> Self {
        ImageUsage {
            transfer_source: self.transfer_source || rhs.transfer_source,
            transfer_dest: self.transfer_dest || rhs.transfer_dest,
            sampled: self.sampled || rhs.sampled,
            storage: self.storage || rhs.storage,
            color_attachment: self.color_attachment || rhs.color_attachment,
            depth_stencil_attachment: self.depth_stencil_attachment || rhs.depth_stencil_attachment,
            transient_attachment: self.transient_attachment || rhs.transient_attachment,
            input_attachment: self.input_attachment || rhs.input_attachment,
        }
    }
}
<commit_msg>Add minor TODO<commit_after>// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

use std::ops::BitOr;
use vk;

/// Describes how an image is going to be used. This is **not** an optimization.
///
/// If you try to use an image in a way that you didn't declare, a panic will happen.
///
/// If `transient_attachment` is true, then only `color_attachment`, `depth_stencil_attachment`
/// and `input_attachment` can be true as well. The rest must be false or an error will be returned
/// when creating the image.
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub struct ImageUsage {
    /// Can be used a source for transfers. Includes blits.
    pub transfer_source: bool,

    /// Can be used a destination for transfers. Includes blits.
    pub transfer_dest: bool,

    /// Can be sampled from a shader.
    pub sampled: bool,

    /// Can be used as an image storage in a shader.
    pub storage: bool,

    /// Can be attached as a color attachment to a framebuffer.
    pub color_attachment: bool,

    /// Can be attached as a depth, stencil or depth-stencil attachment to a framebuffer.
    pub depth_stencil_attachment: bool,

    /// Indicates that this image will only ever be used as a temporary framebuffer attachment.
    /// As soon as you leave a render pass, the content of transient images becomes undefined.
    ///
    /// This is a hint to the Vulkan implementation that it may not need allocate any memory for
    /// this image if the image can live entirely in some cache.
    pub transient_attachment: bool,

    /// Can be used as an input attachment. In other words, you can draw to it in a subpass then
    /// read from it in a following pass.
    pub input_attachment: bool,
}

impl ImageUsage {
    /// Builds a `ImageUsage` with all values set to true. Note that using the returned value will
    /// produce an error because of `transient_attachment` being true.
    #[inline]
    pub fn all() -> ImageUsage {
        ImageUsage {
            transfer_source: true,
            transfer_dest: true,
            sampled: true,
            storage: true,
            color_attachment: true,
            depth_stencil_attachment: true,
            transient_attachment: true,
            input_attachment: true,
        }
    }

    /// Builds a `ImageUsage` with all values set to false. Useful as a default value.
    ///
    /// # Example
    ///
    /// ```rust
    /// use vulkano::image::ImageUsage as ImageUsage;
    ///
    /// let _usage = ImageUsage {
    ///     transfer_dest: true,
    ///     sampled: true,
    ///     .. ImageUsage::none()
    /// };
    /// ```
    #[inline]
    pub fn none() -> ImageUsage {
        ImageUsage {
            transfer_source: false,
            transfer_dest: false,
            sampled: false,
            storage: false,
            color_attachment: false,
            depth_stencil_attachment: false,
            transient_attachment: false,
            input_attachment: false,
        }
    }

    // TODO: these functions shouldn't be public-hidden
    #[doc(hidden)]
    #[inline]
    pub fn to_usage_bits(&self) -> vk::ImageUsageFlagBits {
        let mut result = 0;
        if self.transfer_source { result |= vk::IMAGE_USAGE_TRANSFER_SRC_BIT; }
        if self.transfer_dest { result |= vk::IMAGE_USAGE_TRANSFER_DST_BIT; }
        if self.sampled { result |= vk::IMAGE_USAGE_SAMPLED_BIT; }
        if self.storage { result |= vk::IMAGE_USAGE_STORAGE_BIT; }
        if self.color_attachment { result |= vk::IMAGE_USAGE_COLOR_ATTACHMENT_BIT; }
        if self.depth_stencil_attachment { result |= vk::IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; }
        if self.transient_attachment { result |= vk::IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT; }
        if self.input_attachment { result |= vk::IMAGE_USAGE_INPUT_ATTACHMENT_BIT; }
        result
    }

    // TODO: these functions shouldn't be public-hidden
    #[inline]
    #[doc(hidden)]
    pub fn from_bits(val: u32) -> ImageUsage {
        ImageUsage {
            transfer_source: (val & vk::IMAGE_USAGE_TRANSFER_SRC_BIT) != 0,
            transfer_dest: (val & vk::IMAGE_USAGE_TRANSFER_DST_BIT) != 0,
            sampled: (val & vk::IMAGE_USAGE_SAMPLED_BIT) != 0,
            storage: (val & vk::IMAGE_USAGE_STORAGE_BIT) != 0,
            color_attachment: (val & vk::IMAGE_USAGE_COLOR_ATTACHMENT_BIT) != 0,
            depth_stencil_attachment: (val & vk::IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0,
            transient_attachment: (val & vk::IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) != 0,
            input_attachment: (val & vk::IMAGE_USAGE_INPUT_ATTACHMENT_BIT) != 0,
        }
    }
}

impl BitOr for ImageUsage {
    type Output = Self;

    #[inline]
    fn bitor(self, rhs: Self) -> Self {
        ImageUsage {
            transfer_source: self.transfer_source || rhs.transfer_source,
            transfer_dest: self.transfer_dest || rhs.transfer_dest,
            sampled: self.sampled || rhs.sampled,
            storage: self.storage || rhs.storage,
            color_attachment: self.color_attachment || rhs.color_attachment,
            depth_stencil_attachment: self.depth_stencil_attachment || rhs.depth_stencil_attachment,
            transient_attachment: self.transient_attachment || rhs.transient_attachment,
            input_attachment: self.input_attachment || rhs.input_attachment,
        }
    }
}
<|endoftext|>


<commit_before>use super::treenode::*;
use super::values::*;
use std::rc::*;

///
/// BasicTree is a basic in-memory tree node
///
pub struct BasicTree {
    tag: String,
    value: TreeValue,

    child: Option<Rc<TreeNode>>,
    sibling: Option<Rc<TreeNode>>
}

impl BasicTree {
    ///
    /// Creates a new tree node with a particular tag and no siblings
    ///
    pub fn new<TValue: ToTreeValue>(tag: &str, value: TValue) -> BasicTree {
        BasicTree { tag: tag.to_string(), value: value.to_tree_value(), child: None, sibling: None }
    }

    ///
    /// Copies a node into a new basic node
    ///
    pub fn from<TNode: ToTreeNode>(node: TNode) -> BasicTree {
        let as_tree_node    = node.to_tree_node();
        let child           = (*as_tree_node).get_child_ref().map(|n| (*n).to_owned());
        let sibling         = (*as_tree_node).get_sibling_ref().map(|n| (*n).to_owned());

        BasicTree {
            tag:        (*as_tree_node).get_tag().to_owned(),
            value:      (*as_tree_node).get_value().to_owned(),
            child:      child,
            sibling:    sibling
        }
    }
}

impl TreeNode for BasicTree {
    ///
    /// Retrieves a reference to the child of this tree node (or None if this node has no child)
    ///
    fn get_child_ref(&self) -> Option<&Rc<TreeNode>> {
        match self.child {
            Some(ref child) => Some(child),
            None => None
        }
    }

    ///
    /// Retrieves a reference to the sibling of this tree node (or None if this node has no sibling)
    ///
    fn get_sibling_ref(&self) -> Option<&Rc<TreeNode>> {
        match self.sibling {
            Some(ref sibling) => Some(sibling),
            None => None
        }
    }

    ///
    /// Retrieves the tag attached to this tree node
    ///
    fn get_tag(&self) -> &str {
        &self.tag
    }

    ///
    /// Retrieves the value attached to this node
    ///
    fn get_value(&self) -> &TreeValue {
        &self.value
    }
}

impl MutableTreeNode for BasicTree {
    ///
    /// Sets the child for this tree node
    ///
    fn set_child_ref(&mut self, new_node: Rc<TreeNode>) {
        self.child = Some(new_node);
    }

    ///
    /// Sets the sibling for this tree node
    ///
    fn set_sibling_ref(&mut self, new_node: Rc<TreeNode>) {
        self.sibling = Some(new_node);
    }

    ///
    /// Unsets the child for this node
    ///
    fn clear_child(&mut self) {
        self.child = None;
    }

    ///
    /// Unsets the sibling for this node
    ///
    fn clear_sibling(&mut self) {
        self.sibling = None;
    }

    ///
    /// Changes the value set for this node.
    ///
    fn set_tree_value(&mut self, new_value: TreeValue) {
        self.value = new_value;
    }

    ///
    /// Changes the tag attached to this tree
    ///
    fn set_tag(&mut self, new_tag: &str) {
        self.tag = new_tag.to_string();
    }
}

impl<'a> ToTreeNode for &'a str {
    fn to_tree_node(&self) -> Rc<TreeNode> {
        Rc::new(BasicTree::new(self, ()))
    }
}

impl<'a, TValue: ToTreeValue> ToTreeNode for (&'a str, TValue) {
    fn to_tree_node(&self) -> Rc<TreeNode> {
        let (ref tag, ref value) = *self;
        Rc::new(BasicTree::new(tag, value.to_tree_value()))
    }
}

#[cfg(test)]
mod basictree_tests {
    use super::*;
    use super::super::values::*;
    use super::super::treenode::*;
    use std::rc::*;

    #[test]
    fn can_create_basictree() {
        let tree = BasicTree::new("test", ());

        assert!(tree.get_tag() == "test");
        assert!(tree.get_value().is_nothing());
        assert!(tree.get_child_ref().is_none());
        assert!(tree.get_sibling_ref().is_none());
    }

    #[test]
    fn value_is_set() {
        let tree = BasicTree::new("test", 1);

        assert!(tree.get_tag() == "test");
        assert!(!tree.get_value().is_nothing());
    }

    #[test]
    fn can_set_child() {
        let mut tree = BasicTree::new("test", ());

        tree.set_child(("child", "childvalue"));

        assert!(tree.get_child_ref().is_some());
        assert!((tree.get_child_ref().unwrap().get_tag()) == "child");
        assert!(tree.get_sibling_ref().is_none());
    }

    #[test]
    fn can_set_sibling() {
        let mut tree = BasicTree::new("test", ());
        let sibling = Rc::new(BasicTree::new("sibling", ()));

        tree.set_sibling_ref(sibling);

        assert!(tree.get_sibling_ref().is_some());
        assert!((tree.get_sibling_ref().unwrap().get_tag()) == "sibling");
        assert!(tree.get_child_ref().is_none());
    }

    #[test]
    fn can_set_tag() {
        let mut tree = BasicTree::new("test", ());

        tree.set_tag("newtag");

        assert!(tree.get_tag() == "newtag");
    }

    #[test]
    fn can_set_value() {
        let mut tree = BasicTree::new("test", ());

        assert!(tree.get_value().is_nothing());

        tree.set_tree_value(TreeValue::String("Some value".to_string()));

        assert!(match *tree.get_value() { TreeValue::String(ref x) => x == "Some value", _ => false });
    }

    #[test]
    fn can_clone_from() {
        let tree = "tree".to_tree_node();
        let copy = BasicTree::from(tree);

        assert!(copy.get_tag() == "tree");
    }
}
<commit_msg>Make BasicTree clonable<commit_after>use super::treenode::*;
use super::values::*;
use std::rc::*;

///
/// BasicTree is a basic in-memory tree node
///
pub struct BasicTree {
    tag: String,
    value: TreeValue,

    child: Option<Rc<TreeNode>>,
    sibling: Option<Rc<TreeNode>>
}

impl BasicTree {
    ///
    /// Creates a new tree node with a particular tag and no siblings
    ///
    pub fn new<TValue: ToTreeValue>(tag: &str, value: TValue) -> BasicTree {
        BasicTree { tag: tag.to_string(), value: value.to_tree_value(), child: None, sibling: None }
    }

    ///
    /// Copies a node into a new basic node
    ///
    pub fn from<TNode: ToTreeNode>(node: TNode) -> BasicTree {
        let as_tree_node    = node.to_tree_node();
        let child           = (*as_tree_node).get_child_ref().map(|n| (*n).to_owned());
        let sibling         = (*as_tree_node).get_sibling_ref().map(|n| (*n).to_owned());

        BasicTree {
            tag:        (*as_tree_node).get_tag().to_owned(),
            value:      (*as_tree_node).get_value().to_owned(),
            child:      child,
            sibling:    sibling
        }
    }
}

impl TreeNode for BasicTree {
    ///
    /// Retrieves a reference to the child of this tree node (or None if this node has no child)
    ///
    fn get_child_ref(&self) -> Option<&Rc<TreeNode>> {
        match self.child {
            Some(ref child) => Some(child),
            None => None
        }
    }

    ///
    /// Retrieves a reference to the sibling of this tree node (or None if this node has no sibling)
    ///
    fn get_sibling_ref(&self) -> Option<&Rc<TreeNode>> {
        match self.sibling {
            Some(ref sibling) => Some(sibling),
            None => None
        }
    }

    ///
    /// Retrieves the tag attached to this tree node
    ///
    fn get_tag(&self) -> &str {
        &self.tag
    }

    ///
    /// Retrieves the value attached to this node
    ///
    fn get_value(&self) -> &TreeValue {
        &self.value
    }
}

impl MutableTreeNode for BasicTree {
    ///
    /// Sets the child for this tree node
    ///
    fn set_child_ref(&mut self, new_node: Rc<TreeNode>) {
        self.child = Some(new_node);
    }

    ///
    /// Sets the sibling for this tree node
    ///
    fn set_sibling_ref(&mut self, new_node: Rc<TreeNode>) {
        self.sibling = Some(new_node);
    }

    ///
    /// Unsets the child for this node
    ///
    fn clear_child(&mut self) {
        self.child = None;
    }

    ///
    /// Unsets the sibling for this node
    ///
    fn clear_sibling(&mut self) {
        self.sibling = None;
    }

    ///
    /// Changes the value set for this node.
    ///
    fn set_tree_value(&mut self, new_value: TreeValue) {
        self.value = new_value;
    }

    ///
    /// Changes the tag attached to this tree
    ///
    fn set_tag(&mut self, new_tag: &str) {
        self.tag = new_tag.to_string();
    }
}

impl Clone for BasicTree {
    fn clone(&self) -> BasicTree {
        BasicTree {
            tag:        self.tag.to_owned(),
            value:      self.value.to_owned(),
            child:      self.child.to_owned(),
            sibling:    self.sibling.to_owned() }
    }
}

impl<'a> ToTreeNode for &'a str {
    fn to_tree_node(&self) -> Rc<TreeNode> {
        Rc::new(BasicTree::new(self, ()))
    }
}

impl<'a, TValue: ToTreeValue> ToTreeNode for (&'a str, TValue) {
    fn to_tree_node(&self) -> Rc<TreeNode> {
        let (ref tag, ref value) = *self;
        Rc::new(BasicTree::new(tag, value.to_tree_value()))
    }
}

#[cfg(test)]
mod basictree_tests {
    use super::*;
    use super::super::values::*;
    use super::super::treenode::*;
    use std::rc::*;

    #[test]
    fn can_create_basictree() {
        let tree = BasicTree::new("test", ());

        assert!(tree.get_tag() == "test");
        assert!(tree.get_value().is_nothing());
        assert!(tree.get_child_ref().is_none());
        assert!(tree.get_sibling_ref().is_none());
    }

    #[test]
    fn value_is_set() {
        let tree = BasicTree::new("test", 1);

        assert!(tree.get_tag() == "test");
        assert!(!tree.get_value().is_nothing());
    }

    #[test]
    fn can_set_child() {
        let mut tree = BasicTree::new("test", ());

        tree.set_child(("child", "childvalue"));

        assert!(tree.get_child_ref().is_some());
        assert!((tree.get_child_ref().unwrap().get_tag()) == "child");
        assert!(tree.get_sibling_ref().is_none());
    }

    #[test]
    fn can_set_sibling() {
        let mut tree = BasicTree::new("test", ());
        let sibling = Rc::new(BasicTree::new("sibling", ()));

        tree.set_sibling_ref(sibling);

        assert!(tree.get_sibling_ref().is_some());
        assert!((tree.get_sibling_ref().unwrap().get_tag()) == "sibling");
        assert!(tree.get_child_ref().is_none());
    }

    #[test]
    fn can_set_tag() {
        let mut tree = BasicTree::new("test", ());

        tree.set_tag("newtag");

        assert!(tree.get_tag() == "newtag");
    }

    #[test]
    fn can_set_value() {
        let mut tree = BasicTree::new("test", ());

        assert!(tree.get_value().is_nothing());

        tree.set_tree_value(TreeValue::String("Some value".to_string()));

        assert!(match *tree.get_value() { TreeValue::String(ref x) => x == "Some value", _ => false });
    }

    #[test]
    fn can_clone_from() {
        let tree = "tree".to_tree_node();
        let copy = BasicTree::from(tree);

        assert!(copy.get_tag() == "tree");
    }
}
<|endoftext|>