<commit_before>use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std;
use std::collections::HashMap;
use std::io;
use time::{Duration, Time};

pub trait RosMsg: std::marker::Sized {
    fn encode<W: io::Write>(&self, w: W) -> io::Result<()>;
    fn decode<R: io::Read>(r: R) -> io::Result<Self>;

    #[inline]
    fn encode_vec(&self) -> io::Result<Vec<u8>> {
        let mut writer = Vec::with_capacity(128);
        self.encode(&mut writer)?;
        Ok(writer)
    }

    #[inline]
    fn decode_slice(bytes: &[u8]) -> io::Result<Self> {
        Self::decode(&mut io::Cursor::new(bytes))
    }
}

impl RosMsg for u8 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_u8(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_u8()
    }
}

impl RosMsg for i8 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_i8(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_i8()
    }
}

impl RosMsg for u16 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_u16::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_u16::<LittleEndian>()
    }
}

impl RosMsg for i16 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_i16::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_i16::<LittleEndian>()
    }
}

impl RosMsg for u32 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_u32::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_u32::<LittleEndian>()
    }
}

impl RosMsg for i32 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_i32::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_i32::<LittleEndian>()
    }
}

impl RosMsg for u64 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_u64::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_u64::<LittleEndian>()
    }
}

impl RosMsg for i64 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_i64::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_i64::<LittleEndian>()
    }
}

impl RosMsg for f32 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_f32::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_f32::<LittleEndian>()
    }
}

impl RosMsg for f64 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_f64::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_f64::<LittleEndian>()
    }
}

#[inline]
pub fn encode_fixed_slice<W: io::Write, T: RosMsg>(data: &[T], mut w: W) -> io::Result<()> {
    data.into_iter().try_for_each(|v| v.encode(w.by_ref()))
}

#[inline]
pub fn decode_fixed_vec<R: io::Read, T: RosMsg>(len: u32, mut r: R) -> io::Result<Vec<T>> {
    (0..len).map(move |_| T::decode(r.by_ref())).collect()
}

#[inline]
pub fn encode_variable_slice<W: io::Write, T: RosMsg>(data: &[T], mut w: W) -> io::Result<()> {
    (data.len() as u32).encode(w.by_ref())?;
    encode_fixed_slice(data, w)
}

#[inline]
pub fn decode_variable_vec<R: io::Read, T: RosMsg>(mut r: R) -> io::Result<Vec<T>> {
    decode_fixed_vec(u32::decode(r.by_ref())?, r)
}

#[inline]
pub fn encode_str<W: io::Write>(value: &str, w: W) -> io::Result<()> {
    encode_variable_slice(value.as_bytes(), w)
}

impl RosMsg for String {
    #[inline]
    fn encode<W: io::Write>(&self, w: W) -> io::Result<()> {
        encode_str(self, w)
    }

    #[inline]
    fn decode<R: io::Read>(r: R) -> io::Result<Self> {
        decode_variable_vec::<R, u8>(r).and_then(|v| {
            String::from_utf8(v).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
        })
    }
}

impl RosMsg for HashMap<String, String> {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        let rows = self.iter()
            .map(|(key, value)| format!("{}={}", key, value))
            .collect::<Vec<String>>();
        let data_size: usize = rows.iter().map(|item| item.len() + 4).sum();
        write_data_size(data_size as u32, w.by_ref())?;
        rows.into_iter()
            .try_for_each(|item| item.encode(w.by_ref()))
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        let data_size = read_data_size(r.by_ref())? as u64;
        let mut limited_r = r.take(data_size);
        let mut output = HashMap::<String, String>::default();
        loop {
            let item = match String::decode(&mut limited_r) {
                Ok(val) => val,
                Err(_err) => break, // TODO: ensure we break only on EOF
            };
            match item.splitn(2, "=").collect::<Vec<&str>>().as_slice() {
                &[key, value] => output.insert(key.into(), value.into()),
                _ => {
                    return Err(io::Error::new(
                        io::ErrorKind::InvalidData,
                        "Map rows need to have a format of key=value",
                    ))
                }
            };
        }
        Ok(output)
    }
}

impl RosMsg for Time {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        self.sec.encode(w.by_ref())?;
        self.nsec.encode(w)?;
        Ok(())
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        Ok(Self {
            sec: RosMsg::decode(r.by_ref())?,
            nsec: RosMsg::decode(r)?,
        })
    }
}

impl RosMsg for Duration {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        self.sec.encode(w.by_ref())?;
        self.nsec.encode(w)?;
        Ok(())
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        Ok(Self {
            sec: RosMsg::decode(r.by_ref())?,
            nsec: RosMsg::decode(r)?,
        })
    }
}

#[inline]
fn read_data_size<R: io::Read>(r: R) -> io::Result<u32> {
    u32::decode(r)
}

#[inline]
fn write_data_size<W: io::Write>(value: u32, w: W) -> io::Result<()> {
    value.encode(w)
}
<commit_msg>Add the missing message length bytes to the beginning of tcpros message<commit_after>use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std;
use std::collections::HashMap;
use std::io;
use time::{Duration, Time};

pub trait RosMsg: std::marker::Sized {
    fn encode<W: io::Write>(&self, w: W) -> io::Result<()>;
    fn decode<R: io::Read>(r: R) -> io::Result<Self>;

    #[inline]
    fn encode_vec(&self) -> io::Result<Vec<u8>> {
        let mut writer = io::Cursor::new(Vec::with_capacity(128));
        // skip the first 4 bytes that will contain the message length
        writer.set_position(4);

        self.encode(&mut writer)?;

        // write the message length to the start of the header
        let message_length = (writer.position() - 4) as u32;
        writer.set_position(0);
        message_length.encode(&mut writer)?;
        Ok(writer.into_inner())
    }

    #[inline]
    fn decode_slice(bytes: &[u8]) -> io::Result<Self> {
        Self::decode(&mut io::Cursor::new(bytes))
    }
}

impl RosMsg for u8 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_u8(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_u8()
    }
}

impl RosMsg for i8 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_i8(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_i8()
    }
}

impl RosMsg for u16 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_u16::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_u16::<LittleEndian>()
    }
}

impl RosMsg for i16 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_i16::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_i16::<LittleEndian>()
    }
}

impl RosMsg for u32 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_u32::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_u32::<LittleEndian>()
    }
}

impl RosMsg for i32 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_i32::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_i32::<LittleEndian>()
    }
}

impl RosMsg for u64 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_u64::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_u64::<LittleEndian>()
    }
}

impl RosMsg for i64 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_i64::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_i64::<LittleEndian>()
    }
}

impl RosMsg for f32 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_f32::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_f32::<LittleEndian>()
    }
}

impl RosMsg for f64 {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        w.write_f64::<LittleEndian>(*self)
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        r.read_f64::<LittleEndian>()
    }
}

#[inline]
pub fn encode_fixed_slice<W: io::Write, T: RosMsg>(data: &[T], mut w: W) -> io::Result<()> {
    data.into_iter().try_for_each(|v| v.encode(w.by_ref()))
}

#[inline]
pub fn decode_fixed_vec<R: io::Read, T: RosMsg>(len: u32, mut r: R) -> io::Result<Vec<T>> {
    (0..len).map(move |_| T::decode(r.by_ref())).collect()
}

#[inline]
pub fn encode_variable_slice<W: io::Write, T: RosMsg>(data: &[T], mut w: W) -> io::Result<()> {
    (data.len() as u32).encode(w.by_ref())?;
    encode_fixed_slice(data, w)
}

#[inline]
pub fn decode_variable_vec<R: io::Read, T: RosMsg>(mut r: R) -> io::Result<Vec<T>> {
    decode_fixed_vec(u32::decode(r.by_ref())?, r)
}

#[inline]
pub fn encode_str<W: io::Write>(value: &str, w: W) -> io::Result<()> {
    encode_variable_slice(value.as_bytes(), w)
}

impl RosMsg for String {
    #[inline]
    fn encode<W: io::Write>(&self, w: W) -> io::Result<()> {
        encode_str(self, w)
    }

    #[inline]
    fn decode<R: io::Read>(r: R) -> io::Result<Self> {
        decode_variable_vec::<R, u8>(r).and_then(|v| {
            String::from_utf8(v).map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))
        })
    }
}

impl RosMsg for HashMap<String, String> {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        let rows = self.iter()
            .map(|(key, value)| format!("{}={}", key, value))
            .collect::<Vec<String>>();
        let data_size: usize = rows.iter().map(|item| item.len() + 4).sum();
        write_data_size(data_size as u32, w.by_ref())?;
        rows.into_iter()
            .try_for_each(|item| item.encode(w.by_ref()))
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        let data_size = read_data_size(r.by_ref())? as u64;
        let mut limited_r = r.take(data_size);
        let mut output = HashMap::<String, String>::default();
        loop {
            let item = match String::decode(&mut limited_r) {
                Ok(val) => val,
                Err(_err) => break, // TODO: ensure we break only on EOF
            };
            match item.splitn(2, "=").collect::<Vec<&str>>().as_slice() {
                &[key, value] => output.insert(key.into(), value.into()),
                _ => {
                    return Err(io::Error::new(
                        io::ErrorKind::InvalidData,
                        "Map rows need to have a format of key=value",
                    ))
                }
            };
        }
        Ok(output)
    }
}

impl RosMsg for Time {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        self.sec.encode(w.by_ref())?;
        self.nsec.encode(w)?;
        Ok(())
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        Ok(Self {
            sec: RosMsg::decode(r.by_ref())?,
            nsec: RosMsg::decode(r)?,
        })
    }
}

impl RosMsg for Duration {
    #[inline]
    fn encode<W: io::Write>(&self, mut w: W) -> io::Result<()> {
        self.sec.encode(w.by_ref())?;
        self.nsec.encode(w)?;
        Ok(())
    }

    #[inline]
    fn decode<R: io::Read>(mut r: R) -> io::Result<Self> {
        Ok(Self {
            sec: RosMsg::decode(r.by_ref())?,
            nsec: RosMsg::decode(r)?,
        })
    }
}

#[inline]
fn read_data_size<R: io::Read>(r: R) -> io::Result<u32> {
    u32::decode(r)
}

#[inline]
fn write_data_size<W: io::Write>(value: u32, w: W) -> io::Result<()> {
    value.encode(w)
}
<|endoftext|>


<commit_before>use crate::ty::context::TyCtxt;
use crate::ty::{DefId, DefIdTree};
use rustc_hir::CRATE_HIR_ID;
use smallvec::SmallVec;
use std::mem;

/// Represents a forest of `DefId`s closed under the ancestor relation. That is,
/// if a `DefId` representing a module is contained in the forest then all
/// `DefId`s defined in that module or submodules are also implicitly contained
/// in the forest.
///
/// This is used to represent a set of modules in which a type is visibly
/// uninhabited.
#[derive(Clone)]
pub struct DefIdForest {
    /// The minimal set of `DefId`s required to represent the whole set.
    /// If A and B are DefIds in the `DefIdForest`, and A is a descendant
    /// of B, then only B will be in `root_ids`.
    /// We use a `SmallVec` here because (for its use for caching inhabitedness)
    /// its rare that this will contain even two IDs.
    root_ids: SmallVec<[DefId; 1]>,
}

impl<'tcx> DefIdForest {
    /// Creates an empty forest.
    pub fn empty() -> DefIdForest {
        DefIdForest { root_ids: SmallVec::new() }
    }

    /// Creates a forest consisting of a single tree representing the entire
    /// crate.
    #[inline]
    pub fn full(tcx: TyCtxt<'tcx>) -> DefIdForest {
        let crate_id = tcx.hir().local_def_id(CRATE_HIR_ID);
        DefIdForest::from_id(crate_id.to_def_id())
    }

    /// Creates a forest containing a `DefId` and all its descendants.
    pub fn from_id(id: DefId) -> DefIdForest {
        let mut root_ids = SmallVec::new();
        root_ids.push(id);
        DefIdForest { root_ids }
    }

    /// Tests whether the forest is empty.
    pub fn is_empty(&self) -> bool {
        self.root_ids.is_empty()
    }

    /// Tests whether the forest contains a given DefId.
    pub fn contains(&self, tcx: TyCtxt<'tcx>, id: DefId) -> bool {
        self.root_ids.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
    }

    /// Calculate the intersection of a collection of forests.
    pub fn intersection<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest
    where
        I: IntoIterator<Item = DefIdForest>,
    {
        let mut iter = iter.into_iter();
        let mut ret = if let Some(first) = iter.next() {
            first
        } else {
            return DefIdForest::full(tcx);
        };

        let mut next_ret = SmallVec::new();
        let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
        for next_forest in iter {
            // No need to continue if the intersection is already empty.
            if ret.is_empty() {
                break;
            }

            for id in ret.root_ids.drain(..) {
                if next_forest.contains(tcx, id) {
                    next_ret.push(id);
                } else {
                    old_ret.push(id);
                }
            }
            ret.root_ids.extend(old_ret.drain(..));

            next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id)));

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain(..);
        }
        ret
    }

    /// Calculate the union of a collection of forests.
    pub fn union<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest
    where
        I: IntoIterator<Item = DefIdForest>,
    {
        let mut ret = DefIdForest::empty();
        let mut next_ret = SmallVec::new();
        for next_forest in iter {
            next_ret.extend(ret.root_ids.drain(..).filter(|&id| !next_forest.contains(tcx, id)));

            for id in next_forest.root_ids {
                if !next_ret.contains(&id) {
                    next_ret.push(id);
                }
            }

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain(..);
        }
        ret
    }
}
<commit_msg>Rollup merge of #80241 - pierwill:patch-12, r=lcnr<commit_after>use crate::ty::context::TyCtxt;
use crate::ty::{DefId, DefIdTree};
use rustc_hir::CRATE_HIR_ID;
use smallvec::SmallVec;
use std::mem;

/// Represents a forest of `DefId`s closed under the ancestor relation. That is,
/// if a `DefId` representing a module is contained in the forest then all
/// `DefId`s defined in that module or submodules are also implicitly contained
/// in the forest.
///
/// This is used to represent a set of modules in which a type is visibly
/// uninhabited.
#[derive(Clone)]
pub struct DefIdForest {
    /// The minimal set of `DefId`s required to represent the whole set.
    /// If A and B are DefIds in the `DefIdForest`, and A is a descendant
    /// of B, then only B will be in `root_ids`.
    /// We use a `SmallVec` here because (for its use for caching inhabitedness)
    /// it's rare that this will contain even two IDs.
    root_ids: SmallVec<[DefId; 1]>,
}

impl<'tcx> DefIdForest {
    /// Creates an empty forest.
    pub fn empty() -> DefIdForest {
        DefIdForest { root_ids: SmallVec::new() }
    }

    /// Creates a forest consisting of a single tree representing the entire
    /// crate.
    #[inline]
    pub fn full(tcx: TyCtxt<'tcx>) -> DefIdForest {
        let crate_id = tcx.hir().local_def_id(CRATE_HIR_ID);
        DefIdForest::from_id(crate_id.to_def_id())
    }

    /// Creates a forest containing a `DefId` and all its descendants.
    pub fn from_id(id: DefId) -> DefIdForest {
        let mut root_ids = SmallVec::new();
        root_ids.push(id);
        DefIdForest { root_ids }
    }

    /// Tests whether the forest is empty.
    pub fn is_empty(&self) -> bool {
        self.root_ids.is_empty()
    }

    /// Tests whether the forest contains a given DefId.
    pub fn contains(&self, tcx: TyCtxt<'tcx>, id: DefId) -> bool {
        self.root_ids.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
    }

    /// Calculate the intersection of a collection of forests.
    pub fn intersection<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest
    where
        I: IntoIterator<Item = DefIdForest>,
    {
        let mut iter = iter.into_iter();
        let mut ret = if let Some(first) = iter.next() {
            first
        } else {
            return DefIdForest::full(tcx);
        };

        let mut next_ret = SmallVec::new();
        let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
        for next_forest in iter {
            // No need to continue if the intersection is already empty.
            if ret.is_empty() {
                break;
            }

            for id in ret.root_ids.drain(..) {
                if next_forest.contains(tcx, id) {
                    next_ret.push(id);
                } else {
                    old_ret.push(id);
                }
            }
            ret.root_ids.extend(old_ret.drain(..));

            next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id)));

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain(..);
        }
        ret
    }

    /// Calculate the union of a collection of forests.
    pub fn union<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest
    where
        I: IntoIterator<Item = DefIdForest>,
    {
        let mut ret = DefIdForest::empty();
        let mut next_ret = SmallVec::new();
        for next_forest in iter {
            next_ret.extend(ret.root_ids.drain(..).filter(|&id| !next_forest.contains(tcx, id)));

            for id in next_forest.root_ids {
                if !next_ret.contains(&id) {
                    next_ret.push(id);
                }
            }

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain(..);
        }
        ret
    }
}
<|endoftext|>


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

use std::collections::HashMap;

use hcore::service::ServiceGroup;

use census::{CensusGroup, CensusMember, CensusRing, ElectionStatus};
use manager::Sys;
use manager::service::{Cfg, Pkg, ServiceBind};

#[derive(Clone, Debug, Serialize)]
pub struct Binds<'a>(HashMap<String, BindGroup<'a>>);

impl<'a> Binds<'a> {
    fn new(bindings: &[ServiceBind], census: &'a CensusRing) -> Self {
        let mut map = HashMap::default();
        for bind in bindings {
            if let Some(group) = census.census_group_for(&bind.service_group) {
                map.insert(bind.name.to_string(), BindGroup::new(group));
            }
        }
        Binds(map)
    }
}

#[derive(Clone, Debug, Serialize)]
pub struct BindGroup<'a> {
    members: Vec<SvcMember<'a>>,
}

impl<'a> BindGroup<'a> {
    fn new(group: &'a CensusGroup) -> Self {
        BindGroup { members: group.members().iter().map(|m| SvcMember(m)).collect() }
    }
}

#[derive(Clone, Debug, Serialize)]
pub struct RenderContext<'a> {
    pub sys: &'a Sys,
    pub pkg: &'a Pkg,
    pub cfg: &'a Cfg,
    pub svc: Svc<'a>,
    pub bind: Binds<'a>,
}

impl<'a> RenderContext<'a> {
    pub fn new(service_group: &ServiceGroup,
               sys: &'a Sys,
               pkg: &'a Pkg,
               cfg: &'a Cfg,
               census: &'a CensusRing,
               bindings: &[ServiceBind])
               -> RenderContext<'a> {
        let census_group = census
            .census_group_for(&service_group)
            .expect("Census Group missing from list!");
        RenderContext {
            sys: sys,
            pkg: pkg,
            cfg: cfg,
            svc: Svc::new(census_group),
            bind: Binds::new(bindings, census),
        }
    }
}

#[derive(Clone, Debug, Serialize)]
pub struct Svc<'a> {
    pub group: &'a ServiceGroup,
    pub election_is_running: bool,
    pub election_is_no_quorum: bool,
    pub election_is_finished: bool,
    pub update_election_is_running: bool,
    pub update_election_is_no_quorum: bool,
    pub update_election_is_finished: bool,
    pub me: SvcMember<'a>,
    pub first: SvcMember<'a>,
    pub members: Vec<SvcMember<'a>>,
    pub leader: Option<SvcMember<'a>>,
    pub update_leader: Option<SvcMember<'a>>,
}

impl<'a> Svc<'a> {
    fn new(census_group: &'a CensusGroup) -> Self {
        let first = match census_group.leader() {
            Some(member) => SvcMember(member),
            None => SvcMember(census_group.members()[0]),
        };
        Svc {
            group: &census_group.service_group,
            election_is_running: census_group.election_status == ElectionStatus::ElectionInProgress,
            election_is_no_quorum: census_group.election_status == ElectionStatus::ElectionNoQuorum,
            election_is_finished: census_group.election_status == ElectionStatus::ElectionFinished,
            update_election_is_running: census_group.election_status ==
                                        ElectionStatus::ElectionInProgress,
            update_election_is_no_quorum: census_group.election_status ==
                                          ElectionStatus::ElectionNoQuorum,
            update_election_is_finished: census_group.election_status ==
                                         ElectionStatus::ElectionFinished,
            me: SvcMember(census_group.me().expect("Missing 'me'")),
            members: census_group
                .members()
                .iter()
                .map(|m| SvcMember(m))
                .collect(),
            leader: census_group.leader().map(|m| SvcMember(m)),
            first: first,
            update_leader: census_group.update_leader().map(|m| SvcMember(m)),
        }
    }
}

/// A friendly representation of a `CensusMember` to the templating system.
#[derive(Clone, Debug, Serialize)]
pub struct SvcMember<'a>(&'a CensusMember);
<commit_msg>Render components of ServiceGroup in Svc struct<commit_after>// Copyright (c) 2017 Chef Software Inc. and/or applicable contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::HashMap;

use hcore::service::ServiceGroup;

use census::{CensusGroup, CensusMember, CensusRing, ElectionStatus};
use manager::Sys;
use manager::service::{Cfg, Pkg, ServiceBind};

#[derive(Clone, Debug, Serialize)]
pub struct Binds<'a>(HashMap<String, BindGroup<'a>>);

impl<'a> Binds<'a> {
    fn new(bindings: &[ServiceBind], census: &'a CensusRing) -> Self {
        let mut map = HashMap::default();
        for bind in bindings {
            if let Some(group) = census.census_group_for(&bind.service_group) {
                map.insert(bind.name.to_string(), BindGroup::new(group));
            }
        }
        Binds(map)
    }
}

#[derive(Clone, Debug, Serialize)]
pub struct BindGroup<'a> {
    members: Vec<SvcMember<'a>>,
}

impl<'a> BindGroup<'a> {
    fn new(group: &'a CensusGroup) -> Self {
        BindGroup { members: group.members().iter().map(|m| SvcMember(m)).collect() }
    }
}

#[derive(Clone, Debug, Serialize)]
pub struct RenderContext<'a> {
    pub sys: &'a Sys,
    pub pkg: &'a Pkg,
    pub cfg: &'a Cfg,
    pub svc: Svc<'a>,
    pub bind: Binds<'a>,
}

impl<'a> RenderContext<'a> {
    pub fn new(service_group: &ServiceGroup,
               sys: &'a Sys,
               pkg: &'a Pkg,
               cfg: &'a Cfg,
               census: &'a CensusRing,
               bindings: &[ServiceBind])
               -> RenderContext<'a> {
        let census_group = census
            .census_group_for(&service_group)
            .expect("Census Group missing from list!");
        RenderContext {
            sys: sys,
            pkg: pkg,
            cfg: cfg,
            svc: Svc::new(census_group),
            bind: Binds::new(bindings, census),
        }
    }
}

#[derive(Clone, Debug, Serialize)]
pub struct Svc<'a> {
    pub service: &'a str,
    pub group: &'a str,
    pub org: Option<&'a str>,
    pub election_is_running: bool,
    pub election_is_no_quorum: bool,
    pub election_is_finished: bool,
    pub update_election_is_running: bool,
    pub update_election_is_no_quorum: bool,
    pub update_election_is_finished: bool,
    pub me: SvcMember<'a>,
    pub first: SvcMember<'a>,
    pub members: Vec<SvcMember<'a>>,
    pub leader: Option<SvcMember<'a>>,
    pub update_leader: Option<SvcMember<'a>>,
}

impl<'a> Svc<'a> {
    fn new(census_group: &'a CensusGroup) -> Self {
        let first = match census_group.leader() {
            Some(member) => SvcMember(member),
            None => SvcMember(census_group.members()[0]),
        };
        let sg = &census_group.service_group;
        Svc {
            service: sg.service(),
            group: sg.group(),
            org: sg.org(),
            election_is_running: census_group.election_status == ElectionStatus::ElectionInProgress,
            election_is_no_quorum: census_group.election_status == ElectionStatus::ElectionNoQuorum,
            election_is_finished: census_group.election_status == ElectionStatus::ElectionFinished,
            update_election_is_running: census_group.election_status ==
                                        ElectionStatus::ElectionInProgress,
            update_election_is_no_quorum: census_group.election_status ==
                                          ElectionStatus::ElectionNoQuorum,
            update_election_is_finished: census_group.election_status ==
                                         ElectionStatus::ElectionFinished,
            me: SvcMember(census_group.me().expect("Missing 'me'")),
            members: census_group
                .members()
                .iter()
                .map(|m| SvcMember(m))
                .collect(),
            leader: census_group.leader().map(|m| SvcMember(m)),
            first: first,
            update_leader: census_group.update_leader().map(|m| SvcMember(m)),
        }
    }
}

/// A friendly representation of a `CensusMember` to the templating system.
#[derive(Clone, Debug, Serialize)]
pub struct SvcMember<'a>(&'a CensusMember);
<|endoftext|>


<commit_before>use engine::EngineData;
use image_convert::{image_to_surface, frame_to_surface};
use scene::SceneName;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::{Rect, Point};
use sdl2::render::{WindowCanvas, Texture, TextureCreator};
use sdl2::surface::Surface;
use sdl2::video::WindowContext;
use sdl2_engine_helpers::scene::{Scene, BoxedScene, SceneChangeEvent};
use std::fs::File;
use std::io::Result;
use std::path::Path;

use uorustlibs::anim::{AnimReader, AnimGroup,};

pub struct AnimScene<'a> {
    reader: Result<AnimReader<File>>,
    index: u32,
    texture_creator: &'a TextureCreator<WindowContext>,
    textures: Vec<Texture<'a>>,
    exiting: bool,
    current_frame: usize,
}

impl<'a> AnimScene<'a> {
    pub fn new<'b>(engine_data: &mut EngineData<'b>, texture_creator: &'a TextureCreator<WindowContext>) -> BoxedScene<'a, Event, SceneName, EngineData<'b>> {
        let reader = AnimReader::new(&Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"));  //FIXME: Multiple anim muls!
        let mut scene = Box::new(AnimScene {
            reader: reader,
            index: 110,
            textures: vec![],
            exiting: false,
            texture_creator,
            current_frame: 0,
        });
        scene.create_slice(engine_data);

        scene
    }

    fn create_slice(&mut self, engine_data: &mut EngineData) {
        let offset = 100;
        let anim = match self.reader {
            Ok(ref mut reader) => {
                reader.read(self.index).or_else(|_| Err("Invalid anim"))
            },
            _ => Err("No reader")
        };
        match anim {
            Ok(anim) => {
                self.textures = anim.to_frames().enumerate().map(|(idx, frame)| {
                    let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                    dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();
                    let surface = frame_to_surface(&frame);
                    surface.blit(None, &mut dest, Some(Rect::new(0, 0, surface.width(), surface.height()))).expect("Could not blit surface");

                    engine_data.text_renderer.draw_text(&mut dest, &Point::new(9, offset as i32 + surface.height() as i32 + 16), &format!("{}", self.index));
                    engine_data.text_renderer.draw_text(&mut dest, &Point::new(9, offset as i32 + surface.height() as i32 + 32), &format!("{} / {}", idx, anim.frame_count));
                    self.texture_creator.create_texture_from_surface(&dest).unwrap()
                }).collect::<_>();
            },
            Err(e) => {
                let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();
                engine_data.text_renderer.draw_text(&mut dest, &Point::new(0, 0), e);
                self.textures = vec![self.texture_creator.create_texture_from_surface(&dest).unwrap()];
            }
        }
        self.current_frame = 0;
    }
}

impl<'a, 'b> Scene<Event, SceneName, EngineData<'b>> for AnimScene<'a> {
    fn render(&self, renderer: &mut WindowCanvas, _engine_data: &EngineData, _tick: u64) {
        renderer.clear();
        if self.textures.len() > 0 {
            renderer.copy(&self.textures[self.current_frame], None, None).unwrap();
        }
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, engine_data: &mut EngineData, _tick: u64) {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                self.exiting = true;
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.index > 0 {
                    self.index -= 1;
                    self.create_slice(engine_data);
                }
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.index += 1;
                self.create_slice(engine_data);
            },
            Event::KeyDown { keycode: Some(Keycode::Comma), .. } => {
                if self.index >= 10 {
                    self.index -= 10;
                    self.create_slice(engine_data);
                }
            },
            Event::KeyDown { keycode: Some(Keycode::Period), .. } => {
                self.index += 10;
                self.create_slice(engine_data);
            },
             _ => ()
        }
    }

    fn think(&mut self, _engine_data: &mut EngineData, tick: u64) -> Option<SceneChangeEvent<SceneName>> {
        if self.exiting {
            return Some(SceneChangeEvent::PopScene);
        }

        if tick % 2 == 0 {
            self.current_frame += 1;
            if self.current_frame >= self.textures.len() {
                self.current_frame = 0;
            }
        }

        None
    }
}
<commit_msg>Switch between anim files<commit_after>use engine::EngineData;
use image_convert::frame_to_surface;
use scene::SceneName;
use sdl2::event::Event;
use sdl2::keyboard::Keycode;
use sdl2::pixels::{Color, PixelFormatEnum};
use sdl2::rect::{Rect, Point};
use sdl2::render::{WindowCanvas, Texture, TextureCreator};
use sdl2::surface::Surface;
use sdl2::video::WindowContext;
use sdl2_engine_helpers::scene::{Scene, BoxedScene, SceneChangeEvent};
use std::fs::File;
use std::io::Result;
use std::path::Path;

use uorustlibs::anim::AnimReader;

pub struct AnimScene<'a> {
    reader: Result<AnimReader<File>>,
    file_index: u8,
    index: u32,
    texture_creator: &'a TextureCreator<WindowContext>,
    textures: Vec<Texture<'a>>,
    exiting: bool,
    current_frame: usize,
}

impl<'a> AnimScene<'a> {
    pub fn new<'b>(engine_data: &mut EngineData<'b>, texture_creator: &'a TextureCreator<WindowContext>) -> BoxedScene<'a, Event, SceneName, EngineData<'b>> {
        let reader = AnimReader::new(&Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"));  //FIXME: Multiple anim muls!
        let mut scene = Box::new(AnimScene {
            reader: reader,
            index: 110,
            textures: vec![],
            exiting: false,
            texture_creator,
            current_frame: 0,
            file_index: 0,
        });
        scene.load_reader(&Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"), engine_data);

        scene
    }

    fn load_reader(&mut self, idx: &Path, mul: &Path, engine_data: &mut EngineData) {
        self.reader = AnimReader::new(idx, mul);
        self.create_slice(engine_data);
    }

    fn set_file_index(&mut self, idx: u8, engine_data: &mut EngineData) {
        self.file_index = idx;
        let (idx, mul) = match idx {
            0 => (Path::new("./assets/anim.idx"), Path::new("./assets/Anim.mul")),
            1 => (Path::new("./assets/anim2.idx"), Path::new("./assets/anim2.mul")),
            2 => (Path::new("./assets/anim3.idx"), Path::new("./assets/anim3.mul")),
            _ => panic!("NO")
        };
        self.load_reader(&idx, &mul, engine_data);
    }

    fn create_slice(&mut self, engine_data: &mut EngineData) {
        let offset = 100;
        let anim = match self.reader {
            Ok(ref mut reader) => {
                reader.read(self.index).or_else(|_| Err("Invalid anim"))
            },
            _ => Err("No reader")
        };
        match anim {
            Ok(anim) => {
                self.textures = anim.to_frames().enumerate().map(|(idx, frame)| {
                    let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                    dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();
                    let surface = frame_to_surface(&frame);
                    surface.blit(None, &mut dest, Some(Rect::new(0, 0, surface.width(), surface.height()))).expect("Could not blit surface");

                    engine_data.text_renderer.draw_text(&mut dest, &Point::new(9, offset as i32 + surface.height() as i32 + 16), &format!("{}", self.index));
                    engine_data.text_renderer.draw_text(&mut dest, &Point::new(9, offset as i32 + surface.height() as i32 + 32), &format!("{} / {}", idx, anim.frame_count));
                    self.texture_creator.create_texture_from_surface(&dest).unwrap()
                }).collect::<_>();
            },
            Err(e) => {
                let mut dest = Surface::new(1024, 768, PixelFormatEnum::RGBA8888).unwrap();
                dest.fill_rect(None, Color::RGB(0, 0, 0)).unwrap();
                engine_data.text_renderer.draw_text(&mut dest, &Point::new(0, 0), e);
                engine_data.text_renderer.draw_text(&mut dest, &Point::new(0, 16), &format!("{}", self.index));
                self.textures = vec![self.texture_creator.create_texture_from_surface(&dest).unwrap()];
            }
        }
        self.current_frame = 0;
    }
}

impl<'a, 'b> Scene<Event, SceneName, EngineData<'b>> for AnimScene<'a> {
    fn render(&self, renderer: &mut WindowCanvas, _engine_data: &EngineData, _tick: u64) {
        renderer.clear();
        if self.textures.len() > 0 {
            renderer.copy(&self.textures[self.current_frame], None, None).unwrap();
        }
        renderer.present();
    }

    fn handle_event(&mut self, event: &Event, engine_data: &mut EngineData, _tick: u64) {
        match *event {
            Event::KeyDown { keycode: Some(Keycode::Escape), .. } => {
                self.exiting = true;
            },
            Event::KeyDown { keycode: Some(Keycode::Left), .. } => {
                if self.index > 0 {
                    self.index -= 1;
                    self.create_slice(engine_data);
                }
            },
            Event::KeyDown { keycode: Some(Keycode::Right), .. } => {
                self.index += 1;
                self.create_slice(engine_data);
            },
            Event::KeyDown { keycode: Some(Keycode::Comma), .. } => {
                if self.index >= 10 {
                    self.index -= 10;
                    self.create_slice(engine_data);
                }
            },
            Event::KeyDown { keycode: Some(Keycode::Period), .. } => {
                self.index += 10;
                self.create_slice(engine_data);
            },
            Event::KeyDown { keycode: Some(Keycode::Tab), .. } => {
                let idx = self.file_index;
                self.set_file_index((idx + 1) % 3, engine_data);
            },
             _ => ()
        }
    }

    fn think(&mut self, _engine_data: &mut EngineData, tick: u64) -> Option<SceneChangeEvent<SceneName>> {
        if self.exiting {
            return Some(SceneChangeEvent::PopScene);
        }

        if tick % 2 == 0 {
            self.current_frame += 1;
            if self.current_frame >= self.textures.len() {
                self.current_frame = 0;
            }
        }

        None
    }
}
<|endoftext|>


<commit_before>use std::path::Path;
use image_convert::frame_to_surface;
use scene::{SceneName, SceneChangeEvent, BoxedScene, Scene};
use cgmath::Point2;
use ggez::Context;
use ggez::graphics::{self, Canvas, Text, DrawParam};
use ggez::event::{KeyCode, KeyMods, MouseButton};
use std::io::Result;
use std::fs::File;

use uorustlibs::anim::AnimReader;

pub struct AnimScene {
    reader: Result<AnimReader<File>>,
    file_index: u8,
    index: u32,
    textures: Vec<Canvas>,
    exiting: bool,
    current_frame: usize,
}

impl<'a> AnimScene {
    pub fn new(ctx: &mut Context) -> BoxedScene<'a, SceneName, ()> {
        let reader = AnimReader::new(&Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"));  //FIXME: Multiple anim muls!
        let mut scene = Box::new(AnimScene {
            reader: reader,
            index: 110,
            textures: vec![],
            exiting: false,
            current_frame: 0,
            file_index: 0,
        });
        scene.load_reader(ctx, &Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"));

        scene
    }

    fn load_reader(&mut self, ctx: &mut Context, idx: &Path, mul: &Path) {
        self.reader = AnimReader::new(idx, mul);
        self.create_slice(ctx);
    }

    fn set_file_index(&mut self, ctx: &mut Context, idx: u8) {
        self.file_index = idx;
        let (idx, mul) = match idx {
            0 => (Path::new("./assets/anim.idx"), Path::new("./assets/Anim.mul")),
            1 => (Path::new("./assets/anim2.idx"), Path::new("./assets/anim2.mul")),
            2 => (Path::new("./assets/anim3.idx"), Path::new("./assets/anim3.mul")),
            _ => panic!("NO")
        };
        self.load_reader(ctx, &idx, &mul);
    }

    fn create_slice(&mut self, ctx: &mut Context) {
        let offset = 100;
        let anim = match self.reader {
            Ok(ref mut reader) => {
                reader.read(self.index).or_else(|_| Err("Invalid anim"))
            },
            _ => Err("No reader")
        };
        match anim {
            Ok(anim) => {
                self.textures = anim.to_frames().enumerate().map(|(idx, frame)| {
                    let mut dest = Canvas::with_window_size(ctx).unwrap();
                    graphics::set_canvas(ctx, Some(&dest));
                    graphics::clear(ctx, graphics::BLACK);
                    let surface = frame_to_surface(ctx, &frame);
                    graphics::draw(ctx, &surface, DrawParam::default()).expect("Failed to blit texture");

                    let label = Text::new(format!("{}", self.index));
                    graphics::draw(ctx, &label, (Point2::new(0.0, 9.0 * offset as f32 + surface.height() as f32 + 16.0), graphics::WHITE));
                    let label = Text::new(format!("{} / {}", idx, anim.frame_count));
                    graphics::draw(ctx, &label, (Point2::new(0.0, 9.0 * offset as f32 + surface.height() as f32 + 32.0), graphics::WHITE));
                    dest
                }).collect::<_>();
            },
            Err(e) => {
                let mut dest = Canvas::with_window_size(ctx).unwrap();
                graphics::set_canvas(ctx, Some(&dest));
                graphics::clear(ctx, graphics::BLACK);
                let label = Text::new(e);
                graphics::draw(ctx, &label, (Point2::new(0.0, 0.0), graphics::WHITE));
                let label = Text::new(format!("{}", self.index));
                graphics::draw(ctx, &label, (Point2::new(0.0, 16.0), graphics::WHITE));
                self.textures = vec![dest];
            }
        };
        graphics::set_canvas(ctx, None);
        self.current_frame = 0;
    }
}

impl Scene<SceneName, ()> for AnimScene {
    fn draw(&mut self, ctx: &mut Context, engine_data: &mut ()) {
        if self.textures.len() > 0 {
            graphics::draw(ctx, &self.textures[self.current_frame], DrawParam::default()).unwrap();
        }
    }

    fn update(&mut self, ctx: &mut Context, engine_data: &mut ()) -> Option<SceneChangeEvent<SceneName>> {
        if self.exiting {
            Some(SceneChangeEvent::PopScene)
        } else {
            None
        }
    }

    fn key_down_event(
        &mut self,
        ctx: &mut Context,
        keycode: KeyCode,
        keymods: KeyMods,
        repeat: bool,
        engine_data: &mut ()
    ) {
        match keycode {
            KeyCode::Escape => {
                self.exiting = true
            },
            KeyCode::Left => {
                if self.index > 0 {
                    self.index -= 1;
                    self.create_slice(ctx);
                }
            },
            KeyCode::Right => {
                self.index += 1;
                self.create_slice(ctx);
            },
            KeyCode::Tab => {
                let idx = self.file_index;
                self.set_file_index(ctx, (idx + 1) % 3);
            },
            _ => ()
        }
    }
}
<commit_msg>Fixed anim<commit_after>use std::path::Path;
use image_convert::frame_to_surface;
use scene::{SceneName, SceneChangeEvent, BoxedScene, Scene};
use cgmath::Point2;
use ggez::Context;
use ggez::graphics::{self, Canvas, Text, DrawParam};
use ggez::event::{KeyCode, KeyMods, MouseButton};
use ggez::timer;
use std::io::Result;
use std::fs::File;
use std::cmp;

use uorustlibs::anim::AnimReader;

pub struct AnimScene {
    reader: Result<AnimReader<File>>,
    file_index: u8,
    index: u32,
    textures: Vec<Canvas>,
    exiting: bool,
    current_frame: usize,
}

impl<'a> AnimScene {
    pub fn new(ctx: &mut Context) -> BoxedScene<'a, SceneName, ()> {
        let reader = AnimReader::new(&Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"));  //FIXME: Multiple anim muls!
        let mut scene = Box::new(AnimScene {
            reader: reader,
            index: 110,
            textures: vec![],
            exiting: false,
            current_frame: 0,
            file_index: 0,
        });
        scene.load_reader(ctx, &Path::new("./assets/anim.idx"), &Path::new("./assets/Anim.mul"));

        scene
    }

    fn load_reader(&mut self, ctx: &mut Context, idx: &Path, mul: &Path) {
        self.reader = AnimReader::new(idx, mul);
        self.create_slice(ctx);
    }

    fn set_file_index(&mut self, ctx: &mut Context, idx: u8) {
        self.file_index = idx;
        let (idx, mul) = match idx {
            0 => (Path::new("./assets/anim.idx"), Path::new("./assets/Anim.mul")),
            1 => (Path::new("./assets/anim2.idx"), Path::new("./assets/anim2.mul")),
            2 => (Path::new("./assets/anim3.idx"), Path::new("./assets/anim3.mul")),
            _ => panic!("NO")
        };
        self.load_reader(ctx, &idx, &mul);
    }

    fn create_slice(&mut self, ctx: &mut Context) {
        let offset = 100;
        let anim = match self.reader {
            Ok(ref mut reader) => {
                reader.read(self.index).or_else(|_| Err("Invalid anim"))
            },
            _ => Err("No reader")
        };
        match anim {
            Ok(anim) => {
                self.textures = anim.to_frames().enumerate().map(|(idx, frame)| {
                    let mut dest = Canvas::with_window_size(ctx).unwrap();
                    graphics::set_canvas(ctx, Some(&dest));
                    graphics::clear(ctx, graphics::BLACK);
                    let surface = frame_to_surface(ctx, &frame);
                    graphics::draw(ctx, &surface, DrawParam::default()).expect("Failed to blit texture");

                    let label = Text::new(format!("{}", self.index));
                    graphics::draw(ctx, &label, (Point2::new(0.0, surface.height() as f32 + 16.0), graphics::WHITE));
                    let label = Text::new(format!("{} / {}", idx + 1, anim.frame_count));
                    graphics::draw(ctx, &label, (Point2::new(0.0, surface.height() as f32 + 32.0), graphics::WHITE));
                    dest
                }).collect::<_>();
            },
            Err(e) => {
                let mut dest = Canvas::with_window_size(ctx).unwrap();
                graphics::set_canvas(ctx, Some(&dest));
                graphics::clear(ctx, graphics::BLACK);
                let label = Text::new(e);
                graphics::draw(ctx, &label, (Point2::new(0.0, 0.0), graphics::WHITE));
                let label = Text::new(format!("{}", self.index));
                graphics::draw(ctx, &label, (Point2::new(0.0, 16.0), graphics::WHITE));
                self.textures = vec![dest];
            }
        };
        graphics::set_canvas(ctx, None);
        self.current_frame = 0;
    }
}

impl Scene<SceneName, ()> for AnimScene {
    fn draw(&mut self, ctx: &mut Context, engine_data: &mut ()) {
        if self.textures.len() > 0 {
            graphics::draw(ctx, &self.textures[self.current_frame], DrawParam::default()).unwrap();
        }
    }

    fn update(&mut self, ctx: &mut Context, engine_data: &mut ()) -> Option<SceneChangeEvent<SceneName>> {
        const DESIRED_FPS: u32 = 15;

        while timer::check_update_time(ctx, DESIRED_FPS) {
            self.current_frame += 1;
                if (self.current_frame == self.textures.len()) {
                self.current_frame = 0;
            }
        }

        if self.exiting {
            Some(SceneChangeEvent::PopScene)
        } else {
            None
        }
    }

    fn key_down_event(
        &mut self,
        ctx: &mut Context,
        keycode: KeyCode,
        keymods: KeyMods,
        repeat: bool,
        engine_data: &mut ()
    ) {
        match keycode {
            KeyCode::Escape => {
                self.exiting = true
            },
            KeyCode::Left => {
                if self.index > 0 {
                    self.index -= 1;
                    self.current_frame = 0;
                    self.create_slice(ctx);
                }
            },
            KeyCode::Right => {
                self.index += 1;
                    self.current_frame = 0;
                self.create_slice(ctx);
            },
            KeyCode::PageDown => {
                if self.index > 0 {
                    self.index = cmp::max(self.index - 10, 0) ;
                    self.current_frame = 0;
                    self.create_slice(ctx);
                }
            },
            KeyCode::PageUp => {
                self.index += 10;
                self.current_frame = 0;
                self.create_slice(ctx);
            },
            KeyCode::Tab => {
                let idx = self.file_index;
                self.set_file_index(ctx, (idx + 1) % 3);
            },
            _ => ()
        }
    }
}
<|endoftext|>


<commit_before>// Copyright 2017 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::collections::{vec_deque, VecDeque};
use std::str;

use crate::bam;
use crate::bam::errors::{Error, Result};
use crate::bam::Read;

/// A buffer for BAM records. This allows access regions in a sorted BAM file while iterating
/// over it in a single pass.
/// The buffer is implemented as a ringbuffer, such that extension or movement to the right has
/// linear complexity. The buffer makes use of indexed random access. Hence, when fetching a
/// region at the very end of the BAM, everything before is omitted without cost.
#[derive(Debug)]
pub struct RecordBuffer {
    reader: bam::IndexedReader,
    inner: VecDeque<bam::Record>,
    overflow: Option<bam::Record>,
}

unsafe impl Sync for RecordBuffer {}
unsafe impl Send for RecordBuffer {}

impl RecordBuffer {
    /// Create a new `RecordBuffer`.
    pub fn new(bam: bam::IndexedReader) -> Self {
        RecordBuffer {
            reader: bam,
            inner: VecDeque::new(),
            overflow: None,
        }
    }

    /// Return start position of buffer
    fn start(&self) -> Option<u32> {
        self.inner.front().map(|rec| rec.pos() as u32)
    }

    /// Return end position of buffer.
    fn end(&self) -> Option<u32> {
        self.inner.back().map(|rec| rec.pos() as u32)
    }

    fn tid(&self) -> Option<i32> {
        self.inner.back().map(|rec| rec.tid())
    }

    /// Fill buffer at the given interval. If the start coordinate is left of
    /// the previous start coordinate, this will use an additional BAM fetch IO operation.
    /// Coordinates are 0-based, and end is exclusive.
    /// Returns tuple with numbers of added and deleted records since the previous fetch.
    #[allow(unused_assignments)] // TODO this is needed because rustc thinks that deleted is unused
    pub fn fetch(&mut self, chrom: &[u8], start: u32, end: u32) -> Result<(usize, usize)> {
        let mut added = 0;
        // move overflow from last fetch into ringbuffer
        if self.overflow.is_some() {
            added += 1;
            self.inner.push_back(self.overflow.take().unwrap());
        }

        if let Some(tid) = self.reader.header.tid(chrom) {
            let mut deleted = 0;
            let window_start = start;
            if self.inner.is_empty()
                || self.end().unwrap() < window_start
                || self.tid().unwrap() != tid as i32
                || self.start().unwrap() > window_start
            {
                let end = self.reader.header.target_len(tid).unwrap();
                self.reader.fetch(tid, window_start, end)?;
                deleted = self.inner.len();
                self.inner.clear();
            } else {
                // remove records too far left
                let to_remove = self
                    .inner
                    .iter()
                    .take_while(|rec| rec.pos() < window_start as i32)
                    .count();
                for _ in 0..to_remove {
                    self.inner.pop_front();
                }
                deleted = to_remove;
            }

            // extend to the right
            loop {
                let mut record = bam::Record::new();
                if !self.reader.read(&mut record)? {
                    break;
                }

                if record.is_unmapped() {
                    continue;
                }

                let pos = record.pos();
                if pos >= end as i32 {
                    self.overflow = Some(record);
                    break;
                } else {
                    self.inner.push_back(record);
                    added += 1;
                }
            }

            Ok((added, deleted))
        } else {
            Err(Error::UnknownSequence {
                sequence: str::from_utf8(chrom).unwrap().to_owned(),
            })
        }
    }

    /// Iterate over records that have been fetched with `fetch`.
    pub fn iter(&self) -> vec_deque::Iter<'_, bam::Record> {
        self.inner.iter()
    }

    /// Iterate over mutable references to records that have been fetched with `fetch`.
    pub fn iter_mut(&mut self) -> vec_deque::IterMut<'_, bam::Record> {
        self.inner.iter_mut()
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::bam;
    use itertools::Itertools;

    #[test]
    fn test_buffer() {
        let reader = bam::IndexedReader::from_path(&"test/test.bam").unwrap();

        let mut buffer = RecordBuffer::new(reader);

        buffer.fetch(b"CHROMOSOME_I", 1, 5).unwrap();
        {
            let records = buffer.iter().collect_vec();
            assert_eq!(records.len(), 6);
            assert_eq!(records[0].pos(), 1);
            assert_eq!(records[1].pos(), 1);
            assert_eq!(records[2].pos(), 1);
            assert_eq!(records[3].pos(), 1);
            assert_eq!(records[4].pos(), 1);
            assert_eq!(records[5].pos(), 1);
        }
    }
}
<commit_msg>Allow default caching of cigar string in bam::RecordBuffer.<commit_after>// Copyright 2017 Johannes Köster.
// Licensed under the MIT license (http://opensource.org/licenses/MIT)
// This file may not be copied, modified, or distributed
// except according to those terms.

use std::collections::{vec_deque, VecDeque};
use std::str;

use crate::bam;
use crate::bam::errors::{Error, Result};
use crate::bam::Read;

/// A buffer for BAM records. This allows access regions in a sorted BAM file while iterating
/// over it in a single pass.
/// The buffer is implemented as a ringbuffer, such that extension or movement to the right has
/// linear complexity. The buffer makes use of indexed random access. Hence, when fetching a
/// region at the very end of the BAM, everything before is omitted without cost.
#[derive(Debug)]
pub struct RecordBuffer {
    reader: bam::IndexedReader,
    inner: VecDeque<bam::Record>,
    overflow: Option<bam::Record>,
    cache_cigar: bool,
}

unsafe impl Sync for RecordBuffer {}
unsafe impl Send for RecordBuffer {}

impl RecordBuffer {
    /// Create a new `RecordBuffer`.
    ///
    /// # Arguments
    ///
    /// * `bam` - BAM reader
    /// * `cache_cigar` - whether to call `bam::Record::cache_cigar()` for each record.
    pub fn new(bam: bam::IndexedReader, cache_cigar: bool) -> Self {
        RecordBuffer {
            reader: bam,
            inner: VecDeque::new(),
            overflow: None,
            cache_cigar
        }
    }

    /// Return start position of buffer
    fn start(&self) -> Option<u32> {
        self.inner.front().map(|rec| rec.pos() as u32)
    }

    /// Return end position of buffer.
    fn end(&self) -> Option<u32> {
        self.inner.back().map(|rec| rec.pos() as u32)
    }

    fn tid(&self) -> Option<i32> {
        self.inner.back().map(|rec| rec.tid())
    }

    /// Fill buffer at the given interval. If the start coordinate is left of
    /// the previous start coordinate, this will use an additional BAM fetch IO operation.
    /// Coordinates are 0-based, and end is exclusive.
    /// Returns tuple with numbers of added and deleted records since the previous fetch.
    #[allow(unused_assignments)] // TODO this is needed because rustc thinks that deleted is unused
    pub fn fetch(&mut self, chrom: &[u8], start: u32, end: u32) -> Result<(usize, usize)> {
        let mut added = 0;
        // move overflow from last fetch into ringbuffer
        if self.overflow.is_some() {
            added += 1;
            self.inner.push_back(self.overflow.take().unwrap());
        }

        if let Some(tid) = self.reader.header.tid(chrom) {
            let mut deleted = 0;
            let window_start = start;
            if self.inner.is_empty()
                || self.end().unwrap() < window_start
                || self.tid().unwrap() != tid as i32
                || self.start().unwrap() > window_start
            {
                let end = self.reader.header.target_len(tid).unwrap();
                self.reader.fetch(tid, window_start, end)?;
                deleted = self.inner.len();
                self.inner.clear();
            } else {
                // remove records too far left
                let to_remove = self
                    .inner
                    .iter()
                    .take_while(|rec| rec.pos() < window_start as i32)
                    .count();
                for _ in 0..to_remove {
                    self.inner.pop_front();
                }
                deleted = to_remove;
            }

            // extend to the right
            loop {
                let mut record = bam::Record::new();
                if !self.reader.read(&mut record)? {
                    break;
                }

                if record.is_unmapped() {
                    continue;
                }

                let pos = record.pos();

                if self.cache_cigar {
                    record.cache_cigar();
                }

                if pos >= end as i32 {
                    self.overflow = Some(record);
                    break;
                } else {
                    self.inner.push_back(record);
                    added += 1;
                }
            }

            Ok((added, deleted))
        } else {
            Err(Error::UnknownSequence {
                sequence: str::from_utf8(chrom).unwrap().to_owned(),
            })
        }
    }

    /// Iterate over records that have been fetched with `fetch`.
    pub fn iter(&self) -> vec_deque::Iter<'_, bam::Record> {
        self.inner.iter()
    }

    /// Iterate over mutable references to records that have been fetched with `fetch`.
    pub fn iter_mut(&mut self) -> vec_deque::IterMut<'_, bam::Record> {
        self.inner.iter_mut()
    }

    pub fn len(&self) -> usize {
        self.inner.len()
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::bam;
    use itertools::Itertools;

    #[test]
    fn test_buffer() {
        let reader = bam::IndexedReader::from_path(&"test/test.bam").unwrap();

        let mut buffer = RecordBuffer::new(reader);

        buffer.fetch(b"CHROMOSOME_I", 1, 5).unwrap();
        {
            let records = buffer.iter().collect_vec();
            assert_eq!(records.len(), 6);
            assert_eq!(records[0].pos(), 1);
            assert_eq!(records[1].pos(), 1);
            assert_eq!(records[2].pos(), 1);
            assert_eq!(records[3].pos(), 1);
            assert_eq!(records[4].pos(), 1);
            assert_eq!(records[5].pos(), 1);
        }
    }
}
<|endoftext|>


<commit_before>use sqlite::{Connection, Statement, State};
use std::mem;

use streamer::{Config, Result};
use streamer::platform::{self, Platform, Profile};
use streamer::system::{Event, EventKind, Job};

pub struct Output {
    #[allow(dead_code)]
    connection: Connection,
    arrivals: Statement<'static>,
    profiles: Statement<'static>,
}

impl Output {
    pub fn new(platform: &platform::Thermal, config: &Config) -> Result<Self> {
        use sql::prelude::*;

        let connection = ok!(Connection::open(path!(@unchecked config,
                                                    "an output file is required")));
        ok!(connection.execute("
            PRAGMA journal_mode = MEMORY;
            PRAGMA synchronous = OFF;
        "));
        ok!(connection.execute(
            ok!(create_table("arrivals").if_not_exists().columns(&[
                "time".float().not_null(),
            ]).compile())
        ));
        ok!(connection.execute(
            ok!(create_table("profiles").if_not_exists().columns(&[
                "time".float().not_null(), "component_id".integer().not_null(),
                "power".float().not_null(), "temperature".float().not_null(),
            ]).compile())
        ));
        ok!(connection.execute(ok!(delete_from("arrivals").compile())));
        ok!(connection.execute(ok!(delete_from("profiles").compile())));
        let arrivals = {
            let statement = ok!(connection.prepare(
                ok!(insert_into("arrivals").columns(&["time"]).compile())
            ));
            unsafe { mem::transmute(statement) }
        };
        let profiles = {
            let units = platform.elements().len();
            let statement = ok!(connection.prepare(
                ok!(insert_into("profiles").columns(&[
                    "time", "component_id", "power", "temperature",
                ]).batch(units).compile())
            ));
            unsafe { mem::transmute(statement) }
        };
        Ok(Output { connection: connection, arrivals: arrivals, profiles: profiles })
    }

    pub fn next(&mut self, event: &Event, profiles: &(Profile, Profile)) -> Result<()> {
        ok!(self.connection.execute("BEGIN TRANSACTION"));
        if let &EventKind::Arrive(ref job) = &event.kind {
            ok!(self.write_arrival(job));
        }
        ok!(self.write_profiles(profiles));
        ok!(self.connection.execute("END TRANSACTION"));
        Ok(())
    }

    fn write_arrival(&mut self, job: &Job) -> Result<()> {
        let statement = &mut self.arrivals;
        ok!(statement.reset());
        ok!(statement.bind(1, job.arrival));
        if State::Done != ok!(statement.next()) {
            raise!("failed to write into the database");
        }
        Ok(())
    }

    fn write_profiles(&mut self, profiles: &(Profile, Profile)) -> Result<()> {
        let &Profile { units, steps, time, time_step, data: ref power } = &profiles.0;
        let &Profile { data: ref temperature, .. } = &profiles.1;
        let statement = &mut self.profiles;
        for i in 0..steps {
            let time = time + (i as f64) * time_step;
            ok!(statement.reset());
            let mut k = 0;
            for j in 0..units {
                ok!(statement.bind(k + 1, time));
                ok!(statement.bind(k + 2, j as i64));
                ok!(statement.bind(k + 3, power[i * units + j]));
                ok!(statement.bind(k + 4, temperature[i * units + j]));
                k += 4;
            }
            if State::Done != ok!(statement.next()) {
                raise!("failed to write into the database");
            }
        }
        Ok(())
    }
}
<commit_msg>Get rid of a redundant attribute<commit_after>use sqlite::{Connection, Statement, State};
use std::mem;

use streamer::{Config, Result};
use streamer::platform::{self, Platform, Profile};
use streamer::system::{Event, EventKind, Job};

pub struct Output {
    connection: Connection,
    arrivals: Statement<'static>,
    profiles: Statement<'static>,
}

impl Output {
    pub fn new(platform: &platform::Thermal, config: &Config) -> Result<Self> {
        use sql::prelude::*;

        let connection = ok!(Connection::open(path!(@unchecked config,
                                                    "an output file is required")));
        ok!(connection.execute("
            PRAGMA journal_mode = MEMORY;
            PRAGMA synchronous = OFF;
        "));
        ok!(connection.execute(
            ok!(create_table("arrivals").if_not_exists().columns(&[
                "time".float().not_null(),
            ]).compile())
        ));
        ok!(connection.execute(
            ok!(create_table("profiles").if_not_exists().columns(&[
                "time".float().not_null(), "component_id".integer().not_null(),
                "power".float().not_null(), "temperature".float().not_null(),
            ]).compile())
        ));
        ok!(connection.execute(ok!(delete_from("arrivals").compile())));
        ok!(connection.execute(ok!(delete_from("profiles").compile())));
        let arrivals = {
            let statement = ok!(connection.prepare(
                ok!(insert_into("arrivals").columns(&["time"]).compile())
            ));
            unsafe { mem::transmute(statement) }
        };
        let profiles = {
            let units = platform.elements().len();
            let statement = ok!(connection.prepare(
                ok!(insert_into("profiles").columns(&[
                    "time", "component_id", "power", "temperature",
                ]).batch(units).compile())
            ));
            unsafe { mem::transmute(statement) }
        };
        Ok(Output { connection: connection, arrivals: arrivals, profiles: profiles })
    }

    pub fn next(&mut self, event: &Event, profiles: &(Profile, Profile)) -> Result<()> {
        ok!(self.connection.execute("BEGIN TRANSACTION"));
        if let &EventKind::Arrive(ref job) = &event.kind {
            ok!(self.write_arrival(job));
        }
        ok!(self.write_profiles(profiles));
        ok!(self.connection.execute("END TRANSACTION"));
        Ok(())
    }

    fn write_arrival(&mut self, job: &Job) -> Result<()> {
        let statement = &mut self.arrivals;
        ok!(statement.reset());
        ok!(statement.bind(1, job.arrival));
        if State::Done != ok!(statement.next()) {
            raise!("failed to write into the database");
        }
        Ok(())
    }

    fn write_profiles(&mut self, profiles: &(Profile, Profile)) -> Result<()> {
        let &Profile { units, steps, time, time_step, data: ref power } = &profiles.0;
        let &Profile { data: ref temperature, .. } = &profiles.1;
        let statement = &mut self.profiles;
        for i in 0..steps {
            let time = time + (i as f64) * time_step;
            ok!(statement.reset());
            let mut k = 0;
            for j in 0..units {
                ok!(statement.bind(k + 1, time));
                ok!(statement.bind(k + 2, j as i64));
                ok!(statement.bind(k + 3, power[i * units + j]));
                ok!(statement.bind(k + 4, temperature[i * units + j]));
                k += 4;
            }
            if State::Done != ok!(statement.next()) {
                raise!("failed to write into the database");
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::fmt;

#[allow(dead_code)]
#[derive(Clone, Copy, Debug)]
pub enum Rank {
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King,
    Ace,
}

#[allow(dead_code)]
#[derive(Clone, Copy, Debug)]
pub enum Suit {
    Hearts,
    Clubs,
    Diamonds,
    Spades,
}

#[derive(Clone, Copy, Debug)]
pub struct Card {
    pub rank: Rank,
    pub suit: Suit,
}

impl fmt::Display for Card {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let rank_str = match self.rank {
            Rank::Two => "2",
            Rank::Three => "3",
            Rank::Four => "4",
            Rank::Five => "5",
            Rank::Six => "6",
            Rank::Seven => "7",
            Rank::Eight => "8",
            Rank::Nine => "9",
            Rank::Ten => "10",
            Rank::Jack => "J",
            Rank::Queen => "Q",
            Rank::King => "K",
            Rank::Ace => "A",
        };

        let suit_char = match self.suit {
            Suit::Hearts => '\u{2665}',
            Suit::Clubs => '\u{2663}',
            Suit::Diamonds => '\u{2666}',
            Suit::Spades => '\u{2660}',
        };

        write!(formatter, "[{}{}]", rank_str, suit_char)
    }
}<commit_msg>Clean card module. Remove Copy, Clone from card struct. Remove allowance of dead code.<commit_after>use std::fmt;

#[derive(Clone, Copy, Debug)]
pub enum Rank {
    Two,
    Three,
    Four,
    Five,
    Six,
    Seven,
    Eight,
    Nine,
    Ten,
    Jack,
    Queen,
    King,
    Ace,
}

#[derive(Clone, Copy, Debug)]
pub enum Suit {
    Hearts,
    Clubs,
    Diamonds,
    Spades,
}

#[derive(Debug)]
pub struct Card {
    pub rank: Rank,
    pub suit: Suit,
}

impl fmt::Display for Card {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        let rank_str = match self.rank {
            Rank::Two => "2",
            Rank::Three => "3",
            Rank::Four => "4",
            Rank::Five => "5",
            Rank::Six => "6",
            Rank::Seven => "7",
            Rank::Eight => "8",
            Rank::Nine => "9",
            Rank::Ten => "10",
            Rank::Jack => "J",
            Rank::Queen => "Q",
            Rank::King => "K",
            Rank::Ace => "A",
        };

        let suit_char = match self.suit {
            Suit::Hearts => '\u{2665}',
            Suit::Clubs => '\u{2663}',
            Suit::Diamonds => '\u{2666}',
            Suit::Spades => '\u{2660}',
        };

        write!(formatter, "[{}{}]", rank_str, suit_char)
    }
}<|endoftext|>


<commit_before>//! # client
//!
//! Ssh2-config implementation with a ssh2 client

/**
 * MIT License
 *
 * ssh2-config - Copyright (c) 2021 Christian Visintin
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
use dirs::home_dir;
use ssh2::{MethodType, Session};
use ssh2_config::{HostParams, SshConfig};
use std::env::args;
use std::fs::File;
use std::io::BufReader;
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
use std::path::{Path, PathBuf};
use std::process::exit;
use std::time::Duration;

pub fn client() {
    // get args
    let args: Vec<String> = args().collect();
    let address = match args.get(1) {
        Some(addr) => addr.to_string(),
        None => {
            usage();
            exit(255)
        }
    };
    // check path
    let config_path = match args.get(2) {
        Some(p) => PathBuf::from(p),
        None => {
            let mut p = home_dir().expect("Failed to get home_dir for guest OS");
            p.extend(Path::new(".ssh/config"));
            p
        }
    };
    // Open config file
    let config = read_config(config_path.as_path());
    println!("Config file: {:?}", config);

    let params = config.query(address.as_str());
    println!("Params: {:?}", params);

    connect(address.as_str(), &params);
}

fn usage() {
    eprintln!("Usage: cargo run --example client -- <address:port> [config-path]");
}

fn read_config(p: &Path) -> SshConfig {
    let mut reader = match File::open(p) {
        Ok(f) => BufReader::new(f),
        Err(err) => panic!("Could not open file '{}': {}", p.display(), err),
    };
    match SshConfig::default().parse(&mut reader) {
        Ok(config) => config,
        Err(err) => panic!("Failed to parse configuration: {}", err),
    }
}

fn connect(host: &str, params: &HostParams) {
    // Resolve host
    let host = match params.host_name.as_deref() {
        Some(h) => h,
        None => host,
    };
    let port = match params.port {
        None => 22,
        Some(p) => p,
    };
    let host = match host.contains(':') {
        true => host.to_string(),
        false => format!("{}:{}", host, port),
    };
    println!("Connecting to host {}...", host);
    let socket_addresses: Vec<SocketAddr> = match host.to_socket_addrs() {
        Ok(s) => s.collect(),
        Err(err) => {
            panic!("Could not parse host: {}", err);
        }
    };
    let mut tcp: Option<TcpStream> = None;
    // Try addresses
    for socket_addr in socket_addresses.iter() {
        match TcpStream::connect_timeout(
            socket_addr,
            params.connect_timeout.unwrap_or(Duration::from_secs(30)),
        ) {
            Ok(stream) => {
                println!("Established connection with {}", socket_addr);
                tcp = Some(stream);
                break;
            }
            Err(_) => continue,
        }
    }
    // If stream is None, return connection timeout
    let stream: TcpStream = match tcp {
        Some(t) => t,
        None => {
            panic!("No suitable socket address found; connection timeout");
        }
    };
    let mut session: Session = match Session::new() {
        Ok(s) => s,
        Err(err) => {
            panic!("Could not create session: {}", err);
        }
    };
    // Configure session
    configure_session(&mut session, params);
    // Connect
    session.set_tcp_stream(stream);
    if let Err(err) = session.handshake() {
        panic!("Handshake failed: {}", err);
    }
    // Get username
    let username = match params.user.as_ref() {
        Some(u) => {
            println!("Using username '{}'", u);
            u.clone()
        },
        None =>  {
        // reads until a \n is encountered
        println!("User:");
        let line: String = read!("{}\n");
        line.clone()
     }
    };
    for i in (params.identity_file.as_ref()).unwrap().iter() {
        if let Ok(_) = session.userauth_pubkey_file(&username, None, i, None) {
            break;
        }
    }
    if let Some(banner) = session.banner() {
        println!("{}", banner);
    }
    println!("Connection OK!");
    if let Err(err) = session.disconnect(None, "mandi mandi!", None) {
        panic!("Disconnection failed: {}", err);
    }
}

fn configure_session(session: &mut Session, params: &HostParams) {
    println!("Configuring session...");
    if let Some(compress) = params.compression {
        println!("compression: {}", compress);
        session.set_compress(compress);
    }
    if params.tcp_keep_alive.unwrap_or(false) && params.server_alive_interval.is_some() {
        let interval = params.server_alive_interval.unwrap().as_secs() as u32;
        println!("keepalive interval: {} seconds", interval);
        session.set_keepalive(true, interval);
    }
    // algos
    if let Some(algos) = params.kex_algorithms.as_deref() {
        if let Err(err) = session.method_pref(MethodType::Kex, algos.join(",").as_str()) {
            panic!("Could not set KEX algorithms: {}", err);
        }
    }
    if let Some(algos) = params.host_key_algorithms.as_deref() {
        if let Err(err) = session.method_pref(MethodType::HostKey, algos.join(",").as_str()) {
            panic!("Could not set host key algorithms: {}", err);
        }
    }
    if let Some(algos) = params.ciphers.as_deref() {
        if let Err(err) = session.method_pref(MethodType::CryptCs, algos.join(",").as_str()) {
            panic!("Could not set crypt algorithms (client-server): {}", err);
        }
        if let Err(err) = session.method_pref(MethodType::CryptSc, algos.join(",").as_str()) {
            panic!("Could not set crypt algorithms (server-client): {}", err);
        }
    }
    if let Some(algos) = params.mac.as_deref() {
        if let Err(err) = session.method_pref(MethodType::MacCs, algos.join(",").as_str()) {
            panic!("Could not set MAC algorithms (client-server): {}", err);
        }
        if let Err(err) = session.method_pref(MethodType::MacSc, algos.join(",").as_str()) {
            panic!("Could not set MAC algorithms (server-client): {}", err);
        }
    }
}

<commit_msg>Remove the secretpassword stuff, always use env or .config for username<commit_after>//! # client
//!
//! Ssh2-config implementation with a ssh2 client

/**
 * MIT License
 *
 * ssh2-config - Copyright (c) 2021 Christian Visintin
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
use dirs::home_dir;
use ssh2::{MethodType, Session};
use ssh2_config::{HostParams, SshConfig};
use std::env::args;
use std::fs::File;
use std::io::BufReader;
use std::net::{SocketAddr, TcpStream, ToSocketAddrs};
use std::path::{Path, PathBuf};
use std::process::exit;
use std::time::Duration;

pub fn client() {
    // get args
    let args: Vec<String> = args().collect();
    let address = match args.get(1) {
        Some(addr) => addr.to_string(),
        None => {
            usage();
            exit(255)
        }
    };
    // check path
    let config_path = match args.get(2) {
        Some(p) => PathBuf::from(p),
        None => {
            let mut p = home_dir().expect("Failed to get home_dir for guest OS");
            p.extend(Path::new(".ssh/config"));
            p
        }
    };
    // Open config file
    let config = read_config(config_path.as_path());
    println!("Config file: {:?}", config);

    let params = config.query(address.as_str());
    println!("Params: {:?}", params);

    connect(address.as_str(), &params);
}

fn usage() {
    eprintln!("Usage: cargo run --example client -- <address:port> [config-path]");
}

fn read_config(p: &Path) -> SshConfig {
    let mut reader = match File::open(p) {
        Ok(f) => BufReader::new(f),
        Err(err) => panic!("Could not open file '{}': {}", p.display(), err),
    };
    match SshConfig::default().parse(&mut reader) {
        Ok(config) => config,
        Err(err) => panic!("Failed to parse configuration: {}", err),
    }
}

fn connect(host: &str, params: &HostParams) {
    // Resolve host
    let host = match params.host_name.as_deref() {
        Some(h) => h,
        None => host,
    };
    let port = match params.port {
        None => 22,
        Some(p) => p,
    };
    let host = match host.contains(':') {
        true => host.to_string(),
        false => format!("{}:{}", host, port),
    };
    println!("Connecting to host {}...", host);
    let socket_addresses: Vec<SocketAddr> = match host.to_socket_addrs() {
        Ok(s) => s.collect(),
        Err(err) => {
            panic!("Could not parse host: {}", err);
        }
    };
    let mut tcp: Option<TcpStream> = None;
    // Try addresses
    for socket_addr in socket_addresses.iter() {
        match TcpStream::connect_timeout(
            socket_addr,
            params.connect_timeout.unwrap_or(Duration::from_secs(30)),
        ) {
            Ok(stream) => {
                println!("Established connection with {}", socket_addr);
                tcp = Some(stream);
                break;
            }
            Err(_) => continue,
        }
    }
    // If stream is None, return connection timeout
    let stream: TcpStream = match tcp {
        Some(t) => t,
        None => {
            panic!("No suitable socket address found; connection timeout");
        }
    };
    let mut session: Session = match Session::new() {
        Ok(s) => s,
        Err(err) => {
            panic!("Could not create session: {}", err);
        }
    };
    // Configure session
    configure_session(&mut session, params);
    // Connect
    session.set_tcp_stream(stream);
    if let Err(err) = session.handshake() {
        panic!("Handshake failed: {}", err);
    }
    // Get username
    let username = match params.user.as_ref() {
        Some(u) => {
            println!("Using username '{}'", u);
            u.clone()
        }
        None => match std::env::var("USER") {
            Ok(val) => val,
            Err(e) => {
                println!("No USER env variable and no user in .ssh/config (consider using %i in .config)");
                exit(1)
            }
        },
    };
    for i in (params.identity_file.as_ref()).unwrap().iter() {
        if let Ok(_) = session.userauth_pubkey_file(&username, None, i, None) {
            break;
        }
    }
    if let Some(banner) = session.banner() {
        println!("{}", banner);
    }
    println!("Connection OK!");
    if let Err(err) = session.disconnect(None, "mandi mandi!", None) {
        panic!("Disconnection failed: {}", err);
    }
}

fn configure_session(session: &mut Session, params: &HostParams) {
    println!("Configuring session...");
    if let Some(compress) = params.compression {
        println!("compression: {}", compress);
        session.set_compress(compress);
    }
    if params.tcp_keep_alive.unwrap_or(false) && params.server_alive_interval.is_some() {
        let interval = params.server_alive_interval.unwrap().as_secs() as u32;
        println!("keepalive interval: {} seconds", interval);
        session.set_keepalive(true, interval);
    }
    // algos
    if let Some(algos) = params.kex_algorithms.as_deref() {
        if let Err(err) = session.method_pref(MethodType::Kex, algos.join(",").as_str()) {
            panic!("Could not set KEX algorithms: {}", err);
        }
    }
    if let Some(algos) = params.host_key_algorithms.as_deref() {
        if let Err(err) = session.method_pref(MethodType::HostKey, algos.join(",").as_str()) {
            panic!("Could not set host key algorithms: {}", err);
        }
    }
    if let Some(algos) = params.ciphers.as_deref() {
        if let Err(err) = session.method_pref(MethodType::CryptCs, algos.join(",").as_str()) {
            panic!("Could not set crypt algorithms (client-server): {}", err);
        }
        if let Err(err) = session.method_pref(MethodType::CryptSc, algos.join(",").as_str()) {
            panic!("Could not set crypt algorithms (server-client): {}", err);
        }
    }
    if let Some(algos) = params.mac.as_deref() {
        if let Err(err) = session.method_pref(MethodType::MacCs, algos.join(",").as_str()) {
            panic!("Could not set MAC algorithms (client-server): {}", err);
        }
        if let Err(err) = session.method_pref(MethodType::MacSc, algos.join(",").as_str()) {
            panic!("Could not set MAC algorithms (server-client): {}", err);
        }
    }
}
<|endoftext|>