<commit_before>//! An abstraction of a plist file as a stream of events. Used to support multiple encodings.

mod binary_reader;
pub use self::binary_reader::BinaryReader;

mod xml_reader;
pub use self::xml_reader::XmlReader;

mod xml_writer;
pub use self::xml_writer::XmlWriter;

use std::io::{Read, Seek, SeekFrom};
use std::vec;
use {Date, Error, Integer, Value};

/// An encoding of a plist as a flat structure.
///
/// Output by the event readers.
///
/// Dictionary keys and values are represented as pairs of values e.g.:
///
/// ```ignore rust
/// StartDictionary
/// String("Height") // Key
/// Real(181.2)      // Value
/// String("Age")    // Key
/// Integer(28)      // Value
/// EndDictionary
/// ```
#[derive(Clone, Debug, PartialEq)]
pub enum Event {
    // While the length of an array or dict cannot be feasably greater than max(usize) this better
    // conveys the concept of an effectively unbounded event stream.
    StartArray(Option<u64>),
    EndArray,

    StartDictionary(Option<u64>),
    EndDictionary,

    Boolean(bool),
    Data(Vec<u8>),
    Date(Date),
    Integer(Integer),
    Real(f64),
    String(String),

    #[doc(hidden)]
    __Nonexhaustive,
}

/// An `Event` stream returned by `Value::into_events`.
pub struct IntoEvents {
    events: vec::IntoIter<Event>,
}

impl IntoEvents {
    pub(crate) fn new(value: Value) -> IntoEvents {
        let mut events = Vec::new();
        IntoEvents::new_inner(value, &mut events);
        IntoEvents {
            events: events.into_iter(),
        }
    }

    fn new_inner(value: Value, events: &mut Vec<Event>) {
        match value {
            Value::Array(array) => {
                events.push(Event::StartArray(Some(array.len() as u64)));
                for value in array {
                    IntoEvents::new_inner(value, events);
                }
                events.push(Event::EndArray);
            }
            Value::Dictionary(dict) => {
                events.push(Event::StartDictionary(Some(dict.len() as u64)));
                for (key, value) in dict {
                    events.push(Event::String(key));
                    IntoEvents::new_inner(value, events);
                }
                events.push(Event::EndDictionary);
            }
            Value::Boolean(value) => events.push(Event::Boolean(value)),
            Value::Data(value) => events.push(Event::Data(value)),
            Value::Date(value) => events.push(Event::Date(value)),
            Value::Real(value) => events.push(Event::Real(value)),
            Value::Integer(value) => events.push(Event::Integer(value)),
            Value::String(value) => events.push(Event::String(value)),
            Value::__Nonexhaustive => unreachable!(),
        }
    }
}

impl Iterator for IntoEvents {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        self.events.next()
    }
}

pub struct Reader<R: Read + Seek>(ReaderInner<R>);

enum ReaderInner<R: Read + Seek> {
    Uninitialized(Option<R>),
    Xml(XmlReader<R>),
    Binary(BinaryReader<R>),
}

impl<R: Read + Seek> Reader<R> {
    pub fn new(reader: R) -> Reader<R> {
        Reader(ReaderInner::Uninitialized(Some(reader)))
    }

    fn is_binary(reader: &mut R) -> Result<bool, Error> {
        reader.seek(SeekFrom::Start(0))?;
        let mut magic = [0; 8];
        reader.read_exact(&mut magic)?;
        reader.seek(SeekFrom::Start(0))?;

        Ok(&magic == b"bplist00")
    }
}

impl<R: Read + Seek> Iterator for Reader<R> {
    type Item = Result<Event, Error>;

    fn next(&mut self) -> Option<Result<Event, Error>> {
        let mut reader = match self.0 {
            ReaderInner::Xml(ref mut parser) => return parser.next(),
            ReaderInner::Binary(ref mut parser) => return parser.next(),
            ReaderInner::Uninitialized(ref mut reader) => reader.take().unwrap(),
        };

        let event_reader = match Reader::is_binary(&mut reader) {
            Ok(true) => ReaderInner::Binary(BinaryReader::new(reader)),
            Ok(false) => ReaderInner::Xml(XmlReader::new(reader)),
            Err(err) => {
                ::std::mem::replace(&mut self.0, ReaderInner::Uninitialized(Some(reader)));
                return Some(Err(err));
            }
        };

        ::std::mem::replace(&mut self.0, event_reader);

        self.next()
    }
}

/// Supports writing event streams in different plist encodings.
pub trait Writer: private::Sealed {
    fn write(&mut self, event: &Event) -> Result<(), Error> {
        match event {
            Event::StartArray(len) => self.write_start_array(*len),
            Event::EndArray => self.write_end_array(),
            Event::StartDictionary(len) => self.write_start_dictionary(*len),
            Event::EndDictionary => self.write_end_dictionary(),
            Event::Boolean(value) => self.write_boolean(*value),
            Event::Data(value) => self.write_data(value),
            Event::Date(value) => self.write_date(*value),
            Event::Integer(value) => self.write_integer(*value),
            Event::Real(value) => self.write_real(*value),
            Event::String(value) => self.write_string(value),
            Event::__Nonexhaustive => unreachable!(),
        }
    }

    fn write_start_array(&mut self, len: Option<u64>) -> Result<(), Error>;
    fn write_end_array(&mut self) -> Result<(), Error>;

    fn write_start_dictionary(&mut self, len: Option<u64>) -> Result<(), Error>;
    fn write_end_dictionary(&mut self) -> Result<(), Error>;

    fn write_boolean(&mut self, value: bool) -> Result<(), Error>;
    fn write_data(&mut self, value: &[u8]) -> Result<(), Error>;
    fn write_date(&mut self, value: Date) -> Result<(), Error>;
    fn write_integer(&mut self, value: Integer) -> Result<(), Error>;
    fn write_real(&mut self, value: f64) -> Result<(), Error>;
    fn write_string(&mut self, value: &str) -> Result<(), Error>;
}

#[doc(hidden)]
pub struct VecWriter {
    events: Vec<Event>,
}

impl VecWriter {
    pub fn new() -> VecWriter {
        VecWriter { events: Vec::new() }
    }

    pub fn into_inner(self) -> Vec<Event> {
        self.events
    }
}

impl Writer for VecWriter {
    fn write_start_array(&mut self, len: Option<u64>) -> Result<(), Error> {
        self.events.push(Event::StartArray(len));
        Ok(())
    }

    fn write_end_array(&mut self) -> Result<(), Error> {
        self.events.push(Event::EndArray);
        Ok(())
    }

    fn write_start_dictionary(&mut self, len: Option<u64>) -> Result<(), Error> {
        self.events.push(Event::StartDictionary(len));
        Ok(())
    }

    fn write_end_dictionary(&mut self) -> Result<(), Error> {
        self.events.push(Event::EndDictionary);
        Ok(())
    }

    fn write_boolean(&mut self, value: bool) -> Result<(), Error> {
        self.events.push(Event::Boolean(value));
        Ok(())
    }

    fn write_data(&mut self, value: &[u8]) -> Result<(), Error> {
        self.events.push(Event::Data(value.to_owned()));
        Ok(())
    }

    fn write_date(&mut self, value: Date) -> Result<(), Error> {
        self.events.push(Event::Date(value));
        Ok(())
    }

    fn write_integer(&mut self, value: Integer) -> Result<(), Error> {
        self.events.push(Event::Integer(value));
        Ok(())
    }

    fn write_real(&mut self, value: f64) -> Result<(), Error> {
        self.events.push(Event::Real(value));
        Ok(())
    }

    fn write_string(&mut self, value: &str) -> Result<(), Error> {
        self.events.push(Event::String(value.to_owned()));
        Ok(())
    }
}

mod private {
    use std::io::Write;

    pub trait Sealed {}

    impl<W: Write> Sealed for super::XmlWriter<W> {}
    impl Sealed for super::VecWriter {}
}
<commit_msg>Lazily convert a `Value` to an `Event` iterator in `Value::into_events`.<commit_after>//! An abstraction of a plist file as a stream of events. Used to support multiple encodings.

mod binary_reader;
pub use self::binary_reader::BinaryReader;

mod xml_reader;
pub use self::xml_reader::XmlReader;

mod xml_writer;
pub use self::xml_writer::XmlWriter;

use std::collections::btree_map;
use std::io::{Read, Seek, SeekFrom};
use std::vec;
use {Date, Error, Integer, Value};

/// An encoding of a plist as a flat structure.
///
/// Output by the event readers.
///
/// Dictionary keys and values are represented as pairs of values e.g.:
///
/// ```ignore rust
/// StartDictionary
/// String("Height") // Key
/// Real(181.2)      // Value
/// String("Age")    // Key
/// Integer(28)      // Value
/// EndDictionary
/// ```
#[derive(Clone, Debug, PartialEq)]
pub enum Event {
    // While the length of an array or dict cannot be feasably greater than max(usize) this better
    // conveys the concept of an effectively unbounded event stream.
    StartArray(Option<u64>),
    EndArray,

    StartDictionary(Option<u64>),
    EndDictionary,

    Boolean(bool),
    Data(Vec<u8>),
    Date(Date),
    Integer(Integer),
    Real(f64),
    String(String),

    #[doc(hidden)]
    __Nonexhaustive,
}

/// An `Event` stream returned by `Value::into_events`.
pub struct IntoEvents {
    stack: Vec<StackItem>,
}

enum StackItem {
    Root(Value),
    Array(vec::IntoIter<Value>),
    Dict(btree_map::IntoIter<String, Value>),
    DictValue(Value),
}

impl IntoEvents {
    pub(crate) fn new(value: Value) -> IntoEvents {
        IntoEvents {
            stack: vec![StackItem::Root(value)],
        }
    }
}

impl Iterator for IntoEvents {
    type Item = Event;

    fn next(&mut self) -> Option<Event> {
        fn handle_value(value: Value, stack: &mut Vec<StackItem>) -> Event {
            match value {
                Value::Array(array) => {
                    let len = array.len();
                    let iter = array.into_iter();
                    stack.push(StackItem::Array(iter));
                    Event::StartArray(Some(len as u64))
                }
                Value::Dictionary(dict) => {
                    let len = dict.len();
                    let iter = dict.into_iter();
                    stack.push(StackItem::Dict(iter));
                    Event::StartDictionary(Some(len as u64))
                }
                Value::Boolean(value) => Event::Boolean(value),
                Value::Data(value) => Event::Data(value),
                Value::Date(value) => Event::Date(value),
                Value::Real(value) => Event::Real(value),
                Value::Integer(value) => Event::Integer(value),
                Value::String(value) => Event::String(value),
                Value::__Nonexhaustive => unreachable!(),
            }
        }

        Some(match self.stack.pop()? {
            StackItem::Root(value) => handle_value(value, &mut self.stack),
            StackItem::Array(mut array) => {
                if let Some(value) = array.next() {
                    // There might still be more items in the array so return it to the stack.
                    self.stack.push(StackItem::Array(array));
                    handle_value(value, &mut self.stack)
                } else {
                    Event::EndArray
                }
            }
            StackItem::Dict(mut dict) => {
                if let Some((key, value)) = dict.next() {
                    // There might still be more items in the dictionary so return it to the stack.
                    self.stack.push(StackItem::Dict(dict));
                    // The next event to be returned must be the dictionary value.
                    self.stack.push(StackItem::DictValue(value));
                    // Return the key event now.
                    Event::String(key)
                } else {
                    Event::EndDictionary
                }
            }
            StackItem::DictValue(value) => handle_value(value, &mut self.stack),
        })
    }
}

pub struct Reader<R: Read + Seek>(ReaderInner<R>);

enum ReaderInner<R: Read + Seek> {
    Uninitialized(Option<R>),
    Xml(XmlReader<R>),
    Binary(BinaryReader<R>),
}

impl<R: Read + Seek> Reader<R> {
    pub fn new(reader: R) -> Reader<R> {
        Reader(ReaderInner::Uninitialized(Some(reader)))
    }

    fn is_binary(reader: &mut R) -> Result<bool, Error> {
        reader.seek(SeekFrom::Start(0))?;
        let mut magic = [0; 8];
        reader.read_exact(&mut magic)?;
        reader.seek(SeekFrom::Start(0))?;

        Ok(&magic == b"bplist00")
    }
}

impl<R: Read + Seek> Iterator for Reader<R> {
    type Item = Result<Event, Error>;

    fn next(&mut self) -> Option<Result<Event, Error>> {
        let mut reader = match self.0 {
            ReaderInner::Xml(ref mut parser) => return parser.next(),
            ReaderInner::Binary(ref mut parser) => return parser.next(),
            ReaderInner::Uninitialized(ref mut reader) => reader.take().unwrap(),
        };

        let event_reader = match Reader::is_binary(&mut reader) {
            Ok(true) => ReaderInner::Binary(BinaryReader::new(reader)),
            Ok(false) => ReaderInner::Xml(XmlReader::new(reader)),
            Err(err) => {
                ::std::mem::replace(&mut self.0, ReaderInner::Uninitialized(Some(reader)));
                return Some(Err(err));
            }
        };

        ::std::mem::replace(&mut self.0, event_reader);

        self.next()
    }
}

/// Supports writing event streams in different plist encodings.
pub trait Writer: private::Sealed {
    fn write(&mut self, event: &Event) -> Result<(), Error> {
        match event {
            Event::StartArray(len) => self.write_start_array(*len),
            Event::EndArray => self.write_end_array(),
            Event::StartDictionary(len) => self.write_start_dictionary(*len),
            Event::EndDictionary => self.write_end_dictionary(),
            Event::Boolean(value) => self.write_boolean(*value),
            Event::Data(value) => self.write_data(value),
            Event::Date(value) => self.write_date(*value),
            Event::Integer(value) => self.write_integer(*value),
            Event::Real(value) => self.write_real(*value),
            Event::String(value) => self.write_string(value),
            Event::__Nonexhaustive => unreachable!(),
        }
    }

    fn write_start_array(&mut self, len: Option<u64>) -> Result<(), Error>;
    fn write_end_array(&mut self) -> Result<(), Error>;

    fn write_start_dictionary(&mut self, len: Option<u64>) -> Result<(), Error>;
    fn write_end_dictionary(&mut self) -> Result<(), Error>;

    fn write_boolean(&mut self, value: bool) -> Result<(), Error>;
    fn write_data(&mut self, value: &[u8]) -> Result<(), Error>;
    fn write_date(&mut self, value: Date) -> Result<(), Error>;
    fn write_integer(&mut self, value: Integer) -> Result<(), Error>;
    fn write_real(&mut self, value: f64) -> Result<(), Error>;
    fn write_string(&mut self, value: &str) -> Result<(), Error>;
}

#[doc(hidden)]
pub struct VecWriter {
    events: Vec<Event>,
}

impl VecWriter {
    pub fn new() -> VecWriter {
        VecWriter { events: Vec::new() }
    }

    pub fn into_inner(self) -> Vec<Event> {
        self.events
    }
}

impl Writer for VecWriter {
    fn write_start_array(&mut self, len: Option<u64>) -> Result<(), Error> {
        self.events.push(Event::StartArray(len));
        Ok(())
    }

    fn write_end_array(&mut self) -> Result<(), Error> {
        self.events.push(Event::EndArray);
        Ok(())
    }

    fn write_start_dictionary(&mut self, len: Option<u64>) -> Result<(), Error> {
        self.events.push(Event::StartDictionary(len));
        Ok(())
    }

    fn write_end_dictionary(&mut self) -> Result<(), Error> {
        self.events.push(Event::EndDictionary);
        Ok(())
    }

    fn write_boolean(&mut self, value: bool) -> Result<(), Error> {
        self.events.push(Event::Boolean(value));
        Ok(())
    }

    fn write_data(&mut self, value: &[u8]) -> Result<(), Error> {
        self.events.push(Event::Data(value.to_owned()));
        Ok(())
    }

    fn write_date(&mut self, value: Date) -> Result<(), Error> {
        self.events.push(Event::Date(value));
        Ok(())
    }

    fn write_integer(&mut self, value: Integer) -> Result<(), Error> {
        self.events.push(Event::Integer(value));
        Ok(())
    }

    fn write_real(&mut self, value: f64) -> Result<(), Error> {
        self.events.push(Event::Real(value));
        Ok(())
    }

    fn write_string(&mut self, value: &str) -> Result<(), Error> {
        self.events.push(Event::String(value.to_owned()));
        Ok(())
    }
}

mod private {
    use std::io::Write;

    pub trait Sealed {}

    impl<W: Write> Sealed for super::XmlWriter<W> {}
    impl Sealed for super::VecWriter {}
}
<|endoftext|>


<commit_before>use super::super::{Coord, GraphSeparation, Grid, X, Y};
use super::{Cell, Clue, Dictionary, DICTIONARY_INCONSISTENT, DICTIONARY_NEIGHBOR_OFFSET, NO_CLUE};

pub struct Field<'a> {
    cell: Grid<Cell>,
    clue: Grid<Clue>,
    inconsistent: bool,
    dic: &'a Dictionary,
}

impl<'a> Field<'a> {
    pub fn new(height: i32, width: i32, dic: &'a Dictionary) -> Field {
        Field {
            cell: Grid::new(height, width, Cell::Undecided),
            clue: Grid::new(height, width, NO_CLUE),
            inconsistent: false,
            dic,
        }
    }
    pub fn height(&self) -> i32 {
        self.cell.height()
    }
    pub fn width(&self) -> i32 {
        self.cell.width()
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn set_inconsistent(&mut self) {
        self.inconsistent = true;
    }
    pub fn add_clue(&mut self, loc: Coord, clue: Clue) {
        let current_clue = self.clue[loc];
        if current_clue != NO_CLUE {
            if current_clue != clue {
                self.inconsistent = true;
            }
            return;
        }

        self.clue[loc] = clue;
        self.decide(loc, Cell::White);
    }
    pub fn cell(&self, loc: Coord) -> Cell {
        self.cell[loc]
    }
    pub fn cell_checked(&self, loc: Coord) -> Cell {
        if self.cell.is_valid_coord(loc) {
            self.cell[loc]
        } else {
            Cell::White
        }
    }
    pub fn decide(&mut self, loc: Coord, v: Cell) {
        let current_status = self.cell_checked(loc);
        if current_status != Cell::Undecided {
            if current_status != v {
                self.inconsistent = true;
            }
            return;
        }

        self.cell[loc] = v;

        let (Y(y), X(x)) = loc;
        for dy in -1..2 {
            for dx in -1..2 {
                self.inspect((Y(y + dy), X(x + dx)));
            }
        }
    }
    pub fn inspect_connectivity(&mut self) {
        let height = self.height();
        let width = self.width();
        let cells = (height * width) as usize;
        let mut graph = GraphSeparation::new(cells, cells * 2);

        for y in 0..height {
            for x in 0..width {
                let c = self.cell((Y(y), X(x)));
                graph.set_weight(
                    (y * width + x) as usize,
                    if c == Cell::Black { 1 } else { 0 },
                );
                if c != Cell::White {
                    if self.cell_checked((Y(y + 1), X(x))) != Cell::White {
                        graph.add_edge((y * width + x) as usize, ((y + 1) * width + x) as usize);
                    }
                    if self.cell_checked((Y(y), X(x + 1))) != Cell::White {
                        graph.add_edge((y * width + x) as usize, (y * width + (x + 1)) as usize);
                    }
                }
            }
        }

        graph.build();

        for y in 0..height {
            for x in 0..width {
                if self.cell((Y(y), X(x))) == Cell::Undecided {
                    let sep = graph.separate((y * width + x) as usize);
                    let mut nonzero = 0;
                    for v in sep {
                        if v > 0 {
                            nonzero += 1;
                        }
                    }
                    if nonzero >= 2 {
                        self.decide((Y(y), X(x)), Cell::Black);
                    }
                }
            }
        }
    }
    fn inspect(&mut self, loc: Coord) {
        if !self.cell.is_valid_coord(loc) {
            return;
        }

        let (Y(y), X(x)) = loc;
        let cell = self.cell(loc);
        let clue = self.clue[loc];
        if clue != NO_CLUE {
            let mut neighbor = 0;
            let mut pow = 1;
            for i in 0..8 {
                let (Y(dy), X(dx)) = DICTIONARY_NEIGHBOR_OFFSET[i];
                neighbor += pow * match self.cell_checked((Y(y + dy), X(x + dx))) {
                    Cell::Undecided => 0,
                    Cell::Black => 1,
                    Cell::White => 2,
                };
                pow *= 3;
            }
            let neighbor = self.dic.consult_raw(clue, neighbor);

            if neighbor == DICTIONARY_INCONSISTENT {
                self.inconsistent = true;
                return;
            }

            for i in 0..8 {
                let v = (neighbor >> (2 * i)) & 3;
                let (Y(dy), X(dx)) = DICTIONARY_NEIGHBOR_OFFSET[i];
                if v == 1 {
                    self.decide((Y(y + dy), X(x + dx)), Cell::Black);
                } else if v == 2 {
                    self.decide((Y(y + dy), X(x + dx)), Cell::White);
                }
            }
        }
    }
}

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

    #[test]
    fn test_tapa_field() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.add_clue((Y(2), X(1)), clue_pattern_to_id(&[]).unwrap());
        field.add_clue((Y(2), X(3)), clue_pattern_to_id(&[4]).unwrap());

        assert_eq!(field.cell((Y(2), X(0))), Cell::White);
        assert_eq!(field.cell((Y(1), X(4))), Cell::Black);
        assert_eq!(field.cell((Y(2), X(4))), Cell::Black);
        assert_eq!(field.cell((Y(3), X(4))), Cell::Black);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_tapa_connectivity() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.decide((Y(0), X(0)), Cell::Black);
        field.decide((Y(4), X(5)), Cell::Black);
        field.decide((Y(1), X(0)), Cell::White);
        field.decide((Y(2), X(1)), Cell::White);
        field.decide((Y(0), X(3)), Cell::White);
        field.decide((Y(0), X(2)), Cell::Undecided);
        field.decide((Y(1), X(1)), Cell::Undecided);

        field.inspect_connectivity();

        assert_eq!(field.cell((Y(0), X(1))), Cell::Black);
        assert_eq!(field.cell((Y(1), X(2))), Cell::Black);
        assert_eq!(field.inconsistent(), false);
    }
}
<commit_msg>Tapa: add avoid_cluster<commit_after>use super::super::{Coord, GraphSeparation, Grid, X, Y};
use super::{Cell, Clue, Dictionary, DICTIONARY_INCONSISTENT, DICTIONARY_NEIGHBOR_OFFSET, NO_CLUE};

pub struct Field<'a> {
    cell: Grid<Cell>,
    clue: Grid<Clue>,
    inconsistent: bool,
    dic: &'a Dictionary,
}

impl<'a> Field<'a> {
    pub fn new(height: i32, width: i32, dic: &'a Dictionary) -> Field {
        Field {
            cell: Grid::new(height, width, Cell::Undecided),
            clue: Grid::new(height, width, NO_CLUE),
            inconsistent: false,
            dic,
        }
    }
    pub fn height(&self) -> i32 {
        self.cell.height()
    }
    pub fn width(&self) -> i32 {
        self.cell.width()
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn set_inconsistent(&mut self) {
        self.inconsistent = true;
    }
    pub fn add_clue(&mut self, loc: Coord, clue: Clue) {
        let current_clue = self.clue[loc];
        if current_clue != NO_CLUE {
            if current_clue != clue {
                self.inconsistent = true;
            }
            return;
        }

        self.clue[loc] = clue;
        self.decide(loc, Cell::White);
    }
    pub fn cell(&self, loc: Coord) -> Cell {
        self.cell[loc]
    }
    pub fn cell_checked(&self, loc: Coord) -> Cell {
        if self.cell.is_valid_coord(loc) {
            self.cell[loc]
        } else {
            Cell::White
        }
    }
    pub fn decide(&mut self, loc: Coord, v: Cell) {
        let current_status = self.cell_checked(loc);
        if current_status != Cell::Undecided {
            if current_status != v {
                self.inconsistent = true;
            }
            return;
        }

        self.cell[loc] = v;

        let (Y(y), X(x)) = loc;

        if v == Cell::Black {
            self.avoid_cluster((Y(y - 1), X(x - 1)), (Y(y - 1), X(x)), (Y(y), X(x - 1)));
            self.avoid_cluster((Y(y - 1), X(x + 1)), (Y(y - 1), X(x)), (Y(y), X(x + 1)));
            self.avoid_cluster((Y(y + 1), X(x - 1)), (Y(y + 1), X(x)), (Y(y), X(x - 1)));
            self.avoid_cluster((Y(y + 1), X(x + 1)), (Y(y + 1), X(x)), (Y(y), X(x + 1)));
        }

        for dy in -1..2 {
            for dx in -1..2 {
                self.inspect((Y(y + dy), X(x + dx)));
            }
        }
    }
    fn avoid_cluster(&mut self, loc1: Coord, loc2: Coord, loc3: Coord) {
        if self.cell_checked(loc1) == Cell::Black {
            if self.cell_checked(loc2) == Cell::Black {
                self.decide(loc3, Cell::White);
            }
            if self.cell_checked(loc3) == Cell::Black {
                self.decide(loc2, Cell::White);
            }
        } else {
            if self.cell_checked(loc2) == Cell::Black && self.cell_checked(loc3) == Cell::Black {
                self.decide(loc1, Cell::White);
            }
        }
    }
    pub fn inspect_connectivity(&mut self) {
        let height = self.height();
        let width = self.width();
        let cells = (height * width) as usize;
        let mut graph = GraphSeparation::new(cells, cells * 2);

        for y in 0..height {
            for x in 0..width {
                let c = self.cell((Y(y), X(x)));
                graph.set_weight(
                    (y * width + x) as usize,
                    if c == Cell::Black { 1 } else { 0 },
                );
                if c != Cell::White {
                    if self.cell_checked((Y(y + 1), X(x))) != Cell::White {
                        graph.add_edge((y * width + x) as usize, ((y + 1) * width + x) as usize);
                    }
                    if self.cell_checked((Y(y), X(x + 1))) != Cell::White {
                        graph.add_edge((y * width + x) as usize, (y * width + (x + 1)) as usize);
                    }
                }
            }
        }

        graph.build();

        for y in 0..height {
            for x in 0..width {
                if self.cell((Y(y), X(x))) == Cell::Undecided {
                    let sep = graph.separate((y * width + x) as usize);
                    let mut nonzero = 0;
                    for v in sep {
                        if v > 0 {
                            nonzero += 1;
                        }
                    }
                    if nonzero >= 2 {
                        self.decide((Y(y), X(x)), Cell::Black);
                    }
                }
            }
        }
    }
    fn inspect(&mut self, loc: Coord) {
        if !self.cell.is_valid_coord(loc) {
            return;
        }

        let (Y(y), X(x)) = loc;
        let cell = self.cell(loc);
        let clue = self.clue[loc];
        if clue != NO_CLUE {
            let mut neighbor = 0;
            let mut pow = 1;
            for i in 0..8 {
                let (Y(dy), X(dx)) = DICTIONARY_NEIGHBOR_OFFSET[i];
                neighbor += pow * match self.cell_checked((Y(y + dy), X(x + dx))) {
                    Cell::Undecided => 0,
                    Cell::Black => 1,
                    Cell::White => 2,
                };
                pow *= 3;
            }
            let neighbor = self.dic.consult_raw(clue, neighbor);

            if neighbor == DICTIONARY_INCONSISTENT {
                self.inconsistent = true;
                return;
            }

            for i in 0..8 {
                let v = (neighbor >> (2 * i)) & 3;
                let (Y(dy), X(dx)) = DICTIONARY_NEIGHBOR_OFFSET[i];
                if v == 1 {
                    self.decide((Y(y + dy), X(x + dx)), Cell::Black);
                } else if v == 2 {
                    self.decide((Y(y + dy), X(x + dx)), Cell::White);
                }
            }
        }
    }
}

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

    #[test]
    fn test_tapa_field_clues() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.add_clue((Y(2), X(1)), clue_pattern_to_id(&[]).unwrap());
        field.add_clue((Y(2), X(3)), clue_pattern_to_id(&[4]).unwrap());

        assert_eq!(field.cell((Y(2), X(0))), Cell::White);
        assert_eq!(field.cell((Y(1), X(4))), Cell::Black);
        assert_eq!(field.cell((Y(2), X(4))), Cell::Black);
        assert_eq!(field.cell((Y(3), X(4))), Cell::Black);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_tapa_field_cluster() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.decide(((Y(1), X(1))), Cell::Black);
        field.decide(((Y(1), X(2))), Cell::Black);
        field.decide(((Y(2), X(2))), Cell::Black);

        assert_eq!(field.cell((Y(2), X(1))), Cell::White);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_tapa_field_connectivity() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.decide((Y(0), X(0)), Cell::Black);
        field.decide((Y(4), X(5)), Cell::Black);
        field.decide((Y(1), X(0)), Cell::White);
        field.decide((Y(2), X(1)), Cell::White);
        field.decide((Y(0), X(3)), Cell::White);
        field.decide((Y(0), X(2)), Cell::Undecided);
        field.decide((Y(1), X(1)), Cell::Undecided);

        field.inspect_connectivity();

        assert_eq!(field.cell((Y(0), X(1))), Cell::Black);
        assert_eq!(field.cell((Y(1), X(2))), Cell::Black);
        assert_eq!(field.inconsistent(), false);
    }
}
<|endoftext|>


<commit_before>use super::super::{Coord, GraphSeparation, Grid, X, Y};
use super::{Cell, Clue, Dictionary, DICTIONARY_INCONSISTENT, DICTIONARY_NEIGHBOR_OFFSET, NO_CLUE};

pub struct Field<'a> {
    cell: Grid<Cell>,
    clue: Grid<Clue>,
    inconsistent: bool,
    dic: &'a Dictionary,
}

impl<'a> Field<'a> {
    pub fn new(height: i32, width: i32, dic: &'a Dictionary) -> Field {
        Field {
            cell: Grid::new(height, width, Cell::Undecided),
            clue: Grid::new(height, width, NO_CLUE),
            inconsistent: false,
            dic,
        }
    }
    pub fn height(&self) -> i32 {
        self.cell.height()
    }
    pub fn width(&self) -> i32 {
        self.cell.width()
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn set_inconsistent(&mut self) {
        self.inconsistent = true;
    }
    pub fn add_clue(&mut self, loc: Coord, clue: Clue) {
        let current_clue = self.clue[loc];
        if current_clue != NO_CLUE {
            if current_clue != clue {
                self.inconsistent = true;
            }
            return;
        }

        self.clue[loc] = clue;
        self.decide(loc, Cell::White);
    }
    pub fn cell(&self, loc: Coord) -> Cell {
        self.cell[loc]
    }
    pub fn cell_checked(&self, loc: Coord) -> Cell {
        if self.cell.is_valid_coord(loc) {
            self.cell[loc]
        } else {
            Cell::White
        }
    }
    pub fn decide(&mut self, loc: Coord, v: Cell) {
        let current_status = self.cell_checked(loc);
        if current_status != Cell::Undecided {
            if current_status != v {
                self.inconsistent = true;
            }
            return;
        }

        self.cell[loc] = v;

        let (Y(y), X(x)) = loc;

        if v == Cell::Black {
            self.avoid_cluster((Y(y - 1), X(x - 1)), (Y(y - 1), X(x)), (Y(y), X(x - 1)));
            self.avoid_cluster((Y(y - 1), X(x + 1)), (Y(y - 1), X(x)), (Y(y), X(x + 1)));
            self.avoid_cluster((Y(y + 1), X(x - 1)), (Y(y + 1), X(x)), (Y(y), X(x - 1)));
            self.avoid_cluster((Y(y + 1), X(x + 1)), (Y(y + 1), X(x)), (Y(y), X(x + 1)));
        }

        for dy in -1..2 {
            for dx in -1..2 {
                self.inspect((Y(y + dy), X(x + dx)));
            }
        }
    }
    fn avoid_cluster(&mut self, loc1: Coord, loc2: Coord, loc3: Coord) {
        if self.cell_checked(loc1) == Cell::Black {
            if self.cell_checked(loc2) == Cell::Black {
                self.decide(loc3, Cell::White);
            }
            if self.cell_checked(loc3) == Cell::Black {
                self.decide(loc2, Cell::White);
            }
        } else {
            if self.cell_checked(loc2) == Cell::Black && self.cell_checked(loc3) == Cell::Black {
                self.decide(loc1, Cell::White);
            }
        }
    }
    pub fn inspect_connectivity(&mut self) {
        let height = self.height();
        let width = self.width();
        let cells = (height * width) as usize;
        let mut graph = GraphSeparation::new(cells, cells * 2);

        for y in 0..height {
            for x in 0..width {
                let c = self.cell((Y(y), X(x)));
                graph.set_weight(
                    (y * width + x) as usize,
                    if c == Cell::Black { 1 } else { 0 },
                );
                if c != Cell::White {
                    if self.cell_checked((Y(y + 1), X(x))) != Cell::White {
                        graph.add_edge((y * width + x) as usize, ((y + 1) * width + x) as usize);
                    }
                    if self.cell_checked((Y(y), X(x + 1))) != Cell::White {
                        graph.add_edge((y * width + x) as usize, (y * width + (x + 1)) as usize);
                    }
                }
            }
        }

        graph.build();

        for y in 0..height {
            for x in 0..width {
                if self.cell((Y(y), X(x))) == Cell::Undecided {
                    let sep = graph.separate((y * width + x) as usize);
                    let mut nonzero = 0;
                    for v in sep {
                        if v > 0 {
                            nonzero += 1;
                        }
                    }
                    if nonzero >= 2 {
                        self.decide((Y(y), X(x)), Cell::Black);
                    }
                }
            }
        }
    }
    fn inspect(&mut self, loc: Coord) {
        if !self.cell.is_valid_coord(loc) {
            return;
        }

        let (Y(y), X(x)) = loc;
        let cell = self.cell(loc);
        let clue = self.clue[loc];
        if clue != NO_CLUE {
            let mut neighbor = 0;
            let mut pow = 1;
            for i in 0..8 {
                let (Y(dy), X(dx)) = DICTIONARY_NEIGHBOR_OFFSET[i];
                neighbor += pow * match self.cell_checked((Y(y + dy), X(x + dx))) {
                    Cell::Undecided => 0,
                    Cell::Black => 1,
                    Cell::White => 2,
                };
                pow *= 3;
            }
            let neighbor = self.dic.consult_raw(clue, neighbor);

            if neighbor == DICTIONARY_INCONSISTENT {
                self.inconsistent = true;
                return;
            }

            for i in 0..8 {
                let v = (neighbor >> (2 * i)) & 3;
                let (Y(dy), X(dx)) = DICTIONARY_NEIGHBOR_OFFSET[i];
                if v == 1 {
                    self.decide((Y(y + dy), X(x + dx)), Cell::Black);
                } else if v == 2 {
                    self.decide((Y(y + dy), X(x + dx)), Cell::White);
                }
            }
        }
    }
}

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

    #[test]
    fn test_tapa_field_clues() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.add_clue((Y(2), X(1)), clue_pattern_to_id(&[]).unwrap());
        field.add_clue((Y(2), X(3)), clue_pattern_to_id(&[4]).unwrap());

        assert_eq!(field.cell((Y(2), X(0))), Cell::White);
        assert_eq!(field.cell((Y(1), X(4))), Cell::Black);
        assert_eq!(field.cell((Y(2), X(4))), Cell::Black);
        assert_eq!(field.cell((Y(3), X(4))), Cell::Black);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_tapa_field_cluster() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.decide(((Y(1), X(1))), Cell::Black);
        field.decide(((Y(1), X(2))), Cell::Black);
        field.decide(((Y(2), X(2))), Cell::Black);

        assert_eq!(field.cell((Y(2), X(1))), Cell::White);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_tapa_field_connectivity() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.decide((Y(0), X(0)), Cell::Black);
        field.decide((Y(4), X(5)), Cell::Black);
        field.decide((Y(1), X(0)), Cell::White);
        field.decide((Y(2), X(1)), Cell::White);
        field.decide((Y(0), X(3)), Cell::White);
        field.decide((Y(0), X(2)), Cell::Undecided);
        field.decide((Y(1), X(1)), Cell::Undecided);

        field.inspect_connectivity();

        assert_eq!(field.cell((Y(0), X(1))), Cell::Black);
        assert_eq!(field.cell((Y(1), X(2))), Cell::Black);
        assert_eq!(field.inconsistent(), false);
    }
}
<commit_msg>Tapa: implement Display for Field, add a test with a problem<commit_after>use super::super::{Coord, GraphSeparation, Grid, X, Y};
use super::{Cell, Clue, Dictionary, CLUE_VALUES, DICTIONARY_INCONSISTENT,
            DICTIONARY_NEIGHBOR_OFFSET, NO_CLUE};
use std::fmt;

pub struct Field<'a> {
    cell: Grid<Cell>,
    clue: Grid<Clue>,
    inconsistent: bool,
    dic: &'a Dictionary,
}

impl<'a> Field<'a> {
    pub fn new(height: i32, width: i32, dic: &'a Dictionary) -> Field {
        Field {
            cell: Grid::new(height, width, Cell::Undecided),
            clue: Grid::new(height, width, NO_CLUE),
            inconsistent: false,
            dic,
        }
    }
    pub fn height(&self) -> i32 {
        self.cell.height()
    }
    pub fn width(&self) -> i32 {
        self.cell.width()
    }
    pub fn inconsistent(&self) -> bool {
        self.inconsistent
    }
    pub fn set_inconsistent(&mut self) {
        self.inconsistent = true;
    }
    pub fn clue(&self, loc: Coord) -> Clue {
        self.clue[loc]
    }
    pub fn add_clue(&mut self, loc: Coord, clue: Clue) {
        let current_clue = self.clue[loc];
        if current_clue != NO_CLUE {
            if current_clue != clue {
                self.inconsistent = true;
            }
            return;
        }

        self.clue[loc] = clue;
        self.decide(loc, Cell::White);
    }
    pub fn cell(&self, loc: Coord) -> Cell {
        self.cell[loc]
    }
    pub fn cell_checked(&self, loc: Coord) -> Cell {
        if self.cell.is_valid_coord(loc) {
            self.cell[loc]
        } else {
            Cell::White
        }
    }
    pub fn decide(&mut self, loc: Coord, v: Cell) {
        let current_status = self.cell_checked(loc);
        if current_status != Cell::Undecided {
            if current_status != v {
                self.inconsistent = true;
            }
            return;
        }

        self.cell[loc] = v;

        let (Y(y), X(x)) = loc;

        if v == Cell::Black {
            self.avoid_cluster((Y(y - 1), X(x - 1)), (Y(y - 1), X(x)), (Y(y), X(x - 1)));
            self.avoid_cluster((Y(y - 1), X(x + 1)), (Y(y - 1), X(x)), (Y(y), X(x + 1)));
            self.avoid_cluster((Y(y + 1), X(x - 1)), (Y(y + 1), X(x)), (Y(y), X(x - 1)));
            self.avoid_cluster((Y(y + 1), X(x + 1)), (Y(y + 1), X(x)), (Y(y), X(x + 1)));
        }

        for dy in -1..2 {
            for dx in -1..2 {
                self.inspect((Y(y + dy), X(x + dx)));
            }
        }
    }
    fn avoid_cluster(&mut self, loc1: Coord, loc2: Coord, loc3: Coord) {
        if self.cell_checked(loc1) == Cell::Black {
            if self.cell_checked(loc2) == Cell::Black {
                self.decide(loc3, Cell::White);
            }
            if self.cell_checked(loc3) == Cell::Black {
                self.decide(loc2, Cell::White);
            }
        } else {
            if self.cell_checked(loc2) == Cell::Black && self.cell_checked(loc3) == Cell::Black {
                self.decide(loc1, Cell::White);
            }
        }
    }
    pub fn inspect_connectivity(&mut self) {
        let height = self.height();
        let width = self.width();
        let cells = (height * width) as usize;
        let mut graph = GraphSeparation::new(cells, cells * 2);

        for y in 0..height {
            for x in 0..width {
                let c = self.cell((Y(y), X(x)));
                graph.set_weight(
                    (y * width + x) as usize,
                    if c == Cell::Black { 1 } else { 0 },
                );
                if c != Cell::White {
                    if self.cell_checked((Y(y + 1), X(x))) != Cell::White {
                        graph.add_edge((y * width + x) as usize, ((y + 1) * width + x) as usize);
                    }
                    if self.cell_checked((Y(y), X(x + 1))) != Cell::White {
                        graph.add_edge((y * width + x) as usize, (y * width + (x + 1)) as usize);
                    }
                }
            }
        }

        graph.build();

        for y in 0..height {
            for x in 0..width {
                if self.cell((Y(y), X(x))) == Cell::Undecided {
                    let sep = graph.separate((y * width + x) as usize);
                    let mut nonzero = 0;
                    for v in sep {
                        if v > 0 {
                            nonzero += 1;
                        }
                    }
                    if nonzero >= 2 {
                        self.decide((Y(y), X(x)), Cell::Black);
                    }
                }
            }
        }
    }
    fn inspect(&mut self, loc: Coord) {
        if !self.cell.is_valid_coord(loc) {
            return;
        }

        let (Y(y), X(x)) = loc;
        let cell = self.cell(loc);
        let clue = self.clue[loc];
        if clue != NO_CLUE {
            let mut neighbor = 0;
            let mut pow = 1;
            for i in 0..8 {
                let (Y(dy), X(dx)) = DICTIONARY_NEIGHBOR_OFFSET[i];
                neighbor += pow * match self.cell_checked((Y(y + dy), X(x + dx))) {
                    Cell::Undecided => 0,
                    Cell::Black => 1,
                    Cell::White => 2,
                };
                pow *= 3;
            }
            let neighbor = self.dic.consult_raw(clue, neighbor);

            if neighbor == DICTIONARY_INCONSISTENT {
                self.inconsistent = true;
                return;
            }

            for i in 0..8 {
                let v = (neighbor >> (2 * i)) & 3;
                let (Y(dy), X(dx)) = DICTIONARY_NEIGHBOR_OFFSET[i];
                if v == 1 {
                    self.decide((Y(y + dy), X(x + dx)), Cell::Black);
                } else if v == 2 {
                    self.decide((Y(y + dy), X(x + dx)), Cell::White);
                }
            }
        }
    }
}

impl<'a> fmt::Display for Field<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let height = self.height();
        let width = self.width();
        for y in 0..height {
            for x in 0..width {
                match self.cell((Y(y), X(x))) {
                    Cell::Undecided => write!(f, ".... ")?,
                    Cell::Black => write!(f, "#### ")?,
                    Cell::White => {
                        let clue = self.clue((Y(y), X(x)));
                        if clue == NO_CLUE {
                            write!(f, "____ ")?;
                        } else {
                            let Clue(id) = clue;
                            if id == 0 {
                                write!(f, "0____ ")?;
                            } else {
                                for i in 0..4 {
                                    let v = CLUE_VALUES[id as usize][i];
                                    if v == -1 {
                                        write!(f, "_")?;
                                    } else {
                                        write!(f, "{}", v)?;
                                    }
                                }
                                write!(f, " ")?;
                            }
                        }
                    }
                }
            }
            writeln!(f)?;
        }
        Ok(())
    }
}

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

    #[test]
    fn test_tapa_field_clues() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.add_clue((Y(2), X(1)), clue_pattern_to_id(&[]).unwrap());
        field.add_clue((Y(2), X(3)), clue_pattern_to_id(&[4]).unwrap());

        assert_eq!(field.cell((Y(2), X(0))), Cell::White);
        assert_eq!(field.cell((Y(1), X(4))), Cell::Black);
        assert_eq!(field.cell((Y(2), X(4))), Cell::Black);
        assert_eq!(field.cell((Y(3), X(4))), Cell::Black);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_tapa_field_cluster() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.decide(((Y(1), X(1))), Cell::Black);
        field.decide(((Y(1), X(2))), Cell::Black);
        field.decide(((Y(2), X(2))), Cell::Black);

        assert_eq!(field.cell((Y(2), X(1))), Cell::White);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_tapa_field_connectivity() {
        let dic = Dictionary::complete();

        let mut field = Field::new(5, 6, &dic);
        field.decide((Y(0), X(0)), Cell::Black);
        field.decide((Y(4), X(5)), Cell::Black);
        field.decide((Y(1), X(0)), Cell::White);
        field.decide((Y(2), X(1)), Cell::White);
        field.decide((Y(0), X(3)), Cell::White);
        field.decide((Y(0), X(2)), Cell::Undecided);
        field.decide((Y(1), X(1)), Cell::Undecided);

        field.inspect_connectivity();

        assert_eq!(field.cell((Y(0), X(1))), Cell::Black);
        assert_eq!(field.cell((Y(1), X(2))), Cell::Black);
        assert_eq!(field.inconsistent(), false);
    }

    #[test]
    fn test_tapa_field_problem() {
        let dic = Dictionary::complete();

        let mut field = Field::new(6, 5, &dic);
        field.add_clue((Y(1), X(0)), clue_pattern_to_id(&[1, 3]).unwrap());
        field.add_clue((Y(1), X(2)), clue_pattern_to_id(&[2, 4]).unwrap());
        field.add_clue((Y(3), X(1)), clue_pattern_to_id(&[3, 3]).unwrap());
        field.add_clue((Y(4), X(3)), clue_pattern_to_id(&[4]).unwrap());

        field.inspect_connectivity();
        field.inspect_connectivity();
        field.inspect_connectivity();

        let expected = [
            [1, 1, 1, 1, 1],
            [0, 1, 0, 0, 1],
            [1, 0, 1, 1, 1],
            [1, 0, 1, 0, 0],
            [1, 0, 1, 0, 0],
            [1, 1, 1, 1, 0],
        ];
        for y in 0..6 {
            for x in 0..5 {
                assert_eq!(
                    field.cell((Y(y), X(x))),
                    if expected[y as usize][x as usize] == 1 {
                        Cell::Black
                    } else {
                        Cell::White
                    }
                );
            }
        }
        assert_eq!(field.inconsistent(), false);
    }
}
<|endoftext|>


<commit_before>use crate::tls::*;
use crate::tls_alert::TlsAlertSeverity;

/// Error types for the state machine
pub enum StateChangeError {
    InvalidTransition,
    ParseError,
}

/// TLS machine possible states
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum TlsState {
    None,
    ClientHello,
    AskResumeSession,
    ResumeSession,
    ServerHello,
    Certificate,
    CertificateSt,
    ServerKeyExchange,
    ServerHelloDone,
    ClientKeyExchange,
    ClientChangeCipherSpec,

    CRCertRequest,
    CRHelloDone,
    CRCert,
    CRClientKeyExchange,
    CRCertVerify,

    NoCertSKE,
    NoCertHelloDone,
    NoCertCKE,

    PskHelloDone,
    PskCKE,

    SessionEncrypted,

    Alert,

    Finished,

    Invalid,
}

#[rustfmt::skip]
fn tls_state_transition_handshake(state: TlsState, msg: &TlsMessageHandshake, to_server:bool) -> Result<TlsState,StateChangeError> {
    match (state,msg,to_server) {
        (TlsState::None,             &TlsMessageHandshake::ClientHello(ref msg), true) => {
            match msg.session_id {
                Some(_) => Ok(TlsState::AskResumeSession),
                _       => Ok(TlsState::ClientHello)
            }
        },
        // Server certificate
        (TlsState::ClientHello,      &TlsMessageHandshake::ServerHello(_), false)       => Ok(TlsState::ServerHello),
        (TlsState::ServerHello,      &TlsMessageHandshake::Certificate(_), false)       => Ok(TlsState::Certificate),
        // Server certificate, no client certificate requested
        (TlsState::Certificate,      &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::ServerKeyExchange),
        (TlsState::Certificate,      &TlsMessageHandshake::CertificateStatus(_), false) => Ok(TlsState::CertificateSt),
        (TlsState::CertificateSt,    &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::ServerKeyExchange),
        (TlsState::ServerKeyExchange,&TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::ServerHelloDone),
        (TlsState::ServerHelloDone  ,&TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::ClientKeyExchange),
        // Server certificate, client certificate requested
        (TlsState::Certificate,      &TlsMessageHandshake::CertificateRequest(_), false)=> Ok(TlsState::CRCertRequest),
        (TlsState::ServerKeyExchange,&TlsMessageHandshake::CertificateRequest(_), false)=> Ok(TlsState::CRCertRequest),
        (TlsState::CRCertRequest,    &TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::CRHelloDone),
        (TlsState::CRHelloDone,      &TlsMessageHandshake::Certificate(_), false)       => Ok(TlsState::CRCert),
        (TlsState::CRCert,           &TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::CRClientKeyExchange),
        (TlsState::CRClientKeyExchange, &TlsMessageHandshake::CertificateVerify(_), _)  => Ok(TlsState::CRCertVerify),
        // Server has no certificate (but accepts anonymous)
        (TlsState::ServerHello,      &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::NoCertSKE),
        (TlsState::NoCertSKE,        &TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::NoCertHelloDone),
        (TlsState::NoCertHelloDone,  &TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::NoCertCKE),
        // PSK
        (TlsState::Certificate,      &TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::PskHelloDone),
        (TlsState::PskHelloDone,     &TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::PskCKE),
        // Resuming session
        (TlsState::AskResumeSession, &TlsMessageHandshake::ServerHello(_), false)       => Ok(TlsState::ResumeSession),
        // Resume session failed
        (TlsState::ResumeSession,    &TlsMessageHandshake::Certificate(_), false)       => Ok(TlsState::Certificate),
        // TLS 1.3 Draft 18 1-RTT
        // Re-use the ClientChangeCipherSpec state to indicate the next message will be encrypted
        (TlsState::ClientHello,      &TlsMessageHandshake::ServerHelloV13Draft18(_), false)    => Ok(TlsState::ClientChangeCipherSpec),
        // Hello requests must be accepted at any time (except start), but ignored [RFC5246] 7.4.1.1
        (TlsState::None,             &TlsMessageHandshake::HelloRequest, _)             => Err(StateChangeError::InvalidTransition),
        (s,                          &TlsMessageHandshake::HelloRequest, _)             => Ok(s),
        // All other transitions are considered invalid
        _ => Err(StateChangeError::InvalidTransition),
    }
}

/// Update the TLS state machine, doing one transition
///
/// Given the previous state and the parsed message, return the new state or a state machine error.
///
/// This state machine only implements the TLS handshake.
///
/// Some transitions only check the new message type, while some others must match the content
/// (for example, to check if the client asked to resume a session).
///
/// If the previous state is `Invalid`, the state machine will not return an error, but keep the
/// same `Invalid` state. This is used to raise error only once if the state machine keeps being
/// updated by new messages.
#[rustfmt::skip]
pub fn tls_state_transition(state: TlsState, msg: &TlsMessage, to_server:bool) -> Result<TlsState,StateChangeError> {
    match (state,msg,to_server) {
        (TlsState::Invalid,_,_) => Ok(TlsState::Invalid),
        (TlsState::Finished,_,_) => Ok(TlsState::Invalid),
        (_,&TlsMessage::Handshake(ref m),_) => tls_state_transition_handshake(state,m,to_server),
        // Server certificate
        (TlsState::ClientKeyExchange,     &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        (TlsState::ClientChangeCipherSpec,&TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::SessionEncrypted),
        // Server certificate, client certificate requested
        (TlsState::CRClientKeyExchange,   &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        (TlsState::CRCertVerify,          &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        // No server certificate
        (TlsState::NoCertCKE,             &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        // PSK
        (TlsState::PskCKE,                &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        // Resume session
        (TlsState::ResumeSession,         &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        // 0-rtt
        (TlsState::AskResumeSession,      &TlsMessage::ChangeCipherSpec, true) => Ok(TlsState::AskResumeSession),
        // non-fatal alerts
        (s,                               &TlsMessage::Alert(ref a), _) => {
            if a.severity == TlsAlertSeverity::Warning { Ok(s) } else { Ok(TlsState::Finished) }
        },
        (_,_,_) => Err(StateChangeError::InvalidTransition),
    }
}
<commit_msg>Fix error in state machine (wrong Client Certificate direction)<commit_after>use crate::tls::*;
use crate::tls_alert::TlsAlertSeverity;

/// Error types for the state machine
pub enum StateChangeError {
    InvalidTransition,
    ParseError,
}

/// TLS machine possible states
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum TlsState {
    None,
    ClientHello,
    AskResumeSession,
    ResumeSession,
    ServerHello,
    Certificate,
    CertificateSt,
    ServerKeyExchange,
    ServerHelloDone,
    ClientKeyExchange,
    ClientChangeCipherSpec,

    CRCertRequest,
    CRHelloDone,
    CRCert,
    CRClientKeyExchange,
    CRCertVerify,

    NoCertSKE,
    NoCertHelloDone,
    NoCertCKE,

    PskHelloDone,
    PskCKE,

    SessionEncrypted,

    Alert,

    Finished,

    Invalid,
}

#[rustfmt::skip]
fn tls_state_transition_handshake(state: TlsState, msg: &TlsMessageHandshake, to_server:bool) -> Result<TlsState,StateChangeError> {
    match (state,msg,to_server) {
        (TlsState::None,             &TlsMessageHandshake::ClientHello(ref msg), true) => {
            match msg.session_id {
                Some(_) => Ok(TlsState::AskResumeSession),
                _       => Ok(TlsState::ClientHello)
            }
        },
        // Server certificate
        (TlsState::ClientHello,      &TlsMessageHandshake::ServerHello(_), false)       => Ok(TlsState::ServerHello),
        (TlsState::ServerHello,      &TlsMessageHandshake::Certificate(_), false)       => Ok(TlsState::Certificate),
        // Server certificate, no client certificate requested
        (TlsState::Certificate,      &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::ServerKeyExchange),
        (TlsState::Certificate,      &TlsMessageHandshake::CertificateStatus(_), false) => Ok(TlsState::CertificateSt),
        (TlsState::CertificateSt,    &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::ServerKeyExchange),
        (TlsState::ServerKeyExchange,&TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::ServerHelloDone),
        (TlsState::ServerHelloDone  ,&TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::ClientKeyExchange),
        // Server certificate, client certificate requested
        (TlsState::Certificate,      &TlsMessageHandshake::CertificateRequest(_), false)=> Ok(TlsState::CRCertRequest),
        (TlsState::ServerKeyExchange,&TlsMessageHandshake::CertificateRequest(_), false)=> Ok(TlsState::CRCertRequest),
        (TlsState::CRCertRequest,    &TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::CRHelloDone),
        (TlsState::CRHelloDone,      &TlsMessageHandshake::Certificate(_), true)        => Ok(TlsState::CRCert),
        (TlsState::CRCert,           &TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::CRClientKeyExchange),
        (TlsState::CRClientKeyExchange, &TlsMessageHandshake::CertificateVerify(_), _)  => Ok(TlsState::CRCertVerify),
        // Server has no certificate (but accepts anonymous)
        (TlsState::ServerHello,      &TlsMessageHandshake::ServerKeyExchange(_), false) => Ok(TlsState::NoCertSKE),
        (TlsState::NoCertSKE,        &TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::NoCertHelloDone),
        (TlsState::NoCertHelloDone,  &TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::NoCertCKE),
        // PSK
        (TlsState::Certificate,      &TlsMessageHandshake::ServerDone(_), false)        => Ok(TlsState::PskHelloDone),
        (TlsState::PskHelloDone,     &TlsMessageHandshake::ClientKeyExchange(_), true)  => Ok(TlsState::PskCKE),
        // Resuming session
        (TlsState::AskResumeSession, &TlsMessageHandshake::ServerHello(_), false)       => Ok(TlsState::ResumeSession),
        // Resume session failed
        (TlsState::ResumeSession,    &TlsMessageHandshake::Certificate(_), false)       => Ok(TlsState::Certificate),
        // TLS 1.3 Draft 18 1-RTT
        // Re-use the ClientChangeCipherSpec state to indicate the next message will be encrypted
        (TlsState::ClientHello,      &TlsMessageHandshake::ServerHelloV13Draft18(_), false)    => Ok(TlsState::ClientChangeCipherSpec),
        // Hello requests must be accepted at any time (except start), but ignored [RFC5246] 7.4.1.1
        (TlsState::None,             &TlsMessageHandshake::HelloRequest, _)             => Err(StateChangeError::InvalidTransition),
        (s,                          &TlsMessageHandshake::HelloRequest, _)             => Ok(s),
        // All other transitions are considered invalid
        _ => Err(StateChangeError::InvalidTransition),
    }
}

/// Update the TLS state machine, doing one transition
///
/// Given the previous state and the parsed message, return the new state or a state machine error.
///
/// This state machine only implements the TLS handshake.
///
/// Some transitions only check the new message type, while some others must match the content
/// (for example, to check if the client asked to resume a session).
///
/// If the previous state is `Invalid`, the state machine will not return an error, but keep the
/// same `Invalid` state. This is used to raise error only once if the state machine keeps being
/// updated by new messages.
#[rustfmt::skip]
pub fn tls_state_transition(state: TlsState, msg: &TlsMessage, to_server:bool) -> Result<TlsState,StateChangeError> {
    match (state,msg,to_server) {
        (TlsState::Invalid,_,_) => Ok(TlsState::Invalid),
        (TlsState::Finished,_,_) => Ok(TlsState::Invalid),
        (_,&TlsMessage::Handshake(ref m),_) => tls_state_transition_handshake(state,m,to_server),
        // Server certificate
        (TlsState::ClientKeyExchange,     &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        (TlsState::ClientChangeCipherSpec,&TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::SessionEncrypted),
        // Server certificate, client certificate requested
        (TlsState::CRClientKeyExchange,   &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        (TlsState::CRCertVerify,          &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        // No server certificate
        (TlsState::NoCertCKE,             &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        // PSK
        (TlsState::PskCKE,                &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        // Resume session
        (TlsState::ResumeSession,         &TlsMessage::ChangeCipherSpec, _) => Ok(TlsState::ClientChangeCipherSpec),
        // 0-rtt
        (TlsState::AskResumeSession,      &TlsMessage::ChangeCipherSpec, true) => Ok(TlsState::AskResumeSession),
        // non-fatal alerts
        (s,                               &TlsMessage::Alert(ref a), _) => {
            if a.severity == TlsAlertSeverity::Warning { Ok(s) } else { Ok(TlsState::Finished) }
        },
        (_,_,_) => Err(StateChangeError::InvalidTransition),
    }
}
<|endoftext|>


<commit_before>// Claxon -- A FLAC decoding library in Rust
// Copyright 2015 van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

extern crate claxon;
extern crate hound;

use claxon::{Block, FlacReader};
use hound::{WavSpec, WavWriter};
use std::env;
use std::path;

fn main() {
    let arg = env::args().nth(1).expect("no file given");
    let fname = path::Path::new(&arg);
    let mut reader = FlacReader::open(fname).expect("failed to open FLAC stream");

    let spec = WavSpec {
        // TODO: u8 for channels, is that weird? Would u32 be better?
        channels: reader.streaminfo().channels as u16,
        sample_rate: reader.streaminfo().sample_rate,
        // TODO: again, would u32 be better, even if the range is smaller?
        bits_per_sample: reader.streaminfo().bits_per_sample as u16,
        sample_format: hound::SampleFormat::Int,
    };
    let fname_wav = fname.with_extension("wav");
    let mut wav_writer = WavWriter::create(fname_wav, spec).expect("failed to create wav file");
    {
        // TODO: Write fallback for other sample widths and channel numbers.
        assert!(reader.streaminfo().bits_per_sample == 16);
        assert!(reader.streaminfo().channels == 2);

        let mut frame_reader = reader.blocks();
        let mut block = Block::empty();
        loop {
            // Read a single frame. Recycle the buffer from the previous frame to
            // avoid allocations as much as possible.
            match frame_reader.read_next_or_eof(block.into_buffer()) {
                Ok(Some(next_block)) => block = next_block,
                Ok(None) => break, // EOF.
                Err(error) => panic!("{}", error),
            }

            let mut sample_writer = wav_writer.get_i16_writer(block.duration() * 2);

            // Write the samples in the block to the wav file, channels interleaved.
            for (left, right) in block.stereo_samples() {
                sample_writer.write_sample(left);
                sample_writer.write_sample(right);
            }

            sample_writer.flush().expect("failed to write samples to wav file");
        }
    }

    wav_writer.finalize().expect("failed to finalize wav file");
}
<commit_msg>Use Hound's new unchecked sample writer<commit_after>// Claxon -- A FLAC decoding library in Rust
// Copyright 2015 van Asseldonk
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// A copy of the License has been included in the root of the repository.

extern crate claxon;
extern crate hound;

use claxon::{Block, FlacReader};
use hound::{WavSpec, WavWriter};
use std::env;
use std::path;

fn main() {
    let arg = env::args().nth(1).expect("no file given");
    let fname = path::Path::new(&arg);
    let mut reader = FlacReader::open(fname).expect("failed to open FLAC stream");

    let spec = WavSpec {
        // TODO: u8 for channels, is that weird? Would u32 be better?
        channels: reader.streaminfo().channels as u16,
        sample_rate: reader.streaminfo().sample_rate,
        // TODO: again, would u32 be better, even if the range is smaller?
        bits_per_sample: reader.streaminfo().bits_per_sample as u16,
        sample_format: hound::SampleFormat::Int,
    };
    let fname_wav = fname.with_extension("wav");
    let mut wav_writer = WavWriter::create(fname_wav, spec).expect("failed to create wav file");
    {
        // TODO: Write fallback for other sample widths and channel numbers.
        assert!(reader.streaminfo().bits_per_sample == 16);
        assert!(reader.streaminfo().channels == 2);

        let mut frame_reader = reader.blocks();
        let mut block = Block::empty();
        loop {
            // Read a single frame. Recycle the buffer from the previous frame to
            // avoid allocations as much as possible.
            match frame_reader.read_next_or_eof(block.into_buffer()) {
                Ok(Some(next_block)) => block = next_block,
                Ok(None) => break, // EOF.
                Err(error) => panic!("{}", error),
            }

            let mut sample_writer = wav_writer.get_i16_writer(block.duration() * 2);

            // Write the samples in the block to the wav file, channels interleaved.
            for (left, right) in block.stereo_samples() {
                // The `stereo_samples()` iterator does not yield more samples
                // than the duration of the block, so we never write more
                // samples to the writer than requested, hence using the
                // unchecked functions is safe here.
                unsafe {
                    sample_writer.write_sample_unchecked(left);
                    sample_writer.write_sample_unchecked(right);
                }
            }

            sample_writer.flush().expect("failed to write samples to wav file");
        }
    }

    wav_writer.finalize().expect("failed to finalize wav file");
}
<|endoftext|>


<commit_before>extern crate ggez;
extern crate specs;

use ggez::{Game, State, GameError, Context};
use std::time::Duration;
use std::path::Path;
use specs::{Join, World};

struct Transform {
    position: (u32, u32),
    rotation: f32,
}

impl specs::Component for Transform {
    type Storage = specs::VecStorage<Transform>;
}

struct MainState {
    planner: specs::Planner<()>,
    a: i32
}

impl MainState {
    fn new() -> MainState {
        let mut world = specs::World::new();
        world.register::<Transform>();
        world.create_now()
             .with(Transform {
                 position: (50, 50),
                 rotation: 0f32,
             })
             .build();
        MainState { planner: specs::Planner::new(world, 4), a: 0 }
    }
}

impl State for MainState {
    fn load(&mut self, ctx: &mut Context) -> Result<(), GameError>
    {
        println!("load");
        ctx.resources.load_sound("sound", Path::new("./resources/sound.mp3"));
        Ok(())
    }
    fn update(&mut self, ctx: &mut Context, dt: Duration) -> Result<(), GameError>
    {
        self.a = self.a + 1;
        if self.a > 100
        {
            self.a = 0;
            //let _ : () = Game::play_sound(ctx, "sound");
        }

        println!("update");
        Ok(())
    }

    fn draw(&mut self) -> Result<(), GameError> {
        println!("draw");
        Ok(())
    }
}

pub fn main() {
    let mut g = MainState::new();
    let mut e: Game<MainState> = Game::new(g);
    e.run();
}
<commit_msg>fontmanagement broken<commit_after>extern crate ggez;
extern crate specs;

use ggez::{Game, State, GameError, Context};
use std::time::Duration;
use std::path::Path;
use specs::{Join, World};

struct Transform {
    position: (u32, u32),
    rotation: f32,
}

impl specs::Component for Transform {
    type Storage = specs::VecStorage<Transform>;
}

struct MainState {
    planner: specs::Planner<()>,
    a: i32
}

impl MainState {
    fn new() -> MainState {
        let mut world = specs::World::new();
        world.register::<Transform>();
        world.create_now()
             .with(Transform {
                 position: (50, 50),
                 rotation: 0f32,
             })
             .build();
        MainState { planner: specs::Planner::new(world, 4), a: 0 }
    }
}

impl State for MainState {
    fn load(&mut self, ctx: &mut Context) -> Result<(), GameError>
    {
        println!("load");
        ctx.resources.load_sound("sound", Path::new("./resources/sound.mp3"));
        Ok(())
    }
    fn update(&mut self, ctx: &mut Context, dt: Duration) -> Result<(), GameError>
    {
        println!("update");
        self.planner.run1w0r(|t: &mut Transform| {
            t.position.0 += 1;
            t.position.1 += 1;
        });
        self.a = self.a + 1;
        if self.a > 100
        {
            self.a = 0;
            //let _ : () = Game::play_sound(ctx, "sound");
        }
        Ok(())
    }

    fn draw(&mut self) -> Result<(), GameError> {
        println!("draw");
        Ok(())
    }
}

pub fn main() {
    let mut g = MainState::new();
    let mut e: Game<MainState> = Game::new(g);
    e.run();
}
<|endoftext|>


<commit_before>use backend::Backend;
use query_builder::*;
use result::QueryResult;
use super::{Expression, SelectableExpression};
use types::BigInt;

/// Creates a SQL `COUNT` expression
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::expression::count`, or glob import
/// `diesel::expression::dsl::*`
pub fn count<T: Expression>(t: T) -> Count<T> {
    Count {
        target: t,
    }
}

/// Creates a SQL `COUNT(*)` expression
///
/// For selecting the count of a query, and nothing else, you can just call
/// [`count`](../../trait.CountDsl.html) on the query instead.
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::expression::count_star`, or glob import
/// `diesel::expression::dsl::*`
///
/// # Example
///
/// # #[macro_use] extern crate diesel;
/// # include!("src/doctest_setup.rs");
/// # use diesel::expression::dsl::*;
/// #
/// # table! {
/// #     users {
/// #         id -> Serial,
/// #         name -> VarChar,
/// #     }
/// # }
/// #
/// # fn main() {
/// #     use self::users::dsl::*;
/// #     let connection = establish_connection();
/// assert_eq!(Ok(Some(2)), users.select(count_star()).first(&connection));
/// # }
pub fn count_star() -> CountStar {
    CountStar
}

#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Count<T> {
    target: T,
}

impl<T: Expression> Expression for Count<T> {
    type SqlType = BigInt;
}

impl<T: QueryFragment<DB>, DB: Backend> QueryFragment<DB> for Count<T> {
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        out.push_sql("COUNT(");
        try!(self.target.to_sql(out));
        out.push_sql(")");
        Ok(())
    }

    fn collect_binds(&self, out: &mut DB::BindCollector) -> QueryResult<()> {
        try!(self.target.collect_binds(out));
        Ok(())
    }

    fn is_safe_to_cache_prepared(&self) -> bool {
        self.target.is_safe_to_cache_prepared()
    }
}

impl_query_id!(Count<T>);

impl<T: Expression, QS> SelectableExpression<QS> for Count<T> {
}

#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CountStar;

impl Expression for CountStar {
    type SqlType = BigInt;
}

impl<DB: Backend> QueryFragment<DB> for CountStar {
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        out.push_sql("COUNT(*)");
        Ok(())
    }

    fn collect_binds(&self, _out: &mut DB::BindCollector) -> QueryResult<()> {
        Ok(())
    }

    fn is_safe_to_cache_prepared(&self) -> bool {
        true
    }
}

impl<QS> SelectableExpression<QS> for CountStar {
}

impl_query_id!(CountStar);
<commit_msg>Update Doc Comment Markup<commit_after>use backend::Backend;
use query_builder::*;
use result::QueryResult;
use super::{Expression, SelectableExpression};
use types::BigInt;

/// Creates a SQL `COUNT` expression
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::expression::count`, or glob import
/// `diesel::expression::dsl::*`
pub fn count<T: Expression>(t: T) -> Count<T> {
    Count {
        target: t,
    }
}

/// Creates a SQL `COUNT(*)` expression
///
/// For selecting the count of a query, and nothing else, you can just call
/// [`count`](../../trait.CountDsl.html) on the query instead.
///
/// As with most bare functions, this is not exported by default. You can import
/// it specifically as `diesel::expression::count_star`, or glob import
/// `diesel::expression::dsl::*`
///
/// # Example
///
/// ```rust
/// # #[macro_use] extern crate diesel;
/// # include!("src/doctest_setup.rs");
/// # use diesel::expression::dsl::*;
/// #
/// # table! {
/// #     users {
/// #         id -> Integer,
/// #         name -> VarChar,
/// #     }
/// # }
/// #
/// # fn main() {
/// #     use self::users::dsl::*;
/// #     let connection = establish_connection();
/// assert_eq!(Ok(2), users.select(count_star()).first(&connection));
/// # }
/// ```
pub fn count_star() -> CountStar {
    CountStar
}

#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct Count<T> {
    target: T,
}

impl<T: Expression> Expression for Count<T> {
    type SqlType = BigInt;
}

impl<T: QueryFragment<DB>, DB: Backend> QueryFragment<DB> for Count<T> {
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        out.push_sql("COUNT(");
        try!(self.target.to_sql(out));
        out.push_sql(")");
        Ok(())
    }

    fn collect_binds(&self, out: &mut DB::BindCollector) -> QueryResult<()> {
        try!(self.target.collect_binds(out));
        Ok(())
    }

    fn is_safe_to_cache_prepared(&self) -> bool {
        self.target.is_safe_to_cache_prepared()
    }
}

impl_query_id!(Count<T>);

impl<T: Expression, QS> SelectableExpression<QS> for Count<T> {
}

#[derive(Debug, Clone, Copy)]
#[doc(hidden)]
pub struct CountStar;

impl Expression for CountStar {
    type SqlType = BigInt;
}

impl<DB: Backend> QueryFragment<DB> for CountStar {
    fn to_sql(&self, out: &mut DB::QueryBuilder) -> BuildQueryResult {
        out.push_sql("COUNT(*)");
        Ok(())
    }

    fn collect_binds(&self, _out: &mut DB::BindCollector) -> QueryResult<()> {
        Ok(())
    }

    fn is_safe_to_cache_prepared(&self) -> bool {
        true
    }
}

impl<QS> SelectableExpression<QS> for CountStar {
}

impl_query_id!(CountStar);
<|endoftext|>


<commit_before>extern crate iron;
extern crate mount;
extern crate logger;
extern crate rustc_serialize;
#[macro_use] extern crate juniper;

use std::env;

use mount::Mount;
use logger::Logger;
use iron::prelude::*;
use juniper::FieldResult;
use juniper::iron_handlers::{GraphQLHandler, GraphiQLHandler};

fn context_factory(_: &mut Request) -> () {
    ()
}

fn main() {
    let mut mount = Mount::new();

    let graphql_endpoint = GraphQLHandler::new(context_factory, Query { }, Mutation { });
    let graphiql_endpoint = GraphiQLHandler::new("/graphql");

    mount.mount("/graphiql", graphiql_endpoint);
    mount.mount("/graphql", graphql_endpoint);

    let (logger_before, logger_after) = Logger::new(None);

    let mut chain = Chain::new(mount);
    chain.link_before(logger_before);
    chain.link_after(logger_after);

    let host = env::var("LISTEN").unwrap_or("0.0.0.0:8080".to_owned());
    println!("GraphQL server started on {}", host);
    Iron::new(chain).http(host.as_str()).unwrap();
}

struct Query {}
struct Mutation {}

graphql_object!(Query: () as "Query" |&self| {
    field dummy() -> FieldResult<&str> {
        Ok("Dummy field")
    }

    field error() -> FieldResult<&str> {
        Err("Can't do it".to_owned())
    }
});

graphql_object!(<CtxT> Mutation: CtxT as "Mutation" |&self| {
    field print(value: String) -> FieldResult<String> {
        println!("Printing text according to mutation");
        println!("{}", value);
        Ok(value)
    }
});
<commit_msg>Move GraphiQL to root<commit_after>extern crate iron;
extern crate mount;
extern crate logger;
extern crate rustc_serialize;
#[macro_use] extern crate juniper;

use std::env;

use mount::Mount;
use logger::Logger;
use iron::prelude::*;
use juniper::FieldResult;
use juniper::iron_handlers::{GraphQLHandler, GraphiQLHandler};

fn context_factory(_: &mut Request) -> () {
    ()
}

fn main() {
    let mut mount = Mount::new();

    let graphql_endpoint = GraphQLHandler::new(context_factory, Query { }, Mutation { });
    let graphiql_endpoint = GraphiQLHandler::new("/graphql");

    mount.mount("/", graphiql_endpoint);
    mount.mount("/graphql", graphql_endpoint);

    let (logger_before, logger_after) = Logger::new(None);

    let mut chain = Chain::new(mount);
    chain.link_before(logger_before);
    chain.link_after(logger_after);

    let host = env::var("LISTEN").unwrap_or("0.0.0.0:8080".to_owned());
    println!("GraphQL server started on {}", host);
    Iron::new(chain).http(host.as_str()).unwrap();
}

struct Query {}
struct Mutation {}

graphql_object!(Query: () as "Query" |&self| {
    field dummy() -> FieldResult<&str> {
        Ok("Dummy field")
    }

    field error() -> FieldResult<&str> {
        Err("Can't do it".to_owned())
    }
});

graphql_object!(<CtxT> Mutation: CtxT as "Mutation" |&self| {
    field print(value: String) -> FieldResult<String> {
        println!("Printing text according to mutation");
        println!("{}", value);
        Ok(value)
    }
});
<|endoftext|>


<commit_before>use std::iter::Iterator;

pub type FileNum = uint;

#[deriving(Show)]
pub enum UserReply
{
   TakeFile(FileNum),
   MoveToTrash,
   ShowDiff,
   ShowDiffWith(FileNum),
   ShowDiffBetween(FileNum, FileNum),
   Skip,
   Quit,
   Help
}

pub fn parse(input: &String) -> Option<UserReply>
{
   if input.is_empty() {
      return None;
   }

   let num_chars = input.len();
   let mut chars = input.chars()
                        .skip_while(|c| c.is_whitespace())
                        .map(|c| c.to_lowercase());

   match chars.next() {
      Some(c) => {
         match c {
            't' => {
               let uints = parse_uints(&chars.collect::<String>());
               match uints.len() {
                  1 => Some(TakeFile(uints[0])),
                  _ => None
               }
            }

            'd' => {
               let uints = parse_uints(&chars.collect::<String>());
               match uints.len() {
                  0 => Some(ShowDiff),
                  1 => Some(ShowDiffWith(uints[0])),
                  2 => Some(ShowDiffBetween(uints[0], uints[1])),
                  _ => None
               }
            }

            'm'      if num_chars == 1 => Some(MoveToTrash),
            's'      if num_chars == 1 => Some(Skip),
            'q'      if num_chars == 1 => Some(Quit),
            'h' |'?' if num_chars == 1 => Some(Help),

            _ => None,
         }
      }

      None => None,
   }
}

fn parse_uints(string: &String) -> Vec<uint>
{
   let mut uints  = Vec::new();
   let mut digits = String::new();

   for c in string.chars() {
      if c.is_digit() {
         digits.push(c);
      }
      else if ! digits.is_empty() {
         from_str::<uint>(digits.as_slice()).map(|u| uints.push(u));
         digits.clear();
         continue;
      }
   }

   if ! digits.is_empty() {
      from_str::<uint>(digits.as_slice()).map(|u| uints.push(u));
   }

   uints
}
<commit_msg>user_reply: use Parser in the 'parse' function<commit_after>use std::iter::Iterator;
use parser::Parser;

pub type FileNum = uint;

#[deriving(Show, PartialEq, Eq)]
pub enum UserReply
{
   TakeFile(FileNum),
   MoveToTrash,
   ShowDiff,
   ShowDiffWith(FileNum),
   ShowDiffBetween(FileNum, FileNum),
   Skip,
   Quit,
   Help
}

pub fn parse(input: &String) -> Option<UserReply>
{
   if input.is_empty() {
      return None;
   }

   let lowercase_input = input.chars()
                              .map(|c| c.to_lowercase())
                              .collect::<String>();

   let mut parser = Parser::new(lowercase_input.as_slice());
   parser.skip_whitespace();
   match parser.take_char() {
      Err(..) => None,

      Ok(c)   => {
         parser.skip_whitespace();
         let only_whitespace_left = parser.eof();
         let uints = take_uints(&mut parser);
         match c {
            't' => {
               match uints.len() {
                  1 => Some(TakeFile(uints[0])),
                  _ => None
               }
            }

            'd' => {
               match uints.len() {
                  0 => Some(ShowDiff),
                  1 => Some(ShowDiffWith(uints[0])),
                  2 => Some(ShowDiffBetween(uints[0], uints[1])),
                  _ => None
               }
            }

            'm'      if num_chars == 1 => Some(MoveToTrash),
            's'      if num_chars == 1 => Some(Skip),
            'q'      if num_chars == 1 => Some(Quit),
            'h' |'?' if num_chars == 1 => Some(Help),

            _ => None,
         }
      }

      None => None,
   }
}

fn parse_uints(string: &String) -> Vec<uint>
{
   let mut uints  = Vec::new();
   let mut digits = String::new();

   for c in string.chars() {
      if c.is_digit() {
         digits.push(c);
      }
      else if ! digits.is_empty() {
         from_str::<uint>(digits.as_slice()).map(|u| uints.push(u));
         digits.clear();
         continue;
      }
   }

   if ! digits.is_empty() {
      from_str::<uint>(digits.as_slice()).map(|u| uints.push(u));
   }

   uints
}
<|endoftext|>


<commit_before>//! Assorted functions shared by several assists.

use ra_syntax::{
    ast::{self, make, NameOwner},
    AstNode, T,
};

use hir::db::HirDatabase;

use rustc_hash::FxHashSet;

pub fn get_missing_impl_items(
    db: &impl HirDatabase,
    analyzer: &hir::SourceAnalyzer,
    impl_block: &ast::ImplBlock,
) -> Vec<hir::AssocItem> {
    // since the names are unique only to each associated type (fn/type/const),
    // create buckets of each already implemented type that we'll use in the
    // lookup later.
    let mut impl_fns = FxHashSet::default();
    let mut impl_type = FxHashSet::default();
    let mut impl_const = FxHashSet::default();

    if let Some(item_list) = impl_block.item_list() {
        for item in item_list.impl_items() {
            match item {
                ast::ImplItem::FnDef(f) => {
                    if let Some(n) = f.name() {
                        impl_fns.insert(n.syntax().to_string());
                    }
                }

                ast::ImplItem::TypeAliasDef(t) => {
                    if let Some(n) = t.name() {
                        impl_type.insert(n.syntax().to_string());
                    }
                }

                ast::ImplItem::ConstDef(c) => {
                    if let Some(n) = c.name() {
                        impl_const.insert(n.syntax().to_string());
                    }
                }
            }
        }
    }

    resolve_target_trait(db, analyzer, impl_block).map_or(vec![], |target_trait| {
        target_trait
            .items(db)
            .iter()
            .filter(|i| match i {
                hir::AssocItem::Function(f) => !impl_fns.contains(&f.name(db).to_string()),
                hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(db).to_string()),
                hir::AssocItem::Const(c) => {
                    c.name(db).map(|n| !impl_const.contains(&n.to_string())).unwrap_or_default()
                }
            })
            .map(|i| i.clone())
            .collect()
    })
}

fn resolve_target_trait(
    db: &impl HirDatabase,
    analyzer: &hir::SourceAnalyzer,
    impl_block: &ast::ImplBlock,
) -> Option<hir::Trait> {
    let ast_path = impl_block
        .target_trait()
        .map(|it| it.syntax().clone())
        .and_then(ast::PathType::cast)?
        .path()?;

    match analyzer.resolve_path(db, &ast_path) {
        Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def),
        _ => None,
    }
}

pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr {
    if let Some(expr) = invert_special_case(&expr) {
        return expr;
    }
    make::expr_prefix(T![!], expr)
}

fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
    match expr {
        ast::Expr::BinExpr(bin) => match bin.op_kind()? {
            ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()),
            ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()),
            _ => None,
        },
        ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(),
        // FIXME:
        // ast::Expr::Literal(true | false )
        _ => None,
    }
}
<commit_msg>Adjusted the hashset buckets to lump functions/consts together as their names must be unique.<commit_after>//! Assorted functions shared by several assists.

use ra_syntax::{
    ast::{self, make, NameOwner},
    AstNode, T,
};

use hir::db::HirDatabase;

use rustc_hash::FxHashSet;

/// Generate a collection of associated items that are missing from a
/// `impl Trait for` block.
pub fn get_missing_impl_items(
    db: &impl HirDatabase,
    analyzer: &hir::SourceAnalyzer,
    impl_block: &ast::ImplBlock,
) -> Vec<hir::AssocItem> {

    // Names must be unique between constants and functions. However, type aliases
    // may share the same name as a function or constant.
    let mut impl_fns_consts = FxHashSet::default();
    let mut impl_type = FxHashSet::default();

    if let Some(item_list) = impl_block.item_list() {
        for item in item_list.impl_items() {
            match item {
                ast::ImplItem::FnDef(f) => {
                    if let Some(n) = f.name() {
                        impl_fns_consts.insert(n.syntax().to_string());
                    }
                }

                ast::ImplItem::TypeAliasDef(t) => {
                    if let Some(n) = t.name() {
                        impl_type.insert(n.syntax().to_string());
                    }
                }

                ast::ImplItem::ConstDef(c) => {
                    if let Some(n) = c.name() {
                        impl_fns_consts.insert(n.syntax().to_string());
                    }
                }
            }
        }
    }

    resolve_target_trait(db, analyzer, impl_block).map_or(vec![], |target_trait| {
        target_trait
            .items(db)
            .iter()
            .filter(|i| match i {
                hir::AssocItem::Function(f) => !impl_fns_consts.contains(&f.name(db).to_string()),
                hir::AssocItem::TypeAlias(t) => !impl_type.contains(&t.name(db).to_string()),
                hir::AssocItem::Const(c) => {
                    c.name(db).map(|n| !impl_fns_consts.contains(&n.to_string())).unwrap_or_default()
                }
            })
            .map(|i| i.clone())
            .collect()
    })
}

fn resolve_target_trait(
    db: &impl HirDatabase,
    analyzer: &hir::SourceAnalyzer,
    impl_block: &ast::ImplBlock,
) -> Option<hir::Trait> {
    let ast_path = impl_block
        .target_trait()
        .map(|it| it.syntax().clone())
        .and_then(ast::PathType::cast)?
        .path()?;

    match analyzer.resolve_path(db, &ast_path) {
        Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def),
        _ => None,
    }
}

pub(crate) fn invert_boolean_expression(expr: ast::Expr) -> ast::Expr {
    if let Some(expr) = invert_special_case(&expr) {
        return expr;
    }
    make::expr_prefix(T![!], expr)
}

fn invert_special_case(expr: &ast::Expr) -> Option<ast::Expr> {
    match expr {
        ast::Expr::BinExpr(bin) => match bin.op_kind()? {
            ast::BinOp::NegatedEqualityTest => bin.replace_op(T![==]).map(|it| it.into()),
            ast::BinOp::EqualityTest => bin.replace_op(T![!=]).map(|it| it.into()),
            _ => None,
        },
        ast::Expr::PrefixExpr(pe) if pe.op_kind()? == ast::PrefixOp::Not => pe.expr(),
        // FIXME:
        // ast::Expr::Literal(true | false )
        _ => None,
    }
}
<|endoftext|>