<commit_before>use std::fmt;
use std::io::Read;

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::message::Message;
use crate::message_dyn::MessageDyn;
use crate::reflect::dynamic::DynamicMessage;
use crate::reflect::file::index::FileIndexMessageEntry;
use crate::reflect::file::FileDescriptorImpl;
use crate::reflect::message::dynamic::DynamicMessageDescriptor;
use crate::reflect::message::generated::GeneratedMessageDescriptor;
use crate::reflect::message::index::MessageIndex;
use crate::reflect::reflect_eq::ReflectEq;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::EnumDescriptor;
use crate::reflect::FieldDescriptor;
use crate::reflect::FileDescriptor;
use crate::reflect::OneofDescriptor;
use crate::CodedInputStream;
use crate::ProtobufResult;

pub(crate) mod dynamic;
pub(crate) mod generated;
pub(crate) mod index;
pub(crate) mod message_ref;
pub(crate) mod path;

/// Dynamic representation of message type.
///
/// Used for reflection.
#[derive(Clone, Eq, PartialEq)]
pub struct MessageDescriptor {
    file_descriptor: FileDescriptor,
    index: usize,
}

impl fmt::Display for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl fmt::Debug for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MessageDescriptor")
            // TODO: add smth
            .finish()
    }
}

impl MessageDescriptor {
    pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor {
            file_descriptor,
            index,
        }
    }

    /// Get internal index.
    ///
    /// Only needed for codegen.
    #[doc(hidden)]
    pub fn get_index_in_file_for_codegen(&self) -> usize {
        self.index
    }

    /// Get underlying `DescriptorProto` object.
    pub fn get_proto(&self) -> &DescriptorProto {
        self.file_descriptor.message_proto(self.index)
    }

    /// Message name as specified in `.proto` file.
    pub fn get_name(&self) -> &str {
        self.get_proto().get_name()
    }

    /// Get enums declared in this message.
    pub fn get_enums(&self) -> Vec<EnumDescriptor> {
        let first_enum_index = self.get_index_entry().first_enum_index;
        self.get_proto()
            .enum_type
            .iter()
            .enumerate()
            .map(|(i, _)| EnumDescriptor::new(self.file_descriptor.clone(), first_enum_index + i))
            .collect()
    }

    fn get_index_entry(&self) -> &FileIndexMessageEntry {
        self.file_descriptor.message_index_entry(self.index)
    }

    /// Get a message descriptor for given message type
    pub fn for_type<M: Message>() -> MessageDescriptor {
        M::descriptor_static()
    }

    #[doc(hidden)]
    pub fn new_generated_2(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor::new(file_descriptor, index)
    }

    /// Messages declared in this messages.
    pub fn get_nested_messages(&self) -> Vec<MessageDescriptor> {
        self.get_index_entry()
            .nested_messages
            .iter()
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), *i))
            .collect()
    }

    pub(crate) fn get_impl(&self) -> MessageDescriptorImplRef {
        match &self.file_descriptor.imp {
            FileDescriptorImpl::Generated(g) => {
                MessageDescriptorImplRef::Generated(&g.messages[self.index])
            }
            FileDescriptorImpl::Dynamic(d) => {
                MessageDescriptorImplRef::Dynamic(&d.messages[self.index])
            }
        }
    }

    /// [`FileDescriptor`] containing this message.
    pub fn file_descriptor(&self) -> &FileDescriptor {
        &self.file_descriptor
    }

    /// `FileDescriptorProto` containg this message type
    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor().proto()
    }

    /// This message descriptor is a map entry.
    pub fn is_map_entry(&self) -> bool {
        self.get_proto().options.get_or_default().get_map_entry()
    }

    fn assert_not_map_entry(&self) {
        assert!(
            !self.is_map_entry(),
            "message is map entry: {}",
            self.full_name()
        );
    }

    /// New empty message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn new_instance(&self) -> Box<dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.new_instance(),
            MessageDescriptorImplRef::Dynamic(..) => Box::new(DynamicMessage::new(self.clone())),
        }
    }

    /// Shared immutable empty message.
    ///
    /// Returns `None` for dynamic message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn default_instance(&self) -> Option<&'static dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => Some(g.non_map().factory.default_instance()),
            MessageDescriptorImplRef::Dynamic(..) => None,
        }
    }

    /// Clone a message
    pub(crate) fn clone_message(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
        assert!(&message.descriptor_dyn() == self);
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.clone(message),
            MessageDescriptorImplRef::Dynamic(..) => {
                let message: &DynamicMessage = <dyn MessageDyn>::downcast_ref(message).unwrap();
                Box::new(message.clone())
            }
        }
    }

    /// Check if two messages equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.eq(a, b),
            MessageDescriptorImplRef::Dynamic(..) => unimplemented!(),
        }
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub(crate) fn reflect_eq(
        &self,
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(self, &a.descriptor_dyn());
        assert_eq!(self, &b.descriptor_dyn());

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_eq(&bf, mode) {
                return false;
            }
        }
        true
    }

    pub(crate) fn reflect_eq_maybe_unrelated(
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        let ad = a.descriptor_dyn();
        let bd = b.descriptor_dyn();
        ad == bd && ad.reflect_eq(a, b, mode)
    }

    /// Message name as given in `.proto` file
    pub fn name(&self) -> &str {
        self.get_proto().get_name()
    }

    /// Fully qualified protobuf message name
    pub fn full_name(&self) -> &str {
        &self.get_index_entry().full_name
    }

    /// Message field descriptors.
    pub fn fields<'a>(&'a self) -> impl ExactSizeIterator<Item = FieldDescriptor> + 'a {
        (0..self.get_index().fields.len()).map(move |index| FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Nested oneofs
    pub fn oneofs<'a>(&'a self) -> impl ExactSizeIterator<Item = OneofDescriptor> + 'a {
        self.get_proto()
            .oneof_decl
            .iter()
            .enumerate()
            .map(move |(index, _)| OneofDescriptor {
                message_descriptor: self.clone(),
                index,
            })
    }

    pub(crate) fn get_index(&self) -> &MessageIndex {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => &g.non_map().index,
            MessageDescriptorImplRef::Dynamic(d) => &d.indices,
        }
    }

    pub(crate) fn get_generated_index(&self) -> &'static MessageIndex {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => &g.non_map().index,
            MessageDescriptorImplRef::Dynamic(_) => panic!("dynamic message: {}", self),
        }
    }

    /// Find message field by protobuf field name
    ///
    /// Note: protobuf field name might be different for Rust field name.
    // TODO: return value, not pointer, pointer is not compatible with dynamic message
    pub fn get_field_by_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_name.get(name)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Find message field by field name or field JSON name
    pub fn get_field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_name_or_json_name.get(name)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Find message field by field name
    pub fn get_field_by_number(&self, number: u32) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_number.get(&number)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Parse message from stream.
    pub fn parse_from(&self, is: &mut CodedInputStream) -> ProtobufResult<Box<dyn MessageDyn>> {
        let mut r = self.new_instance();
        r.merge_from_dyn(is)?;
        r.check_initialized_dyn()?;
        Ok(r)
    }

    /// Parse message from reader.
    /// Parse stops on EOF or when error encountered.
    pub fn parse_from_reader(&self, reader: &mut dyn Read) -> ProtobufResult<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::new(reader);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from byte array.
    pub fn parse_from_bytes(&self, bytes: &[u8]) -> ProtobufResult<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::from_bytes(bytes);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }
}

pub(crate) enum MessageDescriptorImplRef<'a> {
    Generated(&'static GeneratedMessageDescriptor),
    Dynamic(&'a DynamicMessageDescriptor),
}
<commit_msg>Expose MessageDescriptor::name_to_package<commit_after>use std::fmt;
use std::io::Read;

use crate::descriptor::DescriptorProto;
use crate::descriptor::FileDescriptorProto;
use crate::message::Message;
use crate::message_dyn::MessageDyn;
use crate::reflect::dynamic::DynamicMessage;
use crate::reflect::file::index::FileIndexMessageEntry;
use crate::reflect::file::FileDescriptorImpl;
use crate::reflect::message::dynamic::DynamicMessageDescriptor;
use crate::reflect::message::generated::GeneratedMessageDescriptor;
use crate::reflect::message::index::MessageIndex;
use crate::reflect::reflect_eq::ReflectEq;
use crate::reflect::reflect_eq::ReflectEqMode;
use crate::reflect::EnumDescriptor;
use crate::reflect::FieldDescriptor;
use crate::reflect::FileDescriptor;
use crate::reflect::OneofDescriptor;
use crate::CodedInputStream;
use crate::ProtobufResult;

pub(crate) mod dynamic;
pub(crate) mod generated;
pub(crate) mod index;
pub(crate) mod message_ref;
pub(crate) mod path;

/// Dynamic representation of message type.
///
/// Used for reflection.
#[derive(Clone, Eq, PartialEq)]
pub struct MessageDescriptor {
    file_descriptor: FileDescriptor,
    index: usize,
}

impl fmt::Display for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.full_name())
    }
}

impl fmt::Debug for MessageDescriptor {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("MessageDescriptor")
            // TODO: add smth
            .finish()
    }
}

impl MessageDescriptor {
    pub(crate) fn new(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor {
            file_descriptor,
            index,
        }
    }

    /// Get internal index.
    ///
    /// Only needed for codegen.
    #[doc(hidden)]
    pub fn get_index_in_file_for_codegen(&self) -> usize {
        self.index
    }

    /// Get underlying `DescriptorProto` object.
    pub fn get_proto(&self) -> &DescriptorProto {
        self.file_descriptor.message_proto(self.index)
    }

    /// Message name as specified in `.proto` file.
    pub fn get_name(&self) -> &str {
        self.get_proto().get_name()
    }

    /// Get enums declared in this message.
    pub fn get_enums(&self) -> Vec<EnumDescriptor> {
        let first_enum_index = self.get_index_entry().first_enum_index;
        self.get_proto()
            .enum_type
            .iter()
            .enumerate()
            .map(|(i, _)| EnumDescriptor::new(self.file_descriptor.clone(), first_enum_index + i))
            .collect()
    }

    fn get_index_entry(&self) -> &FileIndexMessageEntry {
        self.file_descriptor.message_index_entry(self.index)
    }

    /// Get a message descriptor for given message type
    pub fn for_type<M: Message>() -> MessageDescriptor {
        M::descriptor_static()
    }

    #[doc(hidden)]
    pub fn new_generated_2(file_descriptor: FileDescriptor, index: usize) -> MessageDescriptor {
        MessageDescriptor::new(file_descriptor, index)
    }

    /// Messages declared in this messages.
    pub fn get_nested_messages(&self) -> Vec<MessageDescriptor> {
        self.get_index_entry()
            .nested_messages
            .iter()
            .map(|i| MessageDescriptor::new(self.file_descriptor.clone(), *i))
            .collect()
    }

    pub(crate) fn get_impl(&self) -> MessageDescriptorImplRef {
        match &self.file_descriptor.imp {
            FileDescriptorImpl::Generated(g) => {
                MessageDescriptorImplRef::Generated(&g.messages[self.index])
            }
            FileDescriptorImpl::Dynamic(d) => {
                MessageDescriptorImplRef::Dynamic(&d.messages[self.index])
            }
        }
    }

    /// [`FileDescriptor`] containing this message.
    pub fn file_descriptor(&self) -> &FileDescriptor {
        &self.file_descriptor
    }

    /// `FileDescriptorProto` containg this message type
    pub fn file_descriptor_proto(&self) -> &FileDescriptorProto {
        self.file_descriptor().proto()
    }

    /// This message descriptor is a map entry.
    pub fn is_map_entry(&self) -> bool {
        self.get_proto().options.get_or_default().get_map_entry()
    }

    fn assert_not_map_entry(&self) {
        assert!(
            !self.is_map_entry(),
            "message is map entry: {}",
            self.full_name()
        );
    }

    /// New empty message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn new_instance(&self) -> Box<dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.new_instance(),
            MessageDescriptorImplRef::Dynamic(..) => Box::new(DynamicMessage::new(self.clone())),
        }
    }

    /// Shared immutable empty message.
    ///
    /// Returns `None` for dynamic message.
    ///
    /// # Panics
    ///
    /// If this message is a map entry message.
    pub fn default_instance(&self) -> Option<&'static dyn MessageDyn> {
        self.assert_not_map_entry();
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => Some(g.non_map().factory.default_instance()),
            MessageDescriptorImplRef::Dynamic(..) => None,
        }
    }

    /// Clone a message
    pub(crate) fn clone_message(&self, message: &dyn MessageDyn) -> Box<dyn MessageDyn> {
        assert!(&message.descriptor_dyn() == self);
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.clone(message),
            MessageDescriptorImplRef::Dynamic(..) => {
                let message: &DynamicMessage = <dyn MessageDyn>::downcast_ref(message).unwrap();
                Box::new(message.clone())
            }
        }
    }

    /// Check if two messages equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub fn eq(&self, a: &dyn MessageDyn, b: &dyn MessageDyn) -> bool {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => g.non_map().factory.eq(a, b),
            MessageDescriptorImplRef::Dynamic(..) => unimplemented!(),
        }
    }

    /// Similar to `eq`, but considers `NaN` values equal.
    ///
    /// # Panics
    ///
    /// Is any message has different type than this descriptor.
    pub(crate) fn reflect_eq(
        &self,
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        // Explicitly force panic even if field list is empty
        assert_eq!(self, &a.descriptor_dyn());
        assert_eq!(self, &b.descriptor_dyn());

        for field in self.fields() {
            let af = field.get_reflect(a);
            let bf = field.get_reflect(b);
            if !af.reflect_eq(&bf, mode) {
                return false;
            }
        }
        true
    }

    pub(crate) fn reflect_eq_maybe_unrelated(
        a: &dyn MessageDyn,
        b: &dyn MessageDyn,
        mode: &ReflectEqMode,
    ) -> bool {
        let ad = a.descriptor_dyn();
        let bd = b.descriptor_dyn();
        ad == bd && ad.reflect_eq(a, b, mode)
    }

    /// Message name as given in `.proto` file
    pub fn name(&self) -> &str {
        self.get_proto().get_name()
    }

    /// Fully qualified protobuf message name
    pub fn full_name(&self) -> &str {
        &self.get_index_entry().full_name
    }

    /// Name relative to the package where the message is declared.
    pub fn name_to_package(&self) -> &str {
        &self.get_index_entry().name_to_package
    }

    /// Message field descriptors.
    pub fn fields<'a>(&'a self) -> impl ExactSizeIterator<Item = FieldDescriptor> + 'a {
        (0..self.get_index().fields.len()).map(move |index| FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Nested oneofs
    pub fn oneofs<'a>(&'a self) -> impl ExactSizeIterator<Item = OneofDescriptor> + 'a {
        self.get_proto()
            .oneof_decl
            .iter()
            .enumerate()
            .map(move |(index, _)| OneofDescriptor {
                message_descriptor: self.clone(),
                index,
            })
    }

    pub(crate) fn get_index(&self) -> &MessageIndex {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => &g.non_map().index,
            MessageDescriptorImplRef::Dynamic(d) => &d.indices,
        }
    }

    pub(crate) fn get_generated_index(&self) -> &'static MessageIndex {
        match self.get_impl() {
            MessageDescriptorImplRef::Generated(g) => &g.non_map().index,
            MessageDescriptorImplRef::Dynamic(_) => panic!("dynamic message: {}", self),
        }
    }

    /// Find message field by protobuf field name
    ///
    /// Note: protobuf field name might be different for Rust field name.
    // TODO: return value, not pointer, pointer is not compatible with dynamic message
    pub fn get_field_by_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_name.get(name)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Find message field by field name or field JSON name
    pub fn get_field_by_name_or_json_name<'a>(&'a self, name: &str) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_name_or_json_name.get(name)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Find message field by field name
    pub fn get_field_by_number(&self, number: u32) -> Option<FieldDescriptor> {
        let &index = self.get_index().index_by_number.get(&number)?;
        Some(FieldDescriptor {
            message_descriptor: self.clone(),
            index,
        })
    }

    /// Parse message from stream.
    pub fn parse_from(&self, is: &mut CodedInputStream) -> ProtobufResult<Box<dyn MessageDyn>> {
        let mut r = self.new_instance();
        r.merge_from_dyn(is)?;
        r.check_initialized_dyn()?;
        Ok(r)
    }

    /// Parse message from reader.
    /// Parse stops on EOF or when error encountered.
    pub fn parse_from_reader(&self, reader: &mut dyn Read) -> ProtobufResult<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::new(reader);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }

    /// Parse message from byte array.
    pub fn parse_from_bytes(&self, bytes: &[u8]) -> ProtobufResult<Box<dyn MessageDyn>> {
        let mut is = CodedInputStream::from_bytes(bytes);
        let r = self.parse_from(&mut is)?;
        is.check_eof()?;
        Ok(r)
    }
}

pub(crate) enum MessageDescriptorImplRef<'a> {
    Generated(&'static GeneratedMessageDescriptor),
    Dynamic(&'a DynamicMessageDescriptor),
}
<|endoftext|>


<commit_before>use nom::{self, IResult};
use std::str;

pub enum Expr<'a> {
     Var(&'a [u8]),
     Filter(&'a str, Box<Expr<'a>>),
     Eq(Box<Expr<'a>>, Box<Expr<'a>>),
}

pub enum Target<'a> {
    Name(&'a [u8]),
}

pub enum Node<'a> {
    Lit(&'a [u8]),
    Expr(Expr<'a>),
    Cond(Vec<(Option<Expr<'a>>, Vec<Node<'a>>)>),
    Loop(Target<'a>, Expr<'a>, Vec<Node<'a>>),
}

pub type Nodes<'a> = Vec<Node<'a>>;
pub type Conds<'a> = Vec<(Option<Expr<'a>>, Nodes<'a>)>;

fn take_content(i: &[u8]) -> IResult<&[u8], Node> {
    if i.len() < 1 || i[0] == b'{' {
        return IResult::Error(error_position!(nom::ErrorKind::TakeUntil, i));
    }
    for (j, c) in i.iter().enumerate() {
        if *c == b'{' {
            if i.len() < j + 2 {
                return IResult::Done(&i[..0], Node::Lit(&i[..]));
            } else if i[j + 1] == '{' as u8 {
                return IResult::Done(&i[j..], Node::Lit(&i[..j]));
            } else if i[j + 1] == '%' as u8 {
                return IResult::Done(&i[j..], Node::Lit(&i[..j]));
            }
        }
    }
    IResult::Done(&i[..0], Node::Lit(&i[..]))
}

named!(expr_var<Expr>, map!(nom::alphanumeric, Expr::Var));

named!(target_single<Target>, map!(nom::alphanumeric, Target::Name));

fn expr_filtered(i: &[u8]) -> IResult<&[u8], Expr> {
    let (mut left, mut expr) = match expr_var(i) {
        IResult::Error(err) => { return IResult::Error(err); },
        IResult::Incomplete(needed) => { return IResult::Incomplete(needed); },
        IResult::Done(left, res) => (left, res),
    };
    while left[0] == b'|' {
        match nom::alphanumeric(&left[1..]) {
            IResult::Error(err) => {
                return IResult::Error(err);
            },
            IResult::Incomplete(needed) => {
                return IResult::Incomplete(needed);
            },
            IResult::Done(new_left, res) => {
                left = new_left;
                expr = Expr::Filter(str::from_utf8(res).unwrap(), Box::new(expr));
            },
        };
    }
    return IResult::Done(left, expr);
}

named!(expr_eq<Expr>, do_parse!(
    left: expr_filtered >>
    ws!(tag_s!("==")) >>
    right: expr_filtered >>
    (Expr::Eq(Box::new(left), Box::new(right)))));

named!(expr_any<Expr>, alt!(expr_eq | expr_filtered));

named!(expr_node<Node>, map!(
    delimited!(tag_s!("{{"), ws!(expr_any), tag_s!("}}")),
    Node::Expr));

named!(cond_if<Expr>, do_parse!(
    ws!(tag_s!("if")) >>
    cond: ws!(expr_any) >>
    (cond)));

named!(cond_block<(Option<Expr>, Nodes)>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("else")) >>
    cond: opt!(cond_if) >>
    tag_s!("%}") >>
    block: parse_template >>
    (cond, block)));

named!(block_if<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("if")) >>
    cond: ws!(expr_any) >>
    tag_s!("%}") >>
    block: parse_template >>
    elifs: many0!(cond_block) >>
    tag_s!("{%") >>
    ws!(tag_s!("endif")) >>
    tag_s!("%}") >>
    ({
        let mut res = Vec::new();
        res.push((Some(cond), block));
        res.extend(elifs);
        Node::Cond(res)
    })));

named!(block_for<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("for")) >>
    var: ws!(target_single) >>
    ws!(tag_s!("in")) >>
    iter: ws!(expr_any) >>
    tag_s!("%}") >>
    block: parse_template >>
    tag_s!("{%") >>
    ws!(tag_s!("endfor")) >>
    tag_s!("%}") >>
    (Node::Loop(var, iter, block))));

named!(parse_template<Nodes>, many1!(alt!(
    take_content |
    expr_node |
    block_if |
    block_for)));

pub fn parse<'a>(src: &'a str) -> Nodes {
    match parse_template(src.as_bytes()) {
        IResult::Done(_, res) => res,
        IResult::Error(err) => panic!("problems parsing template source: {}", err),
        IResult::Incomplete(_) => panic!("parsing incomplete"),
    }
}
<commit_msg>Fix incorrect indentation<commit_after>use nom::{self, IResult};
use std::str;

pub enum Expr<'a> {
    Var(&'a [u8]),
    Filter(&'a str, Box<Expr<'a>>),
    Eq(Box<Expr<'a>>, Box<Expr<'a>>),
}

pub enum Target<'a> {
    Name(&'a [u8]),
}

pub enum Node<'a> {
    Lit(&'a [u8]),
    Expr(Expr<'a>),
    Cond(Vec<(Option<Expr<'a>>, Vec<Node<'a>>)>),
    Loop(Target<'a>, Expr<'a>, Vec<Node<'a>>),
}

pub type Nodes<'a> = Vec<Node<'a>>;
pub type Conds<'a> = Vec<(Option<Expr<'a>>, Nodes<'a>)>;

fn take_content(i: &[u8]) -> IResult<&[u8], Node> {
    if i.len() < 1 || i[0] == b'{' {
        return IResult::Error(error_position!(nom::ErrorKind::TakeUntil, i));
    }
    for (j, c) in i.iter().enumerate() {
        if *c == b'{' {
            if i.len() < j + 2 {
                return IResult::Done(&i[..0], Node::Lit(&i[..]));
            } else if i[j + 1] == '{' as u8 {
                return IResult::Done(&i[j..], Node::Lit(&i[..j]));
            } else if i[j + 1] == '%' as u8 {
                return IResult::Done(&i[j..], Node::Lit(&i[..j]));
            }
        }
    }
    IResult::Done(&i[..0], Node::Lit(&i[..]))
}

named!(expr_var<Expr>, map!(nom::alphanumeric, Expr::Var));

named!(target_single<Target>, map!(nom::alphanumeric, Target::Name));

fn expr_filtered(i: &[u8]) -> IResult<&[u8], Expr> {
    let (mut left, mut expr) = match expr_var(i) {
        IResult::Error(err) => { return IResult::Error(err); },
        IResult::Incomplete(needed) => { return IResult::Incomplete(needed); },
        IResult::Done(left, res) => (left, res),
    };
    while left[0] == b'|' {
        match nom::alphanumeric(&left[1..]) {
            IResult::Error(err) => {
                return IResult::Error(err);
            },
            IResult::Incomplete(needed) => {
                return IResult::Incomplete(needed);
            },
            IResult::Done(new_left, res) => {
                left = new_left;
                expr = Expr::Filter(str::from_utf8(res).unwrap(), Box::new(expr));
            },
        };
    }
    return IResult::Done(left, expr);
}

named!(expr_eq<Expr>, do_parse!(
    left: expr_filtered >>
    ws!(tag_s!("==")) >>
    right: expr_filtered >>
    (Expr::Eq(Box::new(left), Box::new(right)))));

named!(expr_any<Expr>, alt!(expr_eq | expr_filtered));

named!(expr_node<Node>, map!(
    delimited!(tag_s!("{{"), ws!(expr_any), tag_s!("}}")),
    Node::Expr));

named!(cond_if<Expr>, do_parse!(
    ws!(tag_s!("if")) >>
    cond: ws!(expr_any) >>
    (cond)));

named!(cond_block<(Option<Expr>, Nodes)>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("else")) >>
    cond: opt!(cond_if) >>
    tag_s!("%}") >>
    block: parse_template >>
    (cond, block)));

named!(block_if<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("if")) >>
    cond: ws!(expr_any) >>
    tag_s!("%}") >>
    block: parse_template >>
    elifs: many0!(cond_block) >>
    tag_s!("{%") >>
    ws!(tag_s!("endif")) >>
    tag_s!("%}") >>
    ({
        let mut res = Vec::new();
        res.push((Some(cond), block));
        res.extend(elifs);
        Node::Cond(res)
    })));

named!(block_for<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("for")) >>
    var: ws!(target_single) >>
    ws!(tag_s!("in")) >>
    iter: ws!(expr_any) >>
    tag_s!("%}") >>
    block: parse_template >>
    tag_s!("{%") >>
    ws!(tag_s!("endfor")) >>
    tag_s!("%}") >>
    (Node::Loop(var, iter, block))));

named!(parse_template<Nodes>, many1!(alt!(
    take_content |
    expr_node |
    block_if |
    block_for)));

pub fn parse<'a>(src: &'a str) -> Nodes {
    match parse_template(src.as_bytes()) {
        IResult::Done(_, res) => res,
        IResult::Error(err) => panic!("problems parsing template source: {}", err),
        IResult::Incomplete(_) => panic!("parsing incomplete"),
    }
}
<|endoftext|>


<commit_before>use nom::{self, IResult};
use std::str;

pub enum Expr<'a> {
    StrLit(&'a str),
    Var(&'a [u8]),
    Filter(&'a str, Box<Expr<'a>>),
    Compare(&'a str, Box<Expr<'a>>, Box<Expr<'a>>),
}

pub enum Target<'a> {
    Name(&'a [u8]),
}

pub enum Node<'a> {
    Lit(&'a [u8], &'a [u8], &'a [u8]),
    Expr(Expr<'a>),
    Cond(Vec<(Option<Expr<'a>>, Vec<Node<'a>>)>),
    Loop(Target<'a>, Expr<'a>, Vec<Node<'a>>),
    Extends(Expr<'a>),
    BlockDef(&'a str, Vec<Node<'a>>),
    Block(&'a str),
}

pub type Cond<'a> = (Option<Expr<'a>>, Vec<Node<'a>>);

fn split_ws_parts(s: &[u8]) -> Node {
    if s.is_empty() {
        return Node::Lit(s, s, s);
    }
    let is_ws = |c: &u8| {
        *c != b' ' && *c != b'\t' && *c != b'\r' && *c != b'\n'
    };
    let start = s.iter().position(&is_ws);
    if let None = start {
        return Node::Lit(s, &s[0..0], &s[0..0]);
    }
    let start = start.unwrap();
    let end = s.iter().rposition(&is_ws);
    if let None = end {
        return Node::Lit(&s[..start], &s[start..], &s[0..0]);
    }
    let end = end.unwrap();
    Node::Lit(&s[..start], &s[start..end + 1], &s[end + 1..])
}

fn take_content(i: &[u8]) -> IResult<&[u8], Node> {
    if i.len() < 1 || i[0] == b'{' {
        return IResult::Error(error_position!(nom::ErrorKind::TakeUntil, i));
    }
    for (j, c) in i.iter().enumerate() {
        if *c == b'{' {
            if i.len() < j + 2 {
                return IResult::Done(&i[..0], split_ws_parts(&i[..]));
            } else if i[j + 1] == b'{' || i[j + 1] == b'%' {
                return IResult::Done(&i[j..], split_ws_parts(&i[..j]));
            }
        }
    }
    IResult::Done(&i[..0], split_ws_parts(&i[..]))
}

named!(expr_str_lit<Expr>, map!(
    delimited!(char!('"'), is_not!("\""), char!('"')),
    |s| Expr::StrLit(str::from_utf8(s).unwrap())));

named!(expr_var<Expr>, map!(nom::alphanumeric, Expr::Var));

named!(target_single<Target>, map!(nom::alphanumeric, Target::Name));

fn expr_filtered(i: &[u8]) -> IResult<&[u8], Expr> {
    let (mut left, mut expr) = match expr_var(i) {
        IResult::Error(err) => { return IResult::Error(err); },
        IResult::Incomplete(needed) => { return IResult::Incomplete(needed); },
        IResult::Done(left, res) => (left, res),
    };
    while left[0] == b'|' {
        match nom::alphanumeric(&left[1..]) {
            IResult::Error(err) => {
                return IResult::Error(err);
            },
            IResult::Incomplete(needed) => {
                return IResult::Incomplete(needed);
            },
            IResult::Done(new_left, res) => {
                left = new_left;
                expr = Expr::Filter(str::from_utf8(res).unwrap(), Box::new(expr));
            },
        };
    }
    IResult::Done(left, expr)
}

named!(expr_compare<Expr>, do_parse!(
    left: expr_filtered >>
    op: ws!(alt!(
        tag_s!("==") | tag_s!("!=") |
        tag_s!(">=") | tag_s!(">") |
        tag_s!("<=") | tag_s!("<")
    )) >>
    right: expr_filtered >>
    (Expr::Compare(str::from_utf8(op).unwrap(),
                   Box::new(left), Box::new(right)))));

named!(expr_any<Expr>, alt!(
    expr_compare |
    expr_filtered |
    expr_str_lit));

named!(expr_node<Node>, map!(
    delimited!(tag_s!("{{"), ws!(expr_any), tag_s!("}}")),
    Node::Expr));

named!(cond_if<Expr>, do_parse!(
    ws!(tag_s!("if")) >>
    cond: ws!(expr_any) >>
    (cond)));

named!(cond_block<Cond>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("else")) >>
    cond: opt!(cond_if) >>
    tag_s!("%}") >>
    block: parse_template >>
    (cond, block)));

named!(block_if<Node>, do_parse!(
    tag_s!("{%") >>
    cond: ws!(cond_if) >>
    tag_s!("%}") >>
    block: parse_template >>
    elifs: many0!(cond_block) >>
    tag_s!("{%") >>
    ws!(tag_s!("endif")) >>
    tag_s!("%}") >>
    ({
        let mut res = Vec::new();
        res.push((Some(cond), block));
        res.extend(elifs);
        Node::Cond(res)
    })));

named!(block_for<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("for")) >>
    var: ws!(target_single) >>
    ws!(tag_s!("in")) >>
    iter: ws!(expr_any) >>
    tag_s!("%}") >>
    block: parse_template >>
    tag_s!("{%") >>
    ws!(tag_s!("endfor")) >>
    tag_s!("%}") >>
    (Node::Loop(var, iter, block))));

named!(block_extends<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("extends")) >>
    name: ws!(expr_str_lit) >>
    tag_s!("%}") >>
    (Node::Extends(name))));

named!(block_block<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("block")) >>
    name: ws!(nom::alphanumeric) >>
    tag_s!("%}") >>
    contents: parse_template >>
    tag_s!("{%") >>
    ws!(tag_s!("endblock")) >>
    tag_s!("%}") >>
    (Node::BlockDef(str::from_utf8(name).unwrap(), contents))));

named!(parse_template<Vec<Node<'a>>>, many0!(alt!(
    take_content |
    expr_node |
    block_if |
    block_for |
    block_extends |
    block_block)));

pub fn parse(src: &str) -> Vec<Node> {
    match parse_template(src.as_bytes()) {
        IResult::Done(_, res) => res,
        IResult::Error(err) => panic!("problems parsing template source: {}", err),
        IResult::Incomplete(_) => panic!("parsing incomplete"),
    }
}

#[cfg(test)]
mod tests {
    fn check_ws_split(s: &str, res: &(&[u8], &[u8], &[u8])) {
        let node = super::split_ws_parts(s.as_bytes());
        match node {
            super::Node::Lit(lws, s, rws) => {
                assert_eq!(lws, res.0);
                assert_eq!(s, res.1);
                assert_eq!(rws, res.2);
            },
            _ => { panic!("fail"); },
        }
    }
    #[test]
    fn test_ws_splitter() {
        check_ws_split("a", &(b"", b"a", b""));
        check_ws_split("", &(b"", b"", b""));
        check_ws_split("\ta", &(b"\t", b"a", b""));
        check_ws_split("b\n", &(b"", b"b", b"\n"));
        check_ws_split(" \t\r\n", &(b" \t\r\n", b"", b""));
    }
}
<commit_msg>Improve readability of parser macro invocations<commit_after>use nom::{self, IResult};
use std::str;

pub enum Expr<'a> {
    StrLit(&'a str),
    Var(&'a [u8]),
    Filter(&'a str, Box<Expr<'a>>),
    Compare(&'a str, Box<Expr<'a>>, Box<Expr<'a>>),
}

pub enum Target<'a> {
    Name(&'a [u8]),
}

pub enum Node<'a> {
    Lit(&'a [u8], &'a [u8], &'a [u8]),
    Expr(Expr<'a>),
    Cond(Vec<(Option<Expr<'a>>, Vec<Node<'a>>)>),
    Loop(Target<'a>, Expr<'a>, Vec<Node<'a>>),
    Extends(Expr<'a>),
    BlockDef(&'a str, Vec<Node<'a>>),
    Block(&'a str),
}

pub type Cond<'a> = (Option<Expr<'a>>, Vec<Node<'a>>);

fn split_ws_parts(s: &[u8]) -> Node {
    if s.is_empty() {
        return Node::Lit(s, s, s);
    }
    let is_ws = |c: &u8| {
        *c != b' ' && *c != b'\t' && *c != b'\r' && *c != b'\n'
    };
    let start = s.iter().position(&is_ws);
    if let None = start {
        return Node::Lit(s, &s[0..0], &s[0..0]);
    }
    let start = start.unwrap();
    let end = s.iter().rposition(&is_ws);
    if let None = end {
        return Node::Lit(&s[..start], &s[start..], &s[0..0]);
    }
    let end = end.unwrap();
    Node::Lit(&s[..start], &s[start..end + 1], &s[end + 1..])
}

fn take_content(i: &[u8]) -> IResult<&[u8], Node> {
    if i.len() < 1 || i[0] == b'{' {
        return IResult::Error(error_position!(nom::ErrorKind::TakeUntil, i));
    }
    for (j, c) in i.iter().enumerate() {
        if *c == b'{' {
            if i.len() < j + 2 {
                return IResult::Done(&i[..0], split_ws_parts(&i[..]));
            } else if i[j + 1] == b'{' || i[j + 1] == b'%' {
                return IResult::Done(&i[j..], split_ws_parts(&i[..j]));
            }
        }
    }
    IResult::Done(&i[..0], split_ws_parts(&i[..]))
}

named!(expr_str_lit<Expr>, map!(
    delimited!(char!('"'), is_not!("\""), char!('"')),
    |s| Expr::StrLit(str::from_utf8(s).unwrap())
));

named!(expr_var<Expr>, map!(nom::alphanumeric, Expr::Var));

named!(target_single<Target>, map!(nom::alphanumeric, Target::Name));

fn expr_filtered(i: &[u8]) -> IResult<&[u8], Expr> {
    let (mut left, mut expr) = match expr_var(i) {
        IResult::Error(err) => { return IResult::Error(err); },
        IResult::Incomplete(needed) => { return IResult::Incomplete(needed); },
        IResult::Done(left, res) => (left, res),
    };
    while left[0] == b'|' {
        match nom::alphanumeric(&left[1..]) {
            IResult::Error(err) => {
                return IResult::Error(err);
            },
            IResult::Incomplete(needed) => {
                return IResult::Incomplete(needed);
            },
            IResult::Done(new_left, res) => {
                left = new_left;
                expr = Expr::Filter(str::from_utf8(res).unwrap(), Box::new(expr));
            },
        };
    }
    IResult::Done(left, expr)
}

named!(expr_compare<Expr>, do_parse!(
    left: expr_filtered >>
    op: ws!(alt!(
        tag_s!("==") | tag_s!("!=") |
        tag_s!(">=") | tag_s!(">") |
        tag_s!("<=") | tag_s!("<")
    )) >>
    right: expr_filtered >>
    (Expr::Compare(str::from_utf8(op).unwrap(),
                   Box::new(left), Box::new(right)))
));

named!(expr_any<Expr>, alt!(
    expr_compare |
    expr_filtered |
    expr_str_lit
));

named!(expr_node<Node>, map!(
    delimited!(tag_s!("{{"), ws!(expr_any), tag_s!("}}")),
    Node::Expr
));

named!(cond_if<Expr>, do_parse!(
    ws!(tag_s!("if")) >>
    cond: ws!(expr_any) >>
    (cond)
));

named!(cond_block<Cond>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("else")) >>
    cond: opt!(cond_if) >>
    tag_s!("%}") >>
    block: parse_template >>
    (cond, block)
));

named!(block_if<Node>, do_parse!(
    tag_s!("{%") >>
    cond: ws!(cond_if) >>
    tag_s!("%}") >>
    block: parse_template >>
    elifs: many0!(cond_block) >>
    tag_s!("{%") >>
    ws!(tag_s!("endif")) >>
    tag_s!("%}") >>
    ({
       let mut res = Vec::new();
       res.push((Some(cond), block));
       res.extend(elifs);
       Node::Cond(res)
    })
));

named!(block_for<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("for")) >>
    var: ws!(target_single) >>
    ws!(tag_s!("in")) >>
    iter: ws!(expr_any) >>
    tag_s!("%}") >>
    block: parse_template >>
    tag_s!("{%") >>
    ws!(tag_s!("endfor")) >>
    tag_s!("%}") >>
    (Node::Loop(var, iter, block))
));

named!(block_extends<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("extends")) >>
    name: ws!(expr_str_lit) >>
    tag_s!("%}") >>
    (Node::Extends(name))
));

named!(block_block<Node>, do_parse!(
    tag_s!("{%") >>
    ws!(tag_s!("block")) >>
    name: ws!(nom::alphanumeric) >>
    tag_s!("%}") >>
    contents: parse_template >>
    tag_s!("{%") >>
    ws!(tag_s!("endblock")) >>
    tag_s!("%}") >>
    (Node::BlockDef(str::from_utf8(name).unwrap(), contents))
));

named!(parse_template<Vec<Node<'a>>>, many0!(alt!(
    take_content |
    expr_node |
    block_if |
    block_for |
    block_extends |
    block_block
)));

pub fn parse(src: &str) -> Vec<Node> {
    match parse_template(src.as_bytes()) {
        IResult::Done(_, res) => res,
        IResult::Error(err) => panic!("problems parsing template source: {}", err),
        IResult::Incomplete(_) => panic!("parsing incomplete"),
    }
}

#[cfg(test)]
mod tests {
    fn check_ws_split(s: &str, res: &(&[u8], &[u8], &[u8])) {
        let node = super::split_ws_parts(s.as_bytes());
        match node {
            super::Node::Lit(lws, s, rws) => {
                assert_eq!(lws, res.0);
                assert_eq!(s, res.1);
                assert_eq!(rws, res.2);
            },
            _ => { panic!("fail"); },
        }
    }
    #[test]
    fn test_ws_splitter() {
        check_ws_split("a", &(b"", b"a", b""));
        check_ws_split("", &(b"", b"", b""));
        check_ws_split("\ta", &(b"\t", b"a", b""));
        check_ws_split("b\n", &(b"", b"b", b"\n"));
        check_ws_split(" \t\r\n", &(b" \t\r\n", b"", b""));
    }
}
<|endoftext|>


<commit_before>use crate::combat::components::intent::{XAxis, YAxis};
use crate::combat::components::{Action, Command, Facing, Intent, State, Velocity, WalkingState};
use specs::{ReadStorage, System, WriteStorage};

pub const X_STEP_SIZES: [[i32; 4]; 3] = [[-25, -3, -23, -4], [0, 0, 0, 0], [25, 3, 23, 4]];
pub const Y_STEP_SIZES: [[i32; 4]; 3] = [[-2, -9, -2, -9], [0, 0, 0, 0], [8, 2, 9, 2]];

pub struct VelocitySystem;

impl<'a> System<'a> for VelocitySystem {
    type SystemData = (
        ReadStorage<'a, Intent>,
        WriteStorage<'a, State>,
        WriteStorage<'a, Velocity>,
        WriteStorage<'a, WalkingState>,
    );

    fn run(&mut self, (intent, mut state, mut velocity, mut walking_state): Self::SystemData) {
        use specs::Join;

        for (intent, state, velocity, walking_state) in
            (&intent, &mut state, &mut velocity, &mut walking_state).join()
        {
            match state.action {
                Action::Idle | Action::Move { .. } => match intent.command {
                    Command::Move { x, y } => {
                        if x == XAxis::Centre && y == YAxis::Centre {
                            state.action = Action::Idle;
                            velocity.x = 0;
                            velocity.y = 0;
                        } else {
                            let walking_direction = match x {
                                XAxis::Right => Facing::Right,
                                XAxis::Left => Facing::Left,
                                _ => state.direction,
                            };
                            state.action = Action::Move { x, y };

                            // TODO: we're assuming x_axis animation is the same length as the y axis animation
                            let total_steps = walking_state.step_distances.x_axis
                                [(x as i32 + 1) as usize]
                                .len() as u32;
                            let mut step = (walking_state.step + 1) % total_steps;
                            if walking_direction != state.direction {
                                // if we have an ai player, then they are always
                                // facing the player, so the step sizes don't
                                // match the animation, shifting this fixes that
                                // this wasn't fixed in the original and the
                                // forward facing animations were off by 1
                                //
                                // TODO: come back to this when we add other enemy
                                // types.
                                step = (step + 1) % total_steps;
                            }

                            velocity.y = walking_state.step_distances.y_axis
                                [(y as i32 + 1) as usize][step as usize]
                                .j;
                            velocity.x = walking_state.step_distances.x_axis
                                [(x as i32 + 1) as usize][step as usize]
                                .i;
                            if x as i32 != 0 {
                                velocity.x = walking_state.step_distances.x_axis
                                    [(x as i32 + 1) as usize][step as usize]
                                    .i;
                            };
                        }
                    }
                    _ => {
                        state.action = Action::Idle;
                        velocity.x = 0;
                        velocity.y = 0;
                    }
                },
                _ => {
                    velocity.x = 0;
                    velocity.y = 0;
                }
            }
        }
    }
}

pub struct ConfirmVelocity;
// If an entity has a non zero velocity, set movement in State,
// update the walking state step
// This is used after VelocitySystem is piped through RestrictMovementBoundry
// and check entity collision, those two systems might prevent movement
// so we want to update the final velocity here.

impl<'a> System<'a> for ConfirmVelocity {
    type SystemData = (WriteStorage<'a, State>, WriteStorage<'a, WalkingState>);
    fn run(&mut self, (mut state, mut walking_state): Self::SystemData) {
        use specs::Join;
        for (state, walking_state) in (&mut state, &mut walking_state).join() {
            if let Action::Move { x, y } = state.action {
                if x == XAxis::Centre && y == YAxis::Centre {
                    state.action = Action::Idle;
                } else {
                    let walk_cycle_length =
                        walking_state.step_distances.x_axis[(x as i32 + 1) as usize].len() as u32;
                    walking_state.step = (walking_state.step + 1) % walk_cycle_length;
                }
            }
        }
    }
}
<commit_msg>Check x step size in ConfirmVelocity before centering the x axis<commit_after>use crate::combat::components::intent::{XAxis, YAxis};
use crate::combat::components::{Action, Command, Facing, Intent, State, Velocity, WalkingState};
use specs::{ReadStorage, System, WriteStorage};

pub const X_STEP_SIZES: [[i32; 4]; 3] = [[-25, -3, -23, -4], [0, 0, 0, 0], [25, 3, 23, 4]];
pub const Y_STEP_SIZES: [[i32; 4]; 3] = [[-2, -9, -2, -9], [0, 0, 0, 0], [8, 2, 9, 2]];

pub struct VelocitySystem;

impl<'a> System<'a> for VelocitySystem {
    type SystemData = (
        ReadStorage<'a, Intent>,
        WriteStorage<'a, State>,
        WriteStorage<'a, Velocity>,
        WriteStorage<'a, WalkingState>,
    );

    fn run(&mut self, (intent, mut state, mut velocity, mut walking_state): Self::SystemData) {
        use specs::Join;

        for (intent, state, velocity, walking_state) in
            (&intent, &mut state, &mut velocity, &mut walking_state).join()
        {
            match state.action {
                Action::Idle | Action::Move { .. } => match intent.command {
                    Command::Move { x, y } => {
                        if x == XAxis::Centre && y == YAxis::Centre {
                            state.action = Action::Idle;
                            velocity.x = 0;
                            velocity.y = 0;
                        } else {
                            let walking_direction = match x {
                                XAxis::Right => Facing::Right,
                                XAxis::Left => Facing::Left,
                                _ => state.direction,
                            };
                            state.action = Action::Move { x, y };

                            // TODO: we're assuming x_axis animation is the same length as the y axis animation
                            let total_steps = walking_state.step_distances.x_axis
                                [(x as i32 + 1) as usize]
                                .len() as u32;
                            let mut step = (walking_state.step + 1) % total_steps;
                            if walking_direction != state.direction {
                                // if we have an ai player, then they are always
                                // facing the player, so the step sizes don't
                                // match the animation, shifting this fixes that
                                // this wasn't fixed in the original and the
                                // forward facing animations were off by 1
                                //
                                // TODO: come back to this when we add other enemy
                                // types.
                                step = (step + 1) % total_steps;
                            }

                            velocity.y = walking_state.step_distances.y_axis
                                [(y as i32 + 1) as usize][step as usize]
                                .j;
                            velocity.x = walking_state.step_distances.x_axis
                                [(x as i32 + 1) as usize][step as usize]
                                .i;
                            if x as i32 != 0 {
                                velocity.x = walking_state.step_distances.x_axis
                                    [(x as i32 + 1) as usize][step as usize]
                                    .i;
                            };
                        }
                    }
                    _ => {
                        state.action = Action::Idle;
                        velocity.x = 0;
                        velocity.y = 0;
                    }
                },
                _ => {
                    velocity.x = 0;
                    velocity.y = 0;
                }
            }
        }
    }
}

pub struct ConfirmVelocity;
// If an entity has a non zero velocity, set movement in State,
// update the walking state step
// This is used after VelocitySystem is piped through RestrictMovementBoundry
// and check entity collision, those two systems might prevent movement
// so we want to update the final velocity here.

impl<'a> System<'a> for ConfirmVelocity {
    type SystemData = (
        ReadStorage<'a, Velocity>,
        WriteStorage<'a, State>,
        WriteStorage<'a, WalkingState>,
    );
    fn run(&mut self, (velocity, mut state, mut walking_state): Self::SystemData) {
        use specs::Join;
        for (velocity, state, walking_state) in (&velocity, &mut state, &mut walking_state).join() {
            if let Action::Move { mut x, mut y } = state.action {

                let x_step_size = walking_state.step_distances.x_axis[(x as i32 + 1) as usize][walking_state.step as usize].i;
                // Trogg spears have an animation where the size of the step they take is x = 0
                // if we only checked velocity here, then the x axis would be centered and we'd
                // incorrectly set the action as Idle. This check will also be needed if I come
                // across another enemy type that has 0 step size animations in the y direction.
                if velocity.x == 0 && x_step_size != 0 {
                    x = XAxis::Centre;
                }
                if velocity.y == 0 {
                    y = YAxis::Centre;
                }
                if x == XAxis::Centre && y == YAxis::Centre {
                    state.action = Action::Idle;
                } else {
                    let walk_cycle_length =
                        walking_state.step_distances.x_axis[(x as i32 + 1) as usize].len() as u32;
                    walking_state.step = (walking_state.step + 1) % walk_cycle_length;
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>use zerocopy::AsBytes;

#[derive(AsBytes, Copy, Clone, Debug)]
#[allow(non_camel_case_types)]
#[repr(transparent)]
pub struct i24([u8; 3]);
impl i24 {
    fn pcm_from_i32(sample: i32) -> Self {
        // drop the least significant byte
        let [a, b, c, _d] = (sample >> 8).to_le_bytes();
        i24([a, b, c])
    }
}

// Losslessly represent [-1.0, 1.0] to [$type::MIN, $type::MAX] while maintaining DC linearity.
macro_rules! convert_samples_to {
    ($type: ident, $samples: expr) => {
        convert_samples_to!($type, $samples, 0)
    };
    ($type: ident, $samples: expr, $drop_bits: expr) => {
        $samples
            .iter()
            .map(|sample| {
                (*sample as f64 * (std::$type::MAX as f64 + 0.5) - 0.5) as $type >> $drop_bits
            })
            .collect()
    };
}

pub struct SamplesConverter {}
impl SamplesConverter {
    pub fn to_s32(samples: &[f32]) -> Vec<i32> {
        convert_samples_to!(i32, samples)
    }

    pub fn to_s24(samples: &[f32]) -> Vec<i32> {
        convert_samples_to!(i32, samples, 8)
    }

    pub fn to_s24_3(samples: &[f32]) -> Vec<i24> {
        Self::to_s32(samples)
            .iter()
            .map(|sample| i24::pcm_from_i32(*sample))
            .collect()
    }

    pub fn to_s16(samples: &[f32]) -> Vec<i16> {
        convert_samples_to!(i16, samples)
    }
}
<commit_msg>Optimize requantizer to work in `f32`, then round<commit_after>use zerocopy::AsBytes;

#[derive(AsBytes, Copy, Clone, Debug)]
#[allow(non_camel_case_types)]
#[repr(transparent)]
pub struct i24([u8; 3]);
impl i24 {
    fn pcm_from_i32(sample: i32) -> Self {
        // drop the least significant byte
        let [a, b, c, _d] = (sample >> 8).to_le_bytes();
        i24([a, b, c])
    }
}

// Losslessly represent [-1.0, 1.0] to [$type::MIN, $type::MAX] while maintaining DC linearity.
macro_rules! convert_samples_to {
    ($type: ident, $samples: expr) => {
        convert_samples_to!($type, $samples, 0)
    };
    ($type: ident, $samples: expr, $drop_bits: expr) => {
        $samples
            .iter()
            .map(|sample| {
                // Losslessly represent [-1.0, 1.0] to [$type::MIN, $type::MAX]
                // while maintaining DC linearity. There is nothing to be gained
                // by doing this in f64, as the significand of a f32 is 24 bits,
                // just like the maximum bit depth we are converting to.
                let int_value = *sample * (std::$type::MAX as f32 + 0.5) - 0.5;

                // Casting floats to ints truncates by default, which results
                // in larger quantization error than rounding arithmetically.
                // Flooring is faster, but again with larger error.
                int_value.round() as $type >> $drop_bits
            })
            .collect()
    };
}

pub struct SamplesConverter {}
impl SamplesConverter {
    pub fn to_s32(samples: &[f32]) -> Vec<i32> {
        convert_samples_to!(i32, samples)
    }

    pub fn to_s24(samples: &[f32]) -> Vec<i32> {
        convert_samples_to!(i32, samples, 8)
    }

    pub fn to_s24_3(samples: &[f32]) -> Vec<i24> {
        Self::to_s32(samples)
            .iter()
            .map(|sample| i24::pcm_from_i32(*sample))
            .collect()
    }

    pub fn to_s16(samples: &[f32]) -> Vec<i16> {
        convert_samples_to!(i16, samples)
    }
}
<|endoftext|>


<commit_before>// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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.

extern crate pnet;

use pnet::datalink;
use pnet::packet::{MutablePacket, Packet};
use pnet::packet::ethernet::{EtherTypes, EthernetPacket, MutableEthernetPacket};
use pnet::packet::ip::IpNextHeaderProtocols;
use pnet::packet::ipv4::{self, MutableIpv4Packet};
use pnet::packet::udp::{self, MutableUdpPacket};

use std::env;
use std::net::Ipv4Addr;

static IPV4_HEADER_LEN: usize = 20;
static UDP_HEADER_LEN: usize = 8;
static TEST_DATA_LEN: usize = 5;

pub fn build_ipv4_header(packet: &mut [u8]) -> MutableIpv4Packet {
    let mut ip_header = MutableIpv4Packet::new(packet).unwrap();

    let total_len = (IPV4_HEADER_LEN + UDP_HEADER_LEN + TEST_DATA_LEN) as u16;

    ip_header.set_version(4);
    ip_header.set_header_length(5);
    ip_header.set_total_length(total_len);
    ip_header.set_ttl(4);
    ip_header.set_next_level_protocol(IpNextHeaderProtocols::Udp);
    ip_header.set_source(Ipv4Addr::new(127, 0, 0, 1));
    ip_header.set_destination(Ipv4Addr::new(127, 0, 0, 1));

    let checksum = ipv4::checksum(&ip_header.to_immutable());
    ip_header.set_checksum(checksum);

    ip_header
}

pub fn build_udp_header(packet: &mut [u8]) -> MutableUdpPacket {
    let mut udp_header = MutableUdpPacket::new(packet).unwrap();

    udp_header.set_source(1234); // Arbitary port number
    udp_header.set_destination(1234);
    udp_header.set_length((UDP_HEADER_LEN + TEST_DATA_LEN) as u16);

    udp_header
}

pub fn build_udp4_packet(packet: &mut [u8], msg: &str) {
    let mut ip_header = build_ipv4_header(packet);
    let source = ip_header.get_source();
    let destination = ip_header.get_destination();
    let mut udp_header = build_udp_header(ip_header.payload_mut());

    {
        let data = udp_header.payload_mut();
        let msg = msg.as_bytes();
        data[0] = msg[0];
        data[1] = msg[1];
        data[2] = msg[2];
        data[3] = msg[3];
        data[4] = msg[4];
    }

    let checksum = udp::ipv4_checksum(&udp_header.to_immutable(), source, destination);
    udp_header.set_checksum(checksum);
}

fn main() {
    use pnet::datalink::Channel::Ethernet;

    let interface_name = env::args().nth(1).unwrap();
    let destination = (&env::args().nth(2).unwrap()[..]).parse().unwrap();
    // Find the network interface with the provided name
    let interfaces = datalink::interfaces();
    let interface = interfaces.iter().filter(|iface| iface.name == interface_name).next().unwrap();

    // Create a channel to send on
    let mut tx = match datalink::channel(interface, Default::default()) {
        Ok(Ethernet(tx, _)) => tx,
        Ok(_) => panic!("rs_sender: unhandled channel type"),
        Err(e) => panic!("rs_sender: unable to create channel: {}", e),
    };

    let mut buffer = [0u8; 64];
    {
        let mut mut_ethernet_header = MutableEthernetPacket::new(&mut buffer[..]).unwrap();
        mut_ethernet_header.set_destination(destination);
        mut_ethernet_header.set_source(interface.mac_address());
        mut_ethernet_header.set_ethertype(EtherTypes::Ipv4);
        build_udp4_packet(mut_ethernet_header.payload_mut(), "rmesg");
    }

    loop {
        tx.send_to(&buffer, None);
    }
}
<commit_msg>Remove unused imports<commit_after>// Copyright (c) 2014, 2015 Robert Clipsham <robert@octarineparrot.com>
//
// 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.

extern crate pnet;

use pnet::datalink;
use pnet::packet::MutablePacket;
use pnet::packet::ethernet::{EtherTypes, MutableEthernetPacket};
use pnet::packet::ip::IpNextHeaderProtocols;
use pnet::packet::ipv4::{self, MutableIpv4Packet};
use pnet::packet::udp::{self, MutableUdpPacket};

use std::env;
use std::net::Ipv4Addr;

static IPV4_HEADER_LEN: usize = 20;
static UDP_HEADER_LEN: usize = 8;
static TEST_DATA_LEN: usize = 5;

pub fn build_ipv4_header(packet: &mut [u8]) -> MutableIpv4Packet {
    let mut ip_header = MutableIpv4Packet::new(packet).unwrap();

    let total_len = (IPV4_HEADER_LEN + UDP_HEADER_LEN + TEST_DATA_LEN) as u16;

    ip_header.set_version(4);
    ip_header.set_header_length(5);
    ip_header.set_total_length(total_len);
    ip_header.set_ttl(4);
    ip_header.set_next_level_protocol(IpNextHeaderProtocols::Udp);
    ip_header.set_source(Ipv4Addr::new(127, 0, 0, 1));
    ip_header.set_destination(Ipv4Addr::new(127, 0, 0, 1));

    let checksum = ipv4::checksum(&ip_header.to_immutable());
    ip_header.set_checksum(checksum);

    ip_header
}

pub fn build_udp_header(packet: &mut [u8]) -> MutableUdpPacket {
    let mut udp_header = MutableUdpPacket::new(packet).unwrap();

    udp_header.set_source(1234); // Arbitary port number
    udp_header.set_destination(1234);
    udp_header.set_length((UDP_HEADER_LEN + TEST_DATA_LEN) as u16);

    udp_header
}

pub fn build_udp4_packet(packet: &mut [u8], msg: &str) {
    let mut ip_header = build_ipv4_header(packet);
    let source = ip_header.get_source();
    let destination = ip_header.get_destination();
    let mut udp_header = build_udp_header(ip_header.payload_mut());

    {
        let data = udp_header.payload_mut();
        let msg = msg.as_bytes();
        data[0] = msg[0];
        data[1] = msg[1];
        data[2] = msg[2];
        data[3] = msg[3];
        data[4] = msg[4];
    }

    let checksum = udp::ipv4_checksum(&udp_header.to_immutable(), source, destination);
    udp_header.set_checksum(checksum);
}

fn main() {
    use pnet::datalink::Channel::Ethernet;

    let interface_name = env::args().nth(1).unwrap();
    let destination = (&env::args().nth(2).unwrap()[..]).parse().unwrap();
    // Find the network interface with the provided name
    let interfaces = datalink::interfaces();
    let interface = interfaces.iter().filter(|iface| iface.name == interface_name).next().unwrap();

    // Create a channel to send on
    let mut tx = match datalink::channel(interface, Default::default()) {
        Ok(Ethernet(tx, _)) => tx,
        Ok(_) => panic!("rs_sender: unhandled channel type"),
        Err(e) => panic!("rs_sender: unable to create channel: {}", e),
    };

    let mut buffer = [0u8; 64];
    {
        let mut mut_ethernet_header = MutableEthernetPacket::new(&mut buffer[..]).unwrap();
        mut_ethernet_header.set_destination(destination);
        mut_ethernet_header.set_source(interface.mac_address());
        mut_ethernet_header.set_ethertype(EtherTypes::Ipv4);
        build_udp4_packet(mut_ethernet_header.payload_mut(), "rmesg");
    }

    loop {
        tx.send_to(&buffer, None);
    }
}
<|endoftext|>


<commit_before>use crate::{api::prelude::*, proc_macros::*, render::prelude::*};

widget!(
    /// The `ImageWidget` widget is used to draw an image. It is not interactive.
    ///
    /// **style:** `image-widget`
    ImageWidget {
        /// Sets or shares the image property.
        ///
        /// Set image property:
        /// * &str: `Image::new().image("path/to/image.png").build(xt)`
        /// * String: `Image::new().image(String::from()).build(xt)`
        /// * (width: u32, height: u32, data: Vec<u32>): `Image::new().image((width, height, vec![0; width * height]));`
        image: Image
    }
);

impl Template for ImageWidget {
    fn template(self, _: Entity, _: &mut BuildContext) -> Self {
        self.name("ImageWidget").style("image-widget").image("")
    }

    fn render_object(&self) -> Box<dyn RenderObject> {
        ImageRenderObject.into()
    }

    fn layout(&self) -> Box<dyn Layout> {
        FixedSizeLayout::new().into()
    }
}
<commit_msg>fix ImageWidget examples<commit_after>use crate::{api::prelude::*, proc_macros::*, render::prelude::*};

widget!(
    /// The `ImageWidget` widget is used to draw an image. It is not interactive.
    ///
    /// **style:** `image-widget`
    ImageWidget {
        /// Sets or shares the image property.
        ///
        /// Set image property:
        /// * &str: `ImageWidget::new().image("path/to/image.png").build(xt)`
        /// * String: `ImageWidget::new().image(String::from()).build(xt)`
        /// * (width: u32, height: u32, data: Vec<u32>): `ImageWidget::new().image((width, height, vec![0; width * height]));`
        image: Image
    }
);

impl Template for ImageWidget {
    fn template(self, _: Entity, _: &mut BuildContext) -> Self {
        self.name("ImageWidget").style("image-widget").image("")
    }

    fn render_object(&self) -> Box<dyn RenderObject> {
        ImageRenderObject.into()
    }

    fn layout(&self) -> Box<dyn Layout> {
        FixedSizeLayout::new().into()
    }
}
<|endoftext|>


<commit_before>use config::action::ActionType;
use state::State;
use dispatcher::response::ResponseSender;
use context::base::BaseContext;

pub use config::action::message::Alert;

pub trait Action {
    fn on_opened(&self, state: &State, context: &BaseContext, &mut ResponseSender);
    fn on_closed(&self, state: &State, context: &BaseContext, &mut ResponseSender);
}

pub fn from_config(config: ActionType) -> Box<Action> {
    match config {
        ActionType::Message(action) => Box::new(action),
    }
}
<commit_msg>action: remove unused from_config() function<commit_after>use state::State;
use dispatcher::response::ResponseSender;
use context::base::BaseContext;

pub use config::action::message::Alert;

pub trait Action {
    fn on_opened(&self, state: &State, context: &BaseContext, &mut ResponseSender);
    fn on_closed(&self, state: &State, context: &BaseContext, &mut ResponseSender);
}
<|endoftext|>


<commit_before>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use crate::cpu_features::CpuFeatureLevel;
use crate::frame::*;
use crate::mc::*;
use crate::tiling::*;
use crate::util::*;

#[cfg(all(target_arch = "x86_64", feature = "nasm"))]
use x86_64::*;

pub(crate) type PutFn = unsafe extern fn(
  dst: *mut u8,
  dst_stride: isize,
  src: *const u8,
  src_stride: isize,
  width: i32,
  height: i32,
  col_frac: i32,
  row_frac: i32,
);

pub(crate) type PutHBDFn = unsafe extern fn(
  dst: *mut u8,
  dst_stride: isize,
  src: *const u8,
  src_stride: isize,
  width: i32,
  height: i32,
  col_frac: i32,
  row_frac: i32,
  bit_depth: i32,
);

pub(crate) type PrepFn = unsafe extern fn(
  tmp: *mut i16,
  src: *const u8,
  src_stride: isize,
  width: i32,
  height: i32,
  col_frac: i32,
  row_frac: i32,
);

pub(crate) type PrepHBDFn = unsafe extern fn(
  tmp: *mut i16,
  src: *const u16,
  src_stride: isize,
  width: i32,
  height: i32,
  col_frac: i32,
  row_frac: i32,
  bit_depth: i32,
);

pub(crate) type AvgFn = unsafe extern fn(
  dst: *mut u8,
  dst_stride: isize,
  tmp1: *const i16,
  tmp2: *const i16,
  width: i32,
  height: i32,
);

pub(crate) type AvgHBDFn = unsafe extern fn(
  dst: *mut u16,
  dst_stride: isize,
  tmp1: *const i16,
  tmp2: *const i16,
  width: i32,
  height: i32,
  bit_depth: i32,
);

// gets an index that can be mapped to a function for a pair of filter modes
pub(crate) const fn get_2d_mode_idx(
  mode_x: FilterMode, mode_y: FilterMode,
) -> usize {
  (mode_x as usize + 4 * (mode_y as usize)) & 15
}

pub fn put_8tap<T: Pixel>(
  dst: &mut PlaneRegionMut<'_, T>, src: PlaneSlice<'_, T>, width: usize,
  height: usize, col_frac: i32, row_frac: i32, mode_x: FilterMode,
  mode_y: FilterMode, bit_depth: usize, cpu: CpuFeatureLevel,
) {
  let call_native = |dst: &mut PlaneRegionMut<'_, T>| {
    native::put_8tap(
      dst, src, width, height, col_frac, row_frac, mode_x, mode_y, bit_depth,
      cpu,
    );
  };
  #[cfg(feature = "check_asm")]
  let ref_dst = {
    let mut copy = dst.scratch_copy();
    call_native(&mut copy.as_region_mut());
    copy
  };
  match T::type_enum() {
    PixelType::U8 => {
      match PUT_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] {
        Some(func) => unsafe {
          (func)(
            dst.data_ptr_mut() as *mut _,
            T::to_asm_stride(dst.plane_cfg.stride),
            src.as_ptr() as *const _,
            T::to_asm_stride(src.plane.cfg.stride),
            width as i32,
            height as i32,
            col_frac,
            row_frac,
          );
        },
        None => call_native(dst),
      }
    }
    PixelType::U16 => {
      match PUT_HBD_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] {
        Some(func) => unsafe {
          (func)(
            dst.data_ptr_mut() as *mut _,
            T::to_asm_stride(dst.plane_cfg.stride),
            src.as_ptr() as *const _,
            T::to_asm_stride(src.plane.cfg.stride),
            width as i32,
            height as i32,
            col_frac,
            row_frac,
            bit_depth as i32,
          );
        },
        None => call_native(dst),
      }
    }
  }
  #[cfg(feature = "check_asm")]
  {
    for (dst_row, ref_row) in
      dst.rows_iter().zip(ref_dst.as_region().rows_iter())
    {
      for (dst, reference) in dst_row.iter().zip(ref_row) {
        assert_eq!(*dst, *reference);
      }
    }
  }
}

pub fn prep_8tap<T: Pixel>(
  tmp: &mut [i16], src: PlaneSlice<'_, T>, width: usize, height: usize,
  col_frac: i32, row_frac: i32, mode_x: FilterMode, mode_y: FilterMode,
  bit_depth: usize, cpu: CpuFeatureLevel,
) {
  let call_native = |tmp: &mut [i16]| {
    native::prep_8tap(
      tmp, src, width, height, col_frac, row_frac, mode_x, mode_y, bit_depth,
      cpu,
    );
  };
  #[cfg(feature = "check_asm")]
  let ref_tmp = {
    let mut copy = vec![0; width * height];
    copy[..].copy_from_slice(&tmp[..width * height]);
    call_native(&mut copy);
    copy
  };
  match T::type_enum() {
    PixelType::U8 => {
      match PREP_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] {
        Some(func) => unsafe {
          (func)(
            tmp.as_mut_ptr(),
            src.as_ptr() as *const _,
            T::to_asm_stride(src.plane.cfg.stride),
            width as i32,
            height as i32,
            col_frac,
            row_frac,
          );
        },
        None => call_native(tmp),
      }
    }
    PixelType::U16 => {
      match PREP_HBD_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] {
        Some(func) => unsafe {
          (func)(
            tmp.as_mut_ptr() as *mut _,
            src.as_ptr() as *const _,
            T::to_asm_stride(src.plane.cfg.stride),
            width as i32,
            height as i32,
            col_frac,
            row_frac,
            bit_depth as i32,
          );
        },
        None => call_native(tmp),
      }
    }
  }
  #[cfg(feature = "check_asm")]
  {
    assert_eq!(tmp[..width * height], ref_tmp[..]);
  }
}

pub fn mc_avg<T: Pixel>(
  dst: &mut PlaneRegionMut<'_, T>, tmp1: &[i16], tmp2: &[i16], width: usize,
  height: usize, bit_depth: usize, cpu: CpuFeatureLevel,
) {
  let call_native = |dst: &mut PlaneRegionMut<'_, T>| {
    native::mc_avg(dst, tmp1, tmp2, width, height, bit_depth, cpu);
  };
  #[cfg(feature = "check_asm")]
  let ref_dst = {
    let mut copy = dst.scratch_copy();
    call_native(&mut copy.as_region_mut());
    copy
  };
  match T::type_enum() {
    PixelType::U8 => match AVG_FNS[cpu.as_index()] {
      Some(func) => unsafe {
        (func)(
          dst.data_ptr_mut() as *mut _,
          T::to_asm_stride(dst.plane_cfg.stride),
          tmp1.as_ptr(),
          tmp2.as_ptr(),
          width as i32,
          height as i32,
        );
      },
      None => call_native(dst),
    },
    PixelType::U16 => match AVG_HBD_FNS[cpu.as_index()] {
      Some(func) => unsafe {
        (func)(
          dst.data_ptr_mut() as *mut _,
          T::to_asm_stride(dst.plane_cfg.stride),
          tmp1.as_ptr(),
          tmp2.as_ptr(),
          width as i32,
          height as i32,
          bit_depth as i32,
        );
      },
      None => call_native(dst),
    },
  }
  #[cfg(feature = "check_asm")]
  {
    for (dst_row, ref_row) in
      dst.rows_iter().zip(ref_dst.as_region().rows_iter())
    {
      for (dst, reference) in dst_row.iter().zip(ref_row) {
        assert_eq!(*dst, *reference);
      }
    }
  }
}

#[cfg(all(target_arch = "x86_64", feature = "nasm"))]
mod x86_64 {
  use self::FilterMode::*;
  use super::*;

  macro_rules! decl_mc_fns {
    ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => {
      extern {
        $(
          fn $func_name(
            dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize,
            w: i32, h: i32, mx: i32, my: i32
          );
        )*
      }

      static PUT_FNS_AVX2: [Option<PutFn>; 16] = {
        let mut out: [Option<PutFn>; 16] = [None; 16];
        $(
          out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name);
        )*
        out
      };
    }
  }

  decl_mc_fns!(
    (REGULAR, REGULAR, rav1e_put_8tap_regular_avx2),
    (REGULAR, SMOOTH, rav1e_put_8tap_regular_smooth_avx2),
    (REGULAR, SHARP, rav1e_put_8tap_regular_sharp_avx2),
    (SMOOTH, REGULAR, rav1e_put_8tap_smooth_regular_avx2),
    (SMOOTH, SMOOTH, rav1e_put_8tap_smooth_avx2),
    (SMOOTH, SHARP, rav1e_put_8tap_smooth_sharp_avx2),
    (SHARP, REGULAR, rav1e_put_8tap_sharp_regular_avx2),
    (SHARP, SMOOTH, rav1e_put_8tap_sharp_smooth_avx2),
    (SHARP, SHARP, rav1e_put_8tap_sharp_avx2),
    (BILINEAR, BILINEAR, rav1e_put_bilin_avx2)
  );

  pub(crate) static PUT_FNS: [[Option<PutFn>; 16]; CpuFeatureLevel::len()] = {
    let mut out = [[None; 16]; CpuFeatureLevel::len()];
    out[CpuFeatureLevel::AVX2 as usize] = PUT_FNS_AVX2;
    out
  };

  pub(crate) static PUT_HBD_FNS: [[Option<PutHBDFn>; 16];
    CpuFeatureLevel::len()] = [[None; 16]; CpuFeatureLevel::len()];

  macro_rules! decl_mct_fns {
    ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => {
      extern {
        $(
          fn $func_name(
            tmp: *mut i16, src: *const u8, src_stride: libc::ptrdiff_t, w: i32,
            h: i32, mx: i32, my: i32
          );
        )*
      }

      static PREP_FNS_AVX2: [Option<PrepFn>; 16] = {
        let mut out: [Option<PrepFn>; 16] = [None; 16];
        $(
          out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name);
        )*
        out
      };
    }
  }

  decl_mct_fns!(
    (REGULAR, REGULAR, rav1e_prep_8tap_regular_avx2),
    (REGULAR, SMOOTH, rav1e_prep_8tap_regular_smooth_avx2),
    (REGULAR, SHARP, rav1e_prep_8tap_regular_sharp_avx2),
    (SMOOTH, REGULAR, rav1e_prep_8tap_smooth_regular_avx2),
    (SMOOTH, SMOOTH, rav1e_prep_8tap_smooth_avx2),
    (SMOOTH, SHARP, rav1e_prep_8tap_smooth_sharp_avx2),
    (SHARP, REGULAR, rav1e_prep_8tap_sharp_regular_avx2),
    (SHARP, SMOOTH, rav1e_prep_8tap_sharp_smooth_avx2),
    (SHARP, SHARP, rav1e_prep_8tap_sharp_avx2),
    (BILINEAR, BILINEAR, rav1e_prep_bilin_avx2)
  );

  pub(crate) static PREP_FNS: [[Option<PrepFn>; 16]; CpuFeatureLevel::len()] = {
    let mut out = [[None; 16]; CpuFeatureLevel::len()];
    out[CpuFeatureLevel::AVX2 as usize] = PREP_FNS_AVX2;
    out
  };

  pub(crate) static PREP_HBD_FNS: [[Option<PrepHBDFn>; 16];
    CpuFeatureLevel::len()] = [[None; 16]; CpuFeatureLevel::len()];

  extern {
    fn rav1e_avg_avx2(
      dst: *mut u8, dst_stride: libc::ptrdiff_t, tmp1: *const i16,
      tmp2: *const i16, w: i32, h: i32,
    );
  }

  pub(crate) static AVG_FNS: [Option<AvgFn>; CpuFeatureLevel::len()] = {
    let mut out: [Option<AvgFn>; CpuFeatureLevel::len()] =
      [None; CpuFeatureLevel::len()];
    out[CpuFeatureLevel::AVX2 as usize] = Some(rav1e_avg_avx2);
    out
  };

  pub(crate) static AVG_HBD_FNS: [Option<AvgHBDFn>; CpuFeatureLevel::len()] =
    [None; CpuFeatureLevel::len()];
}
<commit_msg>Remove unneeded pub(crate) from asm/mc.rs<commit_after>// Copyright (c) 2019, The rav1e contributors. All rights reserved
//
// This source code is subject to the terms of the BSD 2 Clause License and
// the Alliance for Open Media Patent License 1.0. If the BSD 2 Clause License
// was not distributed with this source code in the LICENSE file, you can
// obtain it at www.aomedia.org/license/software. If the Alliance for Open
// Media Patent License 1.0 was not distributed with this source code in the
// PATENTS file, you can obtain it at www.aomedia.org/license/patent.

use crate::cpu_features::CpuFeatureLevel;
use crate::frame::*;
use crate::mc::*;
use crate::tiling::*;
use crate::util::*;

#[cfg(all(target_arch = "x86_64", feature = "nasm"))]
use x86_64::*;

type PutFn = unsafe extern fn(
  dst: *mut u8,
  dst_stride: isize,
  src: *const u8,
  src_stride: isize,
  width: i32,
  height: i32,
  col_frac: i32,
  row_frac: i32,
);

type PutHBDFn = unsafe extern fn(
  dst: *mut u8,
  dst_stride: isize,
  src: *const u8,
  src_stride: isize,
  width: i32,
  height: i32,
  col_frac: i32,
  row_frac: i32,
  bit_depth: i32,
);

type PrepFn = unsafe extern fn(
  tmp: *mut i16,
  src: *const u8,
  src_stride: isize,
  width: i32,
  height: i32,
  col_frac: i32,
  row_frac: i32,
);

type PrepHBDFn = unsafe extern fn(
  tmp: *mut i16,
  src: *const u16,
  src_stride: isize,
  width: i32,
  height: i32,
  col_frac: i32,
  row_frac: i32,
  bit_depth: i32,
);

type AvgFn = unsafe extern fn(
  dst: *mut u8,
  dst_stride: isize,
  tmp1: *const i16,
  tmp2: *const i16,
  width: i32,
  height: i32,
);

type AvgHBDFn = unsafe extern fn(
  dst: *mut u16,
  dst_stride: isize,
  tmp1: *const i16,
  tmp2: *const i16,
  width: i32,
  height: i32,
  bit_depth: i32,
);

// gets an index that can be mapped to a function for a pair of filter modes
const fn get_2d_mode_idx(mode_x: FilterMode, mode_y: FilterMode) -> usize {
  (mode_x as usize + 4 * (mode_y as usize)) & 15
}

pub fn put_8tap<T: Pixel>(
  dst: &mut PlaneRegionMut<'_, T>, src: PlaneSlice<'_, T>, width: usize,
  height: usize, col_frac: i32, row_frac: i32, mode_x: FilterMode,
  mode_y: FilterMode, bit_depth: usize, cpu: CpuFeatureLevel,
) {
  let call_native = |dst: &mut PlaneRegionMut<'_, T>| {
    native::put_8tap(
      dst, src, width, height, col_frac, row_frac, mode_x, mode_y, bit_depth,
      cpu,
    );
  };
  #[cfg(feature = "check_asm")]
  let ref_dst = {
    let mut copy = dst.scratch_copy();
    call_native(&mut copy.as_region_mut());
    copy
  };
  match T::type_enum() {
    PixelType::U8 => {
      match PUT_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] {
        Some(func) => unsafe {
          (func)(
            dst.data_ptr_mut() as *mut _,
            T::to_asm_stride(dst.plane_cfg.stride),
            src.as_ptr() as *const _,
            T::to_asm_stride(src.plane.cfg.stride),
            width as i32,
            height as i32,
            col_frac,
            row_frac,
          );
        },
        None => call_native(dst),
      }
    }
    PixelType::U16 => {
      match PUT_HBD_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] {
        Some(func) => unsafe {
          (func)(
            dst.data_ptr_mut() as *mut _,
            T::to_asm_stride(dst.plane_cfg.stride),
            src.as_ptr() as *const _,
            T::to_asm_stride(src.plane.cfg.stride),
            width as i32,
            height as i32,
            col_frac,
            row_frac,
            bit_depth as i32,
          );
        },
        None => call_native(dst),
      }
    }
  }
  #[cfg(feature = "check_asm")]
  {
    for (dst_row, ref_row) in
      dst.rows_iter().zip(ref_dst.as_region().rows_iter())
    {
      for (dst, reference) in dst_row.iter().zip(ref_row) {
        assert_eq!(*dst, *reference);
      }
    }
  }
}

pub fn prep_8tap<T: Pixel>(
  tmp: &mut [i16], src: PlaneSlice<'_, T>, width: usize, height: usize,
  col_frac: i32, row_frac: i32, mode_x: FilterMode, mode_y: FilterMode,
  bit_depth: usize, cpu: CpuFeatureLevel,
) {
  let call_native = |tmp: &mut [i16]| {
    native::prep_8tap(
      tmp, src, width, height, col_frac, row_frac, mode_x, mode_y, bit_depth,
      cpu,
    );
  };
  #[cfg(feature = "check_asm")]
  let ref_tmp = {
    let mut copy = vec![0; width * height];
    copy[..].copy_from_slice(&tmp[..width * height]);
    call_native(&mut copy);
    copy
  };
  match T::type_enum() {
    PixelType::U8 => {
      match PREP_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] {
        Some(func) => unsafe {
          (func)(
            tmp.as_mut_ptr(),
            src.as_ptr() as *const _,
            T::to_asm_stride(src.plane.cfg.stride),
            width as i32,
            height as i32,
            col_frac,
            row_frac,
          );
        },
        None => call_native(tmp),
      }
    }
    PixelType::U16 => {
      match PREP_HBD_FNS[cpu.as_index()][get_2d_mode_idx(mode_x, mode_y)] {
        Some(func) => unsafe {
          (func)(
            tmp.as_mut_ptr() as *mut _,
            src.as_ptr() as *const _,
            T::to_asm_stride(src.plane.cfg.stride),
            width as i32,
            height as i32,
            col_frac,
            row_frac,
            bit_depth as i32,
          );
        },
        None => call_native(tmp),
      }
    }
  }
  #[cfg(feature = "check_asm")]
  {
    assert_eq!(tmp[..width * height], ref_tmp[..]);
  }
}

pub fn mc_avg<T: Pixel>(
  dst: &mut PlaneRegionMut<'_, T>, tmp1: &[i16], tmp2: &[i16], width: usize,
  height: usize, bit_depth: usize, cpu: CpuFeatureLevel,
) {
  let call_native = |dst: &mut PlaneRegionMut<'_, T>| {
    native::mc_avg(dst, tmp1, tmp2, width, height, bit_depth, cpu);
  };
  #[cfg(feature = "check_asm")]
  let ref_dst = {
    let mut copy = dst.scratch_copy();
    call_native(&mut copy.as_region_mut());
    copy
  };
  match T::type_enum() {
    PixelType::U8 => match AVG_FNS[cpu.as_index()] {
      Some(func) => unsafe {
        (func)(
          dst.data_ptr_mut() as *mut _,
          T::to_asm_stride(dst.plane_cfg.stride),
          tmp1.as_ptr(),
          tmp2.as_ptr(),
          width as i32,
          height as i32,
        );
      },
      None => call_native(dst),
    },
    PixelType::U16 => match AVG_HBD_FNS[cpu.as_index()] {
      Some(func) => unsafe {
        (func)(
          dst.data_ptr_mut() as *mut _,
          T::to_asm_stride(dst.plane_cfg.stride),
          tmp1.as_ptr(),
          tmp2.as_ptr(),
          width as i32,
          height as i32,
          bit_depth as i32,
        );
      },
      None => call_native(dst),
    },
  }
  #[cfg(feature = "check_asm")]
  {
    for (dst_row, ref_row) in
      dst.rows_iter().zip(ref_dst.as_region().rows_iter())
    {
      for (dst, reference) in dst_row.iter().zip(ref_row) {
        assert_eq!(*dst, *reference);
      }
    }
  }
}

#[cfg(all(target_arch = "x86_64", feature = "nasm"))]
mod x86_64 {
  use self::FilterMode::*;
  use super::*;

  macro_rules! decl_mc_fns {
    ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => {
      extern {
        $(
          fn $func_name(
            dst: *mut u8, dst_stride: isize, src: *const u8, src_stride: isize,
            w: i32, h: i32, mx: i32, my: i32
          );
        )*
      }

      static PUT_FNS_AVX2: [Option<PutFn>; 16] = {
        let mut out: [Option<PutFn>; 16] = [None; 16];
        $(
          out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name);
        )*
        out
      };
    }
  }

  decl_mc_fns!(
    (REGULAR, REGULAR, rav1e_put_8tap_regular_avx2),
    (REGULAR, SMOOTH, rav1e_put_8tap_regular_smooth_avx2),
    (REGULAR, SHARP, rav1e_put_8tap_regular_sharp_avx2),
    (SMOOTH, REGULAR, rav1e_put_8tap_smooth_regular_avx2),
    (SMOOTH, SMOOTH, rav1e_put_8tap_smooth_avx2),
    (SMOOTH, SHARP, rav1e_put_8tap_smooth_sharp_avx2),
    (SHARP, REGULAR, rav1e_put_8tap_sharp_regular_avx2),
    (SHARP, SMOOTH, rav1e_put_8tap_sharp_smooth_avx2),
    (SHARP, SHARP, rav1e_put_8tap_sharp_avx2),
    (BILINEAR, BILINEAR, rav1e_put_bilin_avx2)
  );

  pub(crate) static PUT_FNS: [[Option<PutFn>; 16]; CpuFeatureLevel::len()] = {
    let mut out = [[None; 16]; CpuFeatureLevel::len()];
    out[CpuFeatureLevel::AVX2 as usize] = PUT_FNS_AVX2;
    out
  };

  pub(crate) static PUT_HBD_FNS: [[Option<PutHBDFn>; 16];
    CpuFeatureLevel::len()] = [[None; 16]; CpuFeatureLevel::len()];

  macro_rules! decl_mct_fns {
    ($(($mode_x:expr, $mode_y:expr, $func_name:ident)),+) => {
      extern {
        $(
          fn $func_name(
            tmp: *mut i16, src: *const u8, src_stride: libc::ptrdiff_t, w: i32,
            h: i32, mx: i32, my: i32
          );
        )*
      }

      static PREP_FNS_AVX2: [Option<PrepFn>; 16] = {
        let mut out: [Option<PrepFn>; 16] = [None; 16];
        $(
          out[get_2d_mode_idx($mode_x, $mode_y)] = Some($func_name);
        )*
        out
      };
    }
  }

  decl_mct_fns!(
    (REGULAR, REGULAR, rav1e_prep_8tap_regular_avx2),
    (REGULAR, SMOOTH, rav1e_prep_8tap_regular_smooth_avx2),
    (REGULAR, SHARP, rav1e_prep_8tap_regular_sharp_avx2),
    (SMOOTH, REGULAR, rav1e_prep_8tap_smooth_regular_avx2),
    (SMOOTH, SMOOTH, rav1e_prep_8tap_smooth_avx2),
    (SMOOTH, SHARP, rav1e_prep_8tap_smooth_sharp_avx2),
    (SHARP, REGULAR, rav1e_prep_8tap_sharp_regular_avx2),
    (SHARP, SMOOTH, rav1e_prep_8tap_sharp_smooth_avx2),
    (SHARP, SHARP, rav1e_prep_8tap_sharp_avx2),
    (BILINEAR, BILINEAR, rav1e_prep_bilin_avx2)
  );

  pub(crate) static PREP_FNS: [[Option<PrepFn>; 16]; CpuFeatureLevel::len()] = {
    let mut out = [[None; 16]; CpuFeatureLevel::len()];
    out[CpuFeatureLevel::AVX2 as usize] = PREP_FNS_AVX2;
    out
  };

  pub(crate) static PREP_HBD_FNS: [[Option<PrepHBDFn>; 16];
    CpuFeatureLevel::len()] = [[None; 16]; CpuFeatureLevel::len()];

  extern {
    fn rav1e_avg_avx2(
      dst: *mut u8, dst_stride: libc::ptrdiff_t, tmp1: *const i16,
      tmp2: *const i16, w: i32, h: i32,
    );
  }

  pub(crate) static AVG_FNS: [Option<AvgFn>; CpuFeatureLevel::len()] = {
    let mut out: [Option<AvgFn>; CpuFeatureLevel::len()] =
      [None; CpuFeatureLevel::len()];
    out[CpuFeatureLevel::AVX2 as usize] = Some(rav1e_avg_avx2);
    out
  };

  pub(crate) static AVG_HBD_FNS: [Option<AvgHBDFn>; CpuFeatureLevel::len()] =
    [None; CpuFeatureLevel::len()];
}
<|endoftext|>