<commit_before>//! Implementation of a piece table based on a vector.
//! A piece table provides efficient methods for inserting and removing elements sequentially, intended for use as the underlying data structure in a text editor.
//!
//! The piece table stores a read only reference to a source (if one is provided) and stores inserted elements in an append-only vector.
//! A table of pieces pointing either to the source or add-buffer is maintained, and these pieces are manipulated when inserting and removing text.
//! Asymptotics in the following are based on `p`, the number of pieces, where `p` should be strictly smaller than the number of elements when used as intended.

use std::iter::Iterator;
use std::ops::Index;

use Buffer::*;
use Location::*;

#[derive(Debug, PartialEq, Clone, Copy)]
enum Buffer {
    Add,
    Original,
}

// TODO: consider just making PieceHead carry norm_idx=0 also, for simplicity elsewhere
#[derive(PartialEq, Debug, Clone, Copy)]
enum Location {
    PieceHead(usize),
    PieceMid(usize, usize),
    PieceTail(usize, usize),
    EOF,
}

#[derive(Debug, Clone, Copy)]
struct Piece {
    start: usize,
    length: usize,
    buffer: Buffer,
}

/// The `PieceTable` type with all relevant methods.
#[derive(Debug, Clone)]
pub struct PieceTable<'a, T: 'a> {
    original: &'a [T],
    adds: Vec<T>,
    pieces: Vec<Piece>,
    last_idx: usize,
    length: usize,
    reusable_insert: Option<usize>,
    reusable_remove: Option<Location>,
}

/// Struct for iterating the elements of a `PieceTable`.
pub struct Iter<'a, T: 'a>
{
    table: &'a PieceTable<'a, T>,
    piece_idx: usize,
    it: std::slice::Iter<'a, T>,
}

/// Struct for iterating a range of elements in a `PieceTable`.
pub struct Range<'a, T: 'a> {
    iter: Iter<'a, T>,
    idx: usize,
    to: usize,
}

impl<'a, T: 'a> PieceTable<'a, T> {

    /// Construct a new `PieceTable`
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let table: PieceTable<char> = PieceTable::new();
    /// ```
    pub fn new() -> PieceTable<'a, T> {
        PieceTable {
            original: &[],
            adds: Vec::new(),
            pieces: Vec::new(),
            last_idx: 0,
            length: 0,
            reusable_insert: None,
            reusable_remove: None,
        }
    }

    /// Assign a read-only source to an existing `PieceTable`.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..100).collect();
    /// let table = PieceTable::new().src(&src);
    /// ```
    pub fn src(mut self, src: &'a [T]) -> PieceTable<'a, T> {
        let mut pieces = Vec::new();
        if src.len() > 0 {
            pieces.push(Piece {
                start: 0,
                length: src.len(),
                buffer: Original,
            });
        }

        self.original = src;
        self.pieces = pieces;
        self.length = src.len();

        self
    }

    /// The number of elements stored in the piece table.
    pub fn len(&self) -> usize {
        self.length
    }

    fn make_iter(&'a self, idx: usize) -> Iter<'a, T> {
        let (piece_idx, norm_idx) = match self.idx_to_location(idx) {
            PieceHead(piece_idx) => (piece_idx, 0),
            PieceMid(piece_idx, norm_idx) |
            PieceTail(piece_idx, norm_idx) => (piece_idx, norm_idx),
            EOF => {
                // Need an iterator that just closes.
                let it = self.adds[(0 .. 0)].iter();
                return Iter {
                    table: &self,
                    piece_idx: self.pieces.len(),
                    it: it,
                }
            },
        };

        let piece = self.pieces[piece_idx];
        let buf = self.get_buffer(&piece);
        let it = buf[(piece.start + norm_idx .. piece.start + piece.length)].iter();

        Iter {
            table: &self,
            piece_idx: piece_idx,
            it: it,
        }
    }

    /// Return an iterator over all elements of the `PieceTable`.
    ///
    /// Advancing the iterator takes constant time.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..101).collect();
    /// let table = PieceTable::new().src(&src);
    /// assert_eq!(5050, table.iter().fold(0, |acc, &x| acc + x));
    /// ```
    pub fn iter(&'a self) -> Iter<'a, T> {
        self.make_iter(0)
    }

    /// Return an iterator over the range `[from, to)` in the `PieceTable`.
    /// Construction the iterator takes `O(p)` time, but consuming it is constant time per element.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..100).collect();
    /// let table = PieceTable::new().src(&src);
    /// assert_eq!(vec![&55, &56, &57], table.range(55, 58).collect::<Vec<&i32>>());
    /// ```
    pub fn range(&'a self, from: usize, to: usize) -> Range<'a, T> {
        let iter = self.make_iter(from);

        Range {
            iter: iter,
            idx: from,
            to: to,
        }
    }

    /// Insert an element at `idx`.
    ///
    /// `O(p)` time, but sequential inserts afterwards take `O(1) `time.
    ///
    /// # Panics
    /// Panics if not `idx <= len`.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..100).collect();
    /// let mut table = PieceTable::new().src(&src);
    /// table.insert(11, 42); // takes `O(p)` time
    /// table.insert(12, 42); // constant time
    /// table.insert(13, 42); // constant time
    /// table.insert(27, 42); // `O(p)` time
    /// table.insert(28, 42); // constant time
    /// ```
    pub fn insert(&mut self, idx: usize, item: T) {
        assert!(idx <= self.length);

        match self.reusable_insert {
            Some(piece_idx) if idx == self.last_idx+1 => {
                let piece = &mut self.pieces[piece_idx];
                self.adds.push(item);
                piece.length += 1;
            }
            _ => self.raw_insert(idx, item),
        }

        self.reusable_remove = None;
        self.last_idx = idx;
        self.length += 1;
    }

    fn raw_insert(&mut self, idx: usize, item: T) {
        let item_idx = self.adds.len();
        self.adds.push(item);

        match self.idx_to_location(idx) {
            PieceHead(piece_idx) => {
                self.pieces.insert(piece_idx, Piece {
                    start: item_idx,
                    length: 1,
                    buffer: Add,
                });

                self.reusable_insert = Some(piece_idx);
            },
            PieceMid(piece_idx, norm_idx) | PieceTail(piece_idx, norm_idx) => {
                let orig = self.pieces[piece_idx].clone();
                if let Some(piece) = self.pieces.get_mut(piece_idx) {
                    piece.length = norm_idx;
                } else {
                    panic!("find_piece_idx returned invalid index.");
                }

                self.pieces.insert(piece_idx+1, Piece {
                    start: item_idx,
                    length: 1,
                    buffer: Add,
                });

                self.reusable_insert = Some(piece_idx+1);

                self.pieces.insert(piece_idx+2, Piece {
                    start: orig.start + norm_idx,
                    length: orig.length - norm_idx,
                    buffer: orig.buffer,
                });
            },
            EOF => {
                let piece_idx = self.pieces.len();

                self.pieces.push(Piece {
                    start: item_idx,
                    length: 1,
                    buffer: Add,
                });

                self.reusable_insert = Some(piece_idx);
            }
        }
    }

    /// Remove the element at the given index.
    ///
    /// `O(p)` operation initially, but removing sequentially backwards afterwards is `O(1)`.
    ///
    /// # Panics
    /// Panics if not `idx < len`.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..10).collect();
    /// let mut table = PieceTable::new().src(&src);
    /// table.remove(5); // `O(p)`
    /// table.remove(4); // `O(1)`
    /// table.remove(3); // `O(1)`
    /// table.remove(6); // `O(p)`
    /// assert_eq!(vec![&0, &1, &2, &6, &7, &8], table.iter().collect::<Vec<&i32>>());
    /// ```
    pub fn remove(&mut self, idx: usize) {
        assert!(idx < self.length);

        let mut remove: Option<usize> = None;

        match self.reusable_insert {
            Some(piece_idx) if idx == self.last_idx => {
                let piece = &mut self.pieces[piece_idx];
                piece.length -= 1;
                if piece.length == 0 {
                    remove = Some(piece_idx);
                }
                self.reusable_remove = None;
            },
            _ => {
                let location = if idx+1 == self.last_idx && self.reusable_remove.is_some() {
                    self.reusable_remove.unwrap()
                } else {
                    self.idx_to_location(idx)
                };

                self.raw_remove(location);
            },
        }

        self.reusable_insert = None;

        if let Some(piece_idx) = remove {
            self.pieces.remove(piece_idx);
        }

        self.last_idx = idx;
        self.length -= 1;
    }

    fn raw_remove(&mut self, location: Location) {
        self.reusable_remove = None;

        match location {
            PieceHead(piece_idx) => {
                let remove = {
                    let piece = &mut self.pieces[piece_idx];
                    piece.start += 1;
                    piece.length -= 1;
                    piece.length == 0
                };

                if remove {
                    self.pieces.remove(piece_idx);
                }

                if piece_idx > 0 {
                    let idx = piece_idx-1;
                    let len = self.pieces[idx].length;
                    let loc = if len == 1 {
                        PieceHead(idx)
                    } else {
                        PieceTail(idx, len-1)
                    };

                    self.reusable_remove = Some(loc);
                }
            },
            PieceTail(piece_idx, norm_idx) => {
                self.pieces[piece_idx].length -= 1;

                if piece_idx > 0 {
                    let loc = if norm_idx-1 == 0 {
                        PieceHead(piece_idx)
                    } else {
                        PieceTail(piece_idx, norm_idx-1)
                    };
                    self.reusable_remove = Some(loc);
                }
            },
            PieceMid(piece_idx, norm_idx) => {
                let orig = self.pieces[piece_idx];
                self.pieces[piece_idx].length = norm_idx;

                let start = norm_idx + 1;
                if orig.length - start > 0 {
                    self.pieces.insert(piece_idx+1, Piece {
                        start: orig.start + start,
                        length: orig.length - start,
                        buffer: orig.buffer,
                    });
                }

                if piece_idx > 0 {
                    let loc = if norm_idx-1 == 0 {
                        PieceHead(piece_idx)
                    } else {
                        PieceMid(piece_idx, norm_idx-1)
                    };

                    self.reusable_remove = Some(loc);
                }
            },
            EOF => {},
        }
    }

    fn idx_to_location(&self, idx: usize) -> Location {
        let mut offset = 0;
        for (i, piece) in self.pieces.iter().enumerate() {
            if idx >= offset && idx < offset + piece.length {
                return match idx - offset {
                    0 => PieceHead(i),
                    delta if delta == piece.length-1 => PieceTail(i, delta),
                    delta => PieceMid(i, delta),
                };
            }

            offset += piece.length;
        }

        EOF
    }

    fn get_buffer(&'a self, piece: &Piece) -> &'a [T] {
        match piece.buffer {
            Add => &self.adds,
            Original => self.original,
        }
    }
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(next) = self.it.next() {
            Some(next)
        } else {
            self.piece_idx += 1;

            if self.piece_idx >= self.table.pieces.len() {
                None
            } else {
                let piece = self.table.pieces[self.piece_idx];
                let buf = self.table.get_buffer(&piece);

                self.it = buf[(piece.start .. piece.start + piece.length)].iter();
                self.next()
            }
        }
    }
}

impl<'a, T> Iterator for Range<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.to {
            None
        } else {
            self.idx += 1;
            self.iter.next()
        }
    }
}

impl<'a, T> Index<usize> for PieceTable<'a, T> {
    type Output = T;

    /// Note: Reading an index takes `O(p)` time, use iterators for fast sequential access.
    fn index<'b>(&'b self, idx: usize) -> &'b T {
        let (piece_idx, norm_idx) = match self.idx_to_location(idx) {
            PieceHead(piece_idx) => (piece_idx, 0),
            PieceMid(piece_idx, norm_idx) |
            PieceTail(piece_idx, norm_idx) => (piece_idx, norm_idx),
            EOF => panic!("PieceTable out of bounds: {}", idx),
        };

        let ref piece = self.pieces[piece_idx];
        match piece.buffer {
            Add => &self.adds[piece.start + norm_idx],
            Original => &self.original[piece.start + norm_idx],
        }
    }
}
<commit_msg>simplify remove<commit_after>//! Implementation of a piece table based on a vector.
//! A piece table provides efficient methods for inserting and removing elements sequentially, intended for use as the underlying data structure in a text editor.
//!
//! The piece table stores a read only reference to a source (if one is provided) and stores inserted elements in an append-only vector.
//! A table of pieces pointing either to the source or add-buffer is maintained, and these pieces are manipulated when inserting and removing text.
//! Asymptotics in the following are based on `p`, the number of pieces, where `p` should be strictly smaller than the number of elements when used as intended.

use std::iter::Iterator;
use std::ops::Index;

use Buffer::*;
use Location::*;

#[derive(Debug, PartialEq, Clone, Copy)]
enum Buffer {
    Add,
    Original,
}

// TODO: consider just making PieceHead carry norm_idx=0 also, for simplicity elsewhere
#[derive(PartialEq, Debug, Clone, Copy)]
enum Location {
    PieceHead(usize),
    PieceMid(usize, usize),
    PieceTail(usize, usize),
    EOF,
}

#[derive(Debug, Clone, Copy)]
struct Piece {
    start: usize,
    length: usize,
    buffer: Buffer,
}

/// The `PieceTable` type with all relevant methods.
#[derive(Debug, Clone)]
pub struct PieceTable<'a, T: 'a> {
    original: &'a [T],
    adds: Vec<T>,
    pieces: Vec<Piece>,
    last_idx: usize,
    length: usize,
    reusable_insert: Option<usize>,
    reusable_remove: Option<Location>,
}

/// Struct for iterating the elements of a `PieceTable`.
pub struct Iter<'a, T: 'a>
{
    table: &'a PieceTable<'a, T>,
    piece_idx: usize,
    it: std::slice::Iter<'a, T>,
}

/// Struct for iterating a range of elements in a `PieceTable`.
pub struct Range<'a, T: 'a> {
    iter: Iter<'a, T>,
    idx: usize,
    to: usize,
}

impl<'a, T: 'a> PieceTable<'a, T> {

    /// Construct a new `PieceTable`
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let table: PieceTable<char> = PieceTable::new();
    /// ```
    pub fn new() -> PieceTable<'a, T> {
        PieceTable {
            original: &[],
            adds: Vec::new(),
            pieces: Vec::new(),
            last_idx: 0,
            length: 0,
            reusable_insert: None,
            reusable_remove: None,
        }
    }

    /// Assign a read-only source to an existing `PieceTable`.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..100).collect();
    /// let table = PieceTable::new().src(&src);
    /// ```
    pub fn src(mut self, src: &'a [T]) -> PieceTable<'a, T> {
        let mut pieces = Vec::new();
        if src.len() > 0 {
            pieces.push(Piece {
                start: 0,
                length: src.len(),
                buffer: Original,
            });
        }

        self.original = src;
        self.pieces = pieces;
        self.length = src.len();

        self
    }

    /// The number of elements stored in the piece table.
    pub fn len(&self) -> usize {
        self.length
    }

    fn make_iter(&'a self, idx: usize) -> Iter<'a, T> {
        let (piece_idx, norm_idx) = match self.idx_to_location(idx) {
            PieceHead(piece_idx) => (piece_idx, 0),
            PieceMid(piece_idx, norm_idx) |
            PieceTail(piece_idx, norm_idx) => (piece_idx, norm_idx),
            EOF => {
                // Need an iterator that just closes.
                let it = self.adds[(0 .. 0)].iter();
                return Iter {
                    table: &self,
                    piece_idx: self.pieces.len(),
                    it: it,
                }
            },
        };

        let piece = self.pieces[piece_idx];
        let buf = self.get_buffer(&piece);
        let it = buf[(piece.start + norm_idx .. piece.start + piece.length)].iter();

        Iter {
            table: &self,
            piece_idx: piece_idx,
            it: it,
        }
    }

    /// Return an iterator over all elements of the `PieceTable`.
    ///
    /// Advancing the iterator takes constant time.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..101).collect();
    /// let table = PieceTable::new().src(&src);
    /// assert_eq!(5050, table.iter().fold(0, |acc, &x| acc + x));
    /// ```
    pub fn iter(&'a self) -> Iter<'a, T> {
        self.make_iter(0)
    }

    /// Return an iterator over the range `[from, to)` in the `PieceTable`.
    /// Construction the iterator takes `O(p)` time, but consuming it is constant time per element.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..100).collect();
    /// let table = PieceTable::new().src(&src);
    /// assert_eq!(vec![&55, &56, &57], table.range(55, 58).collect::<Vec<&i32>>());
    /// ```
    pub fn range(&'a self, from: usize, to: usize) -> Range<'a, T> {
        let iter = self.make_iter(from);

        Range {
            iter: iter,
            idx: from,
            to: to,
        }
    }

    /// Insert an element at `idx`.
    ///
    /// `O(p)` time, but sequential inserts afterwards take `O(1) `time.
    ///
    /// # Panics
    /// Panics if not `idx <= len`.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..100).collect();
    /// let mut table = PieceTable::new().src(&src);
    /// table.insert(11, 42); // takes `O(p)` time
    /// table.insert(12, 42); // constant time
    /// table.insert(13, 42); // constant time
    /// table.insert(27, 42); // `O(p)` time
    /// table.insert(28, 42); // constant time
    /// ```
    pub fn insert(&mut self, idx: usize, item: T) {
        assert!(idx <= self.length);

        match self.reusable_insert {
            Some(piece_idx) if idx == self.last_idx+1 => {
                let piece = &mut self.pieces[piece_idx];
                self.adds.push(item);
                piece.length += 1;
            }
            _ => self.raw_insert(idx, item),
        }

        self.reusable_remove = None;
        self.last_idx = idx;
        self.length += 1;
    }

    fn raw_insert(&mut self, idx: usize, item: T) {
        let item_idx = self.adds.len();
        self.adds.push(item);

        match self.idx_to_location(idx) {
            PieceHead(piece_idx) => {
                self.pieces.insert(piece_idx, Piece {
                    start: item_idx,
                    length: 1,
                    buffer: Add,
                });

                self.reusable_insert = Some(piece_idx);
            },
            PieceMid(piece_idx, norm_idx) | PieceTail(piece_idx, norm_idx) => {
                let orig = self.pieces[piece_idx].clone();
                self.pieces[piece_idx].length = norm_idx;

                self.pieces.insert(piece_idx+1, Piece {
                    start: item_idx,
                    length: 1,
                    buffer: Add,
                });

                self.reusable_insert = Some(piece_idx+1);

                self.pieces.insert(piece_idx+2, Piece {
                    start: orig.start + norm_idx,
                    length: orig.length - norm_idx,
                    buffer: orig.buffer,
                });
            },
            EOF => {
                let piece_idx = self.pieces.len();

                self.pieces.push(Piece {
                    start: item_idx,
                    length: 1,
                    buffer: Add,
                });

                self.reusable_insert = Some(piece_idx);
            }
        }
    }

    /// Remove the element at the given index.
    ///
    /// `O(p)` operation initially, but removing sequentially backwards afterwards is `O(1)`.
    ///
    /// # Panics
    /// Panics if not `idx < len`.
    ///
    /// # Example
    /// ```
    /// use piecetable::PieceTable;
    /// let src: Vec<i32> = (0..10).collect();
    /// let mut table = PieceTable::new().src(&src);
    /// table.remove(5); // `O(p)`
    /// table.remove(4); // `O(1)`
    /// table.remove(3); // `O(1)`
    /// table.remove(6); // `O(p)`
    /// assert_eq!(vec![&0, &1, &2, &6, &7, &8], table.iter().collect::<Vec<&i32>>());
    /// ```
    pub fn remove(&mut self, idx: usize) {
        assert!(idx < self.length);

        self.reusable_insert = None;

        let location = match self.reusable_remove {
            Some(loc) if idx+1 == self.last_idx => loc,
            _ => self.idx_to_location(idx),
        };

        self.raw_remove(location);

        self.last_idx = idx;
        self.length -= 1;
    }

    fn raw_remove(&mut self, location: Location) {
        self.reusable_remove = None;

        match location {
            PieceHead(piece_idx) => {
                let remove = {
                    let piece = &mut self.pieces[piece_idx];
                    piece.start += 1;
                    piece.length -= 1;
                    piece.length == 0
                };

                if remove {
                    self.pieces.remove(piece_idx);
                }

                if piece_idx > 0 {
                    let idx = piece_idx-1;
                    let len = self.pieces[idx].length;
                    let loc = if len == 1 {
                        PieceHead(idx)
                    } else {
                        PieceTail(idx, len-1)
                    };

                    self.reusable_remove = Some(loc);
                }
            },
            PieceTail(piece_idx, norm_idx) => {
                self.pieces[piece_idx].length -= 1;

                if piece_idx > 0 {
                    let loc = if norm_idx-1 == 0 {
                        PieceHead(piece_idx)
                    } else {
                        PieceTail(piece_idx, norm_idx-1)
                    };
                    self.reusable_remove = Some(loc);
                }
            },
            PieceMid(piece_idx, norm_idx) => {
                let orig = self.pieces[piece_idx];
                self.pieces[piece_idx].length = norm_idx;

                let start = norm_idx + 1;
                if orig.length - start > 0 {
                    self.pieces.insert(piece_idx+1, Piece {
                        start: orig.start + start,
                        length: orig.length - start,
                        buffer: orig.buffer,
                    });
                }

                if piece_idx > 0 {
                    let loc = if norm_idx-1 == 0 {
                        PieceHead(piece_idx)
                    } else {
                        PieceMid(piece_idx, norm_idx-1)
                    };

                    self.reusable_remove = Some(loc);
                }
            },
            EOF => {},
        }
    }

    fn idx_to_location(&self, idx: usize) -> Location {
        let mut offset = 0;
        for (i, piece) in self.pieces.iter().enumerate() {
            if idx >= offset && idx < offset + piece.length {
                return match idx - offset {
                    0 => PieceHead(i),
                    delta if delta == piece.length-1 => PieceTail(i, delta),
                    delta => PieceMid(i, delta),
                };
            }

            offset += piece.length;
        }

        EOF
    }

    fn get_buffer(&'a self, piece: &Piece) -> &'a [T] {
        match piece.buffer {
            Add => &self.adds,
            Original => self.original,
        }
    }
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        if let Some(next) = self.it.next() {
            Some(next)
        } else {
            self.piece_idx += 1;

            if self.piece_idx >= self.table.pieces.len() {
                None
            } else {
                let piece = self.table.pieces[self.piece_idx];
                let buf = self.table.get_buffer(&piece);

                self.it = buf[(piece.start .. piece.start + piece.length)].iter();
                self.next()
            }
        }
    }
}

impl<'a, T> Iterator for Range<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<Self::Item> {
        if self.idx >= self.to {
            None
        } else {
            self.idx += 1;
            self.iter.next()
        }
    }
}

impl<'a, T> Index<usize> for PieceTable<'a, T> {
    type Output = T;

    /// Note: Reading an index takes `O(p)` time, use iterators for fast sequential access.
    fn index<'b>(&'b self, idx: usize) -> &'b T {
        let (piece_idx, norm_idx) = match self.idx_to_location(idx) {
            PieceHead(piece_idx) => (piece_idx, 0),
            PieceMid(piece_idx, norm_idx) |
            PieceTail(piece_idx, norm_idx) => (piece_idx, norm_idx),
            EOF => panic!("PieceTable out of bounds: {}", idx),
        };

        let ref piece = self.pieces[piece_idx];
        match piece.buffer {
            Add => &self.adds[piece.start + norm_idx],
            Original => &self.original[piece.start + norm_idx],
        }
    }
}
<|endoftext|>


<commit_before>#![feature(question_mark)]
#![feature(associated_consts)]
#![feature(const_fn)]
#![feature(conservative_impl_trait)]
#![feature(plugin)]

#![cfg_attr(test, plugin(stainless))]

extern crate mio;
extern crate slab;
extern crate uuid;
extern crate byteorder;
extern crate graphsearch;
extern crate twox_hash;
extern crate walkdir;
#[macro_use]
extern crate protocol as proto;
extern crate itertools;

pub use self::parapet::Parapet;
pub use self::interactive::Interactive;
pub use self::network::Network;
pub use self::error::Error;
pub use self::protocol::{Packet, PacketKind};

pub mod parapet;
pub mod interactive;
pub mod network;
pub mod error;
pub mod protocol;
pub mod ci;

pub const SERVER_PORT: u16 = 53371;
pub const SERVER_ADDRESS: (&'static str, u16) = ("127.0.0.1", SERVER_PORT);

pub const CLIENT_NAME: &'static str = "vanilla";
pub const CLIENT_VERSION: &'static str = env!("CARGO_PKG_VERSION");

pub const PROTOCOL_MAJOR: u16 = 0;
pub const PROTOCOL_REVISION: u16 = 0;

pub fn user_agent() -> protocol::UserAgent {
    protocol::UserAgent {
        client: format!("{} v{}", CLIENT_NAME, CLIENT_VERSION),
        protocol_major: PROTOCOL_MAJOR,
        protocol_revision: PROTOCOL_REVISION,
    }
}

<commit_msg>Remove now-stable feature flags<commit_after>#![cfg_attr(test, plugin(stainless))]

extern crate mio;
extern crate slab;
extern crate uuid;
extern crate byteorder;
extern crate graphsearch;
extern crate twox_hash;
extern crate walkdir;
#[macro_use]
extern crate protocol as proto;
extern crate itertools;

pub use self::parapet::Parapet;
pub use self::interactive::Interactive;
pub use self::network::Network;
pub use self::error::Error;
pub use self::protocol::{Packet, PacketKind};

pub mod parapet;
pub mod interactive;
pub mod network;
pub mod error;
pub mod protocol;
pub mod ci;

pub const SERVER_PORT: u16 = 53371;
pub const SERVER_ADDRESS: (&'static str, u16) = ("127.0.0.1", SERVER_PORT);

pub const CLIENT_NAME: &'static str = "vanilla";
pub const CLIENT_VERSION: &'static str = env!("CARGO_PKG_VERSION");

pub const PROTOCOL_MAJOR: u16 = 0;
pub const PROTOCOL_REVISION: u16 = 0;

pub fn user_agent() -> protocol::UserAgent {
    protocol::UserAgent {
        client: format!("{} v{}", CLIENT_NAME, CLIENT_VERSION),
        protocol_major: PROTOCOL_MAJOR,
        protocol_revision: PROTOCOL_REVISION,
    }
}

<|endoftext|>


<commit_before>#![doc(
    test(attr(deny(warnings))),
    test(attr(allow(bare_trait_objects, unknown_lints)))
)]
#![warn(missing_docs)]
// Don't fail on links to things not enabled in features
#![allow(
    unknown_lints,
    renamed_and_removed_lints,
    intra_doc_link_resolution_failure,
    broken_intra_doc_links
)]
// These little nifty labels saying that something needs a feature to be enabled
#![cfg_attr(docsrs, feature(doc_cfg))]
//! Library for easier and safe Unix signal handling
//!
//! Unix signals are inherently hard to handle correctly, for several reasons:
//!
//! * They are a global resource. If a library wants to set its own signal handlers, it risks
//!   disturbing some other library. It is possible to chain the previous signal handler, but then
//!   it is impossible to remove the old signal handlers from the chains in any practical manner.
//! * They can be called from whatever thread, requiring synchronization. Also, as they can
//!   interrupt a thread at any time, making most handling race-prone.
//! * According to the POSIX standard, the set of functions one may call inside a signal handler is
//!   limited to very few of them. To highlight, mutexes (or other locking mechanisms) and memory
//!   allocation and deallocation is *not* allowed.
//!
//! # The easy way
//!
//! If you are interested in the easiest way to handle signals, head over to the
//! [`Signals`][crate::iterator] iterator. It is one of the abstractions provided by this library
//! and probably the easiest one to use and with the least amount of catches.
//!
//! Note that they still are some catches, most importantly that both the OS and the library may
//! collate multiple instances of the same signal into one (if you're not consuming fast enough).
//!
//! If you want an asynchronous version, see below for extension crates giving you that support.
//!
//! Otherwise, read on for the full details.
//!
//! # Details
//!
//! This library aims to solve some of the problems. It provides a global registry of actions
//! performed on arrival of signals. It is possible to register multiple actions for the same
//! signal and it is possible to remove the actions later on. If there was a previous signal
//! handler when the first action for a signal is registered, it is chained (but the original one
//! can't be removed).
//!
//! The main function of the library is [`register`](fn.register.html).
//!
//! It also offers several common actions one might want to register, implemented in the correct
//! way. They are scattered through submodules and have the same limitations and characteristics as
//! the [`register`](fn.register.html) function. Generally, they work to postpone the action taken
//! outside of the signal handler, where the full freedom and power of rust is available.
//!
//! Unlike other Rust libraries for signal handling, this should be flexible enough to handle all
//! the common and useful patterns.
//!
//! The library avoids all the newer fancy signal-handling routines. These generally have two
//! downsides:
//!
//! * They are not fully portable, therefore the library would have to contain *both* the
//!   implementation using the basic routines and the fancy ones. As signal handling is not on the
//!   hot path of most programs, this would not bring any actual benefit.
//! * The other routines require that the given signal is masked in all application's threads. As
//!   the signals are not masked by default and a new thread inherits the signal mask of its
//!   parent, it is possible to guarantee such global mask by masking them before any threads
//!   start. While this is possible for an application developer to do, it is not possible for a
//!   a library.
//!
//! # Warning
//!
//! Even with this library, you should thread with care. It does not eliminate all the problems
//! mentioned above.
//!
//! Also, note that the OS may collate multiple instances of the same signal into just one call of
//! the signal handler. Furthermore, some abstractions implemented here also naturally collate
//! multiple instances of the same signal. The general guarantee is, if there was at least one
//! signal of the given number delivered, an action will be taken, but it is not specified how many
//! times ‒ signals work mostly as kind of „wake up now“ nudge, if the application is slow to wake
//! up, it may be nudged multiple times before it does so.
//!
//! # Signal limitations
//!
//! OS limits still apply ‒ it is not possible to redefine certain signals (eg. `SIGKILL` or
//! `SIGSTOP`) and it is probably a *very* stupid idea to touch certain other ones (`SIGSEGV`,
//! `SIGFPE`, `SIGILL`). Therefore, this library will panic if any attempt at manipulating these is
//! made. There are some use cases for redefining the latter ones, but these are not well served by
//! this library and you really *really* have to know what you're doing and are generally on your
//! own doing that. You can, however, have a look at the very low level API in
//! [`signal_hook_registry`].
//!
//! # Signal masks
//!
//! As the library uses `sigaction` under the hood, signal masking works as expected (eg. with
//! `pthread_sigmask`). This means, signals will *not* be delivered if the signal is masked in all
//! program's threads.
//!
//! By the way, if you do want to modify the signal mask (or do other Unix-specific magic), the
//! [nix](https://crates.io/crates/nix) crate offers safe interface to many low-level functions,
//! including
//! [`pthread_sigmask`](https://docs.rs/nix/0.11.0/nix/sys/signal/fn.pthread_sigmask.html).
//!
//! # Portability
//!
//! It should work on any POSIX.1-2001 system, which are all the major big OSes with the notable
//! exception of Windows.
//!
//! Non-standard signals are also supported. Pass the signal value directly from `libc` or use
//! the numeric value directly.
//!
//! ```rust
//! use std::sync::Arc;
//! use std::sync::atomic::{AtomicBool};
//! let term = Arc::new(AtomicBool::new(false));
//! let _ = signal_hook::flag::register(libc::SIGINT, Arc::clone(&term));
//! ```
//!
//! This crate includes a limited support for Windows, based on `signal`/`raise` in the CRT.
//! There are differences in both API and behavior:
//!
//! - `iterator` and `pipe` are not yet implemented.
//! - We have only a few signals: `SIGABRT`, `SIGABRT_COMPAT`, `SIGBREAK`,
//!   `SIGFPE`, `SIGILL`, `SIGINT`, `SIGSEGV` and `SIGTERM`.
//! - Due to lack of signal blocking, there's a race condition.
//!   After the call to `signal`, there's a moment where we miss a signal.
//!   That means when you register a handler, there may be a signal which invokes
//!   neither the default handler or the handler you register.
//! - Handlers registered by `signal` in Windows are cleared on first signal.
//!   To match behavior in other platforms, we re-register the handler each time the handler is
//!   called, but there's a moment where we miss a handler.
//!   That means when you receive two signals in a row, there may be a signal which invokes
//!   the default handler, nevertheless you certainly have registered the handler.
//!
//! Moreover, signals won't work as you expected. `SIGTERM` isn't actually used and
//! not all `Ctrl-C`s are turned into `SIGINT`.
//!
//! Patches to improve Windows support in this library are welcome.
//!
//! # Examples
//!
//! ```rust
//! extern crate signal_hook;
//!
//! use std::io::Error;
//! use std::sync::Arc;
//! use std::sync::atomic::{AtomicBool, Ordering};
//!
//! fn main() -> Result<(), Error> {
//!     let term = Arc::new(AtomicBool::new(false));
//!     signal_hook::flag::register(signal_hook::SIGTERM, Arc::clone(&term))?;
//!     while !term.load(Ordering::Relaxed) {
//!         // Do some time-limited stuff here
//!         // (if this could block forever, then there's no guarantee the signal will have any
//!         // effect).
//! #
//! #       // Hack to terminate the example, not part of the real code.
//! #       term.store(true, Ordering::Relaxed);
//!     }
//!     Ok(())
//! }
//! ```
//!
//! # Asynchronous runtime support
//!
//! If you are looking for integration with an asynchronous runtime take a look at one of the
//! following adapter crates:
//!
//! * [`signal-hook-async-std`](https://docs.rs/signal-hook-async-std) for async-std support
//! * [`signal-hook-mio`](https://docs.rs/signal-hook-mio) for MIO support
//! * [`signal-hook-tokio`](https://docs.rs/signal-hook-tokio) for Tokio support
//!
//! Feel free to open a pull requests if you want to add support for runtimes not mentioned above.

extern crate libc;
extern crate signal_hook_registry;

pub mod cleanup;
pub mod flag;
#[cfg(all(not(windows), feature = "iterator"))]
pub mod iterator;
#[cfg(not(windows))]
pub mod pipe;

#[cfg(not(windows))]
pub use libc::{
    SIGABRT, SIGALRM, SIGBUS, SIGCHLD, SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGIO, SIGKILL,
    SIGPIPE, SIGPROF, SIGQUIT, SIGSEGV, SIGSTOP, SIGSYS, SIGTERM, SIGTRAP, SIGUSR1, SIGUSR2,
    SIGWINCH,
};

#[cfg(windows)]
pub use libc::{SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM};

// NOTE: they perhaps deserve backport to libc.
#[cfg(windows)]
/// Same as `SIGABRT`, but the number is compatible to other platforms.
pub const SIGABRT_COMPAT: libc::c_int = 6;
#[cfg(windows)]
/// Ctrl-Break is pressed for Windows Console processes.
pub const SIGBREAK: libc::c_int = 21;

pub use signal_hook_registry::{register, unregister, SigId, FORBIDDEN};
<commit_msg>Add additional signal reexports<commit_after>#![doc(
    test(attr(deny(warnings))),
    test(attr(allow(bare_trait_objects, unknown_lints)))
)]
#![warn(missing_docs)]
// Don't fail on links to things not enabled in features
#![allow(
    unknown_lints,
    renamed_and_removed_lints,
    intra_doc_link_resolution_failure,
    broken_intra_doc_links
)]
// These little nifty labels saying that something needs a feature to be enabled
#![cfg_attr(docsrs, feature(doc_cfg))]
//! Library for easier and safe Unix signal handling
//!
//! Unix signals are inherently hard to handle correctly, for several reasons:
//!
//! * They are a global resource. If a library wants to set its own signal handlers, it risks
//!   disturbing some other library. It is possible to chain the previous signal handler, but then
//!   it is impossible to remove the old signal handlers from the chains in any practical manner.
//! * They can be called from whatever thread, requiring synchronization. Also, as they can
//!   interrupt a thread at any time, making most handling race-prone.
//! * According to the POSIX standard, the set of functions one may call inside a signal handler is
//!   limited to very few of them. To highlight, mutexes (or other locking mechanisms) and memory
//!   allocation and deallocation is *not* allowed.
//!
//! # The easy way
//!
//! If you are interested in the easiest way to handle signals, head over to the
//! [`Signals`][crate::iterator] iterator. It is one of the abstractions provided by this library
//! and probably the easiest one to use and with the least amount of catches.
//!
//! Note that they still are some catches, most importantly that both the OS and the library may
//! collate multiple instances of the same signal into one (if you're not consuming fast enough).
//!
//! If you want an asynchronous version, see below for extension crates giving you that support.
//!
//! Otherwise, read on for the full details.
//!
//! # Details
//!
//! This library aims to solve some of the problems. It provides a global registry of actions
//! performed on arrival of signals. It is possible to register multiple actions for the same
//! signal and it is possible to remove the actions later on. If there was a previous signal
//! handler when the first action for a signal is registered, it is chained (but the original one
//! can't be removed).
//!
//! The main function of the library is [`register`](fn.register.html).
//!
//! It also offers several common actions one might want to register, implemented in the correct
//! way. They are scattered through submodules and have the same limitations and characteristics as
//! the [`register`](fn.register.html) function. Generally, they work to postpone the action taken
//! outside of the signal handler, where the full freedom and power of rust is available.
//!
//! Unlike other Rust libraries for signal handling, this should be flexible enough to handle all
//! the common and useful patterns.
//!
//! The library avoids all the newer fancy signal-handling routines. These generally have two
//! downsides:
//!
//! * They are not fully portable, therefore the library would have to contain *both* the
//!   implementation using the basic routines and the fancy ones. As signal handling is not on the
//!   hot path of most programs, this would not bring any actual benefit.
//! * The other routines require that the given signal is masked in all application's threads. As
//!   the signals are not masked by default and a new thread inherits the signal mask of its
//!   parent, it is possible to guarantee such global mask by masking them before any threads
//!   start. While this is possible for an application developer to do, it is not possible for a
//!   a library.
//!
//! # Warning
//!
//! Even with this library, you should thread with care. It does not eliminate all the problems
//! mentioned above.
//!
//! Also, note that the OS may collate multiple instances of the same signal into just one call of
//! the signal handler. Furthermore, some abstractions implemented here also naturally collate
//! multiple instances of the same signal. The general guarantee is, if there was at least one
//! signal of the given number delivered, an action will be taken, but it is not specified how many
//! times ‒ signals work mostly as kind of „wake up now“ nudge, if the application is slow to wake
//! up, it may be nudged multiple times before it does so.
//!
//! # Signal limitations
//!
//! OS limits still apply ‒ it is not possible to redefine certain signals (eg. `SIGKILL` or
//! `SIGSTOP`) and it is probably a *very* stupid idea to touch certain other ones (`SIGSEGV`,
//! `SIGFPE`, `SIGILL`). Therefore, this library will panic if any attempt at manipulating these is
//! made. There are some use cases for redefining the latter ones, but these are not well served by
//! this library and you really *really* have to know what you're doing and are generally on your
//! own doing that. You can, however, have a look at the very low level API in
//! [`signal_hook_registry`].
//!
//! # Signal masks
//!
//! As the library uses `sigaction` under the hood, signal masking works as expected (eg. with
//! `pthread_sigmask`). This means, signals will *not* be delivered if the signal is masked in all
//! program's threads.
//!
//! By the way, if you do want to modify the signal mask (or do other Unix-specific magic), the
//! [nix](https://crates.io/crates/nix) crate offers safe interface to many low-level functions,
//! including
//! [`pthread_sigmask`](https://docs.rs/nix/0.11.0/nix/sys/signal/fn.pthread_sigmask.html).
//!
//! # Portability
//!
//! It should work on any POSIX.1-2001 system, which are all the major big OSes with the notable
//! exception of Windows.
//!
//! Non-standard signals are also supported. Pass the signal value directly from `libc` or use
//! the numeric value directly.
//!
//! ```rust
//! use std::sync::Arc;
//! use std::sync::atomic::{AtomicBool};
//! let term = Arc::new(AtomicBool::new(false));
//! let _ = signal_hook::flag::register(libc::SIGINT, Arc::clone(&term));
//! ```
//!
//! This crate includes a limited support for Windows, based on `signal`/`raise` in the CRT.
//! There are differences in both API and behavior:
//!
//! - `iterator` and `pipe` are not yet implemented.
//! - We have only a few signals: `SIGABRT`, `SIGABRT_COMPAT`, `SIGBREAK`,
//!   `SIGFPE`, `SIGILL`, `SIGINT`, `SIGSEGV` and `SIGTERM`.
//! - Due to lack of signal blocking, there's a race condition.
//!   After the call to `signal`, there's a moment where we miss a signal.
//!   That means when you register a handler, there may be a signal which invokes
//!   neither the default handler or the handler you register.
//! - Handlers registered by `signal` in Windows are cleared on first signal.
//!   To match behavior in other platforms, we re-register the handler each time the handler is
//!   called, but there's a moment where we miss a handler.
//!   That means when you receive two signals in a row, there may be a signal which invokes
//!   the default handler, nevertheless you certainly have registered the handler.
//!
//! Moreover, signals won't work as you expected. `SIGTERM` isn't actually used and
//! not all `Ctrl-C`s are turned into `SIGINT`.
//!
//! Patches to improve Windows support in this library are welcome.
//!
//! # Examples
//!
//! ```rust
//! extern crate signal_hook;
//!
//! use std::io::Error;
//! use std::sync::Arc;
//! use std::sync::atomic::{AtomicBool, Ordering};
//!
//! fn main() -> Result<(), Error> {
//!     let term = Arc::new(AtomicBool::new(false));
//!     signal_hook::flag::register(signal_hook::SIGTERM, Arc::clone(&term))?;
//!     while !term.load(Ordering::Relaxed) {
//!         // Do some time-limited stuff here
//!         // (if this could block forever, then there's no guarantee the signal will have any
//!         // effect).
//! #
//! #       // Hack to terminate the example, not part of the real code.
//! #       term.store(true, Ordering::Relaxed);
//!     }
//!     Ok(())
//! }
//! ```
//!
//! # Asynchronous runtime support
//!
//! If you are looking for integration with an asynchronous runtime take a look at one of the
//! following adapter crates:
//!
//! * [`signal-hook-async-std`](https://docs.rs/signal-hook-async-std) for async-std support
//! * [`signal-hook-mio`](https://docs.rs/signal-hook-mio) for MIO support
//! * [`signal-hook-tokio`](https://docs.rs/signal-hook-tokio) for Tokio support
//!
//! Feel free to open a pull requests if you want to add support for runtimes not mentioned above.

extern crate libc;
extern crate signal_hook_registry;

pub mod cleanup;
pub mod flag;
#[cfg(all(not(windows), feature = "iterator"))]
pub mod iterator;
#[cfg(not(windows))]
pub mod pipe;

#[cfg(not(windows))]
pub use libc::{
    SIGABRT, SIGALRM, SIGBUS, SIGCHLD, SIGCONT, SIGFPE, SIGHUP, SIGILL, SIGINT, SIGIO, SIGKILL,
    SIGPIPE, SIGPROF, SIGQUIT, SIGSEGV, SIGSTOP, SIGSYS, SIGTERM, SIGTRAP, SIGUSR1, SIGUSR2,
    SIGWINCH, SIGTSTP, SIGPWR, SIGTTIN, SIGTTOU, SIGURG, SIGVTALRM, SIGXCPU, SIGXFSZ,
};

#[cfg(windows)]
pub use libc::{SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM};

// NOTE: they perhaps deserve backport to libc.
#[cfg(windows)]
/// Same as `SIGABRT`, but the number is compatible to other platforms.
pub const SIGABRT_COMPAT: libc::c_int = 6;
#[cfg(windows)]
/// Ctrl-Break is pressed for Windows Console processes.
pub const SIGBREAK: libc::c_int = 21;

pub use signal_hook_registry::{register, unregister, SigId, FORBIDDEN};
<|endoftext|>


<commit_before>#![crate_name = "abc"]
#![crate_type = "lib"]
#![doc(html_root_url = "https://daviddonna.github.io/abc-rs/")]

#![warn(missing_docs)]

//! Runs Karaboga's Artificial Bee Colony algorithm in parallel.
//!
//! To take advantage of this crate, the user must implement the
//! [`Solution`](trait.Solution.html) trait for a type of their creation.
//! A [`Hive`](struct.Hive.html) of the appropriate type can then be built,
//! which will search the solution space for the fittest candidate.
//!
//! # Examples
//!
//! ```
//! // ABC algorithm with canonical (proportionate) fitness scaling
//! // to minimize the 10-dimensional Rastrigin function.
//!
//! extern crate abc;
//! extern crate rand;
//!
//! use std::f32::consts::PI;
//! use rand::{random, Closed01, thread_rng, Rng};
//! use abc::{Solution, Candidate, HiveBuilder};
//!
//! const SIZE: usize = 10;
//!
//! #[derive(Clone, Debug)]
//! struct S([f32;SIZE]);
//!
//! // Not really necessary; we're using this mostly to demonstrate usage.
//! struct SBuilder {
//!     min: f32,
//!     max: f32,
//! }
//!
//! impl Solution for S {
//!     type Builder = SBuilder;
//!
//!     fn make(builder: &mut SBuilder) -> S {
//!         let mut new = [0.0;SIZE];
//!         for i in 0..SIZE {
//!             let Closed01(x) = random::<Closed01<f32>>();
//!             new[i] = (x * (builder.max - builder.min)) + builder.min;
//!         }
//!         S(new)
//!     }
//!
//!     fn evaluate_fitness(&self) -> f64 {
//!         let a = 10.0;
//!         let sum = self.0.iter()
//!                         .map(|x| x.powf(2.0) - a * (*x * 2.0 * PI).cos())
//!                         .fold(0.0, |total, next| total + next);
//!         let rastrigin = ((a * SIZE as f32) + sum) as f64;
//!
//!         // Minimize.
//!         if rastrigin >= 0.0 {
//!             1.0 / (1.0 + rastrigin)
//!         } else {
//!             1.0 + rastrigin.abs()
//!         }
//!     }
//!
//!     fn explore(field: &[Candidate<S>], index: usize) -> S {
//!         // new[i] = current[i] + Φ * (current[i] - other[i]), where:
//!         //      -1.0 <= Φ <= 1.0
//!         //      other is a solution, other than current, chosen at random
//!
//!         let S(ref current) = field[index].solution;
//!         let mut new = [0_f32;SIZE];
//!
//!         for i in 0..SIZE {
//!             // Choose a different vector at random.
//!             let mut rng = thread_rng();
//!             let mut index2 = rng.gen_range(0, current.len() - 1);
//!             if index2 >= index { index2 += 1; }
//!             let S(ref other) = field[index2].solution;
//!
//!             let phi = random::<Closed01<f32>>().0 * 2.0 - 1.0;
//!             new[i] = current[i] + (phi * (current[i] - other[i]));
//!         }
//!
//!         S(new)
//!     }
//! }
//!
//! fn main() {
//!     let mut builder = SBuilder { min: -5.12, max: 5.12 };
//!     let hive = HiveBuilder::<S>::new(builder, 10);
//!     println!("{:?}", hive.build().unwrap().run_for_rounds(100).unwrap());
//! }
//! ```

mod result;
mod task;
mod solution;
mod candidate;
mod hive;

pub mod scaling;

pub use result::{Error, Result};
pub use solution::Solution;
pub use candidate::Candidate;
pub use hive::{HiveBuilder, Hive};
<commit_msg>Demonstrate more functionality in crate example<commit_after>#![crate_name = "abc"]
#![crate_type = "lib"]
#![doc(html_root_url = "https://daviddonna.github.io/abc-rs/")]

#![warn(missing_docs)]

//! Runs Karaboga's Artificial Bee Colony algorithm in parallel.
//!
//! To take advantage of this crate, the user must implement the
//! [`Solution`](trait.Solution.html) trait for a type of their creation.
//! A [`Hive`](struct.Hive.html) of the appropriate type can then be built,
//! which will search the solution space for the fittest candidate.
//!
//! # Examples
//!
//! ```
//! // ABC algorithm with canonical (proportionate) fitness scaling
//! // to minimize the 10-dimensional Rastrigin function.
//!
//! extern crate abc;
//! extern crate rand;
//!
//! use std::f32::consts::PI;
//! use rand::{random, Closed01, thread_rng, Rng};
//! use abc::{Solution, Candidate, HiveBuilder};
//!
//! const SIZE: usize = 10;
//!
//! #[derive(Clone, Debug)]
//! struct S([f32;SIZE]);
//!
//! // Not really necessary; we're using this mostly to demonstrate usage.
//! struct SBuilder {
//!     min: f32,
//!     max: f32,
//! }
//!
//! impl Solution for S {
//!     type Builder = SBuilder;
//!
//!     fn make(builder: &mut SBuilder) -> S {
//!         let mut new = [0.0;SIZE];
//!         for i in 0..SIZE {
//!             let Closed01(x) = random::<Closed01<f32>>();
//!             new[i] = (x * (builder.max - builder.min)) + builder.min;
//!         }
//!         S(new)
//!     }
//!
//!     fn evaluate_fitness(&self) -> f64 {
//!         let a = 10.0;
//!         let sum = self.0.iter()
//!                         .map(|x| x.powf(2.0) - a * (*x * 2.0 * PI).cos())
//!                         .fold(0.0, |total, next| total + next);
//!         let rastrigin = ((a * SIZE as f32) + sum) as f64;
//!
//!         // Minimize.
//!         if rastrigin >= 0.0 {
//!             1.0 / (1.0 + rastrigin)
//!         } else {
//!             1.0 + rastrigin.abs()
//!         }
//!     }
//!
//!     fn explore(field: &[Candidate<S>], index: usize) -> S {
//!         // new[i] = current[i] + Φ * (current[i] - other[i]), where:
//!         //      -1.0 <= Φ <= 1.0
//!         //      other is a solution, other than current, chosen at random
//!
//!         let S(ref current) = field[index].solution;
//!         let mut new = [0_f32;SIZE];
//!
//!         for i in 0..SIZE {
//!             // Choose a different vector at random.
//!             let mut rng = thread_rng();
//!             let mut index2 = rng.gen_range(0, current.len() - 1);
//!             if index2 >= index { index2 += 1; }
//!             let S(ref other) = field[index2].solution;
//!
//!             let phi = random::<Closed01<f32>>().0 * 2.0 - 1.0;
//!             new[i] = current[i] + (phi * (current[i] - other[i]));
//!         }
//!
//!         S(new)
//!     }
//! }
//!
//! fn main() {
//!     let mut builder = SBuilder { min: -5.12, max: 5.12 };
//!     let hive_builder = HiveBuilder::<S>::new(builder, 10);
//!     let hive = hive_builder.build().unwrap();
//!
//!     // Once built, the hive can be run for a number of rounds.
//!     let best_after_100 = hive.run_for_rounds(100).unwrap();
//!
//!     // As long as it's run some rounds at a time, you can keep running it.
//!     let best_after_200 = hive.run_for_rounds(100).unwrap();
//!
//!     // The algorithm doesn't guarantee improvement in any number of rounds,
//!     // but it always keeps its all-time best.
//!     assert!(best_after_200.fitness >= best_after_100.fitness);
//!
//!     // The hive can be consumed to create a Receiver object. This can be
//!     // iterated over indefinitely, and will receive successive improvements
//!     // on the best candidate so far.
//!     let mut current_best_fitness = best_after_200.fitness;
//!     for new_best in hive.stream().iter().take(5) {
//!         assert!(new_best.fitness > current_best_fitness);
//!         current_best_fitness = new_best.fitness;
//!     }
//! }
//! ```

mod result;
mod task;
mod solution;
mod candidate;
mod hive;

pub mod scaling;

pub use result::{Error, Result};
pub use solution::Solution;
pub use candidate::Candidate;
pub use hive::{HiveBuilder, Hive};
<|endoftext|>


<commit_before>//! jsonrpc http server.
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate jsonrpc_http_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use jsonrpc_http_server::*;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let _server = Server::start(&"127.0.0.1:3030".parse().unwrap(), Arc::new(io), AccessControlAllowOrigin::Null);
//! }
//! ```

extern crate hyper;
extern crate unicase;
extern crate jsonrpc_core as jsonrpc;

use std::sync::Arc;
use std::io::{Read, Write};
use std::net::SocketAddr;
use hyper::header::{Headers, Allow, ContentType, AccessControlAllowHeaders};
use hyper::method::Method;
use hyper::server::{Request, Response};
use hyper::{Next, Encoder, Decoder};
use hyper::net::HttpStream;
use unicase::UniCase;
use self::jsonrpc::{IoHandler};

pub use hyper::header::AccessControlAllowOrigin;

pub type ServerResult = Result<Server, RpcServerError>;

/// RPC Server startup error
#[derive(Debug)]
pub enum RpcServerError {
	IoError(std::io::Error),
	Other(hyper::error::Error),
}

impl From<hyper::error::Error> for RpcServerError {
	fn from(err: hyper::error::Error) -> Self {
		match err {
			hyper::error::Error::Io(e) => RpcServerError::IoError(e),
			e => RpcServerError::Other(e)
		}
	}
}
/// jsonrpc http request handler.
pub struct ServerHandler {
	jsonrpc_handler: Arc<IoHandler>,
	cors_domain: AccessControlAllowOrigin,
	request: String,
	response: Option<String>,
}

impl ServerHandler {
	/// Create new request handler.
	pub fn new(jsonrpc_handler: Arc<IoHandler>, cors_domain: AccessControlAllowOrigin) -> Self {
		ServerHandler {
			jsonrpc_handler: jsonrpc_handler,
			cors_domain: cors_domain,
			request: String::new(),
			response: None,
		}
	}

	fn response_headers(&self) -> Headers {
		let mut headers = Headers::new();
		headers.set(
			Allow(vec![
				Method::Options, Method::Post
			])
		);
		headers.set(ContentType::json());
		headers.set(
			AccessControlAllowHeaders(vec![
				UniCase("origin".to_owned()),
				UniCase("content-type".to_owned()),
				UniCase("accept".to_owned()),
			])
		);
		headers.set(self.cors_domain.clone());
		headers
	}
}

impl hyper::server::Handler<HttpStream> for ServerHandler {
    fn on_request(&mut self, request: Request) -> Next {
		match *request.method() {
			Method::Options => {
				self.response = Some(String::new());
				Next::write()
			},
			Method::Post => Next::read(),
			_ => Next::write(),
		}
	}

    /// This event occurs each time the `Request` is ready to be read from.
    fn on_request_readable(&mut self, decoder: &mut Decoder<HttpStream>) -> Next {
		match decoder.read_to_string(&mut self.request) {
			Ok(0) => {
				self.response = self.jsonrpc_handler.handle_request(&self.request);
				Next::write()
			}
			Ok(_) => {
				Next::read()
			}
			Err(e) => match e.kind() {
				::std::io::ErrorKind::WouldBlock => Next::read(),
				_ => {
					//trace!("Read error: {}", e);
					Next::end()
				}
			}
		}
	}

    /// This event occurs after the first time this handled signals `Next::write()`.
    fn on_response(&mut self, response: &mut Response) -> Next {
		*response.headers_mut() = self.response_headers();
		if self.response.is_none() {
			response.set_status(hyper::status::StatusCode::MethodNotAllowed);
		}
		Next::write()
	}

    /// This event occurs each time the `Response` is ready to be written to.
    fn on_response_writable(&mut self, encoder: &mut Encoder<HttpStream>) -> Next {
		if let Some(ref response) = self.response {
			encoder.write(response.as_bytes()).unwrap();
		}
		Next::end()
	}
}

/// jsonrpc http server.
///
/// ```no_run
/// extern crate jsonrpc_core;
/// extern crate jsonrpc_http_server;
///
/// use std::sync::Arc;
/// use jsonrpc_core::*;
/// use jsonrpc_http_server::*;
///
/// struct SayHello;
/// impl MethodCommand for SayHello {
/// 	fn execute(&self, _params: Params) -> Result<Value, Error> {
/// 		Ok(Value::String("hello".to_string()))
/// 	}
/// }
///
/// fn main() {
/// 	let io = IoHandler::new();
/// 	io.add_method("say_hello", SayHello);
/// 	let _server = Server::start(&"127.0.0.1:3030".parse().unwrap(), Arc::new(io), AccessControlAllowOrigin::Null);
/// }
/// ```
pub struct Server {
	_server: hyper::server::Listening,
}

impl Server {
	pub fn start(addr: &SocketAddr, jsonrpc_handler: Arc<IoHandler>, cors_domain: AccessControlAllowOrigin) -> ServerResult {
		let srv = try!(try!(hyper::Server::http(addr)).handle(move |_| ServerHandler::new(jsonrpc_handler.clone(), cors_domain.clone())));
		Ok(Server {
			_server: srv,
		})
	}
}
<commit_msg>Fixed shutdown<commit_after>//! jsonrpc http server.
//!
//! ```no_run
//! extern crate jsonrpc_core;
//! extern crate jsonrpc_http_server;
//!
//! use std::sync::Arc;
//! use jsonrpc_core::*;
//! use jsonrpc_http_server::*;
//!
//! struct SayHello;
//! impl MethodCommand for SayHello {
//! 	fn execute(&self, _params: Params) -> Result<Value, Error> {
//! 		Ok(Value::String("hello".to_string()))
//! 	}
//! }
//!
//! fn main() {
//! 	let io = IoHandler::new();
//! 	io.add_method("say_hello", SayHello);
//! 	let _server = Server::start(&"127.0.0.1:3030".parse().unwrap(), Arc::new(io), AccessControlAllowOrigin::Null);
//! }
//! ```

extern crate hyper;
extern crate unicase;
extern crate jsonrpc_core as jsonrpc;

use std::sync::Arc;
use std::io::{Read, Write};
use std::net::SocketAddr;
use hyper::header::{Headers, Allow, ContentType, AccessControlAllowHeaders};
use hyper::method::Method;
use hyper::server::{Request, Response};
use hyper::{Next, Encoder, Decoder};
use hyper::net::HttpStream;
use unicase::UniCase;
use self::jsonrpc::{IoHandler};

pub use hyper::header::AccessControlAllowOrigin;

pub type ServerResult = Result<Server, RpcServerError>;

/// RPC Server startup error
#[derive(Debug)]
pub enum RpcServerError {
	IoError(std::io::Error),
	Other(hyper::error::Error),
}

impl From<hyper::error::Error> for RpcServerError {
	fn from(err: hyper::error::Error) -> Self {
		match err {
			hyper::error::Error::Io(e) => RpcServerError::IoError(e),
			e => RpcServerError::Other(e)
		}
	}
}
/// jsonrpc http request handler.
pub struct ServerHandler {
	jsonrpc_handler: Arc<IoHandler>,
	cors_domain: AccessControlAllowOrigin,
	request: String,
	response: Option<String>,
}

impl ServerHandler {
	/// Create new request handler.
	pub fn new(jsonrpc_handler: Arc<IoHandler>, cors_domain: AccessControlAllowOrigin) -> Self {
		ServerHandler {
			jsonrpc_handler: jsonrpc_handler,
			cors_domain: cors_domain,
			request: String::new(),
			response: None,
		}
	}

	fn response_headers(&self) -> Headers {
		let mut headers = Headers::new();
		headers.set(
			Allow(vec![
				Method::Options, Method::Post
			])
		);
		headers.set(ContentType::json());
		headers.set(
			AccessControlAllowHeaders(vec![
				UniCase("origin".to_owned()),
				UniCase("content-type".to_owned()),
				UniCase("accept".to_owned()),
			])
		);
		headers.set(self.cors_domain.clone());
		headers
	}
}

impl hyper::server::Handler<HttpStream> for ServerHandler {
    fn on_request(&mut self, request: Request) -> Next {
		match *request.method() {
			Method::Options => {
				self.response = Some(String::new());
				Next::write()
			},
			Method::Post => Next::read(),
			_ => Next::write(),
		}
	}

    /// This event occurs each time the `Request` is ready to be read from.
    fn on_request_readable(&mut self, decoder: &mut Decoder<HttpStream>) -> Next {
		match decoder.read_to_string(&mut self.request) {
			Ok(0) => {
				self.response = self.jsonrpc_handler.handle_request(&self.request);
				Next::write()
			}
			Ok(_) => {
				Next::read()
			}
			Err(e) => match e.kind() {
				::std::io::ErrorKind::WouldBlock => Next::read(),
				_ => {
					//trace!("Read error: {}", e);
					Next::end()
				}
			}
		}
	}

    /// This event occurs after the first time this handled signals `Next::write()`.
    fn on_response(&mut self, response: &mut Response) -> Next {
		*response.headers_mut() = self.response_headers();
		if self.response.is_none() {
			response.set_status(hyper::status::StatusCode::MethodNotAllowed);
		}
		Next::write()
	}

    /// This event occurs each time the `Response` is ready to be written to.
    fn on_response_writable(&mut self, encoder: &mut Encoder<HttpStream>) -> Next {
		if let Some(ref response) = self.response {
			encoder.write(response.as_bytes()).unwrap();
		}
		Next::end()
	}
}

/// jsonrpc http server.
///
/// ```no_run
/// extern crate jsonrpc_core;
/// extern crate jsonrpc_http_server;
///
/// use std::sync::Arc;
/// use jsonrpc_core::*;
/// use jsonrpc_http_server::*;
///
/// struct SayHello;
/// impl MethodCommand for SayHello {
/// 	fn execute(&self, _params: Params) -> Result<Value, Error> {
/// 		Ok(Value::String("hello".to_string()))
/// 	}
/// }
///
/// fn main() {
/// 	let io = IoHandler::new();
/// 	io.add_method("say_hello", SayHello);
/// 	let _server = Server::start(&"127.0.0.1:3030".parse().unwrap(), Arc::new(io), AccessControlAllowOrigin::Null);
/// }
/// ```
pub struct Server {
	server: Option<hyper::server::Listening>,
}

impl Server {
	pub fn start(addr: &SocketAddr, jsonrpc_handler: Arc<IoHandler>, cors_domain: AccessControlAllowOrigin) -> ServerResult {
		let srv = try!(try!(hyper::Server::http(addr)).handle(move |_| ServerHandler::new(jsonrpc_handler.clone(), cors_domain.clone())));
		Ok(Server {
			server: Some(srv),
		})
	}
}

impl Drop for Server {
	fn drop(&mut self) {
		self.server.take().unwrap().close()
	}
}
<|endoftext|>


<commit_before>#![allow(non_camel_case_types,non_upper_case_globals,non_snake_case)]

extern crate CoreFoundation_sys as cf;
extern crate libc;
extern crate mach;

use cf::{CFTypeRef,CFDictionaryRef,CFMutableDictionaryRef,CFStringRef,CFAllocatorRef};
use libc::{c_void,c_char,c_int,size_t,uintptr_t};

use mach::boolean::boolean_t;
use mach::clock_types::mach_timespec_t;
use mach::kern_return::kern_return_t;
use mach::port::mach_port_t;
use mach::types::task_port_t;
use mach::vm_types::{mach_vm_address_t,mach_vm_size_t};

pub use io_return::*;
pub use keys::*;
pub use serial::*;
pub use types::*;
pub use usb::*;
pub use io_hid_keys::*;
pub use io_hid_base::*;
pub use io_hid_manager::*;

mod io_return;
mod keys;
mod serial;
mod types;
mod usb;
mod io_hid_keys;
mod io_hid_base;
mod io_hid_manager;

// exports from <IOKit/IOKitLib.h>

#[repr(C)]
pub struct IONotificationPort {
    __private: c_void,
}

pub type IONotificationPortRef = *mut IONotificationPort;

pub type IOServiceMatchingCallback = extern fn (refcon: *mut c_void, iterator: io_iterator_t);
pub type IOServiceInterestCallback = extern fn (refcon: *mut c_void, service: io_service_t, messageType: u32, messageArgument: *mut c_void);

// options for IOServiceAuthorize()
pub const kIOServiceInteractionAllowed: u32 = 0x00000001;

// options for IORegistryCreateIterator(), IORegistryEntryCreateIterator(), IORegistryEntrySearchCFProperty()
pub const kIORegistryIterateRecursively: IOOptionBits = 0x00000001;
pub const kIORegistryIterateParents:     IOOptionBits = 0x00000002;

type IOAsyncCallback0 = extern fn (refcon: *mut c_void, result: IOReturn);
type IOAsyncCallback1 = extern fn (refcon: *mut c_void, result: IOReturn, arg0: *mut c_void);
type IOAsyncCallback2 = extern fn (refcon: *mut c_void, result: IOReturn, arg0: *mut c_void, arg1: *mut c_void);
type IOAsyncCallback = extern fn (refcon: *mut c_void, result: IOReturn, args: *mut *mut c_void, numArgs: u32);

extern "C" {
    pub static kIOMasterPortDefault: mach_port_t;

    pub fn IOMasterPort(bootstrapPort: mach_port_t, masterPort: *mut mach_port_t) -> kern_return_t;

    pub fn IONotificationPortCreate(masterPort: mach_port_t) -> IONotificationPortRef;
    pub fn IONotificationPortDestroy(notify: IONotificationPortRef);
    pub fn IONotificationPortGetMachPort(notify: IONotificationPortRef) -> mach_port_t;

    pub fn IOCreateReceivePort(msgType: u32, recvPort: *mut mach_port_t) -> kern_return_t;

    // IOObject

    pub fn IOObjectRelease(object: io_object_t) -> kern_return_t;
    pub fn IOObjectRetain(object: io_object_t) -> kern_return_t;
    pub fn IOObjectGetClass(object: io_object_t, className: *mut c_char) -> kern_return_t;
    pub fn IOObjectCopyClass(object: io_object_t) -> CFStringRef;
    pub fn IOObjectCopySuperclassForClass(classname: CFStringRef) -> CFStringRef;
    pub fn IOObjectCopyBundleIdentifierForClass(classname: CFStringRef) -> CFStringRef;
    pub fn IOObjectConformsTo(object: io_object_t, className: *const c_char) -> boolean_t;
    pub fn IOObjectGetKernelRetainCount(object: io_object_t) -> u32;
    pub fn IOObjectGetUserRetainCount(object: io_object_t) -> u32;
    pub fn IOObjectGetRetainCount(object: io_object_t) -> u32;

    // IOIterator, subclass of IOObject

    pub fn IOIteratorNext(iterator: io_iterator_t) -> io_object_t;
    pub fn IOIteratorReset(iterator: io_iterator_t);
    pub fn IOIteratorIsValid(iterator: io_iterator_t) -> boolean_t;

    // IOService, subclass of IORegistryEntry

    pub fn IOServiceGetMatchingService(masterPort: mach_port_t, matching: CFDictionaryRef) -> io_service_t;
    pub fn IOServiceGetMatchingServices(masterPort: mach_port_t, matching: CFDictionaryRef, existing: *mut io_iterator_t) -> kern_return_t;
    pub fn IOServiceAddNotification(masterPort: mach_port_t, notificationType: *const c_char, matching: CFDictionaryRef, wakePort: mach_port_t, reference: uintptr_t, notification: *mut io_iterator_t) -> kern_return_t;
    pub fn IOServiceAddMatchingNotification(notifyPort: IONotificationPortRef, notificationType: *const c_char, matching: CFDictionaryRef, callback: IOServiceMatchingCallback, refCon: *mut c_void, notification: *mut io_iterator_t) -> kern_return_t;
    pub fn IOServiceAddInterestNotification(notifyPort: IONotificationPortRef, service: io_service_t, interestType: *const c_char, callback: IOServiceInterestCallback, refCon: *mut c_void, notification: *mut io_object_t) -> kern_return_t;
    pub fn IOServiceMatchPropertyTable(service: io_service_t, matching: CFDictionaryRef, matches: *mut boolean_t) -> kern_return_t;
    pub fn IOServiceGetBusyState(service: io_service_t, busyState: *mut u32) -> kern_return_t;
    pub fn IOServiceWaitQuiet(service: io_service_t, waitTime: *mut mach_timespec_t) -> kern_return_t;

    pub fn IOKitGetBusyState(masterPort: mach_port_t, busyState: *mut u32) -> kern_return_t;
    pub fn IOKitWaitQuiet(masterPort: mach_port_t, waitTime: *mut mach_timespec_t) -> kern_return_t;

    pub fn IOServiceOpen(service: io_service_t, owningTask: task_port_t, connectionType: u32, connect: *mut io_connect_t) -> kern_return_t;
    pub fn IOServiceRequestProbe(service: io_service_t, options: u32) -> kern_return_t;
    pub fn IOServiceAuthorize(service: io_service_t, options: u32) -> kern_return_t;
    pub fn IOServiceOpenAsFileDescriptor(service: io_service_t, oflag: c_int) -> c_int;

    // IOService connection

    pub fn IOServiceClose(connect: io_connect_t) -> kern_return_t;
    pub fn IOConnectAddRef(connect: io_connect_t) -> kern_return_t;
    pub fn IOConnectRelease(connect: io_connect_t) -> kern_return_t;
    pub fn IOConnectGetService(connect: io_connect_t, service: *mut io_service_t) -> kern_return_t;
    pub fn IOConnectSetNotificationPort(connect: io_connect_t, notificationType: u32, port: mach_port_t, reference: uintptr_t) -> kern_return_t;
    pub fn IOConnectMapMemory64(connect: io_connect_t, memoryType: u32, intoTask: task_port_t, atAddress: *mut mach_vm_address_t, ofSize: *mut mach_vm_size_t, options: IOOptionBits) -> kern_return_t;
    pub fn IOConnectUnmapMemory64(connect: io_connect_t, memoryType: u32, fromTask: task_port_t, atAddress: mach_vm_address_t) -> kern_return_t;
    pub fn IOConnectSetCFProperties(connect: io_connect_t, properties: CFTypeRef) -> kern_return_t;
    pub fn IOConnectSetCFProperty(conect: io_connect_t, propertyName: CFStringRef, property: CFTypeRef) -> kern_return_t;

    pub fn IOConnectCallMethod(connection: mach_port_t, selector: u32, input: *const u64, inputCnt: u32, inputStruct: *const c_void, inputStructCnt: size_t, output: *mut u64, outputCnt: *mut u32, outputStruct: *mut c_void, outputStructCnt: *mut size_t) -> kern_return_t;
    pub fn IOConnectCallAsyncMethod(connection: mach_port_t, selector: u32, wake_port: mach_port_t, reference: *mut u64, referenceCnt: u32, input: *const u64, inputStruct: *const c_void, inputStructCnt: size_t, output: *mut u64, outputCnt: *mut u32, outputStruct: *mut c_void, outputStructCnt: *mut size_t) -> kern_return_t;
    pub fn IOConnectCallStructMethod(connection: mach_port_t, selector: u32, inputStruct: *const c_void, inputStructCnt: size_t, outputStruct: *mut c_void, outputStructCnt: *mut size_t) -> kern_return_t;
    pub fn IOConnectCallAsyncStructMethod(connection: mach_port_t, selector: u32, wake_port: mach_port_t, reference: *mut u64, referenceCnt: u32, inputStruct: *const c_void, inputStructCnt: size_t, outputStruct: *mut c_void, outputStructCnt: *mut size_t) -> kern_return_t;
    pub fn IOConnectCallScalarMethod(connection: mach_port_t, selector: u32, input: *const u64, inputCnt: u32, output: *mut u64, outputCnt: *mut u32) -> kern_return_t;
    pub fn IOConnectCallAsyncScalarMethod(connection: mach_port_t, selector: u32, wake_port: mach_port_t, reference: *mut u64, referenceCnt: u32, input: *const u64, inputCnt: u32, output: *mut u64, outputCnt: *mut u32) -> kern_return_t;

    pub fn IOConnectTrap0(connect: io_connect_t, index: u32) -> kern_return_t;
    pub fn IOConnectTrap1(connect: io_connect_t, index: u32, p1: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap2(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap3(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t, p3: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap4(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t, p3: uintptr_t, p4: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap5(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t, p3: uintptr_t, p4: uintptr_t, p5: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap6(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t, p3: uintptr_t, p4: uintptr_t, p5: uintptr_t, p6: uintptr_t) -> kern_return_t;
    pub fn IOConnectAddClient(connect: io_connect_t, client: io_connect_t) -> kern_return_t;

    // IORegistry accessors

    pub fn IORegistryGetRootEntry(masterPort: mach_port_t) -> io_registry_entry_t;
    pub fn IORegistryEntryFromPath(masterPort: mach_port_t, path: *const c_char) -> io_registry_entry_t;
    pub fn IORegistryCreateIterator(masterPort: mach_port_t, plane: *const c_char, options: IOOptionBits, iterator: *mut io_iterator_t) -> kern_return_t;
    pub fn IORegistryEntryCreateIterator(masterPort: mach_port_t, plane: *const c_char, options: IOOptionBits, iterator: *mut io_iterator_t) -> kern_return_t;

    // IORegistryIterator, subclass of IOIterator

    pub fn IORegistryIteratorEnterEntry(iterator: io_iterator_t) -> kern_return_t;
    pub fn IORegistryIteratorExitEntry(iterator: io_iterator_t) -> kern_return_t;

    // IORegistryEntry, subclass of IOObject

    pub fn IORegistryEntryGetName(entry: io_registry_entry_t, name: *mut c_char) -> kern_return_t;
    pub fn IORegistryEntryGetNameInPlane(entry: io_registry_entry_t, plane: *const c_char, name: *mut c_char) -> kern_return_t;
    pub fn IORegistryEntryGetLocationInPlane(entry: io_registry_entry_t, plane: *const c_char, location: *mut c_char) -> kern_return_t;
    pub fn IORegistryEntryGetPath(entry: io_registry_entry_t, plane: *const c_char, path: *mut c_char) -> kern_return_t;
    pub fn IORegistryEntryGetRegistryEntryID(entry: io_registry_entry_t, entryID: *mut u64) -> kern_return_t;
    pub fn IORegistryEntryCreateCFProperties(entry: io_registry_entry_t, properties: *mut CFMutableDictionaryRef, allocator: CFAllocatorRef, options: IOOptionBits) -> kern_return_t;
    pub fn IORegistryEntryCreateCFProperty(entry: io_registry_entry_t, key: CFStringRef, allocator: CFAllocatorRef, options: IOOptionBits) -> CFTypeRef;
    pub fn IORegistryEntrySetCFProperties(entry: io_registry_entry_t, properties: CFTypeRef) -> kern_return_t;
    pub fn IORegistryEntrySetCFProperty(entry: io_registry_entry_t, propertyName: CFStringRef, property: CFTypeRef) -> kern_return_t;
    pub fn IORegistryEntryGetChildIterator(entry: io_registry_entry_t, plane: *const c_char, iterator: *mut io_iterator_t) -> kern_return_t;
    pub fn IORegistryEntryGetChildEntry(entry: io_registry_entry_t, plane: *const c_char, child: *mut io_registry_entry_t) -> kern_return_t;
    pub fn IORegistryEntryGetParentIterator(entry: io_registry_entry_t, plane: *const c_char, iterator: *mut io_iterator_t) -> kern_return_t;
    pub fn IORegistryEntryGetParentEntry(entry: io_registry_entry_t, plane: *const c_char, parent: *mut io_registry_entry_t) -> kern_return_t;
    pub fn IORegistryEntryInPlane(entry: io_registry_entry_t, plane: *const c_char) -> boolean_t;

    // matching dictionary creation helpers

    pub fn IOServiceMatching(name: *const c_char) -> CFMutableDictionaryRef;
    pub fn IOServiceNameMatching(name: *const c_char) -> CFMutableDictionaryRef;
    pub fn IOBSDNameMatching(masterPort: mach_port_t, options: u32, bsdName: *const c_char) -> CFMutableDictionaryRef;
    pub fn IORegistryEntryIDMatching(entryID: u64) -> CFMutableDictionaryRef;
}
<commit_msg>fix unused type warnings<commit_after>#![allow(non_camel_case_types,non_upper_case_globals,non_snake_case)]

extern crate CoreFoundation_sys as cf;
extern crate libc;
extern crate mach;

use cf::{CFTypeRef,CFDictionaryRef,CFMutableDictionaryRef,CFStringRef,CFAllocatorRef};
use libc::{c_void,c_char,c_int,size_t,uintptr_t};

use mach::boolean::boolean_t;
use mach::clock_types::mach_timespec_t;
use mach::kern_return::kern_return_t;
use mach::port::mach_port_t;
use mach::types::task_port_t;
use mach::vm_types::{mach_vm_address_t,mach_vm_size_t};

pub use io_return::*;
pub use keys::*;
pub use serial::*;
pub use types::*;
pub use usb::*;
pub use io_hid_keys::*;
pub use io_hid_base::*;
pub use io_hid_manager::*;

mod io_return;
mod keys;
mod serial;
mod types;
mod usb;
mod io_hid_keys;
mod io_hid_base;
mod io_hid_manager;

// exports from <IOKit/IOKitLib.h>

#[repr(C)]
pub struct IONotificationPort {
    __private: c_void,
}

pub type IONotificationPortRef = *mut IONotificationPort;

pub type IOServiceMatchingCallback = extern fn (refcon: *mut c_void, iterator: io_iterator_t);
pub type IOServiceInterestCallback = extern fn (refcon: *mut c_void, service: io_service_t, messageType: u32, messageArgument: *mut c_void);

// options for IOServiceAuthorize()
pub const kIOServiceInteractionAllowed: u32 = 0x00000001;

// options for IORegistryCreateIterator(), IORegistryEntryCreateIterator(), IORegistryEntrySearchCFProperty()
pub const kIORegistryIterateRecursively: IOOptionBits = 0x00000001;
pub const kIORegistryIterateParents:     IOOptionBits = 0x00000002;

pub type IOAsyncCallback0 = extern fn (refcon: *mut c_void, result: IOReturn);
pub type IOAsyncCallback1 = extern fn (refcon: *mut c_void, result: IOReturn, arg0: *mut c_void);
pub type IOAsyncCallback2 = extern fn (refcon: *mut c_void, result: IOReturn, arg0: *mut c_void, arg1: *mut c_void);
pub type IOAsyncCallback = extern fn (refcon: *mut c_void, result: IOReturn, args: *mut *mut c_void, numArgs: u32);

extern "C" {
    pub static kIOMasterPortDefault: mach_port_t;

    pub fn IOMasterPort(bootstrapPort: mach_port_t, masterPort: *mut mach_port_t) -> kern_return_t;

    pub fn IONotificationPortCreate(masterPort: mach_port_t) -> IONotificationPortRef;
    pub fn IONotificationPortDestroy(notify: IONotificationPortRef);
    pub fn IONotificationPortGetMachPort(notify: IONotificationPortRef) -> mach_port_t;

    pub fn IOCreateReceivePort(msgType: u32, recvPort: *mut mach_port_t) -> kern_return_t;

    // IOObject

    pub fn IOObjectRelease(object: io_object_t) -> kern_return_t;
    pub fn IOObjectRetain(object: io_object_t) -> kern_return_t;
    pub fn IOObjectGetClass(object: io_object_t, className: *mut c_char) -> kern_return_t;
    pub fn IOObjectCopyClass(object: io_object_t) -> CFStringRef;
    pub fn IOObjectCopySuperclassForClass(classname: CFStringRef) -> CFStringRef;
    pub fn IOObjectCopyBundleIdentifierForClass(classname: CFStringRef) -> CFStringRef;
    pub fn IOObjectConformsTo(object: io_object_t, className: *const c_char) -> boolean_t;
    pub fn IOObjectGetKernelRetainCount(object: io_object_t) -> u32;
    pub fn IOObjectGetUserRetainCount(object: io_object_t) -> u32;
    pub fn IOObjectGetRetainCount(object: io_object_t) -> u32;

    // IOIterator, subclass of IOObject

    pub fn IOIteratorNext(iterator: io_iterator_t) -> io_object_t;
    pub fn IOIteratorReset(iterator: io_iterator_t);
    pub fn IOIteratorIsValid(iterator: io_iterator_t) -> boolean_t;

    // IOService, subclass of IORegistryEntry

    pub fn IOServiceGetMatchingService(masterPort: mach_port_t, matching: CFDictionaryRef) -> io_service_t;
    pub fn IOServiceGetMatchingServices(masterPort: mach_port_t, matching: CFDictionaryRef, existing: *mut io_iterator_t) -> kern_return_t;
    pub fn IOServiceAddNotification(masterPort: mach_port_t, notificationType: *const c_char, matching: CFDictionaryRef, wakePort: mach_port_t, reference: uintptr_t, notification: *mut io_iterator_t) -> kern_return_t;
    pub fn IOServiceAddMatchingNotification(notifyPort: IONotificationPortRef, notificationType: *const c_char, matching: CFDictionaryRef, callback: IOServiceMatchingCallback, refCon: *mut c_void, notification: *mut io_iterator_t) -> kern_return_t;
    pub fn IOServiceAddInterestNotification(notifyPort: IONotificationPortRef, service: io_service_t, interestType: *const c_char, callback: IOServiceInterestCallback, refCon: *mut c_void, notification: *mut io_object_t) -> kern_return_t;
    pub fn IOServiceMatchPropertyTable(service: io_service_t, matching: CFDictionaryRef, matches: *mut boolean_t) -> kern_return_t;
    pub fn IOServiceGetBusyState(service: io_service_t, busyState: *mut u32) -> kern_return_t;
    pub fn IOServiceWaitQuiet(service: io_service_t, waitTime: *mut mach_timespec_t) -> kern_return_t;

    pub fn IOKitGetBusyState(masterPort: mach_port_t, busyState: *mut u32) -> kern_return_t;
    pub fn IOKitWaitQuiet(masterPort: mach_port_t, waitTime: *mut mach_timespec_t) -> kern_return_t;

    pub fn IOServiceOpen(service: io_service_t, owningTask: task_port_t, connectionType: u32, connect: *mut io_connect_t) -> kern_return_t;
    pub fn IOServiceRequestProbe(service: io_service_t, options: u32) -> kern_return_t;
    pub fn IOServiceAuthorize(service: io_service_t, options: u32) -> kern_return_t;
    pub fn IOServiceOpenAsFileDescriptor(service: io_service_t, oflag: c_int) -> c_int;

    // IOService connection

    pub fn IOServiceClose(connect: io_connect_t) -> kern_return_t;
    pub fn IOConnectAddRef(connect: io_connect_t) -> kern_return_t;
    pub fn IOConnectRelease(connect: io_connect_t) -> kern_return_t;
    pub fn IOConnectGetService(connect: io_connect_t, service: *mut io_service_t) -> kern_return_t;
    pub fn IOConnectSetNotificationPort(connect: io_connect_t, notificationType: u32, port: mach_port_t, reference: uintptr_t) -> kern_return_t;
    pub fn IOConnectMapMemory64(connect: io_connect_t, memoryType: u32, intoTask: task_port_t, atAddress: *mut mach_vm_address_t, ofSize: *mut mach_vm_size_t, options: IOOptionBits) -> kern_return_t;
    pub fn IOConnectUnmapMemory64(connect: io_connect_t, memoryType: u32, fromTask: task_port_t, atAddress: mach_vm_address_t) -> kern_return_t;
    pub fn IOConnectSetCFProperties(connect: io_connect_t, properties: CFTypeRef) -> kern_return_t;
    pub fn IOConnectSetCFProperty(conect: io_connect_t, propertyName: CFStringRef, property: CFTypeRef) -> kern_return_t;

    pub fn IOConnectCallMethod(connection: mach_port_t, selector: u32, input: *const u64, inputCnt: u32, inputStruct: *const c_void, inputStructCnt: size_t, output: *mut u64, outputCnt: *mut u32, outputStruct: *mut c_void, outputStructCnt: *mut size_t) -> kern_return_t;
    pub fn IOConnectCallAsyncMethod(connection: mach_port_t, selector: u32, wake_port: mach_port_t, reference: *mut u64, referenceCnt: u32, input: *const u64, inputStruct: *const c_void, inputStructCnt: size_t, output: *mut u64, outputCnt: *mut u32, outputStruct: *mut c_void, outputStructCnt: *mut size_t) -> kern_return_t;
    pub fn IOConnectCallStructMethod(connection: mach_port_t, selector: u32, inputStruct: *const c_void, inputStructCnt: size_t, outputStruct: *mut c_void, outputStructCnt: *mut size_t) -> kern_return_t;
    pub fn IOConnectCallAsyncStructMethod(connection: mach_port_t, selector: u32, wake_port: mach_port_t, reference: *mut u64, referenceCnt: u32, inputStruct: *const c_void, inputStructCnt: size_t, outputStruct: *mut c_void, outputStructCnt: *mut size_t) -> kern_return_t;
    pub fn IOConnectCallScalarMethod(connection: mach_port_t, selector: u32, input: *const u64, inputCnt: u32, output: *mut u64, outputCnt: *mut u32) -> kern_return_t;
    pub fn IOConnectCallAsyncScalarMethod(connection: mach_port_t, selector: u32, wake_port: mach_port_t, reference: *mut u64, referenceCnt: u32, input: *const u64, inputCnt: u32, output: *mut u64, outputCnt: *mut u32) -> kern_return_t;

    pub fn IOConnectTrap0(connect: io_connect_t, index: u32) -> kern_return_t;
    pub fn IOConnectTrap1(connect: io_connect_t, index: u32, p1: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap2(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap3(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t, p3: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap4(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t, p3: uintptr_t, p4: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap5(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t, p3: uintptr_t, p4: uintptr_t, p5: uintptr_t) -> kern_return_t;
    pub fn IOConnectTrap6(connect: io_connect_t, index: u32, p1: uintptr_t, p2: uintptr_t, p3: uintptr_t, p4: uintptr_t, p5: uintptr_t, p6: uintptr_t) -> kern_return_t;
    pub fn IOConnectAddClient(connect: io_connect_t, client: io_connect_t) -> kern_return_t;

    // IORegistry accessors

    pub fn IORegistryGetRootEntry(masterPort: mach_port_t) -> io_registry_entry_t;
    pub fn IORegistryEntryFromPath(masterPort: mach_port_t, path: *const c_char) -> io_registry_entry_t;
    pub fn IORegistryCreateIterator(masterPort: mach_port_t, plane: *const c_char, options: IOOptionBits, iterator: *mut io_iterator_t) -> kern_return_t;
    pub fn IORegistryEntryCreateIterator(masterPort: mach_port_t, plane: *const c_char, options: IOOptionBits, iterator: *mut io_iterator_t) -> kern_return_t;

    // IORegistryIterator, subclass of IOIterator

    pub fn IORegistryIteratorEnterEntry(iterator: io_iterator_t) -> kern_return_t;
    pub fn IORegistryIteratorExitEntry(iterator: io_iterator_t) -> kern_return_t;

    // IORegistryEntry, subclass of IOObject

    pub fn IORegistryEntryGetName(entry: io_registry_entry_t, name: *mut c_char) -> kern_return_t;
    pub fn IORegistryEntryGetNameInPlane(entry: io_registry_entry_t, plane: *const c_char, name: *mut c_char) -> kern_return_t;
    pub fn IORegistryEntryGetLocationInPlane(entry: io_registry_entry_t, plane: *const c_char, location: *mut c_char) -> kern_return_t;
    pub fn IORegistryEntryGetPath(entry: io_registry_entry_t, plane: *const c_char, path: *mut c_char) -> kern_return_t;
    pub fn IORegistryEntryGetRegistryEntryID(entry: io_registry_entry_t, entryID: *mut u64) -> kern_return_t;
    pub fn IORegistryEntryCreateCFProperties(entry: io_registry_entry_t, properties: *mut CFMutableDictionaryRef, allocator: CFAllocatorRef, options: IOOptionBits) -> kern_return_t;
    pub fn IORegistryEntryCreateCFProperty(entry: io_registry_entry_t, key: CFStringRef, allocator: CFAllocatorRef, options: IOOptionBits) -> CFTypeRef;
    pub fn IORegistryEntrySetCFProperties(entry: io_registry_entry_t, properties: CFTypeRef) -> kern_return_t;
    pub fn IORegistryEntrySetCFProperty(entry: io_registry_entry_t, propertyName: CFStringRef, property: CFTypeRef) -> kern_return_t;
    pub fn IORegistryEntryGetChildIterator(entry: io_registry_entry_t, plane: *const c_char, iterator: *mut io_iterator_t) -> kern_return_t;
    pub fn IORegistryEntryGetChildEntry(entry: io_registry_entry_t, plane: *const c_char, child: *mut io_registry_entry_t) -> kern_return_t;
    pub fn IORegistryEntryGetParentIterator(entry: io_registry_entry_t, plane: *const c_char, iterator: *mut io_iterator_t) -> kern_return_t;
    pub fn IORegistryEntryGetParentEntry(entry: io_registry_entry_t, plane: *const c_char, parent: *mut io_registry_entry_t) -> kern_return_t;
    pub fn IORegistryEntryInPlane(entry: io_registry_entry_t, plane: *const c_char) -> boolean_t;

    // matching dictionary creation helpers

    pub fn IOServiceMatching(name: *const c_char) -> CFMutableDictionaryRef;
    pub fn IOServiceNameMatching(name: *const c_char) -> CFMutableDictionaryRef;
    pub fn IOBSDNameMatching(masterPort: mach_port_t, options: u32, bsdName: *const c_char) -> CFMutableDictionaryRef;
    pub fn IORegistryEntryIDMatching(entryID: u64) -> CFMutableDictionaryRef;
}
<|endoftext|>