<commit_before>#![allow(dead_code)]

use proto::raftpb::{Entry, Snapshot};
use std::ops::RangeTo;

// unstable.entris[i] has raft log position i+unstable.offset.
// Note that unstable.offset may be less than the highest log
// position in storage; this means that the next write to storage
// might need to truncate the log before persisting unstable.entries.
#[derive(Debug, PartialEq)]
pub struct Unstable {
    // the incoming unstable snapshot, if any.
    pub snapshot: Option<Box<Snapshot>>,
    // all entries that have not yet been written to storage.
    pub entries: Vec<Entry>,
    pub offset: u64,
}

impl Unstable {
    pub fn new(offset: u64) -> Unstable {
        Unstable {
            offset: offset,
            snapshot: None,
            entries: vec![],
        }
    }
    // maybe_first_index returns the last index if it has at least one
    // unstable entry or snapshot.
    pub fn maybe_first_index(&self) -> Option<u64> {
        self.snapshot
            .as_ref()
            .map_or(None, |snap| Some(snap.get_metadata().get_index() + 1))
    }

    pub fn get_snapshot(&self) -> Snapshot {
        return *self.snapshot.as_ref().unwrap().clone();
    }

    // maybe_last_index returns the last index if it has at least one
    // unstable entry or snapshot.
    pub fn maybe_last_index(&self) -> Option<u64> {
        match self.entries.len() {
            0 => {
                self.snapshot
                    .as_ref()
                    .map_or(None, |snap| Some(snap.get_metadata().get_index()))
            }
            len => Some(self.offset + len as u64 - 1),
        }
    }

    // maybe_term returns the term of the entry at index idx, if there
    // is any.
    pub fn maybe_term(&self, idx: u64) -> Option<u64> {
        if idx < self.offset {
            if self.snapshot.is_none() {
                return None;
            }

            let meta = self.snapshot.as_ref().unwrap().get_metadata().clone();
            if idx == meta.get_index() {
                return Some(meta.get_term());
            }
            return None;
        }
        match self.maybe_last_index() {
            None => None,
            Some(last) => {
                if idx > last {
                    return None;
                }
                Some(self.entries[(idx - self.offset) as usize].get_Term())
            }
        }
    }

    pub fn stable_to(&mut self, idx: u64, term: u64) {
        let t = self.maybe_term(idx);
        if t.is_none() {
            return;
        }

        if t.unwrap() == term && idx >= self.offset {
            let start = idx + 1 - self.offset;
            self.entries.drain(RangeTo { end: start as usize });
            self.offset = idx + 1;
        }
    }

    pub fn stable_snap_to(&mut self, idx: u64) {
        if self.snapshot.is_none() {
            return;
        }
        if idx == self.snapshot.as_ref().unwrap().get_metadata().get_index() {
            self.snapshot = None;
        }
    }

    pub fn restore(&mut self, snap: Snapshot) {
        self.entries.clear();
        self.offset = snap.get_metadata().get_index() + 1;
        self.snapshot = Some(Box::new(snap));
    }

    pub fn truncate_and_append(&mut self, ents: &[Entry]) {
        let after = ents[0].get_Index() - 1;
        if after == self.offset + self.entries.len() as u64 - 1 {
            self.entries.extend_from_slice(ents);
        } else if after < self.offset {
            // The log is being truncated to before our current offset
            // portion, so set the offset and replace the entries
            self.offset = after + 1;
            self.entries.clear();
            self.entries.extend_from_slice(ents);
        } else {
            // truncate to after and copy to self.entries
            // then append
            let off = self.offset.clone();
            let cut_ents = &self.slice(off, after + 1);
            self.entries = vec![];
            self.entries.extend_from_slice(cut_ents);
            self.entries.extend_from_slice(ents);
        }
    }

    pub fn slice(&mut self, lo: u64, hi: u64) -> Vec<Entry> {
        self.must_check_outofbounds(lo, hi);
        let l = lo as usize;
        let h = hi as usize;
        let off = self.offset as usize;
        return self.entries.drain(l - off..h - off).map(|e| e).collect();
    }

    pub fn must_check_outofbounds(&self, lo: u64, hi: u64) {
        if lo > hi {
            panic!("invalid unstable.slice {} > {}", lo, hi)
        }
        let upper = self.offset + self.entries.len() as u64;
        if lo < self.offset || hi > upper {
            panic!("unstable.slice[{}, {}] out of bound[{}, {}]",
                   lo,
                   hi,
                   self.offset,
                   upper)
        }
    }
}

#[cfg(test)]
mod test {
    use proto::raftpb::{Entry, Snapshot};
    use raft::log_unstable::Unstable;

    fn new_entry(index: u64, term: u64) -> Entry {
        let mut e = Entry::new();
        e.set_Term(term);
        e.set_Index(index);
        e
    }

    fn new_snapshot(index: u64, term: u64) -> Snapshot {
        use proto::raftpb::{SnapshotMetadata, Snapshot};
        let mut snap = Snapshot::new();
        let mut meta = SnapshotMetadata::new();
        meta.set_index(index);
        meta.set_term(term);
        snap.set_metadata(meta);
        snap
    }

    #[test]
    fn test_maybe_first_index() {
        // entry, offset, snap, wok, windex,
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, bool, u64)> = vec![
            // no snapshot
            (Some(new_entry(5,1)), 5, None, false, 0),
            (None, 0, None, false, 0),
            // has snapshot
            (Some(new_entry(5, 1)), 5, Some(new_snapshot(4,1)), true, 5),
            (None, 5, Some(new_snapshot(4,1)), true, 5),
        ];

        for (entries, offset, snapshot, wok, windex) in tests {
            let u = Unstable {
                entries: entries.map_or(vec![], |entry| vec![entry]),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            let index = u.maybe_first_index();
            match index {
                None => assert!(!wok),
                Some(index) => assert_eq!(index, windex),
            }
        }
    }

    #[test]
    fn test_maybe_last_index() {
        // entry, offset, snap, wok, windex,
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, bool, u64)> = vec![
            (Some(new_entry(5,1)), 5, None, true, 5),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), true, 5),
            // last in snapshot
            (None, 5, Some(new_snapshot(4,1)), true, 4),
            // empty unstable
            (None, 0, None, false, 0),
       ];

        for (entries, offset, snapshot, wok, windex) in tests {
            let u = Unstable {
                entries: entries.map_or(vec![], |entry| vec![entry]),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            let index = u.maybe_last_index();
            match index {
                None => assert!(!wok),
                Some(index) => assert_eq!(index, windex),
            }
        }
    }

    #[test]
    fn test_maybe_term() {
        // entry, offset, snap, index, wok, wterm
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, u64, bool, u64)> = vec![
            // term from entries
            (Some(new_entry(5,1)), 5, None, 5, true, 1),
            (Some(new_entry(5,1)), 5, None, 6, false, 0),
            (Some(new_entry(5,1)), 5, None, 4, false, 0),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 5, true, 1),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 6, false, 0),
            // term from snapshot
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 4, true, 1),
            (None, 5, Some(new_snapshot(4,1)), 5, false, 0),
            (None, 5, Some(new_snapshot(4,1)), 4, true, 1),
            (None, 0, None, 5, false, 0),
       ];

        for (entries, offset, snapshot, index, wok, wterm) in tests {
            let u = Unstable {
                entries: entries.map_or(vec![], |entry| vec![entry]),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            let term = u.maybe_term(index);
            match term {
                None => assert!(!wok),
                Some(term) => assert_eq!(term, wterm),
            }
        }
    }

    #[test]
    fn test_restore() {
        let mut u = Unstable {
            entries: vec![new_entry(5, 1)],
            offset: 5,
            snapshot: Some(Box::new(new_snapshot(4, 1))),
        };

        let s = new_snapshot(6, 2);
        u.restore(s.clone());

        assert_eq!(u.offset, s.get_metadata().get_index() + 1);
        assert_eq!(u.entries.len(), 0);
        assert_eq!(*u.snapshot.unwrap(), s);
    }

    #[test]
    fn test_stable_to() {
        // entries, offset, snap, index, term, woffset, wlen
        let tests: Vec<(Vec<Entry>, u64, Option<Snapshot>, u64, u64, u64, usize)> = vec![
            (vec![], 0, None, 5, 1, 0, 0),
            // stable to the first entry
            (vec![new_entry(5,1)], 5, None, 5, 1, 6, 0),
            (vec![new_entry(5,1), new_entry(6, 0)], 5, None, 5, 1, 6, 1),
            // stable to the first entry and term mismatch
            (vec![new_entry(6,2)], 5, None, 6, 1, 5, 1),
            // stable to old entry
            (vec![new_entry(5,1)], 5, None, 4, 1, 5, 1),
            (vec![new_entry(5,1)], 5, None, 4, 2, 5, 1),
            // with snapshot
            // stable to the first entry
            (vec![new_entry(5,1)], 5, Some(new_snapshot(4,1)), 5, 1, 6, 0),
            // stable to the first entry
            (vec![new_entry(5,1), new_entry(6,1)], 5, Some(new_snapshot(4,1)), 5, 1, 6, 1),
            // stable to the first entry and term mismatch
            (vec![new_entry(6,2)], 5, Some(new_snapshot(5,1)), 6, 1, 5, 1),
            // stable to snapshot
            (vec![new_entry(5,1)], 5, Some(new_snapshot(4,1)), 4, 1, 5, 1),
            // stable to old entry
            (vec![new_entry(5,2)], 5, Some(new_snapshot(4,2)), 4, 1, 5, 1),
       ];

        for (entries, offset, snapshot, index, term, woffset, wlen) in tests {
            let mut u = Unstable {
                entries: entries,
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            u.stable_to(index, term);
            assert_eq!(u.offset, woffset);
            assert_eq!(u.entries.len(), wlen);
        }
    }

    #[test]
    fn test_truncate_and_append() {
        // entries, offset, snap, to_append, woffset, wentries
        let tests: Vec<(Vec<Entry>,
                        u64,
                        Option<Snapshot>,
                        Vec<Entry>,
                        u64,
                        Vec<Entry>)> = vec![
            // replace to the end
            (vec![new_entry(5, 1)], 5, None,
                vec![new_entry(6, 1), new_entry(7, 1)],
                    5, vec![new_entry(5,1), new_entry(6,1), new_entry(7,1)]),

            // replace to unstable entries
           (vec![new_entry(5, 1)], 5, None,
               vec![new_entry(5, 2), new_entry(6, 2)],
                   5, vec![new_entry(5, 2), new_entry(6, 2)]),

            (vec![new_entry(5, 1)], 5, None,
                vec![new_entry(4, 2), new_entry(5, 2), new_entry(6, 2)],
                    4, vec![new_entry(4,2), new_entry(5, 2), new_entry(6, 2)]),

            // truncate existing entries and append
           (vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 1)], 5, None,
               vec![new_entry(6, 2)],
                   5, vec![new_entry(5, 1), new_entry(6, 2)]),

            (vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 1)], 5, None,
                vec![new_entry(7, 2), new_entry(8, 2)],
                    5, vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 2), new_entry(8, 2)]),
      ];

        for (entries, offset, snapshot, to_append, woffset, wentries) in tests {
            let mut u = Unstable {
                entries: entries,
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(Box::new(snap))),
            };
            u.truncate_and_append(&to_append);
            assert_eq!(u.offset, woffset);
            assert_eq!(u.entries, wentries);
        }
    }
}
<commit_msg>Tiny clean up<commit_after>#![allow(dead_code)]

use proto::raftpb::{Entry, Snapshot};
use std::ops::RangeTo;

// unstable.entris[i] has raft log position i+unstable.offset.
// Note that unstable.offset may be less than the highest log
// position in storage; this means that the next write to storage
// might need to truncate the log before persisting unstable.entries.
#[derive(Debug, PartialEq)]
pub struct Unstable {
    // the incoming unstable snapshot, if any.
    pub snapshot: Option<Snapshot>,
    // all entries that have not yet been written to storage.
    pub entries: Vec<Entry>,
    pub offset: u64,
}

impl Unstable {
    pub fn new(offset: u64) -> Unstable {
        Unstable {
            offset: offset,
            snapshot: None,
            entries: vec![],
        }
    }
    // maybe_first_index returns the last index if it has at least one
    // unstable entry or snapshot.
    pub fn maybe_first_index(&self) -> Option<u64> {
        self.snapshot
            .as_ref()
            .map_or(None, |snap| Some(snap.get_metadata().get_index() + 1))
    }

    pub fn get_snapshot(&self) -> Snapshot {
        return self.snapshot.as_ref().unwrap().clone();
    }

    // maybe_last_index returns the last index if it has at least one
    // unstable entry or snapshot.
    pub fn maybe_last_index(&self) -> Option<u64> {
        match self.entries.len() {
            0 => {
                self.snapshot
                    .as_ref()
                    .map_or(None, |snap| Some(snap.get_metadata().get_index()))
            }
            len => Some(self.offset + len as u64 - 1),
        }
    }

    // maybe_term returns the term of the entry at index idx, if there
    // is any.
    pub fn maybe_term(&self, idx: u64) -> Option<u64> {
        if idx < self.offset {
            if self.snapshot.is_none() {
                return None;
            }

            let meta = self.snapshot.as_ref().unwrap().get_metadata().clone();
            if idx == meta.get_index() {
                return Some(meta.get_term());
            }
            return None;
        }
        match self.maybe_last_index() {
            None => None,
            Some(last) => {
                if idx > last {
                    return None;
                }
                Some(self.entries[(idx - self.offset) as usize].get_Term())
            }
        }
    }

    pub fn stable_to(&mut self, idx: u64, term: u64) {
        let t = self.maybe_term(idx);
        if t.is_none() {
            return;
        }

        if t.unwrap() == term && idx >= self.offset {
            let start = idx + 1 - self.offset;
            self.entries.drain(RangeTo { end: start as usize });
            self.offset = idx + 1;
        }
    }

    pub fn stable_snap_to(&mut self, idx: u64) {
        if self.snapshot.is_none() {
            return;
        }
        if idx == self.snapshot.as_ref().unwrap().get_metadata().get_index() {
            self.snapshot = None;
        }
    }

    pub fn restore(&mut self, snap: Snapshot) {
        self.entries.clear();
        self.offset = snap.get_metadata().get_index() + 1;
        self.snapshot = Some(snap.clone());
    }

    pub fn truncate_and_append(&mut self, ents: &[Entry]) {
        let after = ents[0].get_Index() - 1;
        if after == self.offset + self.entries.len() as u64 - 1 {
            self.entries.extend_from_slice(ents);
        } else if after < self.offset {
            // The log is being truncated to before our current offset
            // portion, so set the offset and replace the entries
            self.offset = after + 1;
            self.entries.clear();
            self.entries.extend_from_slice(ents);
        } else {
            // truncate to after and copy to self.entries
            // then append
            let off = self.offset.clone();
            let cut_ents = &self.slice(off, after + 1);
            self.entries = vec![];
            self.entries.extend_from_slice(cut_ents);
            self.entries.extend_from_slice(ents);
        }
    }

    pub fn slice(&mut self, lo: u64, hi: u64) -> Vec<Entry> {
        self.must_check_outofbounds(lo, hi);
        let l = lo as usize;
        let h = hi as usize;
        let off = self.offset as usize;
        return self.entries.drain(l - off..h - off).map(|e| e).collect();
    }

    pub fn must_check_outofbounds(&self, lo: u64, hi: u64) {
        if lo > hi {
            panic!("invalid unstable.slice {} > {}", lo, hi)
        }
        let upper = self.offset + self.entries.len() as u64;
        if lo < self.offset || hi > upper {
            panic!("unstable.slice[{}, {}] out of bound[{}, {}]",
                   lo,
                   hi,
                   self.offset,
                   upper)
        }
    }
}

#[cfg(test)]
mod test {
    use proto::raftpb::{Entry, Snapshot};
    use raft::log_unstable::Unstable;

    fn new_entry(index: u64, term: u64) -> Entry {
        let mut e = Entry::new();
        e.set_Term(term);
        e.set_Index(index);
        e
    }

    fn new_snapshot(index: u64, term: u64) -> Snapshot {
        use proto::raftpb::{SnapshotMetadata, Snapshot};
        let mut snap = Snapshot::new();
        let mut meta = SnapshotMetadata::new();
        meta.set_index(index);
        meta.set_term(term);
        snap.set_metadata(meta);
        snap
    }

    #[test]
    fn test_maybe_first_index() {
        // entry, offset, snap, wok, windex,
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, bool, u64)> = vec![
            // no snapshot
            (Some(new_entry(5,1)), 5, None, false, 0),
            (None, 0, None, false, 0),
            // has snapshot
            (Some(new_entry(5, 1)), 5, Some(new_snapshot(4,1)), true, 5),
            (None, 5, Some(new_snapshot(4,1)), true, 5),
        ];

        for (entries, offset, snapshot, wok, windex) in tests {
            let u = Unstable {
                entries: entries.map_or(vec![], |entry| vec![entry]),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(snap)),
            };
            let index = u.maybe_first_index();
            match index {
                None => assert!(!wok),
                Some(index) => assert_eq!(index, windex),
            }
        }
    }

    #[test]
    fn test_maybe_last_index() {
        // entry, offset, snap, wok, windex,
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, bool, u64)> = vec![
            (Some(new_entry(5,1)), 5, None, true, 5),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), true, 5),
            // last in snapshot
            (None, 5, Some(new_snapshot(4,1)), true, 4),
            // empty unstable
            (None, 0, None, false, 0),
       ];

        for (entries, offset, snapshot, wok, windex) in tests {
            let u = Unstable {
                entries: entries.map_or(vec![], |entry| vec![entry]),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(snap)),
            };
            let index = u.maybe_last_index();
            match index {
                None => assert!(!wok),
                Some(index) => assert_eq!(index, windex),
            }
        }
    }

    #[test]
    fn test_maybe_term() {
        // entry, offset, snap, index, wok, wterm
        let tests: Vec<(Option<Entry>, u64, Option<Snapshot>, u64, bool, u64)> = vec![
            // term from entries
            (Some(new_entry(5,1)), 5, None, 5, true, 1),
            (Some(new_entry(5,1)), 5, None, 6, false, 0),
            (Some(new_entry(5,1)), 5, None, 4, false, 0),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 5, true, 1),
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 6, false, 0),
            // term from snapshot
            (Some(new_entry(5,1)), 5, Some(new_snapshot(4,1)), 4, true, 1),
            (None, 5, Some(new_snapshot(4,1)), 5, false, 0),
            (None, 5, Some(new_snapshot(4,1)), 4, true, 1),
            (None, 0, None, 5, false, 0),
       ];

        for (entries, offset, snapshot, index, wok, wterm) in tests {
            let u = Unstable {
                entries: entries.map_or(vec![], |entry| vec![entry]),
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(snap)),
            };
            let term = u.maybe_term(index);
            match term {
                None => assert!(!wok),
                Some(term) => assert_eq!(term, wterm),
            }
        }
    }

    #[test]
    fn test_restore() {
        let mut u = Unstable {
            entries: vec![new_entry(5, 1)],
            offset: 5,
            snapshot: Some(new_snapshot(4, 1)),
        };

        let s = new_snapshot(6, 2);
        u.restore(s.clone());

        assert_eq!(u.offset, s.get_metadata().get_index() + 1);
        assert_eq!(u.entries.len(), 0);
        assert_eq!(u.snapshot.unwrap(), s);
    }

    #[test]
    fn test_stable_to() {
        // entries, offset, snap, index, term, woffset, wlen
        let tests: Vec<(Vec<Entry>, u64, Option<Snapshot>, u64, u64, u64, usize)> = vec![
            (vec![], 0, None, 5, 1, 0, 0),
            // stable to the first entry
            (vec![new_entry(5,1)], 5, None, 5, 1, 6, 0),
            (vec![new_entry(5,1), new_entry(6, 0)], 5, None, 5, 1, 6, 1),
            // stable to the first entry and term mismatch
            (vec![new_entry(6,2)], 5, None, 6, 1, 5, 1),
            // stable to old entry
            (vec![new_entry(5,1)], 5, None, 4, 1, 5, 1),
            (vec![new_entry(5,1)], 5, None, 4, 2, 5, 1),
            // with snapshot
            // stable to the first entry
            (vec![new_entry(5,1)], 5, Some(new_snapshot(4,1)), 5, 1, 6, 0),
            // stable to the first entry
            (vec![new_entry(5,1), new_entry(6,1)], 5, Some(new_snapshot(4,1)), 5, 1, 6, 1),
            // stable to the first entry and term mismatch
            (vec![new_entry(6,2)], 5, Some(new_snapshot(5,1)), 6, 1, 5, 1),
            // stable to snapshot
            (vec![new_entry(5,1)], 5, Some(new_snapshot(4,1)), 4, 1, 5, 1),
            // stable to old entry
            (vec![new_entry(5,2)], 5, Some(new_snapshot(4,2)), 4, 1, 5, 1),
       ];

        for (entries, offset, snapshot, index, term, woffset, wlen) in tests {
            let mut u = Unstable {
                entries: entries,
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(snap)),
            };
            u.stable_to(index, term);
            assert_eq!(u.offset, woffset);
            assert_eq!(u.entries.len(), wlen);
        }
    }

    #[test]
    fn test_truncate_and_append() {
        // entries, offset, snap, to_append, woffset, wentries
        let tests: Vec<(Vec<Entry>,
                        u64,
                        Option<Snapshot>,
                        Vec<Entry>,
                        u64,
                        Vec<Entry>)> = vec![
            // replace to the end
            (vec![new_entry(5, 1)], 5, None,
                vec![new_entry(6, 1), new_entry(7, 1)],
                    5, vec![new_entry(5,1), new_entry(6,1), new_entry(7,1)]),

            // replace to unstable entries
           (vec![new_entry(5, 1)], 5, None,
               vec![new_entry(5, 2), new_entry(6, 2)],
                   5, vec![new_entry(5, 2), new_entry(6, 2)]),

            (vec![new_entry(5, 1)], 5, None,
                vec![new_entry(4, 2), new_entry(5, 2), new_entry(6, 2)],
                    4, vec![new_entry(4,2), new_entry(5, 2), new_entry(6, 2)]),

            // truncate existing entries and append
           (vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 1)], 5, None,
               vec![new_entry(6, 2)],
                   5, vec![new_entry(5, 1), new_entry(6, 2)]),

            (vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 1)], 5, None,
                vec![new_entry(7, 2), new_entry(8, 2)],
                    5, vec![new_entry(5, 1), new_entry(6, 1), new_entry(7, 2), new_entry(8, 2)]),
      ];

        for (entries, offset, snapshot, to_append, woffset, wentries) in tests {
            let mut u = Unstable {
                entries: entries,
                offset: offset,
                snapshot: snapshot.map_or(None, |snap| Some(snap)),
            };
            u.truncate_and_append(&to_append);
            assert_eq!(u.offset, woffset);
            assert_eq!(u.entries, wentries);
        }
    }
}
<|endoftext|>


<commit_before>use csv::{Reader, ReaderBuilder};
use std::io;

pub struct CsvReader<T> {
  reader: Reader<T>,
  headers: bool,
}

impl<T: io::Read> CsvReader<T> {
  pub fn new(reader: T, delimiter: u8, headers: bool) -> CsvReader<T> {
    let reader = ReaderBuilder::new()
      .delimiter(delimiter)
      .has_headers(false)
      .from_reader(reader);

    CsvReader { reader, headers }
  }
}

impl<T: io::Read> crate::Read for CsvReader<T> {
  fn read(&mut self) -> Result<crate::Table, crate::Error> {
    let mut table = crate::Table::with_headers(self.headers);

    for result in self.reader.records() {
      match result {
        Ok(record) => {
          let row: Vec<String> = record.iter().map(|field| String::from(field)).collect();
          table.push_row(row);
        }
        Err(_) => {
          return Err(crate::Error {
            kind: crate::ErrorKind::Read,
          });
        }
      }
    }

    Ok(table)
  }
}

mod tests {
  use super::*;
  use crate::Read;

  #[test]
  fn read() {
    let test_cases = vec![
      (
        "alice\t80",
        false,
        crate::Table::from(vec![vec![String::from("alice"), String::from("80")]], false),
      ),
      (
        "alice\t80\nbob\t100",
        false,
        crate::Table::from(
          vec![
            vec![String::from("alice"), String::from("80")],
            vec![String::from("bob"), String::from("100")],
          ],
          false,
        ),
      ),
      (
        "name\tscore\nalice\t80",
        true,
        crate::Table::from(
          vec![
            vec![String::from("name"), String::from("score")],
            vec![String::from("alice"), String::from("80")],
          ],
          true,
        ),
      ),
    ];

    for test_case in test_cases {
      let mut reader = CsvReader::new(test_case.0.as_bytes(), b'\t', test_case.1);
      let table = reader.read().expect("failed to read table");
      assert_eq!(table, test_case.2);
    }
  }
}
<commit_msg>Suppress false positive warnings<commit_after>use csv::{Reader, ReaderBuilder};
use std::io;

pub struct CsvReader<T> {
  reader: Reader<T>,
  headers: bool,
}

impl<T: io::Read> CsvReader<T> {
  pub fn new(reader: T, delimiter: u8, headers: bool) -> CsvReader<T> {
    let reader = ReaderBuilder::new()
      .delimiter(delimiter)
      .has_headers(false)
      .from_reader(reader);

    CsvReader { reader, headers }
  }
}

impl<T: io::Read> crate::Read for CsvReader<T> {
  fn read(&mut self) -> Result<crate::Table, crate::Error> {
    let mut table = crate::Table::with_headers(self.headers);

    for result in self.reader.records() {
      match result {
        Ok(record) => {
          let row: Vec<String> = record.iter().map(|field| String::from(field)).collect();
          table.push_row(row);
        }
        Err(_) => {
          return Err(crate::Error {
            kind: crate::ErrorKind::Read,
          });
        }
      }
    }

    Ok(table)
  }
}

mod tests {
  #[allow(unused)]
  use super::*;
  #[allow(unused)]
  use crate::Read;

  #[test]
  fn read() {
    let test_cases = vec![
      (
        "alice\t80",
        false,
        crate::Table::from(vec![vec![String::from("alice"), String::from("80")]], false),
      ),
      (
        "alice\t80\nbob\t100",
        false,
        crate::Table::from(
          vec![
            vec![String::from("alice"), String::from("80")],
            vec![String::from("bob"), String::from("100")],
          ],
          false,
        ),
      ),
      (
        "name\tscore\nalice\t80",
        true,
        crate::Table::from(
          vec![
            vec![String::from("name"), String::from("score")],
            vec![String::from("alice"), String::from("80")],
          ],
          true,
        ),
      ),
    ];

    for test_case in test_cases {
      let mut reader = CsvReader::new(test_case.0.as_bytes(), b'\t', test_case.1);
      let table = reader.read().expect("failed to read table");
      assert_eq!(table, test_case.2);
    }
  }
}
<|endoftext|>


<commit_before>use core::num::{IntErrorKind, NonZeroU8, NonZeroU32, NonZeroI32, ParseIntError};
use core::option::Option::{self, Some, None};
use std::mem::size_of;

#[test]
fn test_create_nonzero_instance() {
    let _a = unsafe {
        NonZeroU32::new_unchecked(21)
    };
}

#[test]
fn test_size_nonzero_in_option() {
    assert_eq!(size_of::<NonZeroU32>(), size_of::<Option<NonZeroU32>>());
    assert_eq!(size_of::<NonZeroI32>(), size_of::<Option<NonZeroI32>>());
}

#[test]
fn test_match_on_nonzero_option() {
    let a = Some(unsafe {
        NonZeroU32::new_unchecked(42)
    });
    match a {
        Some(val) => assert_eq!(val.get(), 42),
        None => panic!("unexpected None while matching on Some(NonZeroU32(_))")
    }

    match unsafe { Some(NonZeroU32::new_unchecked(43)) } {
        Some(val) => assert_eq!(val.get(), 43),
        None => panic!("unexpected None while matching on Some(NonZeroU32(_))")
    }
}

#[test]
fn test_match_option_empty_vec() {
    let a: Option<Vec<isize>> = Some(vec![]);
    match a {
        None => panic!("unexpected None while matching on Some(vec![])"),
        _ => {}
    }
}

#[test]
fn test_match_option_vec() {
    let a = Some(vec![1, 2, 3, 4]);
    match a {
        Some(v) => assert_eq!(v, [1, 2, 3, 4]),
        None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
    }
}

#[test]
fn test_match_option_rc() {
    use std::rc::Rc;

    let five = Rc::new(5);
    match Some(five) {
        Some(r) => assert_eq!(*r, 5),
        None => panic!("unexpected None while matching on Some(Rc::new(5))")
    }
}

#[test]
fn test_match_option_arc() {
    use std::sync::Arc;

    let five = Arc::new(5);
    match Some(five) {
        Some(a) => assert_eq!(*a, 5),
        None => panic!("unexpected None while matching on Some(Arc::new(5))")
    }
}

#[test]
fn test_match_option_empty_string() {
    let a = Some(String::new());
    match a {
        None => panic!("unexpected None while matching on Some(String::new())"),
        _ => {}
    }
}

#[test]
fn test_match_option_string() {
    let five = "Five".to_string();
    match Some(five) {
        Some(s) => assert_eq!(s, "Five"),
        None => panic!("unexpected None while matching on Some(String { ... })")
    }
}

mod atom {
    use core::num::NonZeroU32;

    #[derive(PartialEq, Eq)]
    pub struct Atom {
        index: NonZeroU32, // private
    }
    pub const FOO_ATOM: Atom = Atom { index: unsafe { NonZeroU32::new_unchecked(7) } };
}

macro_rules! atom {
    ("foo") => { atom::FOO_ATOM }
}

#[test]
fn test_match_nonzero_const_pattern() {
    match atom!("foo") {
        // Using as a pattern is supported by the compiler:
        atom!("foo") => {}
        _ => panic!("Expected the const item as a pattern to match.")
    }
}

#[test]
fn test_from_nonzero() {
    let nz = NonZeroU32::new(1).unwrap();
    let num: u32 = nz.into();
    assert_eq!(num, 1u32);
}

#[test]
fn test_from_signed_nonzero() {
    let nz = NonZeroI32::new(1).unwrap();
    let num: i32 = nz.into();
    assert_eq!(num, 1i32);
}

#[test]
fn test_from_str() {
    assert_eq!("123".parse::<NonZeroU8>(), Ok(NonZeroU8::new(123).unwrap()));
    assert_eq!(
        "0".parse::<NonZeroU8>(),
        Err(ParseIntError {
            kind: IntErrorKind::Zero
        })
    );
    assert_eq!(
        "-1".parse::<NonZeroU8>(),
        Err(ParseIntError {
            kind: IntErrorKind::Underflow
        })
    );
    assert_eq!(
        "257".parse::<NonZeroU8>(),
        Err(ParseIntError {
            kind: IntErrorKind::Overflow
        })
    );
}
<commit_msg>fixed tests again<commit_after>use core::num::{IntErrorKind, NonZeroI32, NonZeroI8, NonZeroU32, NonZeroU8};
use core::option::Option::{self, None, Some};
use std::mem::size_of;

#[test]
fn test_create_nonzero_instance() {
    let _a = unsafe {
        NonZeroU32::new_unchecked(21)
    };
}

#[test]
fn test_size_nonzero_in_option() {
    assert_eq!(size_of::<NonZeroU32>(), size_of::<Option<NonZeroU32>>());
    assert_eq!(size_of::<NonZeroI32>(), size_of::<Option<NonZeroI32>>());
}

#[test]
fn test_match_on_nonzero_option() {
    let a = Some(unsafe {
        NonZeroU32::new_unchecked(42)
    });
    match a {
        Some(val) => assert_eq!(val.get(), 42),
        None => panic!("unexpected None while matching on Some(NonZeroU32(_))")
    }

    match unsafe { Some(NonZeroU32::new_unchecked(43)) } {
        Some(val) => assert_eq!(val.get(), 43),
        None => panic!("unexpected None while matching on Some(NonZeroU32(_))")
    }
}

#[test]
fn test_match_option_empty_vec() {
    let a: Option<Vec<isize>> = Some(vec![]);
    match a {
        None => panic!("unexpected None while matching on Some(vec![])"),
        _ => {}
    }
}

#[test]
fn test_match_option_vec() {
    let a = Some(vec![1, 2, 3, 4]);
    match a {
        Some(v) => assert_eq!(v, [1, 2, 3, 4]),
        None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
    }
}

#[test]
fn test_match_option_rc() {
    use std::rc::Rc;

    let five = Rc::new(5);
    match Some(five) {
        Some(r) => assert_eq!(*r, 5),
        None => panic!("unexpected None while matching on Some(Rc::new(5))")
    }
}

#[test]
fn test_match_option_arc() {
    use std::sync::Arc;

    let five = Arc::new(5);
    match Some(five) {
        Some(a) => assert_eq!(*a, 5),
        None => panic!("unexpected None while matching on Some(Arc::new(5))")
    }
}

#[test]
fn test_match_option_empty_string() {
    let a = Some(String::new());
    match a {
        None => panic!("unexpected None while matching on Some(String::new())"),
        _ => {}
    }
}

#[test]
fn test_match_option_string() {
    let five = "Five".to_string();
    match Some(five) {
        Some(s) => assert_eq!(s, "Five"),
        None => panic!("unexpected None while matching on Some(String { ... })")
    }
}

mod atom {
    use core::num::NonZeroU32;

    #[derive(PartialEq, Eq)]
    pub struct Atom {
        index: NonZeroU32, // private
    }
    pub const FOO_ATOM: Atom = Atom { index: unsafe { NonZeroU32::new_unchecked(7) } };
}

macro_rules! atom {
    ("foo") => { atom::FOO_ATOM }
}

#[test]
fn test_match_nonzero_const_pattern() {
    match atom!("foo") {
        // Using as a pattern is supported by the compiler:
        atom!("foo") => {}
        _ => panic!("Expected the const item as a pattern to match.")
    }
}

#[test]
fn test_from_nonzero() {
    let nz = NonZeroU32::new(1).unwrap();
    let num: u32 = nz.into();
    assert_eq!(num, 1u32);
}

#[test]
fn test_from_signed_nonzero() {
    let nz = NonZeroI32::new(1).unwrap();
    let num: i32 = nz.into();
    assert_eq!(num, 1i32);
}

#[test]
fn test_from_str() {
    assert_eq!("123".parse::<NonZeroU8>(), Ok(NonZeroU8::new(123).unwrap()));
    assert_eq!(
        "0".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
        Some(IntErrorKind::Zero)
    );
    assert_eq!(
        "-1".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
        Some(IntErrorKind::InvalidDigit)
    );
    assert_eq!(
        "-129".parse::<NonZeroI8>().err().map(|e| e.kind().clone()),
        Some(IntErrorKind::Underflow)
    );
    assert_eq!(
        "257".parse::<NonZeroU8>().err().map(|e| e.kind().clone()),
        Some(IntErrorKind::Overflow)
    );
}
<|endoftext|>


<commit_before>extern crate piston_window;

use piston_window::*;

fn main() {
    let window: PistonWindow = WindowSettings::new("Hello Piston!", [640, 480])
        .exit_on_esc(true)
        .build()
        .unwrap();
    println!("Press any button to enter inner loop");
    for e in window {
        e.draw_2d(|_c, g| {
            clear([0.5, 1.0, 0.5, 1.0], g);
        });

        if let Some(button) = e.press_args() {
            println!("Pressed {:?}", button);
            println!("Press X to exit inner loop");
            for e in e.clone() {
                e.draw_2d(|_c, g| {
                    clear([0.5, 0.5, 1.0, 1.0], g);
                });

                // Inner loop.
                if let Some(Button::Keyboard(Key::X)) = e.press_args() {
                    break;
                }
            }
            println!("You have exited the inner loop");
        }
    }
}
<commit_msg>Update the example<commit_after>extern crate piston_window;

use piston_window::*;

fn main() {
    let window: PistonWindow = WindowSettings::new("Hello Piston!", [640, 480])
        .exit_on_esc(true)
        .build()
        .unwrap_or_else(|e| { panic!("Failed to build PistonWindow: {}", e) });
    println!("Press any button to enter inner loop");
    for e in window {
        e.draw_2d(|_c, g| {
            clear([0.5, 1.0, 0.5, 1.0], g);
        });

        if let Some(button) = e.press_args() {
            println!("Pressed {:?}", button);
            println!("Press X to exit inner loop");
            for e in e.clone() {
                e.draw_2d(|_c, g| {
                    clear([0.5, 0.5, 1.0, 1.0], g);
                });

                // Inner loop.
                if let Some(Button::Keyboard(Key::X)) = e.press_args() {
                    break;
                }
            }
            println!("You have exited the inner loop");
        }
    }
}
<|endoftext|>


<commit_before>use std::fmt;

use futures::{Async, Poll, Stream};
use futures::sync::mpsc;

/// Body stream
pub struct Body<T, E> {
    inner: Option<mpsc::Receiver<Result<T, E>>>,
}

impl<T, E> Body<T, E> {
    /// Return an empty body stream
    pub fn empty() -> Body<T, E> {
        Body { inner: None }
    }

    /// Return a body stream with an associated sender half
    pub fn pair() -> (mpsc::Sender<Result<T, E>>, Body<T, E>) {
        let (tx, rx) = mpsc::channel(0);
        let rx = Body { inner: Some(rx) };
        (tx, rx)
    }
}

impl<T, E> Stream for Body<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<Option<T>, E> {
        match self.inner {
            Some(ref mut s) => {
                match s.poll().unwrap() {
                    Async::Ready(None) => Ok(Async::Ready(None)),
                    Async::Ready(Some(Ok(e))) => Ok(Async::Ready(Some(e))),
                    Async::Ready(Some(Err(e))) => Err(e),
                    Async::NotReady => Ok(Async::NotReady),
                }
            }
            None => Ok(Async::Ready(None)),
        }
    }
}

impl<T, E> From<mpsc::Receiver<Result<T, E>>> for Body<T, E> {
    fn from(src: mpsc::Receiver<Result<T, E>>) -> Body<T, E> {
        Body { inner: Some(src) }
    }
}

impl<T, E> fmt::Debug for Body<T, E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Body {{ [stream of values] }}")
    }
}
<commit_msg>add Body::from(T) for immediate bodies<commit_after>use std::fmt;

use futures::{Async, Poll, Stream};
use futures::sync::mpsc;

/// Body stream
pub struct Body<T, E> {
    inner: Inner<T, E>,
}

enum Inner<T, E> {
    Once(Option<T>),
    Stream(mpsc::Receiver<Result<T, E>>),
    Empty,
}

impl<T, E> Body<T, E> {
    /// Return an empty body stream
    pub fn empty() -> Body<T, E> {
        Body { inner: Inner::Empty }
    }

    /// Return a body stream with an associated sender half
    pub fn pair() -> (mpsc::Sender<Result<T, E>>, Body<T, E>) {
        let (tx, rx) = mpsc::channel(0);
        let rx = Body { inner: Inner::Stream(rx) };
        (tx, rx)
    }
}

impl<T, E> Stream for Body<T, E> {
    type Item = T;
    type Error = E;

    fn poll(&mut self) -> Poll<Option<T>, E> {
        match self.inner {
            Inner::Once(ref mut val) => Ok(Async::Ready(val.take())),
            Inner::Stream(ref mut s) => {
                match s.poll().unwrap() {
                    Async::Ready(None) => Ok(Async::Ready(None)),
                    Async::Ready(Some(Ok(e))) => Ok(Async::Ready(Some(e))),
                    Async::Ready(Some(Err(e))) => Err(e),
                    Async::NotReady => Ok(Async::NotReady),
                }
            }
            Inner::Empty => Ok(Async::Ready(None)),
        }
    }
}

impl<T, E> From<mpsc::Receiver<Result<T, E>>> for Body<T, E> {
    fn from(src: mpsc::Receiver<Result<T, E>>) -> Body<T, E> {
        Body { inner: Inner::Stream(src) }
    }
}

impl<T, E> From<T> for Body<T, E> {
    fn from(val: T) -> Body<T, E> {
        Body { inner: Inner::Once(Some(val)) }
    }
}

impl<T, E> fmt::Debug for Body<T, E> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        write!(fmt, "Body {{ [stream of values] }}")
    }
}
<|endoftext|>


<commit_before>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use cli::client_proxy::ClientProxy;
use diem_client::BlockingClient;
use diem_config::config::NodeConfig;
use diem_temppath::TempPath;
use diem_types::{chain_id::ChainId, waypoint::Waypoint};
use nix::{
    sys::signal::{kill, SIGKILL},
    unistd::Pid,
};
use std::{fmt, fs::File, path::PathBuf, process::Stdio, time::Duration};

#[derive(Debug)]
pub struct NodeInfo {
    pub chain_id: ChainId,
    pub json_rpc: String,
    pub root_key_path: PathBuf,
    pub waypoint: Waypoint,
    pub local_node_info: Option<LocalNodeInfo>,
}

#[derive(Debug)]
pub struct LocalNodeInfo {
    pub log_path: PathBuf,
    pub config_path: TempPath,
    node_pid: Pid,
}

fn diem_root_folder() -> PathBuf {
    let mut diem_root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    diem_root_dir.pop();
    diem_root_dir.pop();
    diem_root_dir.pop();
    diem_root_dir
}

fn wait_till_healthy(json_rpc: &str) {
    let client = BlockingClient::new(json_rpc);
    loop {
        if client.get_metadata().is_ok() {
            break;
        }
        std::thread::sleep(Duration::from_millis(10));
    }
}

impl NodeInfo {
    pub fn new_local() -> Self {
        let config_temp_path = diem_temppath::TempPath::new();
        let config_path = config_temp_path.as_ref().to_path_buf();
        std::fs::DirBuilder::new()
            .recursive(true)
            .create(&config_path)
            .unwrap();
        let config_path = config_path.canonicalize().unwrap();

        // Build a single validator network
        let template = NodeConfig::default_for_validator();
        let builder =
            diem_genesis_tool::config_builder::ValidatorBuilder::new(1, template, &config_path)
                .randomize_first_validator_ports(true);
        let test_config =
            diem_genesis_tool::swarm_config::SwarmConfig::build(&builder, &config_path).unwrap();

        let mut log_file = config_path.clone();
        log_file.push("validator.log");
        let log = File::create(log_file.as_path()).unwrap();

        let child_pid = std::process::Command::new("cargo")
            .args(&[
                "run",
                "--bin",
                "diem-node",
                "--",
                "--config",
                test_config.config_files[0].as_os_str().to_str().unwrap(),
            ])
            .current_dir(diem_root_folder())
            .stderr(log)
            .stdout(Stdio::null())
            .spawn()
            .unwrap()
            .id();

        let config = NodeConfig::load(&test_config.config_files[0]).unwrap();
        let json_rpc = format!("http://localhost:{}", config.json_rpc.address.port());

        wait_till_healthy(json_rpc.as_str());

        NodeInfo {
            chain_id: ChainId::test(),
            json_rpc,
            root_key_path: test_config.diem_root_key_path,
            waypoint: test_config.waypoint,
            local_node_info: Some(LocalNodeInfo {
                log_path: log_file,
                config_path: config_temp_path,
                node_pid: Pid::from_raw(child_pid as i32),
            }),
        }
    }

    pub fn get_client(&self) -> ClientProxy {
        let root_key = self.root_key_path.to_str().unwrap();
        ClientProxy::new(
            self.chain_id,
            self.json_rpc.as_str(),
            root_key,
            root_key,
            root_key,
            false,
            None,
            None,
            self.waypoint,
            false,
        )
        .expect("Failed to spawn a client from the NodeInfo")
    }
}

impl Drop for LocalNodeInfo {
    fn drop(&mut self) {
        kill(self.node_pid, Some(SIGKILL)).unwrap();
    }
}

impl fmt::Display for NodeInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "json-rpc endpoint: {}", self.json_rpc)?;
        writeln!(f, "waypoint: {}", self.waypoint)?;
        writeln!(f, "chain-id: {}", self.chain_id)?;
        writeln!(f, "root-key path: {:?}", self.root_key_path)?;
        if let Some(info) = &self.local_node_info {
            writeln!(f, "config path: {:?}", info.config_path.path())?;
            writeln!(f, "log path: {:?}", info.log_path)?;
        }
        Ok(())
    }
}
<commit_msg>oncall-trainer: convert to using the new ValidatorBuilder<commit_after>// Copyright (c) The Diem Core Contributors
// SPDX-License-Identifier: Apache-2.0

use cli::client_proxy::ClientProxy;
use diem_client::BlockingClient;
use diem_config::config::NodeConfig;
use diem_temppath::TempPath;
use diem_types::{chain_id::ChainId, waypoint::Waypoint};
use nix::{
    sys::signal::{kill, SIGKILL},
    unistd::Pid,
};
use std::{fmt, fs::File, path::PathBuf, process::Stdio, time::Duration};

#[derive(Debug)]
pub struct NodeInfo {
    pub chain_id: ChainId,
    pub json_rpc: String,
    pub root_key_path: PathBuf,
    pub waypoint: Waypoint,
    pub local_node_info: Option<LocalNodeInfo>,
}

#[derive(Debug)]
pub struct LocalNodeInfo {
    pub log_path: PathBuf,
    pub config_path: TempPath,
    node_pid: Pid,
}

fn diem_root_folder() -> PathBuf {
    let mut diem_root_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
    diem_root_dir.pop();
    diem_root_dir.pop();
    diem_root_dir.pop();
    diem_root_dir
}

fn wait_till_healthy(json_rpc: &str) {
    let client = BlockingClient::new(json_rpc);
    loop {
        if client.get_metadata().is_ok() {
            break;
        }
        std::thread::sleep(Duration::from_millis(10));
    }
}

impl NodeInfo {
    pub fn new_local() -> Self {
        let config_temp_path = diem_temppath::TempPath::new();
        let config_path = config_temp_path.as_ref().to_path_buf();
        std::fs::DirBuilder::new()
            .recursive(true)
            .create(&config_path)
            .unwrap();
        let config_path = config_path.canonicalize().unwrap();

        // Build a single validator network
        let template = NodeConfig::default_for_validator();
        let builder = diem_genesis_tool::validator_builder::ValidatorBuilder::new(&config_path)
            .num_validators(1)
            .template(template)
            .randomize_first_validator_ports(true);
        let test_config =
            diem_genesis_tool::swarm_config::SwarmConfig::build(&builder, &config_path).unwrap();

        let mut log_file = config_path;
        log_file.push("validator.log");
        let log = File::create(log_file.as_path()).unwrap();

        let child_pid = std::process::Command::new("cargo")
            .args(&[
                "run",
                "--bin",
                "diem-node",
                "--",
                "--config",
                test_config.config_files[0].as_os_str().to_str().unwrap(),
            ])
            .current_dir(diem_root_folder())
            .stderr(log)
            .stdout(Stdio::null())
            .spawn()
            .unwrap()
            .id();

        let config = NodeConfig::load(&test_config.config_files[0]).unwrap();
        let json_rpc = format!("http://localhost:{}", config.json_rpc.address.port());

        wait_till_healthy(json_rpc.as_str());

        NodeInfo {
            chain_id: ChainId::test(),
            json_rpc,
            root_key_path: test_config.diem_root_key_path,
            waypoint: test_config.waypoint,
            local_node_info: Some(LocalNodeInfo {
                log_path: log_file,
                config_path: config_temp_path,
                node_pid: Pid::from_raw(child_pid as i32),
            }),
        }
    }

    pub fn get_client(&self) -> ClientProxy {
        let root_key = self.root_key_path.to_str().unwrap();
        ClientProxy::new(
            self.chain_id,
            self.json_rpc.as_str(),
            root_key,
            root_key,
            root_key,
            false,
            None,
            None,
            self.waypoint,
            false,
        )
        .expect("Failed to spawn a client from the NodeInfo")
    }
}

impl Drop for LocalNodeInfo {
    fn drop(&mut self) {
        kill(self.node_pid, Some(SIGKILL)).unwrap();
    }
}

impl fmt::Display for NodeInfo {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        writeln!(f, "json-rpc endpoint: {}", self.json_rpc)?;
        writeln!(f, "waypoint: {}", self.waypoint)?;
        writeln!(f, "chain-id: {}", self.chain_id)?;
        writeln!(f, "root-key path: {:?}", self.root_key_path)?;
        if let Some(info) = &self.local_node_info {
            writeln!(f, "config path: {:?}", info.config_path.path())?;
            writeln!(f, "log path: {:?}", info.log_path)?;
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use crate::namespace::Namespace;
use rustc::traits::{self, IntercrateMode, SkipLeakCheck};
use rustc::ty::TyCtxt;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor;

pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
    assert_eq!(crate_num, LOCAL_CRATE);
    let krate = tcx.hir().krate();
    krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
}

struct InherentOverlapChecker<'tcx> {
    tcx: TyCtxt<'tcx>,
}

impl InherentOverlapChecker<'tcx> {
    fn check_for_common_items_in_impls(
        &self,
        impl1: DefId,
        impl2: DefId,
        overlap: traits::OverlapResult<'_>,
    ) {
        let name_and_namespace =
            |assoc: &AssocItem| (assoc.ident.modern(), Namespace::from(assoc.kind));

        let impl_items1 = self.tcx.associated_items(impl1);
        let impl_items2 = self.tcx.associated_items(impl2);

        for item1 in &impl_items1[..] {
            let (name, namespace) = name_and_namespace(item1);

            for item2 in &impl_items2[..] {
                if (name, namespace) == name_and_namespace(item2) {
                    let mut err = struct_span_err!(
                        self.tcx.sess,
                        self.tcx.span_of_impl(item1.def_id).unwrap(),
                        E0592,
                        "duplicate definitions with name `{}`",
                        name
                    );
                    err.span_label(
                        self.tcx.span_of_impl(item1.def_id).unwrap(),
                        format!("duplicate definitions for `{}`", name),
                    );
                    err.span_label(
                        self.tcx.span_of_impl(item2.def_id).unwrap(),
                        format!("other definition for `{}`", name),
                    );

                    for cause in &overlap.intercrate_ambiguity_causes {
                        cause.add_intercrate_ambiguity_hint(&mut err);
                    }

                    if overlap.involves_placeholder {
                        traits::add_placeholder_note(&mut err);
                    }

                    err.emit();
                }
            }
        }
    }

    fn check_for_overlapping_inherent_impls(&self, ty_def_id: DefId) {
        let impls = self.tcx.inherent_impls(ty_def_id);

        for (i, &impl1_def_id) in impls.iter().enumerate() {
            for &impl2_def_id in &impls[(i + 1)..] {
                traits::overlapping_impls(
                    self.tcx,
                    impl1_def_id,
                    impl2_def_id,
                    IntercrateMode::Issue43355,
                    // We go ahead and just skip the leak check for
                    // inherent impls without warning.
                    SkipLeakCheck::Yes,
                    |overlap| {
                        self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
                        false
                    },
                    || true,
                );
            }
        }
    }
}

impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
    fn visit_item(&mut self, item: &'v hir::Item<'v>) {
        match item.kind {
            hir::ItemKind::Enum(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::Trait(..)
            | hir::ItemKind::Union(..) => {
                let type_def_id = self.tcx.hir().local_def_id(item.hir_id);
                self.check_for_overlapping_inherent_impls(type_def_id);
            }
            _ => {}
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'v>) {}

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'v>) {}
}
<commit_msg>Add a fast path to inherent impl overlap check<commit_after>use crate::namespace::Namespace;
use rustc::traits::{self, IntercrateMode, SkipLeakCheck};
use rustc::ty::TyCtxt;
use rustc_errors::struct_span_err;
use rustc_hir as hir;
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE};
use rustc_hir::itemlikevisit::ItemLikeVisitor;

pub fn crate_inherent_impls_overlap_check(tcx: TyCtxt<'_>, crate_num: CrateNum) {
    assert_eq!(crate_num, LOCAL_CRATE);
    let krate = tcx.hir().krate();
    krate.visit_all_item_likes(&mut InherentOverlapChecker { tcx });
}

struct InherentOverlapChecker<'tcx> {
    tcx: TyCtxt<'tcx>,
}

impl InherentOverlapChecker<'tcx> {
    /// Checks whether any associated items in impls 1 and 2 share the same identifier and
    /// namespace.
    fn impls_have_common_items(&self, impl1: DefId, impl2: DefId) -> bool {
        let impl_items1 = self.tcx.associated_items(impl1);
        let impl_items2 = self.tcx.associated_items(impl2);

        for item1 in &impl_items1[..] {
            for item2 in &impl_items2[..] {
                // Avoid costly `.modern()` calls as much as possible by doing them as late as we
                // can. Compare raw symbols first.
                if item1.ident.name == item2.ident.name
                    && Namespace::from(item1.kind) == Namespace::from(item2.kind)
                {
                    // Symbols and namespace match, compare hygienically.
                    if item1.ident.modern() == item2.ident.modern() {
                        return true;
                    }
                }
            }
        }

        false
    }

    fn check_for_common_items_in_impls(
        &self,
        impl1: DefId,
        impl2: DefId,
        overlap: traits::OverlapResult<'_>,
    ) {
        let name_and_namespace =
            |assoc: &AssocItem| (assoc.ident.modern(), Namespace::from(assoc.kind));

        let impl_items1 = self.tcx.associated_items(impl1);
        let impl_items2 = self.tcx.associated_items(impl2);

        for item1 in &impl_items1[..] {
            let (name, namespace) = name_and_namespace(item1);

            for item2 in &impl_items2[..] {
                if (name, namespace) == name_and_namespace(item2) {
                    let mut err = struct_span_err!(
                        self.tcx.sess,
                        self.tcx.span_of_impl(item1.def_id).unwrap(),
                        E0592,
                        "duplicate definitions with name `{}`",
                        name
                    );
                    err.span_label(
                        self.tcx.span_of_impl(item1.def_id).unwrap(),
                        format!("duplicate definitions for `{}`", name),
                    );
                    err.span_label(
                        self.tcx.span_of_impl(item2.def_id).unwrap(),
                        format!("other definition for `{}`", name),
                    );

                    for cause in &overlap.intercrate_ambiguity_causes {
                        cause.add_intercrate_ambiguity_hint(&mut err);
                    }

                    if overlap.involves_placeholder {
                        traits::add_placeholder_note(&mut err);
                    }

                    err.emit();
                }
            }
        }
    }

    fn check_for_overlapping_inherent_impls(&self, impl1_def_id: DefId, impl2_def_id: DefId) {
        traits::overlapping_impls(
            self.tcx,
            impl1_def_id,
            impl2_def_id,
            IntercrateMode::Issue43355,
            // We go ahead and just skip the leak check for
            // inherent impls without warning.
            SkipLeakCheck::Yes,
            |overlap| {
                self.check_for_common_items_in_impls(impl1_def_id, impl2_def_id, overlap);
                false
            },
            || true,
        );
    }
}

impl ItemLikeVisitor<'v> for InherentOverlapChecker<'tcx> {
    fn visit_item(&mut self, item: &'v hir::Item<'v>) {
        match item.kind {
            hir::ItemKind::Enum(..)
            | hir::ItemKind::Struct(..)
            | hir::ItemKind::Trait(..)
            | hir::ItemKind::Union(..) => {
                let ty_def_id = self.tcx.hir().local_def_id(item.hir_id);
                let impls = self.tcx.inherent_impls(ty_def_id);

                for (i, &impl1_def_id) in impls.iter().enumerate() {
                    for &impl2_def_id in &impls[(i + 1)..] {
                        if self.impls_have_common_items(impl1_def_id, impl2_def_id) {
                            self.check_for_overlapping_inherent_impls(impl1_def_id, impl2_def_id);
                        }
                    }
                }
            }
            _ => {}
        }
    }

    fn visit_trait_item(&mut self, _trait_item: &hir::TraitItem<'v>) {}

    fn visit_impl_item(&mut self, _impl_item: &hir::ImplItem<'v>) {}
}
<|endoftext|>


<commit_before>use std::borrow::Borrow;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::{mem, slice, str};

/// Where we store all the intermediate bytes.
#[derive(Debug, Clone)]
pub struct DataBuffer(Vec<u8>, HashMap<u64, DataBufferPtr<str>>);

impl DataBuffer {
    /// Creates a new task buffer with specified capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        DataBuffer(Vec::with_capacity(capacity), HashMap::new())
    }

    pub fn clear(&mut self) {
        self.0.clear();
        self.1.clear();
    }

    pub fn extend<T>(&mut self, value: &T) -> DataBufferPtr<T>
    where
        T: Copy,
    {
        let data =
            unsafe { slice::from_raw_parts(value as *const T as *const u8, mem::size_of::<T>()) };

        self.0.extend_from_slice(data);
        DataBufferPtr {
            position: (self.0.len() - data.len()) as u32,
            size: data.len() as u32,
            _phantom: PhantomData,
        }
    }

    /// Clones and appends all elements in a slice to the buffer.
    pub fn extend_from_slice<T>(&mut self, slice: &[T]) -> DataBufferPtr<[T]>
    where
        T: Copy,
    {
        let len = mem::size_of::<T>().wrapping_mul(slice.len());
        let u8_slice = unsafe { slice::from_raw_parts(slice.as_ptr() as *const u8, len) };
        self.0.extend_from_slice(u8_slice);
        DataBufferPtr {
            position: (self.0.len() - len) as u32,
            size: len as u32,
            _phantom: PhantomData,
        }
    }

    /// Clones and append all bytes in a string slice to the buffer.
    pub fn extend_from_str<T>(&mut self, value: T) -> DataBufferPtr<str>
    where
        T: Borrow<str>,
    {
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hash, Hasher};

        let value = value.borrow();
        let mut s = DefaultHasher::new();
        value.hash(&mut s);
        let hash_value = s.finish();
        if let Some(ptr) = self.1.get(&hash_value) {
            return *ptr;
        }

        let slice = self.extend_from_slice(value.as_bytes());
        let ptr = DataBufferPtr {
            position: slice.position,
            size: slice.size,
            _phantom: PhantomData,
        };

        self.1.insert(hash_value, ptr);
        ptr
    }

    /// Returns reference to object indicated by `DataBufferPtr`.
    #[inline]
    pub fn as_ref<T>(&self, ptr: DataBufferPtr<T>) -> &T
    where
        T: Copy,
    {
        let slice = self.as_bytes(ptr);
        assert_eq!(slice.len(), mem::size_of::<T>());
        unsafe { &*(slice.as_ptr() as *const _) }
    }

    /// Returns a object slice indicated by `DataBufferPtr.
    #[inline]
    pub fn as_slice<T>(&self, ptr: DataBufferPtr<[T]>) -> &[T]
    where
        T: Copy,
    {
        let slice = self.as_bytes(ptr);
        let len = slice.len() / mem::size_of::<T>();
        assert_eq!(slice.len(), mem::size_of::<T>().wrapping_mul(len));
        unsafe { slice::from_raw_parts(slice.as_ptr() as *const T, len) }
    }

    /// Returns string slice indicated by `DataBufferPtr`.
    #[inline]
    pub fn as_str(&self, ptr: DataBufferPtr<str>) -> &str {
        str::from_utf8(self.as_bytes(ptr)).unwrap()
    }

    #[inline]
    pub fn as_bytes<T>(&self, slice: DataBufferPtr<T>) -> &[u8]
    where
        T: ?Sized,
    {
        &self.0[slice.position as usize..(slice.position + slice.size) as usize]
    }
}

/// A view into our `DataBuffer`, indicates where the object `T` stored.
#[derive(Debug)]
pub struct DataBufferPtr<T>
where
    T: ?Sized,
{
    position: u32,
    size: u32,
    _phantom: PhantomData<T>,
}

impl<T: ?Sized> Clone for DataBufferPtr<T> {
    fn clone(&self) -> Self {
        DataBufferPtr {
            position: self.position,
            size: self.size,
            _phantom: PhantomData,
        }
    }
}

impl<T: ?Sized> Copy for DataBufferPtr<T> {}

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

    #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
    struct UpdateSurfaceRect {
        position: (u16, u16),
        size: (u16, u16),
    }

    #[test]
    fn buf() {
        let mut buffer = DataBuffer::with_capacity(128);

        let mut uvp = UpdateSurfaceRect::default();
        uvp.position = (256, 128);
        let slice_uvp = buffer.extend(&uvp);

        let int = 128 as u32;
        let slice_int = buffer.extend(&int);

        assert_eq!(*buffer.as_ref(slice_int), int);
        assert_eq!(*buffer.as_ref(slice_uvp), uvp);

        let arr = [1, 2, 3];
        let slice_arr = buffer.extend(&arr);
        assert_eq!(*buffer.as_ref(slice_arr), arr);

        let slice_arr_1_2 = buffer.extend_from_slice(&arr[0..2]);
        assert_eq!(buffer.as_slice(slice_arr_1_2), &arr[0..2]);

        let text = "string serialization";
        let slice_text = buffer.extend_from_str(text);
        assert_eq!(text, buffer.as_str(slice_text));
    }
}
<commit_msg>Addressed a performance hot point with DTrace.<commit_after>use std::borrow::Borrow;
use std::collections::HashMap;
use std::marker::PhantomData;
use std::{mem, slice, str};

/// Where we store all the intermediate bytes.
#[derive(Debug, Clone)]
pub struct DataBuffer(Vec<u8>, HashMap<u64, DataBufferPtr<str>>);

impl DataBuffer {
    /// Creates a new task buffer with specified capacity.
    pub fn with_capacity(capacity: usize) -> Self {
        DataBuffer(Vec::with_capacity(capacity), HashMap::new())
    }

    pub fn clear(&mut self) {
        unsafe {
            self.0.set_len(0);
            self.1.clear();
        }
    }

    pub fn extend<T>(&mut self, value: &T) -> DataBufferPtr<T>
    where
        T: Copy,
    {
        let data =
            unsafe { slice::from_raw_parts(value as *const T as *const u8, mem::size_of::<T>()) };

        self.0.extend_from_slice(data);

        DataBufferPtr {
            position: (self.0.len() - data.len()) as u32,
            size: data.len() as u32,
            _phantom: PhantomData,
        }
    }

    /// Clones and appends all elements in a slice to the buffer.
    pub fn extend_from_slice<T>(&mut self, slice: &[T]) -> DataBufferPtr<[T]>
    where
        T: Copy,
    {
        let len = mem::size_of::<T>().wrapping_mul(slice.len());
        let u8_slice = unsafe { slice::from_raw_parts(slice.as_ptr() as *const u8, len) };
        self.0.extend_from_slice(u8_slice);
        DataBufferPtr {
            position: (self.0.len() - len) as u32,
            size: len as u32,
            _phantom: PhantomData,
        }
    }

    /// Clones and append all bytes in a string slice to the buffer.
    pub fn extend_from_str<T>(&mut self, value: T) -> DataBufferPtr<str>
    where
        T: Borrow<str>,
    {
        use std::collections::hash_map::DefaultHasher;
        use std::hash::{Hash, Hasher};

        let value = value.borrow();
        let mut s = DefaultHasher::new();
        value.hash(&mut s);
        let hash_value = s.finish();
        if let Some(ptr) = self.1.get(&hash_value) {
            return *ptr;
        }

        let slice = self.extend_from_slice(value.as_bytes());
        let ptr = DataBufferPtr {
            position: slice.position,
            size: slice.size,
            _phantom: PhantomData,
        };

        self.1.insert(hash_value, ptr);
        ptr
    }

    /// Returns reference to object indicated by `DataBufferPtr`.
    #[inline]
    pub fn as_ref<T>(&self, ptr: DataBufferPtr<T>) -> &T
    where
        T: Copy,
    {
        let slice = self.as_bytes(ptr);
        assert_eq!(slice.len(), mem::size_of::<T>());
        unsafe { &*(slice.as_ptr() as *const _) }
    }

    /// Returns a object slice indicated by `DataBufferPtr.
    #[inline]
    pub fn as_slice<T>(&self, ptr: DataBufferPtr<[T]>) -> &[T]
    where
        T: Copy,
    {
        let slice = self.as_bytes(ptr);
        let len = slice.len() / mem::size_of::<T>();
        assert_eq!(slice.len(), mem::size_of::<T>().wrapping_mul(len));
        unsafe { slice::from_raw_parts(slice.as_ptr() as *const T, len) }
    }

    /// Returns string slice indicated by `DataBufferPtr`.
    #[inline]
    pub fn as_str(&self, ptr: DataBufferPtr<str>) -> &str {
        str::from_utf8(self.as_bytes(ptr)).unwrap()
    }

    #[inline]
    pub fn as_bytes<T>(&self, slice: DataBufferPtr<T>) -> &[u8]
    where
        T: ?Sized,
    {
        &self.0[slice.position as usize..(slice.position + slice.size) as usize]
    }
}

/// A view into our `DataBuffer`, indicates where the object `T` stored.
#[derive(Debug)]
pub struct DataBufferPtr<T>
where
    T: ?Sized,
{
    position: u32,
    size: u32,
    _phantom: PhantomData<T>,
}

impl<T: ?Sized> Clone for DataBufferPtr<T> {
    fn clone(&self) -> Self {
        DataBufferPtr {
            position: self.position,
            size: self.size,
            _phantom: PhantomData,
        }
    }
}

impl<T: ?Sized> Copy for DataBufferPtr<T> {}

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

    #[derive(Debug, Default, Copy, Clone, PartialEq, Eq)]
    struct UpdateSurfaceRect {
        position: (u16, u16),
        size: (u16, u16),
    }

    #[test]
    fn buf() {
        let mut buffer = DataBuffer::with_capacity(128);

        let mut uvp = UpdateSurfaceRect::default();
        uvp.position = (256, 128);
        let slice_uvp = buffer.extend(&uvp);

        let int = 128 as u32;
        let slice_int = buffer.extend(&int);

        assert_eq!(*buffer.as_ref(slice_int), int);
        assert_eq!(*buffer.as_ref(slice_uvp), uvp);

        let arr = [1, 2, 3];
        let slice_arr = buffer.extend(&arr);
        assert_eq!(*buffer.as_ref(slice_arr), arr);

        let slice_arr_1_2 = buffer.extend_from_slice(&arr[0..2]);
        assert_eq!(buffer.as_slice(slice_arr_1_2), &arr[0..2]);

        let text = "string serialization";
        let slice_text = buffer.extend_from_str(text);
        assert_eq!(text, buffer.as_str(slice_text));
    }
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::fmt;

use serde::{Deserialize, Deserializer, Serialize, Serializer};
use serde::de::{MapAccess, Visitor};
use serde::ser::SerializeMap;

#[derive(Debug, Eq, PartialEq, Clone)]
/// Contains openapi specification extensions
/// see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#specificationExtensions
pub struct Extensions(HashMap<String, serde_json::Value>);

impl Extensions {
    fn add(&mut self, ext_id: String, value: serde_json::Value) {
        self.0.insert(ext_id, value);
    }

    /// Fetch extension by name
    pub fn get(&self, ext_id: &str) -> Option<&serde_json::Value> {
        self.0.get(ext_id)
    }

    /// A reference to all the captured extensions
    pub fn all(&self) -> &HashMap<String, serde_json::Value> {
        &self.0
    }
}

impl Default for Extensions {
    fn default() -> Self {
        Self(HashMap::new())
    }
}

impl<'de> Deserialize<'de> for Extensions {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: Deserializer<'de>,
    {
        struct ExtensionsVisitor;
        impl<'de> Visitor<'de> for ExtensionsVisitor {
            type Value = Extensions;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("struct Extensions")
            }

            fn visit_map<V>(self, mut map: V) -> Result<Extensions, V::Error>
                where
                    V: MapAccess<'de>,
            {
                let mut extensions = Extensions::default();
                while let Some(key) = map.next_key::<String>()? {
                    if key.starts_with("x-") {
                        extensions.add(key, map.next_value()?);
                    }
                }
                Ok(extensions)
            }
        }
        deserializer.deserialize_map(ExtensionsVisitor)
    }
}

impl Serialize for Extensions {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(self.0.len()))?;
        for (k, v) in self.0.clone() {
            map.serialize_entry(&k, &v)?;
        }
        map.end()
    }
}

#[cfg(test)]
mod tests {
    use serde_json::Value;
    use serde_test::{assert_tokens, Token};

    use crate::v3_0::extension::Extensions;

    #[test]
    fn test_serde_extensions() {
        let mut extensions = Extensions::default();
        extensions.add(String::from("x-test"), Value::from("val"));
        assert_tokens(
            &extensions,
            &[
                Token::Map { len: Some(1) },
                Token::String("x-test"),
                Token::String("val"),
                Token::MapEnd,
            ],
        )
    }

    #[test]
    fn test_get_extension() {
        let value = Value::from("val");

        let mut extensions = Extensions::default();
        extensions.add(String::from("x-test"), value.clone());

        assert_eq!(extensions.get("x-test"), Some(&value));
    }

    #[test]
    fn test_all_extensions() {
        let value = Value::from("val");

        let mut extensions = Extensions::default();
        extensions.add(String::from("x-test"), value.clone());

        assert_eq!(
            extensions.all().get_key_value("x-test"),
            Some((&"x-test".to_string(), &value))
        );
    }
}
<commit_msg>chore(formatting): cargo fmt<commit_after>use std::collections::HashMap;
use std::fmt;

use serde::de::{MapAccess, Visitor};
use serde::ser::SerializeMap;
use serde::{Deserialize, Deserializer, Serialize, Serializer};

/// Contains openapi specification extensions
/// see https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#specificationExtensions
#[derive(Debug, Eq, PartialEq, Clone)]
pub struct Extensions(HashMap<String, serde_json::Value>);

impl Extensions {
    fn add(&mut self, ext_id: String, value: serde_json::Value) {
        self.0.insert(ext_id, value);
    }

    /// Fetch extension by name
    pub fn get(&self, ext_id: &str) -> Option<&serde_json::Value> {
        self.0.get(ext_id)
    }

    /// A reference to all the captured extensions
    pub fn all(&self) -> &HashMap<String, serde_json::Value> {
        &self.0
    }
}

impl Default for Extensions {
    fn default() -> Self {
        Self(HashMap::new())
    }
}

impl<'de> Deserialize<'de> for Extensions {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct ExtensionsVisitor;
        impl<'de> Visitor<'de> for ExtensionsVisitor {
            type Value = Extensions;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("struct Extensions")
            }

            fn visit_map<V>(self, mut map: V) -> Result<Extensions, V::Error>
            where
                V: MapAccess<'de>,
            {
                let mut extensions = Extensions::default();
                while let Some(key) = map.next_key::<String>()? {
                    if key.starts_with("x-") {
                        extensions.add(key, map.next_value()?);
                    }
                }
                Ok(extensions)
            }
        }
        deserializer.deserialize_map(ExtensionsVisitor)
    }
}

impl Serialize for Extensions {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let mut map = serializer.serialize_map(Some(self.0.len()))?;
        for (k, v) in self.0.clone() {
            map.serialize_entry(&k, &v)?;
        }
        map.end()
    }
}

#[cfg(test)]
mod tests {
    use serde_json::Value;
    use serde_test::{assert_tokens, Token};

    use crate::v3_0::extension::Extensions;

    #[test]
    fn test_serde_extensions() {
        let mut extensions = Extensions::default();
        extensions.add(String::from("x-test"), Value::from("val"));
        assert_tokens(
            &extensions,
            &[
                Token::Map { len: Some(1) },
                Token::String("x-test"),
                Token::String("val"),
                Token::MapEnd,
            ],
        )
    }

    #[test]
    fn test_get_extension() {
        let value = Value::from("val");

        let mut extensions = Extensions::default();
        extensions.add(String::from("x-test"), value.clone());

        assert_eq!(extensions.get("x-test"), Some(&value));
    }

    #[test]
    fn test_all_extensions() {
        let value = Value::from("val");

        let mut extensions = Extensions::default();
        extensions.add(String::from("x-test"), value.clone());

        assert_eq!(
            extensions.all().get_key_value("x-test"),
            Some((&"x-test".to_string(), &value))
        );
    }
}
<|endoftext|>


<commit_before>use ncurses;

use color;
use vec::Vec2;
use view::{View,SizeRequest};
use event::EventResult;
use printer::Printer;

/// Displays an editable text.
pub struct EditView {
    content: String,
    cursor: usize,
    min_length: usize,
}

impl EditView {
    /// Creates a new, empty edit view.
    pub fn new() -> Self {
        EditView {
            content: String::new(),
            cursor: 0,
            min_length: 1,
        }
    }

    /// Replace the entire content of the view with the given one.
    pub fn set_content<'a>(&mut self, content: &'a str) {
        self.content = content.to_string();
    }

    /// Get the current text.
    pub fn get_content(&self) -> &str {
        &self.content
    }

    /// Sets the current content to the given value. Convenient chainable method.
    pub fn content<'a>(mut self, content: &'a str) -> Self {
        self.set_content(content);
        self
    }

    /// Sets the minimum length for this view.
    /// (This applies to the layout, not the content.)
    pub fn min_length(mut self, min_length: usize) -> Self {
        self.min_length = min_length;

        self
    }
}

fn read_char(ch: i32) -> Option<char> {
    // Printable ascii range: 32-126
    if ch >= ' ' as i32 && ch <= '~' as i32 {
        Some(ch as u8 as char)
    } else {
        None
    }
}

impl View for EditView {
    fn draw(&mut self, printer: &Printer, focused: bool) {
        // let style = if focused { color::HIGHLIGHT } else { color::HIGHLIGHT_INACTIVE };
        printer.with_color(color::SECONDARY, |printer| {
            printer.with_style(ncurses::A_REVERSE(), |printer| {
                printer.print((0,0), &self.content);
                printer.print_hline((self.content.len(),0), printer.size.x-self.content.len(), '_' as u64);
            });

            // Now print cursor
            if focused {
                let c = if self.cursor == self.content.len() {
                    '_'
                } else {
                    // Get the char from the string... Is it so hard?
                    self.content[self.cursor..].chars().next().unwrap()
                };
                printer.print_hline((self.cursor, 0), 1, c as u64);
            }
        });
    }

    fn get_min_size(&self, _: SizeRequest) -> Vec2 {
        Vec2::new(self.min_length, 1)
    }

    fn take_focus(&mut self) -> bool {
        true
    }

    fn on_key_event(&mut self, ch: i32) -> EventResult {

        if let Some(ch) = read_char(ch) {
            self.content.insert(self.cursor, ch);
            self.cursor += 1;
            return EventResult::Consumed(None);
        }

        match ch {
            ncurses::KEY_HOME => self.cursor = 0,
            ncurses::KEY_END => self.cursor = self.content.len(),
            ncurses::KEY_LEFT if self.cursor > 0 => self.cursor -= 1,
            ncurses::KEY_RIGHT if self.cursor < self.content.len() => self.cursor += 1,
            127 if self.cursor > 0 => { self.cursor -= 1; self.content.remove(self.cursor); },
            330 if self.cursor < self.content.len() => { self.content.remove(self.cursor); },
            _ => return EventResult::Ignored,
        }

        EventResult::Consumed(None)
    }
}
<commit_msg>Better char selection in EditView<commit_after>use ncurses;

use color;
use vec::Vec2;
use view::{View,SizeRequest};
use event::EventResult;
use printer::Printer;

/// Displays an editable text.
pub struct EditView {
    content: String,
    cursor: usize,
    min_length: usize,
}

impl EditView {
    /// Creates a new, empty edit view.
    pub fn new() -> Self {
        EditView {
            content: String::new(),
            cursor: 0,
            min_length: 1,
        }
    }

    /// Replace the entire content of the view with the given one.
    pub fn set_content<'a>(&mut self, content: &'a str) {
        self.content = content.to_string();
    }

    /// Get the current text.
    pub fn get_content(&self) -> &str {
        &self.content
    }

    /// Sets the current content to the given value. Convenient chainable method.
    pub fn content<'a>(mut self, content: &'a str) -> Self {
        self.set_content(content);
        self
    }

    /// Sets the minimum length for this view.
    /// (This applies to the layout, not the content.)
    pub fn min_length(mut self, min_length: usize) -> Self {
        self.min_length = min_length;

        self
    }
}

fn read_char(ch: i32) -> Option<char> {
    // Printable ascii range: 32-126
    if ch >= ' ' as i32 && ch <= '~' as i32 {
        Some(ch as u8 as char)
    } else {
        None
    }
}

impl View for EditView {
    fn draw(&mut self, printer: &Printer, focused: bool) {
        // let style = if focused { color::HIGHLIGHT } else { color::HIGHLIGHT_INACTIVE };
        printer.with_color(color::SECONDARY, |printer| {
            printer.with_style(ncurses::A_REVERSE(), |printer| {
                printer.print((0,0), &self.content);
                printer.print_hline((self.content.len(),0), printer.size.x-self.content.len(), '_' as u64);
            });

            // Now print cursor
            if focused {
                let c = if self.cursor == self.content.len() {
                    '_'
                } else {
                    // Get the char from the string... Is it so hard?
                    self.content.chars().nth(self.cursor).unwrap()
                };
                printer.print_hline((self.cursor, 0), 1, c as u64);
            }
        });
    }

    fn get_min_size(&self, _: SizeRequest) -> Vec2 {
        Vec2::new(self.min_length, 1)
    }

    fn take_focus(&mut self) -> bool {
        true
    }

    fn on_key_event(&mut self, ch: i32) -> EventResult {

        if let Some(ch) = read_char(ch) {
            self.content.insert(self.cursor, ch);
            self.cursor += 1;
            return EventResult::Consumed(None);
        }

        match ch {
            ncurses::KEY_HOME => self.cursor = 0,
            ncurses::KEY_END => self.cursor = self.content.len(),
            ncurses::KEY_LEFT if self.cursor > 0 => self.cursor -= 1,
            ncurses::KEY_RIGHT if self.cursor < self.content.len() => self.cursor += 1,
            127 if self.cursor > 0 => { self.cursor -= 1; self.content.remove(self.cursor); },
            330 if self.cursor < self.content.len() => { self.content.remove(self.cursor); },
            _ => return EventResult::Ignored,
        }

        EventResult::Consumed(None)
    }
}
<|endoftext|>


<commit_before>#![deny(warnings)]

extern crate arg_parser;
extern crate coreutils;
extern crate extra;
#[cfg(target_os = "redox")]
extern crate syscall;

#[cfg(target_os = "redox")]
fn df(path: &str, parser: &ArgParser) -> ::std::io::Result<()> {
    use coreutils::to_human_readable_string;
    use std::io::Error;
    use syscall::data::StatVfs;

    let mut stat = StatVfs::default();
    {
        let fd = syscall::open(path, syscall::O_STAT).map_err(|err| Error::from_raw_os_error(err.errno))?;
        syscall::fstatvfs(fd, &mut stat).map_err(|err| Error::from_raw_os_error(err.errno))?;
        let _ = syscall::close(fd);
    }

    let size = stat.f_blocks * stat.f_bsize as u64;
    let used = (stat.f_blocks - stat.f_bfree) * stat.f_bsize as u64;
    let free = stat.f_bavail * stat.f_bsize as u64;
    let percent = (100.0 * used as f64 / size as f64) as u64;

    if parser.found("human-readable") {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 to_human_readable_string(size),
                 to_human_readable_string(used),
                 to_human_readable_string(free),
                 format!("{}%", percent));
    } else {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 (size + 1023)/1024,
                 (used + 1023)/1024,
                 (free + 1023)/1024,
                 format!("{}%", percent));
    }

    Ok(())
}

#[cfg(target_os = "redox")]
fn main() {
    use std::env;
    use std::fs::File;
    use std::io::{stdout, stderr, BufRead, BufReader, Write};
    use std::process::exit;
    use arg_parser::ArgParser;
    use extra::option::OptionalExt;

    const MAN_PAGE: &'static str = /* @MANSTART{df} */ r#"
    NAME
        df - view filesystem space usage

    SYNOPSIS
        df [ -h | --help ] FILE...

    DESCRIPTION
        df gets the filesystem space usage for the filesystem providing FILE

    OPTIONS
        -h
        --human-readable
            human readable output
        --help
            display this help and exit
    "#; /* @MANEND */

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "human-readable"])
        .add_flag(&["help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    println!("{:<10}{:>10}{:>10}{:>10}{:>5}", "Path", "Size", "Used", "Free", "Use%");
    if parser.args.is_empty() {
        let file = BufReader::new(File::open("sys:scheme").try(&mut stderr));
        for line in file.lines() {
            let _ = df(&format!("{}:", line.try(&mut stderr)), &parser);
        }
    } else {
        for path in &parser.args {
            df(&path, &parser).try(&mut stderr);
        }
    }
}

#[cfg(not(target_os = "redox"))]
fn main() {
    use std::io::{stderr, Write};
    use std::process::exit;

    let mut stderr = stderr();
    stderr.write(b"error: unimplemented outside redox").unwrap();
    exit(1);
}
<commit_msg>Fix broken compilation on Redox.<commit_after>#![deny(warnings)]

extern crate arg_parser;
extern crate coreutils;
extern crate extra;
#[cfg(target_os = "redox")]
extern crate syscall;

#[cfg(target_os = "redox")]
fn df(path: &str, parser: &arg_parser::ArgParser) -> ::std::io::Result<()> {
    use coreutils::to_human_readable_string;
    use std::io::Error;
    use syscall::data::StatVfs;

    let mut stat = StatVfs::default();
    {
        let fd = syscall::open(path, syscall::O_STAT).map_err(|err| Error::from_raw_os_error(err.errno))?;
        syscall::fstatvfs(fd, &mut stat).map_err(|err| Error::from_raw_os_error(err.errno))?;
        let _ = syscall::close(fd);
    }

    let size = stat.f_blocks * stat.f_bsize as u64;
    let used = (stat.f_blocks - stat.f_bfree) * stat.f_bsize as u64;
    let free = stat.f_bavail * stat.f_bsize as u64;
    let percent = (100.0 * used as f64 / size as f64) as u64;

    if parser.found("human-readable") {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 to_human_readable_string(size),
                 to_human_readable_string(used),
                 to_human_readable_string(free),
                 format!("{}%", percent));
    } else {
        println!("{:<10}{:>10}{:>10}{:>10}{:>5}",
                 path,
                 (size + 1023)/1024,
                 (used + 1023)/1024,
                 (free + 1023)/1024,
                 format!("{}%", percent));
    }

    Ok(())
}

#[cfg(target_os = "redox")]
fn main() {
    use std::env;
    use std::fs::File;
    use std::io::{stdout, stderr, BufRead, BufReader, Write};
    use std::process::exit;
    use arg_parser::ArgParser;
    use extra::option::OptionalExt;

    const MAN_PAGE: &'static str = /* @MANSTART{df} */ r#"
    NAME
        df - view filesystem space usage

    SYNOPSIS
        df [ -h | --help ] FILE...

    DESCRIPTION
        df gets the filesystem space usage for the filesystem providing FILE

    OPTIONS
        -h
        --human-readable
            human readable output
        --help
            display this help and exit
    "#; /* @MANEND */

    let stdout = stdout();
    let mut stdout = stdout.lock();
    let mut stderr = stderr();
    let mut parser = ArgParser::new(1)
        .add_flag(&["h", "human-readable"])
        .add_flag(&["help"]);
    parser.parse(env::args());

    if parser.found("help") {
        stdout.write(MAN_PAGE.as_bytes()).try(&mut stderr);
        stdout.flush().try(&mut stderr);
        exit(0);
    }

    println!("{:<10}{:>10}{:>10}{:>10}{:>5}", "Path", "Size", "Used", "Free", "Use%");
    if parser.args.is_empty() {
        let file = BufReader::new(File::open("sys:scheme").try(&mut stderr));
        for line in file.lines() {
            let _ = df(&format!("{}:", line.try(&mut stderr)), &parser);
        }
    } else {
        for path in &parser.args {
            df(&path, &parser).try(&mut stderr);
        }
    }
}

#[cfg(not(target_os = "redox"))]
fn main() {
    use std::io::{stderr, Write};
    use std::process::exit;

    let mut stderr = stderr();
    stderr.write(b"error: unimplemented outside redox").unwrap();
    exit(1);
}
<|endoftext|>