<commit_before>use nom::multispace;
use std::collections::{HashSet, VecDeque};
use std::str;
use std::fmt;

use column::Column;
use common::{binary_comparison_operator, column_identifier, integer_literal, opt_multispace,
             string_literal, Literal, Operator};

use select::{nested_selection, SelectStatement};

#[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
pub enum ConditionBase {
    Field(Column),
    Literal(Literal),
    Placeholder,
    NestedSelect(Box<SelectStatement>),
}

impl fmt::Display for ConditionBase {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ConditionBase::Field(ref col) => write!(f, "{}", col),
            ConditionBase::Literal(ref literal) => write!(f, "{}", literal.to_string()),
            ConditionBase::Placeholder => write!(f, "?"),
            ConditionBase::NestedSelect(ref select) => write!(f, "{}", select),
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
pub struct ConditionTree {
    pub operator: Operator,
    pub left: Box<ConditionExpression>,
    pub right: Box<ConditionExpression>,
}

impl<'a> ConditionTree {
    pub fn contained_columns(&'a self) -> HashSet<&'a Column> {
        let mut s = HashSet::new();
        let mut q = VecDeque::<&'a ConditionTree>::new();
        q.push_back(self);
        while let Some(ref ct) = q.pop_front() {
            match *ct.left.as_ref() {
                ConditionExpression::Base(ConditionBase::Field(ref c)) => {
                    s.insert(c);
                }
                ConditionExpression::LogicalOp(ref ct)
                | ConditionExpression::ComparisonOp(ref ct) => q.push_back(ct),
                _ => (),
            }
            match *ct.right.as_ref() {
                ConditionExpression::Base(ConditionBase::Field(ref c)) => {
                    s.insert(c);
                }
                ConditionExpression::LogicalOp(ref ct)
                | ConditionExpression::ComparisonOp(ref ct) => q.push_back(ct),
                _ => (),
            }
        }
        s
    }
}

impl fmt::Display for ConditionTree {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.left)?;
        write!(f, " {} ", self.operator)?;
        write!(f, "{}", self.right)
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
pub enum ConditionExpression {
    ComparisonOp(ConditionTree),
    LogicalOp(ConditionTree),
    NegationOp(Box<ConditionExpression>),
    Base(ConditionBase),
}

impl fmt::Display for ConditionExpression {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ConditionExpression::ComparisonOp(ref tree) => write!(f, "{}", tree),
            ConditionExpression::LogicalOp(ref tree) => write!(f, "{}", tree),
            ConditionExpression::NegationOp(ref expr) => write!(f, "NOT {}", expr),
            ConditionExpression::Base(ref base) => write!(f, "{}", base),
        }
    }
}

/// Parse a conditional expression into a condition tree structure
named!(pub condition_expr<&[u8], ConditionExpression>,
       alt_complete!(
           do_parse!(
               left: and_expr >>
               opt_multispace >>
               tag_no_case!("or") >>
               multispace >>
               right: condition_expr >>
               (ConditionExpression::LogicalOp(
                   ConditionTree {
                       operator: Operator::Or,
                       left: Box::new(left),
                       right: Box::new(right),
                   }
               ))
           )
       |   and_expr)
);

named!(pub and_expr<&[u8], ConditionExpression>,
       alt_complete!(
           do_parse!(
               left: parenthetical_expr >>
               opt_multispace >>
               tag_no_case!("and") >>
               multispace >>
               right: and_expr >>
               (ConditionExpression::LogicalOp(
                   ConditionTree {
                       operator: Operator::And,
                       left: Box::new(left),
                       right: Box::new(right),
                   }
               ))
           )
       |   parenthetical_expr)
);

named!(pub parenthetical_expr<&[u8], ConditionExpression>,
       alt_complete!(
           delimited!(
               do_parse!(tag!("(") >> opt_multispace >> ()),
               condition_expr,
               do_parse!(opt_multispace >> tag!(")") >> opt_multispace >> ())
            )
       |   not_expr)
);

named!(pub not_expr<&[u8], ConditionExpression>,
       alt_complete!(
           do_parse!(
               tag_no_case!("not") >>
               multispace >>
               right: parenthetical_expr >>
               (ConditionExpression::NegationOp(Box::new(right)))
           )
       |   boolean_primary)
);

named!(boolean_primary<&[u8], ConditionExpression>,
    alt_complete!(
        do_parse!(
            left: predicate >>
            opt_multispace >>
            op: binary_comparison_operator >>
            opt_multispace >>
            right: predicate >>
            (ConditionExpression::ComparisonOp(
                ConditionTree {
                    operator: op,
                    left: Box::new(left),
                    right: Box::new(right),
                }
            ))
        )
        | predicate)
);

named!(predicate<&[u8], ConditionExpression>,
    alt_complete!(
            do_parse!(
                tag!("?") >>
                (ConditionExpression::Base(
                    ConditionBase::Placeholder
                ))
            )
        |   do_parse!(
                field: integer_literal >>
                (ConditionExpression::Base(ConditionBase::Literal(field)))
            )
        |   do_parse!(
                field: string_literal >>
                (ConditionExpression::Base(ConditionBase::Literal(field)))
            )
        |   do_parse!(
                field: column_identifier >>
                (ConditionExpression::Base(
                    ConditionBase::Field(field)
                ))
            )
        |   do_parse!(
                select: delimited!(tag!("("), nested_selection, tag!(")")) >>
                (ConditionExpression::Base(
                    ConditionBase::NestedSelect(Box::new(select))
                ))
            )
    )
);

#[cfg(test)]
mod tests {
    use super::*;
    use column::Column;
    use common::{FieldExpression, Literal, Operator};

    fn columns(cols: &[&str]) -> Vec<FieldExpression> {
        cols.iter()
            .map(|c| FieldExpression::Col(Column::from(*c)))
            .collect()
    }

    fn flat_condition_tree(
        op: Operator,
        l: ConditionBase,
        r: ConditionBase,
    ) -> ConditionExpression {
        ConditionExpression::ComparisonOp(ConditionTree {
            operator: op,
            left: Box::new(ConditionExpression::Base(l)),
            right: Box::new(ConditionExpression::Base(r)),
        })
    }

    #[test]
    fn ct_contained_columns() {
        use std::collections::HashSet;

        let cond = "a.foo = ? and b.bar = 42";

        let res = condition_expr(cond.as_bytes());
        let c1 = Column::from("a.foo");
        let c2 = Column::from("b.bar");
        let mut expected_cols = HashSet::new();
        expected_cols.insert(&c1);
        expected_cols.insert(&c2);
        match res.unwrap().1 {
            ConditionExpression::LogicalOp(ct) => {
                assert_eq!(ct.contained_columns(), expected_cols);
            }
            _ => panic!(),
        }
    }

    #[test]
    fn equality_placeholder() {
        let cond = "foo = ?";

        let res = condition_expr(cond.as_bytes());
        assert_eq!(
            res.unwrap().1,
            flat_condition_tree(
                Operator::Equal,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Placeholder
            )
        );
    }

    #[test]
    fn equality_literals() {
        let cond1 = "foo = 42";
        let cond2 = "foo = \"hello\"";

        let res1 = condition_expr(cond1.as_bytes());
        assert_eq!(
            res1.unwrap().1,
            flat_condition_tree(
                Operator::Equal,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::Integer(42 as i64))
            )
        );

        let res2 = condition_expr(cond2.as_bytes());
        assert_eq!(
            res2.unwrap().1,
            flat_condition_tree(
                Operator::Equal,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::String(String::from("hello")))
            )
        );
    }

    #[test]
    fn inequality_literals() {
        let cond1 = "foo >= 42";
        let cond2 = "foo <= 5";

        let res1 = condition_expr(cond1.as_bytes());
        assert_eq!(
            res1.unwrap().1,
            flat_condition_tree(
                Operator::GreaterOrEqual,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::Integer(42 as i64))
            )
        );

        let res2 = condition_expr(cond2.as_bytes());
        assert_eq!(
            res2.unwrap().1,
            flat_condition_tree(
                Operator::LessOrEqual,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::Integer(5 as i64))
            )
        );
    }

    #[test]
    fn empty_string_literal() {
        let cond = "foo = ''";

        let res = condition_expr(cond.as_bytes());
        assert_eq!(
            res.unwrap().1,
            flat_condition_tree(
                Operator::Equal,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::String(String::from("")))
            )
        );
    }

    #[test]
    fn parenthesis() {
        let cond = "(foo = ? or bar = 12) and foobar = 'a'";

        use ConditionExpression::*;
        use ConditionBase::*;
        use common::Literal;

        let a = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foo".into()))),
            right: Box::new(Base(Placeholder)),
        });

        let b = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("bar".into()))),
            right: Box::new(Base(Literal(Literal::Integer(12.into())))),
        });

        let left = LogicalOp(ConditionTree {
            operator: Operator::Or,
            left: Box::new(a),
            right: Box::new(b),
        });

        let right = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foobar".into()))),
            right: Box::new(Base(Literal(Literal::String("a".into())))),
        });

        let complete = LogicalOp(ConditionTree {
            operator: Operator::And,
            left: Box::new(left),
            right: Box::new(right),
        });

        let res = condition_expr(cond.as_bytes());
        assert_eq!(res.unwrap().1, complete);
    }

    #[test]
    fn order_of_operations() {
        let cond = "foo = ? and bar = 12 or foobar = 'a'";

        use ConditionExpression::*;
        use ConditionBase::*;
        use common::Literal;

        let a = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foo".into()))),
            right: Box::new(Base(Placeholder)),
        });

        let b = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("bar".into()))),
            right: Box::new(Base(Literal(Literal::Integer(12.into())))),
        });

        let left = LogicalOp(ConditionTree {
            operator: Operator::And,
            left: Box::new(a),
            right: Box::new(b),
        });

        let right = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foobar".into()))),
            right: Box::new(Base(Literal(Literal::String("a".into())))),
        });

        let complete = LogicalOp(ConditionTree {
            operator: Operator::Or,
            left: Box::new(left),
            right: Box::new(right),
        });

        let res = condition_expr(cond.as_bytes());
        assert_eq!(res.unwrap().1, complete);
    }

    #[test]
    fn negation() {
        let cond = "not bar = 12 or foobar = 'a'";

        use ConditionExpression::*;
        use ConditionBase::*;
        use common::Literal::*;

        let left = NegationOp(Box::new(ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("bar".into()))),
            right: Box::new(Base(Literal(Integer(12.into())))),
        })));

        let right = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foobar".into()))),
            right: Box::new(Base(Literal(String("a".into())))),
        });

        let complete = LogicalOp(ConditionTree {
            operator: Operator::Or,
            left: Box::new(left),
            right: Box::new(right),
        });

        let res = condition_expr(cond.as_bytes());
        assert_eq!(res.unwrap().1, complete);
    }

    #[test]
    fn nested_select() {
        use select::SelectStatement;
        use table::Table;
        use ConditionBase::*;
        use std::default::Default;

        let cond = "bar in (select col from foo)";

        let res = condition_expr(cond.as_bytes());

        let nested_select = Box::new(SelectStatement {
            tables: vec![Table::from("foo")],
            fields: columns(&["col"]),
            ..Default::default()
        });

        let expected = flat_condition_tree(
            Operator::In,
            Field("bar".into()),
            NestedSelect(nested_select),
        );

        assert_eq!(res.unwrap().1, expected);
    }

    #[test]
    fn and_with_nested_select() {
        use select::SelectStatement;
        use table::Table;
        use ConditionBase::*;
        use std::default::Default;

        let cond = "paperId in (select paperId from PaperConflict) and size > 0";

        let res = condition_expr(cond.as_bytes());

        let nested_select = Box::new(SelectStatement {
            tables: vec![Table::from("PaperConflict")],
            fields: columns(&["paperId"]),
            ..Default::default()
        });

        let left = flat_condition_tree(
            Operator::In,
            Field("paperId".into()),
            NestedSelect(nested_select),
        );

        let right = flat_condition_tree(Operator::Greater, Field("size".into()), Literal(0.into()));

        let expected = ConditionExpression::LogicalOp(ConditionTree {
            left: Box::new(left),
            right: Box::new(right),
            operator: Operator::And,
        });

        assert_eq!(res.unwrap().1, expected);
    }

}
<commit_msg>Rudimentary support for IN over list of literals<commit_after>use nom::multispace;
use std::collections::{HashSet, VecDeque};
use std::str;
use std::fmt;

use column::Column;
use common::{binary_comparison_operator, column_identifier, integer_literal, opt_multispace,
             string_literal, value_list, Literal, Operator};

use select::{nested_selection, SelectStatement};

#[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
pub enum ConditionBase {
    Field(Column),
    Literal(Literal),
    Placeholder,
    NestedSelect(Box<SelectStatement>),
}

impl fmt::Display for ConditionBase {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ConditionBase::Field(ref col) => write!(f, "{}", col),
            ConditionBase::Literal(ref literal) => write!(f, "{}", literal.to_string()),
            ConditionBase::Placeholder => write!(f, "?"),
            ConditionBase::NestedSelect(ref select) => write!(f, "{}", select),
        }
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
pub struct ConditionTree {
    pub operator: Operator,
    pub left: Box<ConditionExpression>,
    pub right: Box<ConditionExpression>,
}

impl<'a> ConditionTree {
    pub fn contained_columns(&'a self) -> HashSet<&'a Column> {
        let mut s = HashSet::new();
        let mut q = VecDeque::<&'a ConditionTree>::new();
        q.push_back(self);
        while let Some(ref ct) = q.pop_front() {
            match *ct.left.as_ref() {
                ConditionExpression::Base(ConditionBase::Field(ref c)) => {
                    s.insert(c);
                }
                ConditionExpression::LogicalOp(ref ct)
                | ConditionExpression::ComparisonOp(ref ct) => q.push_back(ct),
                _ => (),
            }
            match *ct.right.as_ref() {
                ConditionExpression::Base(ConditionBase::Field(ref c)) => {
                    s.insert(c);
                }
                ConditionExpression::LogicalOp(ref ct)
                | ConditionExpression::ComparisonOp(ref ct) => q.push_back(ct),
                _ => (),
            }
        }
        s
    }
}

impl fmt::Display for ConditionTree {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{}", self.left)?;
        write!(f, " {} ", self.operator)?;
        write!(f, "{}", self.right)
    }
}

#[derive(Clone, Debug, Hash, PartialEq, Serialize, Deserialize)]
pub enum ConditionExpression {
    ComparisonOp(ConditionTree),
    LogicalOp(ConditionTree),
    NegationOp(Box<ConditionExpression>),
    Base(ConditionBase),
}

impl fmt::Display for ConditionExpression {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            ConditionExpression::ComparisonOp(ref tree) => write!(f, "{}", tree),
            ConditionExpression::LogicalOp(ref tree) => write!(f, "{}", tree),
            ConditionExpression::NegationOp(ref expr) => write!(f, "NOT {}", expr),
            ConditionExpression::Base(ref base) => write!(f, "{}", base),
        }
    }
}

/// Parse a conditional expression into a condition tree structure
named!(pub condition_expr<&[u8], ConditionExpression>,
       alt_complete!(
           do_parse!(
               left: and_expr >>
               opt_multispace >>
               tag_no_case!("or") >>
               multispace >>
               right: condition_expr >>
               (ConditionExpression::LogicalOp(
                   ConditionTree {
                       operator: Operator::Or,
                       left: Box::new(left),
                       right: Box::new(right),
                   }
               ))
           )
       |   and_expr)
);

named!(pub and_expr<&[u8], ConditionExpression>,
       alt_complete!(
           do_parse!(
               left: parenthetical_expr >>
               opt_multispace >>
               tag_no_case!("and") >>
               multispace >>
               right: and_expr >>
               (ConditionExpression::LogicalOp(
                   ConditionTree {
                       operator: Operator::And,
                       left: Box::new(left),
                       right: Box::new(right),
                   }
               ))
           )
       |   parenthetical_expr)
);

named!(pub parenthetical_expr<&[u8], ConditionExpression>,
       alt_complete!(
           delimited!(
               do_parse!(tag!("(") >> opt_multispace >> ()),
               condition_expr,
               do_parse!(opt_multispace >> tag!(")") >> opt_multispace >> ())
            )
       |   not_expr)
);

named!(pub not_expr<&[u8], ConditionExpression>,
       alt_complete!(
           do_parse!(
               tag_no_case!("not") >>
               multispace >>
               right: parenthetical_expr >>
               (ConditionExpression::NegationOp(Box::new(right)))
           )
       |   boolean_primary)
);

named!(boolean_primary<&[u8], ConditionExpression>,
    alt_complete!(
        do_parse!(
            left: predicate >>
            opt_multispace >>
            op: binary_comparison_operator >>
            opt_multispace >>
            right: predicate >>
            (ConditionExpression::ComparisonOp(
                ConditionTree {
                    operator: op,
                    left: Box::new(left),
                    right: Box::new(right),
                }
            ))
        )
        | predicate)
);

named!(predicate<&[u8], ConditionExpression>,
    dbg_dmp!(do_parse!(
        left: simple_expr >>
        op_right: opt!(
            alt_complete!(
                  do_parse!(
                      neg: opt!(preceded!(opt_multispace, tag_no_case!("not"))) >>
                      multispace >>
                      tag_no_case!("in") >>
                      multispace >>
                      sq: nested_selection >>
                      (ConditionExpression::Base(ConditionBase::NestedSelect(Box::new(sq))))
                  )
                | do_parse!(
                      neg: opt!(preceded!(opt_multispace, tag_no_case!("not"))) >>
                      multispace >>
                      tag_no_case!("in") >>
                      multispace >>
                      vl: delimited!(tag!("("), value_list, tag!(")")) >>
                      // XXX(malte): incorrect -- don't just return first element!
                      (ConditionExpression::Base(ConditionBase::Literal(vl[0].clone())))
                  )
            )
        ) >>
        (match op_right {
            Some(right) => ConditionExpression::ComparisonOp(
                ConditionTree {
                    operator: Operator::In,
                    left: Box::new(left),
                    right: Box::new(right),
                }),
            None => left,
        })
    ))
);

named!(simple_expr<&[u8], ConditionExpression>,
    alt_complete!(
            do_parse!(
                tag!("?") >>
                (ConditionExpression::Base(
                    ConditionBase::Placeholder
                ))
            )
        |   do_parse!(
                field: integer_literal >>
                (ConditionExpression::Base(ConditionBase::Literal(field)))
            )
        |   do_parse!(
                field: string_literal >>
                (ConditionExpression::Base(ConditionBase::Literal(field)))
            )
        |   do_parse!(
                field: column_identifier >>
                (ConditionExpression::Base(
                    ConditionBase::Field(field)
                ))
            )
        |   do_parse!(
                select: delimited!(tag!("("), nested_selection, tag!(")")) >>
                (ConditionExpression::Base(
                    ConditionBase::NestedSelect(Box::new(select))
                ))
            )
    )
);

#[cfg(test)]
mod tests {
    use super::*;
    use column::Column;
    use common::{FieldExpression, Literal, Operator};

    fn columns(cols: &[&str]) -> Vec<FieldExpression> {
        cols.iter()
            .map(|c| FieldExpression::Col(Column::from(*c)))
            .collect()
    }

    fn flat_condition_tree(
        op: Operator,
        l: ConditionBase,
        r: ConditionBase,
    ) -> ConditionExpression {
        ConditionExpression::ComparisonOp(ConditionTree {
            operator: op,
            left: Box::new(ConditionExpression::Base(l)),
            right: Box::new(ConditionExpression::Base(r)),
        })
    }

    #[test]
    fn ct_contained_columns() {
        use std::collections::HashSet;

        let cond = "a.foo = ? and b.bar = 42";

        let res = condition_expr(cond.as_bytes());
        let c1 = Column::from("a.foo");
        let c2 = Column::from("b.bar");
        let mut expected_cols = HashSet::new();
        expected_cols.insert(&c1);
        expected_cols.insert(&c2);
        match res.unwrap().1 {
            ConditionExpression::LogicalOp(ct) => {
                assert_eq!(ct.contained_columns(), expected_cols);
            }
            _ => panic!(),
        }
    }

    #[test]
    fn equality_placeholder() {
        let cond = "foo = ?";

        let res = condition_expr(cond.as_bytes());
        assert_eq!(
            res.unwrap().1,
            flat_condition_tree(
                Operator::Equal,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Placeholder
            )
        );
    }

    #[test]
    fn equality_literals() {
        let cond1 = "foo = 42";
        let cond2 = "foo = \"hello\"";

        let res1 = condition_expr(cond1.as_bytes());
        assert_eq!(
            res1.unwrap().1,
            flat_condition_tree(
                Operator::Equal,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::Integer(42 as i64))
            )
        );

        let res2 = condition_expr(cond2.as_bytes());
        assert_eq!(
            res2.unwrap().1,
            flat_condition_tree(
                Operator::Equal,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::String(String::from("hello")))
            )
        );
    }

    #[test]
    fn inequality_literals() {
        let cond1 = "foo >= 42";
        let cond2 = "foo <= 5";

        let res1 = condition_expr(cond1.as_bytes());
        assert_eq!(
            res1.unwrap().1,
            flat_condition_tree(
                Operator::GreaterOrEqual,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::Integer(42 as i64))
            )
        );

        let res2 = condition_expr(cond2.as_bytes());
        assert_eq!(
            res2.unwrap().1,
            flat_condition_tree(
                Operator::LessOrEqual,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::Integer(5 as i64))
            )
        );
    }

    #[test]
    fn empty_string_literal() {
        let cond = "foo = ''";

        let res = condition_expr(cond.as_bytes());
        assert_eq!(
            res.unwrap().1,
            flat_condition_tree(
                Operator::Equal,
                ConditionBase::Field(Column::from("foo")),
                ConditionBase::Literal(Literal::String(String::from("")))
            )
        );
    }

    #[test]
    fn parenthesis() {
        let cond = "(foo = ? or bar = 12) and foobar = 'a'";

        use ConditionExpression::*;
        use ConditionBase::*;
        use common::Literal;

        let a = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foo".into()))),
            right: Box::new(Base(Placeholder)),
        });

        let b = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("bar".into()))),
            right: Box::new(Base(Literal(Literal::Integer(12.into())))),
        });

        let left = LogicalOp(ConditionTree {
            operator: Operator::Or,
            left: Box::new(a),
            right: Box::new(b),
        });

        let right = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foobar".into()))),
            right: Box::new(Base(Literal(Literal::String("a".into())))),
        });

        let complete = LogicalOp(ConditionTree {
            operator: Operator::And,
            left: Box::new(left),
            right: Box::new(right),
        });

        let res = condition_expr(cond.as_bytes());
        assert_eq!(res.unwrap().1, complete);
    }

    #[test]
    fn order_of_operations() {
        let cond = "foo = ? and bar = 12 or foobar = 'a'";

        use ConditionExpression::*;
        use ConditionBase::*;
        use common::Literal;

        let a = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foo".into()))),
            right: Box::new(Base(Placeholder)),
        });

        let b = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("bar".into()))),
            right: Box::new(Base(Literal(Literal::Integer(12.into())))),
        });

        let left = LogicalOp(ConditionTree {
            operator: Operator::And,
            left: Box::new(a),
            right: Box::new(b),
        });

        let right = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foobar".into()))),
            right: Box::new(Base(Literal(Literal::String("a".into())))),
        });

        let complete = LogicalOp(ConditionTree {
            operator: Operator::Or,
            left: Box::new(left),
            right: Box::new(right),
        });

        let res = condition_expr(cond.as_bytes());
        assert_eq!(res.unwrap().1, complete);
    }

    #[test]
    fn negation() {
        let cond = "not bar = 12 or foobar = 'a'";

        use ConditionExpression::*;
        use ConditionBase::*;
        use common::Literal::*;

        let left = NegationOp(Box::new(ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("bar".into()))),
            right: Box::new(Base(Literal(Integer(12.into())))),
        })));

        let right = ComparisonOp(ConditionTree {
            operator: Operator::Equal,
            left: Box::new(Base(Field("foobar".into()))),
            right: Box::new(Base(Literal(String("a".into())))),
        });

        let complete = LogicalOp(ConditionTree {
            operator: Operator::Or,
            left: Box::new(left),
            right: Box::new(right),
        });

        let res = condition_expr(cond.as_bytes());
        assert_eq!(res.unwrap().1, complete);
    }

    #[test]
    fn nested_select() {
        use select::SelectStatement;
        use table::Table;
        use ConditionBase::*;
        use std::default::Default;

        let cond = "bar in (select col from foo)";

        let res = condition_expr(cond.as_bytes());

        let nested_select = Box::new(SelectStatement {
            tables: vec![Table::from("foo")],
            fields: columns(&["col"]),
            ..Default::default()
        });

        let expected = flat_condition_tree(
            Operator::In,
            Field("bar".into()),
            NestedSelect(nested_select),
        );

        assert_eq!(res.unwrap().1, expected);
    }

    #[test]
    fn and_with_nested_select() {
        use select::SelectStatement;
        use table::Table;
        use ConditionBase::*;
        use std::default::Default;

        let cond = "paperId in (select paperId from PaperConflict) and size > 0";

        let res = condition_expr(cond.as_bytes());

        let nested_select = Box::new(SelectStatement {
            tables: vec![Table::from("PaperConflict")],
            fields: columns(&["paperId"]),
            ..Default::default()
        });

        let left = flat_condition_tree(
            Operator::In,
            Field("paperId".into()),
            NestedSelect(nested_select),
        );

        let right = flat_condition_tree(Operator::Greater, Field("size".into()), Literal(0.into()));

        let expected = ConditionExpression::LogicalOp(ConditionTree {
            left: Box::new(left),
            right: Box::new(right),
            operator: Operator::And,
        });

        assert_eq!(res.unwrap().1, expected);
    }

    #[test]
    fn in_list_of_values() {
        use ConditionBase::*;

        let cond = "bar in (0)";

        let res = condition_expr(cond.as_bytes());

        let expected = flat_condition_tree(Operator::In, Field("bar".into()), Literal(0.into()));

        assert_eq!(res.unwrap().1, expected);
    }
}
<|endoftext|>


<commit_before>use blake2_rfc::blake2b::{ blake2b};
use std;
use crate::preludes::from_std::*;
use std::path::MAIN_SEPARATOR;
use regex::{Regex,Captures};
use twox_hash::XxHash;
use std::hash::Hasher;

// Guidance for selecting a hash function
// Need cryptographic? Use black2b 256 or 512 and a secret seed.
// Don't fold or truncate cryptographic results; they're no longer cryptographic, and you'll get collisions.
// Need fast for short keys without nulls? FNV1a. Like djb2, it can zero out, so avoid null bytes or sequences which can cause a sticky state.
// Need fast for huge arrays? metrohash or xxhash.
//

/// This is an extremely fast non-cryptographic hash
pub fn hash_64(bytes: &[u8]) -> u64{
    // But metrohash is 20% faster and can do 128bit
    // https://github.com/arthurprs/metrohash-rs
    // So maybe we should consider that...
    let mut h = XxHash::with_seed(0x8ed1_2ad9_483d_28a0);
    h.write(bytes);
    h.finish()
}

///
/// Returns a 32-byte cryptographic hash of the given data (via Blake2b), with a null seed.
pub fn hash_256(bytes: &[u8]) -> [u8;32]{
    let mut hash: [u8;32] = [0u8;32];
    hash256_to(bytes, &mut hash);
    hash
}
fn hash256_to(bytes: &[u8], to: &mut [u8;32]){
    to.copy_from_slice(blake2b(32, &[], bytes).as_bytes());
}

pub fn legacy_djb2(bytes: &[u8]) -> u64{
    bytes.iter().fold(5381u64, |hash, c| ((hash << 5).wrapping_add(hash)).wrapping_add(u64::from(*c)))
}

/// Format string supports printing specific bit ranges in hexadecimal:
/// `{0-23:x}` will print the first 23 bits of the hash in hex - WITHOUT leading zeroes
/// `{0-256:064x}` will print all 256 bits, padded to 64 hex digits (256 bits) with zeroes
///
/// No escaping of `{` is supported.
pub fn bits_format(bits: &[u8], format: &'static str) -> String{
    lazy_static! {
      static ref RE: Regex = Regex::new(r"\{([0-9]+)-([0-9]+):(0([0-9]+))?x\}").unwrap();
    };

    RE.replace_all(format, |c: &Captures | {
        let from = c[1].parse::<usize>().unwrap();
        let until = c[2].parse::<usize>().unwrap();
        let padding = c.get(4).and_then(|f| Some(f.as_str().parse::<usize>().unwrap_or(0))).unwrap_or(0);
        if from == 0 && until == bits.len() * 8{
            format!("{:01$x}", HexableBytes(bits), padding)
        }else{
            format!("{:01$x}", bits_select(bits, from, until).expect("Formats may specify up to 57 bits or the entire range, but no range greater than 58 and less than the the whole"), padding)
        }
    }).into_owned()
}
///
/// Returns up to 57 bits from the provided byte slice, using big-endian interpretation.
pub fn bits_select(hash: &[u8], from: usize, until: usize) -> Option<u64>{
    if until > hash.len() * 8 || until < from || until - from > 57 {
        return None;
    }
    let relevant_bytes = &hash[from / 8..(until + 7) / 8];
    let truncate_right = (8 - until % 8) % 8;
    let mask = if until == from { 0 } else{ !0u64 >> (64 - (until - from)) };

    Some((relevant_bytes.iter().fold(0u64, | acc, elem| (u64::from(*elem) | (acc << 8)) ) >> truncate_right) & mask)
    //println!("bits {} to {} of {:032x} - using bytes {} to {}. Unshift {} and mask {:#016x} to produce {:x}",from, until, HexableBytes(hash), (from / 8), (until + 7) / 8, truncate_right, mask, res.unwrap());
}

/// Prints the bytes as hex, padding with zeroes
pub fn bytes_to_hex(bytes: &[u8]) -> String{
    format!("{:01$x}", HexableBytes(bytes), bytes.len() * 2)
}

/// Behavior undefined on platforms where the directory separator is not / or \
pub fn normalize_slashes(s: String) -> String {
    if MAIN_SEPARATOR == '/' && s.contains('\\') {
        s.replace("\\", "/")
    } else if MAIN_SEPARATOR == '\\' && s.contains('/') {
        s.replace("/", "\\")
    }else{
        s
    }
}

pub struct HexableBytes<'a>(pub &'a [u8]);

//impl<'a> HexableBytes<'a>{
//    pub fn wrap(bytes: &[u8]) -> HexableBytes {
//        HexableBytes(bytes)
//    }
//}

impl<'a> std::fmt::LowerHex for HexableBytes<'a> {
    fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        let mut nonzero = false;
        for (index, byte) in self.0.iter().enumerate() {
            if nonzero {
                fmtr.write_fmt(format_args!("{:02x}", byte))?;
            }else if *byte > 0{
                let pad_width = fmtr.width().and_then(|w| {
                    let a = 2 + w as i64 - (self.0.len() as i64 - index as i64) * 2;
                    if a < 2 {
                        None //At least one character will be written anyway.
                    }else{
                        Some(a)
                    }
                }).unwrap_or(0);
                fmtr.write_fmt(format_args!("{:01$x}", byte, pad_width as usize))?;
                nonzero = true;
            }
        }
        Ok(())
    }
}

#[test]
fn test_bits_format(){
    let hash = hash_256(b"perplexities");
    assert_eq!("dbf90c29d914a7e3b0756e3365e87cf05723a7df53c01dcebda066ce7a99488c", bytes_to_hex(&hash));
    assert_eq!("/c/8/8c/88/dbf90c29d914a7e3b0756e3365e87cf05723a7df53c01dcebda066ce7a99488c", bits_format(&hash, "/{252-256:x}/{248-252:x}/{248-256:x}/{244-252:x}/{0-256:064x}"));
    assert_eq!("/0c/22/4/dbf90c29d914a7e3b0756e3365e87cf05723a7df53c01dcebda066ce7a99488c", bits_format(&hash, "/{250-256:02x}/{244-250:02x}/{240-244:x}/{0-256:x}"));
}

#[test]
fn test_bits_select(){
    assert_eq!(!0u64 >> 63, 1);
    assert_eq!(None, bits_select(&[1u8;32],0, 58));
    assert_eq!(None, bits_select(&[1u8;32],240, 298));
    assert_eq!(Some(1), bits_select(&[255u8;32],255, 256));
    assert_eq!(Some(3), bits_select(&[255u8;32],254, 256));
    assert_eq!(Some(2u64.pow(57) - 1), bits_select(&[255u8;32],0, 57));
    assert_eq!(Some(2u64.pow(11) - 1), bits_select(&[255u8;32],245, 256));
}

#[test]
fn compare_byte_styles(){
    let bytes = [0, 0, 2, 1, 5, 255, 32];
    assert_eq!("20105ff20", format!("{:x}", HexableBytes(&bytes)));
    assert_eq!("20105ff20", format!("{:09x}", HexableBytes(&bytes)));
    assert_eq!("20105ff20", format!("{:08x}", HexableBytes(&bytes)));
    assert_eq!("020105ff20", format!("{:10x}", HexableBytes(&bytes)));
    assert_eq!("0020105ff20", format!("{:11x}", HexableBytes(&bytes)));
    assert_eq!("20105ff20", format!("{:x}", HexableBytes(&bytes)));
    assert_eq!("0000020105ff20", bytes_to_hex(&bytes));
    assert_eq!(bytes_to_hex(&bytes), format!("{:01$x}", HexableBytes(&bytes), bytes.len() * 2));
}
<commit_msg>spelling: the<commit_after>use blake2_rfc::blake2b::{ blake2b};
use std;
use crate::preludes::from_std::*;
use std::path::MAIN_SEPARATOR;
use regex::{Regex,Captures};
use twox_hash::XxHash;
use std::hash::Hasher;

// Guidance for selecting a hash function
// Need cryptographic? Use black2b 256 or 512 and a secret seed.
// Don't fold or truncate cryptographic results; they're no longer cryptographic, and you'll get collisions.
// Need fast for short keys without nulls? FNV1a. Like djb2, it can zero out, so avoid null bytes or sequences which can cause a sticky state.
// Need fast for huge arrays? metrohash or xxhash.
//

/// This is an extremely fast non-cryptographic hash
pub fn hash_64(bytes: &[u8]) -> u64{
    // But metrohash is 20% faster and can do 128bit
    // https://github.com/arthurprs/metrohash-rs
    // So maybe we should consider that...
    let mut h = XxHash::with_seed(0x8ed1_2ad9_483d_28a0);
    h.write(bytes);
    h.finish()
}

///
/// Returns a 32-byte cryptographic hash of the given data (via Blake2b), with a null seed.
pub fn hash_256(bytes: &[u8]) -> [u8;32]{
    let mut hash: [u8;32] = [0u8;32];
    hash256_to(bytes, &mut hash);
    hash
}
fn hash256_to(bytes: &[u8], to: &mut [u8;32]){
    to.copy_from_slice(blake2b(32, &[], bytes).as_bytes());
}

pub fn legacy_djb2(bytes: &[u8]) -> u64{
    bytes.iter().fold(5381u64, |hash, c| ((hash << 5).wrapping_add(hash)).wrapping_add(u64::from(*c)))
}

/// Format string supports printing specific bit ranges in hexadecimal:
/// `{0-23:x}` will print the first 23 bits of the hash in hex - WITHOUT leading zeroes
/// `{0-256:064x}` will print all 256 bits, padded to 64 hex digits (256 bits) with zeroes
///
/// No escaping of `{` is supported.
pub fn bits_format(bits: &[u8], format: &'static str) -> String{
    lazy_static! {
      static ref RE: Regex = Regex::new(r"\{([0-9]+)-([0-9]+):(0([0-9]+))?x\}").unwrap();
    };

    RE.replace_all(format, |c: &Captures | {
        let from = c[1].parse::<usize>().unwrap();
        let until = c[2].parse::<usize>().unwrap();
        let padding = c.get(4).and_then(|f| Some(f.as_str().parse::<usize>().unwrap_or(0))).unwrap_or(0);
        if from == 0 && until == bits.len() * 8{
            format!("{:01$x}", HexableBytes(bits), padding)
        }else{
            format!("{:01$x}", bits_select(bits, from, until).expect("Formats may specify up to 57 bits or the entire range, but no range greater than 58 and less than the whole"), padding)
        }
    }).into_owned()
}
///
/// Returns up to 57 bits from the provided byte slice, using big-endian interpretation.
pub fn bits_select(hash: &[u8], from: usize, until: usize) -> Option<u64>{
    if until > hash.len() * 8 || until < from || until - from > 57 {
        return None;
    }
    let relevant_bytes = &hash[from / 8..(until + 7) / 8];
    let truncate_right = (8 - until % 8) % 8;
    let mask = if until == from { 0 } else{ !0u64 >> (64 - (until - from)) };

    Some((relevant_bytes.iter().fold(0u64, | acc, elem| (u64::from(*elem) | (acc << 8)) ) >> truncate_right) & mask)
    //println!("bits {} to {} of {:032x} - using bytes {} to {}. Unshift {} and mask {:#016x} to produce {:x}",from, until, HexableBytes(hash), (from / 8), (until + 7) / 8, truncate_right, mask, res.unwrap());
}

/// Prints the bytes as hex, padding with zeroes
pub fn bytes_to_hex(bytes: &[u8]) -> String{
    format!("{:01$x}", HexableBytes(bytes), bytes.len() * 2)
}

/// Behavior undefined on platforms where the directory separator is not / or \
pub fn normalize_slashes(s: String) -> String {
    if MAIN_SEPARATOR == '/' && s.contains('\\') {
        s.replace("\\", "/")
    } else if MAIN_SEPARATOR == '\\' && s.contains('/') {
        s.replace("/", "\\")
    }else{
        s
    }
}

pub struct HexableBytes<'a>(pub &'a [u8]);

//impl<'a> HexableBytes<'a>{
//    pub fn wrap(bytes: &[u8]) -> HexableBytes {
//        HexableBytes(bytes)
//    }
//}

impl<'a> std::fmt::LowerHex for HexableBytes<'a> {
    fn fmt(&self, fmtr: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
        let mut nonzero = false;
        for (index, byte) in self.0.iter().enumerate() {
            if nonzero {
                fmtr.write_fmt(format_args!("{:02x}", byte))?;
            }else if *byte > 0{
                let pad_width = fmtr.width().and_then(|w| {
                    let a = 2 + w as i64 - (self.0.len() as i64 - index as i64) * 2;
                    if a < 2 {
                        None //At least one character will be written anyway.
                    }else{
                        Some(a)
                    }
                }).unwrap_or(0);
                fmtr.write_fmt(format_args!("{:01$x}", byte, pad_width as usize))?;
                nonzero = true;
            }
        }
        Ok(())
    }
}

#[test]
fn test_bits_format(){
    let hash = hash_256(b"perplexities");
    assert_eq!("dbf90c29d914a7e3b0756e3365e87cf05723a7df53c01dcebda066ce7a99488c", bytes_to_hex(&hash));
    assert_eq!("/c/8/8c/88/dbf90c29d914a7e3b0756e3365e87cf05723a7df53c01dcebda066ce7a99488c", bits_format(&hash, "/{252-256:x}/{248-252:x}/{248-256:x}/{244-252:x}/{0-256:064x}"));
    assert_eq!("/0c/22/4/dbf90c29d914a7e3b0756e3365e87cf05723a7df53c01dcebda066ce7a99488c", bits_format(&hash, "/{250-256:02x}/{244-250:02x}/{240-244:x}/{0-256:x}"));
}

#[test]
fn test_bits_select(){
    assert_eq!(!0u64 >> 63, 1);
    assert_eq!(None, bits_select(&[1u8;32],0, 58));
    assert_eq!(None, bits_select(&[1u8;32],240, 298));
    assert_eq!(Some(1), bits_select(&[255u8;32],255, 256));
    assert_eq!(Some(3), bits_select(&[255u8;32],254, 256));
    assert_eq!(Some(2u64.pow(57) - 1), bits_select(&[255u8;32],0, 57));
    assert_eq!(Some(2u64.pow(11) - 1), bits_select(&[255u8;32],245, 256));
}

#[test]
fn compare_byte_styles(){
    let bytes = [0, 0, 2, 1, 5, 255, 32];
    assert_eq!("20105ff20", format!("{:x}", HexableBytes(&bytes)));
    assert_eq!("20105ff20", format!("{:09x}", HexableBytes(&bytes)));
    assert_eq!("20105ff20", format!("{:08x}", HexableBytes(&bytes)));
    assert_eq!("020105ff20", format!("{:10x}", HexableBytes(&bytes)));
    assert_eq!("0020105ff20", format!("{:11x}", HexableBytes(&bytes)));
    assert_eq!("20105ff20", format!("{:x}", HexableBytes(&bytes)));
    assert_eq!("0000020105ff20", bytes_to_hex(&bytes));
    assert_eq!(bytes_to_hex(&bytes), format!("{:01$x}", HexableBytes(&bytes), bytes.len() * 2));
}
<|endoftext|>


<commit_before>//! Serde `Deserializer` module

use crate::{errors::serialize::DeError, errors::Error, escape::unescape, reader::Decoder};
use serde::de::{self, Visitor};
use serde::{self, forward_to_deserialize_any};
use std::borrow::Cow;

/// A deserializer for a xml escaped and encoded value
///
/// # Note
///
/// Escaping the value is actually not always necessary, for instance
/// when converting to float, we don't expect any escapable character
/// anyway
#[derive(Clone, Debug)]
pub(crate) struct EscapedDeserializer {
    decoder: Decoder,
    /// Possible escaped value of text/CDATA or attribute value
    escaped_value: Vec<u8>,
    /// If `true`, value requires unescaping before using
    escaped: bool,
}

impl EscapedDeserializer {
    pub fn new(escaped_value: Vec<u8>, decoder: Decoder, escaped: bool) -> Self {
        EscapedDeserializer {
            decoder,
            escaped_value,
            escaped,
        }
    }
    fn unescaped(&self) -> Result<Cow<[u8]>, DeError> {
        if self.escaped {
            unescape(&self.escaped_value).map_err(|e| DeError::Xml(Error::EscapeError(e)))
        } else {
            Ok(Cow::Borrowed(&self.escaped_value))
        }
    }
}

macro_rules! deserialize_num {
    ($method:ident, $visit:ident) => {
        fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
        where
            V: Visitor<'de>,
        {
            #[cfg(not(feature = "encoding"))]
            let value = self.decoder.decode(&self.escaped_value)?.parse()?;

            #[cfg(feature = "encoding")]
            let value = self.decoder.decode(&self.escaped_value).parse()?;

            visitor.$visit(value)
        }
    };
}

impl<'de> serde::Deserializer<'de> for EscapedDeserializer {
    type Error = DeError;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        self.deserialize_str(visitor)
    }

    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        let unescaped = self.unescaped()?;
        #[cfg(not(feature = "encoding"))]
        let value = self.decoder.decode(&unescaped)?;

        #[cfg(feature = "encoding")]
        let value = self.decoder.decode(&unescaped);
        visitor.visit_str(&value)
    }

    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        let v = self.unescaped()?;
        visitor.visit_bytes(&v)
    }

    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        self.deserialize_bytes(visitor)
    }

    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        self.deserialize_str(visitor)
    }

    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        #[cfg(feature = "encoding")]
        {
            #[cfg(feature = "encoding")]
            let value = self.decoder.decode(&self.escaped_value);

            match value.as_ref() {
                "true" | "1" | "True" | "TRUE" | "t" | "Yes" | "YES" | "yes" | "y" => {
                    visitor.visit_bool(true)
                }
                "false" | "0" | "False" | "FALSE" | "f" | "No" | "NO" | "no" | "n" => {
                    visitor.visit_bool(false)
                }
                _ => Err(DeError::InvalidBoolean(value.into())),
            }
        }

        #[cfg(not(feature = "encoding"))]
        {
            match &*self.escaped_value {
                b"true" | b"1" | b"True" | b"TRUE" | b"t" | b"Yes" | b"YES" | b"yes" | b"y" => {
                    visitor.visit_bool(true)
                }
                b"false" | b"0" | b"False" | b"FALSE" | b"f" | b"No" | b"NO" | b"no" | b"n" => {
                    visitor.visit_bool(false)
                }
                e => Err(DeError::InvalidBoolean(self.decoder.decode(e)?.into())),
            }
        }
    }

    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        self.deserialize_str(visitor)
    }

    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        if self.escaped_value.is_empty() {
            visitor.visit_unit()
        } else {
            Err(DeError::InvalidUnit(
                "Expecting unit, got non empty attribute".into(),
            ))
        }
    }

    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        if self.escaped_value.is_empty() {
            visitor.visit_none()
        } else {
            visitor.visit_some(self)
        }
    }

    fn deserialize_enum<V: de::Visitor<'de>>(
        self,
        _name: &str,
        _variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_enum(self)
    }

    fn deserialize_newtype_struct<V>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        visitor.visit_newtype_struct(self)
    }

    deserialize_num!(deserialize_i64, visit_i64);
    deserialize_num!(deserialize_i32, visit_i32);
    deserialize_num!(deserialize_i16, visit_i16);
    deserialize_num!(deserialize_i8, visit_i8);
    deserialize_num!(deserialize_u64, visit_u64);
    deserialize_num!(deserialize_u32, visit_u32);
    deserialize_num!(deserialize_u16, visit_u16);
    deserialize_num!(deserialize_u8, visit_u8);
    deserialize_num!(deserialize_f64, visit_f64);
    deserialize_num!(deserialize_f32, visit_f32);

    forward_to_deserialize_any! {
        unit_struct seq tuple tuple_struct map struct identifier ignored_any
    }
}

impl<'de> de::EnumAccess<'de> for EscapedDeserializer {
    type Error = DeError;
    type Variant = Self;

    fn variant_seed<V: de::DeserializeSeed<'de>>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self), DeError> {
        let name = seed.deserialize(self.clone())?;
        Ok((name, self))
    }
}

impl<'de> de::VariantAccess<'de> for EscapedDeserializer {
    type Error = DeError;

    fn unit_variant(self) -> Result<(), DeError> {
        Ok(())
    }

    fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(
        self,
        seed: T,
    ) -> Result<T::Value, DeError> {
        seed.deserialize(self)
    }

    fn tuple_variant<V: de::Visitor<'de>>(
        self,
        _len: usize,
        _visitor: V,
    ) -> Result<V::Value, DeError> {
        unimplemented!()
    }

    fn struct_variant<V: de::Visitor<'de>>(
        self,
        _fields: &'static [&'static str],
        _visitor: V,
    ) -> Result<V::Value, DeError> {
        unimplemented!()
    }
}
<commit_msg>Allow deserialization of unit from any escaped value.<commit_after>//! Serde `Deserializer` module

use crate::{errors::serialize::DeError, errors::Error, escape::unescape, reader::Decoder};
use serde::de::{self, Visitor};
use serde::{self, forward_to_deserialize_any};
use std::borrow::Cow;

/// A deserializer for a xml escaped and encoded value
///
/// # Note
///
/// Escaping the value is actually not always necessary, for instance
/// when converting to float, we don't expect any escapable character
/// anyway
#[derive(Clone, Debug)]
pub(crate) struct EscapedDeserializer {
    decoder: Decoder,
    /// Possible escaped value of text/CDATA or attribute value
    escaped_value: Vec<u8>,
    /// If `true`, value requires unescaping before using
    escaped: bool,
}

impl EscapedDeserializer {
    pub fn new(escaped_value: Vec<u8>, decoder: Decoder, escaped: bool) -> Self {
        EscapedDeserializer {
            decoder,
            escaped_value,
            escaped,
        }
    }
    fn unescaped(&self) -> Result<Cow<[u8]>, DeError> {
        if self.escaped {
            unescape(&self.escaped_value).map_err(|e| DeError::Xml(Error::EscapeError(e)))
        } else {
            Ok(Cow::Borrowed(&self.escaped_value))
        }
    }
}

macro_rules! deserialize_num {
    ($method:ident, $visit:ident) => {
        fn $method<V>(self, visitor: V) -> Result<V::Value, Self::Error>
        where
            V: Visitor<'de>,
        {
            #[cfg(not(feature = "encoding"))]
            let value = self.decoder.decode(&self.escaped_value)?.parse()?;

            #[cfg(feature = "encoding")]
            let value = self.decoder.decode(&self.escaped_value).parse()?;

            visitor.$visit(value)
        }
    };
}

impl<'de> serde::Deserializer<'de> for EscapedDeserializer {
    type Error = DeError;

    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        self.deserialize_str(visitor)
    }

    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        let unescaped = self.unescaped()?;
        #[cfg(not(feature = "encoding"))]
        let value = self.decoder.decode(&unescaped)?;

        #[cfg(feature = "encoding")]
        let value = self.decoder.decode(&unescaped);
        visitor.visit_str(&value)
    }

    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        let v = self.unescaped()?;
        visitor.visit_bytes(&v)
    }

    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        self.deserialize_bytes(visitor)
    }

    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        self.deserialize_str(visitor)
    }

    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        #[cfg(feature = "encoding")]
        {
            #[cfg(feature = "encoding")]
            let value = self.decoder.decode(&self.escaped_value);

            match value.as_ref() {
                "true" | "1" | "True" | "TRUE" | "t" | "Yes" | "YES" | "yes" | "y" => {
                    visitor.visit_bool(true)
                }
                "false" | "0" | "False" | "FALSE" | "f" | "No" | "NO" | "no" | "n" => {
                    visitor.visit_bool(false)
                }
                _ => Err(DeError::InvalidBoolean(value.into())),
            }
        }

        #[cfg(not(feature = "encoding"))]
        {
            match &*self.escaped_value {
                b"true" | b"1" | b"True" | b"TRUE" | b"t" | b"Yes" | b"YES" | b"yes" | b"y" => {
                    visitor.visit_bool(true)
                }
                b"false" | b"0" | b"False" | b"FALSE" | b"f" | b"No" | b"NO" | b"no" | b"n" => {
                    visitor.visit_bool(false)
                }
                e => Err(DeError::InvalidBoolean(self.decoder.decode(e)?.into())),
            }
        }
    }

    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        self.deserialize_str(visitor)
    }

    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        visitor.visit_unit()
    }

    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        if self.escaped_value.is_empty() {
            visitor.visit_none()
        } else {
            visitor.visit_some(self)
        }
    }

    fn deserialize_enum<V: de::Visitor<'de>>(
        self,
        _name: &str,
        _variants: &'static [&'static str],
        visitor: V,
    ) -> Result<V::Value, Self::Error> {
        visitor.visit_enum(self)
    }

    fn deserialize_newtype_struct<V>(
        self,
        _name: &'static str,
        visitor: V,
    ) -> Result<V::Value, Self::Error>
    where
        V: Visitor<'de>,
    {
        visitor.visit_newtype_struct(self)
    }

    deserialize_num!(deserialize_i64, visit_i64);
    deserialize_num!(deserialize_i32, visit_i32);
    deserialize_num!(deserialize_i16, visit_i16);
    deserialize_num!(deserialize_i8, visit_i8);
    deserialize_num!(deserialize_u64, visit_u64);
    deserialize_num!(deserialize_u32, visit_u32);
    deserialize_num!(deserialize_u16, visit_u16);
    deserialize_num!(deserialize_u8, visit_u8);
    deserialize_num!(deserialize_f64, visit_f64);
    deserialize_num!(deserialize_f32, visit_f32);

    forward_to_deserialize_any! {
        unit_struct seq tuple tuple_struct map struct identifier ignored_any
    }
}

impl<'de> de::EnumAccess<'de> for EscapedDeserializer {
    type Error = DeError;
    type Variant = Self;

    fn variant_seed<V: de::DeserializeSeed<'de>>(
        self,
        seed: V,
    ) -> Result<(V::Value, Self), DeError> {
        let name = seed.deserialize(self.clone())?;
        Ok((name, self))
    }
}

impl<'de> de::VariantAccess<'de> for EscapedDeserializer {
    type Error = DeError;

    fn unit_variant(self) -> Result<(), DeError> {
        Ok(())
    }

    fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(
        self,
        seed: T,
    ) -> Result<T::Value, DeError> {
        seed.deserialize(self)
    }

    fn tuple_variant<V: de::Visitor<'de>>(
        self,
        _len: usize,
        _visitor: V,
    ) -> Result<V::Value, DeError> {
        unimplemented!()
    }

    fn struct_variant<V: de::Visitor<'de>>(
        self,
        _fields: &'static [&'static str],
        _visitor: V,
    ) -> Result<V::Value, DeError> {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>extern crate sfunc;

use std::rand::Rng;
use std::rand::distributions::{Gamma, IndependentSample};

use super::Distribution;

/// A beta distribution.
pub struct Beta {
    /// The first shape parameter.
    pub alpha: f64,
    /// The second shape parameter.
    pub beta: f64,
    /// The left endpoint of the support.
    pub a: f64,
    /// The right endpoint of the support.
    pub b: f64,

    ln_beta: f64,
    gamma_alpha: Gamma,
    gamma_beta: Gamma,
}

impl Beta {
    /// Creates a beta distribution with the shape parameters `alpha` and
    /// `beta` on the interval `[a, b]`.
    #[inline]
    pub fn new(alpha: f64, beta: f64, a: f64, b: f64) -> Beta {
        Beta {
            alpha: alpha,
            beta: beta,
            a: a,
            b: b,
            ln_beta: sfunc::ln_beta(alpha, beta),
            gamma_alpha: Gamma::new(alpha, 1.0),
            gamma_beta: Gamma::new(beta, 1.0),
        }
    }
}

impl Distribution<f64> for Beta {
    #[inline]
    fn cdf(&self, x: f64) -> f64 {
        use self::sfunc::inc_beta;
        inc_beta((x - self.a) / (self.b - self.a), self.alpha, self.beta, self.ln_beta)
    }

    #[inline]
    fn inv_cdf(&self, p: f64) -> f64 {
        use self::sfunc::inv_inc_beta;
        self.a + (self.b - self.a) * inv_inc_beta(p, self.alpha, self.beta, self.ln_beta)
    }

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let x = self.gamma_alpha.ind_sample(rng);
        let y = self.gamma_beta.ind_sample(rng);
        self.a + (self.b - self.a) * x / (x + y)
    }
}

#[cfg(test)]
mod test {
    use super::super::{Distribution, Sampler};
    use super::Beta;

    macro_rules! assert_almost_eq(
        ($x:expr, $y:expr) => ({
            let e: f64 = ::std::f64::EPSILON.sqrt();
            let x: Vec<f64> = $x;
            let y: Vec<f64> = $y;
            for i in range(0u, x.len()) {
                assert!(::std::num::abs(x[i] - y[i]) < e,
                        "expected {:e} ~ {:e}", x[i], y[i]);
            }
        });
    )

    #[test]
    fn cdf() {
        let dist = Beta::new(2.0, 3.0, -1.0, 2.0);

        let x = vec![-1.00, -0.85, -0.70, -0.55, -0.40, -0.25, -0.10, 0.05,
                     0.20, 0.35, 0.50, 0.65, 0.80, 0.95, 1.10, 1.25, 1.40,
                     1.55, 1.70, 1.85, 2.00];
        let p = vec![0.000000000000000e+00, 1.401875000000000e-02,
                     5.230000000000002e-02, 1.095187500000000e-01,
                     1.807999999999999e-01, 2.617187500000001e-01,
                     3.483000000000000e-01, 4.370187500000001e-01,
                     5.248000000000003e-01, 6.090187500000001e-01,
                     6.875000000000000e-01, 7.585187500000001e-01,
                     8.208000000000000e-01, 8.735187499999999e-01,
                     9.163000000000000e-01, 9.492187500000000e-01,
                     9.728000000000000e-01, 9.880187500000001e-01,
                     9.963000000000000e-01, 9.995187500000000e-01,
                     1.000000000000000e+00];

        assert_almost_eq!(x.iter().map(|&x| dist.cdf(x)).collect(), p);
    }

    #[test]
    fn inv_cdf() {
        let dist = Beta::new(1.0, 2.0, 3.0, 4.0);

        let p = vec![0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40,
                     0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85,
                     0.90, 0.95, 1.00];
        let x = vec![3.000000000000000e+00, 3.025320565519104e+00,
                     3.051316701949486e+00, 3.078045554270711e+00,
                     3.105572809000084e+00, 3.133974596215561e+00,
                     3.163339973465924e+00, 3.193774225170145e+00,
                     3.225403330758517e+00, 3.258380151290432e+00,
                     3.292893218813452e+00, 3.329179606750063e+00,
                     3.367544467966324e+00, 3.408392021690038e+00,
                     3.452277442494834e+00, 3.500000000000000e+00,
                     3.552786404500042e+00, 3.612701665379257e+00,
                     3.683772233983162e+00, 3.776393202250021e+00,
                     4.000000000000000e+00];

        assert_almost_eq!(p.iter().map(|&p| dist.inv_cdf(p)).collect(), x);
    }

    #[test]
    fn sample() {
        let mut rng = ::std::rand::task_rng();
        for x in Sampler(&Beta::new(1.0, 2.0, 7.0, 42.0), &mut rng).take(100) {
            assert!(7.0 <= x && x <= 42.0);
        }
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use std::rand::random;

    use super::super::Distribution;
    use super::Beta;

    #[bench]
    fn cdf(bench: &mut test::Bencher) {
        let dist = Beta::new(0.5, 1.5, 0.0, 1.0);
        let x = range(0u, 1000).map(|_| random()).collect::<Vec<_>>();

        bench.iter(|| {
            test::black_box(x.iter().map(|&x| dist.cdf(x)).collect::<Vec<_>>())
        });
    }

    #[bench]
    fn inv_cdf(bench: &mut test::Bencher) {
        let dist = Beta::new(0.5, 1.5, 0.0, 1.0);
        let p = range(0u, 1000).map(|_| random()).collect::<Vec<_>>();

        bench.iter(|| {
            test::black_box(p.iter().map(|&p| dist.inv_cdf(p)).collect::<Vec<_>>())
        });
    }
}
<commit_msg>Simplified the benchmarks a bit more<commit_after>extern crate sfunc;

use std::rand::Rng;
use std::rand::distributions::{Gamma, IndependentSample};

use super::Distribution;

/// A beta distribution.
pub struct Beta {
    /// The first shape parameter.
    pub alpha: f64,
    /// The second shape parameter.
    pub beta: f64,
    /// The left endpoint of the support.
    pub a: f64,
    /// The right endpoint of the support.
    pub b: f64,

    ln_beta: f64,
    gamma_alpha: Gamma,
    gamma_beta: Gamma,
}

impl Beta {
    /// Creates a beta distribution with the shape parameters `alpha` and
    /// `beta` on the interval `[a, b]`.
    #[inline]
    pub fn new(alpha: f64, beta: f64, a: f64, b: f64) -> Beta {
        Beta {
            alpha: alpha,
            beta: beta,
            a: a,
            b: b,
            ln_beta: sfunc::ln_beta(alpha, beta),
            gamma_alpha: Gamma::new(alpha, 1.0),
            gamma_beta: Gamma::new(beta, 1.0),
        }
    }
}

impl Distribution<f64> for Beta {
    #[inline]
    fn cdf(&self, x: f64) -> f64 {
        use self::sfunc::inc_beta;
        inc_beta((x - self.a) / (self.b - self.a), self.alpha, self.beta, self.ln_beta)
    }

    #[inline]
    fn inv_cdf(&self, p: f64) -> f64 {
        use self::sfunc::inv_inc_beta;
        self.a + (self.b - self.a) * inv_inc_beta(p, self.alpha, self.beta, self.ln_beta)
    }

    #[inline]
    fn sample<R: Rng>(&self, rng: &mut R) -> f64 {
        let x = self.gamma_alpha.ind_sample(rng);
        let y = self.gamma_beta.ind_sample(rng);
        self.a + (self.b - self.a) * x / (x + y)
    }
}

#[cfg(test)]
mod test {
    use super::super::{Distribution, Sampler};
    use super::Beta;

    macro_rules! assert_almost_eq(
        ($x:expr, $y:expr) => ({
            let e: f64 = ::std::f64::EPSILON.sqrt();
            let x: Vec<f64> = $x;
            let y: Vec<f64> = $y;
            for i in range(0u, x.len()) {
                assert!(::std::num::abs(x[i] - y[i]) < e,
                        "expected {:e} ~ {:e}", x[i], y[i]);
            }
        });
    )

    #[test]
    fn cdf() {
        let dist = Beta::new(2.0, 3.0, -1.0, 2.0);

        let x = vec![-1.00, -0.85, -0.70, -0.55, -0.40, -0.25, -0.10, 0.05,
                     0.20, 0.35, 0.50, 0.65, 0.80, 0.95, 1.10, 1.25, 1.40,
                     1.55, 1.70, 1.85, 2.00];
        let p = vec![0.000000000000000e+00, 1.401875000000000e-02,
                     5.230000000000002e-02, 1.095187500000000e-01,
                     1.807999999999999e-01, 2.617187500000001e-01,
                     3.483000000000000e-01, 4.370187500000001e-01,
                     5.248000000000003e-01, 6.090187500000001e-01,
                     6.875000000000000e-01, 7.585187500000001e-01,
                     8.208000000000000e-01, 8.735187499999999e-01,
                     9.163000000000000e-01, 9.492187500000000e-01,
                     9.728000000000000e-01, 9.880187500000001e-01,
                     9.963000000000000e-01, 9.995187500000000e-01,
                     1.000000000000000e+00];

        assert_almost_eq!(x.iter().map(|&x| dist.cdf(x)).collect(), p);
    }

    #[test]
    fn inv_cdf() {
        let dist = Beta::new(1.0, 2.0, 3.0, 4.0);

        let p = vec![0.00, 0.05, 0.10, 0.15, 0.20, 0.25, 0.30, 0.35, 0.40,
                     0.45, 0.50, 0.55, 0.60, 0.65, 0.70, 0.75, 0.80, 0.85,
                     0.90, 0.95, 1.00];
        let x = vec![3.000000000000000e+00, 3.025320565519104e+00,
                     3.051316701949486e+00, 3.078045554270711e+00,
                     3.105572809000084e+00, 3.133974596215561e+00,
                     3.163339973465924e+00, 3.193774225170145e+00,
                     3.225403330758517e+00, 3.258380151290432e+00,
                     3.292893218813452e+00, 3.329179606750063e+00,
                     3.367544467966324e+00, 3.408392021690038e+00,
                     3.452277442494834e+00, 3.500000000000000e+00,
                     3.552786404500042e+00, 3.612701665379257e+00,
                     3.683772233983162e+00, 3.776393202250021e+00,
                     4.000000000000000e+00];

        assert_almost_eq!(p.iter().map(|&p| dist.inv_cdf(p)).collect(), x);
    }

    #[test]
    fn sample() {
        let mut rng = ::std::rand::task_rng();
        for x in Sampler(&Beta::new(1.0, 2.0, 7.0, 42.0), &mut rng).take(100) {
            assert!(7.0 <= x && x <= 42.0);
        }
    }
}

#[cfg(test)]
mod bench {
    extern crate test;

    use std::rand::random;

    use super::super::Distribution;
    use super::Beta;

    #[bench]
    fn cdf(bench: &mut test::Bencher) {
        let dist = Beta::new(0.5, 1.5, 0.0, 1.0);
        let x = range(0u, 1000).map(|_| random()).collect::<Vec<_>>();

        bench.iter(|| {
            for &x in x.iter() {
                test::black_box(dist.cdf(x));
            }
        });
    }

    #[bench]
    fn inv_cdf(bench: &mut test::Bencher) {
        let dist = Beta::new(0.5, 1.5, 0.0, 1.0);
        let p = range(0u, 1000).map(|_| random()).collect::<Vec<_>>();

        bench.iter(|| {
            for &p in p.iter() {
                test::black_box(dist.inv_cdf(p));
            }
        });
    }
}
<|endoftext|>


<commit_before>use dnsresolv::DnsAnswer;
use dnsresolv::DnsType;
use std::fmt::Write;
use std::slice::Iter;

use pop_u16;

#[derive(Debug)]
/// Informations needed to download a file
pub struct Resource {
    ip: String,
    port: u16,
    user: String,
    file: String,
}

impl Resource {
    /// given a list of dns answer (PTR request) created by DnsResolv::resolv_ptr(),
    /// create a Resource object to download the file
    pub fn parse_dns(dns_answers: Vec<DnsAnswer>) -> Result<Resource, &'static str> {
        let mut ip = String::new();
        let mut user = String::new();
        let mut file = String::new();
        let mut port = 0;

        for answer in dns_answers {
            match *answer.get_type() {
                DnsType::TXT => parse_txt(answer.get_data(), &mut user, &mut file),
                DnsType::A => parse_a(answer.get_data(), &mut ip),
                DnsType::SRV => parse_srv(answer.get_data(), &mut port),
                DnsType::PTR => continue,
                DnsType::UNKNOWN => continue,
            };
        }
        let resource = Resource {
            ip,
            port,
            user,
            file,
        };
        Ok(resource)
    }
}

fn parse_txt(mut data: Iter<u8>, user: &mut String, file: &mut String) {
    while let Some(size) = data.next() {
        let mut str = String::with_capacity(*size as usize);
        for _ in 0..*size {
            str.push(*data.next().unwrap() as char);
        }
        if str.starts_with("file=") {
            *file = str.split_off(5);
        } else if str.starts_with("user=") {
            *user = str.split_off(5);
        }
    }
}

fn parse_a(mut data: Iter<u8>, ip: &mut String) {
    write!(
        ip,
        "{}.{}.{}.{}",
        data.next().unwrap(),
        data.next().unwrap(),
        data.next().unwrap(),
        data.next().unwrap()
    ).expect("cannot write");

}

fn parse_srv(data: Iter<u8>, port: &mut u16) {
    let mut data = data.skip(4);
    *port = pop_u16(&mut data);
}

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

    #[test]
    fn tst_parse_srv() {
        let v: Vec<u8> = vec![0, 0, 0, 0, 0x1f, 0x90];
        let mut port = 0;
        parse_srv(v.iter(), &mut port);
        assert_eq!(8080, port);
    }

    #[test]
    fn tst_parse_txt() {
        let v: Vec<u8> = vec![
            0x11,
            0x66,
            0x69,
            0x6c,
            0x65,
            0x3d,
            0x70,
            0x61,
            0x74,
            0x68,
            0x2f,
            0x74,
            0x6f,
            0x2f,
            0x66,
            0x69,
            0x6c,
            0x65,
            0x08,
            0x75,
            0x73,
            0x65,
            0x72,
            0x3d,
            0x63,
            0x65,
            0x64,
        ];
        let mut file = String::new();
        let mut user = String::new();
        parse_txt(v.iter(), &mut user, &mut file);
        assert_eq!("path/to/file", file);
        assert_eq!("ced", user);
    }

    #[test]
    fn tst_parse_a() {
        let v: Vec<u8> = vec![0xc0, 0xa8, 0x01, 0x02];
        let mut ip = String::new();
        parse_a(v.iter(), &mut ip);
        assert_eq!("192.168.1.2", ip);
    }
}
<commit_msg>use return tuple for parse_{srv,txt,a}<commit_after>use dnsresolv::DnsAnswer;
use dnsresolv::DnsType;
use std::fmt::Write;
use std::slice::Iter;

use pop_u16;

#[derive(Debug)]
/// Informations needed to download a file
pub struct Resource {
    ip: String,
    port: u16,
    user: String,
    file: String,
}

impl Resource {
    /// given a list of dns answer (PTR request) created by DnsResolv::resolv_ptr(),
    /// create a Resource object to download the file
    pub fn parse_dns(dns_answers: Vec<DnsAnswer>) -> Result<Resource, &'static str> {
        let mut ip = String::new();
        let mut user = String::new();
        let mut file = String::new();
        let mut port = 0;

        for answer in dns_answers {
            match *answer.get_type() {
                DnsType::TXT => {
                    let (f, u) = parse_txt(answer.get_data());
                    file = f;
                    user = u;
                },
                DnsAnswer::A(data) => {
                    ip = parse_a(Cursor::new(data))?;
                }
                DnsType::SRV => {
                    port = parse_srv(answer.get_data());
                }
                DnsType::PTR => continue,
                DnsType::UNKNOWN => continue,
            };
        }
        let resource = Resource {
            ip,
            port,
            user,
            file,
        };
        Ok(resource)
    }
}

fn parse_txt(mut data: Iter<u8>) -> (String, String) {
    let mut file = String::new();
    let mut user = String::new();

    while let Some(size) = data.next() {
        let mut str = String::with_capacity(*size as usize);
        for _ in 0..*size {
            str.push(*data.next().unwrap() as char);
        }
        if str.starts_with("file=") {
            file = str.split_off(5);
        } else if str.starts_with("user=") {
            user = str.split_off(5);
        }
    }
    (file, user)
}

fn parse_a(mut data: Iter<u8>) -> String {
    let mut ip = String::new();
    write!(
        ip,
        "{}.{}.{}.{}",
        data.next().unwrap(),
        data.next().unwrap(),
        data.next().unwrap(),
        data.next().unwrap()
    ).expect("cannot write");
    ip
}

fn parse_srv(data: Iter<u8>) -> u16 {
    let port;
    let mut data = data.skip(4);
    port = pop_u16(&mut data);
    port
}

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

    #[test]
    fn tst_parse_srv() {
        let v: Vec<u8> = vec![0, 0, 0, 0, 0x1f, 0x90];
        let port = parse_srv(v.iter());
        assert_eq!(8080, port);
    }

    #[test]
    fn tst_parse_txt() {
        let v: Vec<u8> = vec![
            0x11,
            0x66,
            0x69,
            0x6c,
            0x65,
            0x3d,
            0x70,
            0x61,
            0x74,
            0x68,
            0x2f,
            0x74,
            0x6f,
            0x2f,
            0x66,
            0x69,
            0x6c,
            0x65,
            0x08,
            0x75,
            0x73,
            0x65,
            0x72,
            0x3d,
            0x63,
            0x65,
            0x64,
        ];
        let (file, user) = parse_txt(v.iter());
        assert_eq!("path/to/file", file);
        assert_eq!("ced", user);
    }

    #[test]
    fn tst_parse_a() {
        let v: Vec<u8> = vec![0xc0, 0xa8, 0x01, 0x02];
        let ip = parse_a(v.iter());
        assert_eq!("192.168.1.2", ip);
    }
}
<|endoftext|>


<commit_before>//! The global epoch
//!
//! The last bit in this number is unused and is always zero. Every so often the global epoch is
//! incremented, i.e. we say it "advances". A pinned participant may advance the global epoch only
//! if all currently pinned participants have been pinned in the current epoch.
//!
//! If an object became garbage in some epoch, then we can be sure that after two advancements no
//! participant will hold a reference to it. That is the crux of safe memory reclamation.

use core::sync::atomic::{AtomicUsize, Ordering};

/// An epoch that can be marked as pinned or unpinned.
///
/// Internally, the epoch is represented as an integer that wraps around at some unspecified point
/// and a flag that represents whether it is pinned or unpinned.
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
pub(super) struct Epoch {
    /// The least significant bit is set if pinned. The rest of the bits hold the epoch.
    data: usize,
}

impl Epoch {
    /// Returns the starting epoch in unpinned state.
    #[inline]
    pub(super) fn starting() -> Self {
        Self::default()
    }

    /// Returns the number of epochs `self` is ahead of `rhs`.
    ///
    /// Internally, epochs are represented as numbers in the range `(isize::MIN / 2) .. (isize::MAX
    /// / 2)`, so the returned distance will be in the same interval.
    pub(super) fn wrapping_sub(self, rhs: Self) -> usize {
        // The result is the same with `(self.data & !1).wrapping_sub(rhs.data & !1) as isize >> 1`,
        // because the possible difference of LSB in `(self.data & !1).wrapping_sub(rhs.data & !1)`
        // will be ignored in the shift operation.
        self.data.wrapping_sub(rhs.data & !1) >> 1
    }

    /// Returns `true` if the epoch is marked as pinned.
    #[inline]
    pub(super) fn is_pinned(self) -> bool {
        (self.data & 1) == 1
    }

    /// Returns the same epoch, but marked as pinned.
    #[inline]
    pub(super) fn pinned(self) -> Epoch {
        Epoch { data: self.data | 1 }
    }

    /// Returns the same epoch, but marked as unpinned.
    #[inline]
    pub(super) fn unpinned(self) -> Epoch {
        Epoch { data: self.data & !1 }
    }

    /// Returns the successor epoch.
    ///
    /// The returned epoch will be marked as pinned only if the previous one was as well.
    #[inline]
    pub(super) fn successor(self) -> Epoch {
        Epoch { data: self.data.wrapping_add(2) }
    }
}

/// An atomic value that holds an `Epoch`.
#[derive(Default, Debug)]
pub(super) struct AtomicEpoch {
    /// Since `Epoch` is just a wrapper around `usize`, an `AtomicEpoch` is similarly represented
    /// using an `AtomicUsize`.
    data: AtomicUsize,
}

impl AtomicEpoch {
    /// Creates a new atomic epoch.
    #[inline]
    pub(super) fn new(epoch: Epoch) -> Self {
        let data = AtomicUsize::new(epoch.data);
        AtomicEpoch { data }
    }

    /// Loads a value from the atomic epoch.
    #[inline]
    pub(super) fn load(&self, ord: Ordering) -> Epoch {
        Epoch { data: self.data.load(ord) }
    }

    /// Stores a value into the atomic epoch.
    #[inline]
    pub(super) fn store(&self, epoch: Epoch, ord: Ordering) {
        self.data.store(epoch.data, ord);
    }

    /// Stores a value into the atomic epoch if the current value is the same as `current`.
    ///
    /// The return value is always the previous value. If it is equal to `current`, then the value
    /// is updated.
    ///
    /// The `Ordering` argument describes the memory ordering of this operation.
    #[inline]
    pub(super) fn compare_and_swap(
        &self,
        current: Epoch,
        new: Epoch,
        ord: Ordering,
    ) -> Epoch {
        let data = self.data.compare_and_swap(current.data, new.data, ord);
        Epoch { data }

        /*
        use super::atomic::CompareAndSetOrdering;

        match self.data.compare_exchange(
            current.data,
            new.data,
            ord.success(),
            ord.failure(),
        ) {
            Ok(data) | Err(data) => Epoch { data },
        }
        */
    }
}
<commit_msg>Use compare_exchange instead of compare_and_swap on the Epoch::compare_and_swap method<commit_after>//! The global epoch
//!
//! The last bit in this number is unused and is always zero. Every so often the global epoch is
//! incremented, i.e. we say it "advances". A pinned participant may advance the global epoch only
//! if all currently pinned participants have been pinned in the current epoch.
//!
//! If an object became garbage in some epoch, then we can be sure that after two advancements no
//! participant will hold a reference to it. That is the crux of safe memory reclamation.

use core::sync::atomic::{AtomicUsize, Ordering};

/// An epoch that can be marked as pinned or unpinned.
///
/// Internally, the epoch is represented as an integer that wraps around at some unspecified point
/// and a flag that represents whether it is pinned or unpinned.
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
pub(super) struct Epoch {
    /// The least significant bit is set if pinned. The rest of the bits hold the epoch.
    data: usize,
}

impl Epoch {
    /// Returns the starting epoch in unpinned state.
    #[inline]
    pub(super) fn starting() -> Self {
        Self::default()
    }

    /// Returns the number of epochs `self` is ahead of `rhs`.
    ///
    /// Internally, epochs are represented as numbers in the range `(isize::MIN / 2) .. (isize::MAX
    /// / 2)`, so the returned distance will be in the same interval.
    pub(super) fn wrapping_sub(self, rhs: Self) -> usize {
        // The result is the same with `(self.data & !1).wrapping_sub(rhs.data & !1) as isize >> 1`,
        // because the possible difference of LSB in `(self.data & !1).wrapping_sub(rhs.data & !1)`
        // will be ignored in the shift operation.
        self.data.wrapping_sub(rhs.data & !1) >> 1
    }

    /// Returns `true` if the epoch is marked as pinned.
    #[inline]
    pub(super) fn is_pinned(self) -> bool {
        (self.data & 1) == 1
    }

    /// Returns the same epoch, but marked as pinned.
    #[inline]
    pub(super) fn pinned(self) -> Epoch {
        Epoch { data: self.data | 1 }
    }

    /// Returns the same epoch, but marked as unpinned.
    #[inline]
    pub(super) fn unpinned(self) -> Epoch {
        Epoch { data: self.data & !1 }
    }

    /// Returns the successor epoch.
    ///
    /// The returned epoch will be marked as pinned only if the previous one was as well.
    #[inline]
    pub(super) fn successor(self) -> Epoch {
        Epoch { data: self.data.wrapping_add(2) }
    }
}

/// An atomic value that holds an `Epoch`.
#[derive(Default, Debug)]
pub(super) struct AtomicEpoch {
    /// Since `Epoch` is just a wrapper around `usize`, an `AtomicEpoch` is similarly represented
    /// using an `AtomicUsize`.
    data: AtomicUsize,
}

impl AtomicEpoch {
    /// Creates a new atomic epoch.
    #[inline]
    pub(super) fn new(epoch: Epoch) -> Self {
        let data = AtomicUsize::new(epoch.data);
        AtomicEpoch { data }
    }

    /// Loads a value from the atomic epoch.
    #[inline]
    pub(super) fn load(&self, ord: Ordering) -> Epoch {
        Epoch { data: self.data.load(ord) }
    }

    /// Stores a value into the atomic epoch.
    #[inline]
    pub(super) fn store(&self, epoch: Epoch, ord: Ordering) {
        self.data.store(epoch.data, ord);
    }

    /// Stores a value into the atomic epoch if the current value is the same as `current`.
    ///
    /// The return value is always the previous value. If it is equal to `current`, then the value
    /// is updated.
    ///
    /// The `Ordering` argument describes the memory ordering of this operation.
    #[inline]
    pub(super) fn compare_and_swap(
        &self,
        current: Epoch,
        new: Epoch,
        ord: Ordering,
    ) -> Epoch {
        use super::atomic::CompareAndSetOrdering;

        match self.data.compare_exchange(
            current.data,
            new.data,
            ord.success(),
            ord.failure(),
        ) {
            Ok(data) | Err(data) => Epoch { data },
        }
    }
}
<|endoftext|>


<commit_before>use std::ops::Range;
use std::slice;
use libc::c_void;

use objc::Id;
use {INSObject, INSCopying, INSMutableCopying, NSRange};

pub trait INSData : INSObject {
    fn len(&self) -> usize {
        unsafe {
            msg_send![self, length]
        }
    }

    fn bytes(&self) -> &[u8] {
        let len = self.len();
        unsafe {
            let ptr: *const c_void = msg_send![self, bytes];
            slice::from_raw_parts(ptr as *const u8, len)
        }
    }

    fn with_bytes(bytes: &[u8]) -> Id<Self> {
        let cls = <Self as INSObject>::class();
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, initWithBytes:bytes.as_ptr()
                                                       length:bytes.len()];
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSData);

impl INSData for NSData { }

impl INSCopying for NSData {
    type Output = NSData;
}

impl INSMutableCopying for NSData {
    type Output = NSMutableData;
}

pub trait INSMutableData : INSData {
    fn bytes_mut(&mut self) -> &mut [u8] {
        let len = self.len();
        unsafe {
            let ptr: *mut c_void = msg_send![self, bytes];
            slice::from_raw_parts_mut(ptr as *mut u8, len)
        }
    }

    fn set_len(&mut self, len: usize) {
        unsafe {
            let _: () = msg_send![self, setLength:len];
        }
    }

    fn append(&mut self, bytes: &[u8]) {
        unsafe {
            let _: () = msg_send![self, appendBytes:bytes.as_ptr()
                                             length:bytes.len()];
        }
    }

    fn replace_range(&mut self, range: Range<usize>, bytes: &[u8]) {
        let range = NSRange::from_range(range);
        unsafe {
            let _: () = msg_send![self, replaceBytesInRange:range
                                                  withBytes:bytes.as_ptr()
                                                     length:bytes.len()];
        }
    }

    fn set_bytes(&mut self, bytes: &[u8]) {
        let len = self.len();
        self.replace_range(0..len, bytes);
    }
}

object_struct!(NSMutableData);

impl INSData for NSMutableData { }

impl INSMutableData for NSMutableData { }

impl INSCopying for NSMutableData {
    type Output = NSData;
}

impl INSMutableCopying for NSMutableData {
    type Output = NSMutableData;
}

#[cfg(test)]
mod tests {
    use objc::Id;
    use super::{INSData, NSData};

    #[test]
    fn test_bytes() {
        let bytes = [3u8, 7, 16, 52, 112, 19];
        let data: Id<NSData> = INSData::with_bytes(&bytes);
        assert!(data.len() == bytes.len());
        assert!(data.bytes() == bytes.as_slice());
    }
}
<commit_msg>Fixed null-bytes issue in NSData.<commit_after>use std::ops::Range;
use std::slice;
use libc::c_void;

use objc::Id;
use {INSObject, INSCopying, INSMutableCopying, NSRange};

pub trait INSData : INSObject {
    fn len(&self) -> usize {
        unsafe {
            msg_send![self, length]
        }
    }

    fn bytes(&self) -> &[u8] {
        let ptr: *const c_void = unsafe { msg_send![self, bytes] };
        // The bytes pointer may be null for length zero
        let (ptr, len) = if ptr.is_null() {
            (0x1 as *const u8, 0)
        } else {
            (ptr as *const u8, self.len())
        };
        unsafe {
            slice::from_raw_parts(ptr, len)
        }
    }

    fn with_bytes(bytes: &[u8]) -> Id<Self> {
        let cls = <Self as INSObject>::class();
        unsafe {
            let obj: *mut Self = msg_send![cls, alloc];
            let obj: *mut Self = msg_send![obj, initWithBytes:bytes.as_ptr()
                                                       length:bytes.len()];
            Id::from_retained_ptr(obj)
        }
    }
}

object_struct!(NSData);

impl INSData for NSData { }

impl INSCopying for NSData {
    type Output = NSData;
}

impl INSMutableCopying for NSData {
    type Output = NSMutableData;
}

pub trait INSMutableData : INSData {
    fn bytes_mut(&mut self) -> &mut [u8] {
        let ptr: *mut c_void = unsafe { msg_send![self, mutableBytes] };
        // The bytes pointer may be null for length zero
        let (ptr, len) = if ptr.is_null() {
            (0x1 as *mut u8, 0)
        } else {
            (ptr as *mut u8, self.len())
        };
        unsafe {
            slice::from_raw_parts_mut(ptr, len)
        }
    }

    fn set_len(&mut self, len: usize) {
        unsafe {
            let _: () = msg_send![self, setLength:len];
        }
    }

    fn append(&mut self, bytes: &[u8]) {
        unsafe {
            let _: () = msg_send![self, appendBytes:bytes.as_ptr()
                                             length:bytes.len()];
        }
    }

    fn replace_range(&mut self, range: Range<usize>, bytes: &[u8]) {
        let range = NSRange::from_range(range);
        unsafe {
            let _: () = msg_send![self, replaceBytesInRange:range
                                                  withBytes:bytes.as_ptr()
                                                     length:bytes.len()];
        }
    }

    fn set_bytes(&mut self, bytes: &[u8]) {
        let len = self.len();
        self.replace_range(0..len, bytes);
    }
}

object_struct!(NSMutableData);

impl INSData for NSMutableData { }

impl INSMutableData for NSMutableData { }

impl INSCopying for NSMutableData {
    type Output = NSData;
}

impl INSMutableCopying for NSMutableData {
    type Output = NSMutableData;
}

#[cfg(test)]
mod tests {
    use objc::Id;
    use INSObject;
    use super::{INSData, NSData};

    #[test]
    fn test_bytes() {
        let bytes = [3u8, 7, 16, 52, 112, 19];
        let data: Id<NSData> = INSData::with_bytes(&bytes);
        assert!(data.len() == bytes.len());
        assert!(data.bytes() == bytes.as_slice());
    }

    #[test]
    fn test_no_bytes() {
        let data: Id<NSData> = INSObject::new();
        assert!(Some(data.bytes()).is_some());
    }
}
<|endoftext|>


<commit_before>use regex::Regex;
use std::env;
use std::fs::File;
use std::io::BufReader;

#[macro_use]
extern crate lazy_static;
extern crate regex;

//Maybe do not need regex
lazy_static! {
    static ref line_re: Regex = Regex::new(r"^\d ").unwrap();
    static ref symbols_re: Regex = Regex::new(r"").unwrap();
    static ref addres_re: Regex = Regex::new(r"").unwrap();
}

#[derive(Debug)]
enum Content {
    Symbols(Vec<String>),
    Addrs(Vec<String>),
}

#[derive(Debug)]
struct SingleLine {
    num: i32,
    content: Option<Content>,
}

fn read_linker_line(li: String) -> SingleLine {
    let mut cut_str: Vec<&str> = li.split_whitespace().collect();
    let num = cut_str[0].parse::<i32>().unwrap();

    if cut_str[1] != "A" && cut_str[1] != "E" && cut_str[1] != "R" && cut_str[1] != "I" {
        return SingleLine {
            num: num,
            content: Some(Content::Symbols(
                cut_str.split_off(1).iter().map(|s| s.to_string()).collect(),
            )),
        };
    } else {
        return SingleLine {
            num: num,
            content: Some(Content::Addrs(
                cut_str.split_off(1).iter().map(|s| s.to_string()).collect(),
            )),
        };
    }

    return SingleLine {
        num: num,
        content: None,
    };
}

#[test]
fn regex_test() {
    let mut fields: Vec<&str> = line_re
        .split("5 R 1004  I 5678  E 2000  R 8002  E 7001")
        .collect();
    //println!("{:?}", fields);

    fields = line_re
        .split("5 R 1004  I 5678  E 2000  R 8002  E 7001")
        .collect();
}

#[test]
fn read_linker_line_test() {
    println!(
        "{:?}",
        read_linker_line(String::from("5 R 1004  I 5678  E 2000  R 8002  E 7001"))
    );

    println!("{:?}", read_linker_line(String::from("2 xy z")));
}

fn main() {
    let fname = env::args().nth(1).unwrap();
    let mut f = File::open(fname).expect("cannot find file");
    let mut file = BufReader::new(&f);
}
<commit_msg>add a bit<commit_after>use regex::Regex;
use std::env;
use std::fs::File;
use std::io::BufReader;

#[macro_use]
extern crate lazy_static;
extern crate regex;

//Maybe do not need regex
lazy_static! {
    static ref line_re: Regex = Regex::new(r"^\d ").unwrap();
    static ref symbols_re: Regex = Regex::new(r"").unwrap();
    static ref addres_re: Regex = Regex::new(r"").unwrap();
}

#[derive(Debug)]
enum Content {
    DefSym(Vec<String>),
    Symbols(Vec<String>),
    Addrs(Vec<String>),
}

#[derive(Debug)]
struct SingleLine {
    num: i32,
    content: Option<Content>,
}

impl Content {
    fn num_change(&mut self) -> Vec<(String, i32)> {
        let mut result: Vec<(String, i32)> = vec![];
        match self {
            Content::DefSym(l) | Content::Addrs(l) => {
                let (_, l2) = l.split_at(1);
                for (i, (x, y)) in l.iter().zip(l2.iter()).enumerate() {
                    if i % 2 == 0 {
                        result.push((x.clone(), y.parse::<i32>().unwrap()));
                    }
                }
            }
            _ => (),
        }
        return result;
    }
}

#[test]
fn test_num_change() {
    let a = read_linker_line(String::from("5 R 1004  I 5678  E 2000  R 8002  E 7001"));
    println!("{:?}", a.content.unwrap().num_change());
}

fn read_linker_line(li: String) -> SingleLine {
    let mut cut_str: Vec<&str> = li.split_whitespace().collect();
    let num = cut_str[0].parse::<i32>().unwrap();

    if cut_str.len() == 1 {
        return SingleLine {
            num: num,
            content: None,
        };
    }

    if cut_str[1] != "A" && cut_str[1] != "E" && cut_str[1] != "R" && cut_str[1] != "I" {
        if let Ok(_) = cut_str[2].parse::<i32>() {
            return SingleLine {
                num: num,
                content: Some(Content::DefSym(
                    cut_str.split_off(1).iter().map(|s| s.to_string()).collect(),
                )),
            };
        }
        return SingleLine {
            num: num,
            content: Some(Content::Symbols(
                cut_str.split_off(1).iter().map(|s| s.to_string()).collect(),
            )),
        };
    } else {
        return SingleLine {
            num: num,
            content: Some(Content::Addrs(
                cut_str.split_off(1).iter().map(|s| s.to_string()).collect(),
            )),
        };
    }
}

#[test]
#[ignore]
fn read_linker_line_test() {
    println!(
        "{:?}",
        read_linker_line(String::from("5 R 1004  I 5678  E 2000  R 8002  E 7001"))
    );

    println!("{:?}", read_linker_line(String::from("2 xy z")));

    println!("{:?}", read_linker_line(String::from("0")));

    println!("{:?}", read_linker_line(String::from("2 xy 2")));
}

fn main() {
    let fname = env::args().nth(1).unwrap();
    let mut f = File::open(fname).expect("cannot find file");
    let mut file = BufReader::new(&f);
}
<|endoftext|>