<commit_before>use std::collections::{HashMap};

use num::bigint::{BigInt};

use opcode::{OpCode, BooleanOrInt};
use value::{Value};

pub struct Machine {
    stack: Vec<Value>,
    memo: HashMap<usize, Value>,
    marker: Option<usize>,
}

impl Machine {
    fn new() -> Self {
        Machine {
            stack: Vec::new(),
            memo: HashMap::new(),
            marker: None,
        }
    }

    fn split_off(&mut self) -> Vec<Value> {
        let at = match self.marker {
            None => panic!("Empty marker"),
            Some(marker) => marker,
        };

        if at > self.stack.len() {
            panic!("Stack too small");
        }

        self.stack.split_off(at)
    }

    fn pop(&mut self) -> Value {
        match self.stack.pop() {
            None => panic!("Empty stack"),
            Some(value) => value,
        }
    }

    fn handle_get(&mut self, i: usize) {
        let value = match self.memo.get(&i) {
            None => panic!("Empty memo"),
            Some(ref v) => (*v).clone(),
        };
        self.stack.push(value);
    }

    fn handle_put(&mut self, i: usize) {
        let value = match self.stack.last() {
            None => panic!("Empty stack"),
            Some(ref v) => (*v).clone(),
        };
        self.memo.insert(i, value);
    }

    fn execute(&mut self, opcode: OpCode) {
        match opcode {
            OpCode::Proto(_) => (),
            OpCode::Stop => (),  // TODO: !!!

            OpCode::Int(value) => {
                self.stack.push(match value {
                    BooleanOrInt::Boolean(v) => Value::Bool(v),
                    BooleanOrInt::Int(v) => Value::Int(BigInt::from(v)),
                })
            },
            OpCode::BinInt(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::BinInt1(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::BinInt2(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::Long(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::Long1(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::Long4(i) => self.stack.push(Value::Int(BigInt::from(i))),

            OpCode::String(s) => self.stack.push(Value::String(s)),
            OpCode::BinString(s) => self.stack.push(Value::String(s)),
            OpCode::ShortBinString(s) => self.stack.push(Value::String(s)),

            OpCode::None => self.stack.push(Value::None),

            OpCode::NewTrue => self.stack.push(Value::Bool(true)),
            OpCode::NewFalse => self.stack.push(Value::Bool(false)),

            OpCode::Unicode(s) => self.stack.push(Value::Unicode(s)),
            OpCode::BinUnicode(s) => self.stack.push(Value::Unicode(s)),

            OpCode::Float(i) => self.stack.push(Value::Float(i)),
            OpCode::BinFloat(i) => self.stack.push(Value::Float(i)),

            OpCode::EmptyList => self.stack.push(Value::List(Vec::new())),
            OpCode::Append => {
                let v = self.pop();
                match self.stack.last_mut() {
                    None => panic!("Empty stack"),
                    Some(&mut Value::List(ref mut list)) => list.push(v),
                    _ => panic!("Invalid value on stack"),
                }
            },
            OpCode::Appends => {
                let values = self.split_off();
                match self.stack.last_mut() {
                    None => panic!("Empty stack"),
                    Some(&mut Value::List(ref mut list)) => {
                        list.extend(values);
                    },
                    _ => panic!("Invalid value on stack"),
                }
            },
            OpCode::List => {
                let values = self.split_off();
                self.stack.push(Value::List(values));
            },

            OpCode::EmptyTuple => self.stack.push(Value::Tuple(Vec::new())),
            OpCode::Tuple => {
                let values = self.split_off();
                self.stack.push(Value::Tuple(values));
            },
            OpCode::Tuple1 => {
                let v1 = self.pop();
                self.stack.push(Value::Tuple(vec![v1]))
            },
            OpCode::Tuple2 => {
                let v1 = self.pop();
                let v2 = self.pop();
                self.stack.push(Value::Tuple(vec![v1, v2]))
            },
            OpCode::Tuple3 => {
                let v1 = self.pop();
                let v2 = self.pop();
                let v3 = self.pop();
                self.stack.push(Value::Tuple(vec![v1, v2, v3]))
            }

            OpCode::EmptyDict => self.stack.push(Value::Dict(Vec::new())),
            OpCode::Dict => {
                let mut values = self.split_off();
                let mut dict = Vec::new();

                for i in 0 .. values.len() / 2 { // TODO: Check panic
                    let key = values.remove(2 * i);
                    let value = values.remove(2 * i + 1);
                    dict.push((key, value));
                }
                self.stack.push(Value::Dict(dict));
            },
            OpCode::SetItem => {
                let value = self.pop();
                let key = self.pop();
                match self.stack.last_mut() {
                    None => panic!("Empty stack"),
                    Some(&mut Value::Dict(ref mut dict)) => dict.push((key, value)),
                    _ => panic!("Invalid value on stack"),
                }
            },
            OpCode::SetItems => {
                let mut values = self.split_off();

                match self.stack.last_mut() {
                    None => panic!("Empty stack"),
                    Some(&mut Value::Dict(ref mut dict)) => {
                        for i in 0 .. values.len() / 2 { // TODO: Check panic
                            let key = values.remove(2 * i);
                            let value = values.remove(2 * i + 1);
                            dict.push((key, value));
                        }
                    },
                    _ => panic!("Invalid value on stack"),
                }
            },

            OpCode::Pop => {
                self.pop();
            },
            OpCode::Dup => {
                let value = match self.stack.last() {
                    None => panic!("Empty stack"),
                    Some(ref v) => (*v).clone(),
                };
                self.stack.push(value)
            },
            OpCode::Mark => {
                self.marker = Some(self.stack.len())
            },
            OpCode::PopMark => {
                self.split_off();
            },

            OpCode::Get(i) => self.handle_get(i),
            OpCode::BinGet(i) => self.handle_get(i),
            OpCode::LongBinGet(i) => self.handle_get(i),
            OpCode::Put(i) => self.handle_put(i),
            OpCode::BinPut(i) => self.handle_put(i),
            OpCode::LongBinPut(i) => self.handle_put(i),

            _ => panic!("Not implemented")
        }
    }
}<commit_msg>Add pickle machine errrors<commit_after>use std::collections::{HashMap};

use num::bigint::{BigInt};

use opcode::{OpCode, BooleanOrInt};
use value::{Value};

quick_error! {
    #[derive(Debug)]
    pub enum Error {
        EmptyMarker
        StackTooSmall
        EmptyStack
        InvalidValueOnStack
        InvalidMemoValue
        NotImplemented
    }
}

pub struct Machine {
    stack: Vec<Value>,
    memo: HashMap<usize, Value>,
    marker: Option<usize>,
}

impl Machine {
    fn new() -> Self {
        Machine {
            stack: Vec::new(),
            memo: HashMap::new(),
            marker: None,
        }
    }

    fn split_off(&mut self) -> Result<Vec<Value>, Error> {
        let at = match self.marker {
            None => return Err(Error::EmptyMarker),
            Some(marker) => marker,
        };

        if at > self.stack.len() {
            return Err(Error::StackTooSmall);
        }

        Ok(self.stack.split_off(at))
    }

    fn pop(&mut self) -> Result<Value, Error> {
        match self.stack.pop() {
            None => return Err(Error::EmptyStack),
            Some(value) => Ok(value),
        }
    }

    fn handle_get(&mut self, i: usize) -> Result<(), Error> {
        let value = match self.memo.get(&i) {
            None => return Err(Error::InvalidMemoValue),
            Some(ref v) => (*v).clone(),
        };
        self.stack.push(value);
        Ok(())
    }

    fn handle_put(&mut self, i: usize) -> Result<(), Error> {
        let value = match self.stack.last() {
            None => return Err(Error::EmptyStack),
            Some(ref v) => (*v).clone(),
        };
        self.memo.insert(i, value);
        Ok(())
    }

    pub fn execute(&mut self, opcode: OpCode) -> Result<(), Error> {
        match opcode {
            OpCode::Proto(_) => (),
            OpCode::Stop => (),  // TODO: !!!

            OpCode::Int(value) => {
                self.stack.push(match value {
                    BooleanOrInt::Boolean(v) => Value::Bool(v),
                    BooleanOrInt::Int(v) => Value::Int(BigInt::from(v)),
                })
            },
            OpCode::BinInt(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::BinInt1(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::BinInt2(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::Long(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::Long1(i) => self.stack.push(Value::Int(BigInt::from(i))),
            OpCode::Long4(i) => self.stack.push(Value::Int(BigInt::from(i))),

            OpCode::String(s) => self.stack.push(Value::String(s)),
            OpCode::BinString(s) => self.stack.push(Value::String(s)),
            OpCode::ShortBinString(s) => self.stack.push(Value::String(s)),

            OpCode::None => self.stack.push(Value::None),

            OpCode::NewTrue => self.stack.push(Value::Bool(true)),
            OpCode::NewFalse => self.stack.push(Value::Bool(false)),

            OpCode::Unicode(s) => self.stack.push(Value::Unicode(s)),
            OpCode::BinUnicode(s) => self.stack.push(Value::Unicode(s)),

            OpCode::Float(i) => self.stack.push(Value::Float(i)),
            OpCode::BinFloat(i) => self.stack.push(Value::Float(i)),

            OpCode::EmptyList => self.stack.push(Value::List(Vec::new())),
            OpCode::Append => {
                let v = try!(self.pop());
                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::List(ref mut list)) => list.push(v),
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },
            OpCode::Appends => {
                let values = try!(self.split_off());
                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::List(ref mut list)) => {
                        list.extend(values);
                    },
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },
            OpCode::List => {
                let values = try!(self.split_off());
                self.stack.push(Value::List(values));
            },

            OpCode::EmptyTuple => self.stack.push(Value::Tuple(Vec::new())),
            OpCode::Tuple => {
                let values = try!(self.split_off());
                self.stack.push(Value::Tuple(values));
            },
            OpCode::Tuple1 => {
                let v1 = try!(self.pop());
                self.stack.push(Value::Tuple(vec![v1]))
            },
            OpCode::Tuple2 => {
                let v1 = try!(self.pop());
                let v2 = try!(self.pop());
                self.stack.push(Value::Tuple(vec![v1, v2]))
            },
            OpCode::Tuple3 => {
                let v1 = try!(self.pop());
                let v2 = try!(self.pop());
                let v3 = try!(self.pop());
                self.stack.push(Value::Tuple(vec![v1, v2, v3]))
            }

            OpCode::EmptyDict => self.stack.push(Value::Dict(Vec::new())),
            OpCode::Dict => {
                let mut values = try!(self.split_off());
                let mut dict = Vec::new();

                for i in 0 .. values.len() / 2 { // TODO: Check panic
                    let key = values.remove(2 * i);
                    let value = values.remove(2 * i + 1);
                    dict.push((key, value));
                }
                self.stack.push(Value::Dict(dict));
            },
            OpCode::SetItem => {
                let value = try!(self.pop());
                let key = try!(self.pop());
                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::Dict(ref mut dict)) => dict.push((key, value)),
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },
            OpCode::SetItems => {
                let mut values = try!(self.split_off());

                match self.stack.last_mut() {
                    None => return Err(Error::EmptyStack),
                    Some(&mut Value::Dict(ref mut dict)) => {
                        for i in 0 .. values.len() / 2 { // TODO: Check panic
                            let key = values.remove(2 * i);
                            let value = values.remove(2 * i + 1);
                            dict.push((key, value));
                        }
                    },
                    _ => return Err(Error::InvalidValueOnStack),
                }
            },

            OpCode::Pop => {
                try!(self.pop());
            },
            OpCode::Dup => {
                let value = match self.stack.last() {
                    None => return Err(Error::EmptyStack),
                    Some(ref v) => (*v).clone(),
                };
                self.stack.push(value)
            },
            OpCode::Mark => {
                self.marker = Some(self.stack.len())
            },
            OpCode::PopMark => {
                try!(self.split_off());
            },

            OpCode::Get(i) => try!(self.handle_get(i)),
            OpCode::BinGet(i) => try!(self.handle_get(i)),
            OpCode::LongBinGet(i) => try!(self.handle_get(i)),
            OpCode::Put(i) => try!(self.handle_put(i)),
            OpCode::BinPut(i) => try!(self.handle_put(i)),
            OpCode::LongBinPut(i) => try!(self.handle_put(i)),

            _ => return Err(Error::NotImplemented)
        }
        Ok(())
    }
}<|endoftext|>


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

//!
//! These functions deal with establishing how much of a particular stream (or string) matches a particular pattern. The
//! most important function is `matches`, which takes a stream and a pattern and returns the number of characters from the
//! stream that matches the pattern. Use it like this:
//!
//! ```
//! # use ndfa::*;
//! # assert!(matches("abcabc", "abc".repeat_forever(1)) == Some(6));
//! # assert!(matches("abcabcabc", "abc".repeat_forever(1)).is_some());
//! # assert!(matches("abc", "abc").is_some());
//! # assert!(matches("def", "abc".repeat_forever(1)).is_none());
//! if matches("abcabc", "abc".repeat_forever(1)) == Some(6) { /* ... */ }
//! ```
//!
//! To determine if a string exactly matches a pattern, compare to the string length like this:
//!
//! ```
//! # use ndfa::*;
//! let input_string = "abcabc";
//! let pattern      = "abc".repeat_forever(1);
//!
//! if matches(input_string, pattern) == Some(input_string.len()) { }
//! # assert!(matches(input_string, "abc".repeat_forever(1)) == Some(input_string.len()));
//! ```
//!

use super::symbol_range_dfa::*;
use super::symbol_reader::*;
use super::pattern_matcher::*;
use super::prepare::*;

///
/// Runs a DFA against a symbol stream and returns its final state
///
/// This takes a DFA match action as an initial state (such as that returned by `SymbolRangeDfa::start()`) and runs it until it accepts
/// or rejects the pattern passed to it.
///
/// This call is useful for cases where there is more than one output symbol (as the output symbol that was matched can be retrieved)
/// or for working with pattern matchers other than the default one.
///
/// ```
/// # use ndfa::*;
/// let input_string = "abcabc";
/// let pattern      = "abc".repeat_forever(1);
/// let matcher      = pattern.prepare_to_match();
///
/// let match_result = match_pattern(matcher.start(), &mut input_string.read_symbols()); // == Accept(6, &true)
/// # assert!(match match_result { Accept(count, val) => count == 6 && val == &true, _ => false });
/// ```
///
pub fn match_pattern<'a, InputSymbol: Ord, OutputSymbol, State>(start_state: MatchAction<'a, OutputSymbol, State>, symbol_reader: &mut SymbolReader<InputSymbol>) -> MatchAction<'a, OutputSymbol, State>
where State: MatchingState<'a, InputSymbol, OutputSymbol> {
    let mut current_state = start_state;

    while let More(this_state) = current_state {
        let next_state =
            if let Some(next_char) = symbol_reader.next_symbol() {
                this_state.next(next_char)
            } else {
                this_state.finish()
            };

        current_state = next_state;
    }

    current_state
}

///
/// Runs a pattern matcher against a stream, and returns the number of characters matching if it accepted the stream
///
fn matches_symbol_range<InputSymbol: Ord, OutputSymbol: 'static>(dfa: &SymbolRangeDfa<InputSymbol, OutputSymbol>, symbol_reader: &mut SymbolReader<InputSymbol>) -> Option<usize> {
    // Run the DFA
    let final_state = match_pattern(dfa.start(), symbol_reader);

    if let Accept(count, _) = final_state {
        Some(count)
    } else {
        None
    }
}

///
/// Matches a source stream against a pattern
///
/// This is the basic pattern matcher. It matches against the left-hand side of the source, and if there is a string of any
/// length that can match the passed in pattern it will return the length of that string. Pattern matchers should be greedy,
/// so this will return the length of the longest string that can match the given pattern.
///
/// ```
/// # use ndfa::*;
/// matches("abc", "abc");                      // Returns Some(3)
/// matches("abcabc", "abc");                   // Also returns Some(3) as 'abc' matches the pattern
/// matches("abcabc", "abc".repeat_forever(0)); // Returns Some(6)
/// matches("ab", "abc");                       // Doesn't match: returns None
/// ```
///
/// It's worth noting that this is not just limited to strings and characters. For example, vectors will work too:
///
/// ```
/// # use ndfa::*;
/// matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)); // == Some(6)
/// # assert!(matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)) == Some(6));
/// ```
///
pub fn matches<'a, Symbol, OutputSymbol, Prepare, Reader, Source>(source: Source, pattern: Prepare) -> Option<usize>
where   Prepare: PrepareToMatch<SymbolRangeDfa<Symbol, OutputSymbol>>
,       Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let matcher    = pattern.prepare_to_match();
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

///
/// Matches a source stream against a prepared pattern
///
/// If it's necessary to match a pattern against a lot of different things, then preparing it by calling `pattern.prepare_to_match()`
/// will increase the performance of the matcher for every match after the first one. This call is otherwise identical to `matches`.
///
/// ```
/// # use ndfa::*;
/// let prepared = "abc".repeat_forever(1).prepare_to_match();
///
/// matches_prepared("abcabc", &prepared);      // == Some(6)
/// matches_prepared("abc", &prepared);         // == Some(3)
/// matches_prepared("abcabcabc", &prepared);   // == Some(9)
/// ```
///
pub fn matches_prepared<'a, Symbol, OutputSymbol, Reader, Source>(source: Source, matcher: &SymbolRangeDfa<Symbol, OutputSymbol>) -> Option<usize>
where   Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

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

    #[test]
    fn match_multiple_repeats() {
        assert!(matches("abcabc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_prepared() {
        let prepared = "abc".repeat_forever(1).prepare_to_match();

        assert!(matches_prepared("abcabc", &prepared) == Some(6));
        assert!(matches_prepared("abc", &prepared) == Some(3));
        assert!(matches_prepared("abcabcabc", &prepared) == Some(9));
    }

    #[test]
    fn match_single_repeat() {
        assert!(matches("abc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_with_zero_or_more() {
        assert!(matches("abc", "abc".repeat_forever(0)).is_some());
        assert!(matches("abcabc", "abc".repeat_forever(0)).is_some());
        assert!(matches("abcabcabc", "abc".repeat_forever(0)).is_some());
    }

    #[test]
    fn match_with_zero_or_more_following() {
        assert!(matches("abc", "abc".repeat_forever(0).append("def")).is_none());
        assert!(matches("abcabc", "abc".repeat_forever(0).append("def")).is_none());

        assert!(matches("abcdef", "abc".repeat_forever(0).append("def")).is_some());
        assert!(matches("abcabcdef", "abc".repeat_forever(0).append("def")).is_some());
    }

    #[test]
    fn match_limited_range() {
        assert!(matches("abc", "abc".repeat(2..4)).is_none());
        assert!(matches("abcabc", "abc".repeat(2..4)).is_some());
        assert!(matches("abcabcabc", "abc".repeat(2..4)) == Some(3*3));
        assert!(matches("abcabcabcabc", "abc".repeat(2..4)) == Some(3*3));
    }

    #[test]
    fn match_zero_repeats() {
        assert!(matches("", "abc".repeat_forever(0)).is_some());
    }
}
<commit_msg>This example makes more sense if it calls is_some()<commit_after>//
//   Copyright 2016 Andrew Hunter
//
//   Licensed under the Apache License, Version 2.0 (the "License");
//   you may not use this file except in compliance with the License.
//   You may obtain a copy of the License at
//
//       http://www.apache.org/licenses/LICENSE-2.0
//
//   Unless required by applicable law or agreed to in writing, software
//   distributed under the License is distributed on an "AS IS" BASIS,
//   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//   See the License for the specific language governing permissions and
//   limitations under the License.
//

//!
//! These functions deal with establishing how much of a particular stream (or string) matches a particular pattern. The
//! most important function is `matches`, which takes a stream and a pattern and returns the number of characters from the
//! stream that matches the pattern. Use it like this:
//!
//! ```
//! # use ndfa::*;
//! # assert!(matches("abcabc", "abc".repeat_forever(1)) == Some(6));
//! # assert!(matches("abcabcabc", "abc".repeat_forever(1)).is_some());
//! # assert!(matches("abc", "abc").is_some());
//! # assert!(matches("def", "abc".repeat_forever(1)).is_none());
//! if matches("abcabc", "abc".repeat_forever(1)).is_some() { /* ... */ }
//! ```
//!
//! To determine if a string exactly matches a pattern, compare to the string length like this:
//!
//! ```
//! # use ndfa::*;
//! let input_string = "abcabc";
//! let pattern      = "abc".repeat_forever(1);
//!
//! if matches(input_string, pattern) == Some(input_string.len()) { }
//! # assert!(matches(input_string, "abc".repeat_forever(1)) == Some(input_string.len()));
//! ```
//!

use super::symbol_range_dfa::*;
use super::symbol_reader::*;
use super::pattern_matcher::*;
use super::prepare::*;

///
/// Runs a DFA against a symbol stream and returns its final state
///
/// This takes a DFA match action as an initial state (such as that returned by `SymbolRangeDfa::start()`) and runs it until it accepts
/// or rejects the pattern passed to it.
///
/// This call is useful for cases where there is more than one output symbol (as the output symbol that was matched can be retrieved)
/// or for working with pattern matchers other than the default one.
///
/// ```
/// # use ndfa::*;
/// let input_string = "abcabc";
/// let pattern      = "abc".repeat_forever(1);
/// let matcher      = pattern.prepare_to_match();
///
/// let match_result = match_pattern(matcher.start(), &mut input_string.read_symbols()); // == Accept(6, &true)
/// # assert!(match match_result { Accept(count, val) => count == 6 && val == &true, _ => false });
/// ```
///
pub fn match_pattern<'a, InputSymbol: Ord, OutputSymbol, State>(start_state: MatchAction<'a, OutputSymbol, State>, symbol_reader: &mut SymbolReader<InputSymbol>) -> MatchAction<'a, OutputSymbol, State>
where State: MatchingState<'a, InputSymbol, OutputSymbol> {
    let mut current_state = start_state;

    while let More(this_state) = current_state {
        let next_state =
            if let Some(next_char) = symbol_reader.next_symbol() {
                this_state.next(next_char)
            } else {
                this_state.finish()
            };

        current_state = next_state;
    }

    current_state
}

///
/// Runs a pattern matcher against a stream, and returns the number of characters matching if it accepted the stream
///
fn matches_symbol_range<InputSymbol: Ord, OutputSymbol: 'static>(dfa: &SymbolRangeDfa<InputSymbol, OutputSymbol>, symbol_reader: &mut SymbolReader<InputSymbol>) -> Option<usize> {
    // Run the DFA
    let final_state = match_pattern(dfa.start(), symbol_reader);

    if let Accept(count, _) = final_state {
        Some(count)
    } else {
        None
    }
}

///
/// Matches a source stream against a pattern
///
/// This is the basic pattern matcher. It matches against the left-hand side of the source, and if there is a string of any
/// length that can match the passed in pattern it will return the length of that string. Pattern matchers should be greedy,
/// so this will return the length of the longest string that can match the given pattern.
///
/// ```
/// # use ndfa::*;
/// matches("abc", "abc");                      // Returns Some(3)
/// matches("abcabc", "abc");                   // Also returns Some(3) as 'abc' matches the pattern
/// matches("abcabc", "abc".repeat_forever(0)); // Returns Some(6)
/// matches("ab", "abc");                       // Doesn't match: returns None
/// ```
///
/// It's worth noting that this is not just limited to strings and characters. For example, vectors will work too:
///
/// ```
/// # use ndfa::*;
/// matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)); // == Some(6)
/// # assert!(matches(&vec![1,2,3,1,2,3], vec![1,2,3].repeat_forever(1)) == Some(6));
/// ```
///
pub fn matches<'a, Symbol, OutputSymbol, Prepare, Reader, Source>(source: Source, pattern: Prepare) -> Option<usize>
where   Prepare: PrepareToMatch<SymbolRangeDfa<Symbol, OutputSymbol>>
,       Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let matcher    = pattern.prepare_to_match();
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

///
/// Matches a source stream against a prepared pattern
///
/// If it's necessary to match a pattern against a lot of different things, then preparing it by calling `pattern.prepare_to_match()`
/// will increase the performance of the matcher for every match after the first one. This call is otherwise identical to `matches`.
///
/// ```
/// # use ndfa::*;
/// let prepared = "abc".repeat_forever(1).prepare_to_match();
///
/// matches_prepared("abcabc", &prepared);      // == Some(6)
/// matches_prepared("abc", &prepared);         // == Some(3)
/// matches_prepared("abcabcabc", &prepared);   // == Some(9)
/// ```
///
pub fn matches_prepared<'a, Symbol, OutputSymbol, Reader, Source>(source: Source, matcher: &SymbolRangeDfa<Symbol, OutputSymbol>) -> Option<usize>
where   Reader: SymbolReader<Symbol>+'a
,       Source: SymbolSource<'a, Symbol, SymbolReader=Reader>
,       Symbol: Ord
,       OutputSymbol: 'static {
    let mut reader = source.read_symbols();

    matches_symbol_range(&matcher, &mut reader)
}

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

    #[test]
    fn match_multiple_repeats() {
        assert!(matches("abcabc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_prepared() {
        let prepared = "abc".repeat_forever(1).prepare_to_match();

        assert!(matches_prepared("abcabc", &prepared) == Some(6));
        assert!(matches_prepared("abc", &prepared) == Some(3));
        assert!(matches_prepared("abcabcabc", &prepared) == Some(9));
    }

    #[test]
    fn match_single_repeat() {
        assert!(matches("abc", "abc".repeat_forever(1)).is_some());
    }

    #[test]
    fn match_with_zero_or_more() {
        assert!(matches("abc", "abc".repeat_forever(0)).is_some());
        assert!(matches("abcabc", "abc".repeat_forever(0)).is_some());
        assert!(matches("abcabcabc", "abc".repeat_forever(0)).is_some());
    }

    #[test]
    fn match_with_zero_or_more_following() {
        assert!(matches("abc", "abc".repeat_forever(0).append("def")).is_none());
        assert!(matches("abcabc", "abc".repeat_forever(0).append("def")).is_none());

        assert!(matches("abcdef", "abc".repeat_forever(0).append("def")).is_some());
        assert!(matches("abcabcdef", "abc".repeat_forever(0).append("def")).is_some());
    }

    #[test]
    fn match_limited_range() {
        assert!(matches("abc", "abc".repeat(2..4)).is_none());
        assert!(matches("abcabc", "abc".repeat(2..4)).is_some());
        assert!(matches("abcabcabc", "abc".repeat(2..4)) == Some(3*3));
        assert!(matches("abcabcabcabc", "abc".repeat(2..4)) == Some(3*3));
    }

    #[test]
    fn match_zero_repeats() {
        assert!(matches("", "abc".repeat_forever(0)).is_some());
    }
}
<|endoftext|>


<commit_before>#[derive(PartialEq, Debug)]
enum MqttType {
    Connect,
}

fn message_type(bytes: &[u8]) -> MqttType {
    MqttType::Connect
}

#[test]
fn connect_type() {
    let mqtt_connect = &[
        0x10u8, 0x2a, // fixed header
        0x00, 0x06, 'M' as u8, 'Q' as u8, 'I' as u8, 's' as u8, 'd' as u8, 'p' as u8,
        0x03, // protocol version
        0xcc, // connection flags 1100111x user, pw, !wr, w(01), w, !c, x
        0x00, 0x0a, // keepalive of 100
        0x00, 0x03, 'c' as u8, 'i' as u8, 'd' as u8, // client ID
        0x00, 0x04, 'w' as u8, 'i' as u8, 'l' as u8, 'l' as u8, // will topic
        0x00, 0x04, 'w' as u8, 'm' as u8, 's' as u8, 'g' as u8, // will msg
        0x00, 0x07, 'g' as u8, 'l' as u8, 'i' as u8, 'f' as u8, 't' as u8, 'e' as u8, 'l' as u8, // username
        0x00, 0x02, 'p' as u8, 'w' as u8, // password
        ][0..];
    assert_eq!(message_type(mqtt_connect), MqttType::Connect);
}
<commit_msg>Failing UT for ping type bytes<commit_after>#[derive(PartialEq, Debug)]
enum MqttType {
    Connect,
    Ping,
}

fn message_type(bytes: &[u8]) -> MqttType {
    MqttType::Connect
}

#[test]
fn connect_type() {
    let connect_bytes = &[
        0x10u8, 0x2a, // fixed header
        0x00, 0x06, 'M' as u8, 'Q' as u8, 'I' as u8, 's' as u8, 'd' as u8, 'p' as u8,
        0x03, // protocol version
        0xcc, // connection flags 1100111x user, pw, !wr, w(01), w, !c, x
        0x00, 0x0a, // keepalive of 100
        0x00, 0x03, 'c' as u8, 'i' as u8, 'd' as u8, // client ID
        0x00, 0x04, 'w' as u8, 'i' as u8, 'l' as u8, 'l' as u8, // will topic
        0x00, 0x04, 'w' as u8, 'm' as u8, 's' as u8, 'g' as u8, // will msg
        0x00, 0x07, 'g' as u8, 'l' as u8, 'i' as u8, 'f' as u8, 't' as u8, 'e' as u8, 'l' as u8, // username
        0x00, 0x02, 'p' as u8, 'w' as u8, // password
        ][0..];
    assert_eq!(message_type(connect_bytes), MqttType::Connect);
}

#[test]
fn ping_type() {
    let ping_bytes = &[0xc0u8, 0][0..];
    assert_eq!(message_type(ping_bytes), MqttType::Ping);
}
<|endoftext|>


<commit_before>use std::vec;
use std::iter::FromIterator;
use document::dom4;

use super::EvaluationContext;
use self::Node::*;
use std::slice::Iter;

macro_rules! unpack(
    ($enum_name:ident, $name:ident, $wrapper:ident, dom4::$inner:ident) => (
        impl<'d> $enum_name<'d> {
            pub fn $name(self) -> Option<dom4::$inner<'d>> {
                match self {
                    $wrapper(n) => Some(n),
                    _ => None,
                }
            }
        }
    )
);

macro_rules! conversion_trait(
    ($tr_name:ident, $method:ident, $res_type:ident,
        { $(dom4::$leaf_type:ident => $variant:ident),* }
    ) => (
        pub trait $tr_name<'d> {
            fn $method(self) -> $res_type<'d>;
        }

        impl<'d> $tr_name<'d> for $res_type<'d> {
            fn $method(self) -> $res_type<'d> {
                self
            }
        }

        $(impl<'d> $tr_name<'d> for dom4::$leaf_type<'d> {
            fn $method(self) -> $res_type<'d> {
                $variant(self)
            }
        })*
    )
);

#[derive(Clone,PartialEq,Debug,Copy)]
pub enum Node<'d> {
    RootNode(dom4::Root<'d>),
    ElementNode(dom4::Element<'d>),
    AttributeNode(dom4::Attribute<'d>),
    TextNode(dom4::Text<'d>),
    CommentNode(dom4::Comment<'d>),
    ProcessingInstructionNode(dom4::ProcessingInstruction<'d>),
}

unpack!(Node, root, RootNode, dom4::Root);
unpack!(Node, element, ElementNode, dom4::Element);
unpack!(Node, attribute, AttributeNode, dom4::Attribute);
unpack!(Node, text, TextNode, dom4::Text);
unpack!(Node, comment, CommentNode, dom4::Comment);
unpack!(Node, processing_instruction, ProcessingInstructionNode, dom4::ProcessingInstruction);

impl<'d> Node<'d> {
    pub fn document(&self) -> &'d dom4::Document<'d> {
        match self {
            &RootNode(n)                  => n.document(),
            &ElementNode(n)               => n.document(),
            &AttributeNode(n)             => n.document(),
            &TextNode(n)                  => n.document(),
            &CommentNode(n)               => n.document(),
            &ProcessingInstructionNode(n) => n.document(),
        }
    }

    pub fn parent(&self) -> Option<Node<'d>> {
        match self {
            &RootNode(_)                  => None,
            &ElementNode(n)               => n.parent().map(|n| n.to_node()),
            &AttributeNode(n)             => n.parent().map(|n| n.to_node()),
            &TextNode(n)                  => n.parent().map(|n| n.to_node()),
            &CommentNode(n)               => n.parent().map(|n| n.to_node()),
            &ProcessingInstructionNode(n) => n.parent().map(|n| n.to_node()),
        }
    }

    pub fn children(&self) -> Vec<Node<'d>> {
        match self {
            &RootNode(n)                  => n.children().iter().map(|n| n.to_node()).collect(),
            &ElementNode(n)               => n.children().iter().map(|n| n.to_node()).collect(),
            &AttributeNode(_)             => Vec::new(),
            &TextNode(_)                  => Vec::new(),
            &CommentNode(_)               => Vec::new(),
            &ProcessingInstructionNode(_) => Vec::new(),
        }
    }

    pub fn preceding_siblings(&self) -> Vec<Node<'d>> {
        match self {
            &RootNode(_)                  => Vec::new(),
            &ElementNode(n)               => n.preceding_siblings().iter().rev().map(|n| n.to_node()).collect(),
            &AttributeNode(_)             => Vec::new(),
            &TextNode(n)                  => n.preceding_siblings().iter().rev().map(|n| n.to_node()).collect(),
            &CommentNode(n)               => n.preceding_siblings().iter().rev().map(|n| n.to_node()).collect(),
            &ProcessingInstructionNode(n) => n.preceding_siblings().iter().rev().map(|n| n.to_node()).collect(),
        }
    }

    pub fn following_siblings(&self) -> Vec<Node<'d>> {
        match self {
            &RootNode(_)                  => Vec::new(),
            &ElementNode(n)               => n.following_siblings().iter().map(|n| n.to_node()).collect(),
            &AttributeNode(_)             => Vec::new(),
            &TextNode(n)                  => n.following_siblings().iter().map(|n| n.to_node()).collect(),
            &CommentNode(n)               => n.following_siblings().iter().map(|n| n.to_node()).collect(),
            &ProcessingInstructionNode(n) => n.following_siblings().iter().map(|n| n.to_node()).collect(),
        }
    }
}

conversion_trait!(ToNode, to_node, Node, {
    dom4::Root => RootNode,
    dom4::Element => ElementNode,
    dom4::Attribute => AttributeNode,
    dom4::Text => TextNode,
    dom4::Comment => CommentNode,
    dom4::ProcessingInstruction => ProcessingInstructionNode
});

impl<'d> ToNode<'d> for dom4::ChildOfRoot<'d> {
    fn to_node(self) -> Node<'d> {
        match self {
            dom4::ChildOfRoot::Element(n)               => ElementNode(n),
            dom4::ChildOfRoot::Comment(n)               => CommentNode(n),
            dom4::ChildOfRoot::ProcessingInstruction(n) => ProcessingInstructionNode(n),
        }
    }
}

impl<'d> ToNode<'d> for dom4::ChildOfElement<'d> {
    fn to_node(self) -> Node<'d> {
        match self {
            dom4::ChildOfElement::Element(n)               => ElementNode(n),
            dom4::ChildOfElement::Text(n)                  => TextNode(n),
            dom4::ChildOfElement::Comment(n)               => CommentNode(n),
            dom4::ChildOfElement::ProcessingInstruction(n) => ProcessingInstructionNode(n),
        }
    }
}

impl<'d> ToNode<'d> for dom4::ParentOfChild<'d> {
    fn to_node(self) -> Node<'d> {
        match self {
            dom4::ParentOfChild::Root(n)    => RootNode(n),
            dom4::ParentOfChild::Element(n) => ElementNode(n),
        }
    }
}

/// A collection of nodes
#[derive(PartialEq,Debug,Clone)]
pub struct Nodeset<'d> {
    nodes: Vec<Node<'d>>,
}

impl<'d> Nodeset<'d> {
    pub fn new() -> Nodeset<'d> {
        Nodeset { nodes: Vec::new() }
    }

    pub fn add<N : ToNode<'d>>(&mut self, node: N) {
        self.nodes.push(node.to_node());
    }

    pub fn iter(&self) -> Iter<Node<'d>> {
        self.nodes.iter()
    }

    pub fn add_nodeset(& mut self, other: &Nodeset<'d>) {
        self.nodes.push_all(&other.nodes);
    }

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

    pub fn into_iter(self) -> vec::IntoIter<Node<'d>> {
        self.nodes.into_iter()
    }
}

impl<'a, 'd : 'a> FromIterator<EvaluationContext<'a, 'd>> for Nodeset<'d> {
    fn from_iter<T>(iterator: T) -> Nodeset<'d>
        where T: Iterator<Item=EvaluationContext<'a, 'd>>
    {
        let mut ns = Nodeset::new();
        for n in iterator { ns.add(n.node) };
        ns
    }
}

#[cfg(test)]
mod test {
    use document::Package;
    use super::Node::{
        AttributeNode,
        CommentNode,
        ElementNode,
        ProcessingInstructionNode,
        RootNode,
        TextNode,
    };
    use super::Nodeset;

    #[test]
    fn nodeset_can_include_all_node_types() {
        let package = Package::new();
        let doc = package.as_document();
        let mut nodes = Nodeset::new();

        let r = doc.root();
        let e = doc.create_element("element");
        let a = e.set_attribute_value("name", "value");
        let t = doc.create_text("text");
        let c = doc.create_comment("comment");
        let p = doc.create_processing_instruction("pi", None);

        nodes.add(r);
        nodes.add(e);
        nodes.add(a);
        nodes.add(t);
        nodes.add(c);
        nodes.add(p);

        let node_vec: Vec<_> = nodes.iter().collect();

        assert_eq!(6, node_vec.len());
        assert_eq!(node_vec[0], &RootNode(r));
        assert_eq!(node_vec[1], &ElementNode(e));
        assert_eq!(node_vec[2], &AttributeNode(a));
        assert_eq!(node_vec[3], &TextNode(t));
        assert_eq!(node_vec[4], &CommentNode(c));
        assert_eq!(node_vec[5], &ProcessingInstructionNode(p));
    }

    #[test]
    fn nodesets_can_be_combined() {
        let package = Package::new();
        let doc = package.as_document();

        let mut all_nodes = Nodeset::new();
        let mut nodes1 = Nodeset::new();
        let mut nodes2 = Nodeset::new();

        let e1 = doc.create_element("element1");
        let e2 = doc.create_element("element2");

        all_nodes.add(e1);
        all_nodes.add(e2);

        nodes1.add(e1);
        nodes2.add(e2);

        nodes1.add_nodeset(&nodes2);

        assert_eq!(all_nodes, nodes1);
    }
}
<commit_msg>Introduce the concept of document order to Nodeset<commit_after>use std::collections::HashMap;
use std::iter::FromIterator;
use std::slice::Iter;
use std::vec;

use document::dom4;

use super::EvaluationContext;

use self::Node::*;

macro_rules! unpack(
    ($enum_name:ident, $name:ident, $wrapper:ident, dom4::$inner:ident) => (
        impl<'d> $enum_name<'d> {
            pub fn $name(self) -> Option<dom4::$inner<'d>> {
                match self {
                    $wrapper(n) => Some(n),
                    _ => None,
                }
            }
        }
    )
);

macro_rules! conversion_trait(
    ($tr_name:ident, $method:ident, $res_type:ident,
        { $(dom4::$leaf_type:ident => $variant:ident),* }
    ) => (
        pub trait $tr_name<'d> {
            fn $method(self) -> $res_type<'d>;
        }

        impl<'d> $tr_name<'d> for $res_type<'d> {
            fn $method(self) -> $res_type<'d> {
                self
            }
        }

        $(impl<'d> $tr_name<'d> for dom4::$leaf_type<'d> {
            fn $method(self) -> $res_type<'d> {
                $variant(self)
            }
        })*
    )
);

#[derive(Copy,Clone,PartialEq,Eq,Hash,Debug)]
pub enum Node<'d> {
    RootNode(dom4::Root<'d>),
    ElementNode(dom4::Element<'d>),
    AttributeNode(dom4::Attribute<'d>),
    TextNode(dom4::Text<'d>),
    CommentNode(dom4::Comment<'d>),
    ProcessingInstructionNode(dom4::ProcessingInstruction<'d>),
}

unpack!(Node, root, RootNode, dom4::Root);
unpack!(Node, element, ElementNode, dom4::Element);
unpack!(Node, attribute, AttributeNode, dom4::Attribute);
unpack!(Node, text, TextNode, dom4::Text);
unpack!(Node, comment, CommentNode, dom4::Comment);
unpack!(Node, processing_instruction, ProcessingInstructionNode, dom4::ProcessingInstruction);

impl<'d> Node<'d> {
    pub fn document(&self) -> &'d dom4::Document<'d> {
        match self {
            &RootNode(n)                  => n.document(),
            &ElementNode(n)               => n.document(),
            &AttributeNode(n)             => n.document(),
            &TextNode(n)                  => n.document(),
            &CommentNode(n)               => n.document(),
            &ProcessingInstructionNode(n) => n.document(),
        }
    }

    pub fn parent(&self) -> Option<Node<'d>> {
        match self {
            &RootNode(_)                  => None,
            &ElementNode(n)               => n.parent().map(|n| n.to_node()),
            &AttributeNode(n)             => n.parent().map(|n| n.to_node()),
            &TextNode(n)                  => n.parent().map(|n| n.to_node()),
            &CommentNode(n)               => n.parent().map(|n| n.to_node()),
            &ProcessingInstructionNode(n) => n.parent().map(|n| n.to_node()),
        }
    }

    pub fn children(&self) -> Vec<Node<'d>> {
        match self {
            &RootNode(n)                  => n.children().iter().map(|n| n.to_node()).collect(),
            &ElementNode(n)               => n.children().iter().map(|n| n.to_node()).collect(),
            &AttributeNode(_)             => Vec::new(),
            &TextNode(_)                  => Vec::new(),
            &CommentNode(_)               => Vec::new(),
            &ProcessingInstructionNode(_) => Vec::new(),
        }
    }

    pub fn preceding_siblings(&self) -> Vec<Node<'d>> {
        match self {
            &RootNode(_)                  => Vec::new(),
            &ElementNode(n)               => n.preceding_siblings().iter().rev().map(|n| n.to_node()).collect(),
            &AttributeNode(_)             => Vec::new(),
            &TextNode(n)                  => n.preceding_siblings().iter().rev().map(|n| n.to_node()).collect(),
            &CommentNode(n)               => n.preceding_siblings().iter().rev().map(|n| n.to_node()).collect(),
            &ProcessingInstructionNode(n) => n.preceding_siblings().iter().rev().map(|n| n.to_node()).collect(),
        }
    }

    pub fn following_siblings(&self) -> Vec<Node<'d>> {
        match self {
            &RootNode(_)                  => Vec::new(),
            &ElementNode(n)               => n.following_siblings().iter().map(|n| n.to_node()).collect(),
            &AttributeNode(_)             => Vec::new(),
            &TextNode(n)                  => n.following_siblings().iter().map(|n| n.to_node()).collect(),
            &CommentNode(n)               => n.following_siblings().iter().map(|n| n.to_node()).collect(),
            &ProcessingInstructionNode(n) => n.following_siblings().iter().map(|n| n.to_node()).collect(),
        }
    }
}

conversion_trait!(ToNode, to_node, Node, {
    dom4::Root => RootNode,
    dom4::Element => ElementNode,
    dom4::Attribute => AttributeNode,
    dom4::Text => TextNode,
    dom4::Comment => CommentNode,
    dom4::ProcessingInstruction => ProcessingInstructionNode
});

impl<'d> ToNode<'d> for dom4::ChildOfRoot<'d> {
    fn to_node(self) -> Node<'d> {
        match self {
            dom4::ChildOfRoot::Element(n)               => ElementNode(n),
            dom4::ChildOfRoot::Comment(n)               => CommentNode(n),
            dom4::ChildOfRoot::ProcessingInstruction(n) => ProcessingInstructionNode(n),
        }
    }
}

impl<'d> ToNode<'d> for dom4::ChildOfElement<'d> {
    fn to_node(self) -> Node<'d> {
        match self {
            dom4::ChildOfElement::Element(n)               => ElementNode(n),
            dom4::ChildOfElement::Text(n)                  => TextNode(n),
            dom4::ChildOfElement::Comment(n)               => CommentNode(n),
            dom4::ChildOfElement::ProcessingInstruction(n) => ProcessingInstructionNode(n),
        }
    }
}

impl<'d> ToNode<'d> for dom4::ParentOfChild<'d> {
    fn to_node(self) -> Node<'d> {
        match self {
            dom4::ParentOfChild::Root(n)    => RootNode(n),
            dom4::ParentOfChild::Element(n) => ElementNode(n),
        }
    }
}

/// A collection of nodes
#[derive(PartialEq,Debug,Clone)]
pub struct Nodeset<'d> {
    nodes: Vec<Node<'d>>,
}

impl<'d> Nodeset<'d> {
    pub fn new() -> Nodeset<'d> {
        Nodeset { nodes: Vec::new() }
    }

    pub fn add<N : ToNode<'d>>(&mut self, node: N) {
        self.nodes.push(node.to_node());
    }

    pub fn iter(&self) -> Iter<Node<'d>> {
        self.nodes.iter()
    }

    pub fn add_nodeset(& mut self, other: &Nodeset<'d>) {
        self.nodes.push_all(&other.nodes);
    }

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

    pub fn into_iter(self) -> vec::IntoIter<Node<'d>> {
        self.nodes.into_iter()
    }

    pub fn document_order_first(&self) -> Option<Node<'d>> {
        let doc = match self.nodes.first() {
            Some(n) => n.document(),
            None => return None,
        };

        let mut idx = 0;
        let mut stack = vec![doc.root().to_node()];
        let mut order: HashMap<Node, usize> = HashMap::new();

        // Rebuilding this each time cannot possibly be performant,
        // but I want to see how widely used this is first before
        // picking an appropriate caching point.

        while let Some(n) = stack.pop() {
            order.insert(n, idx);
            idx += 1;
            let c = n.children();

            stack.extend(c.into_iter().rev());

            if let Node::ElementNode(e) = n {
                // TODO: namespaces
                stack.extend(e.attributes().into_iter().map(|a| a.to_node()));
            }
        }

        self.nodes.iter().min_by(|&&n| order[n]).map(|n| *n)
    }
}

impl<'a, 'd : 'a> FromIterator<EvaluationContext<'a, 'd>> for Nodeset<'d> {
    fn from_iter<T>(iterator: T) -> Nodeset<'d>
        where T: Iterator<Item=EvaluationContext<'a, 'd>>
    {
        let mut ns = Nodeset::new();
        for n in iterator { ns.add(n.node) };
        ns
    }
}

#[cfg(test)]
mod test {
    use document::Package;
    use super::Node::{
        AttributeNode,
        CommentNode,
        ElementNode,
        ProcessingInstructionNode,
        RootNode,
        TextNode,
    };
    use super::{Nodeset,ToNode};

    #[test]
    fn nodeset_can_include_all_node_types() {
        let package = Package::new();
        let doc = package.as_document();
        let mut nodes = Nodeset::new();

        let r = doc.root();
        let e = doc.create_element("element");
        let a = e.set_attribute_value("name", "value");
        let t = doc.create_text("text");
        let c = doc.create_comment("comment");
        let p = doc.create_processing_instruction("pi", None);

        nodes.add(r);
        nodes.add(e);
        nodes.add(a);
        nodes.add(t);
        nodes.add(c);
        nodes.add(p);

        let node_vec: Vec<_> = nodes.iter().collect();

        assert_eq!(6, node_vec.len());
        assert_eq!(node_vec[0], &RootNode(r));
        assert_eq!(node_vec[1], &ElementNode(e));
        assert_eq!(node_vec[2], &AttributeNode(a));
        assert_eq!(node_vec[3], &TextNode(t));
        assert_eq!(node_vec[4], &CommentNode(c));
        assert_eq!(node_vec[5], &ProcessingInstructionNode(p));
    }

    #[test]
    fn nodesets_can_be_combined() {
        let package = Package::new();
        let doc = package.as_document();

        let mut all_nodes = Nodeset::new();
        let mut nodes1 = Nodeset::new();
        let mut nodes2 = Nodeset::new();

        let e1 = doc.create_element("element1");
        let e2 = doc.create_element("element2");

        all_nodes.add(e1);
        all_nodes.add(e2);

        nodes1.add(e1);
        nodes2.add(e2);

        nodes1.add_nodeset(&nodes2);

        assert_eq!(all_nodes, nodes1);
    }

    #[test]
    fn nodeset_knows_first_node_in_document_order() {
        let package = Package::new();
        let doc = package.as_document();

        let c1 = doc.create_comment("1");
        let c2 = doc.create_comment("2");
        doc.root().append_child(c1);
        doc.root().append_child(c2);

        let nodes = nodeset![c2, c1];

        assert_eq!(Some(c1.to_node()), nodes.document_order_first());
    }

    #[test]
    fn attributes_come_before_children_in_document_order() {
        let package = Package::new();
        let doc = package.as_document();

        let parent = doc.create_element("parent");
        let attr = parent.set_attribute_value("a", "v");
        let child = doc.create_element("child");

        doc.root().append_child(parent);
        parent.append_child(child);

        let nodes = nodeset![child, attr];

        assert_eq!(Some(attr.to_node()), nodes.document_order_first());
    }
}
<|endoftext|>


<commit_before>use std::ffi::CString;
use std::ptr;

use class::TypeParams;
use ctxt::{Fct, FctId, FctSrc, SemContext};

use dora_parser::ast::*;

use llvm;
use llvm::core::*;
// use llvm::execution_engine::*;
// use llvm::target::*;

pub fn generate<'ast>(
    ctxt: &SemContext<'ast>,
    id: FctId,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let fct = ctxt.fcts[id].borrow();
    let src = fct.src();
    let mut src = src.borrow_mut();

    generate_fct(ctxt, &fct, &mut src, cls_type_params, fct_type_params)
}

pub fn generate_fct<'ast>(
    ctxt: &SemContext<'ast>,
    fct: &Fct<'ast>,
    src: &mut FctSrc,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let name = fct.full_name(ctxt);

    let mut cg = CodeGen {
        ctxt: ctxt,
        fct: fct,
        ast: fct.ast,
        src: src,
        cls_type_params,
        fct_type_params,

        fct_name: CString::new(name).unwrap(),

        context: ptr::null_mut(),
        module: ptr::null_mut(),
        builder: ptr::null_mut(),
        function: ptr::null_mut(),
    };

    cg.generate()
}

struct CodeGen<'a, 'ast: 'a> {
    ctxt: &'a SemContext<'ast>,
    fct: &'a Fct<'ast>,
    ast: &'ast Function,
    src: &'a mut FctSrc,
    cls_type_params: &'a TypeParams,
    fct_type_params: &'a TypeParams,

    fct_name: CString,

    context: *mut llvm::LLVMContext,
    module: *mut llvm::LLVMModule,
    builder: *mut llvm::LLVMBuilder,
    function: *mut llvm::LLVMValue,
}

impl<'a, 'ast> CodeGen<'a, 'ast>
where
    'ast: 'a,
{
    fn generate(&mut self) -> Result<*const u8, ()> {
        self.init();
        self.create_function();

        Err(())
    }

    fn init(&mut self) {
        unsafe {
            self.context = LLVMContextCreate();
            self.module = LLVMModuleCreateWithNameInContext(
                self.fct_name.as_ptr(),
                self.context,
            );
            self.builder = LLVMCreateBuilderInContext(self.context);
        }
    }

    fn create_function(&mut self) {
        unsafe {
            let i64t = LLVMInt64TypeInContext(self.context);
            let mut argts = [i64t, i64t, i64t];
            let function_type = LLVMFunctionType(
                i64t,
                argts.as_mut_ptr(),
                argts.len() as u32,
                0);

            self.function = LLVMAddFunction(self.module, self.fct_name.as_ptr(), function_type);
        }
    }
}
<commit_msg>opt: start returning llvm types<commit_after>use std::ffi::CString;
use std::ptr;

use class::TypeParams;
use ctxt::{Fct, FctId, FctParent, FctSrc, SemContext};
use ty::{BuiltinType, MachineMode};

use dora_parser::ast::*;

use llvm;
use llvm::core::*;
// use llvm::execution_engine::*;
// use llvm::target::*;

pub fn generate<'ast>(
    ctxt: &SemContext<'ast>,
    id: FctId,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let fct = ctxt.fcts[id].borrow();
    let src = fct.src();
    let mut src = src.borrow_mut();

    generate_fct(ctxt, &fct, &mut src, cls_type_params, fct_type_params)
}

pub fn generate_fct<'ast>(
    ctxt: &SemContext<'ast>,
    fct: &Fct<'ast>,
    src: &mut FctSrc,
    cls_type_params: &TypeParams,
    fct_type_params: &TypeParams,
) -> Result<*const u8, ()> {
    let name = fct.full_name(ctxt);

    let mut cg = CodeGen {
        ctxt: ctxt,
        fct: fct,
        ast: fct.ast,
        src: src,
        cls_type_params,
        fct_type_params,

        fct_name: CString::new(name).unwrap(),

        context: ptr::null_mut(),
        module: ptr::null_mut(),
        builder: ptr::null_mut(),
        function: ptr::null_mut(),
    };

    cg.generate()
}

struct CodeGen<'a, 'ast: 'a> {
    ctxt: &'a SemContext<'ast>,
    fct: &'a Fct<'ast>,
    ast: &'ast Function,
    src: &'a mut FctSrc,
    cls_type_params: &'a TypeParams,
    fct_type_params: &'a TypeParams,

    fct_name: CString,

    context: *mut llvm::LLVMContext,
    module: *mut llvm::LLVMModule,
    builder: *mut llvm::LLVMBuilder,
    function: *mut llvm::LLVMValue,
}

impl<'a, 'ast> CodeGen<'a, 'ast>
where
    'ast: 'a,
{
    fn generate(&mut self) -> Result<*const u8, ()> {
        self.init();
        self.create_function()?;

        Err(())
    }

    fn init(&mut self) {
        unsafe {
            self.context = LLVMContextCreate();
            self.module = LLVMModuleCreateWithNameInContext(
                self.fct_name.as_ptr(),
                self.context,
            );
            self.builder = LLVMCreateBuilderInContext(self.context);
        }
    }

    fn create_function(&mut self) -> Result<(), ()> {
        let mut params = Vec::with_capacity(self.ast.params.len());

        for param in &self.ast.params {
            let ty = self.ty(param.id);
            params.push(self.llvm_ty(ty));
        }

        let return_type = self.specialize_type(self.fct.return_type);
        let llvm_return_type = self.llvm_ty(return_type);

        unsafe {
            let function_type = LLVMFunctionType(
                llvm_return_type,
                params.as_mut_ptr(),
                params.len() as u32,
                0);

            self.function = LLVMAddFunction(self.module, self.fct_name.as_ptr(), function_type);
        }

        Err(())
    }

    fn ty(&self, id: NodeId) -> BuiltinType {
        let ty = self.src.ty(id);
        self.specialize_type(ty)
    }

    fn specialize_type(&self, ty: BuiltinType) -> BuiltinType {
        match ty {
            BuiltinType::ClassTypeParam(cls_id, id) => {
                assert!(self.fct.parent == FctParent::Class(cls_id));
                self.cls_type_params[id.idx()]
            }

            BuiltinType::FctTypeParam(fct_id, id) => {
                assert!(self.fct.id == fct_id);
                self.fct_type_params[id.idx()]
            }

            BuiltinType::Class(cls_id, list_id) => {
                let params = self.ctxt.lists.borrow().get(list_id);

                let params: Vec<_> = params.iter().map(|t| self.specialize_type(t)).collect();

                let list_id = self.ctxt.lists.borrow_mut().insert(params.into());

                BuiltinType::Class(cls_id, list_id)
            }

            BuiltinType::Lambda(_) => unimplemented!(),

            _ => ty,
        }
    }

    fn llvm_ty(&self, ty: BuiltinType) -> *mut llvm::LLVMType {
        let mode = ty.mode();

        unsafe {
            match mode {
                MachineMode::Int64 => LLVMInt64TypeInContext(self.context),
                MachineMode::Int32 => LLVMInt32TypeInContext(self.context),
                MachineMode::Int8 => LLVMInt8TypeInContext(self.context),
                MachineMode::Float32 => LLVMFloatTypeInContext(self.context),
                MachineMode::Float64 => LLVMDoubleTypeInContext(self.context),
                MachineMode::Ptr => unimplemented!(),
            }
        }
    }
}
<|endoftext|>


<commit_before>#![macro_escape]

pub trait StrParseExt {
    fn end_of_start_rest(&self, is_first: |char| -> bool, is_rest: |char| -> bool) -> Option<uint>;
    fn end_of_literal(&self, expected: &str) -> Option<uint>;
}

impl<'a> StrParseExt for &'a str {
    fn end_of_start_rest(&self,
                         is_first: |char| -> bool,
                         is_rest: |char| -> bool)
                         -> Option<uint>
    {
        let mut positions = self.char_indices();

        match positions.next() {
            Some((_, c)) if is_first(c) => (),
            Some((_, _)) => return None,
            None => return None,
        };

        let mut positions = positions.skip_while(|&(_, c)| is_rest(c));
        match positions.next() {
            Some((offset, _)) => Some(offset),
            None => Some(self.len()),
        }
    }

    fn end_of_literal(&self, expected: &str) -> Option<uint> {
        if self.starts_with(expected) {
            Some(expected.len())
        } else {
            None
        }
    }
}

pub struct BestFailure<'a, E> {
    pub failure: Option<Progress<'a, E>>
}

impl<'a, E> BestFailure<'a, E> {
    pub fn new() -> BestFailure<'a, E> {
        BestFailure {
            failure: None,
        }
    }

    pub fn with(failure: Progress<'a, E>) -> BestFailure<'a, E> {
        BestFailure {
            failure: Some(failure),
        }
    }

    pub fn push(&mut self, failure: Progress<'a, E>) {
        if let Some(ref old) = self.failure {
            if failure.point.offset <= old.point.offset {
                return;
            }
        }

        self.failure = Some(failure)
    }

    pub fn pop(self) -> Progress<'a, E> {
        self.failure.expect("No errors found")
    }
}

#[deriving(Show,Clone,PartialEq,Copy)]
pub struct Point<'a> {
    pub offset: uint,
    pub s: &'a str,
}

impl<'a> Point<'a> {
    pub fn to(&self, other: Point<'a>) -> &'a str {
        let len = other.offset - self.offset;
        self.s.slice_to(len)
    }

    pub fn slice_at(&self, position: uint) -> Progress<'a, &'a str> {
        Progress {
            data: self.s.slice_to(position),
            point: Point { offset: self.offset + position,
                           s: self.s.slice_from(position) }
        }
    }

    pub fn consume_to<E>(&self, l: Option<uint>) -> Result<'a, &'a str, E> {
        match l {
            None => Result::Failure(Progress{point: self.clone(), data: None}),
            Some(position) => Result::Success(self.slice_at(position)),
        }
    }

    pub fn consume_literal<E>(&self, literal: &str) -> Result<'a, &'a str, E> {
        self.consume_to(self.s.end_of_literal(literal))
    }
}

pub struct Progress<'a, T> {
    pub point: Point<'a>,
    pub data: T,
}

impl<'a, T> Progress<'a, T> {
    pub fn to_tuple(self) -> (T, Point<'a>) {
        (self.data, self.point)
    }

    pub fn map<F, B>(self, f: F) -> Progress<'a, B>
        where F: FnOnce(T) -> B
    {
        Progress { data: f(self.data), point: self.point }
    }
}

pub enum Result<'a, T, E> {
    Success(Progress<'a, T>),
    Partial{success: Progress<'a, T>, failure: Progress<'a, Option<E>>},
    Failure(Progress<'a, Option<E>>),
}

impl<'a, T, E> Result<'a, T, E> {
    pub fn success(data: T, point: Point<'a>) -> Result<'a, T, E> {
        Result::Success(Progress { data: data, point: point })
    }

    // Pattern: zero-or-one
    pub fn optional(self, point: Point<'a>) -> (Option<T>, Point<'a>) {
        match self {
            Result::Success(progress) |
            Result::Partial{ success: progress, .. } =>
                (Some(progress.data), progress.point),
            Result::Failure(_) =>
                (None, point),
        }
    }

    // Pattern: alternate
    pub fn or_else(self, f: || -> Result<'a, T, E>) -> Result<'a, T, E> {
        match self {
            Result::Success(..) => self,
            Result::Partial{ failure: fail, .. } |
            Result::Failure(fail) => {
                let next = f();
                match next {
                    Result::Success(..) => next,
                    Result::Partial{ failure: next_fail, .. } |
                    Result::Failure(next_fail) => {
                        let mut bf = BestFailure::with(fail);
                        bf.push(next_fail);
                        Result::Failure(bf.pop())
                    }
                }
            },
        }
    }

    pub fn map<F, B>(self, f: F) -> Result<'a, B, E>
        where F: FnOnce(T) -> B
    {
        match self {
            Result::Success(prog) =>
                Result::Success(prog.map(f)),
            Result::Partial{success: s, failure: ff} => {
                Result::Partial{ success: s.map(f), failure: ff}
            },
            Result::Failure(pf) =>
                Result::Failure(pf),
        }
    }
}

#[macro_export]
macro_rules! try_parse(
    ($e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) =>
                return ::document::peresil::Result::Failure(pf),
        }
    })
);

#[macro_export]
macro_rules! try_partial_parse(
    ($e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                (progress.data, ::document::peresil::BestFailure::new(), progress.point),
            ::document::peresil::Result::Partial{ success: s, failure: pf } =>
                (s.data, ::document::peresil::BestFailure::with(pf), s.point),
            ::document::peresil::Result::Failure(pf) =>
                return ::document::peresil::Result::Failure(pf),
        }
    })
);

#[macro_export]
macro_rules! try_resume_after_partial_failure(
    ($partial:expr, $e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) => {
                let mut partial = $partial;
                partial.push(pf);
                return ::document::peresil::Result::Failure(partial.pop())
            },
        }
    });
);

// Pattern: zero-or-many
pub fn zero_or_more<'a, T, E, P>(point: Point<'a>, parser: P) -> Result<'a, Vec<T>, E>
    where P: FnMut(Point<'a>) -> Result<'a, T, E>
{
    let mut err;
    let mut data = Vec::new();
    let mut point = point;
    let mut parser = parser;

    loop {
        let (d, next_start) = match parser(point) {
            Result::Success(progress) =>
                progress.to_tuple(),
            Result::Partial{ failure: pf, .. } |
            Result::Failure(pf) => {
                err = Some(pf);
                break
            }
        };

        data.push(d);
        point = next_start;
    }

    Result::Partial {
        success: Progress { data: data, point: point },
        failure: err.unwrap()
    }
}
<commit_msg>Allow specifying the error when parsing fails<commit_after>#![macro_escape]

pub trait StrParseExt {
    fn end_of_start_rest(&self, is_first: |char| -> bool, is_rest: |char| -> bool) -> Option<uint>;
    fn end_of_literal(&self, expected: &str) -> Option<uint>;
}

impl<'a> StrParseExt for &'a str {
    fn end_of_start_rest(&self,
                         is_first: |char| -> bool,
                         is_rest: |char| -> bool)
                         -> Option<uint>
    {
        let mut positions = self.char_indices();

        match positions.next() {
            Some((_, c)) if is_first(c) => (),
            Some((_, _)) => return None,
            None => return None,
        };

        let mut positions = positions.skip_while(|&(_, c)| is_rest(c));
        match positions.next() {
            Some((offset, _)) => Some(offset),
            None => Some(self.len()),
        }
    }

    fn end_of_literal(&self, expected: &str) -> Option<uint> {
        if self.starts_with(expected) {
            Some(expected.len())
        } else {
            None
        }
    }
}

pub struct BestFailure<'a, E> {
    pub failure: Option<Progress<'a, E>>
}

impl<'a, E> BestFailure<'a, E> {
    pub fn new() -> BestFailure<'a, E> {
        BestFailure {
            failure: None,
        }
    }

    pub fn with(failure: Progress<'a, E>) -> BestFailure<'a, E> {
        BestFailure {
            failure: Some(failure),
        }
    }

    pub fn push(&mut self, failure: Progress<'a, E>) {
        if let Some(ref old) = self.failure {
            if failure.point.offset <= old.point.offset {
                return;
            }
        }

        self.failure = Some(failure)
    }

    pub fn pop(self) -> Progress<'a, E> {
        self.failure.expect("No errors found")
    }
}

#[deriving(Show,Clone,PartialEq,Copy)]
pub struct Point<'a> {
    pub offset: uint,
    pub s: &'a str,
}

impl<'a> Point<'a> {
    pub fn to(&self, other: Point<'a>) -> &'a str {
        let len = other.offset - self.offset;
        self.s.slice_to(len)
    }

    pub fn slice_at(&self, position: uint) -> Progress<'a, &'a str> {
        Progress {
            data: self.s.slice_to(position),
            point: Point { offset: self.offset + position,
                           s: self.s.slice_from(position) }
        }
    }

    pub fn consume_to<E>(&self, l: Option<uint>) -> Result<'a, &'a str, E> {
        match l {
            None => Result::Failure(Progress{point: self.clone(), data: None}),
            Some(position) => Result::Success(self.slice_at(position)),
        }
    }

    pub fn consume_literal<E>(&self, literal: &str) -> Result<'a, &'a str, E> {
        self.consume_to(self.s.end_of_literal(literal))
    }
}

pub struct Progress<'a, T> {
    pub point: Point<'a>,
    pub data: T,
}

impl<'a, T> Progress<'a, T> {
    pub fn to_tuple(self) -> (T, Point<'a>) {
        (self.data, self.point)
    }

    pub fn map<F, B>(self, f: F) -> Progress<'a, B>
        where F: FnOnce(T) -> B
    {
        Progress { data: f(self.data), point: self.point }
    }
}

pub enum Result<'a, T, E> {
    Success(Progress<'a, T>),
    Partial{success: Progress<'a, T>, failure: Progress<'a, Option<E>>},
    Failure(Progress<'a, Option<E>>),
}

impl<'a, T, E> Result<'a, T, E> {
    pub fn success(data: T, point: Point<'a>) -> Result<'a, T, E> {
        Result::Success(Progress { data: data, point: point })
    }

    // Pattern: zero-or-one
    pub fn optional(self, point: Point<'a>) -> (Option<T>, Point<'a>) {
        match self {
            Result::Success(progress) |
            Result::Partial{ success: progress, .. } =>
                (Some(progress.data), progress.point),
            Result::Failure(_) =>
                (None, point),
        }
    }

    // Pattern: alternate
    pub fn or_else(self, f: || -> Result<'a, T, E>) -> Result<'a, T, E> {
        match self {
            Result::Success(..) => self,
            Result::Partial{ failure: fail, .. } |
            Result::Failure(fail) => {
                let next = f();
                match next {
                    Result::Success(..) => next,
                    Result::Partial{ failure: next_fail, .. } |
                    Result::Failure(next_fail) => {
                        let mut bf = BestFailure::with(fail);
                        bf.push(next_fail);
                        Result::Failure(bf.pop())
                    }
                }
            },
        }
    }

    pub fn map<F, B>(self, f: F) -> Result<'a, B, E>
        where F: FnOnce(T) -> B
    {
        match self {
            Result::Success(prog) =>
                Result::Success(prog.map(f)),
            Result::Partial{success: s, failure: ff} => {
                Result::Partial{ success: s.map(f), failure: ff}
            },
            Result::Failure(pf) =>
                Result::Failure(pf),
        }
    }

    pub fn set_error(self, error: E) -> Result<'a, T, E> {
        match self {
            Result::Success(..) =>
                self,
            Result::Partial{ success: s, failure: f } =>
                Result::Partial{ success: s, failure: f.map(move |_| Some(error)) },
            Result::Failure(f) =>
                Result::Failure(f.map(move |_| Some(error))),
        }
    }
}

#[macro_export]
macro_rules! try_parse(
    ($e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) =>
                return ::document::peresil::Result::Failure(pf),
        }
    });
    ($e:expr, $err:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) => {
                let fail = ::document::peresil::Progress{ data: Some($err), ..pf };
                return ::document::peresil::Result::Failure(fail);
            },
        }
    });
);

#[macro_export]
macro_rules! try_partial_parse(
    ($e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                (progress.data, ::document::peresil::BestFailure::new(), progress.point),
            ::document::peresil::Result::Partial{ success: s, failure: pf } =>
                (s.data, ::document::peresil::BestFailure::with(pf), s.point),
            ::document::peresil::Result::Failure(pf) =>
                return ::document::peresil::Result::Failure(pf),
        }
    })
);

#[macro_export]
macro_rules! try_resume_after_partial_failure(
    ($partial:expr, $e:expr) => ({
        match $e {
            ::document::peresil::Result::Success(progress) =>
                progress.to_tuple(),
            ::document::peresil::Result::Partial{ failure: pf, .. } |
            ::document::peresil::Result::Failure(pf) => {
                let mut partial = $partial;
                partial.push(pf);
                return ::document::peresil::Result::Failure(partial.pop())
            },
        }
    });
);

// Pattern: zero-or-many
pub fn zero_or_more<'a, T, E, P>(point: Point<'a>, parser: P) -> Result<'a, Vec<T>, E>
    where P: FnMut(Point<'a>) -> Result<'a, T, E>
{
    let mut err;
    let mut data = Vec::new();
    let mut point = point;
    let mut parser = parser;

    loop {
        let (d, next_start) = match parser(point) {
            Result::Success(progress) =>
                progress.to_tuple(),
            Result::Partial{ failure: pf, .. } |
            Result::Failure(pf) => {
                err = Some(pf);
                break
            }
        };

        data.push(d);
        point = next_start;
    }

    Result::Partial {
        success: Progress { data: data, point: point },
        failure: err.unwrap()
    }
}
<|endoftext|>


<commit_before>use std::thread;
use std::sync::mpsc::{self, channel, TryRecvError};
use std::io::{Read, ErrorKind};
use std::collections::HashMap;

use mio::*;
use mio::tcp::TcpListener;

use ladspa::{PluginDescriptor, Plugin, PortConnection};

use super::BASE_PORT;
use super::packet::{BUFFER_SIZE, BYTE_BUFFER_SIZE, Packet};

type ClientPacket = (u64, Packet);

const SERVER: Token = Token(0);

pub struct Receiver {
    sample_rate: u64,
    channel: u16,
    packet_rx: Option<mpsc::Receiver<ClientPacket>>,
    active_packets: Vec<ClientPacket>,
    notify_tx: Option<Sender<<PacketReceiver as Handler>::Message>>,
    client_time_map: HashMap<u64, u64>,
}

impl Receiver {
    pub fn new(_: &PluginDescriptor, sample_rate: u64) -> Box<Plugin + Send> {
        println!("receiver::new");
        Box::new(Receiver {
            sample_rate: sample_rate,
            channel: 0,
            packet_rx: None,
            active_packets: Vec::new(),
            notify_tx: None,
            client_time_map: HashMap::new(),
        })
    }

    fn init_server(&mut self) {
        let (data_tx, data_rx) = channel();
        self.packet_rx = Some(data_rx);

        let channel = self.channel;
        let mut event_loop = EventLoop::new().unwrap();
        self.notify_tx = Some(event_loop.channel());
        thread::spawn(move || {
            let addr = format!("127.0.0.1:{}", BASE_PORT + channel).parse().unwrap();
            let server;
            loop {
                match TcpListener::bind(&addr) {
                    Ok(s) => {
                        server = s;
                        break;
                    }
                    Err(_) => {}
                }
            }
            event_loop.register(&server, SERVER).unwrap();
            event_loop.run(&mut PacketReceiver {
                          server: server,
                          data_tx: data_tx,
                          client_id: 0,
                      })
                      .unwrap();
        });
    }

    fn kill_server(&mut self) {
        self.notify_tx.as_ref().unwrap().send(()).unwrap();
    }
}

impl Plugin for Receiver {
    fn run<'a>(&mut self, sample_count: usize, ports: &[&'a PortConnection<'a>]) {
        let inputl = ports[0].unwrap_audio();
        let inputr = ports[1].unwrap_audio();
        let mut outputl = ports[2].unwrap_audio_mut();
        let mut outputr = ports[3].unwrap_audio_mut();

        let channel = *ports[4].unwrap_control() as u16;

        if channel != self.channel {
            self.channel = channel;
            println!("set channel {}", self.channel);
            self.kill_server();
            self.init_server();
            return;
        }

        loop {
            let packet = match self.packet_rx.as_ref().unwrap().try_recv() {
                Ok(packet) => packet,
                Err(TryRecvError::Disconnected) => {
                    println!("ladspa packet receive failed, dead channel!");
                    self.kill_server();
                    self.init_server();
                    break;
                }
                Err(TryRecvError::Empty) => {
                    break;
                }
            };
            self.active_packets.push(packet);
        }

        for i in 0..sample_count {
            outputl[i] = inputl[i];
            outputr[i] = inputr[i];
        }
        let mut read_clients = Vec::new();
        for &mut (ref client_id, ref mut packet) in &mut self.active_packets {
            let client_time = self.client_time_map.get(client_id).map(|x| *x).unwrap_or(0);
            for i in 0..sample_count {
                let (l, r) = packet.read(client_time + i as u64);
                outputl[i] += l;
                outputr[i] += r;
            }
            read_clients.push(*client_id);
        }
        for client_id in read_clients {
            let client_time = self.client_time_map.get(&client_id).map(|x| *x).unwrap_or(0);
            self.client_time_map.insert(client_id, client_time + BUFFER_SIZE as u64);
        }

        // TODO avoid this clone
        let client_time_map = self.client_time_map.clone();
        self.active_packets.retain(|&(ref client_id, ref packet)| {
            let client_time = client_time_map[client_id];
            !packet.complete(client_time)
        });
    }

    fn activate(&mut self) {
        println!("activate {}", self.channel);
        self.client_time_map.clear();
        self.init_server();
    }

    fn deactivate(&mut self) {
        println!("deactivate {}", self.channel);
        self.kill_server();
    }
}

struct PacketReceiver {
    server: TcpListener,
    data_tx: mpsc::Sender<ClientPacket>,
    client_id: u64,
}

impl Handler for PacketReceiver {
    type Timeout = ();
        type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            SERVER => {
                // Only receive readable events
                assert!(events.is_readable());

                println!("server wait");
                match self.server.accept() {
                    Ok(Some(mut socket)) => {
                        let tx = self.data_tx.clone();
                        let mut buf = [0; BYTE_BUFFER_SIZE];
                        let mut buf_pos = 0;
                        let client_id = self.client_id;
                        println!("server accept client {}", client_id);
                        self.client_id += 1;
                        loop {
                            let res = socket.read(&mut buf[buf_pos..]);
                            match res {
                                Ok(num_read) => {
                                    //println!("server read {}", num_read);
                                    // if we got a length zero read, the connection is done.
                                    if num_read == 0 {
                                        println!("read zero bytes");
                                        return;
                                    }

                                    // check if we've filled the buffer
                                    buf_pos += num_read;
                                    if buf_pos != BYTE_BUFFER_SIZE {
                                        continue;
                                    }
                                    buf_pos = 0;
                                }
                                Err(e) => {
                                    if e.kind() == ErrorKind::WouldBlock {
                                        continue;
                                    }
                                    panic!(e);
                                }
                            }
                            let packet = Packet::parse(&buf[..]);
                            if let Err(_) = tx.send((client_id, packet)) {
                                println!("send packet to ladspa error! channel is dead.");
                                return;
                            }
                        }
                    }
                    Ok(None) => {
                        println!("the server socket wasn't actually ready");
                    }
                    Err(e) => {
                        println!("listener.accept() errored: {}", e);
                        // event_loop.shutdown();
                    }
                }
            }
            _ => panic!("Received unknown token"),
        }
    }
    fn notify(&mut self, event_loop: &mut EventLoop<Self>, msg: Self::Message) {
        event_loop.shutdown();
    }
}
<commit_msg>Fix typo that caused major frustration<commit_after>use std::thread;
use std::sync::mpsc::{self, channel, TryRecvError};
use std::io::{Read, ErrorKind};
use std::collections::HashMap;

use mio::*;
use mio::tcp::TcpListener;

use ladspa::{PluginDescriptor, Plugin, PortConnection};

use super::BASE_PORT;
use super::packet::{BUFFER_SIZE, BYTE_BUFFER_SIZE, Packet};

type ClientPacket = (u64, Packet);

const SERVER: Token = Token(0);

pub struct Receiver {
    sample_rate: u64,
    channel: u16,
    packet_rx: Option<mpsc::Receiver<ClientPacket>>,
    active_packets: Vec<ClientPacket>,
    notify_tx: Option<Sender<<PacketReceiver as Handler>::Message>>,
    client_time_map: HashMap<u64, u64>,
}

impl Receiver {
    pub fn new(_: &PluginDescriptor, sample_rate: u64) -> Box<Plugin + Send> {
        println!("receiver::new");
        Box::new(Receiver {
            sample_rate: sample_rate,
            channel: 0,
            packet_rx: None,
            active_packets: Vec::new(),
            notify_tx: None,
            client_time_map: HashMap::new(),
        })
    }

    fn init_server(&mut self) {
        let (data_tx, data_rx) = channel();
        self.packet_rx = Some(data_rx);

        let channel = self.channel;
        let mut event_loop = EventLoop::new().unwrap();
        self.notify_tx = Some(event_loop.channel());
        thread::spawn(move || {
            let addr = format!("127.0.0.1:{}", BASE_PORT + channel).parse().unwrap();
            let server;
            loop {
                match TcpListener::bind(&addr) {
                    Ok(s) => {
                        server = s;
                        break;
                    }
                    Err(_) => {}
                }
            }
            event_loop.register(&server, SERVER).unwrap();
            event_loop.run(&mut PacketReceiver {
                          server: server,
                          data_tx: data_tx,
                          client_id: 0,
                      })
                      .unwrap();
        });
    }

    fn kill_server(&mut self) {
        self.notify_tx.as_ref().unwrap().send(()).unwrap();
    }
}

impl Plugin for Receiver {
    fn run<'a>(&mut self, sample_count: usize, ports: &[&'a PortConnection<'a>]) {
        let inputl = ports[0].unwrap_audio();
        let inputr = ports[1].unwrap_audio();
        let mut outputl = ports[2].unwrap_audio_mut();
        let mut outputr = ports[3].unwrap_audio_mut();

        let channel = *ports[4].unwrap_control() as u16;

        if channel != self.channel {
            self.channel = channel;
            println!("set channel {}", self.channel);
            self.kill_server();
            self.init_server();
            return;
        }

        loop {
            let packet = match self.packet_rx.as_ref().unwrap().try_recv() {
                Ok(packet) => packet,
                Err(TryRecvError::Disconnected) => {
                    println!("ladspa packet receive failed, dead channel!");
                    self.kill_server();
                    self.init_server();
                    break;
                }
                Err(TryRecvError::Empty) => {
                    break;
                }
            };
            self.active_packets.push(packet);
        }

        for i in 0..sample_count {
            outputl[i] = inputl[i];
            outputr[i] = inputr[i];
        }
        let mut read_clients = Vec::new();
        for &mut (ref client_id, ref mut packet) in &mut self.active_packets {
            let client_time = self.client_time_map.get(client_id).map(|x| *x).unwrap_or(0);
            for i in 0..sample_count {
                let (l, r) = packet.read(client_time + i as u64);
                outputl[i] += l;
                outputr[i] += r;
            }
            read_clients.push(*client_id);
        }
        for client_id in read_clients {
            let client_time = self.client_time_map.get(&client_id).map(|x| *x).unwrap_or(0);
            self.client_time_map.insert(client_id, client_time + sample_count as u64);
        }

        // TODO avoid this clone
        let client_time_map = self.client_time_map.clone();
        self.active_packets.retain(|&(ref client_id, ref packet)| {
            let client_time = client_time_map[client_id];
            !packet.complete(client_time)
        });
    }

    fn activate(&mut self) {
        println!("activate {}", self.channel);
        self.client_time_map.clear();
        self.init_server();
    }

    fn deactivate(&mut self) {
        println!("deactivate {}", self.channel);
        self.kill_server();
    }
}

struct PacketReceiver {
    server: TcpListener,
    data_tx: mpsc::Sender<ClientPacket>,
    client_id: u64,
}

impl Handler for PacketReceiver {
    type Timeout = ();
        type Message = ();

    fn ready(&mut self, event_loop: &mut EventLoop<Self>, token: Token, events: EventSet) {
        match token {
            SERVER => {
                // Only receive readable events
                assert!(events.is_readable());

                println!("server wait");
                match self.server.accept() {
                    Ok(Some(mut socket)) => {
                        let tx = self.data_tx.clone();
                        let mut buf = [0; BYTE_BUFFER_SIZE];
                        let mut buf_pos = 0;
                        let client_id = self.client_id;
                        println!("server accept client {}", client_id);
                        self.client_id += 1;
                        loop {
                            let res = socket.read(&mut buf[buf_pos..]);
                            match res {
                                Ok(num_read) => {
                                    //println!("server read {}", num_read);
                                    // if we got a length zero read, the connection is done.
                                    if num_read == 0 {
                                        println!("read zero bytes");
                                        return;
                                    }

                                    // check if we've filled the buffer
                                    buf_pos += num_read;
                                    if buf_pos != BYTE_BUFFER_SIZE {
                                        continue;
                                    }
                                    buf_pos = 0;
                                }
                                Err(e) => {
                                    if e.kind() == ErrorKind::WouldBlock {
                                        continue;
                                    }
                                    panic!(e);
                                }
                            }
                            let packet = Packet::parse(&buf[..]);
                            if let Err(_) = tx.send((client_id, packet)) {
                                println!("send packet to ladspa error! channel is dead.");
                                return;
                            }
                        }
                    }
                    Ok(None) => {
                        println!("the server socket wasn't actually ready");
                    }
                    Err(e) => {
                        println!("listener.accept() errored: {}", e);
                        // event_loop.shutdown();
                    }
                }
            }
            _ => panic!("Received unknown token"),
        }
    }
    fn notify(&mut self, event_loop: &mut EventLoop<Self>, msg: Self::Message) {
        event_loop.shutdown();
    }
}
<|endoftext|>