<commit_before>//! Defines valid types.

use std::fmt;
use std::collections::HashMap;

use petgraph::graph::{EdgeIndex, Graph, NodeIndex};
use petgraph::EdgeDirection;

type TIEResult<T> = Result<T, String>;

#[derive(Clone, Debug)]
pub enum RType {
    Overdefined,
    Reg8,
    Reg16,
    Reg32,
    Reg64,
    Num8,
    Num16,
    Num32,
    Num64,
    UInt8,
    UInt16,
    UInt32,
    UInt64,
    Int8,
    Int16,
    Int32,
    Int64,
    Bool,
    Ptr(Box<RType>),
    Code,
    Union(Vec<RType>),
    Intersect(Vec<RType>),
    Undefined,
}

impl fmt::Display for RType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let RType::Ptr(ref ty) = *self {
            write!(f, "{}*", ty)
        } else if let RType::Union(ref tys) = *self {
            let mut s = String::from("union(");
            let len = tys.len();
            for (i, ty) in tys.iter().enumerate() {
                s.push_str(&ty.to_string());
                if i < len - 1 {
                    s.push_str(", ");
                }
            }
            write!(f, "{})", s)
        } else if let RType::Intersect(ref tys) = *self {
            let mut s = String::from("intersect(");
            let len = tys.len();
            for (i, ty) in tys.iter().enumerate() {
                s.push_str(&ty.to_string());
                if i < len - 1 {
                    s.push_str(", ");
                }
            }
            write!(f, "{})", s)
        } else {
            let s = match *self {
                RType::Overdefined => "overdefined",
                RType::Reg8 => "reg8",
                RType::Reg16 => "reg16",
                RType::Reg32 => "reg32",
                RType::Reg64 => "reg64",
                RType::Num8 => "n8",
                RType::Num16 => "n16",
                RType::Num32 => "n32",
                RType::Num64 => "n64",
                RType::UInt8 => "u8",
                RType::UInt16 => "u16",
                RType::UInt32 => "u32",
                RType::UInt64 => "u64",
                RType::Int8 => "i8",
                RType::Int16 => "i16",
                RType::Int32 => "i32",
                RType::Int64 => "i64",
                RType::Bool => "bool",
                RType::Undefined => "underdefined",
                RType::Code => "code",
                _ => unreachable!(),
            };
            write!(f, "{}", s)
        }
    }
}

#[derive(Clone, Debug)]
pub enum ConstraintNode {
    Type(RType),
    AbstractType,
    Ptr,
    TypeVar,
    DisjunctiveJoin,
    ConjunctiveJoin,
    Union,
    Intersect,
}

const EQUAL_EDGE: ConstraintEdge = ConstraintEdge::Equal;
const SUBTYPE_EDGE: ConstraintEdge = ConstraintEdge::SubType;

#[derive(Clone, Debug)]
pub enum ConstraintEdge {
    EdgeIdx(u8),
    SubType,
    Equal,
    Ptr,
}

#[derive(Clone, Debug)]
pub enum SubTypeNode {
    // Index in the original constaints set.
    OrigIdx(NodeIndex),
}

#[derive(Clone, Debug)]
pub enum SubTypeEdge {
    SubType,
}

#[derive(Clone, Debug)]
pub struct SubTypeSet {
    g: Graph<SubTypeNode, SubTypeEdge>,
    // Map from NodeIndex in ConstraintSet to NodeIndex in SubTypeSet.
    map: HashMap<NodeIndex, NodeIndex>,
}

impl SubTypeSet {
    pub fn new() -> SubTypeSet {
        SubTypeSet {
            g: Graph::new(),
            map: HashMap::new(),
        }
    }

    // Insert LHS <: RHS
    pub fn insert_relation(&mut self, lhs: &NodeIndex, rhs: &NodeIndex) {
        let sub_lhs = if let Some(idx) = self.map.get(lhs).cloned() {
            idx
        } else {
            let new_node = self.g.add_node(SubTypeNode::OrigIdx(*lhs));
            self.map.insert(*lhs, new_node);
            new_node
        };

        let sub_rhs = if let Some(idx) = self.map.get(rhs).cloned() {
            idx
        } else {
            let new_node = self.g.add_node(SubTypeNode::OrigIdx(*rhs));
            self.map.insert(*rhs, new_node);
            new_node
        };
        self.g.add_edge(sub_lhs, sub_rhs, SubTypeEdge::SubType);
    }

    // For all ( alpha <: S ) return alpha
    pub fn subtypes_of(&self, idx_s: &NodeIndex) -> Vec<NodeIndex> {
        let idx = self.map[idx_s];
        let mut result = Vec::new();
        let mut traverse_list = Vec::new();
        traverse_list.extend(self.g.neighbors_directed(idx, EdgeDirection::Incoming));
        while let Some(node) = traverse_list.pop() {
            traverse_list.extend(self.g.neighbors_directed(node, EdgeDirection::Incoming));
            match self.g[node] {
                SubTypeNode::OrigIdx(ni) => result.push(ni),
            }
        }
        result
    }

    // For all ( T <: beta ) return beta
    pub fn supertypes_of(&self, idx_t: &NodeIndex) -> Vec<NodeIndex> {
        let idx = self.map[idx_t];
        let mut result = Vec::new();
        let mut traverse_list = Vec::new();
        traverse_list.extend(self.g.neighbors_directed(idx, EdgeDirection::Outgoing));
        while let Some(node) = traverse_list.pop() {
            traverse_list.extend(self.g.neighbors_directed(node, EdgeDirection::Outgoing));
            match self.g[node] {
                SubTypeNode::OrigIdx(ni) => result.push(ni),
            }
        }
        result
    }
}

#[derive(Clone, Debug)]
pub struct ConstraintSet {
    g: Graph<ConstraintNode, ConstraintEdge>,
    type_vars: HashMap<String, NodeIndex>,
    // S<:
    subty: SubTypeSet,
    // S=
    binding_map: HashMap<NodeIndex, RType>,
    // B^
    upper_bound: HashMap<NodeIndex, RType>,
    // B_
    lower_bound: HashMap<NodeIndex, RType>,
}

impl ConstraintSet {
    pub fn new() -> ConstraintSet {
        ConstraintSet {
            g: Graph::new(),
            type_vars: HashMap::new(),
            subty: SubTypeSet::new(),
            binding_map: HashMap::new(),
            upper_bound: HashMap::new(),
            lower_bound: HashMap::new(),
        }
    }

    pub fn operands(&self, n: &NodeIndex) -> Vec<NodeIndex> {
        let mut result = Vec::new();
        for (n, e) in self.g.edges_directed(*n, EdgeDirection::Outgoing) {
            if let ConstraintEdge::EdgeIdx(i) = *e {
                result.push((i, n));
            }
        }
        result.sort_by(|a, b| a.0.cmp(&b.0));
        result.iter().map(|a| *a.1).collect()
    }

    pub fn insert_type_var(&mut self, named: Option<String>) -> NodeIndex {
        let var = self.g.add_node(ConstraintNode::TypeVar);
        let name = named.unwrap_or_else(|| format!("var_{}", self.type_vars.keys().len()));
        self.type_vars.insert(name, var);
        var
    }

    pub fn insert_abstract_type(&mut self) -> NodeIndex {
        self.g.add_node(ConstraintNode::AbstractType)
    }

    pub fn insert_base_type(&mut self, ty: RType) -> NodeIndex {
        self.g.add_node(ConstraintNode::Type(ty))
    }

    pub fn subtype(&mut self, lhs: &NodeIndex, rhs: &NodeIndex) {
        self.g.update_edge(*lhs, *rhs, SUBTYPE_EDGE);
    }

    pub fn supertype(&mut self, lhs: &NodeIndex, rhs: &NodeIndex) {
        self.subtype(rhs, lhs)
    }

    pub fn disjunctive_join(&mut self, operands: &[NodeIndex]) -> NodeIndex {
        let disjunction = self.g.add_node(ConstraintNode::DisjunctiveJoin);
        for (i, idx) in operands.iter().enumerate() {
            self.g.update_edge(disjunction, *idx, ConstraintEdge::EdgeIdx(i as u8));
        }
        disjunction
    }

    pub fn conjunctive_join(&mut self, operands: &[NodeIndex]) -> NodeIndex {
        let conjunction = self.g.add_node(ConstraintNode::ConjunctiveJoin);
        for (i, idx) in operands.iter().enumerate() {
            self.g.update_edge(conjunction, *idx, ConstraintEdge::EdgeIdx(i as u8));
        }
        conjunction
    }

    pub fn equal(&mut self, operands: &[NodeIndex; 2]) {
        self.g.update_edge(operands[0], operands[1], EQUAL_EDGE);
    }

    pub fn union(&mut self, operands: &[NodeIndex]) -> NodeIndex {
        let union = self.g.add_node(ConstraintNode::Union);
        for (i, idx) in operands.iter().enumerate() {
            self.g.update_edge(union, *idx, ConstraintEdge::EdgeIdx(i as u8));
        }
        union
    }

    pub fn intersect(&mut self, operands: &[NodeIndex]) -> NodeIndex {
        let intersection = self.g.add_node(ConstraintNode::Intersect);
        for (i, idx) in operands.iter().enumerate() {
            self.g.update_edge(intersection, *idx, ConstraintEdge::EdgeIdx(i as u8));
        }
        intersection
    }

    pub fn solve(&mut self) {
        unimplemented!()
    }

    fn solve_equality_constraint(&mut self, constraint_edge: &EdgeIndex) -> TIEResult<()> {
        unimplemented!()
    }

    fn solve_subtype_constraint(&mut self, constraint_edge: &EdgeIndex) -> TIEResult<()> {
        unimplemented!()
    }

    fn inner_type(&self, ptr_node: NodeIndex) -> NodeIndex {
        self.g
            .edges_directed(ptr_node, EdgeDirection::Outgoing)
            .find(|x| {
                match *x.1 {
                    ConstraintEdge::Ptr => true,
                    _ => false,
                }
            })
            .expect("Inner type of `Ptr` cannot be `None`")
            .0
    }

    // This function decomposes the first node and adds the appropriate edges to
    // the other node.
    fn decompose_constraint_node(&mut self, lhs: NodeIndex, rhs: NodeIndex) {
        let rhs_is_ptr = match self.g[rhs] {
            ConstraintNode::Intersect => {
                let operands = self.operands(&rhs);
                for op in &operands {
                    self.g.update_edge(lhs, *op, ConstraintEdge::SubType);
                }
                false
            }
            ConstraintNode::Ptr => true,
            _ => false,
        };

        let lhs_is_ptr = match self.g[lhs] {
            ConstraintNode::Union => {
                let lhs_operands = self.operands(&lhs);
                let mut subtype_relations = Vec::new();
                let mut edges = self.g.neighbors_directed(lhs, EdgeDirection::Incoming).detach();
                while let Some(edge) = edges.next_edge(&self.g) {
                    if let ConstraintEdge::SubType = self.g[edge] {
                        let (_, target) = self.g.edge_endpoints(edge).expect("");
                        self.g.remove_edge(edge);
                        subtype_relations.push(target);
                    }
                }
                for rhs_op in subtype_relations {
                    for lhs_op in &lhs_operands {
                        self.g.update_edge(*lhs_op, rhs_op, ConstraintEdge::SubType);
                    }
                }
                false
            }
            ConstraintNode::Ptr => true,
            _ => false,
        };

        if lhs_is_ptr && rhs_is_ptr {
            let lhs_inner = self.inner_type(lhs);
            let rhs_inner = self.inner_type(rhs);
            self.g.update_edge(lhs_inner, rhs_inner, ConstraintEdge::SubType);
        }
    }

    fn decompose_subtype_relation(&mut self, subtype_edge: EdgeIndex) {
        // According to section 6.3.2 - Decomposition Rules.
        let (lhs, rhs) = self.g.edge_endpoints(subtype_edge).expect("This cannot be None");
        self.decompose_constraint_node(lhs, rhs);
    }

    fn meet(&mut self, operands: &[RType]) -> RType {
        unimplemented!()
    }

    fn join(&mut self, operands: &[RType]) -> RType {
        unimplemented!()
    }
}
<commit_msg>adapt code to new return type of iterator<commit_after>//! Defines valid types.

use std::fmt;
use std::collections::HashMap;

use petgraph::graph::{EdgeIndex, Graph, NodeIndex, EdgeReference};
use petgraph::EdgeDirection;

type TIEResult<T> = Result<T, String>;

#[derive(Clone, Debug)]
pub enum RType {
    Overdefined,
    Reg8,
    Reg16,
    Reg32,
    Reg64,
    Num8,
    Num16,
    Num32,
    Num64,
    UInt8,
    UInt16,
    UInt32,
    UInt64,
    Int8,
    Int16,
    Int32,
    Int64,
    Bool,
    Ptr(Box<RType>),
    Code,
    Union(Vec<RType>),
    Intersect(Vec<RType>),
    Undefined,
}

impl fmt::Display for RType {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        if let RType::Ptr(ref ty) = *self {
            write!(f, "{}*", ty)
        } else if let RType::Union(ref tys) = *self {
            let mut s = String::from("union(");
            let len = tys.len();
            for (i, ty) in tys.iter().enumerate() {
                s.push_str(&ty.to_string());
                if i < len - 1 {
                    s.push_str(", ");
                }
            }
            write!(f, "{})", s)
        } else if let RType::Intersect(ref tys) = *self {
            let mut s = String::from("intersect(");
            let len = tys.len();
            for (i, ty) in tys.iter().enumerate() {
                s.push_str(&ty.to_string());
                if i < len - 1 {
                    s.push_str(", ");
                }
            }
            write!(f, "{})", s)
        } else {
            let s = match *self {
                RType::Overdefined => "overdefined",
                RType::Reg8 => "reg8",
                RType::Reg16 => "reg16",
                RType::Reg32 => "reg32",
                RType::Reg64 => "reg64",
                RType::Num8 => "n8",
                RType::Num16 => "n16",
                RType::Num32 => "n32",
                RType::Num64 => "n64",
                RType::UInt8 => "u8",
                RType::UInt16 => "u16",
                RType::UInt32 => "u32",
                RType::UInt64 => "u64",
                RType::Int8 => "i8",
                RType::Int16 => "i16",
                RType::Int32 => "i32",
                RType::Int64 => "i64",
                RType::Bool => "bool",
                RType::Undefined => "underdefined",
                RType::Code => "code",
                _ => unreachable!(),
            };
            write!(f, "{}", s)
        }
    }
}

#[derive(Clone, Debug)]
pub enum ConstraintNode {
    Type(RType),
    AbstractType,
    Ptr,
    TypeVar,
    DisjunctiveJoin,
    ConjunctiveJoin,
    Union,
    Intersect,
}

const EQUAL_EDGE: ConstraintEdge = ConstraintEdge::Equal;
const SUBTYPE_EDGE: ConstraintEdge = ConstraintEdge::SubType;

#[derive(Clone, Debug)]
pub enum ConstraintEdge {
    EdgeIdx(u8),
    SubType,
    Equal,
    Ptr,
}

#[derive(Clone, Debug)]
pub enum SubTypeNode {
    // Index in the original constaints set.
    OrigIdx(NodeIndex),
}

#[derive(Clone, Debug)]
pub enum SubTypeEdge {
    SubType,
}

#[derive(Clone, Debug)]
pub struct SubTypeSet {
    g: Graph<SubTypeNode, SubTypeEdge>,
    // Map from NodeIndex in ConstraintSet to NodeIndex in SubTypeSet.
    map: HashMap<NodeIndex, NodeIndex>,
}

impl SubTypeSet {
    pub fn new() -> SubTypeSet {
        SubTypeSet {
            g: Graph::new(),
            map: HashMap::new(),
        }
    }

    // Insert LHS <: RHS
    pub fn insert_relation(&mut self, lhs: &NodeIndex, rhs: &NodeIndex) {
        let sub_lhs = if let Some(idx) = self.map.get(lhs).cloned() {
            idx
        } else {
            let new_node = self.g.add_node(SubTypeNode::OrigIdx(*lhs));
            self.map.insert(*lhs, new_node);
            new_node
        };

        let sub_rhs = if let Some(idx) = self.map.get(rhs).cloned() {
            idx
        } else {
            let new_node = self.g.add_node(SubTypeNode::OrigIdx(*rhs));
            self.map.insert(*rhs, new_node);
            new_node
        };
        self.g.add_edge(sub_lhs, sub_rhs, SubTypeEdge::SubType);
    }

    // For all ( alpha <: S ) return alpha
    pub fn subtypes_of(&self, idx_s: &NodeIndex) -> Vec<NodeIndex> {
        let idx = self.map[idx_s];
        let mut result = Vec::new();
        let mut traverse_list = Vec::new();
        traverse_list.extend(self.g.neighbors_directed(idx, EdgeDirection::Incoming));
        while let Some(node) = traverse_list.pop() {
            traverse_list.extend(self.g.neighbors_directed(node, EdgeDirection::Incoming));
            match self.g[node] {
                SubTypeNode::OrigIdx(ni) => result.push(ni),
            }
        }
        result
    }

    // For all ( T <: beta ) return beta
    pub fn supertypes_of(&self, idx_t: &NodeIndex) -> Vec<NodeIndex> {
        let idx = self.map[idx_t];
        let mut result = Vec::new();
        let mut traverse_list = Vec::new();
        traverse_list.extend(self.g.neighbors_directed(idx, EdgeDirection::Outgoing));
        while let Some(node) = traverse_list.pop() {
            traverse_list.extend(self.g.neighbors_directed(node, EdgeDirection::Outgoing));
            match self.g[node] {
                SubTypeNode::OrigIdx(ni) => result.push(ni),
            }
        }
        result
    }
}

#[derive(Clone, Debug)]
pub struct ConstraintSet {
    g: Graph<ConstraintNode, ConstraintEdge>,
    type_vars: HashMap<String, NodeIndex>,
    // S<:
    subty: SubTypeSet,
    // S=
    binding_map: HashMap<NodeIndex, RType>,
    // B^
    upper_bound: HashMap<NodeIndex, RType>,
    // B_
    lower_bound: HashMap<NodeIndex, RType>,
}

impl ConstraintSet {
    pub fn new() -> ConstraintSet {
        ConstraintSet {
            g: Graph::new(),
            type_vars: HashMap::new(),
            subty: SubTypeSet::new(),
            binding_map: HashMap::new(),
            upper_bound: HashMap::new(),
            lower_bound: HashMap::new(),
        }
    }

    pub fn operands(&self, n: &NodeIndex) -> Vec<NodeIndex> {
        let mut result = Vec::new();
        for edge in self.g.edges_directed(*n, EdgeDirection::Outgoing) {
            if let EdgeReference{index: i, ..} = edge {
                result.push((i, n));
            }
        }
        result.sort_by(|a, b| a.0.cmp(&b.0));
        result.iter().map(|a| *a.1).collect()
    }

    pub fn insert_type_var(&mut self, named: Option<String>) -> NodeIndex {
        let var = self.g.add_node(ConstraintNode::TypeVar);
        let name = named.unwrap_or_else(|| format!("var_{}", self.type_vars.keys().len()));
        self.type_vars.insert(name, var);
        var
    }

    pub fn insert_abstract_type(&mut self) -> NodeIndex {
        self.g.add_node(ConstraintNode::AbstractType)
    }

    pub fn insert_base_type(&mut self, ty: RType) -> NodeIndex {
        self.g.add_node(ConstraintNode::Type(ty))
    }

    pub fn subtype(&mut self, lhs: &NodeIndex, rhs: &NodeIndex) {
        self.g.update_edge(*lhs, *rhs, SUBTYPE_EDGE);
    }

    pub fn supertype(&mut self, lhs: &NodeIndex, rhs: &NodeIndex) {
        self.subtype(rhs, lhs)
    }

    pub fn disjunctive_join(&mut self, operands: &[NodeIndex]) -> NodeIndex {
        let disjunction = self.g.add_node(ConstraintNode::DisjunctiveJoin);
        for (i, idx) in operands.iter().enumerate() {
            self.g.update_edge(disjunction, *idx, ConstraintEdge::EdgeIdx(i as u8));
        }
        disjunction
    }

    pub fn conjunctive_join(&mut self, operands: &[NodeIndex]) -> NodeIndex {
        let conjunction = self.g.add_node(ConstraintNode::ConjunctiveJoin);
        for (i, idx) in operands.iter().enumerate() {
            self.g.update_edge(conjunction, *idx, ConstraintEdge::EdgeIdx(i as u8));
        }
        conjunction
    }

    pub fn equal(&mut self, operands: &[NodeIndex; 2]) {
        self.g.update_edge(operands[0], operands[1], EQUAL_EDGE);
    }

    pub fn union(&mut self, operands: &[NodeIndex]) -> NodeIndex {
        let union = self.g.add_node(ConstraintNode::Union);
        for (i, idx) in operands.iter().enumerate() {
            self.g.update_edge(union, *idx, ConstraintEdge::EdgeIdx(i as u8));
        }
        union
    }

    pub fn intersect(&mut self, operands: &[NodeIndex]) -> NodeIndex {
        let intersection = self.g.add_node(ConstraintNode::Intersect);
        for (i, idx) in operands.iter().enumerate() {
            self.g.update_edge(intersection, *idx, ConstraintEdge::EdgeIdx(i as u8));
        }
        intersection
    }

    pub fn solve(&mut self) {
        unimplemented!()
    }

    fn solve_equality_constraint(&mut self, constraint_edge: &EdgeIndex) -> TIEResult<()> {
        unimplemented!()
    }

    fn solve_subtype_constraint(&mut self, constraint_edge: &EdgeIndex) -> TIEResult<()> {
        unimplemented!()
    }

    fn inner_type(&self, ptr_node: NodeIndex) -> NodeIndex {
        self.g
            .edges_directed(ptr_node, EdgeDirection::Outgoing)
            .find(|x| {
                match *x.1 {
                    ConstraintEdge::Ptr => true,
                    _ => false,
                }
            })
            .expect("Inner type of `Ptr` cannot be `None`")
            .0
    }

    // This function decomposes the first node and adds the appropriate edges to
    // the other node.
    fn decompose_constraint_node(&mut self, lhs: NodeIndex, rhs: NodeIndex) {
        let rhs_is_ptr = match self.g[rhs] {
            ConstraintNode::Intersect => {
                let operands = self.operands(&rhs);
                for op in &operands {
                    self.g.update_edge(lhs, *op, ConstraintEdge::SubType);
                }
                false
            }
            ConstraintNode::Ptr => true,
            _ => false,
        };

        let lhs_is_ptr = match self.g[lhs] {
            ConstraintNode::Union => {
                let lhs_operands = self.operands(&lhs);
                let mut subtype_relations = Vec::new();
                let mut edges = self.g.neighbors_directed(lhs, EdgeDirection::Incoming).detach();
                while let Some(edge) = edges.next_edge(&self.g) {
                    if let ConstraintEdge::SubType = self.g[edge] {
                        let (_, target) = self.g.edge_endpoints(edge).expect("");
                        self.g.remove_edge(edge);
                        subtype_relations.push(target);
                    }
                }
                for rhs_op in subtype_relations {
                    for lhs_op in &lhs_operands {
                        self.g.update_edge(*lhs_op, rhs_op, ConstraintEdge::SubType);
                    }
                }
                false
            }
            ConstraintNode::Ptr => true,
            _ => false,
        };

        if lhs_is_ptr && rhs_is_ptr {
            let lhs_inner = self.inner_type(lhs);
            let rhs_inner = self.inner_type(rhs);
            self.g.update_edge(lhs_inner, rhs_inner, ConstraintEdge::SubType);
        }
    }

    fn decompose_subtype_relation(&mut self, subtype_edge: EdgeIndex) {
        // According to section 6.3.2 - Decomposition Rules.
        let (lhs, rhs) = self.g.edge_endpoints(subtype_edge).expect("This cannot be None");
        self.decompose_constraint_node(lhs, rhs);
    }

    fn meet(&mut self, operands: &[RType]) -> RType {
        unimplemented!()
    }

    fn join(&mut self, operands: &[RType]) -> RType {
        unimplemented!()
    }
}
<|endoftext|>


<commit_before>// hex encoder and decoder used by rust-protobuf unittests

#![allow(dead_code)]

use std::char;

fn decode_hex_digit(digit: char) -> u8 {
    match digit {
        '0' ... '9' => digit as u8 - '0' as u8,
        'a' ... 'f' => digit as u8 - 'a' as u8 + 10,
        'A' ... 'F' => digit as u8 - 'A' as u8 + 10,
        _ => panic!(),
    }
}

pub fn decode_hex(hex: &str) -> Vec<u8> {
    let mut r: Vec<u8> = Vec::new();
    let mut pos = 0;
    loop {
        while pos < hex.char_len() && hex.to_ascii().get(pos).unwrap().to_byte() == b' ' {
            pos += 1;
        }
        if hex.char_len() - pos >= 2 {
            r.push((decode_hex_digit(hex.char_at(pos)) << 4) | decode_hex_digit(hex.char_at(pos + 1)));
            pos += 2;
            continue;
        }
        if pos == hex.char_len() {
            break;
        }
        panic!("pos = {}d", pos);
    }
    r
}

fn encode_hex_digit(digit: u8) -> char {
    match char::from_digit(digit as uint, 16) {
        Some(c) => c,
        _ => panic!()
    }
}

fn encode_hex_byte(byte: u8) -> [char, ..2] {
    [encode_hex_digit(byte >> 4), encode_hex_digit(byte & 0x0Fu8)]
}

pub fn encode_hex(bytes: &[u8]) -> String {
    let strs: Vec<String> = bytes.iter().map(|byte| {
        String::from_chars(encode_hex_byte(*byte).as_slice())
    }).collect();
    strs.connect(" ")
}

#[cfg(test)]
mod test {

    use super::decode_hex;
    use super::encode_hex;

    #[test]
    fn test_decode_hex() {
        assert_eq!([].to_vec(), decode_hex(""));
        assert_eq!([0x00u8].to_vec(), decode_hex("00"));
        assert_eq!([0xffu8].to_vec(), decode_hex("ff"));
        assert_eq!([0xabu8].to_vec(), decode_hex("AB"));
        assert_eq!([0xfau8, 0x19].to_vec(), decode_hex("fa 19"));
    }

    #[test]
    fn test_encode_hex() {
        assert_eq!("".to_string(), encode_hex(&[]));
        assert_eq!("00".to_string(), encode_hex(&[0x00]));
        assert_eq!("ab".to_string(), encode_hex(&[0xab]));
        assert_eq!("01 a2 1a fe".to_string(), encode_hex(&[0x01, 0xa2, 0x1a, 0xfe]));
    }
}
<commit_msg>Ascii to_byte renamed to as_byte<commit_after>// hex encoder and decoder used by rust-protobuf unittests

#![allow(dead_code)]

use std::char;

fn decode_hex_digit(digit: char) -> u8 {
    match digit {
        '0' ... '9' => digit as u8 - '0' as u8,
        'a' ... 'f' => digit as u8 - 'a' as u8 + 10,
        'A' ... 'F' => digit as u8 - 'A' as u8 + 10,
        _ => panic!(),
    }
}

pub fn decode_hex(hex: &str) -> Vec<u8> {
    let mut r: Vec<u8> = Vec::new();
    let mut pos = 0;
    loop {
        while pos < hex.char_len() && hex.to_ascii().get(pos).unwrap().as_byte() == b' ' {
            pos += 1;
        }
        if hex.char_len() - pos >= 2 {
            r.push((decode_hex_digit(hex.char_at(pos)) << 4) | decode_hex_digit(hex.char_at(pos + 1)));
            pos += 2;
            continue;
        }
        if pos == hex.char_len() {
            break;
        }
        panic!("pos = {}d", pos);
    }
    r
}

fn encode_hex_digit(digit: u8) -> char {
    match char::from_digit(digit as uint, 16) {
        Some(c) => c,
        _ => panic!()
    }
}

fn encode_hex_byte(byte: u8) -> [char, ..2] {
    [encode_hex_digit(byte >> 4), encode_hex_digit(byte & 0x0Fu8)]
}

pub fn encode_hex(bytes: &[u8]) -> String {
    let strs: Vec<String> = bytes.iter().map(|byte| {
        String::from_chars(encode_hex_byte(*byte).as_slice())
    }).collect();
    strs.connect(" ")
}

#[cfg(test)]
mod test {

    use super::decode_hex;
    use super::encode_hex;

    #[test]
    fn test_decode_hex() {
        assert_eq!([].to_vec(), decode_hex(""));
        assert_eq!([0x00u8].to_vec(), decode_hex("00"));
        assert_eq!([0xffu8].to_vec(), decode_hex("ff"));
        assert_eq!([0xabu8].to_vec(), decode_hex("AB"));
        assert_eq!([0xfau8, 0x19].to_vec(), decode_hex("fa 19"));
    }

    #[test]
    fn test_encode_hex() {
        assert_eq!("".to_string(), encode_hex(&[]));
        assert_eq!("00".to_string(), encode_hex(&[0x00]));
        assert_eq!("ab".to_string(), encode_hex(&[0xab]));
        assert_eq!("01 a2 1a fe".to_string(), encode_hex(&[0x01, 0xa2, 0x1a, 0xfe]));
    }
}
<|endoftext|>


<commit_before>use hyper::Client;
use hyper::header::{Headers, ContentType};
use hyper::Result as HyperResult;
use hyper::client::Response as HyperResponse;
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::status::StatusCode;

use event::Event;
use types::Result;
use expected_version::ExpectedVersion;
use error::HesError;
use error::UserErrorKind;
use connection::ConnectionInfo;

use api::ESCurrentVersion;
use api::ESExpectedVersion;

const WRONG_EXPECTED_EVENT_NUMBER: &'static str = "Wrong expected EventNumber";

pub struct Appender<'a> {
   connection_info: &'a ConnectionInfo,
}

impl<'a> Appender<'a> {
    pub fn new(connection_info: &'a ConnectionInfo) -> Appender {
        Appender { connection_info: connection_info }
    }

    pub fn append_to_stream(&self, stream_name: &str, expected_version: ExpectedVersion, events: Vec<Event>) -> Result<()> {
        let events_as_json : Vec<String> = events.iter().map(|e| {
            format!(r#"{{
                      "eventType": "{}",
                      "eventId": "{}",
                      "data": {}
                    }}"#,
                    e.event_type.to_string(),
                    e.event_id.hyphenated().to_string(),
                    e.data.clone().unwrap()) //TODO Eliminate `clone` and deal with `unwrap`.
        }).collect::<Vec<String>>();
        let events_json: String = format!("[{}]", events_as_json.join(","));

        let client = Client::default();

        let mut headers = Headers::new();
        headers.set(
            ContentType(Mime(TopLevel::Application, SubLevel::Ext("vnd.eventstore.events+json".to_owned()), vec![]))
        );
        headers.set(ESExpectedVersion(expected_version.into()));

        let result: HyperResult<HyperResponse> = client.post(&self.url(stream_name))
            .headers(headers)
            .body(&events_json)
            .send();

        match result {
            Ok(response) => {
                match response.status {
                    StatusCode::Created => Ok(()),
                    StatusCode::BadRequest => self.handle_bad_request_on_append(response),
                    _ => self.panic_showing(&response)
                }
            },
            Err(err) => Err(HesError::UserError(UserErrorKind::Http(err)))
        }
    }

    fn url(&self, stream_name: &str) -> String {
        format!("http://{}:{}/streams/{}",
                self.connection_info.host,
                self.connection_info.port,
                stream_name)
    }

    fn handle_bad_request_on_append(&self, response: HyperResponse) -> Result<()> {
        // RawStatus(400, ref reason_phrase) => {
        //   Response { status: BadRequest, headers:
        //     Headers { Access-Control-Allow-Headers: Content-Type, X-Requested-With,
        //               X-Forwarded-Host, X-PINGOTHER, Authorization, ES-LongPoll,
        //               ES-ExpectedVersion, ES-EventId, ES-EventType, ES-RequiresMaster,
        //               ES-HardDelete, ES-ResolveLinkTo,
        //               Content-Type: text/plain; charset=utf-8,
        //               Content-Length: 0,
        //               Date: Wed, 12 Oct 2016 16:24:28 GMT,
        //               Connection: close,
        //               Access-Control-Allow-Origin: *,
        // -->           ES-CurrentVersion: -1,
        //               Access-Control-Expose-Headers: Location, ES-Position, ES-CurrentVersion,
        //               Access-Control-Allow-Methods: POST, DELETE, GET, OPTIONS, Server: Mono-HTTPAPI/1.0, },
        //     version: Http11,
        //     url: "http://127.0.0.1:2113/streams/task-c0340f57a914468ea6b48f7dff3519dc",
        // --> status_raw: RawStatus(400, "Wrong expected EventNumber"),
        //     message: Http11Message { is_proxied: false, method: None, stream: Wrapper { obj: Some(Reading(SizedReader(remaining=0))) } } }
        let is_wrong_expected_number = { response.status_raw().1 == WRONG_EXPECTED_EVENT_NUMBER };

        let error_kind = if is_wrong_expected_number {
            let version = self.expected_version(&response);
            UserErrorKind::EventNumberMismatch(version)
        } else {
            UserErrorKind::BadRequest(response)
        };

        Err(HesError::UserError(error_kind))
    }

    fn expected_version(&self, response: &HyperResponse) -> Option<ExpectedVersion> {
        response.headers.get::<ESCurrentVersion>()
            .and_then(|header| Some(ExpectedVersion::from(header.to_string())))
    }

    fn panic_showing(&self, response: &HyperResponse) -> ! {
        panic!("hyper::status::StatusCode {} Response: {:?}", response.status, response)
    }
}
<commit_msg>Refactor Appender<commit_after>use hyper::Client;
use hyper::Result as HyperResult;
use hyper::client::Response as HyperResponse;
use hyper::header::{Headers, ContentType};
use hyper::mime::{Mime, TopLevel, SubLevel};
use hyper::status::StatusCode;

use event::Event;
use types::Result;
use expected_version::ExpectedVersion;
use error::HesError;
use error::UserErrorKind;
use connection::ConnectionInfo;

use api::ESCurrentVersion;
use api::ESExpectedVersion;

const WRONG_EXPECTED_EVENT_NUMBER: &'static str = "Wrong expected EventNumber";

pub struct Appender<'a> {
   connection_info: &'a ConnectionInfo,
}

impl<'a> Appender<'a> {
    pub fn new(connection_info: &'a ConnectionInfo) -> Appender {
        Appender { connection_info: connection_info }
    }

    pub fn append_to_stream(&self, stream_name: &str, expected_version: ExpectedVersion, events: Vec<Event>) -> Result<()> {
        let events_as_json : Vec<String> = events.iter().map(|e| {
            format!(r#"{{
                      "eventType": "{}",
                      "eventId": "{}",
                      "data": {}
                    }}"#,
                    e.event_type.to_string(),
                    e.event_id.hyphenated().to_string(),
                    e.data.clone().unwrap()) //TODO Eliminate `clone` and deal with `unwrap`.
        }).collect::<Vec<String>>();
        let events_json: String = format!("[{}]", events_as_json.join(","));

        let client = Client::default();

        let result = client.post(&self.url(stream_name))
            .headers(self.build_headers(expected_version))
            .body(&events_json)
            .send();

        self.handle_result(result)
    }

    fn build_headers(&self, expected_version: ExpectedVersion) -> Headers {
        let mut headers = Headers::new();
        headers.set(
            ContentType(Mime(TopLevel::Application, SubLevel::Ext("vnd.eventstore.events+json".to_owned()), vec![]))
        );
        headers.set(ESExpectedVersion(expected_version.into()));

        headers
    }

    fn url(&self, stream_name: &str) -> String {
        format!("http://{}:{}/streams/{}",
                self.connection_info.host,
                self.connection_info.port,
                stream_name)
    }

    //TODO Find better name. `handle_...` supposes no return value.
    fn handle_result(&self, result: HyperResult<HyperResponse>) -> Result<()> {
        match result {
            Ok(response) => {
                match response.status {
                    StatusCode::Created => Ok(()),
                    StatusCode::BadRequest => self.handle_bad_request_on_append(response),
                    _ => self.panic_showing(&response)
                }
            },
            Err(err) => Err(HesError::UserError(UserErrorKind::Http(err)))
        }
    }

    fn handle_bad_request_on_append(&self, response: HyperResponse) -> Result<()> {
        // RawStatus(400, ref reason_phrase) => {
        //   Response { status: BadRequest, headers:
        //     Headers { Access-Control-Allow-Headers: Content-Type, X-Requested-With,
        //               X-Forwarded-Host, X-PINGOTHER, Authorization, ES-LongPoll,
        //               ES-ExpectedVersion, ES-EventId, ES-EventType, ES-RequiresMaster,
        //               ES-HardDelete, ES-ResolveLinkTo,
        //               Content-Type: text/plain; charset=utf-8,
        //               Content-Length: 0,
        //               Date: Wed, 12 Oct 2016 16:24:28 GMT,
        //               Connection: close,
        //               Access-Control-Allow-Origin: *,
        // -->           ES-CurrentVersion: -1,
        //               Access-Control-Expose-Headers: Location, ES-Position, ES-CurrentVersion,
        //               Access-Control-Allow-Methods: POST, DELETE, GET, OPTIONS, Server: Mono-HTTPAPI/1.0, },
        //     version: Http11,
        //     url: "http://127.0.0.1:2113/streams/task-c0340f57a914468ea6b48f7dff3519dc",
        // --> status_raw: RawStatus(400, "Wrong expected EventNumber"),
        //     message: Http11Message { is_proxied: false, method: None, stream: Wrapper { obj: Some(Reading(SizedReader(remaining=0))) } } }
        let is_wrong_expected_number = { response.status_raw().1 == WRONG_EXPECTED_EVENT_NUMBER };

        let error_kind = if is_wrong_expected_number {
            let version = self.expected_version(&response);
            UserErrorKind::EventNumberMismatch(version)
        } else {
            UserErrorKind::BadRequest(response)
        };

        Err(HesError::UserError(error_kind))
    }

    fn expected_version(&self, response: &HyperResponse) -> Option<ExpectedVersion> {
        response.headers.get::<ESCurrentVersion>()
            .and_then(|header| Some(ExpectedVersion::from(header.to_string())))
    }

    fn panic_showing(&self, response: &HyperResponse) -> ! {
        panic!("hyper::status::StatusCode {} Response: {:?}", response.status, response)
    }
}
<|endoftext|>


<commit_before>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem;
use smallvec::SmallVec;
use syntax::ast::CRATE_NODE_ID;
use ty::context::TyCtxt;
use ty::{DefId, DefIdTree};

/// Represents a forest of DefIds closed under the ancestor relation. That is,
/// if a DefId representing a module is contained in the forest then all
/// DefIds defined in that module or submodules are also implicitly contained
/// in the forest.
///
/// This is used to represent a set of modules in which a type is visibly
/// uninhabited.
#[derive(Clone)]
pub struct DefIdForest {
    /// The minimal set of DefIds required to represent the whole set.
    /// If A and B are DefIds in the DefIdForest, and A is a descendant
    /// of B, then only B will be in root_ids.
    /// We use a SmallVec here because (for its use for caching inhabitedness)
    /// its rare that this will contain even two ids.
    root_ids: SmallVec<[DefId; 1]>,
}

impl<'a, 'gcx, 'tcx> DefIdForest {
    /// Create an empty forest.
    pub fn empty() -> DefIdForest {
        DefIdForest {
            root_ids: SmallVec::new(),
        }
    }

    /// Create a forest consisting of a single tree representing the entire
    /// crate.
    #[inline]
    pub fn full(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest {
        let crate_id = tcx.hir().local_def_id(CRATE_NODE_ID);
        DefIdForest::from_id(crate_id)
    }

    /// Create a forest containing a DefId and all its descendants.
    pub fn from_id(id: DefId) -> DefIdForest {
        let mut root_ids = SmallVec::new();
        root_ids.push(id);
        DefIdForest {
            root_ids,
        }
    }

    /// Test whether the forest is empty.
    pub fn is_empty(&self) -> bool {
        self.root_ids.is_empty()
    }

    /// Test whether the forest contains a given DefId.
    pub fn contains(&self,
                    tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    id: DefId) -> bool
    {
        self.root_ids.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
    }

    /// Calculate the intersection of a collection of forests.
    pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                           iter: I) -> DefIdForest
            where I: IntoIterator<Item=DefIdForest>
    {
        let mut ret = DefIdForest::full(tcx);
        let mut next_ret = SmallVec::new();
        let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
        for next_forest in iter {
            for id in ret.root_ids.drain() {
                if next_forest.contains(tcx, id) {
                    next_ret.push(id);
                } else {
                    old_ret.push(id);
                }
            }
            ret.root_ids.extend(old_ret.drain());

            next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id)));

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain();
        }
        ret
    }

    /// Calculate the union of a collection of forests.
    pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    iter: I) -> DefIdForest
            where I: IntoIterator<Item=DefIdForest>
    {
        let mut ret = DefIdForest::empty();
        let mut next_ret = SmallVec::new();
        for next_forest in iter {
            next_ret.extend(ret.root_ids.drain().filter(|&id| !next_forest.contains(tcx, id)));

            for id in next_forest.root_ids {
                if !next_ret.contains(&id) {
                    next_ret.push(id);
                }
            }

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain();
        }
        ret
    }
}

<commit_msg>Short-circuit DefIdForest::intersection()<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

use std::mem;
use smallvec::SmallVec;
use syntax::ast::CRATE_NODE_ID;
use ty::context::TyCtxt;
use ty::{DefId, DefIdTree};

/// Represents a forest of DefIds closed under the ancestor relation. That is,
/// if a DefId representing a module is contained in the forest then all
/// DefIds defined in that module or submodules are also implicitly contained
/// in the forest.
///
/// This is used to represent a set of modules in which a type is visibly
/// uninhabited.
#[derive(Clone)]
pub struct DefIdForest {
    /// The minimal set of DefIds required to represent the whole set.
    /// If A and B are DefIds in the DefIdForest, and A is a descendant
    /// of B, then only B will be in root_ids.
    /// We use a SmallVec here because (for its use for caching inhabitedness)
    /// its rare that this will contain even two ids.
    root_ids: SmallVec<[DefId; 1]>,
}

impl<'a, 'gcx, 'tcx> DefIdForest {
    /// Create an empty forest.
    pub fn empty() -> DefIdForest {
        DefIdForest {
            root_ids: SmallVec::new(),
        }
    }

    /// Create a forest consisting of a single tree representing the entire
    /// crate.
    #[inline]
    pub fn full(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest {
        let crate_id = tcx.hir().local_def_id(CRATE_NODE_ID);
        DefIdForest::from_id(crate_id)
    }

    /// Create a forest containing a DefId and all its descendants.
    pub fn from_id(id: DefId) -> DefIdForest {
        let mut root_ids = SmallVec::new();
        root_ids.push(id);
        DefIdForest {
            root_ids,
        }
    }

    /// Test whether the forest is empty.
    pub fn is_empty(&self) -> bool {
        self.root_ids.is_empty()
    }

    /// Test whether the forest contains a given DefId.
    pub fn contains(&self,
                    tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    id: DefId) -> bool
    {
        self.root_ids.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
    }

    /// Calculate the intersection of a collection of forests.
    pub fn intersection<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                           iter: I) -> DefIdForest
            where I: IntoIterator<Item=DefIdForest>
    {
        let mut iter = iter.into_iter();
        let mut ret = if let Some(first) = iter.next() {
            first
        } else {
            return DefIdForest::full(tcx);
        };

        let mut next_ret = SmallVec::new();
        let mut old_ret: SmallVec<[DefId; 1]> = SmallVec::new();
        for next_forest in iter {
            // No need to continue if the intersection is already empty.
            if ret.is_empty() {
                break;
            }

            for id in ret.root_ids.drain() {
                if next_forest.contains(tcx, id) {
                    next_ret.push(id);
                } else {
                    old_ret.push(id);
                }
            }
            ret.root_ids.extend(old_ret.drain());

            next_ret.extend(next_forest.root_ids.into_iter().filter(|&id| ret.contains(tcx, id)));

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain();
        }
        ret
    }

    /// Calculate the union of a collection of forests.
    pub fn union<I>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                    iter: I) -> DefIdForest
            where I: IntoIterator<Item=DefIdForest>
    {
        let mut ret = DefIdForest::empty();
        let mut next_ret = SmallVec::new();
        for next_forest in iter {
            next_ret.extend(ret.root_ids.drain().filter(|&id| !next_forest.contains(tcx, id)));

            for id in next_forest.root_ids {
                if !next_ret.contains(&id) {
                    next_ret.push(id);
                }
            }

            mem::swap(&mut next_ret, &mut ret.root_ids);
            next_ret.drain();
        }
        ret
    }
}

<|endoftext|>


<commit_before>extern crate glib;
extern crate gdk;
extern crate gio;
extern crate gtk;

use gio::prelude::*;
use gtk::prelude::*;

use std::env::args;

macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move |$($p:tt),*| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
                move |$(clone!(@param $p),)*| $body
        }
    );
}

struct Data {
    description: String,
}

fn create_list_model() -> gtk::ListStore {
    let col_types: [gtk::Type; 1] = [
        gtk::Type::String,
    ];

    let data: [Data; 4] = [
        Data {description: "France".to_string()},
        Data {description: "Italy".to_string()},
        Data {description: "Siberia".to_string()},
        Data {description: "Switzerland".to_string()},
    ];
    let store = gtk::ListStore::new(&col_types);
    let col_indices: [u32; 1] = [0];
    for (_, d) in data.iter().enumerate() {
        let values: [&dyn ToValue; 1] = [
            &d.description,
        ];
        store.set(&store.append(), &col_indices, &values);
    }
    store
}

fn build_ui(application: &gtk::Application) {

    // create the main window
    let window = gtk::ApplicationWindow::new(application);
    window.set_title("Entry with autocompletion");
    window.set_border_width(5);
    window.set_position(gtk::WindowPosition::Center);
    window.set_default_size(840, 480);

    // Create a title label
    let win_title = gtk::Label::new(None);
    win_title.set_markup("<big>Which country would you like to spend a holiday in?</big>");

    // Create an EntryCompletion widget
    let completion_countries = gtk::EntryCompletion::new();
    // Use the first (and only) column available to set the autocompletion text
    completion_countries.set_text_column(0);
    // how many keystrokes to wait before attempting to autocomplete?
    completion_countries.set_minimum_key_length(1);
    // whether the completions should be presented in a popup window
    completion_countries.set_popup_completion(true);

    // Create a ListStore of items
    // These will be the source for the autocompletion
    // as the user types into the field
    // For a more evolved example of ListStore see src/bin/list_store.rs
    let ls = create_list_model();
    completion_countries.set_model(Some(&ls));

    let input_field = gtk::Entry::new();
    input_field.set_completion(Some(&completion_countries));

    let row = gtk::Box::new(gtk::Orientation::Vertical, 5);
    row.add(&win_title);
    row.pack_start(&input_field, false, false, 10);

    // window.add(&win_title);
    window.add(&row);

    // show everything
    window.show_all();
}

fn main() {
    let application = gtk::Application::new("com.github.gtk-rs.examples.entry-completion",
                                            Default::default())
        .expect("Initialization failed...");
    application.connect_activate(|app| {
        build_ui(app);
    });

    // When activated, shuts down the application
    let quit = gio::SimpleAction::new("quit", None);
    quit.connect_activate(clone!(application => move |_action, _parameter| {
        application.quit();
    }));
    application.set_accels_for_action("app.quit", &["<Primary>Q"]);
    application.add_action(&quit);

    // Run the application
    application.run(&args().collect::<Vec<_>>());
}
<commit_msg>Fixes<commit_after>//! # Entry completion example
//!
//! This example demonstrates how to build a list of items and use them
//! to autocomplete a field as the user types in something.

extern crate glib;
extern crate gdk;
extern crate gio;
extern crate gtk;

use gio::prelude::*;
use gtk::prelude::*;

use std::env::args;

macro_rules! clone {
    (@param _) => ( _ );
    (@param $x:ident) => ( $x );
    ($($n:ident),+ => move |$($p:tt),*| $body:expr) => (
        {
            $( let $n = $n.clone(); )+
                move |$(clone!(@param $p),)*| $body
        }
    );
}

struct Data {
    description: String,
}

fn create_list_model() -> gtk::ListStore {
    let col_types: [gtk::Type; 1] = [
        gtk::Type::String,
    ];

    let data: [Data; 4] = [
        Data {description: "France".to_string()},
        Data {description: "Italy".to_string()},
        Data {description: "Sweden".to_string()},
        Data {description: "Switzerland".to_string()},
    ];
    let store = gtk::ListStore::new(&col_types);
    let col_indices: [u32; 1] = [0];
    for d in data.iter() {
        let values: [&dyn ToValue; 1] = [
            &d.description,
        ];
        store.set(&store.append(), &col_indices, &values);
    }
    store
}

fn build_ui(application: &gtk::Application) {

    // create the main window
    let window = gtk::ApplicationWindow::new(application);
    window.set_title("Entry with autocompletion");
    window.set_border_width(5);
    window.set_position(gtk::WindowPosition::Center);
    window.set_default_size(840, 480);

    // Create a title label
    let win_title = gtk::Label::new(None);
    win_title.set_markup("<big>Which country would you like to spend a holiday in?</big>");

    // Create an EntryCompletion widget
    let completion_countries = gtk::EntryCompletion::new();
    // Use the first (and only) column available to set the autocompletion text
    completion_countries.set_text_column(0);
    // how many keystrokes to wait before attempting to autocomplete?
    completion_countries.set_minimum_key_length(1);
    // whether the completions should be presented in a popup window
    completion_countries.set_popup_completion(true);

    // Create a ListStore of items
    // These will be the source for the autocompletion
    // as the user types into the field
    // For a more evolved example of ListStore see src/bin/list_store.rs
    let ls = create_list_model();
    completion_countries.set_model(Some(&ls));

    let input_field = gtk::Entry::new();
    input_field.set_completion(Some(&completion_countries));

    let row = gtk::Box::new(gtk::Orientation::Vertical, 5);
    row.add(&win_title);
    row.pack_start(&input_field, false, false, 10);

    // window.add(&win_title);
    window.add(&row);

    // show everything
    window.show_all();
}

fn main() {
    let application = gtk::Application::new(Some("com.github.gtk-rs.examples.entry-completion"),
                                            Default::default())
        .expect("Initialization failed...");
    application.connect_activate(|app| {
        build_ui(app);
    });

    // When activated, shuts down the application
    let quit = gio::SimpleAction::new("quit", None);
    quit.connect_activate(clone!(application => move |_action, _parameter| {
        application.quit();
    }));
    application.set_accels_for_action("app.quit", &["<Primary>Q"]);
    application.add_action(&quit);

    // Run the application
    application.run(&args().collect::<Vec<_>>());
}
<|endoftext|>


<commit_before>extern crate wm_daemons;
use wm_daemons::config::{load_config, load_config_path};
use wm_daemons::dbus_listen::{CallbackMap, DBusInfo, match_signal};
use wm_daemons::exec::{CommandLine, read_command_line_from_config, run_command_line};

#[macro_use]
extern crate clap;
use clap::{Arg, App};

extern crate dbus;
use self::dbus::{Connection, BusType, Message};

use std::error::Error;
use std::path::Path;

struct Context {
    on_lock: Option<CommandLine>,
    on_unlock: Option<CommandLine>,
}

fn run_program(action: &str, cmd_line: &Option<CommandLine>) -> () {
    cmd_line.as_ref().map(|ref cmd| {
        let res = run_command_line(&cmd);
        if res.is_err() {
            println!("failed to handle '{}' action: {}", action, res.err().unwrap());
        }
    });
}

fn handle_signal(ctx: Context, info: &Message) -> Context {
    let (_, _, _, member) = info.headers();

    member.map(|member_name| {
        if member_name == "Lock" {
            run_program("lock", &ctx.on_lock);
        } else if member_name == "Unlock" {
            run_program("unlock", &ctx.on_unlock);
        }
    });

    ctx
}

fn try_main() -> Result<(), Box<Error>> {
    let matches = App::new("wm-session-agent")
        .version(&crate_version!()[..])
        .author("Ben Boeckel <mathstuf@gmail.com>")
        .about("Listens for logind's Lock and Unlock signals")
        .arg(Arg::with_name("CONFIG")
                .short("c")
                .long("config")
                .help("Path to the configuration file")
                .takes_value(true))
        .arg(Arg::with_name("SESSION")
                .short("s")
                .long("session")
                .required(true)
                .help("Session ID to listen on")
                .takes_value(true))
        .get_matches();

    let conf = try!(if matches.is_present("CONFIG") {
            load_config_path(Path::new(matches.value_of("CONFIG").unwrap()))
        } else {
            load_config("wm-session-agent", "config")
        });
    let ctx = Context {
        on_lock: read_command_line_from_config(&conf, "actions.lock"),
        on_unlock: read_command_line_from_config(&conf, "actions.unlock"),
    };

    let sid = matches.value_of("SESSION").unwrap();
    let spath = format!("/org/freedesktop/login1/session/_{}", sid);

    let conn = try!(Connection::get_private(BusType::System));

    let cbs: CallbackMap<Context> = vec![
        (DBusInfo {
            path: None,
            object: None,
            member: Some("Lock".to_string()),
        }, handle_signal),
        (DBusInfo {
            path: None,
            object: None,
            member: Some("Unlock".to_string()),
        }, handle_signal),
    ];

    let match_str = format!("type='signal',interface='org.freedesktop.login1.Session',path='{}'", spath);
    try!(conn.add_match(&match_str[..]));

    conn.iter(100).fold(ctx, |inner_ctx, item| {
        match_signal(inner_ctx, &cbs, item)
    });

    Ok(())
}

fn main() -> () {
    if let Err(err) = try_main() {
        panic!("{}", err.description());
    }
}
<commit_msg>wm-session-agent: use XDG_SESSION_ID if available<commit_after>extern crate wm_daemons;
use wm_daemons::config::{load_config, load_config_path};
use wm_daemons::dbus_listen::{CallbackMap, DBusInfo, match_signal};
use wm_daemons::exec::{CommandLine, read_command_line_from_config, run_command_line};

#[macro_use]
extern crate clap;
use clap::{Arg, App};

extern crate dbus;
use self::dbus::{Connection, BusType, Message};

use std::env::var;
use std::error::Error;
use std::path::Path;

struct Context {
    on_lock: Option<CommandLine>,
    on_unlock: Option<CommandLine>,
}

fn run_program(action: &str, cmd_line: &Option<CommandLine>) -> () {
    cmd_line.as_ref().map(|ref cmd| {
        let res = run_command_line(&cmd);
        if res.is_err() {
            println!("failed to handle '{}' action: {}", action, res.err().unwrap());
        }
    });
}

fn handle_signal(ctx: Context, info: &Message) -> Context {
    let (_, _, _, member) = info.headers();

    member.map(|member_name| {
        if member_name == "Lock" {
            run_program("lock", &ctx.on_lock);
        } else if member_name == "Unlock" {
            run_program("unlock", &ctx.on_unlock);
        }
    });

    ctx
}

fn try_main() -> Result<(), Box<Error>> {
    let matches = App::new("wm-session-agent")
        .version(&crate_version!()[..])
        .author("Ben Boeckel <mathstuf@gmail.com>")
        .about("Listens for logind's Lock and Unlock signals")
        .arg(Arg::with_name("CONFIG")
                .short("c")
                .long("config")
                .help("Path to the configuration file")
                .takes_value(true))
        .arg(Arg::with_name("SESSION")
                .short("s")
                .long("session")
                .help("Session ID to listen on")
                .takes_value(true))
        .get_matches();

    let conf = try!(if matches.is_present("CONFIG") {
            load_config_path(Path::new(matches.value_of("CONFIG").unwrap()))
        } else {
            load_config("wm-session-agent", "config")
        });
    let ctx = Context {
        on_lock: read_command_line_from_config(&conf, "actions.lock"),
        on_unlock: read_command_line_from_config(&conf, "actions.unlock"),
    };

    let sid = match matches.value_of("SESSION") {
        Some(sid) => sid.to_string(),
        None => match var("XDG_SESSION_ID") {
            Ok(sid) => sid,
            Err(err) => {
                println!("No session ID given or available: {}", err);
                return Err(Box::new(err));
            },
        },
    };
    let spath = format!("/org/freedesktop/login1/session/_{}", sid);

    let conn = try!(Connection::get_private(BusType::System));

    let cbs: CallbackMap<Context> = vec![
        (DBusInfo {
            path: None,
            object: None,
            member: Some("Lock".to_string()),
        }, handle_signal),
        (DBusInfo {
            path: None,
            object: None,
            member: Some("Unlock".to_string()),
        }, handle_signal),
    ];

    let match_str = format!("type='signal',interface='org.freedesktop.login1.Session',path='{}'", spath);
    try!(conn.add_match(&match_str[..]));

    conn.iter(100).fold(ctx, |inner_ctx, item| {
        match_signal(inner_ctx, &cbs, item)
    });

    Ok(())
}

fn main() -> () {
    if let Err(err) = try_main() {
        panic!("{}", err.description());
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::sync::RwLock;
use std::collections::HashSet;
use std::slice;
use std::str;
use std::mem;

pub fn leek(s: String) -> &'static str {
    let ptr = s.as_ptr();
    let len = s.len();
    mem::forget(s);
    unsafe {
        let slice = slice::from_raw_parts(ptr, len);
        str::from_utf8_unchecked(slice)
    }
}

lazy_static! {
    static ref STRING_CASHE: RwLock<HashSet<&'static str>> =
        RwLock::new(HashSet::new());
}

#[derive(Eq, PartialEq, Hash, Clone, Copy)]
pub struct InternedString {
    ptr: *const u8,
    len: usize,
}

impl InternedString {
    pub fn new(str: &str) -> InternedString {
        let mut cache = STRING_CASHE.write().unwrap();
        if let Some(&s) = cache.get(str) {
            return InternedString { ptr: s.as_ptr(), len: s.len() };
        }
        let s = leek(str.to_string());
        cache.insert(s);
        InternedString { ptr: s.as_ptr(), len: s.len() }
    }
    pub fn to_inner(&self) -> &'static str {
        unsafe {
            let slice = slice::from_raw_parts(self.ptr, self.len);
            str::from_utf8_unchecked(slice)
        }
    }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "InternedString {{ {} }}", self.to_inner())
    }
}
<commit_msg>use `into_boxed_str` to shrink before we leek<commit_after>use std::fmt;
use std::sync::RwLock;
use std::collections::HashSet;
use std::slice;
use std::str;
use std::mem;
use std::cmp::Ordering;

pub fn leek(s: String) -> &'static str {
    let boxed = s.into_boxed_str();
    let ptr = boxed.as_ptr();
    let len = boxed.len();
    mem::forget(boxed);
    unsafe {
        let slice = slice::from_raw_parts(ptr, len);
        str::from_utf8_unchecked(slice)
    }
}

lazy_static! {
    static ref STRING_CASHE: RwLock<HashSet<&'static str>> =
        RwLock::new(HashSet::new());
}

#[derive(Eq, PartialEq, Hash, Clone, Copy)]
pub struct InternedString {
    ptr: *const u8,
    len: usize,
}

impl InternedString {
    pub fn new(str: &str) -> InternedString {
        let mut cache = STRING_CASHE.write().unwrap();
        if let Some(&s) = cache.get(str) {
            return InternedString { ptr: s.as_ptr(), len: s.len() };
        }
        let s = leek(str.to_string());
        cache.insert(s);
        InternedString { ptr: s.as_ptr(), len: s.len() }
    }
    pub fn to_inner(&self) -> &'static str {
        unsafe {
            let slice = slice::from_raw_parts(self.ptr, self.len);
            str::from_utf8_unchecked(slice)
        }
    }
}

impl fmt::Debug for InternedString {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "InternedString {{ {} }}", self.to_inner())
    }
}

impl Ord for InternedString {
    fn cmp(&self, other: &InternedString) -> Ordering {
        self.to_inner().cmp(&other.to_inner())
    }
}

impl PartialOrd for InternedString {
    fn partial_cmp(&self, other: &InternedString) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

unsafe impl Send for InternedString {}
unsafe impl Sync for InternedString {}<|endoftext|>


<commit_before>use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{Deserialize, Deserializer, Unexpected, Error};
use serde_json::{Value, from_value};

#[derive(Debug)]
struct Version;

impl Serialize for Version {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_str("2.0")
    }
}

impl Deserialize for Version {
    fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
        // The version is actually a string
        let parsed: String = Deserialize::deserialize(deserializer)?;
        if parsed == "2.0" {
            Ok(Version)
        } else {
            Err(D::Error::invalid_value(Unexpected::Str(&parsed), &"value 2.0"))
        }
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Request {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
    // TODO: Make private?
    pub id: Value,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct RPCError {
    pub code: i64,
    pub message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<Value>,
}

#[derive(Debug, Deserialize)]
pub struct Response {
    pub result: Result<Value, RPCError>,
    pub id: Value,
}

impl Serialize for Response {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut sub = serializer.serialize_struct("Response", 2)?;
        sub.serialize_field("id", &self.id)?;
        match self.result {
            Ok(ref value) => sub.serialize_field("result", value),
            Err(ref err) => sub.serialize_field("error", err),
        }?;
        sub.end()
    }
}

#[derive(Debug, Serialize, Deserialize)]
pub struct Notification {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
}

#[derive(Debug)]
pub enum Message {
    Request(Request),
    Response(Response),
    Notification(Notification),
    Batch(Vec<Message>),
    Unmatched(Value),
}

impl Message {
    pub fn request(method: String, params: Option<Value>) -> Self {
        Message::Request(Request {
            jsonrpc: Version,
            method: method,
            params: params,
            // TODO!
            id: Value::Null,
        })
    }
    pub fn notification(method: String, params: Option<Value>) -> Self {
        Message::Notification(Notification {
            jsonrpc: Version,
            method: method,
            params: params,
        })
    }
    // TODO: Other constructors
}

impl Serialize for Message {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        match *self {
            Message::Request(ref req) => req.serialize(serializer),
            Message::Response(ref resp) => resp.serialize(serializer),
            Message::Notification(ref notif) => notif.serialize(serializer),
            Message::Batch(ref batch) => batch.serialize(serializer),
            Message::Unmatched(ref val) => val.serialize(serializer),
        }
    }
}

macro_rules! deser_branch {
    ($src:expr, $branch:ident) => {
        match from_value($src.clone()) {
            Ok(parsed) => return Ok(Message::$branch(parsed)),
            Err(_) => (),
        }
    };
}

impl Deserialize for Message {
    fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
        // Read it as a JSON (delegate the deserialization)
        let preparsed: Value = Deserialize::deserialize(deserializer)?;
        // And try decoding it as a concrete message type, one by one (and get a first match)
        deser_branch!(preparsed, Request);
        deser_branch!(preparsed, Response);
        deser_branch!(preparsed, Notification);
        deser_branch!(preparsed, Batch);
        Ok(Message::Unmatched(preparsed))
    }
}
<commit_msg>Some more handy traits to manipulate with Messages<commit_after>use std::str::FromStr;

use serde::ser::{Serialize, Serializer, SerializeStruct};
use serde::de::{Deserialize, Deserializer, Unexpected, Error};
use serde_json::{Value, from_value};

#[derive(Debug, Clone, PartialEq, Eq)]
struct Version;

impl Serialize for Version {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        serializer.serialize_str("2.0")
    }
}

impl Deserialize for Version {
    fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
        // The version is actually a string
        let parsed: String = Deserialize::deserialize(deserializer)?;
        if parsed == "2.0" {
            Ok(Version)
        } else {
            Err(D::Error::invalid_value(Unexpected::Str(&parsed), &"value 2.0"))
        }
    }
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Request {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
    // TODO: Make private?
    pub id: Value,
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct RPCError {
    pub code: i64,
    pub message: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub data: Option<Value>,
}

#[derive(Debug, Deserialize, Clone, PartialEq)]
pub struct Response {
    pub result: Result<Value, RPCError>,
    pub id: Value,
}

impl Serialize for Response {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        let mut sub = serializer.serialize_struct("Response", 2)?;
        sub.serialize_field("id", &self.id)?;
        match self.result {
            Ok(ref value) => sub.serialize_field("result", value),
            Err(ref err) => sub.serialize_field("error", err),
        }?;
        sub.end()
    }
}

#[derive(Debug, Serialize, Deserialize, Clone, PartialEq)]
pub struct Notification {
    jsonrpc: Version,
    pub method: String,
    #[serde(skip_serializing_if = "Option::is_none")]
    pub params: Option<Value>,
}

#[derive(Debug, Clone, PartialEq)]
pub enum Message {
    Request(Request),
    Response(Response),
    Notification(Notification),
    Batch(Vec<Message>),
    Unmatched(Value),
}

impl Message {
    pub fn request(method: String, params: Option<Value>) -> Self {
        Message::Request(Request {
            jsonrpc: Version,
            method: method,
            params: params,
            // TODO!
            id: Value::Null,
        })
    }
    pub fn notification(method: String, params: Option<Value>) -> Self {
        Message::Notification(Notification {
            jsonrpc: Version,
            method: method,
            params: params,
        })
    }
    // TODO: Other constructors
}

impl Serialize for Message {
    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
        match *self {
            Message::Request(ref req) => req.serialize(serializer),
            Message::Response(ref resp) => resp.serialize(serializer),
            Message::Notification(ref notif) => notif.serialize(serializer),
            Message::Batch(ref batch) => batch.serialize(serializer),
            Message::Unmatched(ref val) => val.serialize(serializer),
        }
    }
}

macro_rules! deser_branch {
    ($src:expr, $branch:ident) => {
        match from_value($src.clone()) {
            Ok(parsed) => return Message::$branch(parsed),
            Err(_) => (),
        }
    };
}

impl From<Value> for Message {
    fn from(v: Value) -> Self {
        // Try decoding it by each branch in sequence, taking the first one that matches
        deser_branch!(v, Request);
        deser_branch!(v, Response);
        deser_branch!(v, Notification);
        deser_branch!(v, Batch);
        Message::Unmatched(v)
    }
}

impl Deserialize for Message {
    fn deserialize<D: Deserializer>(deserializer: D) -> Result<Self, D::Error> {
        // Read it as a JSON (delegate the deserialization)
        let preparsed: Value = Deserialize::deserialize(deserializer)?;
        // Convert it
        Ok(Self::from(preparsed))
    }
}

impl FromStr for Message {
    type Err = ::serde_json::error::Error;
    fn from_str(s: &str) -> Result<Self, Self::Err> {
        ::serde_json::de::from_str(s)
    }
}

impl Into<String> for Message {
    fn into(self) -> String {
        ::serde_json::ser::to_string(&self).unwrap()
    }
}
<|endoftext|>


<commit_before>pub struct BaseMonster {
	pub name:           String,
	pub size_add:       u8,
	pub zoom_pct:       u16,
	pub max_life:       u32,
	pub lvl:            u16,
	pub born_action:    u16,
	pub act_res_ctrl:   u8,
	pub asb:            u8,
	pub adb:            u8,
	pub body_type:      u8,
	pub type_id:        String,
	pub anti_type:      u8,
	pub armet:          u8,
	pub armet_color:    u8,
	pub r_weapon:       u8,
	pub l_weapon:       u8,
	pub l_weapon_color: u8,
	pub misc:           u8,
	pub mount:          u8,
	pub battle_lvl:     u8,
	pub extra_xp:       u8,
	pub stc_type:       u8,
	pub born_effect:    String,
	pub born_sound:     String
}

mod serializer {
    use super::BaseMonster;
    use serializer::{IniEntrySerializer, StringSerializableStructure};

    impl StringSerializableStructure for BaseMonster {
		fn serialize(&self) -> String {
			let mut serializer: IniEntrySerializer = IniEntrySerializer::new();

			serializer.add_section(&self.name);
			serializer.add_entry("SizeAdd", &self.size_add);
			serializer.add_entry("ZoomPercent", &self.zoom_pct);
			serializer.add_entry("MaxLife", &self.max_life);
			serializer.add_entry("Level", &self.lvl);
			serializer.add_entry("BornAction", &self.born_action);
			serializer.add_entry("ActResCtrl", &self.act_res_ctrl);
			serializer.add_entry("ASB", &self.asb);
			serializer.add_entry("ADB", &self.adb);
			serializer.add_entry("BodyType", &self.body_type);
			serializer.add_entry("TypeID", &self.type_id);
			serializer.add_entry("AntiType", &self.anti_type);
			serializer.add_entry("Armet", &self.armet);
			serializer.add_entry("ArmetColor", &self.armet_color);
			serializer.add_entry("RWeapon", &self.r_weapon);
			serializer.add_entry("LWeapon", &self.l_weapon);
			serializer.add_entry("LWeaponColor", &self.l_weapon_color);
			serializer.add_entry("Misc", &self.misc);
			serializer.add_entry("Mount", &self.mount);
			serializer.add_entry("BattleLev", &self.battle_lvl);
			serializer.add_entry("ExtraExp", &self.extra_xp);
			serializer.add_entry("StcType", &self.stc_type);
			serializer.add_entry("BornEffect", &self.born_effect);
			serializer.add_entry("BornSound", &self.born_sound);

			serializer.get_buffer()
		}
    }
}

mod parser {
	use super::BaseMonster;
	use parser::{IniEntryParser, IniEntryParserError, IniEntryParseable};

	impl IniEntryParseable<BaseMonster> for BaseMonster {
		fn from_section_string(section: &String) -> Result<BaseMonster, IniEntryParserError> {
			match IniEntryParser::new_from_str(section.clone()) {
				Result::Ok(parser) => {
					let monster = BaseMonster {
						name: parser.get_section(),
						size_add:    parser.get_entry_as("SizeAdd")?,
						zoom_pct:    parser.get_entry_as("ZoomPercent")?,
						max_life:    parser.get_entry_as("MaxLife")?,
						lvl:    parser.get_entry_as("Level")?,
						born_action:    parser.get_entry_as("BornAction")?,
						act_res_ctrl:    parser.get_entry_as("ActResCtrl")?,
						asb:    parser.get_entry_as("ASB")?,
						adb:    parser.get_entry_as("ADB")?,
						body_type:    parser.get_entry_as("BodyType")?,
						type_id:    parser.get_entry("TypeID")?,
						anti_type:    parser.get_entry_as("AntiType")?,
						armet:    parser.get_entry_as("Armet")?,
						armet_color:    parser.get_entry_as("ArmetColor")?,
						r_weapon:    parser.get_entry_as("RWeapon")?,
						l_weapon:    parser.get_entry_as("LWeapon")?,
						l_weapon_color:    parser.get_entry_as("LWeaponColor")?,
						misc:    parser.get_entry_as("Misc")?,
						mount:    parser.get_entry_as("Mount")?,
						battle_lvl:    parser.get_entry_as("BattleLev")?,
						extra_xp:    parser.get_entry_as("ExtraExp")?,
						stc_type:    parser.get_entry_as("StcType")?,
						born_effect:    parser.get_entry("BornEffect")?,
						born_sound:    parser.get_entry("BornSound")?
					};

					return Result::Ok(monster);
				},

				Result::Err(err) => {
					return Result::Err(err);
				}
			}
		}
	}
}<commit_msg>Reindent<commit_after>pub struct BaseMonster {
	pub name:           String,
	pub size_add:       u8,
	pub zoom_pct:       u16,
	pub max_life:       u32,
	pub lvl:            u16,
	pub born_action:    u16,
	pub act_res_ctrl:   u8,
	pub asb:            u8,
	pub adb:            u8,
	pub body_type:      u8,
	pub type_id:        String,
	pub anti_type:      u8,
	pub armet:          u8,
	pub armet_color:    u8,
	pub r_weapon:       u8,
	pub l_weapon:       u8,
	pub l_weapon_color: u8,
	pub misc:           u8,
	pub mount:          u8,
	pub battle_lvl:     u8,
	pub extra_xp:       u8,
	pub stc_type:       u8,
	pub born_effect:    String,
	pub born_sound:     String
}

mod serializer {
    use super::BaseMonster;
    use serializer::{IniEntrySerializer, StringSerializableStructure};

    impl StringSerializableStructure for BaseMonster {
		fn serialize(&self) -> String {
			let mut serializer: IniEntrySerializer = IniEntrySerializer::new();

			serializer.add_section(&self.name);
			serializer.add_entry("SizeAdd", &self.size_add);
			serializer.add_entry("ZoomPercent", &self.zoom_pct);
			serializer.add_entry("MaxLife", &self.max_life);
			serializer.add_entry("Level", &self.lvl);
			serializer.add_entry("BornAction", &self.born_action);
			serializer.add_entry("ActResCtrl", &self.act_res_ctrl);
			serializer.add_entry("ASB", &self.asb);
			serializer.add_entry("ADB", &self.adb);
			serializer.add_entry("BodyType", &self.body_type);
			serializer.add_entry("TypeID", &self.type_id);
			serializer.add_entry("AntiType", &self.anti_type);
			serializer.add_entry("Armet", &self.armet);
			serializer.add_entry("ArmetColor", &self.armet_color);
			serializer.add_entry("RWeapon", &self.r_weapon);
			serializer.add_entry("LWeapon", &self.l_weapon);
			serializer.add_entry("LWeaponColor", &self.l_weapon_color);
			serializer.add_entry("Misc", &self.misc);
			serializer.add_entry("Mount", &self.mount);
			serializer.add_entry("BattleLev", &self.battle_lvl);
			serializer.add_entry("ExtraExp", &self.extra_xp);
			serializer.add_entry("StcType", &self.stc_type);
			serializer.add_entry("BornEffect", &self.born_effect);
			serializer.add_entry("BornSound", &self.born_sound);

			serializer.get_buffer()
		}
    }
}

mod parser {
	use super::BaseMonster;
	use parser::{IniEntryParser, IniEntryParserError, IniEntryParseable};

	impl IniEntryParseable<BaseMonster> for BaseMonster {
		fn from_section_string(section: &String) -> Result<BaseMonster, IniEntryParserError> {
			match IniEntryParser::new_from_str(section.clone()) {
				Result::Ok(parser) => {
					let monster = BaseMonster {
						name:             parser.get_section(),

						size_add:         parser.get_entry_as("SizeAdd")?,
						zoom_pct:         parser.get_entry_as("ZoomPercent")?,
						max_life:         parser.get_entry_as("MaxLife")?,
						lvl:              parser.get_entry_as("Level")?,
						born_action:      parser.get_entry_as("BornAction")?,
						act_res_ctrl:     parser.get_entry_as("ActResCtrl")?,
						asb:              parser.get_entry_as("ASB")?,
						adb:              parser.get_entry_as("ADB")?,
						body_type:        parser.get_entry_as("BodyType")?,
						type_id:          parser.get_entry("TypeID")?,
						anti_type:        parser.get_entry_as("AntiType")?,
						armet:            parser.get_entry_as("Armet")?,
						armet_color:      parser.get_entry_as("ArmetColor")?,
						r_weapon:         parser.get_entry_as("RWeapon")?,
						l_weapon:         parser.get_entry_as("LWeapon")?,
						l_weapon_color:   parser.get_entry_as("LWeaponColor")?,
						misc:             parser.get_entry_as("Misc")?,
						mount:            parser.get_entry_as("Mount")?,
						battle_lvl:       parser.get_entry_as("BattleLev")?,
						extra_xp:         parser.get_entry_as("ExtraExp")?,
						stc_type:         parser.get_entry_as("StcType")?,
						born_effect:      parser.get_entry("BornEffect")?,
						born_sound:       parser.get_entry("BornSound")?
					};

					return Result::Ok(monster);
				},

				Result::Err(err) => {
					return Result::Err(err);
				}
			}
		}
	}
}<|endoftext|>


<commit_before>pub mod if_;
<commit_msg>Added note regarding naming.<commit_after>// To avoid clashing with the keyword "if", we use "if_" as the module name.
// The original header is called "net/if.h".
pub mod if_;
<|endoftext|>


<commit_before>use std::cmp;

/// A FIR filter for convolving with a series of samples.
pub struct FIRFilter<'a> {
    /// The filter coefficients for multiplying with the input signal, represents bi.
    coefs: &'a [f64],
    /// A ring buffer of samples in the signal, represents x[i].
    history: Vec<f64>,
    /// The index of the most-recently added sample, represents n in x[n].
    idx: usize,
}

impl<'a> FIRFilter<'a> {
    /// Construct an order-N filter with the given N+1 coefficients.
    pub fn new(coefs: &'a [f64]) -> FIRFilter<'a> {
        FIRFilter {
            coefs: coefs,
            history: vec![0.0; coefs.len()],
            idx: 0,
        }
    }

    /// Perform the convolution with the current history of samples. Calculates
    /// y[n] = c0*x[n] + c1*x[n-1] + cN*x[n-N].
    fn calc(&self) -> f64 {
        // Copy the current index so we can move backwards.
        let mut cur = self.idx;

        self.coefs.iter().fold(0.0, |s, &coef| {
            // Wrap around to the last sample after visiting the first.
            cur = cmp::min(cur - 1, self.history.len() - 1);
            // Accumulate the next term.
            s + coef * self.history[cur]
        })
    }

    /// Add a sample to the current history and calculate the convolution.
    pub fn feed(&mut self, sample: f64) -> f64 {
        // Store the given sample in the current history slot.
        self.history[self.idx] = sample;

        // Move to the next slot and wrap around.
        self.idx += 1;
        self.idx %= self.history.len();

        self.calc()
    }
}

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

        const COEFS: &'static [f64] = &[
            0.0,
            1.0,
            0.0,
            1.0,
        ];

        let mut f = FIRFilter::new(COEFS);

        assert!(f.feed(100.0) == 0.0);
        assert!(f.feed(200.0) == 100.0);
        assert!(f.feed(300.0) == 200.0);
        assert!(f.feed(400.0) == 400.0);
        assert!(f.feed(0.0) == 600.0);
        assert!(f.feed(0.0) == 300.0);
        assert!(f.feed(0.0) == 400.0);
        assert!(f.feed(0.0) == 0.0);
        assert!(f.feed(0.0) == 0.0);
    }
}
<commit_msg>Add module docs to fir<commit_after>//! Defines the `FIRFilter` structure for FIR filtering.

use std::cmp;

/// A FIR filter for convolving with a series of samples.
pub struct FIRFilter<'a> {
    /// The filter coefficients for multiplying with the input signal, represents bi.
    coefs: &'a [f64],
    /// A ring buffer of samples in the signal, represents x[i].
    history: Vec<f64>,
    /// The index of the most-recently added sample, represents n in x[n].
    idx: usize,
}

impl<'a> FIRFilter<'a> {
    /// Construct an order-N filter with the given N+1 coefficients.
    pub fn new(coefs: &'a [f64]) -> FIRFilter<'a> {
        FIRFilter {
            coefs: coefs,
            history: vec![0.0; coefs.len()],
            idx: 0,
        }
    }

    /// Perform the convolution with the current history of samples. Calculates
    /// y[n] = c0*x[n] + c1*x[n-1] + cN*x[n-N].
    fn calc(&self) -> f64 {
        // Copy the current index so we can move backwards.
        let mut cur = self.idx;

        self.coefs.iter().fold(0.0, |s, &coef| {
            // Wrap around to the last sample after visiting the first.
            cur = cmp::min(cur - 1, self.history.len() - 1);
            // Accumulate the next term.
            s + coef * self.history[cur]
        })
    }

    /// Add a sample to the current history and calculate the convolution.
    pub fn feed(&mut self, sample: f64) -> f64 {
        // Store the given sample in the current history slot.
        self.history[self.idx] = sample;

        // Move to the next slot and wrap around.
        self.idx += 1;
        self.idx %= self.history.len();

        self.calc()
    }
}

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

        const COEFS: &'static [f64] = &[
            0.0,
            1.0,
            0.0,
            1.0,
        ];

        let mut f = FIRFilter::new(COEFS);

        assert!(f.feed(100.0) == 0.0);
        assert!(f.feed(200.0) == 100.0);
        assert!(f.feed(300.0) == 200.0);
        assert!(f.feed(400.0) == 400.0);
        assert!(f.feed(0.0) == 600.0);
        assert!(f.feed(0.0) == 300.0);
        assert!(f.feed(0.0) == 400.0);
        assert!(f.feed(0.0) == 0.0);
        assert!(f.feed(0.0) == 0.0);
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::hash;

use num::{FromPrimitive};

/// please don't access VA.0 directly.
/// its provided so you can construct VA like:
/// ```
/// use lancelot::arch::VA;
/// let _ = VA(0x0);
/// ```
#[derive(Copy, Clone)]
pub struct VA(pub u64);

impl VA {
    /// Compute the VA given a delta RVA, like `self:va + other:rva`.
    /// Returns None on over/underflow.
    pub fn va(&self, other: RVA) -> Option<VA> {
        if other.0 < 0 {
            Some(VA(match self.0.checked_sub((-other.0) as u64) {
                None => return None,
                Some(v) => v,
            }))
        } else {
            Some(VA(match self.0.checked_add(other.0 as u64) {
                None => return None,
                Some(v) => v,
            }))
        }
    }

    /// Compute the delta RVA from `self:va - other:va`.
    /// Returns None on over/underflow.
    pub fn rva(&self, other: VA) -> Option<RVA> {
        if other.0 > self.0 {
            let v = match other.0.checked_sub(self.0) {
                None => return None,
                Some(v) => v,
            };
            if v > std::i64::MAX as u64{
                return None;
            }
            Some(RVA(-(v as i64)))
        } else {
            let v = match self.0.checked_sub(other.0) {
                None => return None,
                Some(v) => v
            };
            if v > std::i64::MAX as u64 {
                return None;
            }
            Some(RVA(v as i64))
        }
    }
}

impl fmt::Display for VA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#x}", self.0)
    }
}

impl fmt::Debug for VA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#x}", self.0)
    }
}

impl fmt::LowerHex for VA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.0)
    }
}

impl fmt::UpperHex for VA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:X}", self.0)
    }
}

impl hash::Hash for VA {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.0.hash(state);
    }
}

impl PartialEq for VA {
    fn eq(&self, other: &VA) -> bool {
        self.0 == other.0
    }
}

impl Eq for VA {}

impl std::convert::From<usize> for VA {
    fn from(v: usize) -> VA {
        // this should only fail when we get to 128-bit architectures
        VA(v as u64)
    }
}

impl std::convert::From<u32> for VA {
    fn from(v: u32) -> VA {
        VA(v as u64)
    }
}

impl std::convert::From<u64> for VA {
    fn from(v: u64) -> VA {
        VA(v)
    }
}

impl std::convert::Into<u64> for VA {
    fn into(self) -> u64 {
        self.0
    }
}

/// please don't access RVA.0 directly.
/// /// its provided so you can construct RVA like:
/// ```
/// use lancelot::arch::RVA;
/// let _ = RVA(0x0);
/// ```
#[derive(Copy, Clone)]
pub struct RVA(pub i64);

impl fmt::Display for RVA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#x}", self.0)
    }
}

impl fmt::Debug for RVA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#x}", self.0)
    }
}

impl fmt::LowerHex for RVA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.0)
    }
}

impl fmt::UpperHex for RVA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:X}", self.0)
    }
}

impl hash::Hash for RVA {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.0.hash(state);
    }
}

impl PartialEq for RVA {
    fn eq(&self, other: &RVA) -> bool {
        self.0 == other.0
    }
}

impl PartialOrd for RVA {
    fn partial_cmp(&self, other: &RVA) -> Option<std::cmp::Ordering> {
        Some(self.0.cmp(&other.0))
    }
}

impl Ord for RVA {
    fn cmp(&self, other: &RVA) -> std::cmp::Ordering {
        self.0.cmp(&other.0)
    }
}

impl Eq for RVA {}

impl std::convert::Into<usize> for RVA {
    /// may panic on over/underflow
    fn into(self) -> usize {
        if self.0 < 0 {
            panic!("usize underflow")
        }
        if self.0 as u64 > std::usize::MAX as u64 {
            panic!("usize overflow");
        }
        self.0 as usize
    }
}

impl std::convert::Into<u64> for RVA {
    fn into(self) -> u64 {
        self.0 as u64
    }
}

impl std::convert::Into<i64> for RVA {
    fn into(self) -> i64 {
        self.0
    }
}

impl std::convert::From<u32> for RVA {
    fn from(v: u32) -> RVA {
        RVA(v as i64)
    }
}

impl std::convert::From<i32> for RVA {
    fn from(v: i32) -> RVA {
        RVA(v as i64)
    }
}

impl std::convert::From<i64> for RVA {
    fn from(v: i64) -> RVA {
        RVA(v)
    }
}

impl std::convert::From<usize> for RVA {
    /// may panic on overflow
    fn from(v: usize) -> RVA {
        RVA(i64::from_usize(v).expect("usize too large for RVA"))
    }
}

impl std::ops::Add<RVA> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: RVA) -> RVA {
        RVA(self.0.checked_add(rhs.0).expect("rva overflow"))
    }
}

impl std::ops::Add<u8> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: u8) -> RVA {
        self + RVA::from(rhs as i64)
    }
}

impl std::ops::Add<u16> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: u16) -> RVA {
        self + RVA::from(rhs as i64)
    }
}

impl std::ops::Add<i32> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: i32) -> RVA {
        self + RVA::from(rhs as i64)
    }
}

impl std::ops::Add<u32> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: u32) -> RVA {
        self + RVA::from(rhs as i64)
    }
}

impl std::ops::Add<usize> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: usize) -> RVA {
        self + RVA::from(rhs)
    }
}

impl std::ops::Sub<RVA> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn sub(self, rhs: RVA) -> RVA {
        RVA(self.0.checked_sub(rhs.0).expect("rva underflow"))
    }
}

#[derive(Copy, Clone)]
pub enum Arch {
    X32,
    X64
}

impl Arch {
    pub fn get_pointer_size(self) -> u8 {
        match self {
            Arch::X32 => 4,
            Arch::X64 => 8,
        }
    }
}

impl fmt::Display for Arch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Arch::X32 => write!(f, "x32"),
            Arch::X64 => write!(f, "x64"),
        }
    }
}

impl fmt::Debug for Arch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self{
            Arch::X32 => write!(f, "x32"),
            Arch::X64 => write!(f, "x64"),
        }
    }
}

<commit_msg>VA: implement various Ord traits<commit_after>use std::fmt;
use std::hash;

use num::{FromPrimitive};

/// please don't access VA.0 directly.
/// its provided so you can construct VA like:
/// ```
/// use lancelot::arch::VA;
/// let _ = VA(0x0);
/// ```
#[derive(Copy, Clone)]
pub struct VA(pub u64);

impl VA {
    /// Compute the VA given a delta RVA, like `self:va + other:rva`.
    /// Returns None on over/underflow.
    pub fn va(&self, other: RVA) -> Option<VA> {
        if other.0 < 0 {
            Some(VA(match self.0.checked_sub((-other.0) as u64) {
                None => return None,
                Some(v) => v,
            }))
        } else {
            Some(VA(match self.0.checked_add(other.0 as u64) {
                None => return None,
                Some(v) => v,
            }))
        }
    }

    /// Compute the delta RVA from `self:va - other:va`.
    /// Returns None on over/underflow.
    pub fn rva(&self, other: VA) -> Option<RVA> {
        if other.0 > self.0 {
            let v = match other.0.checked_sub(self.0) {
                None => return None,
                Some(v) => v,
            };
            if v > std::i64::MAX as u64 {
                return None;
            }
            Some(RVA(-(v as i64)))
        } else {
            let v = match self.0.checked_sub(other.0) {
                None => return None,
                Some(v) => v
            };
            if v > std::i64::MAX as u64 {
                return None;
            }
            Some(RVA(v as i64))
        }
    }
}

impl fmt::Display for VA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#x}", self.0)
    }
}

impl fmt::Debug for VA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#x}", self.0)
    }
}

impl fmt::LowerHex for VA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.0)
    }
}

impl fmt::UpperHex for VA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:X}", self.0)
    }
}

impl hash::Hash for VA {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.0.hash(state);
    }
}

impl PartialEq for VA {
    fn eq(&self, other: &VA) -> bool {
        self.0 == other.0
    }
}

impl PartialOrd for VA {
    fn partial_cmp(&self, other: &VA) -> Option<std::cmp::Ordering> {
        Some(self.0.cmp(&other.0))
    }
}

impl std::cmp::Ord for VA {
    fn cmp(&self, other: &VA) -> std::cmp::Ordering {
        self.0.cmp(&other.0)
    }
}

impl Eq for VA {}

impl std::convert::From<usize> for VA {
    fn from(v: usize) -> VA {
        // this should only fail when we get to 128-bit architectures
        VA(v as u64)
    }
}

impl std::convert::From<u32> for VA {
    fn from(v: u32) -> VA {
        VA(v as u64)
    }
}

impl std::convert::From<u64> for VA {
    fn from(v: u64) -> VA {
        VA(v)
    }
}

impl std::convert::Into<u64> for VA {
    fn into(self) -> u64 {
        self.0
    }
}

/// please don't access RVA.0 directly.
/// /// its provided so you can construct RVA like:
/// ```
/// use lancelot::arch::RVA;
/// let _ = RVA(0x0);
/// ```
#[derive(Copy, Clone)]
pub struct RVA(pub i64);

impl fmt::Display for RVA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#x}", self.0)
    }
}

impl fmt::Debug for RVA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:#x}", self.0)
    }
}

impl fmt::LowerHex for RVA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:x}", self.0)
    }
}

impl fmt::UpperHex for RVA {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:X}", self.0)
    }
}

impl hash::Hash for RVA {
    fn hash<H: hash::Hasher>(&self, state: &mut H) {
        self.0.hash(state);
    }
}

impl PartialEq for RVA {
    fn eq(&self, other: &RVA) -> bool {
        self.0 == other.0
    }
}

impl PartialOrd for RVA {
    fn partial_cmp(&self, other: &RVA) -> Option<std::cmp::Ordering> {
        Some(self.0.cmp(&other.0))
    }
}

impl Ord for RVA {
    fn cmp(&self, other: &RVA) -> std::cmp::Ordering {
        self.0.cmp(&other.0)
    }
}

impl Eq for RVA {}

impl std::convert::Into<usize> for RVA {
    /// may panic on over/underflow
    fn into(self) -> usize {
        if self.0 < 0 {
            panic!("usize underflow")
        }
        if self.0 as u64 > std::usize::MAX as u64 {
            panic!("usize overflow");
        }
        self.0 as usize
    }
}

impl std::convert::Into<u64> for RVA {
    fn into(self) -> u64 {
        self.0 as u64
    }
}

impl std::convert::Into<i64> for RVA {
    fn into(self) -> i64 {
        self.0
    }
}

impl std::convert::From<u32> for RVA {
    fn from(v: u32) -> RVA {
        RVA(v as i64)
    }
}

impl std::convert::From<i32> for RVA {
    fn from(v: i32) -> RVA {
        RVA(v as i64)
    }
}

impl std::convert::From<i64> for RVA {
    fn from(v: i64) -> RVA {
        RVA(v)
    }
}

impl std::convert::From<usize> for RVA {
    /// may panic on overflow
    fn from(v: usize) -> RVA {
        RVA(i64::from_usize(v).expect("usize too large for RVA"))
    }
}

impl std::ops::Add<RVA> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: RVA) -> RVA {
        RVA(self.0.checked_add(rhs.0).expect("rva overflow"))
    }
}

impl std::ops::Add<u8> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: u8) -> RVA {
        self + RVA::from(rhs as i64)
    }
}

impl std::ops::Add<u16> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: u16) -> RVA {
        self + RVA::from(rhs as i64)
    }
}

impl std::ops::Add<i32> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: i32) -> RVA {
        self + RVA::from(rhs as i64)
    }
}

impl std::ops::Add<u32> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: u32) -> RVA {
        self + RVA::from(rhs as i64)
    }
}

impl std::ops::Add<usize> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn add(self, rhs: usize) -> RVA {
        self + RVA::from(rhs)
    }
}

impl std::ops::Sub<RVA> for RVA {
    type Output = RVA;

    /// may panic on overflow
    fn sub(self, rhs: RVA) -> RVA {
        RVA(self.0.checked_sub(rhs.0).expect("rva underflow"))
    }
}

#[derive(Copy, Clone)]
pub enum Arch {
    X32,
    X64
}

impl Arch {
    pub fn get_pointer_size(self) -> u8 {
        match self {
            Arch::X32 => 4,
            Arch::X64 => 8,
        }
    }
}

impl fmt::Display for Arch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Arch::X32 => write!(f, "x32"),
            Arch::X64 => write!(f, "x64"),
        }
    }
}

impl fmt::Debug for Arch {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self{
            Arch::X32 => write!(f, "x32"),
            Arch::X64 => write!(f, "x64"),
        }
    }
}

<|endoftext|>