<commit_before>use common::types::Types;
use common::conn::Conn;
use common::stream::HttpStreamCommon;
use common::stream::HttpStreamData;
use solicit::connection::HttpFrame;
use solicit::StreamId;

use data_or_headers_with_flag::DataOrHeadersWithFlag;

use error;
use ErrorCode;
use solicit::frame::RstStreamFrame;
use solicit::frame::GoawayFrame;
use solicit::frame::WindowUpdateFrame;
use solicit::frame::PingFrame;
use solicit::frame::SettingsFrame;
use result;
use futures::Poll;
use futures::Async;
use common::conn_read::ConnReadSideCustom;
use common::conn_command::ConnCommandSideCustom;
use common::stream::HttpStreamCommand;
use solicit::frame::FrameBuilder;
use std::cmp;
use solicit::frame::HeadersFrame;
use solicit::connection::EndStream;
use solicit::frame::HeadersFlag;
use solicit::frame::ContinuationFrame;
use solicit::frame::continuation::ContinuationFlag;
use solicit::frame::DataFrame;
use solicit::frame::DataFlag;
use solicit::frame::FrameIR;
use std::mem;

pub enum DirectlyToNetworkFrame {
    RstStream(RstStreamFrame),
    GoAway(GoawayFrame),
    WindowUpdate(WindowUpdateFrame),
    Ping(PingFrame),
    Settings(SettingsFrame),
}

impl DirectlyToNetworkFrame {
    pub fn into_http_frame(self) -> HttpFrame {
        match self {
            DirectlyToNetworkFrame::RstStream(f) => f.into(),
            DirectlyToNetworkFrame::GoAway(f) => f.into(),
            DirectlyToNetworkFrame::WindowUpdate(f) => f.into(),
            DirectlyToNetworkFrame::Ping(f) => f.into(),
            DirectlyToNetworkFrame::Settings(f) => f.into(),
        }
    }
}

pub trait ConnWriteSideCustom {
    type Types : Types;

    fn process_message(&mut self, message: <Self::Types as Types>::ToWriteMessage) -> result::Result<()>;
}

impl<T> Conn<T>
    where
        T : Types,
        Self : ConnReadSideCustom<Types=T>,
        Self : ConnWriteSideCustom<Types=T>,
        Self : ConnCommandSideCustom<Types=T>,
        HttpStreamCommon<T> : HttpStreamData<Types=T>,
{
    fn poll_flush(&mut self) -> Poll<(), error::Error> {
        self.framed_write.poll_flush()
    }

    fn write_part(&mut self, target: &mut FrameBuilder, stream_id: StreamId, part: HttpStreamCommand) {
        let max_frame_size = self.peer_settings.max_frame_size as usize;

        match part {
            HttpStreamCommand::Data(data, end_stream) => {
                // if client requested end of stream,
                // we must send at least one frame with end stream flag
                if end_stream == EndStream::Yes && data.len() == 0 {
                    // probably should send RST_STREAM
                    let mut frame = DataFrame::with_data(stream_id, Vec::new());
                    frame.set_flag(DataFlag::EndStream);

                    debug!("sending frame {:?}", frame);

                    frame.serialize_into(target);
                    return;
                }

                let mut pos = 0;
                while pos < data.len() {
                    let end = cmp::min(data.len(), pos + max_frame_size);

                    let end_stream_in_frame =
                        if end == data.len() && end_stream == EndStream::Yes {
                            EndStream::Yes
                        } else {
                            EndStream::No
                        };

                    let mut frame = DataFrame::with_data(stream_id, data.slice(pos, end));
                    if end_stream_in_frame == EndStream::Yes {
                        frame.set_flag(DataFlag::EndStream);
                    }

                    debug!("sending frame {:?}", frame);

                    frame.serialize_into(target);

                    pos = end;
                }
            }
            HttpStreamCommand::Headers(headers, end_stream) => {
                let headers_fragment = self
                    .encoder.encode(headers.0.iter().map(|h| (h.name(), h.value())));

                let mut pos = 0;
                while pos < headers_fragment.len() || pos == 0 {
                    let end = cmp::min(headers_fragment.len(), pos + max_frame_size);

                    let chunk = &headers_fragment[pos..end];

                    if pos == 0 {
                        let mut frame = HeadersFrame::new(chunk, stream_id);
                        if end_stream == EndStream::Yes {
                            frame.set_flag(HeadersFlag::EndStream);
                        }

                        if end == headers_fragment.len() {
                            frame.set_flag(HeadersFlag::EndHeaders);
                        }

                        debug!("sending frame {:?}", frame);

                        frame.serialize_into(target);
                    } else {
                        let mut frame = ContinuationFrame::new(chunk, stream_id);

                        if end == headers_fragment.len() {
                            frame.set_flag(ContinuationFlag::EndHeaders);
                        }

                        debug!("sending frame {:?}", frame);

                        frame.serialize_into(target);
                    }

                    pos = end;
                }
            }
            HttpStreamCommand::Rst(error_code) => {
                let frame = RstStreamFrame::new(stream_id, error_code);

                debug!("sending frame {:?}", frame);

                frame.serialize_into(target);
            }
        }
    }

    fn pop_outg_all_for_stream_bytes(&mut self, stream_id: StreamId) -> Vec<u8> {
        let mut send = FrameBuilder::new();
        for part in self.pop_outg_all_for_stream(stream_id) {
            self.write_part(&mut send, stream_id, part);
        }
        send.0
    }

    fn pop_outg_all_for_conn_bytes(&mut self) -> Vec<u8> {
        // TODO: maintain own limits of out window
        let mut send = FrameBuilder::new();
        for (stream_id, part) in self.pop_outg_all_for_conn() {
            self.write_part(&mut send, stream_id, part);
        }
        send.0
    }

    fn pop_outg_all_for_stream(&mut self, stream_id: StreamId) -> Vec<HttpStreamCommand> {
        if let Some(stream) = self.streams.get_mut(stream_id) {
            stream.pop_outg_all_maybe_remove(&mut self.out_window_size)
        } else {
            Vec::new()
        }
    }

    pub fn pop_outg_all_for_conn(&mut self) -> Vec<(StreamId, HttpStreamCommand)> {
        let mut r = Vec::new();

        // TODO: keep list of streams with data
        for stream_id in self.streams.stream_ids() {
            r.extend(self.pop_outg_all_for_stream(stream_id).into_iter().map(|s| (stream_id, s)));
        }

        r
    }

    pub fn buffer_outg_stream(&mut self, stream_id: StreamId) -> result::Result<()> {
        let bytes = self.pop_outg_all_for_stream_bytes(stream_id);

        self.framed_write.buffer(bytes.into());

        Ok(())
    }

    fn buffer_outg_conn(&mut self) -> result::Result<()> {
        let bytes = self.pop_outg_all_for_conn_bytes();

        self.framed_write.buffer(bytes.into());

        Ok(())
    }

    fn process_stream_end(&mut self, stream_id: StreamId, error_code: ErrorCode) -> result::Result<()> {
        let stream_id = {
            let stream = self.streams.get_mut(stream_id);
            if let Some(mut stream) = stream {
                stream.stream().outgoing.close(error_code);
                Some(stream_id)
            } else {
                None
            }
        };
        if let Some(stream_id) = stream_id {
            self.buffer_outg_stream(stream_id)?;
        }
        Ok(())
    }

    fn process_stream_enqueue(&mut self, stream_id: StreamId, part: DataOrHeadersWithFlag) -> result::Result<()> {
        let stream_id = {
            let stream = self.streams.get_mut(stream_id);
            if let Some(mut stream) = stream {
                stream.stream().outgoing.push_back_part(part);
                Some(stream_id)
            } else {
                None
            }
        };
        if let Some(stream_id) = stream_id {
            self.buffer_outg_stream(stream_id)?;
        }
        Ok(())
    }

    pub fn process_common_message(&mut self, common: CommonToWriteMessage) -> result::Result<()> {
        match common {
            CommonToWriteMessage::Frame(frame) => {
                self.framed_write.buffer_frame(frame.into_http_frame());
            },
            CommonToWriteMessage::StreamEnd(stream_id, error_code) => {
                self.process_stream_end(stream_id, error_code)?;
            },
            CommonToWriteMessage::StreamEnqueue(stream_id, part) => {
                self.process_stream_enqueue(stream_id, part)?;
            },
            CommonToWriteMessage::IncreaseInWindow(stream_id, increase) => {
                self.increase_in_window(stream_id, increase)?;
            },
            CommonToWriteMessage::CloseConn => {
                return Err(error::Error::Other("close connection"));
            }
        }
        Ok(())
    }

    pub fn poll_write(&mut self) -> Poll<(), error::Error> {
        loop {
            if mem::replace(&mut self.flush_conn, false) {
                self.buffer_outg_conn()?;
            }

            let stream_ids: Vec<StreamId> = self.flush_streams.iter().cloned().collect();
            self.flush_streams.clear();
            for stream_id in stream_ids {
                self.buffer_outg_stream(stream_id)?;
            }

            if let Async::NotReady = self.poll_flush()? {
                return Ok(Async::NotReady);
            }

            let message = match self.write_rx.poll()? {
                Async::NotReady => return Ok(Async::NotReady),
                Async::Ready(Some(message)) => message,
                Async::Ready(None) => return Ok(Async::Ready(())), // Add some diagnostics maybe?
            };

            self.process_message(message)?;
        }
    }
}

// Message sent to write loop.
// Processed while write loop is not handling network I/O.
pub enum CommonToWriteMessage {
    IncreaseInWindow(StreamId, u32),
    Frame(DirectlyToNetworkFrame),    // write frame immediately to the network
    StreamEnqueue(StreamId, DataOrHeadersWithFlag),
    StreamEnd(StreamId, ErrorCode),   // send when user provided handler completed the stream
    CloseConn,
}
<commit_msg>Minor poll_write refactoring<commit_after>use common::types::Types;
use common::conn::Conn;
use common::stream::HttpStreamCommon;
use common::stream::HttpStreamData;
use solicit::connection::HttpFrame;
use solicit::StreamId;

use data_or_headers_with_flag::DataOrHeadersWithFlag;

use error;
use ErrorCode;
use solicit::frame::RstStreamFrame;
use solicit::frame::GoawayFrame;
use solicit::frame::WindowUpdateFrame;
use solicit::frame::PingFrame;
use solicit::frame::SettingsFrame;
use result;
use futures::Poll;
use futures::Async;
use common::conn_read::ConnReadSideCustom;
use common::conn_command::ConnCommandSideCustom;
use common::stream::HttpStreamCommand;
use solicit::frame::FrameBuilder;
use std::cmp;
use solicit::frame::HeadersFrame;
use solicit::connection::EndStream;
use solicit::frame::HeadersFlag;
use solicit::frame::ContinuationFrame;
use solicit::frame::continuation::ContinuationFlag;
use solicit::frame::DataFrame;
use solicit::frame::DataFlag;
use solicit::frame::FrameIR;
use std::mem;

pub enum DirectlyToNetworkFrame {
    RstStream(RstStreamFrame),
    GoAway(GoawayFrame),
    WindowUpdate(WindowUpdateFrame),
    Ping(PingFrame),
    Settings(SettingsFrame),
}

impl DirectlyToNetworkFrame {
    pub fn into_http_frame(self) -> HttpFrame {
        match self {
            DirectlyToNetworkFrame::RstStream(f) => f.into(),
            DirectlyToNetworkFrame::GoAway(f) => f.into(),
            DirectlyToNetworkFrame::WindowUpdate(f) => f.into(),
            DirectlyToNetworkFrame::Ping(f) => f.into(),
            DirectlyToNetworkFrame::Settings(f) => f.into(),
        }
    }
}

pub trait ConnWriteSideCustom {
    type Types : Types;

    fn process_message(&mut self, message: <Self::Types as Types>::ToWriteMessage) -> result::Result<()>;
}

impl<T> Conn<T>
    where
        T : Types,
        Self : ConnReadSideCustom<Types=T>,
        Self : ConnWriteSideCustom<Types=T>,
        Self : ConnCommandSideCustom<Types=T>,
        HttpStreamCommon<T> : HttpStreamData<Types=T>,
{
    fn poll_flush(&mut self) -> Poll<(), error::Error> {
        self.framed_write.poll_flush()
    }

    fn write_part(&mut self, target: &mut FrameBuilder, stream_id: StreamId, part: HttpStreamCommand) {
        let max_frame_size = self.peer_settings.max_frame_size as usize;

        match part {
            HttpStreamCommand::Data(data, end_stream) => {
                // if client requested end of stream,
                // we must send at least one frame with end stream flag
                if end_stream == EndStream::Yes && data.len() == 0 {
                    // probably should send RST_STREAM
                    let mut frame = DataFrame::with_data(stream_id, Vec::new());
                    frame.set_flag(DataFlag::EndStream);

                    debug!("sending frame {:?}", frame);

                    frame.serialize_into(target);
                    return;
                }

                let mut pos = 0;
                while pos < data.len() {
                    let end = cmp::min(data.len(), pos + max_frame_size);

                    let end_stream_in_frame =
                        if end == data.len() && end_stream == EndStream::Yes {
                            EndStream::Yes
                        } else {
                            EndStream::No
                        };

                    let mut frame = DataFrame::with_data(stream_id, data.slice(pos, end));
                    if end_stream_in_frame == EndStream::Yes {
                        frame.set_flag(DataFlag::EndStream);
                    }

                    debug!("sending frame {:?}", frame);

                    frame.serialize_into(target);

                    pos = end;
                }
            }
            HttpStreamCommand::Headers(headers, end_stream) => {
                let headers_fragment = self
                    .encoder.encode(headers.0.iter().map(|h| (h.name(), h.value())));

                let mut pos = 0;
                while pos < headers_fragment.len() || pos == 0 {
                    let end = cmp::min(headers_fragment.len(), pos + max_frame_size);

                    let chunk = &headers_fragment[pos..end];

                    if pos == 0 {
                        let mut frame = HeadersFrame::new(chunk, stream_id);
                        if end_stream == EndStream::Yes {
                            frame.set_flag(HeadersFlag::EndStream);
                        }

                        if end == headers_fragment.len() {
                            frame.set_flag(HeadersFlag::EndHeaders);
                        }

                        debug!("sending frame {:?}", frame);

                        frame.serialize_into(target);
                    } else {
                        let mut frame = ContinuationFrame::new(chunk, stream_id);

                        if end == headers_fragment.len() {
                            frame.set_flag(ContinuationFlag::EndHeaders);
                        }

                        debug!("sending frame {:?}", frame);

                        frame.serialize_into(target);
                    }

                    pos = end;
                }
            }
            HttpStreamCommand::Rst(error_code) => {
                let frame = RstStreamFrame::new(stream_id, error_code);

                debug!("sending frame {:?}", frame);

                frame.serialize_into(target);
            }
        }
    }

    fn pop_outg_all_for_stream_bytes(&mut self, stream_id: StreamId) -> Vec<u8> {
        let mut send = FrameBuilder::new();
        for part in self.pop_outg_all_for_stream(stream_id) {
            self.write_part(&mut send, stream_id, part);
        }
        send.0
    }

    fn pop_outg_all_for_conn_bytes(&mut self) -> Vec<u8> {
        // TODO: maintain own limits of out window
        let mut send = FrameBuilder::new();
        for (stream_id, part) in self.pop_outg_all_for_conn() {
            self.write_part(&mut send, stream_id, part);
        }
        send.0
    }

    fn pop_outg_all_for_stream(&mut self, stream_id: StreamId) -> Vec<HttpStreamCommand> {
        if let Some(stream) = self.streams.get_mut(stream_id) {
            stream.pop_outg_all_maybe_remove(&mut self.out_window_size)
        } else {
            Vec::new()
        }
    }

    pub fn pop_outg_all_for_conn(&mut self) -> Vec<(StreamId, HttpStreamCommand)> {
        let mut r = Vec::new();

        // TODO: keep list of streams with data
        for stream_id in self.streams.stream_ids() {
            r.extend(self.pop_outg_all_for_stream(stream_id).into_iter().map(|s| (stream_id, s)));
        }

        r
    }

    pub fn buffer_outg_stream(&mut self, stream_id: StreamId) -> result::Result<()> {
        let bytes = self.pop_outg_all_for_stream_bytes(stream_id);

        self.framed_write.buffer(bytes.into());

        Ok(())
    }

    fn buffer_outg_conn(&mut self) -> result::Result<()> {
        let bytes = self.pop_outg_all_for_conn_bytes();

        self.framed_write.buffer(bytes.into());

        Ok(())
    }

    fn process_stream_end(&mut self, stream_id: StreamId, error_code: ErrorCode) -> result::Result<()> {
        let stream_id = {
            let stream = self.streams.get_mut(stream_id);
            if let Some(mut stream) = stream {
                stream.stream().outgoing.close(error_code);
                Some(stream_id)
            } else {
                None
            }
        };
        if let Some(stream_id) = stream_id {
            self.buffer_outg_stream(stream_id)?;
        }
        Ok(())
    }

    fn process_stream_enqueue(&mut self, stream_id: StreamId, part: DataOrHeadersWithFlag) -> result::Result<()> {
        let stream_id = {
            let stream = self.streams.get_mut(stream_id);
            if let Some(mut stream) = stream {
                stream.stream().outgoing.push_back_part(part);
                Some(stream_id)
            } else {
                None
            }
        };
        if let Some(stream_id) = stream_id {
            self.buffer_outg_stream(stream_id)?;
        }
        Ok(())
    }

    pub fn process_common_message(&mut self, common: CommonToWriteMessage) -> result::Result<()> {
        match common {
            CommonToWriteMessage::Frame(frame) => {
                self.framed_write.buffer_frame(frame.into_http_frame());
            },
            CommonToWriteMessage::StreamEnd(stream_id, error_code) => {
                self.process_stream_end(stream_id, error_code)?;
            },
            CommonToWriteMessage::StreamEnqueue(stream_id, part) => {
                self.process_stream_enqueue(stream_id, part)?;
            },
            CommonToWriteMessage::IncreaseInWindow(stream_id, increase) => {
                self.increase_in_window(stream_id, increase)?;
            },
            CommonToWriteMessage::CloseConn => {
                return Err(error::Error::Other("close connection"));
            }
        }
        Ok(())
    }

    fn process_flush_xxx_fields(&mut self) -> result::Result<()> {
        if mem::replace(&mut self.flush_conn, false) {
            self.buffer_outg_conn()?;
        }

        let stream_ids: Vec<StreamId> = self.flush_streams.iter().cloned().collect();
        self.flush_streams.clear();
        for stream_id in stream_ids {
            self.buffer_outg_stream(stream_id)?;
        }

        Ok(())
    }

    pub fn poll_write(&mut self) -> Poll<(), error::Error> {
        loop {
            self.process_flush_xxx_fields()?;

            if let Async::NotReady = self.poll_flush()? {
                return Ok(Async::NotReady);
            }

            let message = match self.write_rx.poll()? {
                Async::NotReady => return Ok(Async::NotReady),
                Async::Ready(Some(message)) => message,
                Async::Ready(None) => return Ok(Async::Ready(())), // Add some diagnostics maybe?
            };

            self.process_message(message)?;
        }
    }
}

// Message sent to write loop.
// Processed while write loop is not handling network I/O.
pub enum CommonToWriteMessage {
    IncreaseInWindow(StreamId, u32),
    Frame(DirectlyToNetworkFrame),    // write frame immediately to the network
    StreamEnqueue(StreamId, DataOrHeadersWithFlag),
    StreamEnd(StreamId, ErrorCode),   // send when user provided handler completed the stream
    CloseConn,
}
<|endoftext|>


<commit_before>//! Simple FBX 7.4 binary loader.

use parser::binary::{Result, Parser, ParserSource, FbxFooter};
use loader::binary::simple::GenericNode;

/// FBX 7.4 or later.
#[derive(Debug, Clone, PartialEq)]
pub struct Fbx7400 {
    /// FBX version.
    pub version: u32,
    /// Nodes.
    pub nodes: Vec<GenericNode>,
    /// FBX footer.
    pub footer: Option<FbxFooter>,
}

impl Fbx7400 {
    /// Loads FBX 7400 (or later) structure from the given parser.
    pub fn load_from_parser<R: ParserSource, P: Parser<R>>(
        version: u32,
        mut parser: P
    ) -> Result<Self> {
        info!("FBX version: {}, loading in FBX 7400 mode", version);

        let (nodes, footer) = GenericNode::load_from_parser(&mut parser)?;
        Ok(Fbx7400 {
            version: version,
            nodes: nodes,
            footer: footer,
        })
    }
}
<commit_msg>Add root node types<commit_after>//! Simple FBX 7.4 binary loader.

use parser::binary::{Parser, ParserSource, FbxFooter, Event, Attributes};
use loader::binary::simple::{Result, Error, GenericNode};

/// FBX 7.4 or later.
#[derive(Debug, Clone, PartialEq)]
pub struct Fbx7400 {
    /// FBX version.
    pub version: u32,
    /// `FBXHeaderExtension`.
    pub fbx_header_extension: FbxHeaderExtension,
    /// `FileId`.
    pub file_id: FileId,
    /// `CreationTime`.
    pub creation_time: CreationTime,
    /// `Creator`.
    pub creator: Creator,
    /// `References`.
    pub references: References,
    /// `GlobalSettings`.
    pub global_settings: GlobalSettings,
    /// `Documents`.
    pub documents: Documents,
    /// `Definitions`.
    pub definitions: Definitions,
    /// `Objects`.
    pub objects: Objects,
    /// `Connections`.
    pub connections: Connections,
    /// `Takes`.
    pub takes: Option<Takes>,
    /// FBX footer.
    pub footer: Option<FbxFooter>,
}

impl Fbx7400 {
    /// Loads FBX 7400 (or later) structure from the given parser.
    pub fn load_from_parser<R: ParserSource, P: Parser<R>>(
        version: u32,
        mut parser: P
    ) -> Result<Self> {
        info!("FBX version: {}, loading in FBX 7400 mode", version);

        let footer;
        let mut fbx_header_extension = None;
        let mut file_id = None;
        let mut creation_time = None;
        let mut creator = None;
        let mut global_settings = None;
        let mut documents = None;
        let mut references = None;
        let mut definitions = None;
        let mut objects = None;
        let mut connections = None;
        let mut takes = None;
        loop {
            let node_type = match parser.next_event()? {
                Event::StartFbx(_) |
                Event::EndNode => unreachable!(),
                Event::EndFbx(f) => {
                    footer = f.ok();
                    break;
                },
                Event::StartNode(info) => NodeType::load(info.name, info.attributes)?,
            };
            debug!("node_type: {:?}", node_type);
            match node_type {
                NodeType::FbxHeaderExtension => {
                    fbx_header_extension = Some(FbxHeaderExtension::load(parser.subtree_parser())?);
                },
                NodeType::FileId(attrs) => {
                    file_id = Some(FileId::load(parser.subtree_parser(), attrs)?);
                },
                NodeType::CreationTime(attrs) => {
                    creation_time = Some(CreationTime::load(parser.subtree_parser(), attrs)?);
                },
                NodeType::Creator(attrs) => {
                    creator = Some(Creator::load(parser.subtree_parser(), attrs)?);
                },
                NodeType::GlobalSettings => {
                    global_settings = Some(GlobalSettings::load(parser.subtree_parser())?);
                },
                NodeType::Documents => {
                    documents = Some(Documents::load(parser.subtree_parser())?);
                },
                NodeType::References => {
                    references = Some(References::load(parser.subtree_parser())?);
                },
                NodeType::Definitions => {
                    definitions = Some(Definitions::load(parser.subtree_parser())?);
                },
                NodeType::Objects => {
                    objects = Some(Objects::load(parser.subtree_parser())?);
                },
                NodeType::Connections => {
                    connections = Some(Connections::load(parser.subtree_parser())?);
                },
                NodeType::Takes => {
                    takes = Some(Takes::load(parser.subtree_parser())?);
                },
            }
        }

        Ok(Fbx7400 {
            version: version,
            fbx_header_extension: fbx_header_extension.ok_or_else(|| Error::MissingNode("FBXHeaderExtension".to_owned()))?,
            file_id: file_id.ok_or_else(|| Error::MissingNode("FileId".to_owned()))?,
            creation_time: creation_time.ok_or_else(|| Error::MissingNode("CreationTime".to_owned()))?,
            creator: creator.ok_or_else(|| Error::MissingNode("Creator".to_owned()))?,
            global_settings: global_settings.ok_or_else(|| Error::MissingNode("GlobalSettings".to_owned()))?,
            documents: documents.ok_or_else(|| Error::MissingNode("Documents".to_owned()))?,
            references: references.ok_or_else(|| Error::MissingNode("References".to_owned()))?,
            definitions: definitions.ok_or_else(|| Error::MissingNode("Definitions".to_owned()))?,
            objects: objects.ok_or_else(|| Error::MissingNode("Objects".to_owned()))?,
            connections: connections.ok_or_else(|| Error::MissingNode("Connections".to_owned()))?,
            takes: takes,
            footer: footer,
        })
    }
}

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
enum NodeType {
    FbxHeaderExtension,
    FileId(Vec<u8>),
    CreationTime(String),
    Creator(String),
    GlobalSettings,
    Documents,
    References,
    Definitions,
    Objects,
    Connections,
    Takes,
}

impl NodeType {
    /// Creates `NodeType` from the given node name.
    pub fn load<R: ParserSource>(name: &str, mut attrs: Attributes<R>) -> Result<Self> {
        use parser::binary::utils::AttributeValues;

        match name {
            "FBXHeaderExtension" => Ok(NodeType::FbxHeaderExtension),
            "FileId" => {
                <Vec<u8>>::from_attributes(&mut attrs)
                    ?
                    .ok_or_else(|| Error::InvalidAttribute(name.to_owned()))
                    .map(NodeType::FileId)
            },
            "CreationTime" => {
                <String>::from_attributes(&mut attrs)
                    ?
                    .ok_or_else(|| Error::InvalidAttribute(name.to_owned()))
                    .map(NodeType::CreationTime)
            },
            "Creator" => {
                <String>::from_attributes(&mut attrs)
                    ?
                    .ok_or_else(|| Error::InvalidAttribute(name.to_owned()))
                    .map(NodeType::Creator)
            },
            "GlobalSettings" => Ok(NodeType::GlobalSettings),
            "Documents" => Ok(NodeType::Documents),
            "References" => Ok(NodeType::References),
            "Definitions" => Ok(NodeType::Definitions),
            "Objects" => Ok(NodeType::Objects),
            "Connections" => Ok(NodeType::Connections),
            "Takes" => Ok(NodeType::Takes),
            _ => Err(Error::UnexpectedNode(name.to_owned())),
        }
    }
}

/// `FBXHeaderExtension`.
#[derive(Debug, Clone, PartialEq)]
pub struct FbxHeaderExtension {
    /// Child nodes.
    pub nodes: Vec<GenericNode>,
}

impl FbxHeaderExtension {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let nodes = GenericNode::load_from_parser(&mut parser)?.0;
        Ok(FbxHeaderExtension { nodes: nodes })
    }
}

/// `FileId`.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct FileId(pub Vec<u8>);

impl FileId {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P, attrs: Vec<u8>) -> Result<Self> {
        parser.skip_current_node()?;
        Ok(FileId(attrs))
    }
}

/// `CreationTime`.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct CreationTime(pub String);

impl CreationTime {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P, attrs: String) -> Result<Self> {
        parser.skip_current_node()?;
        Ok(CreationTime(attrs))
    }
}

/// `Creator`.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Creator(pub String);

impl Creator {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P, attrs: String) -> Result<Self> {
        parser.skip_current_node()?;
        Ok(Creator(attrs))
    }
}

/// `GlobalSettings`.
#[derive(Debug, Clone, PartialEq)]
pub struct GlobalSettings {
    /// Child nodes.
    pub nodes: Vec<GenericNode>,
}

impl GlobalSettings {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let nodes = GenericNode::load_from_parser(&mut parser)?.0;
        Ok(GlobalSettings { nodes: nodes })
    }
}

/// `Documents`.
#[derive(Debug, Clone, PartialEq)]
pub struct Documents {
    /// Child nodes.
    pub nodes: Vec<GenericNode>,
}

impl Documents {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let nodes = GenericNode::load_from_parser(&mut parser)?.0;
        Ok(Documents { nodes: nodes })
    }
}

/// `References`.
#[derive(Debug, Clone, PartialEq)]
pub struct References {
    /// Child nodes.
    pub nodes: Vec<GenericNode>,
}

impl References {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let nodes = GenericNode::load_from_parser(&mut parser)?.0;
        Ok(References { nodes: nodes })
    }
}

/// `Definitions`.
#[derive(Debug, Clone, PartialEq)]
pub struct Definitions {
    /// Child nodes.
    pub nodes: Vec<GenericNode>,
}

impl Definitions {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let nodes = GenericNode::load_from_parser(&mut parser)?.0;
        Ok(Definitions { nodes: nodes })
    }
}

/// `Objects`.
#[derive(Debug, Clone, PartialEq)]
pub struct Objects {
    /// Child nodes.
    pub nodes: Vec<GenericNode>,
}

impl Objects {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let nodes = GenericNode::load_from_parser(&mut parser)?.0;
        Ok(Objects { nodes: nodes })
    }
}

/// `Connections`.
#[derive(Debug, Clone, PartialEq)]
pub struct Connections {
    /// Child nodes.
    pub nodes: Vec<GenericNode>,
}

impl Connections {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let nodes = GenericNode::load_from_parser(&mut parser)?.0;
        Ok(Connections { nodes: nodes })
    }
}

/// `Takes`.
#[derive(Debug, Clone, PartialEq)]
pub struct Takes {
    /// Child nodes.
    pub nodes: Vec<GenericNode>,
}

impl Takes {
    /// Loads node contents from the parser.
    pub fn load<R: ParserSource, P: Parser<R>>(mut parser: P) -> Result<Self> {
        let nodes = GenericNode::load_from_parser(&mut parser)?.0;
        Ok(Takes { nodes: nodes })
    }
}
<|endoftext|>


<commit_before>use std::marker::Sized;
use std::{ffi, iter};

use libc;

use jack_enums::JackErr;
use port::port_flags::PortFlags;
use jack_sys as j;
use primitive_types as pt;

lazy_static! {
    /// The maximum string length for port names.
    pub static ref PORT_NAME_SIZE: usize = unsafe { j::jack_port_name_size() - 1 } as usize;

    /// The maximum string length for jack type names.
    pub static ref PORT_TYPE_SIZE: usize = unsafe { j::jack_port_type_size() - 1 } as usize;
}

/// Defines the configuration for a certain port to JACK, ie 32 bit floating audio input, 8 bit raw
/// midi output, etc...
pub unsafe trait PortSpec: Default + Sized {
    /// String used by JACK upon port creation to identify the port
    /// type.
    fn jack_port_type(&self) -> &'static str;

    /// Flags used by jack upon port creation.
    fn jack_flags(&self) -> PortFlags;

    /// Size used by jack upon port creation.
    fn jack_buffer_size(&self) -> libc::c_ulong;
}

/// An endpoint to interact with JACK data streams, for audio, midi,
/// etc...
///
/// The `Port` struct contains mostly metadata and exposes data as raw pointers. For a better data
/// consumption/production API, see the `AudioInPort`, `AudioOutPort`, `MidiInPort`, and
/// `MidiOutPort`.
///
/// Most JACK functionality is exposed, including the raw pointers, but it should be possible to
/// create a client without the need for calling `unsafe` `Port` methods.
#[derive(Debug)]
pub struct Port<PS: PortSpec> {
    spec: PS,
    client_ptr: *mut j::jack_client_t,
    port_ptr: *mut j::jack_port_t,
}

unsafe impl<PS: PortSpec> Send for Port<PS> {}
unsafe impl<PS: PortSpec> Sync for Port<PS> {}

impl<PS: PortSpec> Port<PS> {
    /// Returns the spec that was used to create this port.
    pub fn spec(&self) -> &PS {
        &self.spec
    }

    /// Return a copy of port as an unowned port that can still be used for querying information.
    pub fn clone_unowned(&self) -> Port<Unowned> {
        Port {
            spec: Unowned,
            client_ptr: self.client_ptr(),
            port_ptr: self.as_ptr(),
        }
    }

    /// Returns the full name of the port, including the "client_name:" prefix.
    pub fn name<'a>(&'a self) -> &'a str {
        unsafe { ffi::CStr::from_ptr(j::jack_port_name(self.as_ptr())).to_str().unwrap() }
    }

    /// Returns the short name of the port, it excludes the "client_name:" prefix.
    pub fn short_name<'a>(&'a self) -> &'a str {
        unsafe { ffi::CStr::from_ptr(j::jack_port_short_name(self.as_ptr())).to_str().unwrap() }
    }

    /// The flags for the port. These are set when the port is registered with
    /// its client.
    pub fn flags(&self) -> PortFlags {
        let bits = unsafe { j::jack_port_flags(self.as_ptr()) };
        PortFlags::from_bits(bits as j::Enum_JackPortFlags).unwrap()
    }

    /// The port type. JACK's built in types include `"32 bit float mono audio`" and `"8 bit raw
    /// midi"`. Custom types may also be used.
    pub fn port_type<'a>(&self) -> &'a str {
        unsafe { ffi::CStr::from_ptr(j::jack_port_type(self.as_ptr())).to_str().unwrap() }
    }

    /// Number of ports connected to/from `&self`.
    pub fn connected_count(&self) -> usize {
        let n = unsafe { j::jack_port_connected(self.as_ptr()) };
        n as usize
    }

    /// Returns `true` if the port is directly connected to a port with the name `port_name`.
    pub fn is_connected_to(&self, port_name: &str) -> bool {
        let res = unsafe {
            let port_name = ffi::CString::new(port_name).unwrap();
            j::jack_port_connected_to(self.as_ptr(), port_name.as_ptr())
        };
        match res {
            0 => false,
            _ => true,
        }
    }

    /// Remove connections to/from port `self`.
    pub fn disconnect(&self) -> Result<(), JackErr> {
        let res = unsafe { j::jack_port_disconnect(self.client_ptr(), self.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortDisconnectionError),
        }
    }

    /// Get the alias names for `self`.
    ///
    /// Will return up to 2 strings.
    pub fn aliases(&self) -> Vec<String> {
        let mut a: Vec<i8> = iter::repeat(0).take(*PORT_NAME_SIZE + 1).collect();
        let mut b = a.clone();
        unsafe {
            let mut ptrs: [*mut i8; 2] = [a.as_mut_ptr(), b.as_mut_ptr()];
            j::jack_port_get_aliases(self.as_ptr(), ptrs.as_mut_ptr());
        };
        [a, b]
            .iter()
            .map(|p| p.as_ptr())
            .map(|p| unsafe { ffi::CStr::from_ptr(p).to_string_lossy().into_owned() })
            .filter(|s| s.len() > 0)
            .collect()
    }

    /// Returns `true` if monitoring has been requested for `self`.
    pub fn is_monitoring_input(&self) -> bool {
        match unsafe { j::jack_port_monitoring_input(self.as_ptr()) } {
            0 => false,
            _ => true,
        }
    }

    /// Turn input monitoring for the port on or off.
    ///
    /// This only works if the port has the `CAN_MONITOR` flag set.
    pub fn request_monitor(&self, enable_monitor: bool) -> Result<(), JackErr> {
        let onoff = match enable_monitor {
            true => 1,
            false => 0,
        };
        let res = unsafe { j::jack_port_request_monitor(self.as_ptr(), onoff) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortMonitorError),
        }
    }

    /// If the `CAN_MONITOR` flag is set for the port, then input monitoring is turned on if it was
    /// off, and turns it off if only one request has been made to turn it on. Otherwise it does
    /// nothing.
    pub fn ensure_monitor(&self, enable_monitor: bool) -> Result<(), JackErr> {
        let onoff = match enable_monitor {
            true => 1,
            false => 0,
        };
        let res = unsafe { j::jack_port_ensure_monitor(self.as_ptr(), onoff) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortMonitorError),
        }
    }

    /// Set's the short name of the port. If the full name is longer than `PORT_NAME_SIZE`, then it
    /// will be truncated.
    pub fn set_name(&mut self, short_name: &str) -> Result<(), JackErr> {
        let short_name = ffi::CString::new(short_name).unwrap();
        let res = unsafe { j::jack_port_set_name(self.as_ptr(), short_name.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortNamingError),
        }
    }

    /// Sets `alias` as an alias for `self`.
    ///
    /// May be called at any time. If the alias is longer than `PORT_NAME_SIZE`, it will be
    /// truncated.
    ///
    /// After a successful call, and until JACK exists, or the alias is unset, `alias` may be used
    /// as an alternate name for the port.
    ///
    /// Ports can have up to two aliases - if both are already set, this function will return an
    /// error.
    pub fn set_alias(&mut self, alias: &str) -> Result<(), JackErr> {
        let alias = ffi::CString::new(alias).unwrap();
        let res = unsafe { j::jack_port_set_alias(self.as_ptr(), alias.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortAliasError),
        }
    }

    /// Remove `alias` as an alias for port. May be called at any time.
    ///
    /// After a successful call, `alias` can no longer be used as an alternate name for `self`.
    pub fn unset_alias(&mut self, alias: &str) -> Result<(), JackErr> {
        let alias = ffi::CString::new(alias).unwrap();
        let res = unsafe { j::jack_port_unset_alias(self.as_ptr(), alias.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortAliasError),
        }
    }

    /// Remove the port from the client, disconnecting any existing connections.  The port must have
    /// been created with the provided client.
    pub fn unregister(self) -> Result<(), JackErr> {
        let res = unsafe { j::jack_port_unregister(self.client_ptr, self.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortDisconnectionError),
        }
    }

    /// Create a Port from raw JACK pointers.
    ///
    /// This is mostly for use within the jack crate itself.
    pub unsafe fn from_raw(spec: PS,
                           client_ptr: *mut j::jack_client_t,
                           port_ptr: *mut j::jack_port_t)
                           -> Self {
        Port {
            spec: spec,
            port_ptr: port_ptr,
            client_ptr: client_ptr,
        }
    }

    /// Obtain the client pointer that spawned this port.
    ///
    /// This is mostly for use within the jack crate itself.
    #[inline(always)]
    pub fn client_ptr(&self) -> *mut j::jack_client_t {
        self.client_ptr
    }

    /// Obtain the ffi port pointer.
    ///
    /// This is mostly for use within the jack crate itself.
    #[inline(always)]
    pub fn as_ptr(&self) -> *mut j::jack_port_t {
        self.port_ptr
    }

    /// Obtain the buffer that the Port is holding. For standard audio and midi ports, consider
    /// using the `AudioInPort`, `AudioOutPort`, `MidiInPort`, or `MidiOutPort` adapter. For more
    /// custom data, consider implementing your own adapter that safely uses the `Port::buffer`
    /// method.
    #[inline(always)]
    pub unsafe fn buffer(&self, n_frames: pt::JackFrames) -> *mut libc::c_void {
        j::jack_port_get_buffer(self.port_ptr, n_frames)
    }
}

/// `PortSpec` for a port that holds has no readable or writeable data from JACK on the created
/// client. It can be used for obtaining information about external ports.
#[derive(Debug, Default)]
pub struct Unowned;

/// `Port<UnownedSpec>` - Port that holds no data from Jack, though it can still be used to query
/// information.
pub type UnownedPort = Port<Unowned>;

unsafe impl PortSpec for Unowned {
    /// Panics on call since the `Unowned` spec can't be used to create ports.
    fn jack_port_type(&self) -> &'static str {
        unreachable!()
    }

    /// Panics on call since the `Unowned` spec can't be used to create ports.
    fn jack_flags(&self) -> PortFlags {
        unreachable!()
    }

    /// Panics on call since the `Unowned` spec can't be used to create ports.
    fn jack_buffer_size(&self) -> libc::c_ulong {
        unreachable!()
    }
}
<commit_msg>making PortSpec trait not require Default and a 'static port type. (#68)<commit_after>use std::marker::Sized;
use std::{ffi, iter};

use libc;

use jack_enums::JackErr;
use port::port_flags::PortFlags;
use jack_sys as j;
use primitive_types as pt;

lazy_static! {
    /// The maximum string length for port names.
    pub static ref PORT_NAME_SIZE: usize = unsafe { j::jack_port_name_size() - 1 } as usize;

    /// The maximum string length for jack type names.
    pub static ref PORT_TYPE_SIZE: usize = unsafe { j::jack_port_type_size() - 1 } as usize;
}

/// Defines the configuration for a certain port to JACK, ie 32 bit floating audio input, 8 bit raw
/// midi output, etc...
pub unsafe trait PortSpec: Sized {
    /// String used by JACK upon port creation to identify the port
    /// type.
    fn jack_port_type(&self) -> &str;

    /// Flags used by jack upon port creation.
    fn jack_flags(&self) -> PortFlags;

    /// Size used by jack upon port creation.
    fn jack_buffer_size(&self) -> libc::c_ulong;
}

/// An endpoint to interact with JACK data streams, for audio, midi,
/// etc...
///
/// The `Port` struct contains mostly metadata and exposes data as raw pointers. For a better data
/// consumption/production API, see the `AudioInPort`, `AudioOutPort`, `MidiInPort`, and
/// `MidiOutPort`.
///
/// Most JACK functionality is exposed, including the raw pointers, but it should be possible to
/// create a client without the need for calling `unsafe` `Port` methods.
#[derive(Debug)]
pub struct Port<PS: PortSpec> {
    spec: PS,
    client_ptr: *mut j::jack_client_t,
    port_ptr: *mut j::jack_port_t,
}

unsafe impl<PS: PortSpec> Send for Port<PS> {}
unsafe impl<PS: PortSpec> Sync for Port<PS> {}

impl<PS: PortSpec> Port<PS> {
    /// Returns the spec that was used to create this port.
    pub fn spec(&self) -> &PS {
        &self.spec
    }

    /// Return a copy of port as an unowned port that can still be used for querying information.
    pub fn clone_unowned(&self) -> Port<Unowned> {
        Port {
            spec: Unowned,
            client_ptr: self.client_ptr(),
            port_ptr: self.as_ptr(),
        }
    }

    /// Returns the full name of the port, including the "client_name:" prefix.
    pub fn name<'a>(&'a self) -> &'a str {
        unsafe { ffi::CStr::from_ptr(j::jack_port_name(self.as_ptr())).to_str().unwrap() }
    }

    /// Returns the short name of the port, it excludes the "client_name:" prefix.
    pub fn short_name<'a>(&'a self) -> &'a str {
        unsafe { ffi::CStr::from_ptr(j::jack_port_short_name(self.as_ptr())).to_str().unwrap() }
    }

    /// The flags for the port. These are set when the port is registered with
    /// its client.
    pub fn flags(&self) -> PortFlags {
        let bits = unsafe { j::jack_port_flags(self.as_ptr()) };
        PortFlags::from_bits(bits as j::Enum_JackPortFlags).unwrap()
    }

    /// The port type. JACK's built in types include `"32 bit float mono audio`" and `"8 bit raw
    /// midi"`. Custom types may also be used.
    pub fn port_type<'a>(&self) -> &'a str {
        unsafe { ffi::CStr::from_ptr(j::jack_port_type(self.as_ptr())).to_str().unwrap() }
    }

    /// Number of ports connected to/from `&self`.
    pub fn connected_count(&self) -> usize {
        let n = unsafe { j::jack_port_connected(self.as_ptr()) };
        n as usize
    }

    /// Returns `true` if the port is directly connected to a port with the name `port_name`.
    pub fn is_connected_to(&self, port_name: &str) -> bool {
        let res = unsafe {
            let port_name = ffi::CString::new(port_name).unwrap();
            j::jack_port_connected_to(self.as_ptr(), port_name.as_ptr())
        };
        match res {
            0 => false,
            _ => true,
        }
    }

    /// Remove connections to/from port `self`.
    pub fn disconnect(&self) -> Result<(), JackErr> {
        let res = unsafe { j::jack_port_disconnect(self.client_ptr(), self.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortDisconnectionError),
        }
    }

    /// Get the alias names for `self`.
    ///
    /// Will return up to 2 strings.
    pub fn aliases(&self) -> Vec<String> {
        let mut a: Vec<i8> = iter::repeat(0).take(*PORT_NAME_SIZE + 1).collect();
        let mut b = a.clone();
        unsafe {
            let mut ptrs: [*mut i8; 2] = [a.as_mut_ptr(), b.as_mut_ptr()];
            j::jack_port_get_aliases(self.as_ptr(), ptrs.as_mut_ptr());
        };
        [a, b]
            .iter()
            .map(|p| p.as_ptr())
            .map(|p| unsafe { ffi::CStr::from_ptr(p).to_string_lossy().into_owned() })
            .filter(|s| s.len() > 0)
            .collect()
    }

    /// Returns `true` if monitoring has been requested for `self`.
    pub fn is_monitoring_input(&self) -> bool {
        match unsafe { j::jack_port_monitoring_input(self.as_ptr()) } {
            0 => false,
            _ => true,
        }
    }

    /// Turn input monitoring for the port on or off.
    ///
    /// This only works if the port has the `CAN_MONITOR` flag set.
    pub fn request_monitor(&self, enable_monitor: bool) -> Result<(), JackErr> {
        let onoff = match enable_monitor {
            true => 1,
            false => 0,
        };
        let res = unsafe { j::jack_port_request_monitor(self.as_ptr(), onoff) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortMonitorError),
        }
    }

    /// If the `CAN_MONITOR` flag is set for the port, then input monitoring is turned on if it was
    /// off, and turns it off if only one request has been made to turn it on. Otherwise it does
    /// nothing.
    pub fn ensure_monitor(&self, enable_monitor: bool) -> Result<(), JackErr> {
        let onoff = match enable_monitor {
            true => 1,
            false => 0,
        };
        let res = unsafe { j::jack_port_ensure_monitor(self.as_ptr(), onoff) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortMonitorError),
        }
    }

    /// Set's the short name of the port. If the full name is longer than `PORT_NAME_SIZE`, then it
    /// will be truncated.
    pub fn set_name(&mut self, short_name: &str) -> Result<(), JackErr> {
        let short_name = ffi::CString::new(short_name).unwrap();
        let res = unsafe { j::jack_port_set_name(self.as_ptr(), short_name.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortNamingError),
        }
    }

    /// Sets `alias` as an alias for `self`.
    ///
    /// May be called at any time. If the alias is longer than `PORT_NAME_SIZE`, it will be
    /// truncated.
    ///
    /// After a successful call, and until JACK exists, or the alias is unset, `alias` may be used
    /// as an alternate name for the port.
    ///
    /// Ports can have up to two aliases - if both are already set, this function will return an
    /// error.
    pub fn set_alias(&mut self, alias: &str) -> Result<(), JackErr> {
        let alias = ffi::CString::new(alias).unwrap();
        let res = unsafe { j::jack_port_set_alias(self.as_ptr(), alias.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortAliasError),
        }
    }

    /// Remove `alias` as an alias for port. May be called at any time.
    ///
    /// After a successful call, `alias` can no longer be used as an alternate name for `self`.
    pub fn unset_alias(&mut self, alias: &str) -> Result<(), JackErr> {
        let alias = ffi::CString::new(alias).unwrap();
        let res = unsafe { j::jack_port_unset_alias(self.as_ptr(), alias.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortAliasError),
        }
    }

    /// Remove the port from the client, disconnecting any existing connections.  The port must have
    /// been created with the provided client.
    pub fn unregister(self) -> Result<(), JackErr> {
        let res = unsafe { j::jack_port_unregister(self.client_ptr, self.as_ptr()) };
        match res {
            0 => Ok(()),
            _ => Err(JackErr::PortDisconnectionError),
        }
    }

    /// Create a Port from raw JACK pointers.
    ///
    /// This is mostly for use within the jack crate itself.
    pub unsafe fn from_raw(spec: PS,
                           client_ptr: *mut j::jack_client_t,
                           port_ptr: *mut j::jack_port_t)
                           -> Self {
        Port {
            spec: spec,
            port_ptr: port_ptr,
            client_ptr: client_ptr,
        }
    }

    /// Obtain the client pointer that spawned this port.
    ///
    /// This is mostly for use within the jack crate itself.
    #[inline(always)]
    pub fn client_ptr(&self) -> *mut j::jack_client_t {
        self.client_ptr
    }

    /// Obtain the ffi port pointer.
    ///
    /// This is mostly for use within the jack crate itself.
    #[inline(always)]
    pub fn as_ptr(&self) -> *mut j::jack_port_t {
        self.port_ptr
    }

    /// Obtain the buffer that the Port is holding. For standard audio and midi ports, consider
    /// using the `AudioInPort`, `AudioOutPort`, `MidiInPort`, or `MidiOutPort` adapter. For more
    /// custom data, consider implementing your own adapter that safely uses the `Port::buffer`
    /// method.
    #[inline(always)]
    pub unsafe fn buffer(&self, n_frames: pt::JackFrames) -> *mut libc::c_void {
        j::jack_port_get_buffer(self.port_ptr, n_frames)
    }
}

/// `PortSpec` for a port that holds has no readable or writeable data from JACK on the created
/// client. It can be used for obtaining information about external ports.
#[derive(Debug, Default)]
pub struct Unowned;

/// `Port<UnownedSpec>` - Port that holds no data from Jack, though it can still be used to query
/// information.
pub type UnownedPort = Port<Unowned>;

unsafe impl PortSpec for Unowned {
    /// Panics on call since the `Unowned` spec can't be used to create ports.
    fn jack_port_type(&self) -> &str {
        unreachable!()
    }

    /// Panics on call since the `Unowned` spec can't be used to create ports.
    fn jack_flags(&self) -> PortFlags {
        unreachable!()
    }

    /// Panics on call since the `Unowned` spec can't be used to create ports.
    fn jack_buffer_size(&self) -> libc::c_ulong {
        unreachable!()
    }
}
<|endoftext|>


<commit_before>//! Contains test for all types supporting `bind_parameter`
//!
//! These tests assume there is a Stage table with a Varchar in 'A', an Integer in 'B' and a Real
//! in 'C'
extern crate odbc;
use odbc::*;

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _exec_direct() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    // select '你好' as hello
    if let Ok(Data(mut stmt)) = stmt.exec_direct_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 196, 227, 186, 195, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32].as_slice()) {
        while let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),  // when  你好 is encoded by gbk, it is [196, 227, 186, 195]
                None => panic!(" NULL"),
            }
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _prepare_1() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select '你好' as hello where 1 = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 196, 227, 186, 195, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32, 119, 104, 101, 114, 101, 32, 32, 49, 32, 61, 32, 63, 32].as_slice()).unwrap();
    let stmt = stmt.bind_parameter(1, &1).unwrap();

    match stmt.execute().unwrap() {
        Data(mut stmt) => {
            while let Some(mut cursor) = stmt.fetch().unwrap() {
                match cursor.get_data::<Vec<u8>>(1).unwrap() {
                    Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),
                    None => panic!(" NULL"),
                }
            }
        }
        NoData(_) => {
            panic!("SELECT did not return result set");
        }
    }

}

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _prepare_2() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "sa", "123456").unwrap();
    // select '你好' as hello where '你好' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 228, 189, 160, 229, 165, 189, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32, 119, 104, 101, 114, 101, 32, 39, 228, 189, 160, 229, 165, 189, 39, 32, 61, 32, 63].as_slice()).unwrap();
    // bind gbk encoded byte
    let param = CustomOdbcType {
        data: &[228, 189, 160, 229, 165, 189]
    };
    let stmt = stmt.bind_parameter(1, &param).unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data")
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
fn exec_direct() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    // select 'hello'
    if let Ok(Data(mut stmt)) = stmt.exec_direct_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32].as_slice()) {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),  // when  hello is encoded by utf8, it is [104, 101, 108, 108, 111]
                None => panic!(" NULL"),
            }
        } else {
            panic!("No Data");
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
fn prepare_1() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select 'hello' where 'hello' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32, 119, 104, 101, 114, 101, 32, 39, 104, 101, 108, 108, 111, 39, 32, 61, 32, 63, 32].as_slice()).unwrap();
    let stmt = stmt.bind_parameter(1, &"hello").unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data");
        }
    } else {
        panic!("SELECT did not return result set");
    }

}

/// CustomOdbcType  for bindParameter
struct CustomOdbcType<'a> {
    data: &'a [u8],
}

unsafe impl<'a> OdbcType<'a> for CustomOdbcType<'a> {
    fn sql_data_type() -> ffi::SqlDataType {
        ffi::SQL_VARCHAR
    }
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_CHAR
    }

    fn convert(buffer: &'a [u8]) -> Self {
        CustomOdbcType {
            data: buffer
        }
    }

    fn column_size(&self) -> ffi::SQLULEN {
        self.data.len() as ffi::SQLULEN
    }

    fn value_ptr(&self) -> ffi::SQLPOINTER {
        self.data.as_ptr() as *const Self as ffi::SQLPOINTER
    }
}

#[test]
fn prepare_2() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select 'hello' where 'hello' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32, 119, 104, 101, 114, 101, 32, 39, 104, 101, 108, 108, 111, 39, 32, 61, 32, 63, 32].as_slice()).unwrap();
    // bind utf encoded byte
    // let param: Vec<u8> = vec![104, 101, 108, 108, 111];
    let param = CustomOdbcType {
        data: &[104, 101, 108, 108, 111]
    };
    let stmt = stmt.bind_parameter(1, &param).unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data");
        }
    } else {
        panic!("SELECT did not return result set");
    }
}
<commit_msg>foget changed test file<commit_after>//! Contains test for all types supporting `bind_parameter`
//!
//! These tests assume there is a Stage table with a Varchar in 'A', an Integer in 'B' and a Real
//! in 'C'
extern crate odbc;
use odbc::*;

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _exec_direct() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    // select '你好' as hello
    if let Ok(Data(mut stmt)) = stmt.exec_direct_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 196, 227, 186, 195, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32].as_slice()) {
        while let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),  // when  你好 is encoded by gbk, it is [196, 227, 186, 195]
                None => panic!(" NULL"),
            }
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _prepare_1() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select '你好' as hello where 1 = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 196, 227, 186, 195, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32, 119, 104, 101, 114, 101, 32, 32, 49, 32, 61, 32, 63, 32].as_slice()).unwrap();
    let stmt = stmt.bind_parameter(1, &1).unwrap();

    match stmt.execute().unwrap() {
        Data(mut stmt) => {
            while let Some(mut cursor) = stmt.fetch().unwrap() {
                match cursor.get_data::<Vec<u8>>(1).unwrap() {
                    Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),
                    None => panic!(" NULL"),
                }
            }
        }
        NoData(_) => {
            panic!("SELECT did not return result set");
        }
    }

}

#[test]
#[ignore]
/// tested in windows中文版 codepage 936
fn _prepare_2() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "sa", "123456").unwrap();
    // select '你好' as hello where '你好' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 228, 189, 160, 229, 165, 189, 39, 32, 97, 115, 32, 104, 101, 108, 108, 111, 32, 119, 104, 101, 114, 101, 32, 39, 228, 189, 160, 229, 165, 189, 39, 32, 61, 32, 63].as_slice()).unwrap();
    // bind gbk encoded byte
    let param = CustomOdbcType {
        data: &[228, 189, 160, 229, 165, 189]
    };
    let stmt = stmt.bind_parameter(1, &param).unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![196, 227, 186, 195]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data")
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
fn exec_direct() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    let stmt = Statement::with_parent(&conn).unwrap();

    // select 'hello'
    if let Ok(Data(mut stmt)) = stmt.exec_direct_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32].as_slice()) {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),  // when  hello is encoded by utf8, it is [104, 101, 108, 108, 111]
                None => panic!(" NULL"),
            }
        } else {
            panic!("No Data");
        }
    } else {
        panic!("SELECT did not return result set");
    }
}

#[test]
fn prepare_1() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select 'hello' where 'hello' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32, 119, 104, 101, 114, 101, 32, 39, 104, 101, 108, 108, 111, 39, 32, 61, 32, 63, 32].as_slice()).unwrap();
    let stmt = stmt.bind_parameter(1, &"hello").unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data");
        }
    } else {
        panic!("SELECT did not return result set");
    }

}

/// CustomOdbcType  for bindParameter
struct CustomOdbcType<'a> {
    data: &'a [u8],
}

unsafe impl<'a> OdbcType<'a> for CustomOdbcType<'a> {
    fn sql_data_type() -> ffi::SqlDataType {
        ffi::SQL_VARCHAR
    }
    fn c_data_type() -> ffi::SqlCDataType {
        ffi::SQL_C_CHAR
    }

    fn convert(buffer: &'a [u8]) -> Self {
        CustomOdbcType {
            data: buffer
        }
    }

    fn column_size(&self) -> ffi::SQLULEN {
        self.data.len() as ffi::SQLULEN
    }

    fn value_ptr(&self) -> ffi::SQLPOINTER {
        self.data.as_ptr() as *const Self as ffi::SQLPOINTER
    }

    fn encoded_value(&self) -> EncodedValue {
        EncodedValue::new(None)
    }
}

#[test]
fn prepare_2() {
    let env = create_environment_v3().unwrap();
    let conn = env.connect("TestDataSource", "", "").unwrap();
    // select 'hello' where 'hello' = ?
    let stmt = Statement::with_parent(&conn).unwrap().prepare_bytes(vec![115, 101, 108, 101, 99, 116, 32, 39, 104, 101, 108, 108, 111, 39, 32, 119, 104, 101, 114, 101, 32, 39, 104, 101, 108, 108, 111, 39, 32, 61, 32, 63, 32].as_slice()).unwrap();
    // bind utf encoded byte
    // let param: Vec<u8> = vec![104, 101, 108, 108, 111];
    let param = CustomOdbcType {
        data: &[104, 101, 108, 108, 111]
    };
    let stmt = stmt.bind_parameter(1, &param).unwrap();

    if let Ok(Data(mut stmt)) = stmt.execute() {
        if let Some(mut cursor) = stmt.fetch().unwrap() {
            match cursor.get_data::<Vec<u8>>(1).unwrap() {
                Some(val) => assert_eq!(val, vec![104, 101, 108, 108, 111]),
                None => panic!(" NULL"),
            }
        } else {
            panic!("No data");
        }
    } else {
        panic!("SELECT did not return result set");
    }
}
<|endoftext|>


<commit_before>/*
 * Copyright 2015-2017 Nathan Fiedler
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

extern crate magick_rust;

use magick_rust::{MagickWand, magick_wand_genesis, MetricType};

use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::sync::{Once, ONCE_INIT};

// TODO: nathan does not understand how to expose the FilterType without
//       this ugliness, his Rust skills are sorely lacking
use magick_rust::bindings;

// Used to make sure MagickWand is initialized exactly once. Note that we
// do not bother shutting down, we simply exit when the tests are done.
static START: Once = ONCE_INIT;

#[test]
fn test_new_drop() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    MagickWand::new();
}

#[test]
fn test_resize_image() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let halfwidth = match wand.get_image_width() {
        1 => 1,
        width => width / 2
    };
    let halfheight = match wand.get_image_height() {
        1 => 1,
        height => height / 2
    };
    wand.resize_image(halfwidth, halfheight, bindings::FilterType::LanczosFilter);
    assert_eq!(256, wand.get_image_width());
    assert_eq!(192, wand.get_image_height());
}

#[test]
fn test_read_from_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();

    let path = Path::new("tests/data/IMG_5745.JPG");
    let mut file = match File::open(&path) {
        Err(why) => panic!("couldn't open file: {}", Error::description(&why)),
        Ok(file) => file
    };
    let mut data: Vec<u8> = Vec::new();
    match file.read_to_end(&mut data) {
        Err(why) => panic!("couldn't read file: {}", Error::description(&why)),
        Ok(_) => ()
    };
    assert!(wand.read_image_blob(&data).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_write_image_to_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let blob = wand.write_image_blob("jpeg").unwrap();
    let blob_len = blob.len();
    // There is a slight degree of variability from platform to platform,
    // and version to version of ImageMagick.
    assert!(blob_len > 103000 && blob_len < 105000);
    // should be able to read it back again
    assert!(wand.read_image_blob(&blob).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_write_images_to_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let blob = wand.write_images_blob("jpeg").unwrap();
    let blob_len = blob.len();
    // There is a slight degree of variability from platform to platform,
    // and version to version of ImageMagick.
    assert!(blob_len > 103000 && blob_len < 105000);
    // should be able to read it back again
    assert!(wand.read_image_blob(&blob).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_fit() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    wand.fit(240, 240);
    assert_eq!(240, wand.get_image_width());
    assert_eq!(180, wand.get_image_height());
}

#[test]
fn test_get_image_property() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    // retrieve a property we know exists
    let found_value = wand.get_image_property("exif:DateTimeOriginal");
    assert!(found_value.is_ok());
    assert_eq!("2014:04:23 13:33:08", found_value.unwrap());
    // retrieve a property that does not exist
    let missing_value = wand.get_image_property("exif:Foobar");
    assert!(missing_value.is_err());
    assert_eq!("missing property", missing_value.unwrap_err());
}

#[test]
fn test_requires_orientation() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(false, wand.requires_orientation());
}

#[test]
fn test_auto_orient() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745_rotl.JPG").is_ok());
    assert_eq!(true, wand.requires_orientation());
    assert!(wand.auto_orient());
    assert_eq!(false, wand.requires_orientation());
}

#[test]
fn test_compare_images() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand1 = MagickWand::new();
    assert!(wand1.read_image("tests/data/IMG_5745.JPG").is_ok());

    let wand2 = MagickWand::new();
    assert!(wand2.read_image("tests/data/IMG_5745_rotl.JPG").is_ok());
    wand2.auto_orient();

    let (distortion, diff) = wand1.compare_images(&wand2, MetricType::RootMeanSquaredErrorMetric);
    assert!(distortion < 0.01);
    assert!(diff.is_some());
}

#[test]
fn test_set_option() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let mut wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    // The jpeg:size option is just a hint.
    wand.set_option("jpeg:size", "128x128").unwrap();
    let blob = wand.write_image_blob("jpeg").unwrap();
    assert!(wand.read_image_blob(&blob).is_ok());
    assert_eq!(192, wand.get_image_width());
    assert_eq!(144, wand.get_image_height());
}

#[test]
fn test_page_geometry() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/rust.gif").is_ok());
    assert_eq!((156, 150, 39, 36), wand.get_image_page()); /* width, height, x offset, y offset */
    assert_eq!(80, wand.get_image_width());
    assert_eq!(76, wand.get_image_height());
}
<commit_msg>test new functionality<commit_after>/*
 * Copyright 2015-2017 Nathan Fiedler
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

extern crate magick_rust;

use magick_rust::{MagickWand, magick_wand_genesis, MetricType, ColorspaceType, FilterType, DitherMethod};

use std::error::Error;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use std::sync::{Once, ONCE_INIT};
use magick_rust::ToMagick;

// Used to make sure MagickWand is initialized exactly once. Note that we
// do not bother shutting down, we simply exit when the tests are done.
static START: Once = ONCE_INIT;

#[test]
fn test_new_drop() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    MagickWand::new();
}

#[test]
fn test_resize_image() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let halfwidth = match wand.get_image_width() {
        1 => 1,
        width => width / 2
    };
    let halfheight = match wand.get_image_height() {
        1 => 1,
        height => height / 2
    };
    wand.resize_image(halfwidth, halfheight, FilterType::LanczosFilter);
    assert_eq!(256, wand.get_image_width());
    assert_eq!(192, wand.get_image_height());
}

#[test]
fn test_read_from_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();

    let path = Path::new("tests/data/IMG_5745.JPG");
    let mut file = match File::open(&path) {
        Err(why) => panic!("couldn't open file: {}", Error::description(&why)),
        Ok(file) => file
    };
    let mut data: Vec<u8> = Vec::new();
    match file.read_to_end(&mut data) {
        Err(why) => panic!("couldn't read file: {}", Error::description(&why)),
        Ok(_) => ()
    };
    assert!(wand.read_image_blob(&data).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_write_image_to_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let blob = wand.write_image_blob("jpeg").unwrap();
    let blob_len = blob.len();
    // There is a slight degree of variability from platform to platform,
    // and version to version of ImageMagick.
    assert!(blob_len > 103000 && blob_len < 105000);
    // should be able to read it back again
    assert!(wand.read_image_blob(&blob).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_write_images_to_blob() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    let blob = wand.write_images_blob("jpeg").unwrap();
    let blob_len = blob.len();
    // There is a slight degree of variability from platform to platform,
    // and version to version of ImageMagick.
    assert!(blob_len > 103000 && blob_len < 105000);
    // should be able to read it back again
    assert!(wand.read_image_blob(&blob).is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
}

#[test]
fn test_fit() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(512, wand.get_image_width());
    assert_eq!(384, wand.get_image_height());
    wand.fit(240, 240);
    assert_eq!(240, wand.get_image_width());
    assert_eq!(180, wand.get_image_height());
}

#[test]
fn test_get_image_property() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    // retrieve a property we know exists
    let found_value = wand.get_image_property("exif:DateTimeOriginal");
    assert!(found_value.is_ok());
    assert_eq!("2014:04:23 13:33:08", found_value.unwrap());
    // retrieve a property that does not exist
    let missing_value = wand.get_image_property("exif:Foobar");
    assert!(missing_value.is_err());
    assert_eq!("missing property", missing_value.unwrap_err());
}

#[test]
fn test_requires_orientation() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(false, wand.requires_orientation());
}

#[test]
fn test_auto_orient() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745_rotl.JPG").is_ok());
    assert_eq!(true, wand.requires_orientation());
    assert!(wand.auto_orient());
    assert_eq!(false, wand.requires_orientation());
}

#[test]
fn test_compare_images() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand1 = MagickWand::new();
    assert!(wand1.read_image("tests/data/IMG_5745.JPG").is_ok());

    let wand2 = MagickWand::new();
    assert!(wand2.read_image("tests/data/IMG_5745_rotl.JPG").is_ok());
    wand2.auto_orient();

    let (distortion, diff) = wand1.compare_images(&wand2, MetricType::RootMeanSquaredErrorMetric);
    assert!(distortion < 0.01);
    assert!(diff.is_some());
}

#[test]
fn test_set_option() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let mut wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    // The jpeg:size option is just a hint.
    wand.set_option("jpeg:size", "128x128").unwrap();
    let blob = wand.write_image_blob("jpeg").unwrap();
    assert!(wand.read_image_blob(&blob).is_ok());
    assert_eq!(192, wand.get_image_width());
    assert_eq!(144, wand.get_image_height());
}

#[test]
fn test_page_geometry() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/rust.gif").is_ok());
    assert_eq!((156, 150, 39, 36), wand.get_image_page()); /* width, height, x offset, y offset */
    assert_eq!(80, wand.get_image_width());
    assert_eq!(76, wand.get_image_height());
}

#[test]
fn test_transform_image_colorspace() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(wand.get_image_colorspace(), ColorspaceType::sRGBColorspace);

    let pixel_color = wand.get_image_pixel_color(10, 10).unwrap();
    assert_ne!(pixel_color.get_hsl().hue, 0.0);

    assert!(wand.transform_image_colorspace(ColorspaceType::GRAYColorspace).is_ok());
    assert_eq!(wand.get_image_colorspace(), ColorspaceType::GRAYColorspace);

    let pixel_grayscale = wand.get_image_pixel_color(10, 10).unwrap();
    assert_eq!(pixel_grayscale.get_hsl().hue, 0.0);

    /* The output of `export_image_pixels` should match
     * `convert -type Grayscale tests/data/IMG_5745.JPG[2x2+0+0] txt:` */
    assert_eq!(wand.export_image_pixels(0, 0, 2, 2, "I").unwrap(),
        vec![212, 212, 210, 210])
}

#[test]
fn test_color_reduction() {
    START.call_once(|| {
        magick_wand_genesis();
    });
    let wand = MagickWand::new();
    assert!(wand.read_image("tests/data/IMG_5745.JPG").is_ok());
    assert_eq!(38322, wand.get_image_colors());

    assert!(wand.quantize_image(6, ColorspaceType::RGBColorspace, 1,
                                DitherMethod::UndefinedDitherMethod, false.to_magick()).is_ok());
    assert_eq!(6, wand.get_image_colors());

    let histogram = wand.get_image_histogram().unwrap();
    assert_eq!(6, histogram.len());
    assert_eq!(wand.get_image_width() * wand.get_image_height(),
               histogram.iter().fold(0, |total_colors, wand| total_colors + wand.get_color_count()));
}
<|endoftext|>


<commit_before>extern crate disasm6502;

#[test]
fn check_disasm() {
    let bytes = vec![0x05, 0x0B, 0x6C, 0x01, 0x02, 0x0A, 0xA2, 0xFF, 0x20, 0x02, 0xFD, 0x78, 0xD0, 0xFC, 0x1D, 0x05, 0x1E, 0x04, 0x15, 0x02, 0x96, 0xAB, 0x58, 0x61, 0x01, 0x91, 0xFB];

    let instructions = disasm6502::from_array(&bytes).unwrap();

    for i in instructions.iter() {
        println!("{}", i);
    }
}

#[test]
fn check_disasm_file() {
    let instructions = disasm6502::from_file("tests/file_test.prg").unwrap();

    for i in instructions.iter() {
        println!("{}", i);
    }
}
<commit_msg>added fail test<commit_after>extern crate disasm6502;

#[test]
fn check_disasm() {
    let bytes = vec![0x05, 0x0B, 0x6C, 0x01, 0x02, 0x0A, 0xA2, 0xFF, 0x20, 0x02, 0xFD, 0x78, 0xD0, 0xFC, 0x1D, 0x05, 0x1E, 0x04, 0x15, 0x02, 0x96, 0xAB, 0x58, 0x61, 0x01, 0x91, 0xFB];

    let instructions = disasm6502::from_array(&bytes).unwrap();

    for i in instructions.iter() {
        println!("{}", i);
    }
}

#[test]
fn check_disasm_file() {
    let instructions = disasm6502::from_file("tests/file_test.prg").unwrap();

    for i in instructions.iter() {
        println!("{}", i);
    }
}

#[test]
#[should_panic]
fn check_disasm_file_fail() {
    let _ = disasm6502::from_file("tests/foo").unwrap(); }
<|endoftext|>