<commit_before>use rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use std::fmt;

#[derive(Clone, Debug, PartialEq)]
pub struct EventID {
    pub id: String,
    pub homeserver: String
}

impl EventID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        EventID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug)]
pub struct UserID {
    pub nickname: String,
    pub homeserver: String
}

impl UserID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        UserID {
            nickname: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RoomID {
    pub id: String,
    pub homeserver: String
}

impl fmt::Display for RoomID {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "!{}:{}", self.id, self.homeserver)
    }
}

impl RoomID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        RoomID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Debug)]
pub enum MembershipAction {
    Join,
    Leave,
    Ban,
    Invite,
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            "leave" => MembershipAction::Leave,
            "ban" => MembershipAction::Ban,
            "invite" => MembershipAction::Invite,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases,
    Message(UserID, String),
    PowerLevels,
    Name(UserID, String),
    Avatar(UserID, String),
    Topic(UserID, String),
    Unknown(Json)
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<UserID>,
    pub room: RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent),
    Unknown(Json)
}

impl EventData {
    pub fn type_str(&self) -> &'static str {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) => {
                "m.room.message"
            },
            _ => unreachable!()
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref id, ref evt) => {
                match evt {
                    &RoomEvent::Message(ref sender, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => unreachable!()
                }
            },
            _ => unreachable!()
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<EventID>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").trim().split(".").collect();
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(EventID::from_str(i.as_string().unwrap())),
            None => None
        };
        if tokens[0] != "m" {
            Event {
                id: id,
                data: EventData::Unknown(json.clone()),
            }
        } else {
            Event {
                id: id,
                data: match tokens[1] {
                    "room" =>
                        Self::from_room_json(tokens[2], json),
                    "typing" =>
                        EventData::Typing(TypingEvent {
                            users: vec![],
                            room: RoomID::from_str(mjson::string(json, "room_id"))
                        }),
                    "presence" =>
                        EventData::Presence(PresenceEvent{
                            presence: mjson::string(json, "content.presence").to_string(),
                            user: UserID::from_str(mjson::string(json, "content.user_id"))
                        }),
                    e => panic!("Unknown event {:?}!\nRaw JSON: {:?}", e, json)
                }
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {
        EventData::Room(
            RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" => {
                        if json.find_path(&["content", "join_rules"]) == None {
                            RoomEvent::Unknown(json.clone())
                        } else {
                            RoomEvent::JoinRules(mjson::string(json, "content.join_rules").to_string())
                        }
                    },
                "member" =>
                    RoomEvent::Membership(UserID::from_str(mjson::string(json, "user_id")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" =>
                    RoomEvent::Aliases,
                "power_levels" =>
                    RoomEvent::PowerLevels,
                "message" =>
                    RoomEvent::Message(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.body").to_string()),
                "name" =>
                    RoomEvent::Name(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.name").to_string()),
                "topic" =>
                    RoomEvent::Topic(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.topic").to_string()),
                "avatar" =>
                    RoomEvent::Avatar(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.url").to_string()),
                e => panic!("Unknown room event {:?}: {:?}", e, json)
            }
        )
    }
}
<commit_msg>events: handle join_rule and join_rules<commit_after>use rustc_serialize::json::Json;
use rustc_serialize::json;
use matrix::json as mjson;
use std::fmt;

#[derive(Clone, Debug, PartialEq)]
pub struct EventID {
    pub id: String,
    pub homeserver: String
}

impl EventID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        EventID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug)]
pub struct UserID {
    pub nickname: String,
    pub homeserver: String
}

impl UserID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        UserID {
            nickname: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct RoomID {
    pub id: String,
    pub homeserver: String
}

impl fmt::Display for RoomID {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "!{}:{}", self.id, self.homeserver)
    }
}

impl RoomID {
    pub fn from_str(s: &str) -> Self {
        let parts: Vec<&str> = s.split(":").collect();
        RoomID {
            id: parts[0][1..].to_string(),
            homeserver: parts[1].to_string()
        }
    }
}

#[derive(Debug)]
pub enum MembershipAction {
    Join,
    Leave,
    Ban,
    Invite,
}

impl MembershipAction {
    pub fn from_str(s: &str) -> Self {
        match s {
            "join" => MembershipAction::Join,
            "leave" => MembershipAction::Leave,
            "ban" => MembershipAction::Ban,
            "invite" => MembershipAction::Invite,
            _ => panic!("unknown membership action {:?}", s)
        }
    }
}

#[derive(Debug)]
pub enum RoomEvent {
    CanonicalAlias(String),
    JoinRules(String),
    Membership(UserID, MembershipAction),
    HistoryVisibility(String),
    Create,
    Aliases,
    Message(UserID, String),
    PowerLevels,
    Name(UserID, String),
    Avatar(UserID, String),
    Topic(UserID, String),
    Unknown(Json)
}

#[derive(Debug)]
pub struct TypingEvent {
    pub users: Vec<UserID>,
    pub room: RoomID,
}

#[derive(Debug)]
pub enum EventData {
    Room(RoomID, RoomEvent),
    Typing(TypingEvent),
    Presence(PresenceEvent),
    Unknown(Json)
}

impl EventData {
    pub fn type_str(&self) -> &'static str {
        match self {
            &EventData::Room(_, RoomEvent::Message(_, _)) => {
                "m.room.message"
            },
            _ => unreachable!()
        }
    }

    pub fn to_json(&self) -> json::Json {
        let mut ret = json::Object::new();
        match self {
            &EventData::Room(ref id, ref evt) => {
                match evt {
                    &RoomEvent::Message(ref sender, ref text) => {
                        ret.insert("msgtype".to_string(), json::Json::String("m.text".to_string()));
                        ret.insert("body".to_string(), json::Json::String(text.clone()));
                    },
                    _ => unreachable!()
                }
            },
            _ => unreachable!()
        }
        json::Json::Object(ret)
    }
}

#[derive(Debug)]
pub struct Event {
    pub id: Option<EventID>,
    pub data: EventData
}

#[derive(Debug)]
pub struct PresenceEvent {
    pub presence: String,
    pub user: UserID
}

impl Event {
    pub fn from_json(json: &Json) -> Self {
        let tokens: Vec<&str> = mjson::string(json, "type").trim().split(".").collect();
        let id = match json.as_object().unwrap().get("event_id") {
            Some(i) => Some(EventID::from_str(i.as_string().unwrap())),
            None => None
        };
        if tokens[0] != "m" {
            Event {
                id: id,
                data: EventData::Unknown(json.clone()),
            }
        } else {
            Event {
                id: id,
                data: match tokens[1] {
                    "room" =>
                        Self::from_room_json(tokens[2], json),
                    "typing" =>
                        EventData::Typing(TypingEvent {
                            users: vec![],
                            room: RoomID::from_str(mjson::string(json, "room_id"))
                        }),
                    "presence" =>
                        EventData::Presence(PresenceEvent{
                            presence: mjson::string(json, "content.presence").to_string(),
                            user: UserID::from_str(mjson::string(json, "content.user_id"))
                        }),
                    e => panic!("Unknown event {:?}!\nRaw JSON: {:?}", e, json)
                }
            }
        }
    }

    fn from_room_json(event_type: &str, json: &Json) -> EventData {
        EventData::Room(
            RoomID::from_str(mjson::string(json, "room_id")),
            match event_type {
                "canonical_alias" =>
                    RoomEvent::CanonicalAlias(mjson::string(json, "content.alias").to_string()),
                "join_rules" => {
                        if json.find_path(&["content", "join_rules"]) == None {
                            RoomEvent::JoinRules(mjson::string(json, "content.join_rule").to_string())
                        } else {
                            RoomEvent::JoinRules(mjson::string(json, "content.join_rules").to_string())
                        }
                    },
                "member" =>
                    RoomEvent::Membership(UserID::from_str(mjson::string(json, "user_id")), MembershipAction::from_str(mjson::string(json, "content.membership"))),
                "history_visibility" =>
                    RoomEvent::HistoryVisibility(mjson::string(json, "content.history_visibility").to_string()),
                "create" =>
                    RoomEvent::Create,
                "aliases" =>
                    RoomEvent::Aliases,
                "power_levels" =>
                    RoomEvent::PowerLevels,
                "message" =>
                    RoomEvent::Message(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.body").to_string()),
                "name" =>
                    RoomEvent::Name(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.name").to_string()),
                "topic" =>
                    RoomEvent::Topic(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.topic").to_string()),
                "avatar" =>
                    RoomEvent::Avatar(UserID::from_str(mjson::string(json, "user_id")), mjson::string(json, "content.url").to_string()),
                e => panic!("Unknown room event {:?}: {:?}", e, json)
            }
        )
    }
}
<|endoftext|>


<commit_before>use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
use std::env;
use std::io;
use std::path::Path;
use std::process::Command;

use Arch::*;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Arch {
    Armv7,
    Armv7s,
    Arm64,
    I386,
    X86_64,
    X86_64_macabi,
}

#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum AppleOS {
    tvOS,
    iOS,
}

impl Arch {
    pub fn to_string(self) -> &'static str {
        match self {
            Armv7 => "armv7",
            Armv7s => "armv7s",
            Arm64 => "arm64",
            I386 => "i386",
            X86_64 => "x86_64",
            X86_64_macabi => "x86_64",
        }
    }
}

pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
    // Following what clang does
    // (https://github.com/llvm/llvm-project/blob/
    // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
    // to allow the SDK path to be set. (For clang, xcrun sets
    // SDKROOT; for rustc, the user or build system can set it, or we
    // can fall back to checking for xcrun on PATH.)
    if let Ok(sdkroot) = env::var("SDKROOT") {
        let p = Path::new(&sdkroot);
        match sdk_name {
            // Ignore `SDKROOT` if it's clearly set for the wrong platform.
            "appletvos"
                if sdkroot.contains("TVSimulator.platform")
                    || sdkroot.contains("MacOSX.platform") => {}
            "appletvsimulator"
                if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {}
            "iphoneos"
                if sdkroot.contains("iPhoneSimulator.platform")
                    || sdkroot.contains("MacOSX.platform") => {}
            "iphonesimulator"
                if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => {
            }
            "macosx10.15"
                if sdkroot.contains("iPhoneOS.platform")
                    || sdkroot.contains("iPhoneSimulator.platform") => {}
            // Ignore `SDKROOT` if it's not a valid path.
            _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
            _ => return Ok(sdkroot),
        }
    }
    let res =
        Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
            |output| {
                if output.status.success() {
                    Ok(String::from_utf8(output.stdout).unwrap())
                } else {
                    let error = String::from_utf8(output.stderr);
                    let error = format!("process exit with error: {}", error.unwrap());
                    Err(io::Error::new(io::ErrorKind::Other, &error[..]))
                }
            },
        );

    match res {
        Ok(output) => Ok(output.trim().to_string()),
        Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
    }
}

fn build_pre_link_args(arch: Arch, os: AppleOS) -> Result<LinkArgs, String> {
    let sdk_name = match (arch, os) {
        (Arm64, AppleOS::tvOS) => "appletvos",
        (X86_64, AppleOS::tvOS) => "appletvsimulator",
        (Armv7, AppleOS::iOS) => "iphoneos",
        (Armv7s, AppleOS::iOS) => "iphoneos",
        (Arm64, AppleOS::iOS) => "iphoneos",
        (I386, AppleOS::iOS) => "iphonesimulator",
        (X86_64, AppleOS::iOS) => "iphonesimulator",
        (X86_64_macabi, AppleOS::iOS) => "macosx10.15",
        _ => unreachable!(),
    };

    let arch_name = arch.to_string();

    let sdk_root = get_sdk_root(sdk_name)?;

    let mut args = LinkArgs::new();
    args.insert(
        LinkerFlavor::Gcc,
        vec![
            "-arch".to_string(),
            arch_name.to_string(),
            "-isysroot".to_string(),
            sdk_root.clone(),
            "-Wl,-syslibroot".to_string(),
            sdk_root,
        ],
    );

    Ok(args)
}

fn target_cpu(arch: Arch) -> String {
    match arch {
        Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
        Armv7s => "cortex-a9",
        Arm64 => "apple-a7",
        I386 => "yonah",
        X86_64 => "core2",
        X86_64_macabi => "core2",
    }
    .to_string()
}

fn link_env_remove(arch: Arch) -> Vec<String> {
    match arch {
        Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
        X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
    }
}

pub fn opts(arch: Arch, os: AppleOS) -> Result<TargetOptions, String> {
    let pre_link_args = build_pre_link_args(arch, os)?;
    Ok(TargetOptions {
        cpu: target_cpu(arch),
        dynamic_linking: false,
        executables: true,
        pre_link_args,
        link_env_remove: link_env_remove(arch),
        has_elf_tls: false,
        eliminate_frame_pointer: false,
        ..super::apple_base::opts()
    })
}
<commit_msg>Allow dynamic linking for iOS/tvOS targets.<commit_after>use crate::spec::{LinkArgs, LinkerFlavor, TargetOptions};
use std::env;
use std::io;
use std::path::Path;
use std::process::Command;

use Arch::*;
#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum Arch {
    Armv7,
    Armv7s,
    Arm64,
    I386,
    X86_64,
    X86_64_macabi,
}

#[allow(non_camel_case_types)]
#[derive(Copy, Clone)]
pub enum AppleOS {
    tvOS,
    iOS,
}

impl Arch {
    pub fn to_string(self) -> &'static str {
        match self {
            Armv7 => "armv7",
            Armv7s => "armv7s",
            Arm64 => "arm64",
            I386 => "i386",
            X86_64 => "x86_64",
            X86_64_macabi => "x86_64",
        }
    }
}

pub fn get_sdk_root(sdk_name: &str) -> Result<String, String> {
    // Following what clang does
    // (https://github.com/llvm/llvm-project/blob/
    // 296a80102a9b72c3eda80558fb78a3ed8849b341/clang/lib/Driver/ToolChains/Darwin.cpp#L1661-L1678)
    // to allow the SDK path to be set. (For clang, xcrun sets
    // SDKROOT; for rustc, the user or build system can set it, or we
    // can fall back to checking for xcrun on PATH.)
    if let Ok(sdkroot) = env::var("SDKROOT") {
        let p = Path::new(&sdkroot);
        match sdk_name {
            // Ignore `SDKROOT` if it's clearly set for the wrong platform.
            "appletvos"
                if sdkroot.contains("TVSimulator.platform")
                    || sdkroot.contains("MacOSX.platform") => {}
            "appletvsimulator"
                if sdkroot.contains("TVOS.platform") || sdkroot.contains("MacOSX.platform") => {}
            "iphoneos"
                if sdkroot.contains("iPhoneSimulator.platform")
                    || sdkroot.contains("MacOSX.platform") => {}
            "iphonesimulator"
                if sdkroot.contains("iPhoneOS.platform") || sdkroot.contains("MacOSX.platform") => {
            }
            "macosx10.15"
                if sdkroot.contains("iPhoneOS.platform")
                    || sdkroot.contains("iPhoneSimulator.platform") => {}
            // Ignore `SDKROOT` if it's not a valid path.
            _ if !p.is_absolute() || p == Path::new("/") || !p.exists() => {}
            _ => return Ok(sdkroot),
        }
    }
    let res =
        Command::new("xcrun").arg("--show-sdk-path").arg("-sdk").arg(sdk_name).output().and_then(
            |output| {
                if output.status.success() {
                    Ok(String::from_utf8(output.stdout).unwrap())
                } else {
                    let error = String::from_utf8(output.stderr);
                    let error = format!("process exit with error: {}", error.unwrap());
                    Err(io::Error::new(io::ErrorKind::Other, &error[..]))
                }
            },
        );

    match res {
        Ok(output) => Ok(output.trim().to_string()),
        Err(e) => Err(format!("failed to get {} SDK path: {}", sdk_name, e)),
    }
}

fn build_pre_link_args(arch: Arch, os: AppleOS) -> Result<LinkArgs, String> {
    let sdk_name = match (arch, os) {
        (Arm64, AppleOS::tvOS) => "appletvos",
        (X86_64, AppleOS::tvOS) => "appletvsimulator",
        (Armv7, AppleOS::iOS) => "iphoneos",
        (Armv7s, AppleOS::iOS) => "iphoneos",
        (Arm64, AppleOS::iOS) => "iphoneos",
        (I386, AppleOS::iOS) => "iphonesimulator",
        (X86_64, AppleOS::iOS) => "iphonesimulator",
        (X86_64_macabi, AppleOS::iOS) => "macosx10.15",
        _ => unreachable!(),
    };

    let arch_name = arch.to_string();

    let sdk_root = get_sdk_root(sdk_name)?;

    let mut args = LinkArgs::new();
    args.insert(
        LinkerFlavor::Gcc,
        vec![
            "-arch".to_string(),
            arch_name.to_string(),
            "-isysroot".to_string(),
            sdk_root.clone(),
            "-Wl,-syslibroot".to_string(),
            sdk_root,
        ],
    );

    Ok(args)
}

fn target_cpu(arch: Arch) -> String {
    match arch {
        Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
        Armv7s => "cortex-a9",
        Arm64 => "apple-a7",
        I386 => "yonah",
        X86_64 => "core2",
        X86_64_macabi => "core2",
    }
    .to_string()
}

fn link_env_remove(arch: Arch) -> Vec<String> {
    match arch {
        Armv7 | Armv7s | Arm64 | I386 | X86_64 => vec!["MACOSX_DEPLOYMENT_TARGET".to_string()],
        X86_64_macabi => vec!["IPHONEOS_DEPLOYMENT_TARGET".to_string()],
    }
}

pub fn opts(arch: Arch, os: AppleOS) -> Result<TargetOptions, String> {
    let pre_link_args = build_pre_link_args(arch, os)?;
    Ok(TargetOptions {
        cpu: target_cpu(arch),
        executables: true,
        pre_link_args,
        link_env_remove: link_env_remove(arch),
        has_elf_tls: false,
        eliminate_frame_pointer: false,
        ..super::apple_base::opts()
    })
}
<|endoftext|>


<commit_before>extern crate ffmpeg;

use std::path::Path;
use std::ops::{Deref, DerefMut};
use std::collections::HashMap;
use std::collections::HashSet;

use std::rc::Weak;
use std::rc::Rc;
use std::cell::RefCell;

use ffmpeg::Rational;
use ffmpeg::format::stream::Disposition;

pub trait PacketNotifiable {
    fn new_packet(&mut self, stream: &ffmpeg::format::stream::Stream, packet: &ffmpeg::codec::packet::Packet) {
        println!("\n* Packet for stream: {}", stream.index());
        println!("\tsize: {} - duration: {}", packet.size(), packet.duration());
        if let Some(data) = packet.data() {
            println!("\tfound data with len: {}", data.len());
        }

        let data_iter = stream.side_data();
        println!("\tside data nb: {}", data_iter.size_hint().0);
    }
}

pub struct Context {
    pub ffmpeg_context: ffmpeg::format::context::Input,
    pub name: String,
    pub description: String,
    pub stream_count: usize,
    pub video_stream: Option<VideoStream>,
    pub audio_stream: Option<AudioStream>,
    pub packet_cb_map: HashMap<usize, Weak<RefCell<PacketNotifiable>>>,
}

impl Context {
    pub fn new(path: &Path) -> Result<Context, String> {
        match ffmpeg::format::input(&path) {
            Ok(ffmpeg_context) => {
                let mut new_ctx = Context{
                    ffmpeg_context: ffmpeg_context,
                    name: String::new(),
                    description: String::new(),
                    stream_count: 0,
                    video_stream: None,
                    audio_stream: None,
                    packet_cb_map: HashMap::new(),
                };

                {
                    let format = new_ctx.ffmpeg_context.format();
                    new_ctx.name = String::from(format.name());
                    new_ctx.description = String::from(format.description());

                    let stream_iter = new_ctx.ffmpeg_context.streams();
                    new_ctx.video_stream = VideoStream::new(&stream_iter);
                    new_ctx.audio_stream = AudioStream::new(&stream_iter);
                    new_ctx.stream_count = stream_iter.size_hint().0;
                }

                // TODO: process metadata

                // TODO: see what we should do with subtitles

                println!("\n*** New media - Input: {} - {}, {} streams",
                         &new_ctx.name, &new_ctx.description, new_ctx.stream_count
                );

                if new_ctx.video_stream.is_some() || new_ctx.audio_stream.is_some() {
                    // TODO: also check for misdetections (detection score)
                    Ok(new_ctx)
                }
                else {
                    Err("Couldn't find any video or audio stream".to_owned())
                }
            },
            Err(error) => {
                Err(format!("{:?}", error))
            },
        }
    }

    pub fn register_packets(
            &mut self, stream_index: usize, to_notify: Rc<RefCell<PacketNotifiable>>) {
        self.packet_cb_map.insert(stream_index, Rc::downgrade(&to_notify));
    }

    // TODO: check if this could be an iterator instead (managed from MainController)
    pub fn preview(&mut self) {
        let mut processed = HashSet::new();

        let packet_iter = self.ffmpeg_context.packets();
        for (stream, packet) in packet_iter {
            let stream_index = stream.index();
            match self.packet_cb_map.get(&stream_index) {
                Some(to_notify_weak) => {
                    match to_notify_weak.upgrade() {
                        Some(to_notify) => {
                            if processed.insert(stream_index) {
                                to_notify.borrow_mut().new_packet(&stream, &packet);
                            }
                        },
                        None =>
                            panic!("Notifiable no longer available for stream {}", stream_index),
                    }
                },
                None => println!("No handler for stream {}", stream_index),
            }

            if processed.len() == 2 {
                // both streams processed
                break;
            }
        }
    }
}

// TODO: use lifetimes to hold ffmped stream and codec within the structure below

#[derive(Debug)]
pub struct Stream {
    pub index: usize,
    pub time_base: Rational,
    pub start_time: i64,
    pub duration: i64,
    pub frames: i64,
    pub disposition: Disposition,
    pub rate: Rational,
    pub discard: ffmpeg::Discard,
    pub avg_frame_rate: Rational,
    pub codec_medium: ffmpeg::media::Type,
    pub codec_id: ffmpeg::codec::Id,
}

impl Stream {
    pub fn new(stream: ffmpeg::format::stream::Stream) -> Stream {
        let codec = stream.codec();
        Stream {
            index: stream.index(),
            time_base: stream.time_base(),
            start_time: stream.start_time(),
            duration: stream.duration(),
            frames: stream.frames(),
            disposition: stream.disposition(),
            discard: stream.discard(),
            rate: stream.rate(),
            avg_frame_rate: stream.avg_frame_rate(),
            codec_medium: codec.medium(),
            codec_id: codec.id(),
        }
    }
}

#[derive(Debug)]
pub struct VideoStream {
    pub stream: Stream,
	pub bit_rate: usize,
	pub max_bit_rate: usize,
	pub delay: usize,
    width: u32,
    height: u32,
    format: ffmpeg::format::Pixel,
    has_b_frames: bool,
    aspect_ratio: ffmpeg::Rational,
    color_space: ffmpeg::color::Space,
    color_range: ffmpeg::color::Range,
    color_primaries: ffmpeg::color::Primaries,
    color_transfer_characteristic: ffmpeg::color::TransferCharacteristic,
    chroma_location: ffmpeg::chroma::Location,
    references: usize,
    intra_dc_precision: u8,
}

impl VideoStream {
    pub fn new(stream_iter: &ffmpeg::format::context::common::StreamIter) -> Option<VideoStream> {
        match stream_iter.best(ffmpeg::media::Type::Video) {
            Some(video_stream) => {
                match video_stream.codec().decoder().video() {
                    Ok(video) => {
                        Some(VideoStream{
                            bit_rate: video.bit_rate(),
                            max_bit_rate: video.max_bit_rate(),
                            delay: video.delay(),
                            width: video.width(),
                            height: video.height(),
                            format: video.format(),
                            has_b_frames: video.has_b_frames(),
                            aspect_ratio: video.aspect_ratio(),
                            color_space: video.color_space(),
                            color_range: video.color_range(),
                            color_primaries: video.color_primaries(),
                            color_transfer_characteristic: video.color_transfer_characteristic(),
                            chroma_location: video.chroma_location(),
                            references: video.references(),
                            intra_dc_precision: video.intra_dc_precision(),
                            stream: Stream::new(video_stream),
                        })
                    },
                    Err(error) => {
                        println!("video stream: {:?}", error);
                        // TODO: should probably panic here
                        None
                    }
                }
            },
            None => None,
        }
    }
}

impl Deref for VideoStream {
	type Target = Stream;

	fn deref(&self) -> &Self::Target {
		&self.stream
	}
}

impl DerefMut for VideoStream {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.stream
	}
}

#[derive(Debug)]
pub struct AudioStream {
    pub stream: Stream,
	pub bit_rate: usize,
	pub max_bit_rate: usize,
	pub delay: usize,
	pub rate: u32,
	pub channels: u16,
	pub format: ffmpeg::format::Sample,
	pub frames: usize,
	pub align: usize,
	pub channel_layout: ffmpeg::ChannelLayout,
    pub frame_start: Option<usize>,
}

impl AudioStream {
    pub fn new(stream_iter: &ffmpeg::format::context::common::StreamIter) -> Option<AudioStream> {
        match stream_iter.best(ffmpeg::media::Type::Audio) {
            Some(audio_stream) => {
                match audio_stream.codec().decoder().audio() {
                    Ok(audio) => {
                        Some(AudioStream{
                            bit_rate: audio.bit_rate(),
                            max_bit_rate: audio.max_bit_rate(),
                            delay: audio.delay(),
                            rate: audio.rate(),
                            channels: audio.channels(),
                            format: audio.format(),
                            frames: audio.frames(),
                            align: audio.align(),
                            channel_layout: audio.channel_layout(),
                            frame_start: audio.frame_start(),
                            stream: Stream::new(audio_stream),
                        })
                    },
                    Err(error) => {
                        println!("audio stream: {:?}", error);
                        // TODO: should probably panic here
                        None
                    }
                }
            },
            None => None,
        }
   }
}

impl Deref for AudioStream {
	type Target = Stream;

	fn deref(&self) -> &Self::Target {
		&self.stream
	}
}

impl DerefMut for AudioStream {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.stream
	}
}
<commit_msg>Get more data from packets' content (#1)<commit_after>extern crate ffmpeg;

use std::path::Path;
use std::ops::{Deref, DerefMut};
use std::collections::HashMap;
use std::collections::HashSet;

use std::rc::Weak;
use std::rc::Rc;
use std::cell::RefCell;

use ffmpeg::Rational;
use ffmpeg::format::stream::Disposition;

pub trait PacketNotifiable {
    fn new_packet(&mut self, stream: &ffmpeg::format::stream::Stream, packet: &ffmpeg::codec::packet::Packet) {
        println!("\n* Packet for stream: {}", stream.index());
        println!("\tsize: {} - duration: {}, is key: {}",
                 packet.size(), packet.duration(), packet.is_key(),
        );
        match packet.pts() {
            Some(pts) => println!("\tpts: {}", pts),
            None => (),
        }
        match packet.dts() {
            Some(dts) => println!("\tdts: {}", dts),
            None => (),
        }
        if let Some(data) = packet.data() {
            println!("\tfound data with len: {}", data.len());
        }

        let data_iter = stream.side_data();
        println!("\tside data nb: {}", data_iter.size_hint().0);
    }
}

pub struct Context {
    pub ffmpeg_context: ffmpeg::format::context::Input,
    pub name: String,
    pub description: String,
    pub stream_count: usize,
    pub video_stream: Option<VideoStream>,
    pub audio_stream: Option<AudioStream>,
    pub packet_cb_map: HashMap<usize, Weak<RefCell<PacketNotifiable>>>,
}

impl Context {
    pub fn new(path: &Path) -> Result<Context, String> {
        match ffmpeg::format::input(&path) {
            Ok(ffmpeg_context) => {
                let mut new_ctx = Context{
                    ffmpeg_context: ffmpeg_context,
                    name: String::new(),
                    description: String::new(),
                    stream_count: 0,
                    video_stream: None,
                    audio_stream: None,
                    packet_cb_map: HashMap::new(),
                };

                {
                    let format = new_ctx.ffmpeg_context.format();
                    new_ctx.name = String::from(format.name());
                    new_ctx.description = String::from(format.description());

                    let stream_iter = new_ctx.ffmpeg_context.streams();
                    new_ctx.video_stream = VideoStream::new(&stream_iter);
                    new_ctx.audio_stream = AudioStream::new(&stream_iter);
                    new_ctx.stream_count = stream_iter.size_hint().0;
                }

                // TODO: process metadata

                // TODO: see what we should do with subtitles

                println!("\n*** New media - Input: {} - {}, {} streams",
                         &new_ctx.name, &new_ctx.description, new_ctx.stream_count
                );

                if new_ctx.video_stream.is_some() || new_ctx.audio_stream.is_some() {
                    // TODO: also check for misdetections (detection score)
                    Ok(new_ctx)
                }
                else {
                    Err("Couldn't find any video or audio stream".to_owned())
                }
            },
            Err(error) => {
                Err(format!("{:?}", error))
            },
        }
    }

    pub fn register_packets(
            &mut self, stream_index: usize, to_notify: Rc<RefCell<PacketNotifiable>>) {
        self.packet_cb_map.insert(stream_index, Rc::downgrade(&to_notify));
    }

    // TODO: check if this could be an iterator instead (managed from MainController)
    pub fn preview(&mut self) {
        let mut processed = HashSet::new();

        let packet_iter = self.ffmpeg_context.packets();
        for (stream, packet) in packet_iter {
            if !packet.is_key() {
                // get a key frame
                continue;
            }
            let stream_index = stream.index();
            match self.packet_cb_map.get(&stream_index) {
                Some(to_notify_weak) => {
                    match to_notify_weak.upgrade() {
                        Some(to_notify) => {
                            if processed.insert(stream_index) {
                                to_notify.borrow_mut().new_packet(&stream, &packet);
                            }
                        },
                        None =>
                            panic!("Notifiable no longer available for stream {}", stream_index),
                    }
                },
                None => println!("No handler for stream {}", stream_index),
            }

            if processed.len() == 2 {
                // both streams processed
                break;
            }
        }
    }
}

// TODO: use lifetimes to hold ffmped stream and codec within the structure below

#[derive(Debug)]
pub struct Stream {
    pub index: usize,
    pub time_base: Rational,
    pub start_time: i64,
    pub duration: i64,
    pub frames: i64,
    pub disposition: Disposition,
    pub rate: Rational,
    pub discard: ffmpeg::Discard,
    pub avg_frame_rate: Rational,
    pub codec_medium: ffmpeg::media::Type,
    pub codec_id: ffmpeg::codec::Id,
}

impl Stream {
    pub fn new(stream: ffmpeg::format::stream::Stream) -> Stream {
        let codec = stream.codec();
        Stream {
            index: stream.index(),
            time_base: stream.time_base(),
            start_time: stream.start_time(),
            duration: stream.duration(),
            frames: stream.frames(),
            disposition: stream.disposition(),
            discard: stream.discard(),
            rate: stream.rate(),
            avg_frame_rate: stream.avg_frame_rate(),
            codec_medium: codec.medium(),
            codec_id: codec.id(),
        }
    }
}

#[derive(Debug)]
pub struct VideoStream {
    pub stream: Stream,
	pub bit_rate: usize,
	pub max_bit_rate: usize,
	pub delay: usize,
    width: u32,
    height: u32,
    format: ffmpeg::format::Pixel,
    has_b_frames: bool,
    aspect_ratio: ffmpeg::Rational,
    color_space: ffmpeg::color::Space,
    color_range: ffmpeg::color::Range,
    color_primaries: ffmpeg::color::Primaries,
    color_transfer_characteristic: ffmpeg::color::TransferCharacteristic,
    chroma_location: ffmpeg::chroma::Location,
    references: usize,
    intra_dc_precision: u8,
}

impl VideoStream {
    pub fn new(stream_iter: &ffmpeg::format::context::common::StreamIter) -> Option<VideoStream> {
        match stream_iter.best(ffmpeg::media::Type::Video) {
            Some(video_stream) => {
                match video_stream.codec().decoder().video() {
                    Ok(video) => {
                        Some(VideoStream{
                            bit_rate: video.bit_rate(),
                            max_bit_rate: video.max_bit_rate(),
                            delay: video.delay(),
                            width: video.width(),
                            height: video.height(),
                            format: video.format(),
                            has_b_frames: video.has_b_frames(),
                            aspect_ratio: video.aspect_ratio(),
                            color_space: video.color_space(),
                            color_range: video.color_range(),
                            color_primaries: video.color_primaries(),
                            color_transfer_characteristic: video.color_transfer_characteristic(),
                            chroma_location: video.chroma_location(),
                            references: video.references(),
                            intra_dc_precision: video.intra_dc_precision(),
                            stream: Stream::new(video_stream),
                        })
                    },
                    Err(error) => {
                        println!("video stream: {:?}", error);
                        // TODO: should probably panic here
                        None
                    }
                }
            },
            None => None,
        }
    }
}

impl Deref for VideoStream {
	type Target = Stream;

	fn deref(&self) -> &Self::Target {
		&self.stream
	}
}

impl DerefMut for VideoStream {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.stream
	}
}

#[derive(Debug)]
pub struct AudioStream {
    pub stream: Stream,
	pub bit_rate: usize,
	pub max_bit_rate: usize,
	pub delay: usize,
	pub rate: u32,
	pub channels: u16,
	pub format: ffmpeg::format::Sample,
	pub frames: usize,
	pub align: usize,
	pub channel_layout: ffmpeg::ChannelLayout,
    pub frame_start: Option<usize>,
}

impl AudioStream {
    pub fn new(stream_iter: &ffmpeg::format::context::common::StreamIter) -> Option<AudioStream> {
        match stream_iter.best(ffmpeg::media::Type::Audio) {
            Some(audio_stream) => {
                match audio_stream.codec().decoder().audio() {
                    Ok(audio) => {
                        Some(AudioStream{
                            bit_rate: audio.bit_rate(),
                            max_bit_rate: audio.max_bit_rate(),
                            delay: audio.delay(),
                            rate: audio.rate(),
                            channels: audio.channels(),
                            format: audio.format(),
                            frames: audio.frames(),
                            align: audio.align(),
                            channel_layout: audio.channel_layout(),
                            frame_start: audio.frame_start(),
                            stream: Stream::new(audio_stream),
                        })
                    },
                    Err(error) => {
                        println!("audio stream: {:?}", error);
                        // TODO: should probably panic here
                        None
                    }
                }
            },
            None => None,
        }
   }
}

impl Deref for AudioStream {
	type Target = Stream;

	fn deref(&self) -> &Self::Target {
		&self.stream
	}
}

impl DerefMut for AudioStream {
	fn deref_mut(&mut self) -> &mut Self::Target {
		&mut self.stream
	}
}
<|endoftext|>


<commit_before>use std::error::Error;
use std::fs;
use std::path::Path;

use package::{ find, version };
use operation::selection;
use paths::{ self, PathAppend };

fn uninstall_package(input: &Package, base_path: &Path) -> Result<bool, String> {
    let installation_path = base_path.to_path_buf().append(&(paths::PACKAGE_INSTALL_DIR.to_string() + &input.name + "/"));
    if installation_path.exists() {
        match fs::remove_dir_all(&installation_path) {
            Ok(x) => x,
            Err(why) => return Err(why.description().to_string())
        }
        return Ok(true)
    }
    return Ok(false);
}

pub fn uninstall(input: &str, base_path: &Path) -> Result<bool, String> {
    let installed_package = try!(version::get_list(&base_path.to_path_buf().append(paths::INSTALLED_PACKAGE_LIST)));
    for pkg in installed_package {
        if &pkg.name == &input {
            return uninstall_package(&pkg, base_path)
        }
    }
    Err("Specified package not installed".to_string())
}<commit_msg>Missing module<commit_after>use std::error::Error;
use std::fs;
use std::path::Path;

use package::{ find, version, pkg };
use package::pkg::{ Package, Version };
use operation::selection;
use paths::{ self, PathAppend };

fn uninstall_package(input: &Package, base_path: &Path) -> Result<bool, String> {
    let installation_path = base_path.to_path_buf().append(&(paths::PACKAGE_INSTALL_DIR.to_string() + &input.name + "/"));
    if installation_path.exists() {
        match fs::remove_dir_all(&installation_path) {
            Ok(x) => x,
            Err(why) => return Err(why.description().to_string())
        }
        return Ok(true)
    }
    return Ok(false);
}

pub fn uninstall(input: &str, base_path: &Path) -> Result<bool, String> {
    let installed_package = try!(version::get_list(&base_path.to_path_buf().append(paths::INSTALLED_PACKAGE_LIST)));
    for pkg in installed_package {
        if &pkg.name == &input {
            return uninstall_package(&pkg, base_path)
        }
    }
    Err("Specified package not installed".to_string())
}<|endoftext|>


<commit_before>//! Features and intervals for gene annotations.

use std::collections::HashMap;

use bio::io::Strand;

/// Builder for exons, transcripts, or genes.
///
/// Use this struct to initialize annotation features with the default values.
pub struct Feature;

impl Feature {

    /// Creates a gene interval with default values.
    ///
    /// A gene interval is a container for transcript intervals.
    ///
    /// # Examples
    ///
    /// ```
    /// let gene = Feature::gene();
    ///
    /// assert_eq!(gene.transcript().len(), 0);
    /// assert_eq!(gene.start(), 0);
    /// assert_eq!(gene.end(), 0);
    /// assert_eq!(gene.name(), None);
    /// ```
    pub fn gene() -> Gene {
        Gene::default()
    }

    /// Creates a transcript interval with default values.
    ///
    /// A transcript interval is a container for exon intervals.
    ///
    /// # Examples
    ///
    /// ```
    /// use bio::io::Strand;
    ///
    /// let transcript = Feature::transcript();
    ///
    /// assert_eq!(transcript.exons().len(), 0);
    /// assert_eq!(transcript.strand(), &Strand::Unknown)
    /// assert_eq!(transcript.start(), 0);
    /// assert_eq!(transcript.end(), 0);
    /// assert_eq!(transcript.name(), None);
    /// ```
    pub fn transcript() -> Transcript {
        Transcript::default()
    }

    /// Creates an exon interval with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// let exon = Feature::exon();
    ///
    /// assert_eq!(exon.start(), 0);
    /// assert_eq!(exon.end(), 0);
    /// assert_eq!(exon.name(), None);
    /// ```
    pub fn exon() -> Exon {
        Exon::default()
    }
}

/// Interface for features with start and end coordinates.
///
/// The intervals represented here are zero-based, half open intervals.
/// Coordinates start from zero and start coordinates must be less than
/// or equal to the end coordinates.
pub trait Interval: Sized {

    /// Start coordinate of the interval.
    fn start(&self) -> u64;

    /// End coordinate of the interval.
    fn end(&self) -> u64;

    /// Performs various validation of the interval.
    fn validate(self) -> Result<Self, &'static str>;

    /// The number of bases covered by the interval.
    fn span(&self) -> u64 {
        self.end() - self.start()
    }

    /// Whether two intervals have an intersection or not.
    fn overlaps(&self, other: &Self) -> bool {
        (other.start() <= self.start() && self.start() <= other.end()) ||
        (other.start() <= self.end() && self.end() <= other.end())
    }

    /// Whether one interval completely contains the other.
    fn envelops(&self, other: &Self) -> bool {
        self.start() <= other.start() && self.end() >= other.end()
    }

    /// Whether two intervals cover a contiguous region without any overlaps.
    fn adjacent(&self, other: &Self) -> bool {
        self.end() == other.start() || self.start() == other.end()
    }

    /// Performs validation of the interval coordinates.
    ///
    /// If the validation fails, an error message is returned within
    /// the `Result` type.
    fn validate_coords(self) -> Result<Self, &'static str> {
        if self.start() > self.end() {
            return Err("interval start coordinate larger than its end coordinate")
        }

        Ok(self)
    }
}

/// Gene annotation.
#[derive(Debug, Default)]
pub struct Gene {
    name: Option<String>,
    start: u64,
    end: u64,
    transcripts: HashMap<String, Transcript>,
}

impl Gene {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn transcripts(&self) -> &HashMap<String, Transcript> {
        &self.transcripts
    }
}

impl Interval for Gene {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let gene = Feature::gene();
        assert_eq!(gene.start(), 0);
        assert_eq!(gene.end(), 0);
        assert_eq!(gene.name(), None);
        assert_eq!(gene.transcripts().len(), 0);
    }
}

/// Transcript annotation.
#[derive(Debug)]
pub struct Transcript {
    name: Option<String>,
    strand: Strand,
    start: u64,
    end: u64,
    cds_start: Option<u64>,
    cds_end: Option<u64>,
    exons: Vec<Exon>,
}

impl Default for Transcript {

    fn default() -> Transcript {
        Transcript {
            name: None,
            strand: Strand::Unknown,
            start: 0,
            end: 0,
            cds_start: None,
            cds_end: None,
            exons: Vec::new(),
        }
    }
}

impl Transcript {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn strand(&self) -> &Strand {
        &self.strand
    }

    pub fn cds_start(&self) -> Option<u64> {
        self.cds_start
    }

    pub fn cds_end(&self) -> Option<u64> {
        self.cds_end
    }

    pub fn exons(&self) -> &Vec<Exon> {
        &self.exons
    }
}

impl Interval for Transcript {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let trx = Feature::transcript();
        assert_eq!(trx.start(), 0);
        assert_eq!(trx.end(), 0);
        assert_eq!(trx.name(), None);
        assert_eq!(trx.strand(), &Strand::Unknown);
        assert_eq!(trx.cds_start(), None);
        assert_eq!(trx.cds_end(), None);
        assert_eq!(trx.exons().len(), 0);
    }
}

/// Exon annotation.
#[derive(Debug, Default)]
pub struct Exon {
    name: Option<String>,
    start: u64,
    end: u64,
}

impl Exon {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn with_name<T>(mut self, n: T) -> Exon
        where T: Into<String>
    {
        self.name = Some(n.into());
        self
    }
}

impl Interval for Exon {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let exon = Feature::exon();
        assert_eq!(exon.start(), 0);
        assert_eq!(exon.end(), 0);
        assert_eq!(exon.name(), None);
    }

    #[test]
    fn with_name() {
        let exon1 = Feature::exon().with_name("ex1");
        assert_eq!(exon1.start(), 0);
        assert_eq!(exon1.end(), 0);
        assert_eq!(exon1.name(), Some("ex1"));

        let exon2 = Feature::exon().with_name("ex2".to_owned());
        assert_eq!(exon2.start(), 0);
        assert_eq!(exon2.end(), 0);
        assert_eq!(exon2.name(), Some("ex2"));
    }
}
<commit_msg>Implement Interval for Feature<commit_after>//! Features and intervals for gene annotations.

use std::collections::HashMap;

use bio::io::Strand;

/// Interface for features with start and end coordinates.
///
/// The intervals represented here are zero-based, half open intervals.
/// Coordinates start from zero and start coordinates must be less than
/// or equal to the end coordinates.
pub trait Interval: Sized {

    /// Start coordinate of the interval.
    fn start(&self) -> u64;

    /// End coordinate of the interval.
    fn end(&self) -> u64;

    /// Performs various validation of the interval.
    fn validate(self) -> Result<Self, &'static str>;

    /// The number of bases covered by the interval.
    fn span(&self) -> u64 {
        self.end() - self.start()
    }

    /// Whether two intervals have an intersection or not.
    fn overlaps(&self, other: &Self) -> bool {
        (other.start() <= self.start() && self.start() <= other.end()) ||
        (other.start() <= self.end() && self.end() <= other.end())
    }

    /// Whether one interval completely contains the other.
    fn envelops(&self, other: &Self) -> bool {
        self.start() <= other.start() && self.end() >= other.end()
    }

    /// Whether two intervals cover a contiguous region without any overlaps.
    fn adjacent(&self, other: &Self) -> bool {
        self.end() == other.start() || self.start() == other.end()
    }

    /// Performs validation of the interval coordinates.
    ///
    /// If the validation fails, an error message is returned within
    /// the `Result` type.
    fn validate_coords(self) -> Result<Self, &'static str> {
        if self.start() > self.end() {
            return Err("interval start coordinate larger than its end coordinate")
        }

        Ok(self)
    }
}

/// Default implementation of the `Interval` trait.
///
/// This struct also provides static methods for creating exons, transcripts, and genes.
#[derive(Debug, Default)]
pub struct Feature {
    start: u64,
    end: u64,
}

impl Feature {

    /// Creates a gene interval with default values.
    ///
    /// A gene interval is a container for transcript intervals.
    ///
    /// # Examples
    ///
    /// ```
    /// let gene = Feature::gene();
    ///
    /// assert_eq!(gene.transcript().len(), 0);
    /// assert_eq!(gene.start(), 0);
    /// assert_eq!(gene.end(), 0);
    /// assert_eq!(gene.name(), None);
    /// ```
    pub fn gene() -> Gene {
        Gene::default()
    }

    /// Creates a transcript interval with default values.
    ///
    /// A transcript interval is a container for exon intervals.
    ///
    /// # Examples
    ///
    /// ```
    /// use bio::io::Strand;
    ///
    /// let transcript = Feature::transcript();
    ///
    /// assert_eq!(transcript.exons().len(), 0);
    /// assert_eq!(transcript.strand(), &Strand::Unknown)
    /// assert_eq!(transcript.start(), 0);
    /// assert_eq!(transcript.end(), 0);
    /// assert_eq!(transcript.name(), None);
    /// ```
    pub fn transcript() -> Transcript {
        Transcript::default()
    }

    /// Creates an exon interval with default values.
    ///
    /// # Examples
    ///
    /// ```
    /// let exon = Feature::exon();
    ///
    /// assert_eq!(exon.start(), 0);
    /// assert_eq!(exon.end(), 0);
    /// assert_eq!(exon.name(), None);
    /// ```
    pub fn exon() -> Exon {
        Exon::default()
    }
}

impl Interval for Feature {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let fx = Feature::default();
        assert_eq!(fx.start(), 0);
        assert_eq!(fx.end(), 0);
        assert!(fx.validate().is_ok());
    }
}

/// Gene annotation.
#[derive(Debug, Default)]
pub struct Gene {
    name: Option<String>,
    start: u64,
    end: u64,
    transcripts: HashMap<String, Transcript>,
}

impl Gene {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn transcripts(&self) -> &HashMap<String, Transcript> {
        &self.transcripts
    }
}

impl Interval for Gene {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let gene = Feature::gene();
        assert_eq!(gene.start(), 0);
        assert_eq!(gene.end(), 0);
        assert_eq!(gene.name(), None);
        assert_eq!(gene.transcripts().len(), 0);
    }
}

/// Transcript annotation.
#[derive(Debug)]
pub struct Transcript {
    name: Option<String>,
    strand: Strand,
    start: u64,
    end: u64,
    cds_start: Option<u64>,
    cds_end: Option<u64>,
    exons: Vec<Exon>,
}

impl Default for Transcript {

    fn default() -> Transcript {
        Transcript {
            name: None,
            strand: Strand::Unknown,
            start: 0,
            end: 0,
            cds_start: None,
            cds_end: None,
            exons: Vec::new(),
        }
    }
}

impl Transcript {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn strand(&self) -> &Strand {
        &self.strand
    }

    pub fn cds_start(&self) -> Option<u64> {
        self.cds_start
    }

    pub fn cds_end(&self) -> Option<u64> {
        self.cds_end
    }

    pub fn exons(&self) -> &Vec<Exon> {
        &self.exons
    }
}

impl Interval for Transcript {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let trx = Feature::transcript();
        assert_eq!(trx.start(), 0);
        assert_eq!(trx.end(), 0);
        assert_eq!(trx.name(), None);
        assert_eq!(trx.strand(), &Strand::Unknown);
        assert_eq!(trx.cds_start(), None);
        assert_eq!(trx.cds_end(), None);
        assert_eq!(trx.exons().len(), 0);
    }
}

/// Exon annotation.
#[derive(Debug, Default)]
pub struct Exon {
    name: Option<String>,
    start: u64,
    end: u64,
}

impl Exon {

    pub fn name(&self) -> Option<&str> {
        self.name.as_ref().map(|n| n.as_str())
    }

    pub fn with_name<T>(mut self, n: T) -> Exon
        where T: Into<String>
    {
        self.name = Some(n.into());
        self
    }
}

impl Interval for Exon {

    fn start(&self) -> u64 {
        self.start
    }

    fn end(&self) -> u64 {
        self.end
    }

    fn validate(self) -> Result<Self, &'static str> {
        self.validate_coords()
    }
}

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

    #[test]
    fn default() {
        let exon = Feature::exon();
        assert_eq!(exon.start(), 0);
        assert_eq!(exon.end(), 0);
        assert_eq!(exon.name(), None);
    }

    #[test]
    fn with_name() {
        let exon1 = Feature::exon().with_name("ex1");
        assert_eq!(exon1.start(), 0);
        assert_eq!(exon1.end(), 0);
        assert_eq!(exon1.name(), Some("ex1"));

        let exon2 = Feature::exon().with_name("ex2".to_owned());
        assert_eq!(exon2.start(), 0);
        assert_eq!(exon2.end(), 0);
        assert_eq!(exon2.name(), Some("ex2"));
    }
}
<|endoftext|>


<commit_before>#[allow(non_camel_case_types)]
pub mod bindgen;

#[cfg(test)]
mod bindgen_test {
    use super::bindgen as bg;
    use std::mem;

    #[test]
    fn ffi_call() {
        let mut cif: bg::ffi_cif = Default::default();
        let mut rc: bg::ffi_arg  = Default::default();
        let mut args: Vec<*mut bg::ffi_type> =
            unsafe {
                vec![&mut bg::ffi_type_sint64]
            };
        let mut values: Vec<i64> = vec![5, 7];

        unsafe {
            bg::ffi_prep_cif(&mut cif,
                             bg::FFI_DEFAULT_ABI,
                             1,
                             &mut bg::ffi_type_sint64,
                             args.as_mut_ptr());

            bg::ffi_call(&mut cif,
                         Some(mem::transmute(add_it)),
                         mem::transmute(&mut rc),
                         mem::transmute(values.as_mut_ptr()));
        }
    }

    extern "C" fn add_it(n: i64) -> i64 {
        n + 1
    }
}
<commit_msg>Able to call function via libffi from Rust<commit_after>#[allow(non_camel_case_types)]
pub mod bindgen;

#[cfg(test)]
mod bindgen_test {
    use super::bindgen as bg;
    use std::mem;

    #[test]
    fn ffi_call() {
        let mut cif: bg::ffi_cif = Default::default();
        let mut rc: i64 = 0;
        let mut args: Vec<*mut bg::ffi_type> =
            vec![ unsafe {&mut bg::ffi_type_sint64}
                , unsafe {&mut bg::ffi_type_sint64} ];
        let mut values: Vec<*mut i64> =
            vec![ &mut 5i64 as *mut i64
                , &mut 7i64 as *mut i64 ];

        unsafe {
            bg::ffi_prep_cif(&mut cif,
                             bg::FFI_DEFAULT_ABI,
                             2,
                             &mut bg::ffi_type_sint64,
                             args.as_mut_ptr());

            bg::ffi_call(&mut cif,
                         mem::transmute(add_it as usize),
                         mem::transmute(&mut rc),
                         mem::transmute(values.as_mut_ptr()));
        }

        assert_eq!(12, rc);
    }

    extern "C" fn add_it(n: i64, m: i64) -> i64 {
        return n + m;
    }
}
<|endoftext|>


<commit_before>//! To run a LOGO program, run:
//!     cargo run --example logo_interpreter -- .\examples\my_logo_program.txt

extern crate turtle;

use turtle::Turtle;
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::collections::VecDeque;

fn main() {
    let mut turtle = Turtle::new();

    let args: Vec<String> = env::args().collect();

    if args.len() != 2 {
        println!("No file provided");
        return
    }

    let path = &args[1];
    let file = File::open(path).expect("Could not open provided program");
    let mut reader = BufReader::new(file);
    loop {
        let mut buffer = String::new();
        let read_bytes = reader.read_line(&mut buffer)
            .expect("Unable read input from stdin");
        if read_bytes == 0 {
            // Reached EOF, stop interpreter
            break;
        }

        let mut cmd_args = buffer.split_whitespace().collect();
        handle_command(&mut turtle, &mut cmd_args);
    }
}

fn handle_command(turtle: &mut Turtle, args: &mut VecDeque<&str>) {
    if args.is_empty() {
        return;
    }
    // We already checked if args is empty, so we can unwrap here without fear
    match args.pop_front().unwrap() {
        "fd" | "forward" => {
            let distance = parse_distance(args.pop_front()
                .expect("Expected a distance value after fd/forward command"));
            turtle.forward(distance)
        },
        "bk" | "back" => {
            let distance = parse_distance(args.pop_front()
                .expect("Expect a distance value after bk/back command"));
            turtle.backward(distance)
        },
        "lt" | "left" => {
            let distance = parse_distance(args.pop_front()
                .expect("Expect a distance value after lt/left command"));
            turtle.left(distance)
        }
        "rt" | "right" => {
            let distance = parse_distance(args.pop_front()
                .expect("Expect a distance value after rt/right command"));
            turtle.right(distance)
        }
        _ => unimplemented!(), //TODO: a couple more commands (no need to do everything)
    }
    // Parse any remaining commands on this line
    handle_command(turtle, args);
}

fn parse_distance(s: &str) -> f64 {
    let dist: f64 = s.parse().unwrap();
    dist
}<commit_msg>Minor asthetic changes<commit_after>//! To run a LOGO program, run:
//!     cargo run --example logo_interpreter -- my_logo_program.txt

extern crate turtle;

use turtle::Turtle;
use std::env;
use std::fs::File;
use std::io::{BufRead, BufReader};
use std::collections::VecDeque;

fn main() {
    let mut turtle = Turtle::new();

    let args: Vec<String> = env::args().collect();

    if args.len() != 2 {
        eprintln!("No file provided");
        std::process::exit(1);
    }

    let path = &args[1];
    let file = File::open(path).expect("Could not open provided program");
    let mut reader = BufReader::new(file);
    loop {
        let mut buffer = String::new();
        let read_bytes = reader.read_line(&mut buffer)
            .expect("Unable read input file");
        if read_bytes == 0 {
            // Reached EOF, stop interpreter
            break;
        }

        let mut cmd_args = buffer.split_whitespace().collect();
        handle_command(&mut turtle, &mut cmd_args);
    }
}

fn handle_command(turtle: &mut Turtle, args: &mut VecDeque<&str>) {
    if args.is_empty() {
        return;
    }
    // We already checked if args is empty, so we can unwrap here without fear
    match args.pop_front().unwrap() {
        "fd" | "forward" => {
            let distance = parse_distance(args.pop_front()
                .expect("Expected a distance value after fd/forward command"));
            turtle.forward(distance);
        },
        "bk" | "back" => {
            let distance = parse_distance(args.pop_front()
                .expect("Expect a distance value after bk/back command"));
            turtle.backward(distance);
        },
        "lt" | "left" => {
            let distance = parse_distance(args.pop_front()
                .expect("Expect a distance value after lt/left command"));
            turtle.left(distance);
        },
        "rt" | "right" => {
            let distance = parse_distance(args.pop_front()
                .expect("Expect a distance value after rt/right command"));
            turtle.right(distance);
        },
        _ => unimplemented!("Use of invalid or unsupported LOGO command"),
    }
    // Parse any remaining commands on this line
    handle_command(turtle, args);
}

fn parse_distance(s: &str) -> f64 {
    let dist: f64 = s.parse().expect("Not a valide number");
    dist
}
<|endoftext|>


<commit_before>//! Allows a future to execute for a maximum amount of time.
//!
//! See [`Timeout`] documentation for more details.
//!
//! [`Timeout`]: struct.Timeout.html

use crate::time::{delay_until, Delay, Duration, Instant};

use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};

/// Require a `Future` to complete before the specified duration has elapsed.
///
/// If the future completes before the duration has elapsed, then the completed
/// value is returned. Otherwise, an error is returned.
///
/// # Cancelation
///
/// Cancelling a timeout is done by dropping the future. No additional cleanup
/// or other work is required.
///
/// The original future may be obtained by calling [`Timeout::into_inner`]. This
/// consumes the `Timeout`.
///
/// # Examples
///
/// Create a new `Timeout` set to expire in 10 milliseconds.
///
/// ```rust
/// use tokio::time::timeout;
/// use tokio::sync::oneshot;
///
/// use std::time::Duration;
///
/// # async fn dox() {
/// let (tx, rx) = oneshot::channel();
/// # tx.send(()).unwrap();
///
/// // Wrap the future with a `Timeout` set to expire in 10 milliseconds.
/// if let Err(_) = timeout(Duration::from_millis(10), rx).await {
///     println!("did not receive value within 10 ms");
/// }
/// # }
/// ```
pub fn timeout<T>(duration: Duration, future: T) -> Timeout<T>
where
    T: Future,
{
    let delay = Delay::new_timeout(Instant::now() + duration, duration);
    Timeout::new_with_delay(future, delay)
}

/// Require a `Future` to complete before the specified instant in time.
///
/// If the future completes before the instant is reached, then the completed
/// value is returned. Otherwise, an error is returned.
///
/// # Cancelation
///
/// Cancelling a timeout is done by dropping the future. No additional cleanup
/// or other work is required.
///
/// The original future may be obtained by calling [`Timeout::into_inner`]. This
/// consumes the `Timeout`.
///
/// # Examples
///
/// Create a new `Timeout` set to expire in 10 milliseconds.
///
/// ```rust
/// use tokio::time::{Instant, timeout_at};
/// use tokio::sync::oneshot;
///
/// use std::time::Duration;
///
/// # async fn dox() {
/// let (tx, rx) = oneshot::channel();
/// # tx.send(()).unwrap();
///
/// // Wrap the future with a `Timeout` set to expire 10 milliseconds into the
/// // future.
/// if let Err(_) = timeout_at(Instant::now() + Duration::from_millis(10), rx).await {
///     println!("did not receive value within 10 ms");
/// }
/// # }
/// ```
pub fn timeout_at<T>(deadline: Instant, future: T) -> Timeout<T>
where
    T: Future,
{
    let delay = delay_until(deadline);

    Timeout {
        value: future,
        delay,
    }
}

/// Future returned by [`timeout`](timeout) and [`timeout_at`](timeout_at).
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct Timeout<T> {
    value: T,
    delay: Delay,
}

/// Error returned by `Timeout`.
#[derive(Debug, PartialEq)]
pub struct Elapsed(());

impl Elapsed {
    // Used on StreamExt::timeout
    #[allow(unused)]
    pub(crate) fn new() -> Self {
        Elapsed(())
    }
}

impl<T> Timeout<T> {
    pub(crate) fn new_with_delay(value: T, delay: Delay) -> Timeout<T> {
        Timeout { value, delay }
    }

    /// Gets a reference to the underlying value in this timeout.
    pub fn get_ref(&self) -> &T {
        &self.value
    }

    /// Gets a mutable reference to the underlying value in this timeout.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.value
    }

    /// Consumes this timeout, returning the underlying value.
    pub fn into_inner(self) -> T {
        self.value
    }
}

impl<T> Future for Timeout<T>
where
    T: Future,
{
    type Output = Result<T::Output, Elapsed>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // First, try polling the future

        // Safety: we never move `self.value`
        unsafe {
            let p = self.as_mut().map_unchecked_mut(|me| &mut me.value);
            if let Poll::Ready(v) = p.poll(cx) {
                return Poll::Ready(Ok(v));
            }
        }

        // Now check the timer
        // Safety: X_X!
        unsafe {
            match self.map_unchecked_mut(|me| &mut me.delay).poll(cx) {
                Poll::Ready(()) => Poll::Ready(Err(Elapsed(()))),
                Poll::Pending => Poll::Pending,
            }
        }
    }
}

// ===== impl Elapsed =====

impl fmt::Display for Elapsed {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        "deadline has elapsed".fmt(fmt)
    }
}

impl std::error::Error for Elapsed {}

impl From<Elapsed> for std::io::Error {
    fn from(_err: Elapsed) -> std::io::Error {
        std::io::ErrorKind::TimedOut.into()
    }
}
<commit_msg>time: Add comment about cancelation of timed out futures (#2206)<commit_after>//! Allows a future to execute for a maximum amount of time.
//!
//! See [`Timeout`] documentation for more details.
//!
//! [`Timeout`]: struct.Timeout.html

use crate::time::{delay_until, Delay, Duration, Instant};

use std::fmt;
use std::future::Future;
use std::pin::Pin;
use std::task::{self, Poll};

/// Require a `Future` to complete before the specified duration has elapsed.
///
/// If the future completes before the duration has elapsed, then the completed
/// value is returned. Otherwise, an error is returned and the future is
/// canceled.
///
/// # Cancelation
///
/// Cancelling a timeout is done by dropping the future. No additional cleanup
/// or other work is required.
///
/// The original future may be obtained by calling [`Timeout::into_inner`]. This
/// consumes the `Timeout`.
///
/// # Examples
///
/// Create a new `Timeout` set to expire in 10 milliseconds.
///
/// ```rust
/// use tokio::time::timeout;
/// use tokio::sync::oneshot;
///
/// use std::time::Duration;
///
/// # async fn dox() {
/// let (tx, rx) = oneshot::channel();
/// # tx.send(()).unwrap();
///
/// // Wrap the future with a `Timeout` set to expire in 10 milliseconds.
/// if let Err(_) = timeout(Duration::from_millis(10), rx).await {
///     println!("did not receive value within 10 ms");
/// }
/// # }
/// ```
pub fn timeout<T>(duration: Duration, future: T) -> Timeout<T>
where
    T: Future,
{
    let delay = Delay::new_timeout(Instant::now() + duration, duration);
    Timeout::new_with_delay(future, delay)
}

/// Require a `Future` to complete before the specified instant in time.
///
/// If the future completes before the instant is reached, then the completed
/// value is returned. Otherwise, an error is returned.
///
/// # Cancelation
///
/// Cancelling a timeout is done by dropping the future. No additional cleanup
/// or other work is required.
///
/// The original future may be obtained by calling [`Timeout::into_inner`]. This
/// consumes the `Timeout`.
///
/// # Examples
///
/// Create a new `Timeout` set to expire in 10 milliseconds.
///
/// ```rust
/// use tokio::time::{Instant, timeout_at};
/// use tokio::sync::oneshot;
///
/// use std::time::Duration;
///
/// # async fn dox() {
/// let (tx, rx) = oneshot::channel();
/// # tx.send(()).unwrap();
///
/// // Wrap the future with a `Timeout` set to expire 10 milliseconds into the
/// // future.
/// if let Err(_) = timeout_at(Instant::now() + Duration::from_millis(10), rx).await {
///     println!("did not receive value within 10 ms");
/// }
/// # }
/// ```
pub fn timeout_at<T>(deadline: Instant, future: T) -> Timeout<T>
where
    T: Future,
{
    let delay = delay_until(deadline);

    Timeout {
        value: future,
        delay,
    }
}

/// Future returned by [`timeout`](timeout) and [`timeout_at`](timeout_at).
#[must_use = "futures do nothing unless you `.await` or poll them"]
#[derive(Debug)]
pub struct Timeout<T> {
    value: T,
    delay: Delay,
}

/// Error returned by `Timeout`.
#[derive(Debug, PartialEq)]
pub struct Elapsed(());

impl Elapsed {
    // Used on StreamExt::timeout
    #[allow(unused)]
    pub(crate) fn new() -> Self {
        Elapsed(())
    }
}

impl<T> Timeout<T> {
    pub(crate) fn new_with_delay(value: T, delay: Delay) -> Timeout<T> {
        Timeout { value, delay }
    }

    /// Gets a reference to the underlying value in this timeout.
    pub fn get_ref(&self) -> &T {
        &self.value
    }

    /// Gets a mutable reference to the underlying value in this timeout.
    pub fn get_mut(&mut self) -> &mut T {
        &mut self.value
    }

    /// Consumes this timeout, returning the underlying value.
    pub fn into_inner(self) -> T {
        self.value
    }
}

impl<T> Future for Timeout<T>
where
    T: Future,
{
    type Output = Result<T::Output, Elapsed>;

    fn poll(mut self: Pin<&mut Self>, cx: &mut task::Context<'_>) -> Poll<Self::Output> {
        // First, try polling the future

        // Safety: we never move `self.value`
        unsafe {
            let p = self.as_mut().map_unchecked_mut(|me| &mut me.value);
            if let Poll::Ready(v) = p.poll(cx) {
                return Poll::Ready(Ok(v));
            }
        }

        // Now check the timer
        // Safety: X_X!
        unsafe {
            match self.map_unchecked_mut(|me| &mut me.delay).poll(cx) {
                Poll::Ready(()) => Poll::Ready(Err(Elapsed(()))),
                Poll::Pending => Poll::Pending,
            }
        }
    }
}

// ===== impl Elapsed =====

impl fmt::Display for Elapsed {
    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
        "deadline has elapsed".fmt(fmt)
    }
}

impl std::error::Error for Elapsed {}

impl From<Elapsed> for std::io::Error {
    fn from(_err: Elapsed) -> std::io::Error {
        std::io::ErrorKind::TimedOut.into()
    }
}
<|endoftext|>


<commit_before>//! Messaging primitives for discovering devices and services.

use std::io::{self};
use std::net::{self, SocketAddr, Ipv4Addr};

use net::connector::{UdpConnector};

mod notify;
mod search;
mod ssdp;

pub use message::search::{SearchRequest, SearchResponse};
pub use message::notify::{NotifyMessage, NotifyListener};

/// Multicast Socket Information
const UPNP_MULTICAST_ADDR: &'static str = "239.255.255.250";
const UPNP_MULTICAST_PORT: u16          = 1900;

/// Default TTL For Multicast
const UPNP_MULTICAST_TTL: i32 = 2;

/// Enumerates different types of SSDP messages.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub enum MessageType {
    /// A notify message.
    Notify,
    /// A search message.
    Search,
    /// A response to a search message.
    Response
}

/// Generate UdpConnector objects for all local IPv4 interfaces.
fn all_local_connectors(multicast_ttl: Option<i32>) -> io::Result<Vec<UdpConnector>> {
    map_local_ipv4(|&addr| UdpConnector::new((addr, 0), multicast_ttl))
}

/// Generate a list of some object R constructed from all local Ipv4Addr objects.
///
/// If any of the SocketAddrs fail to resolve, this function will not return an error.
fn map_local_ipv4<F, R>(mut f: F) -> io::Result<Vec<R>>
    where F: FnMut(&Ipv4Addr) -> io::Result<R> {
    let host_iter = try!(net::lookup_host(""));
    let mut obj_list = match host_iter.size_hint() {
        (_, Some(n)) => Vec::with_capacity(n),
        (_, None)    => Vec::new()
    };

    for host in host_iter.filter_map(|host| host.ok()) {
        match host {
            SocketAddr::V4(n) => obj_list.push(try!(f(n.ip()))),
            _ => ()
        }
    }

    Ok(obj_list)
}<commit_msg>fix: `failed to lookup address information` error<commit_after>//! Messaging primitives for discovering devices and services.

use std::io::{self};
use std::net::{self, SocketAddr, Ipv4Addr};

use net::connector::{UdpConnector};

mod notify;
mod search;
mod ssdp;

pub use message::search::{SearchRequest, SearchResponse};
pub use message::notify::{NotifyMessage, NotifyListener};

/// Multicast Socket Information
const UPNP_MULTICAST_ADDR: &'static str = "239.255.255.250";
const UPNP_MULTICAST_PORT: u16          = 1900;

/// Default TTL For Multicast
const UPNP_MULTICAST_TTL: i32 = 2;

/// Enumerates different types of SSDP messages.
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub enum MessageType {
    /// A notify message.
    Notify,
    /// A search message.
    Search,
    /// A response to a search message.
    Response
}

/// Generate UdpConnector objects for all local IPv4 interfaces.
fn all_local_connectors(multicast_ttl: Option<i32>) -> io::Result<Vec<UdpConnector>> {
    map_local_ipv4(|&addr| UdpConnector::new((addr, 0), multicast_ttl))
}

/// Generate a list of some object R constructed from all local Ipv4Addr objects.
///
/// If any of the SocketAddrs fail to resolve, this function will not return an error.
fn map_local_ipv4<F, R>(mut f: F) -> io::Result<Vec<R>>
    where F: FnMut(&Ipv4Addr) -> io::Result<R> {
    let host_iter = try!(net::lookup_host("localhost"));
    let mut obj_list = match host_iter.size_hint() {
        (_, Some(n)) => Vec::with_capacity(n),
        (_, None)    => Vec::new()
    };

    for host in host_iter.filter_map(|host| host.ok()) {
        match host {
            SocketAddr::V4(n) => obj_list.push(try!(f(n.ip()))),
            _ => ()
        }
    }

    Ok(obj_list)
}
<|endoftext|>