Update dependencies

[?]
Jun 15, 2019, 5:30 AM
5WHNHD42CNHXA7YL5T2OZ3KZXEMTI4AYPTR2DWMDEJ4235THRSBQC

Dependencies

  • [2] SH3LIQ4S Starting commands support
  • [3] FVVPKFTL Initial commit
  • [4] CCLGGFKR Move out XmppConnection into own file
  • [5] DCGEFPRC Better README
  • [6] LL3D5CXK Staring using element processor
  • [7] LQXBWNFT Remove unneeded requirement
  • [8] RQZCVDFD Implement applying timeout for expired iq await
  • [9] FV6BJ5K6 Send self-presence and store account info in Rc so it willbe used in some future in parallel
  • [10] GXQCDLYQ Use element processor for incoming iq get
  • [11] VW7NVWAG Leave MUC properly
  • [12] WDCZNZOP Fix rustdoc
  • [13] TPVUBB3F Answer to ping requests
  • [14] ZT3YEIVX Consume connection on processing command
  • [15] 5GINRCKL Send ping XEP-0199
  • [16] 5Y6YJ6UH Add shutdown function to make actions before offline
  • [17] 4IPZTMFI Update dependencies
  • [18] BYJPYYSM Process iq ping response
  • [19] 6UKCVM6E Use new iq processng for initial roster
  • [20] YEMBT7TB Add support for XEP-0092: Software Version
  • [21] HKSQO7JZ Enable hyper http server and configuration
  • [22] LNUU5R56 Support disco#info from XEP-0030 Service Discovery
  • [23] PJV5HPIF Starting to imlements timeouts for iqs
  • [24] SSOKGGCE Update dependencies
  • [25] AA2ZWGRL Enter to MUC
  • [26] WBU7UOQW Read chatroom from config
  • [27] DYRPAV6T Update dependencies
  • [28] JD62RVOJ Update dependencies
  • [29] YTN366WA Support disco#items
  • [30] 2THKW66M Ignore .orig files
  • [31] 5A5UVGNM Move receiver closing logic out of xmpp processing
  • [32] FCPF2FV6 Break connection on iq error
  • [33] GVZ4JAR5 Process self-presence with incoming stanza processor
  • [34] X6L47BHQ Use different structure for established xmpp connection
  • [35] S754Y5DF Refactor IQ processing Always answer to set and get requests. Use XML encoding for stanzas.
  • [36] VS6AHRWI Move XMPP to separate dir
  • [37] DISBBP3I Update dependencies
  • [38] HDLI2X4H Ignore delayed XEP-0203 messages
  • [39] Z3NQEYVI Rename IqSetHandler to IqResuestHandler as it should provide both get and set handling
  • [40] JY4F7VBC Use element processor for incoming iq set
  • [41] 3DSOPLCG Add rustdoc
  • [42] RRLRZTMR Use element processor for iq
  • [43] ZFBPXPAD Cleanup timeouted iq requests with ping Output elapsed time. Refactor iq handling.
  • [44] AEH7WP42 Make element processors static
  • [45] QDHDTOLM Starting support for commands XEP-0050: Ad-Hoc Commands (there no support in xmpp_parsers still)
  • [46] DCMDASHV Mention XEP-0050 and XEP-0203 support
  • [47] OFLAP2G2 Fix possible utf8 errors
  • [48] PLWPCM47 Add id to initital presence

Change contents

  • replacement in src/xmpp/xmpp_connection.rs at line 0
    [3.21][2.0:38895]()
    use tokio_xmpp::{Client, Event, Packet};
    use tokio::prelude::future::{self, Either};
    use tokio::prelude::stream;
    use tokio::prelude::{Future, Stream};
    use std::collections::{HashMap, VecDeque};
    use std::time::{Duration, Instant};
    use super::stanzas;
    use super::element_processor;
    use crate::config;
    #[derive(Debug)]
    pub enum XmppCommand {
    /// Send message to someone by jid
    Chat {
    xmpp_to: xmpp_parsers::Jid,
    message: String,
    },
    /// Send message to MUC
    Chatroom { muc_id: String, message: String },
    /// Send ping request to the server to test connection
    Ping,
    /// Check iq requests if some have expired timeouts
    TimeoutCleanup,
    }
    /// trait of processing iq
    /// each function consumes handlers and
    /// returns false if connection should be reset
    trait IqHandler {
    /// process result
    fn result(
    self: Box<Self>,
    conn: &mut XmppConnection,
    opt_element: Option<xmpp_parsers::Element>,
    ) -> bool;
    /// process error
    fn error(
    self: Box<Self>,
    conn: &mut XmppConnection,
    error: xmpp_parsers::stanza_error::StanzaError,
    ) -> bool;
    /// process tmeout
    fn timeout(self: Box<Self>, conn: &mut XmppConnection) -> bool;
    }
    struct AddRosterIqHandler {
    jid: xmpp_parsers::Jid,
    }
    impl IqHandler for AddRosterIqHandler {
    fn result(
    self: Box<Self>,
    conn: &mut XmppConnection,
    opt_element: Option<xmpp_parsers::Element>,
    ) -> bool {
    match opt_element {
    Some(element) => {
    warn!(
    "Wrong payload when adding {} to roster: {}",
    self.jid,
    String::from(&element)
    );
    }
    None => {
    if conn.state.data.roster.contains_key(&self.jid) {
    info!("Jid {} updated to roster", self.jid);
    } else {
    info!("Jid {} added in roster", self.jid);
    conn.state.data.roster.insert(
    self.jid.clone(),
    (
    xmpp_parsers::roster::Subscription::None,
    xmpp_parsers::roster::Ask::None,
    ),
    );
    }
    conn.process_jid(&self.jid);
    }
    }
    true
    }
    fn error(
    self: Box<Self>,
    _conn: &mut XmppConnection,
    _error: xmpp_parsers::stanza_error::StanzaError,
    ) -> bool {
    true
    }
    fn timeout(self: Box<Self>, _conn: &mut XmppConnection) -> bool {
    true // ignore
    }
    }
    struct PingIqHandler {}
    impl IqHandler for PingIqHandler {
    fn result(
    self: Box<Self>,
    _conn: &mut XmppConnection,
    _opt_element: Option<xmpp_parsers::Element>,
    ) -> bool {
    info!("ping successed");
    true
    }
    fn error(
    self: Box<Self>,
    _conn: &mut XmppConnection,
    _error: xmpp_parsers::stanza_error::StanzaError,
    ) -> bool {
    false
    }
    fn timeout(self: Box<Self>, _conn: &mut XmppConnection) -> bool {
    false
    }
    }
    struct InitRosterIqHandler {}
    impl IqHandler for InitRosterIqHandler {
    fn result(
    self: Box<Self>,
    conn: &mut XmppConnection,
    opt_element: Option<xmpp_parsers::Element>,
    ) -> bool {
    if let Some(result) = opt_element {
    use std::convert::TryInto;
    match result.try_into() as Result<xmpp_parsers::roster::Roster, _> {
    Ok(roster) => {
    conn.state.data.roster_init = true;
    conn.state.data.roster.clear();
    info!("Got first roster:");
    for i in roster.items {
    info!(" >>> {:?}", i);
    conn.state
    .data
    .roster
    .insert(i.jid, (i.subscription, i.ask));
    }
    true
    }
    Err(e) => {
    error!("Cann't parse roster: {}", e);
    false
    }
    }
    } else {
    error!("No roster responded");
    false
    }
    }
    fn error(
    self: Box<Self>,
    _conn: &mut XmppConnection,
    _error: xmpp_parsers::stanza_error::StanzaError,
    ) -> bool {
    false
    }
    fn timeout(self: Box<Self>, _conn: &mut XmppConnection) -> bool {
    false
    }
    }
    #[derive(Default)]
    struct XmppData {
    /// known roster data
    roster: HashMap<
    xmpp_parsers::Jid,
    (
    xmpp_parsers::roster::Subscription,
    xmpp_parsers::roster::Ask,
    ),
    >,
    /// if roster was initialized
    /// ToDo: remove it as it is used only for initialization
    roster_init: bool,
    /// if self-presence accepted
    /// ToDo: remove it as it is used only for initialization
    self_presence: bool,
    /// ids counter
    counter: usize,
    /// stanzas to send
    send_queue: VecDeque<minidom::Element>,
    /// outgoing mailbox
    outgoing_mailbox: HashMap<xmpp_parsers::Jid, Vec<String>>,
    /// muc id to muc jid
    mucs: HashMap<String, xmpp_parsers::Jid>,
    /// map from iq's id to handler of this type of iqs
    pending_ids: HashMap<String, (Instant, Box<dyn IqHandler>)>,
    }
    struct XmppState {
    client: Client,
    data: XmppData,
    }
    pub struct XmppConnection {
    account: std::rc::Rc<config::Account>,
    state: XmppState,
    }
    trait IqRequestHandler {
    fn process(
    self: Box<Self>,
    conn: &mut XmppConnection,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    ) -> xmpp_parsers::iq::Iq;
    }
    struct IqRequestUnknown {
    element: xmpp_parsers::Element,
    type_: &'static str,
    }
    impl IqRequestHandler for IqRequestUnknown {
    fn process(
    self: Box<Self>,
    conn: &mut XmppConnection,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    ) -> xmpp_parsers::iq::Iq {
    warn!(
    "Unsupported IQ {} request from {:?}: {}",
    self.type_,
    from,
    String::from(&self.element)
    );
    stanzas::make_iq_unsupported_error(id, conn.state.client.jid.clone(), from)
    }
    }
    struct IqSetRoster {}
    impl IqRequestHandler for IqSetRoster {
    fn process(
    self: Box<Self>,
    conn: &mut XmppConnection,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    ) -> xmpp_parsers::iq::Iq {
    info!("Got roster push {} from {:?}", id, from);
    stanzas::make_roster_push_answer(id, conn.state.client.jid.clone(), from)
    }
    }
    struct IqGetPing {}
    impl IqRequestHandler for IqGetPing {
    fn process(
    self: Box<Self>,
    conn: &mut XmppConnection,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    ) -> xmpp_parsers::iq::Iq {
    info!("Got ping {} from {:?}", id, from);
    stanzas::make_pong(id, conn.state.client.jid.clone(), from)
    }
    }
    struct IqGetVersion {}
    impl IqRequestHandler for IqGetVersion {
    fn process(
    self: Box<Self>,
    conn: &mut XmppConnection,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    ) -> xmpp_parsers::iq::Iq {
    info!("Got version query {} from {:?}", id, from);
    stanzas::make_version(id, conn.state.client.jid.clone(), from)
    }
    }
    struct IqGetDiscoInfo {}
    impl IqRequestHandler for IqGetDiscoInfo {
    fn process(
    self: Box<Self>,
    conn: &mut XmppConnection,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    ) -> xmpp_parsers::iq::Iq {
    info!("Got disco query {} from {:?}", id, from);
    stanzas::make_disco_info_result(id, conn.state.client.jid.clone(), from)
    }
    }
    struct IqGetDiscoItems {}
    impl IqRequestHandler for IqGetDiscoItems {
    fn process(
    self: Box<Self>,
    conn: &mut XmppConnection,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    ) -> xmpp_parsers::iq::Iq {
    info!("Got disco items query {} from {:?}", id, from);
    stanzas::make_disco_items_result(id, conn.state.client.jid.clone(), from)
    }
    }
    lazy_static! {
    static ref INCOMING: element_processor::Processor<XmppConnection, bool, xmpp_parsers::Element> = {
    let mut incoming = element_processor::Processor::new(&|_, e| {
    warn!("Unknown stanza {}", String::from(&e));
    true
    });
    incoming.register(&XmppConnection::incoming_iq_processing);
    incoming.register(&XmppConnection::incoming_presence_processing);
    incoming.register(&XmppConnection::incoming_message_processing);
    incoming
    };
    static ref INCOMING_IQ_SET: element_processor::Processor<XmppConnection, Box<dyn IqRequestHandler>, xmpp_parsers::Element> = {
    let mut iq_set =
    element_processor::Processor::new(&|_conn: &mut XmppConnection, element| {
    Box::new(IqRequestUnknown {
    element,
    type_: "set",
    }) as Box<dyn IqRequestHandler>
    });
    iq_set.register(&XmppConnection::incoming_iq_processing_set_roster);
    iq_set
    };
    static ref INCOMING_IQ_GET: element_processor::Processor<XmppConnection, Box<dyn IqRequestHandler>, xmpp_parsers::Element> = {
    let mut iq_get =
    element_processor::Processor::new(&|_conn: &mut XmppConnection, element| {
    Box::new(IqRequestUnknown {
    element,
    type_: "get",
    }) as Box<dyn IqRequestHandler>
    });
    iq_get.register(&XmppConnection::incoming_iq_processing_get_ping);
    iq_get.register(&XmppConnection::incoming_iq_processing_get_disco_info);
    iq_get.register(&XmppConnection::incoming_iq_processing_get_disco_items);
    iq_get.register(&XmppConnection::incoming_iq_processing_get_version);
    iq_get
    };
    }
    pub struct MaybeXmppConnection {
    account: std::rc::Rc<config::Account>,
    state: Option<XmppState>,
    }
    impl From<XmppConnection> for MaybeXmppConnection {
    fn from(from: XmppConnection) -> MaybeXmppConnection {
    MaybeXmppConnection {
    account: from.account,
    state: Some(from.state),
    }
    }
    }
    impl From<config::Account> for MaybeXmppConnection {
    fn from(from: config::Account) -> MaybeXmppConnection {
    MaybeXmppConnection {
    account: std::rc::Rc::new(from),
    state: None,
    }
    }
    }
    impl From<std::rc::Rc<config::Account>> for MaybeXmppConnection {
    fn from(from: std::rc::Rc<config::Account>) -> MaybeXmppConnection {
    MaybeXmppConnection {
    account: from,
    state: None,
    }
    }
    }
    impl MaybeXmppConnection {
    /// connects if nothing connected
    /// don't connect only if stop_future resolved
    pub fn connect<F>(
    self,
    stop_future: F,
    ) -> impl Future<Item = XmppConnection, Error = failure::Error>
    where
    F: future::Future + Clone + 'static,
    <F as hyper::rt::Future>::Error: Into<failure::Error> + Send,
    {
    info!("xmpp connection...");
    let MaybeXmppConnection { account, state } = self;
    if let Some(state) = state {
    Box::new(future::ok(XmppConnection { account, state }))
    as Box<dyn Future<Item = _, Error = _>>
    } else {
    Box::new(
    stop_future
    .clone()
    .select2(
    future::loop_fn(account, move |account| {
    info!("xmpp initialization...");
    let client =
    Client::new_with_jid(account.jid.clone(), &account.password);
    info!("xmpp initialized");
    let stop_future2 = stop_future.clone();
    let stop_future3 = stop_future.clone();
    let stop_future4 = stop_future.clone();
    // future to wait for online
    Box::new(
    XmppConnection {
    state: XmppState {
    client,
    data: std::default::Default::default(),
    },
    account,
    }
    .processing(XmppConnection::online, stop_future.clone())
    .map_err(|(acc, _)| acc)
    .and_then(|(conn, r)| match r {
    Ok(Either::A(_)) => future::ok(conn),
    Ok(Either::B(_)) => future::err(conn.account),
    Err(_e) => future::err(conn.account),
    })
    .and_then(|conn| conn.initial_roster(stop_future2))
    .and_then(|conn| conn.self_presence(stop_future3))
    .and_then(|conn| conn.enter_mucs(stop_future4))
    .then(|r| match r {
    Ok(conn) => future::ok(future::Loop::Break(conn)),
    Err(acc) => future::ok(future::Loop::Continue(acc)),
    }),
    )
    })
    .map_err(|_: ()| ()),
    )
    .then(|r| match r {
    Ok(Either::A((_x, _b))) => future::err(format_err!("Stop XMMP connection")),
    Ok(Either::B((x, _a))) => future::ok(x),
    Err(Either::A((e, _b))) => future::err(e.into()),
    Err(Either::B((_, _a))) => {
    future::err(format_err!("Cann't initiate XMPP connection"))
    }
    }),
    )
    }
    }
    }
    impl XmppConnection {
    /// base XMPP processing
    /// Returns false on error to disconnect
    fn xmpp_processing(&mut self, event: &Event) -> bool {
    match event {
    Event::Stanza(stanza) => INCOMING.process(self, stanza.clone()),
    Event::Online => true,
    e => {
    warn!("Unexpected event {:?}", e);
    false
    }
    }
    }
    /// Process roster push
    /// see RFC 6212 2.1.6. Roster Push
    fn incoming_iq_processing_set_roster(
    &mut self,
    roster: xmpp_parsers::roster::Roster,
    ) -> Box<dyn IqRequestHandler> {
    for i in roster.items {
    if let Some(ref mut rdata) = self.state.data.roster.get_mut(&i.jid) {
    info!("Update {} in roster", i.jid);
    rdata.0 = i.subscription;
    rdata.1 = i.ask;
    } else {
    info!("Add {} to roster", i.jid);
    self.state
    .data
    .roster
    .insert(i.jid.clone(), (i.subscription, i.ask));
    }
    self.process_jid(&i.jid);
    }
    Box::new(IqSetRoster {})
    }
    /// Enforce to answer to IQ "set"
    fn incoming_iq_processing_set(
    &mut self,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    element: minidom::Element,
    ) -> xmpp_parsers::iq::Iq {
    INCOMING_IQ_SET
    .process(self, element)
    .process(self, id, from)
    }
    /// Process ping request
    /// see XEP-0199: XMPP Ping
    fn incoming_iq_processing_get_ping(
    &mut self,
    _ping: xmpp_parsers::ping::Ping,
    ) -> Box<dyn IqRequestHandler> {
    Box::new(IqGetPing {})
    }
    /// Process disco query
    /// see XEP-0030: Service Discovery
    fn incoming_iq_processing_get_disco_info(
    &mut self,
    disco: xmpp_parsers::disco::DiscoInfoQuery,
    ) -> Box<dyn IqRequestHandler> {
    if let Some(ref node) = disco.node {
    warn!("Unsupported node {}", node);
    Box::new(IqRequestUnknown {
    element: disco.into(),
    type_: "get",
    })
    } else {
    Box::new(IqGetDiscoInfo {})
    }
    }
    /// Process disco items query
    /// see XEP-0030: Service Discovery
    fn incoming_iq_processing_get_disco_items(
    &mut self,
    disco: xmpp_parsers::disco::DiscoItemsQuery,
    ) -> Box<dyn IqRequestHandler> {
    if let Some(ref node) = disco.node {
    warn!("Unsupported node {}", node);
    Box::new(IqRequestUnknown {
    element: disco.into(),
    type_: "get",
    })
    } else {
    Box::new(IqGetDiscoItems {})
    }
    }
    /// Process version query
    /// see XEP-0092: Software Version
    fn incoming_iq_processing_get_version(
    &mut self,
    _version: xmpp_parsers::version::VersionQuery,
    ) -> Box<dyn IqRequestHandler> {
    Box::new(IqGetVersion {})
    }
    /// Enforce to answer to IQ "get"
    fn incoming_iq_processing_get(
    &mut self,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    element: minidom::Element,
    ) -> xmpp_parsers::iq::Iq {
    INCOMING_IQ_GET
    .process(self, element)
    .process(self, id, from)
    }
    fn incoming_iq_processing(&mut self, iq: xmpp_parsers::iq::Iq) -> bool {
    match iq.payload {
    xmpp_parsers::iq::IqType::Set(element) => {
    let iq_answer = self.incoming_iq_processing_set(iq.id, iq.from, element);
    self.state.data.send_queue.push_back(iq_answer.into());
    }
    xmpp_parsers::iq::IqType::Error(e) => {
    if let Some((_, handler)) = self.state.data.pending_ids.remove_entry(&iq.id) {
    return handler.1.error(self, e);
    }
    error!("iq error: {:?}", e);
    return false;
    }
    xmpp_parsers::iq::IqType::Get(element) => {
    let iq_answer = self.incoming_iq_processing_get(iq.id, iq.from, element);
    self.state.data.send_queue.push_back(iq_answer.into());
    }
    xmpp_parsers::iq::IqType::Result(opt_element) => {
    if let Some((_, handler)) = self.state.data.pending_ids.remove_entry(&iq.id) {
    return handler.1.result(self, opt_element);
    }
    warn!(
    "Unwanted iq result id {} from {:?}: {:?}",
    iq.id,
    iq.from,
    opt_element.map(|e| String::from(&e))
    );
    }
    }
    true
    }
    fn incoming_presence_processing(&mut self, presence: xmpp_parsers::presence::Presence) -> bool {
    if presence.from.as_ref() == Some(&self.state.client.jid) {
    info!("Self-presence accepted");
    self.state.data.self_presence = true;
    } else {
    warn!("Incoming presence stanza: {:?}", presence);
    }
    true
    }
    fn incoming_message_processing(&mut self, message: xmpp_parsers::message::Message) -> bool {
    for payload in message.payloads.iter() {
    use std::convert::TryInto;
    if let Some(_delay) =
    payload.clone().try_into().ok() as Option<xmpp_parsers::delay::Delay>
    {
    return true; // ignore delayed messages
    }
    }
    warn!("Incoming message stanza: {:?}", message);
    true
    }
    /// process event from xmpp stream
    /// returns from future when condition met
    /// or stop future was resolved.
    /// Return item if connection was preserved or error otherwise.
    /// Second part is a state of stop_future
    pub fn processing<S, F, T, E>(
    self,
    stop_condition: S,
    stop_future: F,
    ) -> impl Future<
    Item = (Self, Result<Either<F, T>, E>),
    Error = (std::rc::Rc<config::Account>, Result<Either<F, T>, E>),
    >
    where
    F: Future<Item = T, Error = E> + 'static,
    S: FnMut(&mut Self, Event) -> Result<bool, ()> + 'static,
    T: 'static,
    E: 'static,
    {
    future::loop_fn(
    (self, stop_future, stop_condition),
    |(xmpp, stop_future, mut stop_condition)| {
    // ToDo: check timeouts if iqs
    let XmppConnection {
    state: XmppState { client, mut data },
    account,
    } = xmpp;
    if let Some(send_element) = data.send_queue.pop_front() {
    use tokio::prelude::Sink;
    info!("Sending {}", String::from(&send_element));
    Box::new(
    client
    .send(Packet::Stanza(send_element))
    .select2(stop_future)
    .then(move |r| match r {
    Ok(Either::A((client, b))) => {
    Box::new(future::ok(future::Loop::Continue((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    b,
    stop_condition,
    ))))
    as Box<dyn Future<Item = _, Error = _>>
    }
    Ok(Either::B((t, a))) => Box::new(a.then(|r| match r {
    Ok(client) => future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Ok(Either::B(t)),
    ))),
    Err(se) => {
    warn!("XMPP sending error: {}", se);
    future::err((account, Ok(Either::B(t))))
    }
    })),
    Err(Either::A((e, b))) => {
    warn!("XMPP sending error: {}", e);
    Box::new(future::err((account, Ok(Either::A(b)))))
    }
    Err(Either::B((e, a))) => Box::new(a.then(|r| match r {
    Ok(client) => future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Err(e),
    ))),
    Err(se) => {
    warn!("XMPP sending error: {}", se);
    future::err((account, Err(e)))
    }
    })),
    }),
    ) as Box<dyn Future<Item = _, Error = _>>
    } else {
    Box::new(
    client
    .into_future()
    .select2(stop_future)
    .then(move |r| match r {
    Ok(Either::A(((event, client), b))) => {
    if let Some(event) = event {
    let mut xmpp = XmppConnection {
    state: XmppState { client, data },
    account,
    };
    if xmpp.xmpp_processing(&event) {
    match stop_condition(&mut xmpp, event) {
    Ok(true) => future::ok(future::Loop::Break((
    xmpp,
    Ok(Either::A(b)),
    ))),
    Ok(false) => future::ok(future::Loop::Continue((
    xmpp,
    b,
    stop_condition,
    ))),
    Err(_e) => {
    future::err((xmpp.account, Ok(Either::A(b))))
    }
    }
    } else {
    future::err((xmpp.account, Ok(Either::A(b))))
    }
    } else {
    future::err((account, Ok(Either::A(b))))
    }
    }
    Ok(Either::B((t, a))) => {
    if let Some(client) = a.into_inner() {
    future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Ok(Either::B(t)),
    )))
    } else {
    future::err((account, Ok(Either::B(t))))
    }
    }
    Err(Either::A((e, b))) => {
    warn!("XMPP error: {}", e.0);
    future::err((account, Ok(Either::A(b))))
    }
    Err(Either::B((e, a))) => {
    if let Some(client) = a.into_inner() {
    future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Err(e),
    )))
    } else {
    future::err((account, Err(e)))
    }
    }
    }),
    )
    }
    },
    )
    }
    /// get connection and wait for online status and set presence
    /// returns error if something went wrong and xmpp connection is broken
    fn online(&mut self, event: Event) -> Result<bool, ()> {
    match event {
    Event::Online => {
    info!("Online!");
    Ok(true)
    }
    Event::Stanza(s) => {
    warn!("Stanza before online: {}", String::from(&s));
    Ok(false)
    }
    _ => {
    error!("Disconnected while online");
    Err(())
    }
    }
    }
    fn initial_roster<F, E>(
    self,
    stop_future: F,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>>
    where
    F: Future<Error = E> + 'static,
    E: 'static,
    {
    let XmppConnection {
    account,
    state: XmppState { client, mut data },
    } = self;
    use tokio::prelude::Sink;
    data.counter += 1;
    let id_init_roster = format!("id_init_roster{}", data.counter);
    let get_roster = stanzas::make_get_roster(&id_init_roster);
    let account2 = account.clone();
    info!("Quering roster... {}", String::from(&get_roster));
    data.pending_ids.insert(
    id_init_roster.clone(),
    (
    Instant::now() + Duration::from_secs(60),
    Box::new(InitRosterIqHandler {}),
    ),
    );
    client
    .send(Packet::Stanza(get_roster))
    .map_err(move |e| {
    error!("Error on querying roster: {}", e);
    account2
    })
    .and_then(move |client| {
    XmppConnection {
    state: XmppState { client, data },
    account,
    }
    .processing(move |conn, _| Ok(conn.state.data.roster_init), stop_future)
    .map_err(|(account, _)| account)
    .and_then(|(conn, r)| match r {
    Ok(Either::A(_)) => future::ok(conn),
    Ok(Either::B(_)) => future::err(conn.account),
    Err(_e) => future::err(conn.account),
    })
    })
    }
    fn self_presence<F, E>(
    self,
    stop_future: F,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>>
    where
    F: Future<Error = E> + 'static,
    E: Into<failure::Error> + 'static,
    {
    let XmppConnection {
    account,
    state: XmppState { client, data },
    } = self;
    use tokio::prelude::Sink;
    let presence = stanzas::make_presence(&account);
    let account2 = account.clone();
    info!("Sending presence... {}", String::from(&presence));
    client
    .send(Packet::Stanza(presence))
    .map_err(|e| {
    error!("Error on send self-presence: {}", e);
    account2
    })
    .and_then(move |client| {
    XmppConnection {
    state: XmppState { client, data },
    account,
    }
    .processing(
    move |conn, _| Ok(conn.state.data.self_presence),
    stop_future,
    )
    .map_err(|(account, _)| account)
    .and_then(|(conn, r)| match r {
    Ok(Either::A(_)) => future::ok(conn),
    Ok(Either::B(_)) => future::err(conn.account),
    Err(_e) => future::err(conn.account),
    })
    })
    }
    fn process_jid(&mut self, xmpp_to: &xmpp_parsers::Jid) {
    if let Some(ref mut mailbox) = self.state.data.outgoing_mailbox.get_mut(xmpp_to) {
    if !mailbox.is_empty() {
    if let Some(ref mut rdata) = self.state.data.roster.get_mut(xmpp_to) {
    info!("Jid {} in roster", xmpp_to);
    let sub_to = match rdata.0 {
    xmpp_parsers::roster::Subscription::To => true,
    xmpp_parsers::roster::Subscription::Both => true,
    _ => false,
    };
    if sub_to {
    info!("Subscribed to {}", xmpp_to);
    self.state.data.send_queue.extend(
    mailbox.drain(..).map(|message| {
    stanzas::make_chat_message(xmpp_to.clone(), message)
    }),
    );
    } else if rdata.1 == xmpp_parsers::roster::Ask::None {
    info!("Not subscribed to {}", xmpp_to);
    self.state
    .data
    .send_queue
    .push_back(stanzas::make_ask_subscribe(xmpp_to.clone()));
    }
    let sub_from = match rdata.0 {
    xmpp_parsers::roster::Subscription::From => true,
    xmpp_parsers::roster::Subscription::Both => true,
    _ => false,
    };
    if !sub_from {
    info!("Not subscription from {}", xmpp_to);
    self.state
    .data
    .send_queue
    .push_back(stanzas::make_allow_subscribe(xmpp_to.clone()));
    }
    } else {
    info!("Jid {} not in roster", xmpp_to);
    self.state.data.counter += 1;
    let id_add_roster = format!("id_add_roster{}", self.state.data.counter);
    let add_roster = stanzas::make_add_roster(&id_add_roster, xmpp_to.clone());
    info!("Adding jid {} to roster id {}", xmpp_to, id_add_roster);
    self.state.data.pending_ids.insert(
    id_add_roster,
    (
    Instant::now() + Duration::from_secs(60),
    Box::new(AddRosterIqHandler {
    jid: xmpp_to.clone(),
    }),
    ),
    );
    self.state.data.send_queue.push_back(add_roster);
    }
    }
    }
    }
    pub fn process_command(&mut self, cmd: XmppCommand) {
    info!("Got command");
    match cmd {
    XmppCommand::Chat { xmpp_to, message } => {
    self.state
    .data
    .outgoing_mailbox
    .entry(xmpp_to.clone())
    .or_default()
    .push(message);
    self.process_jid(&xmpp_to);
    }
    XmppCommand::Chatroom { muc_id, message } => {
    if let Some(muc) = self.state.data.mucs.get(&muc_id) {
    self.state
    .data
    .send_queue
    .push_back(stanzas::make_muc_message(muc.clone(), message));
    } else {
    error!("Not found MUC {}", muc_id);
    }
    }
    XmppCommand::Ping => {
    self.state.data.counter += 1;
    let id_ping = format!("id_ping{}", self.state.data.counter);
    let ping = stanzas::make_ping(&id_ping, self.state.client.jid.clone());
    self.state.data.send_queue.push_back(ping);
    self.state.data.pending_ids.insert(
    id_ping,
    (
    Instant::now() + Duration::from_secs(30),
    Box::new(PingIqHandler {}),
    ),
    );
    }
    XmppCommand::TimeoutCleanup => {
    let now = Instant::now();
    let timeouted: Vec<String> = self
    .state
    .data
    .pending_ids
    .iter()
    .filter_map(|(id, (timeout, _))| {
    if now >= *timeout {
    Some(id.to_string())
    } else {
    None
    }
    })
    .collect();
    let mut correct = true;
    timeouted.into_iter().for_each(|id| {
    if let Some((_, handler)) = self.state.data.pending_ids.remove(&id) {
    correct &= handler.timeout(&mut self);
    }
    })
    }
    }
    }
    pub fn shutdown(self) -> impl Future<Item = (), Error = failure::Error> {
    info!("Shutdown connection");
    let XmppConnection { account, state } = self;
    stream::iter_ok(
    state
    .data
    .mucs
    .values()
    .map(std::clone::Clone::clone)
    .collect::<Vec<_>>(),
    )
    .fold(state, move |XmppState { client, data }, muc_jid| {
    let muc_presence =
    stanzas::make_muc_presence_leave(account.jid.clone(), muc_jid.clone());
    info!(
    "Sending muc leave presence... {}",
    String::from(&muc_presence)
    );
    use tokio::prelude::Sink;
    client
    .send(Packet::Stanza(muc_presence))
    .map_err(|e| {
    error!("Error on send muc presence: {}", e);
    e
    })
    .and_then(|client| future::ok(XmppState { client, data }))
    })
    .map(|_| ())
    }
    fn enter_mucs<F, E>(
    self,
    _stop_future: F,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>>
    where
    F: Future<Error = E> + 'static,
    E: Into<failure::Error> + 'static,
    {
    let XmppConnection { account, state } = self;
    let account2 = account.clone();
    let account3 = account.clone();
    stream::iter_ok(account.chatrooms.clone())
    .fold(state, move |XmppState { client, mut data }, muc_jid| {
    data.counter += 1;
    let id_muc_presence = format!("id_muc_presence{}", data.counter);
    let muc_presence = stanzas::make_muc_presence(
    &id_muc_presence,
    account2.jid.clone(),
    muc_jid.1.clone(),
    );
    info!("Sending muc presence... {}", String::from(&muc_presence));
    let account4 = account2.clone();
    use tokio::prelude::Sink;
    client
    .send(Packet::Stanza(muc_presence))
    .map_err(|e| {
    error!("Error on send muc presence: {}", e);
    account4
    })
    .and_then(|client| {
    data.mucs.insert(muc_jid.0, muc_jid.1);
    future::ok(XmppState { client, data })
    })
    })
    .map(|state| XmppConnection {
    account: account3,
    state,
    })
    }
    }
    [3.21]
    use tokio_xmpp::{Client, Event, Packet};
    use tokio::prelude::future::{self, Either};
    use tokio::prelude::stream;
    use tokio::prelude::{Future, Stream};
    use std::collections::{HashMap, VecDeque};
    use std::time::{Duration, Instant};
    use super::stanzas;
    use super::element_processor;
    use crate::config;
    #[derive(Debug)]
    pub enum XmppCommand {
    /// Send message to someone by jid
    Chat {
    xmpp_to: xmpp_parsers::Jid,
    message: String,
    },
    /// Send message to MUC
    Chatroom { muc_id: String, message: String },
    /// Send ping request to the server to test connection
    Ping,
    /// Check iq requests if some have expired timeouts
    TimeoutCleanup,
    }
    /// trait of processing iq
    /// each function consumes handlers and
    /// returns false if connection should be reset
    trait IqHandler {
    /// process result
    fn result(
    self: Box<Self>,
    conn: &mut XmppConnection,
    opt_element: Option<xmpp_parsers::Element>,
    ) -> bool;
    /// process error
    fn error(
    self: Box<Self>,
    conn: &mut XmppConnection,
    error: xmpp_parsers::stanza_error::StanzaError,
    ) -> bool;
    /// process tmeout
    fn timeout(self: Box<Self>, conn: &mut XmppConnection) -> bool;
    }
    struct AddRosterIqHandler {
    jid: xmpp_parsers::Jid,
    }
    impl IqHandler for AddRosterIqHandler {
    fn result(
    self: Box<Self>,
    conn: &mut XmppConnection,
    opt_element: Option<xmpp_parsers::Element>,
    ) -> bool {
    match opt_element {
    Some(element) => {
    warn!(
    "Wrong payload when adding {} to roster: {}",
    self.jid,
    String::from(&element)
    );
    }
    None => {
    if conn.state.data.roster.contains_key(&self.jid) {
    info!("Jid {} updated to roster", self.jid);
    } else {
    info!("Jid {} added in roster", self.jid);
    conn.state.data.roster.insert(
    self.jid.clone(),
    (
    xmpp_parsers::roster::Subscription::None,
    xmpp_parsers::roster::Ask::None,
    ),
    );
    }
    conn.process_jid(&self.jid);
    }
    }
    true
    }
    fn error(
    self: Box<Self>,
    _conn: &mut XmppConnection,
    _error: xmpp_parsers::stanza_error::StanzaError,
    ) -> bool {
    true
    }
    fn timeout(self: Box<Self>, _conn: &mut XmppConnection) -> bool {
    true // ignore
    }
    }
    struct PingIqHandler {}
    impl IqHandler for PingIqHandler {
    fn result(
    self: Box<Self>,
    _conn: &mut XmppConnection,
    _opt_element: Option<xmpp_parsers::Element>,
    ) -> bool {
    info!("ping successed");
    true
    }
    fn error(
    self: Box<Self>,
    _conn: &mut XmppConnection,
    _error: xmpp_parsers::stanza_error::StanzaError,
    ) -> bool {
    false
    }
    fn timeout(self: Box<Self>, _conn: &mut XmppConnection) -> bool {
    false
    }
    }
    struct InitRosterIqHandler {}
    impl IqHandler for InitRosterIqHandler {
    fn result(
    self: Box<Self>,
    conn: &mut XmppConnection,
    opt_element: Option<xmpp_parsers::Element>,
    ) -> bool {
    if let Some(result) = opt_element {
    use std::convert::TryInto;
    match result.try_into() as Result<xmpp_parsers::roster::Roster, _> {
    Ok(roster) => {
    conn.state.data.roster_init = true;
    conn.state.data.roster.clear();
    info!("Got first roster:");
    for i in roster.items {
    info!(" >>> {:?}", i);
    conn.state
    .data
    .roster
    .insert(i.jid, (i.subscription, i.ask));
    }
    true
    }
    Err(e) => {
    error!("Cann't parse roster: {}", e);
    false
    }
    }
    } else {
    error!("No roster responded");
    false
    }
    }
    fn error(
    self: Box<Self>,
    _conn: &mut XmppConnection,
    _error: xmpp_parsers::stanza_error::StanzaError,
    ) -> bool {
    false
    }
    fn timeout(self: Box<Self>, _conn: &mut XmppConnection) -> bool {
    false
    }
    }
    #[derive(Default)]
    struct XmppData {
    /// known roster data
    roster: HashMap<
    xmpp_parsers::Jid,
    (
    xmpp_parsers::roster::Subscription,
    xmpp_parsers::roster::Ask,
    ),
    >,
    /// if roster was initialized
    /// ToDo: remove it as it is used only for initialization
    roster_init: bool,
    /// if self-presence accepted
    /// ToDo: remove it as it is used only for initialization
    self_presence: bool,
    /// ids counter
    counter: usize,
    /// stanzas to send
    send_queue: VecDeque<minidom::Element>,
    /// outgoing mailbox
    outgoing_mailbox: HashMap<xmpp_parsers::Jid, Vec<String>>,
    /// muc id to muc jid
    mucs: HashMap<String, xmpp_parsers::Jid>,
    /// map from iq's id to handler of this type of iqs
    pending_ids: HashMap<String, (Instant, Box<dyn IqHandler>)>,
    }
    struct XmppState {
    client: Client,
    data: XmppData,
    }
    pub struct XmppConnection {
    account: std::rc::Rc<config::Account>,
    state: XmppState,
    }
    lazy_static! {
    static ref INCOMING: element_processor::Processor<XmppConnection, bool, xmpp_parsers::Element> = {
    let mut incoming = element_processor::Processor::new(&|_, e| {
    warn!("Unknown stanza {}", String::from(&e));
    true
    });
    incoming.register(&XmppConnection::incoming_iq_processing);
    incoming.register(&XmppConnection::incoming_presence_processing);
    incoming.register(&XmppConnection::incoming_message_processing);
    incoming
    };
    }
    pub struct MaybeXmppConnection {
    account: std::rc::Rc<config::Account>,
    state: Option<XmppState>,
    }
    impl From<XmppConnection> for MaybeXmppConnection {
    fn from(from: XmppConnection) -> MaybeXmppConnection {
    MaybeXmppConnection {
    account: from.account,
    state: Some(from.state),
    }
    }
    }
    impl From<config::Account> for MaybeXmppConnection {
    fn from(from: config::Account) -> MaybeXmppConnection {
    MaybeXmppConnection {
    account: std::rc::Rc::new(from),
    state: None,
    }
    }
    }
    impl From<std::rc::Rc<config::Account>> for MaybeXmppConnection {
    fn from(from: std::rc::Rc<config::Account>) -> MaybeXmppConnection {
    MaybeXmppConnection {
    account: from,
    state: None,
    }
    }
    }
    impl MaybeXmppConnection {
    /// connects if nothing connected
    /// don't connect only if stop_future resolved
    pub fn connect<F>(
    self,
    stop_future: F,
    ) -> impl Future<Item = XmppConnection, Error = failure::Error>
    where
    F: future::Future + Clone + 'static,
    <F as hyper::rt::Future>::Error: Into<failure::Error> + Send,
    {
    info!("xmpp connection...");
    let MaybeXmppConnection { account, state } = self;
    if let Some(state) = state {
    Box::new(future::ok(XmppConnection { account, state }))
    as Box<dyn Future<Item = _, Error = _>>
    } else {
    Box::new(
    stop_future
    .clone()
    .select2(
    future::loop_fn(account, move |account| {
    info!("xmpp initialization...");
    let client =
    Client::new_with_jid(account.jid.clone(), &account.password);
    info!("xmpp initialized");
    let stop_future2 = stop_future.clone();
    let stop_future3 = stop_future.clone();
    let stop_future4 = stop_future.clone();
    // future to wait for online
    Box::new(
    XmppConnection {
    state: XmppState {
    client,
    data: std::default::Default::default(),
    },
    account,
    }
    .processing(XmppConnection::online, stop_future.clone())
    .map_err(|(acc, _)| acc)
    .and_then(|(conn, r)| match r {
    Ok(Either::A(_)) => future::ok(conn),
    Ok(Either::B(_)) => future::err(conn.account),
    Err(_e) => future::err(conn.account),
    })
    .and_then(|conn| conn.initial_roster(stop_future2))
    .and_then(|conn| conn.self_presence(stop_future3))
    .and_then(|conn| conn.enter_mucs(stop_future4))
    .then(|r| match r {
    Ok(conn) => future::ok(future::Loop::Break(conn)),
    Err(acc) => future::ok(future::Loop::Continue(acc)),
    }),
    )
    })
    .map_err(|_: ()| ()),
    )
    .then(|r| match r {
    Ok(Either::A((_x, _b))) => future::err(format_err!("Stop XMMP connection")),
    Ok(Either::B((x, _a))) => future::ok(x),
    Err(Either::A((e, _b))) => future::err(e.into()),
    Err(Either::B((_, _a))) => {
    future::err(format_err!("Cann't initiate XMPP connection"))
    }
    }),
    )
    }
    }
    }
    impl XmppConnection {
    /// base XMPP processing
    /// Returns false on error to disconnect
    fn xmpp_processing(&mut self, event: &Event) -> bool {
    match event {
    Event::Stanza(stanza) => INCOMING.process(self, stanza.clone()),
    Event::Online => true,
    e => {
    warn!("Unexpected event {:?}", e);
    false
    }
    }
    }
    /// Enforce to answer to IQ "set"
    fn incoming_iq_processing_set(
    &mut self,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    element: minidom::Element,
    ) -> xmpp_parsers::iq::Iq {
    use std::convert::TryInto;
    if let Some(roster) =
    element.clone().try_into().ok() as Option<xmpp_parsers::roster::Roster>
    {
    // RFC 6212 2.1.6. Roster Push
    info!("Got roster push {} from {:?}", id, from);
    for i in roster.items {
    if let Some(ref mut rdata) = self.state.data.roster.get_mut(&i.jid) {
    info!("Update {} in roster", i.jid);
    rdata.0 = i.subscription;
    rdata.1 = i.ask;
    } else {
    info!("Add {} to roster", i.jid);
    self.state
    .data
    .roster
    .insert(i.jid.clone(), (i.subscription, i.ask));
    }
    self.process_jid(&i.jid);
    }
    return stanzas::make_roster_push_answer(id, self.state.client.jid.clone(), from);
    }
    warn!(
    "Unsupported IQ set request from {:?}: {}",
    from,
    String::from(&element)
    );
    stanzas::make_iq_unsupported_error(id, self.state.client.jid.clone(), from)
    }
    /// Enforce to answer to IQ "get"
    fn incoming_iq_processing_get(
    &mut self,
    id: String,
    from: Option<xmpp_parsers::Jid>,
    element: minidom::Element,
    ) -> xmpp_parsers::iq::Iq {
    use std::convert::TryInto;
    if let Some(_ping) = element.clone().try_into().ok() as Option<xmpp_parsers::ping::Ping> {
    info!("Got ping {} from {:?}", id, from);
    return stanzas::make_pong(&id, self.state.client.jid.clone(), from);
    }
    warn!(
    "Unsupported IQ get request from {:?}: {}",
    from,
    String::from(&element)
    );
    stanzas::make_iq_unsupported_error(id, self.state.client.jid.clone(), from)
    }
    fn incoming_iq_processing(&mut self, iq: xmpp_parsers::iq::Iq) -> bool {
    match iq.payload {
    xmpp_parsers::iq::IqType::Set(element) => {
    let iq_answer = self.incoming_iq_processing_set(iq.id, iq.from, element);
    self.state.data.send_queue.push_back(iq_answer.into());
    }
    xmpp_parsers::iq::IqType::Error(e) => {
    if let Some((_, handler)) = self.state.data.pending_ids.remove_entry(&iq.id) {
    return handler.1.error(self, e);
    }
    error!("iq error: {:?}", e);
    return false;
    }
    xmpp_parsers::iq::IqType::Get(element) => {
    let iq_answer = self.incoming_iq_processing_get(iq.id, iq.from, element);
    self.state.data.send_queue.push_back(iq_answer.into());
    }
    xmpp_parsers::iq::IqType::Result(opt_element) => {
    if let Some((_, handler)) = self.state.data.pending_ids.remove_entry(&iq.id) {
    return handler.1.result(self, opt_element);
    }
    warn!(
    "Unwanted iq result id {} from {:?}: {:?}",
    iq.id,
    iq.from,
    opt_element.map(|e| String::from(&e))
    );
    }
    }
    true
    }
    fn incoming_presence_processing(&mut self, presence: xmpp_parsers::presence::Presence) -> bool {
    if presence.from.as_ref() == Some(&self.state.client.jid) {
    info!("Self-presence accepted");
    self.state.data.self_presence = true;
    } else {
    warn!("Incoming presence stanza: {:?}", presence);
    }
    true
    }
    fn incoming_message_processing(&mut self, message: xmpp_parsers::message::Message) -> bool {
    for payload in message.payloads.iter() {
    use std::convert::TryInto;
    if let Some(_delay) =
    payload.clone().try_into().ok() as Option<xmpp_parsers::delay::Delay>
    {
    return true; // ignore delayed messages
    }
    }
    warn!("Incoming message stanza: {:?}", message);
    true
    }
    /// process event from xmpp stream
    /// returns from future when condition met
    /// or stop future was resolved.
    /// Return item if connection was preserved or error otherwise.
    /// Second part is a state of stop_future
    pub fn processing<S, F, T, E>(
    self,
    stop_condition: S,
    stop_future: F,
    ) -> impl Future<
    Item = (Self, Result<Either<F, T>, E>),
    Error = (std::rc::Rc<config::Account>, Result<Either<F, T>, E>),
    >
    where
    F: Future<Item = T, Error = E> + 'static,
    S: FnMut(&mut Self, Event) -> Result<bool, ()> + 'static,
    T: 'static,
    E: 'static,
    {
    future::loop_fn(
    (self, stop_future, stop_condition),
    |(xmpp, stop_future, mut stop_condition)| {
    // ToDo: check timeouts if iqs
    let XmppConnection {
    state: XmppState { client, mut data },
    account,
    } = xmpp;
    if let Some(send_element) = data.send_queue.pop_front() {
    use tokio::prelude::Sink;
    info!("Sending {}", String::from(&send_element));
    Box::new(
    client
    .send(Packet::Stanza(send_element))
    .select2(stop_future)
    .then(move |r| match r {
    Ok(Either::A((client, b))) => {
    Box::new(future::ok(future::Loop::Continue((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    b,
    stop_condition,
    ))))
    as Box<dyn Future<Item = _, Error = _>>
    }
    Ok(Either::B((t, a))) => Box::new(a.then(|r| match r {
    Ok(client) => future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Ok(Either::B(t)),
    ))),
    Err(se) => {
    warn!("XMPP sending error: {}", se);
    future::err((account, Ok(Either::B(t))))
    }
    })),
    Err(Either::A((e, b))) => {
    warn!("XMPP sending error: {}", e);
    Box::new(future::err((account, Ok(Either::A(b)))))
    }
    Err(Either::B((e, a))) => Box::new(a.then(|r| match r {
    Ok(client) => future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Err(e),
    ))),
    Err(se) => {
    warn!("XMPP sending error: {}", se);
    future::err((account, Err(e)))
    }
    })),
    }),
    ) as Box<dyn Future<Item = _, Error = _>>
    } else {
    Box::new(
    client
    .into_future()
    .select2(stop_future)
    .then(move |r| match r {
    Ok(Either::A(((event, client), b))) => {
    if let Some(event) = event {
    let mut xmpp = XmppConnection {
    state: XmppState { client, data },
    account,
    };
    if xmpp.xmpp_processing(&event) {
    match stop_condition(&mut xmpp, event) {
    Ok(true) => future::ok(future::Loop::Break((
    xmpp,
    Ok(Either::A(b)),
    ))),
    Ok(false) => future::ok(future::Loop::Continue((
    xmpp,
    b,
    stop_condition,
    ))),
    Err(_e) => {
    future::err((xmpp.account, Ok(Either::A(b))))
    }
    }
    } else {
    future::err((xmpp.account, Ok(Either::A(b))))
    }
    } else {
    future::err((account, Ok(Either::A(b))))
    }
    }
    Ok(Either::B((t, a))) => {
    if let Some(client) = a.into_inner() {
    future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Ok(Either::B(t)),
    )))
    } else {
    future::err((account, Ok(Either::B(t))))
    }
    }
    Err(Either::A((e, b))) => {
    warn!("XMPP error: {}", e.0);
    future::err((account, Ok(Either::A(b))))
    }
    Err(Either::B((e, a))) => {
    if let Some(client) = a.into_inner() {
    future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Err(e),
    )))
    } else {
    future::err((account, Err(e)))
    }
    }
    }),
    )
    }
    },
    )
    }
    /// get connection and wait for online status and set presence
    /// returns error if something went wrong and xmpp connection is broken
    fn online(&mut self, event: Event) -> Result<bool, ()> {
    match event {
    Event::Online => {
    info!("Online!");
    Ok(true)
    }
    Event::Stanza(s) => {
    warn!("Stanza before online: {}", String::from(&s));
    Ok(false)
    }
    _ => {
    error!("Disconnected while online");
    Err(())
    }
    }
    }
    fn initial_roster<F, E>(
    self,
    stop_future: F,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>>
    where
    F: Future<Error = E> + 'static,
    E: 'static,
    {
    let XmppConnection {
    account,
    state: XmppState { client, mut data },
    } = self;
    use tokio::prelude::Sink;
    data.counter += 1;
    let id_init_roster = format!("id_init_roster{}", data.counter);
    let get_roster = stanzas::make_get_roster(&id_init_roster);
    let account2 = account.clone();
    info!("Quering roster... {}", String::from(&get_roster));
    data.pending_ids.insert(
    id_init_roster.clone(),
    (
    Instant::now() + Duration::from_secs(60),
    Box::new(InitRosterIqHandler {}),
    ),
    );
    client
    .send(Packet::Stanza(get_roster))
    .map_err(move |e| {
    error!("Error on querying roster: {}", e);
    account2
    })
    .and_then(move |client| {
    XmppConnection {
    state: XmppState { client, data },
    account,
    }
    .processing(move |conn, _| Ok(conn.state.data.roster_init), stop_future)
    .map_err(|(account, _)| account)
    .and_then(|(conn, r)| match r {
    Ok(Either::A(_)) => future::ok(conn),
    Ok(Either::B(_)) => future::err(conn.account),
    Err(_e) => future::err(conn.account),
    })
    })
    }
    fn self_presence<F, E>(
    self,
    stop_future: F,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>>
    where
    F: Future<Error = E> + 'static,
    E: Into<failure::Error> + 'static,
    {
    let XmppConnection {
    account,
    state: XmppState { client, data },
    } = self;
    use tokio::prelude::Sink;
    let presence = stanzas::make_presence(&account);
    let account2 = account.clone();
    info!("Sending presence... {}", String::from(&presence));
    client
    .send(Packet::Stanza(presence))
    .map_err(|e| {
    error!("Error on send self-presence: {}", e);
    account2
    })
    .and_then(move |client| {
    XmppConnection {
    state: XmppState { client, data },
    account,
    }
    .processing(
    move |conn, _| Ok(conn.state.data.self_presence),
    stop_future,
    )
    .map_err(|(account, _)| account)
    .and_then(|(conn, r)| match r {
    Ok(Either::A(_)) => future::ok(conn),
    Ok(Either::B(_)) => future::err(conn.account),
    Err(_e) => future::err(conn.account),
    })
    })
    }
    fn process_jid(&mut self, xmpp_to: &xmpp_parsers::Jid) {
    if let Some(ref mut mailbox) = self.state.data.outgoing_mailbox.get_mut(xmpp_to) {
    if !mailbox.is_empty() {
    if let Some(ref mut rdata) = self.state.data.roster.get_mut(xmpp_to) {
    info!("Jid {} in roster", xmpp_to);
    let sub_to = match rdata.0 {
    xmpp_parsers::roster::Subscription::To => true,
    xmpp_parsers::roster::Subscription::Both => true,
    _ => false,
    };
    if sub_to {
    info!("Subscribed to {}", xmpp_to);
    self.state.data.send_queue.extend(
    mailbox.drain(..).map(|message| {
    stanzas::make_chat_message(xmpp_to.clone(), message)
    }),
    );
    } else if rdata.1 == xmpp_parsers::roster::Ask::None {
    info!("Not subscribed to {}", xmpp_to);
    self.state
    .data
    .send_queue
    .push_back(stanzas::make_ask_subscribe(xmpp_to.clone()));
    }
    let sub_from = match rdata.0 {
    xmpp_parsers::roster::Subscription::From => true,
    xmpp_parsers::roster::Subscription::Both => true,
    _ => false,
    };
    if !sub_from {
    info!("Not subscription from {}", xmpp_to);
    self.state
    .data
    .send_queue
    .push_back(stanzas::make_allow_subscribe(xmpp_to.clone()));
    }
    } else {
    info!("Jid {} not in roster", xmpp_to);
    self.state.data.counter += 1;
    let id_add_roster = format!("id_add_roster{}", self.state.data.counter);
    let add_roster = stanzas::make_add_roster(&id_add_roster, xmpp_to.clone());
    info!("Adding jid {} to roster id {}", xmpp_to, id_add_roster);
    self.state.data.pending_ids.insert(
    id_add_roster,
    (
    Instant::now() + Duration::from_secs(60),
    Box::new(AddRosterIqHandler {
    jid: xmpp_to.clone(),
    }),
    ),
    );
    self.state.data.send_queue.push_back(add_roster);
    }
    }
    }
    }
    pub fn process_command(&mut self, cmd: XmppCommand) {
    info!("Got command");
    match cmd {
    XmppCommand::Chat { xmpp_to, message } => {
    self.state
    .data
    .outgoing_mailbox
    .entry(xmpp_to.clone())
    .or_default()
    .push(message);
    self.process_jid(&xmpp_to);
    }
    XmppCommand::Chatroom { muc_id, message } => {
    if let Some(muc) = self.state.data.mucs.get(&muc_id) {
    self.state
    .data
    .send_queue
    .push_back(stanzas::make_muc_message(muc.clone(), message));
    } else {
    error!("Not found MUC {}", muc_id);
    }
    }
    XmppCommand::Ping => {
    self.state.data.counter += 1;
    let id_ping = format!("id_ping{}", self.state.data.counter);
    let ping = stanzas::make_ping(&id_ping, self.state.client.jid.clone());
    self.state.data.send_queue.push_back(ping);
    self.state.data.pending_ids.insert(
    id_ping,
    (
    Instant::now() + Duration::from_secs(30),
    Box::new(PingIqHandler {}),
    ),
    );
    }
    XmppCommand::TimeoutCleanup => {
    let now = Instant::now();
    let timeouted: Vec<String> = self
    .state
    .data
    .pending_ids
    .iter()
    .filter_map(|(id, (timeout, _))| {
    if now >= *timeout {
    Some(id.to_string())
    } else {
    None
    }
    })
    .collect();
    let mut correct = true;
    timeouted.into_iter().for_each(|id| {
    if let Some((_, handler)) = self.state.data.pending_ids.remove(&id) {
    correct &= handler.timeout(&mut self);
    }
    })
    }
    }
    }
    pub fn shutdown(self) -> impl Future<Item = (), Error = failure::Error> {
    info!("Shutdown connection");
    let XmppConnection { account, state } = self;
    stream::iter_ok(
    state
    .data
    .mucs
    .values()
    .map(std::clone::Clone::clone)
    .collect::<Vec<_>>(),
    )
    .fold(state, move |XmppState { client, data }, muc_jid| {
    let muc_presence =
    stanzas::make_muc_presence_leave(account.jid.clone(), muc_jid.clone());
    info!(
    "Sending muc leave presence... {}",
    String::from(&muc_presence)
    );
    use tokio::prelude::Sink;
    client
    .send(Packet::Stanza(muc_presence))
    .map_err(|e| {
    error!("Error on send muc presence: {}", e);
    e
    })
    .and_then(|client| future::ok(XmppState { client, data }))
    })
    .map(|_| ())
    }
    fn enter_mucs<F, E>(
    self,
    _stop_future: F,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>>
    where
    F: Future<Error = E> + 'static,
    E: Into<failure::Error> + 'static,
    {
    let XmppConnection { account, state } = self;
    let account2 = account.clone();
    let account3 = account.clone();
    stream::iter_ok(account.chatrooms.clone())
    .fold(state, move |XmppState { client, mut data }, muc_jid| {
    data.counter += 1;
    let id_muc_presence = format!("id_muc_presence{}", data.counter);
    let muc_presence = stanzas::make_muc_presence(
    &id_muc_presence,
    account2.jid.clone(),
    muc_jid.1.clone(),
    );
    info!("Sending muc presence... {}", String::from(&muc_presence));
    let account4 = account2.clone();
    use tokio::prelude::Sink;
    client
    .send(Packet::Stanza(muc_presence))
    .map_err(|e| {
    error!("Error on send muc presence: {}", e);
    account4
    })
    .and_then(|client| {
    data.mucs.insert(muc_jid.0, muc_jid.1);
    future::ok(XmppState { client, data })
    })
    })
    .map(|state| XmppConnection {
    account: account3,
    state,
    })
    }
    }
  • edit in src/xmpp/stanzas.rs at line 7
    [3.35465]
    [3.141]
    use xmpp_parsers::stanza_error::{DefinedCondition, ErrorType, StanzaError};
  • replacement in src/xmpp/stanzas.rs at line 19
    [3.35611][2.38896:39057]()
    let mut get_roster = Iq::from_get(Roster {
    items: vec![],
    ver: None,
    });
    get_roster.id = Some(id.to_string());
    get_roster.into()
    [3.35611]
    [3.35737]
    Iq::from_get(
    id,
    Roster {
    items: vec![],
    ver: None,
    },
    )
    .into()
  • replacement in src/xmpp/stanzas.rs at line 30
    [3.35810][2.39058:39422]()
    let mut add_roster = Iq::from_set(Roster {
    items: vec![Item {
    jid,
    name: None,
    subscription: xmpp_parsers::roster::Subscription::None,
    ask: xmpp_parsers::roster::Ask::None,
    groups: vec![],
    }],
    ver: None,
    });
    add_roster.id = Some(id.to_string());
    add_roster.into()
    [3.35810]
    [3.39858]
    Iq::from_set(
    id,
    Roster {
    items: vec![Item {
    jid,
    name: None,
    subscription: xmpp_parsers::roster::Subscription::None,
    ask: xmpp_parsers::roster::Ask::None,
    groups: vec![],
    }],
    ver: None,
    },
    )
    .into()
    }
    pub fn make_roster_push_answer(
    id: String,
    from: xmpp_parsers::Jid,
    to: Option<xmpp_parsers::Jid>,
    ) -> Iq {
    let mut answer = Iq::from_result(id, None as Option<Roster>);
    answer.from = Some(from);
    answer.to = to;
    answer
  • edit in src/xmpp/stanzas.rs at line 59
    [3.36544]
    [3.39862]
    presence.to = Some(jid);
    presence.into()
    }
    pub fn make_allow_subscribe(jid: xmpp_parsers::Jid) -> Element {
    let mut presence = Presence::new(PresenceType::Subscribed);
  • replacement in src/xmpp/stanzas.rs at line 100
    [3.40352][2.39423:39498]()
    let mut ping = Iq::from_get(Ping);
    ping.id = Some(id.to_string());
    [3.40352]
    [3.40395]
    let mut ping = Iq::from_get(id, Ping);
  • edit in src/xmpp/stanzas.rs at line 104
    [3.40491]
    [3.41574]
    }
    pub fn make_pong(id: &str, from: xmpp_parsers::Jid, to: Option<xmpp_parsers::Jid>) -> Iq {
    let mut pong = Iq::from_result(id, None as Option<Roster>);
    pong.from = Some(from);
    pong.to = to;
    pong
    }
    pub fn make_iq_unsupported_error(
    id: String,
    from: xmpp_parsers::Jid,
    to: Option<xmpp_parsers::Jid>,
    ) -> Iq {
    let mut error = Iq::from_error(
    id,
    StanzaError {
    type_: ErrorType::Cancel,
    by: Some(from.clone()),
    defined_condition: DefinedCondition::ServiceUnavailable,
    texts: std::collections::BTreeMap::new(),
    other: None,
    },
    );
    error.from = Some(from);
    error.to = to;
    error
  • replacement in src/xmpp/mod.rs at line 0
    [3.17][3.39010:39054]()
    use tokio::prelude::future::{self, Either};
    [3.17]
    [3.62]
    use tokio::prelude::future::{self, Either, Future};
  • edit in src/xmpp/mod.rs at line 2
    [3.90][3.39055:39135]()
    use tokio::prelude::{Future, Stream};
    use tokio_xmpp::{Client, Event, Packet};
  • replacement in src/xmpp/mod.rs at line 5
    [3.39137][3.39137:39180]()
    use std::collections::{HashMap, VecDeque};
    [3.39137]
    [3.39180]
    mod element_processor;
  • edit in src/xmpp/mod.rs at line 8
    [3.42797][3.39195:39877](),[3.40332][3.40332:44627](),[3.44627][2.39499:39638](),[2.39638][3.44731:44792](),[3.44731][3.44731:44792](),[3.44792][3.38896:39001](),[3.39001][3.45091:45092](),[3.45091][3.45091:45092](),[3.45092][2.39639:40830](),[2.40830][3.39526:39563](),[3.39526][3.39526:39563](),[3.39563][2.40831:41006](),[2.41006][3.39977:40042](),[3.39977][3.39977:40042](),[3.40289][3.40289:40337](),[3.40337][2.41007:41967](),[2.41967][3.41523:41557](),[3.41523][3.41523:41557](),[3.41557][2.41968:42026](),[2.42026][3.42371:42401](),[3.42371][3.42371:42401](),[3.42401][3.46939:46965](),[3.46939][3.46939:46965](),[3.42445][3.47015:47037](),[3.47015][3.47015:47037](),[3.42652][3.47037:47055](),[3.47037][3.47037:47055](),[3.47055][2.42027:42060](),[2.42060][3.47055:47069](),[3.42674][3.47055:47069](),[3.47055][3.47055:47069](),[3.47069][2.42061:42108](),[2.42108][3.42710:42780](),[3.42710][3.42710:42780](),[3.42780][2.42109:42151](),[2.42151][3.47196:47210](),[3.42802][3.47196:47210](),[3.47196][3.47196:47210](),[3.47591][3.47591:47601](),[3.47614][3.47614:51858](),[3.51858][2.42152:42220](),[2.42220][3.51930:52105](),[3.51930][3.51930:52105](),[3.52105][2.42221:43514](),[2.43514][3.53029:53125](),[3.53029][3.53029:53125](),[3.53125][2.43515:43840](),[2.43840][3.53306:53351](),[3.53306][3.53306:53351](),[3.53351][2.43841:43932](),[2.43932][3.53432:53563](),[3.53432][3.53432:53563](),[3.53563][2.43933:44017](),[2.44017][3.53638:54191](),[3.53638][3.53638:54191](),[3.54191][2.44018:44057](),[2.44057][3.54229:54389](),[3.54229][3.54229:54389](),[3.54389][2.44058:44145](),[2.44145][3.54466:54560](),[3.54466][3.54466:54560](),[3.54560][2.44146:44230](),[2.44230][3.54635:55168](),[3.54635][3.54635:55168](),[3.55168][2.44231:44270](),[2.44270][3.55206:55343](),[3.55206][3.55206:55343]()
    #[derive(Default)]
    struct XmppData {
    /// known roster data
    roster: HashMap<
    xmpp_parsers::Jid,
    (
    xmpp_parsers::roster::Subscription,
    xmpp_parsers::roster::Ask,
    ),
    >,
    /// ids counter
    counter: usize,
    /// map from id of adding item to roster and jid of item
    pending_add_roster_ids: HashMap<String, xmpp_parsers::Jid>,
    /// stanzas to send
    send_queue: VecDeque<minidom::Element>,
    /// outgoing mailbox
    outgoing_mailbox: HashMap<xmpp_parsers::Jid, Vec<String>>,
    /// muc id to muc jid
    mucs: HashMap<String, xmpp_parsers::Jid>,
    }
    struct XmppState {
    client: Client,
    data: XmppData,
    }
    struct MaybeXmppConnection {
    account: std::rc::Rc<config::Account>,
    state: Option<XmppState>,
    }
    struct XmppConnection {
    account: std::rc::Rc<config::Account>,
    state: XmppState,
    }
    impl From<XmppConnection> for MaybeXmppConnection {
    fn from(from: XmppConnection) -> MaybeXmppConnection {
    MaybeXmppConnection {
    account: from.account,
    state: Some(from.state),
    }
    }
    }
    impl From<config::Account> for MaybeXmppConnection {
    fn from(from: config::Account) -> MaybeXmppConnection {
    MaybeXmppConnection {
    account: std::rc::Rc::new(from),
    state: None,
    }
    }
    }
    impl From<std::rc::Rc<config::Account>> for MaybeXmppConnection {
    fn from(from: std::rc::Rc<config::Account>) -> MaybeXmppConnection {
    MaybeXmppConnection {
    account: from,
    state: None,
    }
    }
    }
    impl MaybeXmppConnection {
    /// connects if nothing connected
    /// don't connect only if stop_future resolved
    fn connect<F>(
    self,
    stop_future: F,
    ) -> impl Future<Item = XmppConnection, Error = failure::Error>
    where
    F: future::Future + Clone + 'static,
    <F as hyper::rt::Future>::Error: Into<failure::Error> + Send,
    {
    info!("xmpp connection...");
    let MaybeXmppConnection { account, state } = self;
    if let Some(state) = state {
    Box::new(future::ok(XmppConnection { account, state }))
    as Box<dyn Future<Item = _, Error = _>>
    } else {
    Box::new(
    stop_future
    .clone()
    .select2(
    future::loop_fn(account, move |account| {
    info!("xmpp initialization...");
    let client =
    Client::new_with_jid(account.jid.clone(), &account.password);
    info!("xmpp initialized");
    let stop_future2 = stop_future.clone();
    let stop_future3 = stop_future.clone();
    let stop_future4 = stop_future.clone();
    // future to wait for online
    Box::new(
    XmppConnection {
    state: XmppState {
    client,
    data: std::default::Default::default(),
    },
    account,
    }
    .processing(XmppConnection::online, stop_future.clone())
    .map_err(|(acc, _)| acc)
    .and_then(|(conn, r)| match r {
    Ok(Either::A(_)) => future::ok(conn),
    Ok(Either::B(_)) => future::err(conn.account),
    Err(_e) => future::err(conn.account),
    })
    .and_then(|conn| conn.initial_roster(stop_future2))
    .and_then(|conn| conn.self_presence(stop_future3))
    .and_then(|conn| conn.enter_mucs(stop_future4))
    .then(|r| match r {
    Ok(conn) => future::ok(future::Loop::Break(conn)),
    Err(acc) => future::ok(future::Loop::Continue(acc)),
    }),
    )
    })
    .map_err(|_: ()| ()),
    )
    .then(|r| match r {
    Ok(Either::A((_x, _b))) => future::err(format_err!("Stop XMMP connection")),
    Ok(Either::B((x, _a))) => future::ok(x),
    Err(Either::A((e, _b))) => future::err(e.into()),
    Err(Either::B((_, _a))) => {
    future::err(format_err!("Cann't initiate XMPP connection"))
    }
    }),
    )
    }
    }
    }
    impl XmppConnection {
    /// base XMPP processing
    fn xmpp_processing(
    mut self,
    event: &Event,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>> {
    match event {
    Event::Stanza(stanza) => {
    info!("Incoming xmpp event: {:?}", stanza);
    let stanza = stanza.clone();
    use try_from::TryInto;
    if let Some(iq) = stanza.try_into().ok() as Option<xmpp_parsers::iq::Iq> {
    if let Some(id) = iq.id {
    if let Some((_, jid)) =
    self.state.data.pending_add_roster_ids.remove_entry(&id)
    {
    if let xmpp_parsers::iq::IqType::Result(None) = iq.payload {
    if self.state.data.roster.contains_key(&jid) {
    info!("Jid {} updated to roster", jid);
    } else {
    info!("Jid {} added in roster", jid);
    self.state.data.roster.insert(
    jid.clone(),
    (
    xmpp_parsers::roster::Subscription::None,
    xmpp_parsers::roster::Ask::None,
    ),
    );
    }
    self.process_jid(&jid);
    } else {
    warn!(
    "Wrong payload when adding {} to roster: {:?}",
    jid, iq.payload
    );
    }
    }
    }
    if let xmpp_parsers::iq::IqType::Set(element) = iq.payload {
    if let Some(roster) =
    element.try_into().ok() as Option<xmpp_parsers::roster::Roster>
    {
    for i in roster.items {
    if let Some(ref mut rdata) = self.state.data.roster.get_mut(&i.jid)
    {
    info!("Update {} in roster", i.jid);
    rdata.0 = i.subscription;
    rdata.1 = i.ask;
    } else {
    info!("Add {} to roster", i.jid);
    self.state
    .data
    .roster
    .insert(i.jid.clone(), (i.subscription, i.ask));
    }
    self.process_jid(&i.jid);
    }
    }
    }
    }
    future::ok(self)
    }
    Event::Online => future::ok(self),
    e => {
    warn!("Unexpected event {:?}", e);
    future::err(self.account)
    }
    }
    }
    /// process event from xmpp stream
    /// returns from future when condition met
    /// or stop future was resolved.
    /// Return item if connection was preserved or error otherwise.
    /// Second part is a state of stop_future
    fn processing<S, F, T, E>(
    self,
    stop_condition: S,
    stop_future: F,
    ) -> impl Future<
    Item = (Self, Result<Either<F, T>, E>),
    Error = (std::rc::Rc<config::Account>, Result<Either<F, T>, E>),
    >
    where
    F: Future<Item = T, Error = E> + 'static,
    S: FnMut(&mut Self, Event) -> Result<bool, ()> + 'static,
    T: 'static,
    E: 'static,
    {
    future::loop_fn(
    (self, stop_future, stop_condition),
    |(xmpp, stop_future, mut stop_condition)| {
    let XmppConnection {
    state: XmppState { client, mut data },
    account,
    } = xmpp;
    if let Some(send_element) = data.send_queue.pop_front() {
    use tokio::prelude::Sink;
    info!("Sending {:?}", send_element);
    Box::new(
    client
    .send(Packet::Stanza(send_element))
    .select2(stop_future)
    .then(move |r| match r {
    Ok(Either::A((client, b))) => {
    Box::new(future::ok(future::Loop::Continue((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    b,
    stop_condition,
    ))))
    as Box<dyn Future<Item = _, Error = _>>
    }
    Ok(Either::B((t, a))) => Box::new(a.then(|r| match r {
    Ok(client) => future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Ok(Either::B(t)),
    ))),
    Err(se) => {
    warn!("XMPP sending error: {}", se);
    future::err((account, Ok(Either::B(t))))
    }
    })),
    Err(Either::A((e, b))) => {
    warn!("XMPP sending error: {}", e);
    Box::new(future::err((account, Ok(Either::A(b)))))
    }
    Err(Either::B((e, a))) => Box::new(a.then(|r| match r {
    Ok(client) => future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Err(e),
    ))),
    Err(se) => {
    warn!("XMPP sending error: {}", se);
    future::err((account, Err(e)))
    }
    })),
    }),
    ) as Box<dyn Future<Item = _, Error = _>>
    } else {
    Box::new(
    client
    .into_future()
    .select2(stop_future)
    .then(move |r| match r {
    Ok(Either::A(((event, client), b))) => {
    if let Some(event) = event {
    let xmpp = XmppConnection {
    state: XmppState { client, data },
    account,
    };
    Box::new(xmpp.xmpp_processing(&event).then(|r| match r {
    Ok(mut xmpp) => {
    match stop_condition(&mut xmpp, event) {
    Ok(true) => future::ok(future::Loop::Break((
    xmpp,
    Ok(Either::A(b)),
    ))),
    Ok(false) => {
    future::ok(future::Loop::Continue((
    xmpp,
    b,
    stop_condition,
    )))
    }
    Err(_e) => future::err((
    xmpp.account,
    Ok(Either::A(b)),
    )),
    }
    }
    Err(account) => {
    future::err((account, Ok(Either::A(b))))
    }
    }))
    as Box<dyn Future<Item = _, Error = _>>
    } else {
    Box::new(future::err((account, Ok(Either::A(b)))))
    }
    }
    Ok(Either::B((t, a))) => {
    Box::new(if let Some(client) = a.into_inner() {
    future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Ok(Either::B(t)),
    )))
    } else {
    future::err((account, Ok(Either::B(t))))
    })
    }
    Err(Either::A((e, b))) => {
    warn!("XMPP error: {}", e.0);
    Box::new(future::err((account, Ok(Either::A(b)))))
    }
    Err(Either::B((e, a))) => {
    Box::new(if let Some(client) = a.into_inner() {
    future::ok(future::Loop::Break((
    XmppConnection {
    state: XmppState { client, data },
    account,
    },
    Err(e),
    )))
    } else {
    future::err((account, Err(e)))
    })
    }
    }),
    )
    }
    },
    )
    }
  • replacement in src/xmpp/mod.rs at line 9
    [3.55344][3.55344:55930](),[3.55344][3.55344:55930]()
    /// get connection and wait for online status and set presence
    /// returns error if something went wrong and xmpp connection is broken
    fn online(&mut self, event: Event) -> Result<bool, ()> {
    match event {
    Event::Online => {
    info!("Online!");
    Ok(true)
    }
    Event::Stanza(s) => {
    warn!("Stanza before online: {:?}", s);
    Ok(false)
    }
    _ => {
    error!("Disconnected while online");
    Err(())
    }
    }
    }
    [3.55344]
    [3.55930]
    mod xmpp_connection;
    use xmpp_connection::MaybeXmppConnection;
  • replacement in src/xmpp/mod.rs at line 12
    [3.55931][3.55931:56072](),[3.55931][3.55931:56072](),[3.56072][2.44271:44306](),[2.44306][3.56111:56207](),[3.56111][3.56111:56207](),[3.56207][2.44307:45881](),[2.45881][3.57267:57309](),[3.57267][3.57267:57309](),[3.57358][3.57358:57396](),[3.57396][2.45882:46071](),[2.46071][3.57608:57672](),[3.57608][3.57608:57672](),[3.57672][2.46072:46143](),[2.46143][3.57845:57900](),[3.57845][3.57845:57900](),[3.57900][2.46144:46232](),[2.46232][3.57934:60161](),[3.57934][3.57934:60161]()
    fn process_initial_roster(&mut self, event: Event, id_init_roster: &str) -> Result<bool, ()> {
    if let Event::Stanza(s) = event {
    use try_from::TryInto;
    match s.try_into() as Result<xmpp_parsers::iq::Iq, _> {
    Ok(iq) => {
    if let Some(id) = iq.id {
    if id == id_init_roster {
    match iq.payload {
    xmpp_parsers::iq::IqType::Error(_e) => {
    error!("Get error instead of roster");
    Err(())
    }
    xmpp_parsers::iq::IqType::Result(Some(result)) => {
    match result.try_into()
    as Result<xmpp_parsers::roster::Roster, _>
    {
    Ok(roster) => {
    self.state.data.roster.clear();
    info!("Got first roster:");
    for i in roster.items {
    info!(" >>> {:?}", i);
    self.state
    .data
    .roster
    .insert(i.jid, (i.subscription, i.ask));
    }
    Ok(true)
    }
    Err(e) => {
    error!("Cann't parse roster: {}", e);
    Err(())
    }
    }
    }
    _ => {
    error!("Unknown result of roster");
    Err(())
    }
    }
    } else {
    Ok(false)
    }
    } else {
    error!("Iq stanza without id");
    Err(())
    }
    }
    Err(_e) => Ok(false),
    }
    } else {
    error!("Wrong event while waiting roster");
    Err(())
    }
    }
    fn initial_roster<F, E>(
    self,
    stop_future: F,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>>
    where
    F: Future<Error = E> + 'static,
    E: 'static,
    {
    let XmppConnection {
    account,
    state: XmppState { client, mut data },
    } = self;
    use tokio::prelude::Sink;
    data.counter += 1;
    let id_init_roster = format!("id_init_roster{}", data.counter);
    let get_roster = stanzas::make_get_roster(&id_init_roster);
    let account2 = account.clone();
    info!("Quering roster... {:?}", get_roster);
    client
    .send(Packet::Stanza(get_roster))
    .map_err(move |e| {
    error!("Error on querying roster: {}", e);
    account2
    })
    .and_then(move |client| {
    XmppConnection {
    state: XmppState { client, data },
    account,
    }
    .processing(
    move |conn, event| conn.process_initial_roster(event, &id_init_roster),
    stop_future,
    )
    .map_err(|(account, _)| account)
    .and_then(|(conn, r)| match r {
    Ok(Either::A(_)) => future::ok(conn),
    Ok(Either::B(_)) => future::err(conn.account),
    Err(_e) => future::err(conn.account),
    })
    })
    }
    fn self_presence<F, E>(
    self,
    stop_future: F,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>>
    where
    F: Future<Error = E> + 'static,
    E: Into<failure::Error> + 'static,
    {
    let XmppConnection {
    account,
    state: XmppState { client, data },
    } = self;
    use tokio::prelude::Sink;
    let presence = stanzas::make_presence(&account);
    let account2 = account.clone();
    info!("Sending presence... {:?}", presence);
    [3.55931]
    [3.60161]
    pub use xmpp_connection::XmppCommand;
  • edit in src/xmpp/mod.rs at line 14
    [3.60162][3.60162:60651](),[3.60162][3.60162:60651](),[3.60651][2.46233:46617](),[2.46617][3.61178:66756](),[3.61178][3.61178:66756](),[3.38938][3.40647:40648](),[3.55914][3.40647:40648](),[3.66756][3.40647:40648](),[3.40647][3.40647:40648](),[3.40648][3.66757:66826](),[3.66826][3.56501:56502](),[3.42861][3.56501:56502](),[3.56501][3.56501:56502](),[3.56502][3.66827:67690](),[3.67690][3.60584:60585](),[3.42900][3.60584:60585](),[3.60584][3.60584:60585]()
    client
    .send(Packet::Stanza(presence))
    .map_err(|e| {
    error!("Error on send self-presence: {}", e);
    account2
    })
    .and_then(move |client| {
    XmppConnection {
    state: XmppState { client, data },
    account,
    }
    .processing(
    move |conn, event| {
    if let Event::Stanza(s) = event {
    if s.name() == "presence"
    && s.attr("from").map_or(false, |f| f == conn.account.jid)
    && s.attr("to").map_or(false, |f| f == conn.account.jid)
    {
    Ok(true)
    } else {
    Ok(false)
    }
    } else {
    error!("Wrong event while waiting self-presence");
    Err(())
    }
    },
    stop_future,
    )
    .map_err(|(account, _)| account)
    .and_then(|(conn, r)| match r {
    Ok(Either::A(_)) => future::ok(conn),
    Ok(Either::B(_)) => future::err(conn.account),
    Err(_e) => future::err(conn.account),
    })
    })
    }
    fn process_jid(&mut self, xmpp_to: &xmpp_parsers::Jid) {
    if let Some(ref mut mailbox) = self.state.data.outgoing_mailbox.get_mut(xmpp_to) {
    if !mailbox.is_empty() {
    if let Some(ref mut rdata) = self.state.data.roster.get_mut(xmpp_to) {
    info!("Jid {} in roster", xmpp_to);
    let sub_to = match rdata.0 {
    xmpp_parsers::roster::Subscription::To => true,
    xmpp_parsers::roster::Subscription::Both => true,
    _ => false,
    };
    if sub_to {
    info!("Subscribed to {}", xmpp_to);
    self.state.data.send_queue.extend(
    mailbox.drain(..).map(|message| {
    stanzas::make_chat_message(xmpp_to.clone(), message)
    }),
    );
    } else if rdata.1 == xmpp_parsers::roster::Ask::None {
    info!("Not subscribed to {}", xmpp_to);
    self.state
    .data
    .send_queue
    .push_back(stanzas::make_ask_subscribe(xmpp_to.clone()));
    }
    } else {
    info!("Jid {} not in roster", xmpp_to);
    self.state.data.counter += 1;
    let id_add_roster = format!("id_add_roster{}", self.state.data.counter);
    let add_roster = stanzas::make_add_roster(&id_add_roster, xmpp_to.clone());
    self.state
    .data
    .pending_add_roster_ids
    .insert(id_add_roster, xmpp_to.clone());
    info!("Adding jid to roster... {:?}", add_roster);
    self.state.data.send_queue.push_back(add_roster);
    }
    }
    }
    }
    fn process_command(&mut self, cmd: XmppCommand) {
    info!("Got command");
    match cmd {
    XmppCommand::Chat { xmpp_to, message } => {
    self.state
    .data
    .outgoing_mailbox
    .entry(xmpp_to.clone())
    .or_default()
    .push(message);
    self.process_jid(&xmpp_to);
    }
    XmppCommand::Chatroom { muc_id, message } => {
    if let Some(muc) = self.state.data.mucs.get(&muc_id) {
    self.state
    .data
    .send_queue
    .push_back(stanzas::make_muc_message(muc.clone(), message));
    } else {
    error!("Not found MUC {}", muc_id);
    }
    }
    XmppCommand::Ping => {
    self.state.data.counter += 1;
    let id_ping = format!("id_ping{}", self.state.data.counter);
    let ping = stanzas::make_ping(&id_ping, self.state.client.jid.clone());
    self.state.data.send_queue.push_back(ping);
    }
    }
    }
    fn shutdown(self) -> impl Future<Item = (), Error = failure::Error> {
    info!("Shutdown connection");
    let XmppConnection { account, state } = self;
    stream::iter_ok(
    state
    .data
    .mucs
    .values()
    .map(std::clone::Clone::clone)
    .collect::<Vec<_>>(),
    )
    .fold(state, move |XmppState { client, data }, muc_jid| {
    let muc_presence =
    stanzas::make_muc_presence_leave(account.jid.clone(), muc_jid.clone());
    info!("Sending muc leave presence... {:?}", muc_presence);
    use tokio::prelude::Sink;
    client
    .send(Packet::Stanza(muc_presence))
    .map_err(|e| {
    error!("Error on send muc presence: {}", e);
    e
    })
    .and_then(|client| future::ok(XmppState { client, data }))
    })
    .map(|_| ())
    }
    fn enter_mucs<F, E>(
    self,
    _stop_future: F,
    ) -> impl Future<Item = Self, Error = std::rc::Rc<config::Account>>
    where
    F: Future<Error = E> + 'static,
    E: Into<failure::Error> + 'static,
    {
    let XmppConnection { account, state } = self;
    let account2 = account.clone();
    let account3 = account.clone();
    stream::iter_ok(account.chatrooms.clone())
    .fold(state, move |XmppState { client, mut data }, muc_jid| {
    data.counter += 1;
    let id_muc_presence = format!("id_muc_presence{}", data.counter);
    let muc_presence = stanzas::make_muc_presence(
    &id_muc_presence,
    account2.jid.clone(),
    muc_jid.1.clone(),
    );
    info!("Sending muc presence... {:?}", muc_presence);
    let account4 = account2.clone();
    use tokio::prelude::Sink;
    client
    .send(Packet::Stanza(muc_presence))
    .map_err(|e| {
    error!("Error on send muc presence: {}", e);
    account4
    })
    .and_then(|client| {
    data.mucs.insert(muc_jid.0, muc_jid.1);
    future::ok(XmppState { client, data })
    })
    })
    .map(|state| XmppConnection {
    account: account3,
    state,
    })
    }
    }
    #[derive(Debug)]
    pub enum XmppCommand {
    Chat {
    xmpp_to: xmpp_parsers::Jid,
    message: String,
    },
    Chatroom {
    muc_id: String,
    message: String,
    },
    Ping,
    }
  • replacement in src/xmpp/element_processor.rs at line 0
    [3.11301][2.46618:47720]()
    type Func<S, T, E> = dyn Fn(&mut S, E) -> T;
    /// TryFrom based visitor
    pub struct Processor<S: 'static, T: 'static, E: Clone + 'static> {
    processors: Vec<Box<Func<S, Option<T>, E>>>,
    default: &'static Func<S, T, E>,
    }
    impl<S: 'static, T: 'static, E: Clone + 'static> Processor<S, T, E> {
    pub fn new<F>(f: &'static F) -> Processor<S, T, E>
    where
    F: Fn(&mut S, E) -> T + 'static,
    {
    Processor {
    processors: vec![],
    default: f,
    }
    }
    pub fn register<F, A>(&mut self, f: &'static F)
    where
    F: Fn(&mut S, A) -> T + 'static,
    A: std::convert::TryFrom<E>,
    {
    self.processors.push(Box::new(move |s, e: E| {
    use std::convert::TryInto;
    (e.try_into().ok() as Option<A>).map(|a| f(s, a))
    }));
    }
    pub fn process(&self, s: &mut S, e: E) -> T {
    for processor in self.processors.iter() {
    match processor(s, e.clone()) {
    Some(t) => return t,
    None => continue,
    }
    }
    (*self.default)(s, e)
    }
    }
    [3.11301]
    type Func<S, T, E> = dyn Fn(&mut S, E) -> T + Sync;
    pub struct Processor<S: 'static, T: 'static, E: Clone + 'static> {
    processors: Vec<Box<Func<S, Option<T>, E>>>,
    default: &'static Func<S, T, E>,
    }
    impl<S: 'static, T: 'static, E: Clone + 'static> Processor<S, T, E> {
    pub fn new<F>(f: &'static F) -> Processor<S, T, E>
    where
    F: Fn(&mut S, E) -> T + Sync + 'static,
    {
    Processor {
    processors: vec![],
    default: f,
    }
    }
    pub fn register<F, A>(&mut self, f: &'static F)
    where
    F: Fn(&mut S, A) -> T + Sync + 'static,
    A: std::convert::TryFrom<E>,
    {
    self.processors.push(Box::new(move |s, e: E| {
    use std::convert::TryInto;
    (e.try_into().ok() as Option<A>).map(|a| f(s, a))
    }));
    }
    pub fn process(&self, s: &mut S, e: E) -> T {
    for processor in self.processors.iter() {
    match processor(s, e.clone()) {
    Some(t) => return t,
    None => continue,
    }
    }
    (*self.default)(s, e)
    }
    }
  • edit in src/main.rs at line 21
    [3.41232]
    [3.41232]
    #[macro_use]
    extern crate lazy_static;
  • edit in src/main.rs at line 217
    [3.49351][2.47721:47758]()
    use hyper::rt::{Future, Stream};
  • replacement in src/config.rs at line 0
    [3.1396][2.47759:47801]()
    use std::collections::{HashMap, HashSet};
    [3.1396]
    [3.1397]
    use std::collections::HashMap;
  • edit in src/config.rs at line 13
    [3.46496][2.47802:48278]()
    }
    #[derive(Debug, Deserialize)]
    pub struct CmdArgs {
    pub name: String,
    }
    /// Allowed sources of command
    #[derive(Debug, Deserialize, PartialEq, Eq, Hash)]
    pub enum Source {
    /// Direct message
    Message,
    /// Groupchat message
    GroupChat,
    /// Private groupchat message
    PrivateGroupChat,
    }
    /// Command to execute
    #[derive(Debug, Deserialize)]
    pub struct Command {
    pub source: HashSet<Source>,
    /// Command arguments
    pub args: Vec<CmdArgs>,
  • edit in src/config.rs at line 19
    [3.1664][2.48279:48375]()
    /// map from command name to command definition
    pub commands: HashMap<String, Command>,
  • replacement in Cargo.toml at line 15
    [3.52750][2.48376:48389]()
    toml = "0.4"
    [3.52750]
    [3.52763]
    toml = "0.5"
  • replacement in Cargo.toml at line 21
    [3.54573][2.48390:48414]()
    xmpp-parsers = "0.12.2"
    [3.54573]
    [3.54595]
    xmpp-parsers = "0.13"
  • replacement in Cargo.toml at line 23
    [3.54630][2.48415:48450]()
    try_from = "=0.3.2" # xmpp-parsers
    [3.54630]
    lazy_static = "1.3.0" # ToDo: remove after const fn will be powerfull enough
  • edit in Cargo.lock at line 3
    [2.48463][2.48463:48660](),[3.55008][3.53201:53213](),[2.48660][3.53201:53213](),[3.53201][3.53201:53213]()
    name = "MacTypes-sys"
    version = "2.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    dependencies = [
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    ]
    [[package]]
  • replacement in Cargo.lock at line 4
    [3.53235][2.48661:48680]()
    version = "0.6.10"
    [3.53235]
    [3.53253]
    version = "0.7.3"
  • replacement in Cargo.lock at line 15
    [3.53543][2.48681:48754]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.53543]
    [3.53616]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 20
    [3.53649][2.48755:48773]()
    version = "0.3.7"
    [3.53649]
    [3.46847]
    version = "0.3.11"
  • replacement in Cargo.lock at line 36
    [3.54069][2.48774:48993]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.54069]
    [3.54288]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 43
    [3.55455][3.55455:55473]()
    version = "0.1.2"
    [3.55455]
    [3.54338]
    version = "0.1.4"
  • replacement in Cargo.lock at line 48
    [3.54435][2.48994:49013]()
    version = "0.3.14"
    [3.54435]
    [3.54454]
    version = "0.3.30"
  • replacement in Cargo.lock at line 51
    [3.54536][3.55494:55568]()
    "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.54536]
    [3.55568]
    "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 53
    [3.55649][2.49014:49314]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.55649]
    [3.54991]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 63
    [3.55130][2.49315:49457]()
    "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.55130]
    [3.55272]
    "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 72
    [3.55404][3.56133:56209]()
    "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.55404]
    [3.55480]
    "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 77
    [3.55513][3.55513:55531](),[3.55513][3.55513:55531](),[3.55513][3.55513:55531]()
    version = "1.0.4"
    [3.55513]
    [3.55531]
    version = "1.1.0"
  • replacement in Cargo.lock at line 93
    [3.56068][2.49458:49476]()
    version = "0.7.0"
    [3.56068]
    [3.56538]
    version = "0.7.3"
  • replacement in Cargo.lock at line 96
    [3.56620][2.49477:49557]()
    "block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.56620]
    [3.56635]
    "block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 98
    [3.56712][3.56712:56788](),[3.56712][3.56712:56788](),[3.56712][3.56712:56788]()
    "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.56712]
    [3.56788]
    "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 104
    [3.56907][2.49558:49576]()
    version = "0.1.3"
    [3.56907]
    [3.56925]
    version = "0.1.4"
  • replacement in Cargo.lock at line 117
    [3.56847][3.57104:57122]()
    version = "1.3.1"
    [3.56847]
    [3.56865]
    version = "1.3.2"
  • replacement in Cargo.lock at line 122
    [3.56958][2.49577:49596]()
    version = "0.4.11"
    [3.56958]
    [3.56977]
    version = "0.4.12"
  • replacement in Cargo.lock at line 125
    [3.57059][3.57143:57219]()
    "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.57059]
    [3.57135]
    "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 137
    [3.57344][2.49597:49616]()
    version = "1.0.30"
    [3.57344]
    [3.57363]
    version = "1.0.37"
  • replacement in Cargo.lock at line 142
    [3.57457][2.49617:49635]()
    version = "0.1.6"
    [3.57457]
    [3.57475]
    version = "0.1.9"
  • replacement in Cargo.lock at line 150
    [3.57669][3.57669:57825](),[3.57669][3.57669:57825](),[3.57669][3.57669:57825](),[3.57669][3.57669:57825](),[3.57669][3.57669:57825](),[3.57669][3.57669:57825]()
    "num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)",
    "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.57669]
    [3.57259]
    "num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)",
    "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 157
    [3.57926][2.49636:49655]()
    version = "2.32.0"
    [3.57926]
    [3.57945]
    version = "2.33.0"
  • replacement in Cargo.lock at line 162
    [3.58176][3.58176:58251](),[3.58176][3.58176:58251](),[3.58176][3.58176:58251](),[3.58176][3.58176:58251](),[3.58176][3.58176:58251](),[3.58176][3.58176:58251](),[3.58251][2.49656:49805]()
    "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
    "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.58176]
    [3.58400]
    "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 174
    [3.58687][3.58687:58762](),[3.58687][3.58687:58762](),[3.58687][3.58687:58762](),[3.58687][3.58687:58762](),[3.58687][3.58687:58762](),[3.58687][3.58687:58762]()
    "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.58687]
    [3.58762]
    "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 179
    [3.58802][2.49806:49824]()
    version = "0.5.1"
    [3.58802]
    [3.58820]
    version = "0.6.4"
  • replacement in Cargo.lock at line 182
    [3.58902][2.49825:49983]()
    "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.58902]
    [3.59060]
    "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 188
    [3.59104][2.49984:50002]()
    version = "0.5.1"
    [3.59104]
    [3.59638]
    version = "0.6.2"
  • edit in Cargo.lock at line 190
    [3.59703][2.50003:50094]()
    dependencies = [
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    ]
  • replacement in Cargo.lock at line 206
    [3.71853][2.50095:50168]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.71853]
    [3.71926]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 226
    [3.60544][2.50169:50242]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.60544]
    [3.49467]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  • edit in Cargo.lock at line 258
    [3.61564]
    [3.61564]
    name = "either"
    version = "1.5.2"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    [[package]]
  • replacement in Cargo.lock at line 267
    [3.61686][2.50243:50316]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.61686]
    [3.61759]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 272
    [3.61794][2.50317:50335]()
    version = "0.6.0"
    [3.61794]
    [3.61812]
    version = "0.6.1"
  • replacement in Cargo.lock at line 278
    [3.59057][2.50336:50408](),[3.59129][3.62184:62260](),[2.50408][3.62184:62260](),[3.51020][3.62184:62260](),[3.30931][3.62184:62260](),[3.72592][3.62184:62260](),[3.44607][3.62184:62260](),[3.63170][3.62184:62260](),[3.49731][3.62184:62260](),[3.62184][3.62184:62260]()
    "regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.59057]
    [3.62260]
    "regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
    "termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 287
    [3.62396][2.50409:50486]()
    "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.62396]
    [3.62473]
    "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 295
    [3.62605][2.50487:50564]()
    "backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.62605]
    [3.59304]
    "backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 304
    [3.62902][2.50565:50789](),[2.50789][3.59629:59709](),[3.72894][3.59629:59709](),[3.44760][3.59629:59709](),[3.50033][3.59629:59709](),[3.59629][3.59629:59709]()
    "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.62902]
    [3.63206]
    "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)",
    "synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 343
    [3.64039][3.64039:64114](),[3.64039][3.64039:64114]()
    "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.64039]
    [3.64114]
    "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 363
    [3.64642][2.50790:50809]()
    version = "0.1.25"
    [3.64642]
    [3.64661]
    version = "0.1.27"
  • replacement in Cargo.lock at line 371
    [3.64864][2.50810:50885](),[2.50885][3.50218:50294](),[3.50218][3.50218:50294]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.64864]
    [3.65015]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 385
    [3.65256][2.50886:50905]()
    version = "0.1.16"
    [3.65256]
    [3.65275]
    version = "0.1.23"
  • replacement in Cargo.lock at line 388
    [3.65357][3.60131:60207](),[3.60207][2.50906:50979]()
    "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.65357]
    [3.65506]
    "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 391
    [3.65576][2.50980:51127]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.65576]
    [3.65723]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 396
    [3.60570][3.60570:60643]()
    "string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.60570]
    [3.50537]
    "string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 414
    [3.66500][2.51128:51200]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.66500]
    [3.66572]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 420
    [3.66675][2.51201:51220]()
    version = "0.1.16"
    [3.66675]
    [3.66694]
    version = "0.1.17"
  • replacement in Cargo.lock at line 423
    [3.66776][2.51221:51294]()
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.66776]
    [3.66849]
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 425
    [3.66919][3.66919:66990](),[3.66919][3.66919:66990](),[3.66919][3.66919:66990](),[3.66919][3.66919:66990](),[3.66919][3.66919:66990](),[3.66919][3.66919:66990]()
    "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.66919]
    [3.66990]
    "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
    ]
    [[package]]
    name = "http-body"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    dependencies = [
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 454
    [3.67346][2.51295:51315]()
    version = "0.12.25"
    [3.67346]
    [3.67366]
    version = "0.12.30"
  • replacement in Cargo.lock at line 457
    [3.67448][2.51316:51464]()
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.67448]
    [3.67596]
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 460
    [3.67678][2.51465:51607]()
    "h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
    "http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.67678]
    [3.67820]
    "h2 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)",
    "http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
    "http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 465
    [3.67967][3.67967:68038](),[3.67967][3.67967:68038](),[3.67967][3.67967:68038](),[3.67967][3.67967:68038](),[3.67967][3.67967:68038](),[3.67967][3.67967:68038]()
    "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.67967]
    [3.61498]
    "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 470
    [3.61721][2.51608:51762]()
    "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.61721]
    [3.51329]
    "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 476
    [3.62107][2.51763:51847](),[2.51847][3.62191:62270](),[3.74349][3.62191:62270](),[3.44992][3.62191:62270](),[3.51570][3.62191:62270](),[3.62191][3.62191:62270]()
    "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.62107]
    [3.68881]
    "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 501
    [3.69566][2.51848:51920]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.69566]
    [3.69638]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 511
    [3.69922][3.69922:69996](),[3.69922][3.69922:69996](),[3.69922][3.69922:69996]()
    "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.69922]
    [3.69996]
    "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 513
    [3.70073][2.51921:51994]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.70073]
    [3.70146]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 519
    [3.70248][3.70248:70266](),[3.70248][3.70248:70266](),[3.70248][3.70248:70266](),[3.70248][3.70248:70266](),[3.70248][3.70248:70266](),[3.70248][3.70248:70266]()
    version = "0.4.3"
    [3.70248]
    [3.70266]
    version = "0.4.4"
  • edit in Cargo.lock at line 552
    [3.71220][3.71220:71238](),[3.71220][3.71220:71238](),[3.71238][3.62795:62813](),[3.62813][3.71256:71334](),[3.54531][3.71256:71334](),[3.71256][3.71256:71334]()
    name = "lazycell"
    version = "1.2.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    [[package]]
  • replacement in Cargo.lock at line 553
    [3.71348][2.51995:52014]()
    version = "0.2.49"
    [3.71348]
    [3.71367]
    version = "0.2.58"
  • replacement in Cargo.lock at line 558
    [3.71470][2.52015:52033]()
    version = "0.4.2"
    [3.71470]
    [3.71488]
    version = "0.5.2"
  • replacement in Cargo.lock at line 575
    [3.54885][2.52034:52107]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.54885]
    [3.72039]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 580
    [3.72073][2.52108:52126]()
    version = "0.1.1"
    [3.72073]
    [3.72091]
    version = "0.1.2"
  • replacement in Cargo.lock at line 583
    [3.72173][2.52127:52209]()
    "linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.72173]
    [3.72255]
    "linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 598
    [3.63314][2.52210:52363]()
    "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
    "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.63314]
    [3.52105]
    "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
    "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 633
    [3.73854][3.73854:73873](),[3.73854][3.73854:73873](),[3.73854][3.73854:73873](),[3.73854][3.73854:73873](),[3.73854][3.73854:73873]()
    version = "0.6.16"
    [3.73854]
    [3.73873]
    version = "0.6.19"
  • replacement in Cargo.lock at line 640
    [3.74272][3.63893:63968](),[3.63968][2.52364:52436]()
    "lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.74272]
    [3.64040]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 654
    [3.74980][2.52437:52509](),[3.64255][3.75052:75123](),[2.52509][3.75052:75123](),[3.56415][3.75052:75123](),[3.75370][3.75052:75123](),[3.45231][3.75052:75123](),[3.52426][3.75052:75123](),[3.75052][3.75052:75123]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.74980]
    [3.75123]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 671
    [3.75588][2.52510:52528]()
    version = "0.2.2"
    [3.75588]
    [3.75606]
    version = "0.2.3"
  • replacement in Cargo.lock at line 675
    [3.52505][2.52529:52601]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.52505]
    [3.64406]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 677
    [3.64476][2.52602:52678]()
    "openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.64476]
    [3.75984]
    "openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 679
    [3.76064][2.52679:52758]()
    "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.76064]
    [3.52734]
    "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 681
    [3.52810][2.52759:52933](),[2.52933][3.52811:52886](),[3.45498][3.52811:52886](),[3.64882][3.52811:52886]()
    "security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
    "tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.52810]
    [3.76468]
    "security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 691
    [3.76598][2.52934:53152]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.76598]
    [3.76816]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 708
    [3.77092][3.77092:77111](),[3.77092][3.77092:77111](),[3.77092][3.77092:77111]()
    version = "0.1.39"
    [3.77092]
    [3.77111]
    version = "0.1.41"
  • replacement in Cargo.lock at line 711
    [3.77193][3.77193:77270](),[3.77193][3.77193:77270](),[3.77193][3.77193:77270]()
    "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.77193]
    [3.77270]
    "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
    "num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 717
    [3.77305][3.77305:77323](),[3.77305][3.77305:77323](),[3.77305][3.77305:77323]()
    version = "0.2.6"
    [3.77305]
    [3.77323]
    version = "0.2.8"
  • edit in Cargo.lock at line 719
    [3.77388]
    [3.77388]
    dependencies = [
    "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
    ]
  • replacement in Cargo.lock at line 725
    [3.77419][3.53125:53144]()
    version = "1.10.0"
    [3.77419]
    [3.77438]
    version = "1.10.1"
  • replacement in Cargo.lock at line 728
    [3.77520][2.53153:53225]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.77520]
    [3.77592]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • edit in Cargo.lock at line 730
    [3.77594]
    [3.65309]
    [[package]]
    name = "numtoa"
    version = "0.1.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
  • replacement in Cargo.lock at line 743
    [3.77742][2.53226:53246]()
    version = "0.10.19"
    [3.77742]
    [3.77762]
    version = "0.10.23"
  • replacement in Cargo.lock at line 746
    [3.77844][3.77844:77919](),[3.77844][3.77844:77919](),[3.77844][3.77844:77919](),[3.77844][3.77844:77919](),[3.77844][3.77844:77919](),[3.77844][3.77844:77919](),[3.77919][2.53247:53320]()
    "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.77844]
    [3.77992]
    "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 750
    [3.53391][2.53321:53472]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.53391]
    [3.78301]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 761
    [3.78456][2.53473:53492]()
    version = "0.9.42"
    [3.78456]
    [3.78475]
    version = "0.9.47"
  • replacement in Cargo.lock at line 764
    [3.78557][2.53493:53635]()
    "cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.78557]
    [3.78699]
    "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
    "cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • edit in Cargo.lock at line 768
    [3.78777][3.53706:53786]()
    "rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 793
    [3.79584][2.53636:53708]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.79584]
    [3.66285]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 796
    [3.79807][3.53860:53935](),[3.53935][2.53709:53782]()
    "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.79807]
    [3.66505]
    "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 805
    [3.66636][3.66636:66712](),[3.66636][3.66636:66712](),[3.66636][3.66636:66712](),[3.66636][3.66636:66712]()
    "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.66636]
    [3.66712]
    "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 860
    [3.81639][2.53783:53802]()
    version = "0.4.27"
    [3.81639]
    [3.81658]
    version = "0.4.30"
  • replacement in Cargo.lock at line 889
    [3.82508][2.53803:53822]()
    version = "0.6.11"
    [3.82508]
    [3.82527]
    version = "0.6.12"
  • replacement in Cargo.lock at line 892
    [3.82609][2.53823:53902]()
    "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.82609]
    [3.82688]
    "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 902
    [3.67870][2.53903:53975]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.67870]
    [3.67942]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 904
    [3.68018][2.53976:54049]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.68018]
    [3.83193]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 912
    [3.68192][3.68192:68266](),[3.68266][2.54050:54122]()
    "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.68192]
    [3.68338]
    "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 918
    [3.68643][3.68643:68721](),[3.68643][3.68643:68721](),[3.68643][3.68643:68721](),[3.68643][3.68643:68721](),[3.68643][3.68643:68721](),[3.68721][2.54123:54197]()
    "rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
    "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.68643]
    [3.54497]
    "rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
    "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 922
    [3.68950][2.54198:54271]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.68950]
    [3.69023]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 930
    [3.83322][3.69078:69152]()
    "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.83322]
    [3.69152]
    "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 965
    [3.69861][3.69861:69879]()
    version = "0.1.3"
    [3.69861]
    [3.69879]
    version = "0.1.4"
  • replacement in Cargo.lock at line 968
    [3.69961][2.54272:54344]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.69961]
    [3.70033]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 970
    [3.70109][2.54345:54418]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.70109]
    [3.70182]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 975
    [3.70214][2.54419:54437]()
    version = "0.1.2"
    [3.70214]
    [3.70232]
    version = "0.1.3"
  • replacement in Cargo.lock at line 980
    [3.70469][2.54438:54510]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.70469]
    [3.70541]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 983
    [3.70690][2.54511:54584]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.70690]
    [3.70763]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 991
    [3.70896][3.54979:55053]()
    "autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.70896]
    [3.55053]
    "autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1013
    [3.86863][2.54585:54604]()
    version = "0.1.51"
    [3.86863]
    [3.86882]
    version = "0.1.54"
  • replacement in Cargo.lock at line 1021
    [3.87083][2.54605:54686]()
    "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.87083]
    [3.87164]
    "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1026
    [3.87194][2.54687:54705]()
    version = "1.1.2"
    [3.87194]
    [3.87212]
    version = "1.1.7"
  • replacement in Cargo.lock at line 1029
    [3.87294][2.54706:54786]()
    "aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.87294]
    [3.55330]
    "aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1031
    [3.55403][2.54787:54866]()
    "regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.55403]
    [3.87525]
    "regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1033
    [3.87604][3.71759:71837]()
    "utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.87604]
    [3.87682]
    "utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1038
    [3.87719][2.54867:54885]()
    version = "0.6.5"
    [3.87719]
    [3.87737]
    version = "0.6.7"
  • replacement in Cargo.lock at line 1046
    [3.87933][3.87933:87951](),[3.87933][3.87933:87951](),[3.87933][3.87933:87951]()
    version = "0.5.1"
    [3.87933]
    [3.87951]
    version = "0.5.2"
  • replacement in Cargo.lock at line 1049
    [3.88033][2.54886:54959]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.88033]
    [3.88106]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1063
    [3.88434][2.54960:54979]()
    version = "0.1.13"
    [3.88434]
    [3.88453]
    version = "0.1.15"
  • replacement in Cargo.lock at line 1076
    [3.88755][3.72046:72064]()
    version = "0.2.7"
    [3.88755]
    [3.88773]
    version = "0.2.8"
  • replacement in Cargo.lock at line 1087
    [3.72302][2.54980:55054]()
    "rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.72302]
    [3.72376]
    "rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1098
    [3.55769][2.55055:55128]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.55769]
    [3.89685]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1108
    [3.89844][2.55129:55147]()
    version = "0.2.2"
    [3.89844]
    [3.89862]
    version = "0.3.1"
  • replacement in Cargo.lock at line 1111
    [3.89944][2.55148:55477]()
    "core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.89944]
    [3.90273]
    "core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
    "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1119
    [3.90320][2.55478:55496]()
    version = "0.2.3"
    [3.90320]
    [3.90338]
    version = "0.3.1"
  • replacement in Cargo.lock at line 1122
    [3.90420][2.55497:55734]()
    "MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.90420]
    [3.90657]
    "core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1142
    [3.91027][2.55735:55884]()
    "clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.91027]
    [3.73194]
    "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1145
    [3.73268][2.55885:55959]()
    "hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.73268]
    [3.73420]
    "hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)",
    "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1149
    [3.73565][2.55960:56186]()
    "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
    "serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.73565]
    [3.91695]
    "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
    "serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1155
    [3.73948][2.56187:56414]()
    "toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)",
    "try_from 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "xmpp-parsers 0.12.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.73948]
    [3.92082]
    "toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "xmpp-parsers 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1161
    [3.92112][2.56415:56434]()
    version = "1.0.89"
    [3.92112]
    [3.92131]
    version = "1.0.92"
  • replacement in Cargo.lock at line 1166
    [3.92231][2.56435:56454]()
    version = "1.0.89"
    [3.92231]
    [3.92250]
    version = "1.0.92"
  • replacement in Cargo.lock at line 1169
    [3.92332][2.56455:56679]()
    "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.92332]
    [3.92556]
    "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1179
    [3.92692][3.92692:92763](),[3.92692][3.92692:92763](),[3.92692][3.92692:92763](),[3.92692][3.92692:92763](),[3.92692][3.92692:92763](),[3.92763][3.74385:74455](),[3.74455][2.56680:56753]()
    "itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
    "ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
    "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.92692]
    [3.92906]
    "itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
    "ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
    "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1189
    [3.93036][2.56754:56833]()
    "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.93036]
    [3.74627]
    "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1200
    [3.93472][2.56834:56913]()
    "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.93472]
    [3.74879]
    "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1208
    [3.93808][2.56914:56932]()
    version = "0.8.1"
    [3.93808]
    [3.93826]
    version = "0.8.2"
  • replacement in Cargo.lock at line 1211
    [3.93908][2.56933:57012]()
    "block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.93908]
    [3.75131]
    "block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1220
    [3.94325][2.57013:57031]()
    version = "0.1.8"
    [3.94325]
    [3.94343]
    version = "0.1.9"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    dependencies = [
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "signal-hook-registry 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
    ]
    [[package]]
    name = "signal-hook-registry"
    version = "1.0.1"
  • replacement in Cargo.lock at line 1232
    [3.94425][2.57032:57179]()
    "arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.94425]
    [3.94573]
    "arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1248
    [3.94831][3.57359:57377]()
    version = "0.6.9"
    [3.94831]
    [3.94849]
    version = "0.6.10"
  • replacement in Cargo.lock at line 1253
    [3.94944][3.94944:94962](),[3.94944][3.94944:94962](),[3.94944][3.94944:94962]()
    version = "0.3.8"
    [3.94944]
    [3.94962]
    version = "0.3.9"
  • replacement in Cargo.lock at line 1256
    [3.95044][2.57180:57479]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.95044]
    [3.95343]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1269
    [3.95498][3.75868:75886]()
    version = "0.1.3"
    [3.95498]
    [3.95516]
    version = "0.2.0"
  • edit in Cargo.lock at line 1271
    [3.95581]
    [3.95581]
    dependencies = [
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    ]
  • replacement in Cargo.lock at line 1284
    [3.96043][2.57480:57553]()
    "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.96043]
    [3.96116]
    "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1296
    [3.76365][2.57554:57706]()
    "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.76365]
    [3.96745]
    "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1308
    [3.96987][2.57707:57725]()
    version = "0.7.0"
    [3.96987]
    [3.76536]
    version = "0.8.0"
  • replacement in Cargo.lock at line 1328
    [3.97562][2.57726:57746]()
    version = "0.15.27"
    [3.97562]
    [3.97582]
    version = "0.15.36"
  • replacement in Cargo.lock at line 1331
    [3.97664][2.57747:57899]()
    "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.97664]
    [3.97816]
    "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1346
    [3.98140][3.76823:76842]()
    version = "0.10.1"
    [3.98140]
    [3.98159]
    version = "0.10.2"
  • replacement in Cargo.lock at line 1349
    [3.98241][2.57900:58124]()
    "proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.98241]
    [3.98465]
    "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
    "quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1357
    [3.98576][3.58253:58271]()
    version = "3.0.7"
    [3.98576]
    [3.98594]
    version = "3.0.8"
  • replacement in Cargo.lock at line 1360
    [3.98676][2.58125:58270]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.98676]
    [3.77232]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1363
    [3.77303][2.58271:58352](),[3.77384][3.98973:99054](),[2.58352][3.98973:99054](),[3.65693][3.98973:99054](),[3.81560][3.98973:99054](),[3.58499][3.98973:99054](),[3.98973][3.98973:99054](),[3.99054][2.58353:58426]()
    "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
    "remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.77303]
    [3.99127]
    "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
    "remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1380
    [3.99506][3.99506:99524](),[3.99506][3.99506:99524](),[3.99506][3.99506:99524]()
    version = "1.0.4"
    [3.99506]
    [3.99524]
    version = "1.0.5"
  • replacement in Cargo.lock at line 1388
    [3.99713][2.58427:58445]()
    version = "1.5.1"
    [3.99713]
    [3.99731]
    version = "1.5.3"
  • replacement in Cargo.lock at line 1391
    [3.99813][2.58446:58599]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.99813]
    [3.99966]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1399
    [3.100079][2.58600:58619]()
    version = "0.10.0"
    [3.100079]
    [3.100098]
    version = "0.11.0"
  • replacement in Cargo.lock at line 1418
    [3.100605][2.58620:58846]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.100605]
    [3.100831]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)",
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1425
    [3.100861][2.58847:58866]()
    version = "0.1.16"
    [3.100861]
    [3.100880]
    version = "0.1.21"
  • replacement in Cargo.lock at line 1428
    [3.100962][2.58867:59015](),[3.78219][3.101110:101181](),[2.59015][3.101110:101181](),[3.66528][3.101110:101181](),[3.82283][3.101110:101181](),[3.59222][3.101110:101181](),[3.101110][3.101110:101181](),[3.101181][3.59223:59299]()
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
    "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.100962]
    [3.101257]
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
    "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1433
    [3.101335][2.59016:59184]()
    "tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.101335]
    [3.59468]
    "tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1438
    [3.59699][2.59185:59262]()
    "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.59699]
    [3.78773]
    "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1440
    [3.78849][2.59263:59347](),[2.59347][3.78933:79012](),[3.82921][3.78933:79012](),[3.48701][3.78933:79012](),[3.59861][3.78933:79012](),[3.78933][3.78933:79012]()
    "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.78849]
    [3.79095]
    "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-trace-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
  • edit in Cargo.lock at line 1445
    [3.79247]
    [3.102285]
    ]
    [[package]]
    name = "tokio-buf"
    version = "0.1.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    dependencies = [
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1462
    [3.102423][2.59348:59423]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.102423]
    [3.102498]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1470
    [3.102634][2.59424:59572]()
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.102634]
    [3.60170]
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1477
    [3.102903][2.59573:59591]()
    version = "0.1.5"
    [3.102903]
    [3.102921]
    version = "0.1.6"
  • replacement in Cargo.lock at line 1480
    [3.103003][2.59592:59748]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.103003]
    [3.103159]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1486
    [3.103198][2.59749:59767]()
    version = "0.1.6"
    [3.103198]
    [3.103216]
    version = "0.1.7"
  • replacement in Cargo.lock at line 1490
    [3.79826][2.59768:59843]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.79826]
    [3.103455]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1498
    [3.103588][2.59844:59919]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.103588]
    [3.60612]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1500
    [3.60688][2.59920:60004]()
    "tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.60688]
    [3.103823]
    "tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1508
    [3.103957][2.60005:60153]()
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.103957]
    [3.80325]
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1519
    [3.80497][2.60154:60229]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.80497]
    [3.61036]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1522
    [3.80720][3.104618:104689](),[3.68707][3.104618:104689](),[3.104618][3.104618:104689](),[3.104689][3.61115:61191]()
    "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
    "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.80720]
    [3.80797]
    "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
    "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1526
    [3.80946][2.60230:60311]()
    "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.80946]
    [3.61273]
    "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1528
    [3.61349][2.60312:60389]()
    "tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.61349]
    [3.105148]
    "tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1536
    [3.105285][2.60390:60537](),[3.81347][3.105432:105503](),[2.60537][3.105432:105503](),[3.69256][3.105432:105503](),[3.84472][3.105432:105503](),[3.48937][3.105432:105503](),[3.61574][3.105432:105503](),[3.105432][3.105432:105503]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.105285]
    [3.105503]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
    "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1540
    [3.105577][2.60538:60697]()
    "signal-hook 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.105577]
    [3.61734]
    "signal-hook 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1544
    [3.61890][2.60698:60771]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.61890]
    [3.81736]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1549
    [3.81771][2.60772:60790]()
    version = "0.1.3"
    [3.81771]
    [3.81789]
    version = "0.1.6"
  • replacement in Cargo.lock at line 1553
    [3.62053][2.60791:60866]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.62053]
    [3.105965]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1561
    [3.106379][2.60867:61015]()
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.106379]
    [3.106527]
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1564
    [3.106599][3.106599:106670](),[3.106599][3.106599:106670](),[3.106599][3.106599:106670](),[3.106599][3.106599:106670](),[3.106599][3.106599:106670](),[3.106599][3.106599:106670]()
    "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.106599]
    [3.62278]
    "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1571
    [3.106867][2.61016:61035]()
    version = "0.1.12"
    [3.106867]
    [3.106886]
    version = "0.1.14"
  • replacement in Cargo.lock at line 1577
    [3.82608][2.61036:61111]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.82608]
    [3.82683]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1579
    [3.82753][3.62696:62772]()
    "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.82753]
    [3.82829]
    "num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1582
    [3.82971][2.61112:61193]()
    "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.82971]
    [3.107658]
    "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1587
    [3.107694][3.83053:83072]()
    version = "0.2.10"
    [3.107694]
    [3.107713]
    version = "0.2.11"
  • replacement in Cargo.lock at line 1591
    [3.83155][2.61194:61269]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.83155]
    [3.83230]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1593
    [3.83301][2.61270:61351]()
    "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.83301]
    [3.108104]
    "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1601
    [3.108238][2.61352:61504]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.108238]
    [3.63089]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
    "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • edit in Cargo.lock at line 1607
    [3.63180]
    [3.108700]
    name = "tokio-trace-core"
    version = "0.2.0"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    dependencies = [
    "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
    ]
    [[package]]
  • replacement in Cargo.lock at line 1619
    [3.108819][2.61505:61653]()
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.108819]
    [3.83941]
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1622
    [3.84011][3.109037:109108](),[3.71265][3.109037:109108](),[3.109037][3.109037:109108]()
    "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.84011]
    [3.109108]
    "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1633
    [3.109476][2.61654:61802]()
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.109476]
    [3.109624]
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1636
    [3.109696][2.61803:61875]()
    "libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.109696]
    [3.84409]
    "libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1638
    [3.84479][3.109838:109909](),[3.71733][3.109838:109909](),[3.109838][3.109838:109909]()
    "mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.84479]
    [3.109909]
    "mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1650
    [3.110352][2.61876:61949]()
    "bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.110352]
    [3.110425]
    "bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1652
    [3.110504][2.61950:62025]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.110504]
    [3.110579]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1654
    [3.110650][2.62026:62103]()
    "native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.110650]
    [3.64220]
    "native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1657
    [3.85032][2.62104:62177]()
    "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.85032]
    [3.110948]
    "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1669
    [3.111531][2.62178:62197]()
    version = "0.4.10"
    [3.111531]
    [3.111549]
    version = "0.5.1"
  • replacement in Cargo.lock at line 1672
    [3.111631][2.62198:62271]()
    "serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.111631]
    [3.111704]
    "serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1680
    [3.111844][3.85695:85771]()
    "byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.111844]
    [3.85771]
    "byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1682
    [3.85845][2.62272:62347]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.85845]
    [3.112069]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1687
    [3.86140][3.64697:64772](),[3.86215][3.112434:112508](),[3.73615][3.112434:112508](),[3.87459][3.112434:112508](),[3.64772][3.112434:112508](),[3.112434][3.112434:112508](),[3.112508][2.62348:62429]()
    "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
    "socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.86140]
    [3.64854]
    "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
    "socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1693
    [3.86529][3.86529:86608](),[3.86529][3.86529:86608](),[3.86529][3.86529:86608]()
    "tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.86529]
    [3.86608]
    "tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1703
    [3.113190][2.62430:62503]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.113190]
    [3.86848]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1705
    [3.86922][2.62504:62579]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.86922]
    [3.86997]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1709
    [3.87220][2.62580:62656]()
    "lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.87220]
    [3.87296]
    "lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1711
    [3.87374][3.65317:65392](),[3.65392][2.62657:62730]()
    "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.87374]
    [3.87522]
    "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
    "tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1726
    [3.87641][2.62731:62804]()
    "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.87641]
    [3.87714]
    "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1752
    [3.87772][3.65540:65615]()
    "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.87772]
    [3.87847]
    "smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1787
    [3.115838][3.87888:87906]()
    version = "1.0.2"
    [3.115838]
    [3.115856]
    version = "1.0.3"
  • replacement in Cargo.lock at line 1805
    [3.116272][2.62805:62880]()
    "futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.116272]
    [3.87982]
    "futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1822
    [3.116751][2.62881:62899]()
    version = "0.3.6"
    [3.116751]
    [3.116769]
    version = "0.3.7"
  • replacement in Cargo.lock at line 1844
    [3.117425][2.62900:62973]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.117425]
    [3.117498]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1857
    [3.117765][2.62974:63047]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.117765]
    [3.88238]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1866
    [3.118047][2.63048:63121]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.118047]
    [3.118120]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1874
    [3.118252][2.63122:63195]()
    "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.118252]
    [3.118325]
    "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1910
    [3.89236][2.63196:63267]()
    "sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
    [3.89236]
    [3.89307]
    "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • edit in Cargo.lock at line 1912
    [3.89382]
    [3.120691]
    ]
    [[package]]
    name = "xmpp-parsers"
    version = "0.13.1"
    source = "registry+https://github.com/rust-lang/crates.io-index"
    dependencies = [
    "base64 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "blake2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "chrono 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
    "digest 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "jid 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
    "minidom 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "sha-1 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
    "sha2 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
    "sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
  • replacement in Cargo.lock at line 1931
    [3.120705][2.63268:63579]()
    "checksum MacTypes-sys 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "eaf9f0d0b1cc33a4d2aee14fb4b2eac03462ef4db29c8ac4057327d8a71ad86f"
    "checksum aho-corasick 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "81ce3d38065e618af2d7b77e10c5ad9a069859b4be3c2250f674af3840d9c8a5"
    [3.120705]
    [3.121015]
    "checksum aho-corasick 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e6f484ae0c99fec2e858eb6134949117399f222608d84cadb3f58c1f97c2364c"
  • replacement in Cargo.lock at line 1933
    [3.121168][2.63580:63731]()
    "checksum arc-swap 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "1025aeae2b664ca0ea726a89d574fe8f4e77dd712d443236ad1de00379450cf6"
    [3.121168]
    [3.90636]
    "checksum arc-swap 0.3.11 (registry+https://github.com/rust-lang/crates.io-index)" = "bc4662175ead9cd84451d5c35070517777949a2ed84551764129cedb88384841"
  • replacement in Cargo.lock at line 1936
    [3.121620][3.90789:90939](),[3.90939][2.63732:63885]()
    "checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
    "checksum backtrace 0.3.14 (registry+https://github.com/rust-lang/crates.io-index)" = "cd5a90e2b463010cd0e0ce9a11d4a9d5d58d9f41d4a6ba3dcaf9e68b466e88b4"
    [3.121620]
    [3.91092]
    "checksum autocfg 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "0e49efa51329a5fd37e7c79db4621af617cd4e3e5bc224939808d076077077bf"
    "checksum backtrace 0.3.30 (registry+https://github.com/rust-lang/crates.io-index)" = "ada4c783bb7e7443c14e0480f429ae2cc99da95065aeab7ee1b81ada0419404f"
  • replacement in Cargo.lock at line 1940
    [3.91399][3.122230:122381](),[3.78254][3.122230:122381](),[3.122230][3.122230:122381]()
    "checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12"
    [3.91399]
    [3.91400]
    "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd"
  • replacement in Cargo.lock at line 1942
    [3.91549][2.63886:64197]()
    "checksum block-buffer 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "49665c62e0e700857531fa5d3763e91b539ff1abeebd56808d378b495870d60d"
    "checksum block-padding 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d75255892aeb580d3c566f213a2b6fdc1c66667839f45719ee1d30ebf2aea591"
    [3.91549]
    [3.91860]
    "checksum block-buffer 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "c0940dc441f31689269e10ac70eb1002a3a1d3ad1390e030043662eb7fe4688b"
    "checksum block-padding 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6d4dc3af3ee2e12f3e5d224e5e1e3d73668abbeb69e566d361f7d5563a4fdf09"
  • replacement in Cargo.lock at line 1945
    [3.92013][3.92013:92165](),[3.92013][3.92013:92165](),[3.92013][3.92013:92165](),[3.92165][2.64198:64347]()
    "checksum byteorder 1.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a019b10a2a7cdeb292db131fc8113e57ea2a908f6e7894b0c3c671893b65dbeb"
    "checksum bytes 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "40ade3d27603c2cb345eb0912aec461a6dec7e06a4ae48589904e808335c7afa"
    [3.92013]
    [3.123295]
    "checksum byteorder 1.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a7c3dd8985a7111efc5c80b44e23ecdd8c007de8ade3b96595387e812b957cf5"
    "checksum bytes 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)" = "206fdffcfa2df7cbe15601ef46c813fce0965eb3286db6b56c583b814b51c81c"
  • replacement in Cargo.lock at line 1948
    [3.123442][2.64348:64643]()
    "checksum cc 1.0.30 (registry+https://github.com/rust-lang/crates.io-index)" = "d01c69d08ff207f231f07196e30f84c70f1c815b04f980f8b7b01ff01f05eb92"
    "checksum cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "082bb9b28e00d3c9d39cc03e64ce4cea0f1bb9b3fde493f0cbc008472d22bdf4"
    [3.123442]
    [3.123737]
    "checksum cc 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)" = "39f75544d7bbaf57560d2168f28fd649ff9c76153874db88bdbdfd839b1a7e7d"
    "checksum cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "b486ce3ccf7ffd79fdeb678eac06a9e6c09fc88d33836340becb8fffe87c5e33"
  • replacement in Cargo.lock at line 1951
    [3.123886][2.64644:64792]()
    "checksum clap 2.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b957d88f4b6a63b9d70d5f454ac8011819c6efa7727858f458ab71c756ce2d3e"
    [3.123886]
    [3.124034]
    "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
  • replacement in Cargo.lock at line 1953
    [3.124185][2.64793:65113]()
    "checksum core-foundation 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "286e0b41c3a20da26536c6000a280585d519fd07b3956b43aed8a79e9edce980"
    "checksum core-foundation-sys 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "716c271e8613ace48344f723b60b900a93150271e5be206212d052bbc0883efa"
    [3.124185]
    [3.68012]
    "checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
    "checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
  • edit in Cargo.lock at line 1962
    [3.93695]
    [3.68330]
    "checksum either 1.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "5527cfe0d098f36e3f8839852688e63c8fff1c90b2b405aef730615f9a7bcf7b"
  • replacement in Cargo.lock at line 1964
    [3.68485][2.65114:65267]()
    "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
    [3.68485]
    [3.125902]
    "checksum env_logger 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b61fa891024a945da30a9581546e8cfaf5602c7b3f4c137a2805cf388f92075a"
  • replacement in Cargo.lock at line 1976
    [3.127601][2.65268:65419]()
    "checksum futures 0.1.25 (registry+https://github.com/rust-lang/crates.io-index)" = "49e7653e374fe0d0c12de4250f0bdb60680b8c80eed558c5c7538eec9c89e21b"
    [3.127601]
    [3.127752]
    "checksum futures 0.1.27 (registry+https://github.com/rust-lang/crates.io-index)" = "a2037ec1c6c1c4f79557762eab1f7eae1f64f6cb418ace90fae88f0942b60139"
  • replacement in Cargo.lock at line 1979
    [3.94778][2.65420:65566]()
    "checksum h2 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "ddb2b25a33e231484694267af28fec74ac63b5ccf51ee2065a5e313b834d836e"
    [3.94778]
    [3.94924]
    "checksum h2 0.1.23 (registry+https://github.com/rust-lang/crates.io-index)" = "1e42e3daed5a7e17b12a0c23b5b2fbff23a925a570938ebee4baca1a9a1a2240"
  • replacement in Cargo.lock at line 1982
    [3.128511][2.65567:65715]()
    "checksum http 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fe67e3678f2827030e89cc4b9e7ecd16d52f132c0b940ab5005f88e821500f6a"
    [3.128511]
    [3.128659]
    "checksum http 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)" = "eed324f0f0daf6ec10c474f150505af2c143f251722bf9dbd1261bd1f2ee2c1a"
    "checksum http-body 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6741c859c1b2463a423a1dbce98d418e6c3c3fc720fb0d45528657320920292d"
  • replacement in Cargo.lock at line 1986
    [3.95373][2.65716:65866]()
    "checksum hyper 0.12.25 (registry+https://github.com/rust-lang/crates.io-index)" = "7d5b6658b016965ae301fa995306db965c93677880ea70765a84235a96eae896"
    [3.95373]
    [3.129112]
    "checksum hyper 0.12.30 (registry+https://github.com/rust-lang/crates.io-index)" = "40e7692b2009a70b1e9b362284add4d8b75880fefddb4acaa5e67194e843f219"
  • replacement in Cargo.lock at line 1991
    [3.95675][3.129709:129856](),[3.82381][3.129709:129856](),[3.129709][3.129709:129856]()
    "checksum itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1306f3464951f30e30d12373d31c79fbd52d236e5e896fd92f96ec7babbbe60b"
    [3.95675]
    [3.95676]
    "checksum itoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "501266b7edd0174f8530248f87f99c88fbe60ca4ef3dd486835b8d8d53136f7f"
  • replacement in Cargo.lock at line 1996
    [3.91759][3.95977:96128](),[3.69392][3.95977:96128](),[3.95977][3.95977:96128](),[3.96128][2.65867:66173]()
    "checksum lazycell 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b294d6fa9ee409a054354afc4352b0b9ef7ca222c69b8812cbea9e7d2bf3783f"
    "checksum libc 0.2.49 (registry+https://github.com/rust-lang/crates.io-index)" = "413f3dfc802c5dc91dc570b05125b6cda9855edfaa9825c9849807876376e70e"
    "checksum linked-hash-map 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7860ec297f7008ff7a1e3382d7f7e1dcd69efc94751a2284bafc3d013c2aa939"
    [3.69392]
    [3.96434]
    "checksum libc 0.2.58 (registry+https://github.com/rust-lang/crates.io-index)" = "6281b86796ba5e4366000be6e9e18bf35580adf9e63fbe2294aadb587613a319"
    "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
  • replacement in Cargo.lock at line 2000
    [3.96731][2.66174:66326]()
    "checksum lru-cache 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4d06ff7ff06f729ce5f4e227876cb88d10bc59cd4ae1e09fbb2bde15c850dc21"
    [3.96731]
    [3.131366]
    "checksum lru-cache 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
  • replacement in Cargo.lock at line 2007
    [3.97340][3.132268:132415](),[3.84191][3.132268:132415](),[3.132268][3.132268:132415]()
    "checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432"
    [3.97340]
    [3.132415]
    "checksum mio 0.6.19 (registry+https://github.com/rust-lang/crates.io-index)" = "83f51996a3ed004ef184e16818edc51fadffe8e7ca68be67f9dee67d84d0ff23"
  • replacement in Cargo.lock at line 2010
    [3.132712][2.66327:66480]()
    "checksum native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ff8e08de0070bbf4c31f452ea2a70db092f36f6f2e4d897adf5674477d488fb2"
    [3.132712]
    [3.132865]
    "checksum native-tls 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4b2df1a4c22fd44a62147fd8f13dd0f95c9d8ca7b2610299b2a2f9cf8964274e"
  • replacement in Cargo.lock at line 2014
    [3.97655][3.133327:133635](),[3.84506][3.133327:133635](),[3.133327][3.133327:133635](),[3.133635][3.70168:70320]()
    "checksum num-integer 0.1.39 (registry+https://github.com/rust-lang/crates.io-index)" = "e83d528d2677f0518c570baf2b7abdcf0cd2d248860b68507bdcb3e91d4c0cea"
    "checksum num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "0b3a5d7cc97d6d30d8b9bc8fa19bf45349ffe46241e8816f50f62f6d6aaabee1"
    "checksum num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1a23f0ed30a54abaa0c7e83b1d2d87ada7c3c23078d1d87815af3e3b6385fbba"
    [3.97655]
    [3.97808]
    "checksum num-integer 0.1.41 (registry+https://github.com/rust-lang/crates.io-index)" = "b85e541ef8255f6cf42bbfe4ef361305c6c135d10919ecc26126c4e5ae94bc09"
    "checksum num-traits 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "6ba9a427cfca2be13aa6f6403b0b7e7368fe982bfa16fccc450ce74c46cd9b32"
    "checksum num_cpus 1.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "bcef43580c035376c0705c42792c294b66974abbfd2789b511784023f71f3273"
    "checksum numtoa 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
  • replacement in Cargo.lock at line 2019
    [3.97963][2.66481:66633]()
    "checksum openssl 0.10.19 (registry+https://github.com/rust-lang/crates.io-index)" = "84321fb9004c3bce5611188a644d6171f895fa2889d155927d528782edb21c5d"
    [3.97963]
    [3.134094]
    "checksum openssl 0.10.23 (registry+https://github.com/rust-lang/crates.io-index)" = "97c140cbb82f3b3468193dd14c1b88def39f341f68257f8a7fe8ed9ed3f628a5"
  • replacement in Cargo.lock at line 2021
    [3.134250][2.66634:66789]()
    "checksum openssl-sys 0.9.42 (registry+https://github.com/rust-lang/crates.io-index)" = "cb534d752bf98cf363b473950659ac2546517f9c6be9723771614ab3f03bbc9e"
    [3.134250]
    [3.98271]
    "checksum openssl-sys 0.9.47 (registry+https://github.com/rust-lang/crates.io-index)" = "75bdd6dbbb4958d38e47a1d2348847ad1eb4dc205dc5d37473ae504391865acc"
  • replacement in Cargo.lock at line 2033
    [3.136105][2.66790:66945]()
    "checksum proc-macro2 0.4.27 (registry+https://github.com/rust-lang/crates.io-index)" = "4d317f9caece796be1980837fd5cb3dfec5613ebdb04ad0956deea83ce168915"
    [3.136105]
    [3.136260]
    "checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
  • replacement in Cargo.lock at line 2037
    [3.136716][2.66946:67095]()
    "checksum quote 0.6.11 (registry+https://github.com/rust-lang/crates.io-index)" = "cdd8e04bd9c52e0342b406469d494fcb033be4bdbe5c606016defbb1681411e1"
    [3.136716]
    [3.99960]
    "checksum quote 0.6.12 (registry+https://github.com/rust-lang/crates.io-index)" = "faf4799c5d274f3868a4aae320a0a182cbd2baee377b378f080e16a23e9d80db"
  • replacement in Cargo.lock at line 2045
    [3.101015][3.101015:101169](),[3.101015][3.101015:101169](),[3.101015][3.101015:101169](),[3.101015][3.101015:101169](),[3.101169][2.67096:67246]()
    "checksum rand_jitter 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b9ea758282efe12823e0d952ddb269d2e1897227e464919a554f2a03ef1b832"
    "checksum rand_os 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b7c690732391ae0abafced5015ffb53656abfaec61b342290e5eb56b286a679d"
    [3.101015]
    [3.71084]
    "checksum rand_jitter 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "1166d5c91dc97b88d1decc3285bb0a99ed84b05cfd0bc2341bdf2d43fc41e39b"
    "checksum rand_os 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "7b75f676a1e053fc562eafbb47838d67c84801e38fc1ba459e8f180deabd5071"
  • replacement in Cargo.lock at line 2050
    [3.101775][2.67247:67404]()
    "checksum redox_syscall 0.1.51 (registry+https://github.com/rust-lang/crates.io-index)" = "423e376fffca3dfa06c9e9790a9ccd282fafb3cc6e6397d01dbf64f9bacc6b85"
    [3.101775]
    [3.138837]
    "checksum redox_syscall 0.1.54 (registry+https://github.com/rust-lang/crates.io-index)" = "12229c14a0f65c4f1cb046a3b52047cdd9da1f4b30f8a39c5063c8bae515e252"
  • replacement in Cargo.lock at line 2052
    [3.138993][2.67405:67708](),[3.102236][3.139296:139453](),[2.67708][3.139296:139453](),[3.87564][3.139296:139453](),[3.94063][3.139296:139453](),[3.71697][3.139296:139453](),[3.139296][3.139296:139453]()
    "checksum regex 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "53ee8cfdddb2e0291adfb9f13d31d3bbe0a03c9a402c01b1e24188d86c35b24f"
    "checksum regex-syntax 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "8c2f35eedad5295fdf00a63d7d4b238135723f92b434ec06774dad15c7ab0861"
    "checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
    [3.138993]
    [3.102237]
    "checksum regex 1.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "0b2f0808e7d7e4fb1cb07feb6ff2f4bc827938f24f8c2e6a3beb7370af544bdd"
    "checksum regex-syntax 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "9d76410686f9e3a17f06128962e0ecc5755870bb890c34820c7af7f1db2e1d48"
    "checksum remove_dir_all 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4a83fa3702a688b9359eccba92d153ac33fd2e8462f9e0e3fdf155239ea7792e"
  • replacement in Cargo.lock at line 2056
    [3.102391][2.67709:67867]()
    "checksum rustc-demangle 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)" = "adacaae16d02b6ec37fdc7acfcddf365978de76d1983d3ee22afc260e1ca9619"
    [3.102391]
    [3.139765]
    "checksum rustc-demangle 0.1.15 (registry+https://github.com/rust-lang/crates.io-index)" = "a7f4dccf6f4891ebcc0c39f9b6eb1a83b9bf5d747cb439ec6fba4f3b977038af"
  • replacement in Cargo.lock at line 2058
    [3.139921][3.102550:102696]()
    "checksum ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "eb9e9b8cde282a9fe6a42dd4681319bfb63f121b8a8ee9439c6f4107e58a46f7"
    [3.139921]
    [3.102696]
    "checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f"
  • replacement in Cargo.lock at line 2062
    [3.140519][2.67868:68194]()
    "checksum security-framework 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bfab8dda0e7a327c696d893df9ffa19cadc4bd195797997f5223cf5831beaf05"
    "checksum security-framework-sys 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3d6696852716b589dff9e886ff83778bb635150168e83afa8ac6b8a78cb82abc"
    [3.140519]
    [3.140845]
    "checksum security-framework 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eee63d0f4a9ec776eeb30e220f0bc1e092c3ad744b2a379e3993070364d3adc2"
    "checksum security-framework-sys 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "9636f8989cbf61385ae4824b98c1aaa54c994d7d8b41f11c601ed799f0549a56"
  • replacement in Cargo.lock at line 2066
    [3.141150][2.68195:68500]()
    "checksum serde 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "92514fb95f900c9b5126e32d020f5c6d40564c27a5ea6d1d7d9f157a96623560"
    "checksum serde_derive 1.0.89 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6eabf4b5914e88e24eea240bb7c9f9a2cbc1bbbe8d961d381975ec3c6b806c"
    [3.141150]
    [3.72315]
    "checksum serde 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "32746bf0f26eab52f06af0d0aa1984f641341d06d8d673c693871da2d188c9be"
    "checksum serde_derive 1.0.92 (registry+https://github.com/rust-lang/crates.io-index)" = "46a3223d0c9ba936b61c0d2e3e559e3217dbfb8d65d06d26e8b3c25de38bae3e"
  • replacement in Cargo.lock at line 2071
    [3.104077][2.68501:68802]()
    "checksum sha3 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "34a5e54083ce2b934bf059fdf38e7330a154177e029ab6c4e18638f2f624053a"
    "checksum signal-hook 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "97a47ae722318beceb0294e6f3d601205a1e6abaa4437d9d33e3a212233e3021"
    [3.104077]
    [3.142205]
    "checksum sha3 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dd26bc0e7a2e3a7c959bc494caf58b72ee0c71d67704e9520f736ca7e4853ecf"
    "checksum signal-hook 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "72ab58f1fda436857e6337dcb6a5aaa34f16c5ddc87b3a8b6ef7a212f90b9c5a"
    "checksum signal-hook-registry 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cded4ffa32146722ec54ab1f16320568465aa922aa9ab4708129599740da85d7"
  • replacement in Cargo.lock at line 2076
    [3.104526][3.72625:72776](),[3.104677][3.142655:142805](),[3.90154][3.142655:142805](),[3.95142][3.142655:142805](),[3.72776][3.142655:142805](),[3.142655][3.142655:142805]()
    "checksum smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c4488ae950c49d403731982257768f48fada354a5203fe81f9bb6f43ca9002be"
    "checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
    [3.104526]
    [3.142805]
    "checksum smallvec 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "ab606a9c5e214920bb66c458cd7be8ef094f813f20fe77a54cc7dbfff220d4b7"
    "checksum socket2 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "4e626972d3593207547f14bf5fc9efa4d0e7283deb73fef1dff313dae9ab8878"
  • replacement in Cargo.lock at line 2079
    [3.142966][3.104678:104827]()
    "checksum string 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "b639411d0b9c738748b5397d5ceba08e648f4f1992231aa859af1a017f31f60b"
    [3.142966]
    [3.143115]
    "checksum string 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d0bbfb8937e38e34c3444ff00afb28b0811d9554f15c5ad64d12b0308d1d1995"
  • replacement in Cargo.lock at line 2083
    [3.143595][2.68803:68952]()
    "checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550"
    [3.143595]
    [3.104977]
    "checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
  • replacement in Cargo.lock at line 2086
    [3.144041][2.68953:69101]()
    "checksum syn 0.15.27 (registry+https://github.com/rust-lang/crates.io-index)" = "525bd55255f03c816e5d7f615587bd13030c7103354fadb104993dcee6a788ec"
    [3.144041]
    [3.144189]
    "checksum syn 0.15.36 (registry+https://github.com/rust-lang/crates.io-index)" = "8b4f551a91e2e3848aeef8751d0d4eec9489b6474c720fd4c55958d8d31a430c"
  • replacement in Cargo.lock at line 2088
    [3.144338][3.105276:105432](),[3.105432][3.73076:73227]()
    "checksum synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)" = "73687139bf99285483c96ac0add482c3776528beac1d97d444f6e91f203a2015"
    "checksum tempfile 3.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b86c784c88d98c801132806dadd3819ed29d8600836c4088e855cdf3e178ed8a"
    [3.144338]
    [3.105583]
    "checksum synstructure 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "02353edf96d6e4dc81aea2d8490a7e9db177bf8acb0e951c24940bf866cb313f"
    "checksum tempfile 3.0.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7dc4738f2e68ed2855de5ac9cdbe05c9216773ecde4739b2f095002ab03a13ef"
  • replacement in Cargo.lock at line 2091
    [3.105733][3.144795:144947](),[3.91061][3.144795:144947](),[3.144795][3.144795:144947](),[3.144947][2.69102:69404]()
    "checksum termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "4096add70612622289f2fdcdbd5086dc81c1e2675e6ae58d6c4f62a16c6d7f2f"
    "checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096"
    "checksum textwrap 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "307686869c93e71f94da64286f9a9524c0f308a9e1c87a583de8e9c9039ad3f6"
    [3.105733]
    [3.145249]
    "checksum termcolor 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "96d6098003bde162e4277c70665bd87c326f5a0c3f3fbfb285787fa482d54e6e"
    "checksum termion 1.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6a8fb22f7cde82c8220e5aeacb3258ed7ce996142c77cba193f203515e26c330"
    "checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060"
  • replacement in Cargo.lock at line 2096
    [3.106035][2.69405:69554]()
    "checksum tokio 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "fcaabb3cec70485d0df6e9454fe514393ad1c4070dee8915f11041e95630b230"
    [3.106035]
    [3.145701]
    "checksum tokio 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)" = "ec2ffcf4bcfc641413fa0f1427bf8f91dfc78f56a6559cbf50e04837ae442a87"
    "checksum tokio-buf 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "8fb220f46c53859a4b7ec083e41dec9778ff0b1851c0942b211edb89e0ccdc46"
  • replacement in Cargo.lock at line 2100
    [3.146011][2.69555:69875]()
    "checksum tokio-current-thread 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "c756b04680eea21902a46fca4e9f410a2332c04995af590e07ff262e2193a9a3"
    "checksum tokio-executor 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "30c6dbf2d1ad1de300b393910e8a3aa272b724a400b6531da03eed99e329fbf0"
    [3.146011]
    [3.73851]
    "checksum tokio-current-thread 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "d16217cad7f1b840c5a97dfb3c43b0c871fef423a6e8d2118c604e843662a443"
    "checksum tokio-executor 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "83ea44c6c0773cc034771693711c35c677b4b5a4b21b9e7071704c54de7d555e"
  • replacement in Cargo.lock at line 2106
    [3.107119][2.69876:70029]()
    "checksum tokio-sync 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "1bf2b9dac2a0509b5cfd1df5aa25eafacb616a42a491a13604d6bbeab4486363"
    [3.107119]
    [3.107272]
    "checksum tokio-sync 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "2162248ff317e2bc713b261f242b69dbb838b85248ed20bb21df56d60ea4cae7"
  • replacement in Cargo.lock at line 2108
    [3.107424][2.70030:70190](),[2.70190][3.107584:107739](),[3.96991][3.107584:107739](),[3.52677][3.107584:107739](),[3.74625][3.107584:107739](),[3.107584][3.107584:107739]()
    "checksum tokio-threadpool 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)" = "742e511f6ce2298aeb86fc9ea0d8df81c2388c6ebae3dc8a7316e8c9df0df801"
    "checksum tokio-timer 0.2.10 (registry+https://github.com/rust-lang/crates.io-index)" = "2910970404ba6fa78c5539126a9ae2045d62e3713041e447f695f41405a120c6"
    [3.107424]
    [3.107739]
    "checksum tokio-threadpool 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "72558af20be886ea124595ea0f806dd5703b8958e4705429dd58b3d8231f72f2"
    "checksum tokio-timer 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "f2106812d500ed25a4f38235b9cae8f78a09edf43203e16e59c3b769a342a60e"
  • edit in Cargo.lock at line 2111
    [3.107891]
    [3.108050]
    "checksum tokio-trace-core 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9c8a256d6956f7cb5e2bdfe8b1e8022f1a09206c6c2b1ba00f3b746b260c613"
  • replacement in Cargo.lock at line 2115
    [3.108507][2.70191:70339]()
    "checksum toml 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "758664fc71a3a69038656bee8b6be6477d2a6c315a6b81f7081f591bffa4111f"
    [3.108507]
    [3.108654]
    "checksum toml 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b8c96d7873fa7ef8bdeb3a9cda3ac48389b4154f32b9803b4bc26220b677b039"
  • replacement in Cargo.lock at line 2129
    [3.109738][3.109738:109892](),[3.109738][3.109738:109892]()
    "checksum utf8-ranges 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "796f7e48bef87609f7ade7e06495a87d5cd06c7866e6a5cbfceffc558a243737"
    [3.109738]
    [3.150635]
    "checksum utf8-ranges 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9d50aa7650df78abf942826607c62468ce18d9019673d4a2ebe1865dbb96ffde"
  • replacement in Cargo.lock at line 2135
    [3.151382][2.70340:70489]()
    "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
    [3.151382]
    [3.151531]
    "checksum winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)" = "f10e386af2b13e47c89e7236a7a14a086791a2b88ebad6df9bf42040195cf770"
  • edit in Cargo.lock at line 2146
    [3.110506]
    "checksum xmpp-parsers 0.13.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5094cec449beca92f82ae4d7fe13cda058005849766d71b86c23e6217f61a357"