<commit_before>#![allow(dead_code)]

use parser::ast::*;
use scope::context::*;
use processing::structs::*;

type FormalProp<'a> = (&'a str);
type FormalPropVec<'a> = Vec<FormalProp<'a>>;

type PropKeyRef = (String, String);
type PropKeyRefVec = Vec<PropKeyRef>;

// type PropValue<'a> = (&'a str, Option<&'a ExprValue>);
// type PropValueVec<'a> = Vec<PropValue<'a>>;

#[derive(Debug, Clone, Default)]
pub struct CompDefProcessorOutput {
    ty: Option<String>,
    ops: Option<OpsVec>
}

impl Into<Component> for CompDefProcessorOutput {
    fn into(self) -> Component {
        Component::new_with_vec(self.ty.unwrap(), self.ops)
    }
}

#[derive(Debug)]
pub struct CompDefProcessor<'out> {
    output: &'out mut CompDefProcessorOutput
}

impl<'out> CompDefProcessor<'out> {
    pub fn with_output(output: &'out mut CompDefProcessorOutput) -> Self {
        CompDefProcessor { output: output }
    }

    fn add_op(&mut self, op: ElementOp) {
        if let Some(ref mut ops) = self.output.ops {
            ops.push(op);
        } else {
            self.output.ops = Some(vec![op]);
        }
    }

    pub fn push_component_definition_scope<'a, I>(&mut self, ctx: &mut Context,component_ty: &str, formals: I)
        where I: IntoIterator<Item = &'a FormalProp<'a>>
    {
        if self.output.ty.is_some() {
            panic!("Already have component defintion in this output.");
        }
        self.output.ty = Some(component_ty.to_owned());

        ctx.push_child_scope();
        for formal in formals {
            ctx.add_unbound_formal_param(formal);
        }
    }

    pub fn push_element_parameter_definition_scope<'a, I>(&mut self, ctx: &mut Context, element_id: &str, element_ty: &str, props: Option<I>)
        where I: IntoIterator<Item = &'a PropKeyRef> + Clone
    {
        // let props = props.map(|props| props.clone().into_iter());
        let element_props = props.as_ref().map(|props| props.clone().into_iter().map(|prop| {
            let key = &prop.0;
            let ref_key = &prop.1;
            let value_sym = ctx.resolve_sym(ref_key);
            if let Some(value_sym) = value_sym {
                return (key.to_owned(), Some(ExprValue::SymbolReference(value_sym)));
            };
            (key.to_owned(), None)
        }).collect());

        let op = ElementOp::ElementVoid(element_ty.to_owned(), Some(element_id.to_owned()), element_props, None, None);
        self.add_op(op);

        let parent_scope_id = ctx.scope().id().to_owned();
        ctx.push_child_scope();
        if let Some(props) = props {
            for prop in props {
                ctx.add_element_prop_ref(&prop.0, &prop.1, Some(&parent_scope_id));
            }
        }
    }

    pub fn push_element_scope(&mut self, ctx: &mut Context, element_id: &str, _element_ty: &str) {
        ctx.push_child_scope();
        ctx.append_path_str(element_id);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::iter::*;
    use parser::ast::*;
    use scope::context::*;

    trait OpsWriter {
        fn write_op(&mut self, op: &ElementOp);
    }

    #[derive(Debug, Default)]
    struct TestOpsWriter {
        output_ops: Vec<ElementOp>
    }

    impl<'a> TestOpsWriter {
        pub fn ops_iter(&'a self) -> impl Iterator<Item = &'a ElementOp> {
            self.output_ops.iter()
        }
    }

    impl OpsWriter for TestOpsWriter {
        fn write_op(&mut self, op: &ElementOp) {
            self.output_ops.push(op.to_owned());
        }
    }

    #[derive(Debug, Default)]
    struct ComponentWriter {}

    impl ComponentWriter {
        fn write_op_to<W>(&mut self, ctx: &mut Context, ops_writer: &mut W, comp_op: &ElementOp)
          where W: OpsWriter
        {
            match comp_op {
                &ElementOp::ElementVoid(ref element_ty, ref element_id, ref props, ref event_handlers, ref value_bindings) => {
                    if let &Some(ref props) = props {
                        let prop_iter = props.iter().map(|prop| (prop.0.as_str(), prop.1.as_ref()));
                        // let iter = ctx.resolve_props(prop_iter);
                        let iter = SymbolResolver::new(ctx, prop_iter);
                        let resolved_props: Vec<Prop> = iter.collect();

                        let op = ElementOp::ElementVoid(element_ty.to_owned(), element_id.to_owned(), Some(resolved_props), event_handlers.to_owned(), value_bindings.to_owned());
                        ops_writer.write_op(&op);
                    };
                },
                _ => { ops_writer.write_op(comp_op); }
            };
        }

        pub fn write_component<W>(&mut self, ctx: &mut Context, ops_writer: &mut W, comp: &Component)
          where W: OpsWriter
        {
            if let Some(ops_iter) = comp.ops_iter() {
                for op in ops_iter {
                    ops_writer.write_op(op);
                }
            };
        }
    }

    #[derive(Debug)]
    pub struct ComponentOutputProcessor {
    }

    impl ComponentOutputProcessor {
        pub fn push_component_invocation_scope<'a, I>(&mut self, ctx: &mut Context, comp: &Component)
          where I: IntoIterator<Item = PropValue<'a>>
        {
            ctx.push_child_scope();
        }
    }

    #[test]
    pub fn test_process_comp_def1() {
        let mut output = CompDefProcessorOutput::default();

        let comp_definition_scope_id: String;
        // let element_param_defs_scope_id: String;
        {
            let mut ctx = Context::default();
            let mut processor = CompDefProcessor::with_output(&mut output);

            // component Component(todo)
            // Create new component context with unbound formal prop (todo)
            {
                let formals: FormalPropVec = vec![("todo")];
                processor.push_component_definition_scope(&mut ctx, "Component", formals.iter());
            }
            comp_definition_scope_id = ctx.scope().id().to_owned();

            // within Component definition
            {
                // The local (todo) should be an unbound formal prop (todo)
                assert_eq!(ctx.resolve_sym("todo"),
                    // Some(Symbol::ref_prop_in_scope("todo", "todo", Some(&lm_element_scope_id)))
                    Some(Symbol::unbound_formal_param("todo", Some(&comp_definition_scope_id)))
                );
            }
            // element_param_defs_scope_id = ctx.scope().id().to_owned();

            // element Pq invocation
            {
                let props: PropKeyRefVec = vec![
                    ("value".into(), "todo".into())
                ];
                processor.push_element_parameter_definition_scope(&mut ctx, "Pq", "input", Some(props.iter()));
            }
            // let element_pq_invocation_scope_id = ctx.scope().id().to_owned();

            // element Pq scope
            {
                processor.push_element_scope(&mut ctx, "Pq", "input");

                // The local (todo) should still be an unbound formal param (todo)
                assert_eq!(ctx.resolve_sym("todo"),
                    Some(Symbol::unbound_formal_param("todo", Some(&comp_definition_scope_id)))
                );
            }
        }

        // Verify output
        let comp: Component = output.into();
        assert_eq!(comp.ty(), "Component");
        assert_eq!(
            comp.ops_iter().map(|v| v.into_iter().cloned().collect()),
            Some(vec![
                ElementOp::ElementVoid("input".into(), Some("Pq".into()), Some(vec![(
                    "value".into(),
                    Some(ExprValue::SymbolReference(Symbol::unbound_formal_param("todo", Some(&comp_definition_scope_id)) ))
                )]), None, None)
            ])
        );

        // Test writer
        let mut ops_writer = TestOpsWriter::default();

        {
            let mut ctx = Context::default();
            let mut comp_writer = ComponentWriter::default();

            comp_writer.write_component(&mut ctx, &mut ops_writer, &comp);
        }

        assert_eq!(ops_writer.ops_iter().cloned().collect::<OpsVec>(), vec![
                ElementOp::ElementVoid("input".into(), Some("Pq".into()), Some(vec![(
                    "value".into(),
                    Some(ExprValue::SymbolReference(Symbol::unbound_formal_param("todo", Some(&comp_definition_scope_id)) ))
                )]), None, None)
        ]);
    }
}<commit_msg>Update ComponentWriter to actually use write_op_to and change it to a static method<commit_after>#![allow(dead_code)]

use parser::ast::*;
use scope::context::*;
use processing::structs::*;

type FormalProp<'a> = (&'a str);
type FormalPropVec<'a> = Vec<FormalProp<'a>>;

type PropKeyRef = (String, String);
type PropKeyRefVec = Vec<PropKeyRef>;

// type PropValue<'a> = (&'a str, Option<&'a ExprValue>);
// type PropValueVec<'a> = Vec<PropValue<'a>>;

#[derive(Debug, Clone, Default)]
pub struct CompDefProcessorOutput {
    ty: Option<String>,
    ops: Option<OpsVec>
}

impl Into<Component> for CompDefProcessorOutput {
    fn into(self) -> Component {
        Component::new_with_vec(self.ty.unwrap(), self.ops)
    }
}

#[derive(Debug)]
pub struct CompDefProcessor<'out> {
    output: &'out mut CompDefProcessorOutput
}

impl<'out> CompDefProcessor<'out> {
    pub fn with_output(output: &'out mut CompDefProcessorOutput) -> Self {
        CompDefProcessor { output: output }
    }

    fn add_op(&mut self, op: ElementOp) {
        if let Some(ref mut ops) = self.output.ops {
            ops.push(op);
        } else {
            self.output.ops = Some(vec![op]);
        }
    }

    pub fn push_component_definition_scope<'a, I>(&mut self, ctx: &mut Context,component_ty: &str, formals: I)
        where I: IntoIterator<Item = &'a FormalProp<'a>>
    {
        if self.output.ty.is_some() {
            panic!("Already have component defintion in this output.");
        }
        self.output.ty = Some(component_ty.to_owned());

        ctx.push_child_scope();
        for formal in formals {
            ctx.add_unbound_formal_param(formal);
        }
    }

    pub fn push_element_parameter_definition_scope<'a, I>(&mut self, ctx: &mut Context, element_id: &str, element_ty: &str, props: Option<I>)
        where I: IntoIterator<Item = &'a PropKeyRef> + Clone
    {
        // let props = props.map(|props| props.clone().into_iter());
        let element_props = props.as_ref().map(|props| props.clone().into_iter().map(|prop| {
            let key = &prop.0;
            let ref_key = &prop.1;
            let value_sym = ctx.resolve_sym(ref_key);
            if let Some(value_sym) = value_sym {
                return (key.to_owned(), Some(ExprValue::SymbolReference(value_sym)));
            };
            (key.to_owned(), None)
        }).collect());

        let op = ElementOp::ElementVoid(element_ty.to_owned(), Some(element_id.to_owned()), element_props, None, None);
        self.add_op(op);

        let parent_scope_id = ctx.scope().id().to_owned();
        ctx.push_child_scope();
        if let Some(props) = props {
            for prop in props {
                ctx.add_element_prop_ref(&prop.0, &prop.1, Some(&parent_scope_id));
            }
        }
    }

    pub fn push_element_scope(&mut self, ctx: &mut Context, element_id: &str, _element_ty: &str) {
        ctx.push_child_scope();
        ctx.append_path_str(element_id);
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::iter::*;
    use parser::ast::*;
    use scope::context::*;

    trait OpsWriter {
        fn write_op(&mut self, op: &ElementOp);
    }

    #[derive(Debug, Default)]
    struct TestOpsWriter {
        output_ops: Vec<ElementOp>
    }

    impl<'a> TestOpsWriter {
        pub fn ops_iter(&'a self) -> impl Iterator<Item = &'a ElementOp> {
            self.output_ops.iter()
        }
    }

    impl OpsWriter for TestOpsWriter {
        fn write_op(&mut self, op: &ElementOp) {
            self.output_ops.push(op.to_owned());
        }
    }

    #[derive(Debug, Default)]
    struct ComponentWriter {}

    impl ComponentWriter {
        fn write_op_to<W>(ctx: &mut Context, ops_writer: &mut W, comp_op: &ElementOp)
          where W: OpsWriter
        {
            match comp_op {
                &ElementOp::ElementVoid(ref element_ty, ref element_id, ref props, ref event_handlers, ref value_bindings) => {
                    if let &Some(ref props) = props {
                        let prop_iter = props.iter().map(|prop| (prop.0.as_str(), prop.1.as_ref()));
                        // let iter = ctx.resolve_props(prop_iter);
                        let iter = SymbolResolver::new(ctx, prop_iter);
                        let resolved_props: Vec<Prop> = iter.collect();

                        let op = ElementOp::ElementVoid(element_ty.to_owned(), element_id.to_owned(), Some(resolved_props), event_handlers.to_owned(), value_bindings.to_owned());
                        ops_writer.write_op(&op);
                    };
                },
                _ => { ops_writer.write_op(comp_op); }
            };
        }

        pub fn write_component<W>(&mut self, ctx: &mut Context, ops_writer: &mut W, comp: &Component)
          where W: OpsWriter
        {
            if let Some(ops_iter) = comp.ops_iter() {
                for op in ops_iter {
                    Self::write_op_to(ctx, ops_writer, op);
                    // ops_writer.write_op(op);
                }
            };
        }
    }

    #[derive(Debug)]
    pub struct ComponentOutputProcessor {
    }

    impl ComponentOutputProcessor {
        pub fn push_component_invocation_scope<'a, I>(&mut self, ctx: &mut Context, comp: &Component)
          where I: IntoIterator<Item = PropValue<'a>>
        {
            ctx.push_child_scope();
        }
    }

    #[test]
    pub fn test_process_comp_def1() {
        let mut output = CompDefProcessorOutput::default();

        let comp_definition_scope_id: String;
        // let element_param_defs_scope_id: String;
        {
            let mut ctx = Context::default();
            let mut processor = CompDefProcessor::with_output(&mut output);

            // component Component(todo)
            // Create new component context with unbound formal prop (todo)
            {
                let formals: FormalPropVec = vec![("todo")];
                processor.push_component_definition_scope(&mut ctx, "Component", formals.iter());
            }
            comp_definition_scope_id = ctx.scope().id().to_owned();

            // within Component definition
            {
                // The local (todo) should be an unbound formal prop (todo)
                assert_eq!(ctx.resolve_sym("todo"),
                    // Some(Symbol::ref_prop_in_scope("todo", "todo", Some(&lm_element_scope_id)))
                    Some(Symbol::unbound_formal_param("todo", Some(&comp_definition_scope_id)))
                );
            }
            // element_param_defs_scope_id = ctx.scope().id().to_owned();

            // element Pq invocation
            {
                let props: PropKeyRefVec = vec![
                    ("value".into(), "todo".into())
                ];
                processor.push_element_parameter_definition_scope(&mut ctx, "Pq", "input", Some(props.iter()));
            }
            // let element_pq_invocation_scope_id = ctx.scope().id().to_owned();

            // element Pq scope
            {
                processor.push_element_scope(&mut ctx, "Pq", "input");

                // The local (todo) should still be an unbound formal param (todo)
                assert_eq!(ctx.resolve_sym("todo"),
                    Some(Symbol::unbound_formal_param("todo", Some(&comp_definition_scope_id)))
                );
            }
        }

        // Verify output
        let comp: Component = output.into();
        assert_eq!(comp.ty(), "Component");
        assert_eq!(
            comp.ops_iter().map(|v| v.into_iter().cloned().collect()),
            Some(vec![
                ElementOp::ElementVoid("input".into(), Some("Pq".into()), Some(vec![(
                    "value".into(),
                    Some(ExprValue::SymbolReference(Symbol::unbound_formal_param("todo", Some(&comp_definition_scope_id)) ))
                )]), None, None)
            ])
        );

        // Test writer
        let mut ops_writer = TestOpsWriter::default();

        {
            let mut ctx = Context::default();
            let mut comp_writer = ComponentWriter::default();

            comp_writer.write_component(&mut ctx, &mut ops_writer, &comp);
        }

        assert_eq!(ops_writer.ops_iter().cloned().collect::<OpsVec>(), vec![
                ElementOp::ElementVoid("input".into(), Some("Pq".into()), Some(vec![(
                    "value".into(),
                    Some(ExprValue::SymbolReference(Symbol::unbound_formal_param("todo", Some(&comp_definition_scope_id)) ))
                )]), None, None)
        ]);
    }
}<|endoftext|>


<commit_before>use core::fmt;
use core::ops::{Deref, DerefMut};

/// Pads and aligns a value to the length of a cache line.
///
/// In concurrent programming, sometimes it is desirable to make sure commonly accessed pieces of
/// data are not placed into the same cache line. Updating an atomic value invalides the whole
/// cache line it belongs to, which makes the next access to the same cache line slower for other
/// CPU cores. Use `CachePadded` to ensure updating one piece of data doesn't invalidate other
/// cached data.
///
/// # Size and alignment
///
/// Cache lines are assumed to be N bytes long, depending on the architecture:
///
/// * On x86-64 and aarch64, N = 128.
/// * On all others, N = 64.
///
/// Note that N is just a reasonable guess and is not guaranteed to match the actual cache line
/// length of the machine the program is running on. On modern Intel architectures, spatial
/// prefetcher is pulling pairs of 64-byte cache lines at a time, so we pessimistically assume that
/// cache lines are 128 bytes long.
///
/// The size of `CachePadded<T>` is the smallest multiple of N bytes large enough to accommodate
/// a value of type `T`.
///
/// The alignment of `CachePadded<T>` is the maximum of N bytes and the alignment of `T`.
///
/// # Examples
///
/// Alignment and padding:
///
/// ```
/// use crossbeam_utils::CachePadded;
///
/// let array = [CachePadded::new(1i8), CachePadded::new(2i8)];
/// let addr1 = &*array[0] as *const i8 as usize;
/// let addr2 = &*array[1] as *const i8 as usize;
///
/// assert!(addr2 - addr1 >= 64);
/// assert_eq!(addr1 % 64, 0);
/// assert_eq!(addr2 % 64, 0);
/// ```
///
/// When building a concurrent queue with a head and a tail index, it is wise to place them in
/// different cache lines so that concurrent threads pushing and popping elements don't invalidate
/// each other's cache lines:
///
/// ```
/// use crossbeam_utils::CachePadded;
/// use std::sync::atomic::AtomicUsize;
///
/// struct Queue<T> {
///     head: CachePadded<AtomicUsize>,
///     tail: CachePadded<AtomicUsize>,
///     buffer: *mut T,
/// }
/// ```
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq)]
// Starting from Intel's Sandy Bridge, spatial prefetcher is now pulling pairs of 64-byte cache
// lines at a time, so we have to align to 128 bytes rather than 64.
//
// Sources:
// - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
// - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107
//
// ARM's big.LITTLE architecture has asymmetric cores and "big" cores have 128 byte cache line size
// Sources:
// - https://www.mono-project.com/news/2016/09/12/arm64-icache/
//
#[cfg_attr(any(target_arch = "x86_64", target_arch = "aarch64"), repr(align(128)))]
#[cfg_attr(not(any(target_arch = "x86_64", target_arch = "aarch64")), repr(align(64)))]
pub struct CachePadded<T> {
    value: T,
}

unsafe impl<T: Send> Send for CachePadded<T> {}
unsafe impl<T: Sync> Sync for CachePadded<T> {}

impl<T> CachePadded<T> {
    /// Pads and aligns a value to the length of a cache line.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::CachePadded;
    ///
    /// let padded_value = CachePadded::new(1);
    /// ```
    pub fn new(t: T) -> CachePadded<T> {
        CachePadded::<T> { value: t }
    }

    /// Returns the inner value.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::CachePadded;
    ///
    /// let padded_value = CachePadded::new(7);
    /// let value = padded_value.into_inner();
    /// assert_eq!(value, 7);
    /// ```
    pub fn into_inner(self) -> T {
        self.value
    }
}

impl<T> Deref for CachePadded<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T> DerefMut for CachePadded<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}

impl<T: fmt::Debug> fmt::Debug for CachePadded<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("CachePadded")
            .field("value", &self.value)
            .finish()
    }
}

impl<T> From<T> for CachePadded<T> {
    fn from(t: T) -> Self {
        CachePadded::new(t)
    }
}
<commit_msg>Rustfmt<commit_after>use core::fmt;
use core::ops::{Deref, DerefMut};

/// Pads and aligns a value to the length of a cache line.
///
/// In concurrent programming, sometimes it is desirable to make sure commonly accessed pieces of
/// data are not placed into the same cache line. Updating an atomic value invalides the whole
/// cache line it belongs to, which makes the next access to the same cache line slower for other
/// CPU cores. Use `CachePadded` to ensure updating one piece of data doesn't invalidate other
/// cached data.
///
/// # Size and alignment
///
/// Cache lines are assumed to be N bytes long, depending on the architecture:
///
/// * On x86-64 and aarch64, N = 128.
/// * On all others, N = 64.
///
/// Note that N is just a reasonable guess and is not guaranteed to match the actual cache line
/// length of the machine the program is running on. On modern Intel architectures, spatial
/// prefetcher is pulling pairs of 64-byte cache lines at a time, so we pessimistically assume that
/// cache lines are 128 bytes long.
///
/// The size of `CachePadded<T>` is the smallest multiple of N bytes large enough to accommodate
/// a value of type `T`.
///
/// The alignment of `CachePadded<T>` is the maximum of N bytes and the alignment of `T`.
///
/// # Examples
///
/// Alignment and padding:
///
/// ```
/// use crossbeam_utils::CachePadded;
///
/// let array = [CachePadded::new(1i8), CachePadded::new(2i8)];
/// let addr1 = &*array[0] as *const i8 as usize;
/// let addr2 = &*array[1] as *const i8 as usize;
///
/// assert!(addr2 - addr1 >= 64);
/// assert_eq!(addr1 % 64, 0);
/// assert_eq!(addr2 % 64, 0);
/// ```
///
/// When building a concurrent queue with a head and a tail index, it is wise to place them in
/// different cache lines so that concurrent threads pushing and popping elements don't invalidate
/// each other's cache lines:
///
/// ```
/// use crossbeam_utils::CachePadded;
/// use std::sync::atomic::AtomicUsize;
///
/// struct Queue<T> {
///     head: CachePadded<AtomicUsize>,
///     tail: CachePadded<AtomicUsize>,
///     buffer: *mut T,
/// }
/// ```
#[derive(Clone, Copy, Default, Hash, PartialEq, Eq)]
// Starting from Intel's Sandy Bridge, spatial prefetcher is now pulling pairs of 64-byte cache
// lines at a time, so we have to align to 128 bytes rather than 64.
//
// Sources:
// - https://www.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-optimization-manual.pdf
// - https://github.com/facebook/folly/blob/1b5288e6eea6df074758f877c849b6e73bbb9fbb/folly/lang/Align.h#L107
//
// ARM's big.LITTLE architecture has asymmetric cores and "big" cores have 128 byte cache line size
// Sources:
// - https://www.mono-project.com/news/2016/09/12/arm64-icache/
//
#[cfg_attr(any(target_arch = "x86_64", target_arch = "aarch64"), repr(align(128)))]
#[cfg_attr(
    not(any(target_arch = "x86_64", target_arch = "aarch64")),
    repr(align(64))
)]
pub struct CachePadded<T> {
    value: T,
}

unsafe impl<T: Send> Send for CachePadded<T> {}
unsafe impl<T: Sync> Sync for CachePadded<T> {}

impl<T> CachePadded<T> {
    /// Pads and aligns a value to the length of a cache line.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::CachePadded;
    ///
    /// let padded_value = CachePadded::new(1);
    /// ```
    pub fn new(t: T) -> CachePadded<T> {
        CachePadded::<T> { value: t }
    }

    /// Returns the inner value.
    ///
    /// # Examples
    ///
    /// ```
    /// use crossbeam_utils::CachePadded;
    ///
    /// let padded_value = CachePadded::new(7);
    /// let value = padded_value.into_inner();
    /// assert_eq!(value, 7);
    /// ```
    pub fn into_inner(self) -> T {
        self.value
    }
}

impl<T> Deref for CachePadded<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.value
    }
}

impl<T> DerefMut for CachePadded<T> {
    fn deref_mut(&mut self) -> &mut T {
        &mut self.value
    }
}

impl<T: fmt::Debug> fmt::Debug for CachePadded<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("CachePadded")
            .field("value", &self.value)
            .finish()
    }
}

impl<T> From<T> for CachePadded<T> {
    fn from(t: T) -> Self {
        CachePadded::new(t)
    }
}
<|endoftext|>


<commit_before>use std::{env, path::Path};

use quote::{quote, ToTokens};
use syn::{parse_quote, visit_mut::VisitMut};

struct FilterSwigAttrs;

impl VisitMut for FilterSwigAttrs {
    fn visit_attribute_mut(&mut self, i: &mut syn::Attribute) {
        if i.path
            .clone()
            .into_token_stream()
            .to_string()
            .starts_with("swig_")
        {
            *i = parse_quote! { #[doc = "swig_ replace"] };
        }
    }
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    for include_path in &[
        Path::new("src/java_jni/jni-include.rs"),
        Path::new("src/cpp/cpp-include.rs"),
    ] {
        let src_cnt = std::fs::read_to_string(include_path)
            .expect(&format!("Error during read {}", include_path.display()));
        let mut file = syn::parse_file(&src_cnt)
            .expect(&format!("Error during parse {}", include_path.display()));

        let mut filter_swig_attrs = FilterSwigAttrs;
        filter_swig_attrs.visit_file_mut(&mut file);

        let out_path = Path::new(&out_dir).join(include_path.file_name().expect("No file name"));
        std::fs::write(&out_path, file.into_token_stream().to_string()).expect(&format!(
            "Error during write to file {}",
            out_path.display()
        ));
        println!("cargo:rerun-if-changed={}", out_path.display());
        println!("cargo:rerun-if-changed={}", include_path.display());
    }
    println!("cargo:rerun-if-changed=tests/test_includes_syntax.rs");
}
<commit_msg>fix rebuild every time<commit_after>use std::{env, io::Write, path::Path};

use quote::{quote, ToTokens};
use syn::{parse_quote, visit_mut::VisitMut};

struct FilterSwigAttrs;

impl VisitMut for FilterSwigAttrs {
    fn visit_attribute_mut(&mut self, i: &mut syn::Attribute) {
        if i.path
            .clone()
            .into_token_stream()
            .to_string()
            .starts_with("swig_")
        {
            *i = parse_quote! { #[doc = "swig_ replace"] };
        }
    }
}

mod file_cache {
    include!("src/file_cache.rs");
}

fn main() {
    let out_dir = env::var("OUT_DIR").unwrap();
    for include_path in &[
        Path::new("src/java_jni/jni-include.rs"),
        Path::new("src/cpp/cpp-include.rs"),
    ] {
        let src_cnt = std::fs::read_to_string(include_path)
            .expect(&format!("Error during read {}", include_path.display()));
        let mut file = syn::parse_file(&src_cnt)
            .expect(&format!("Error during parse {}", include_path.display()));

        let mut filter_swig_attrs = FilterSwigAttrs;
        filter_swig_attrs.visit_file_mut(&mut file);

        let out_path = Path::new(&out_dir).join(include_path.file_name().expect("No file name"));
        let mut cache = file_cache::FileWriteCache::new(&out_path);
        let write_err_msg = format!("Error during write to file {}", out_path.display());
        write!(&mut cache, "{}", file.into_token_stream().to_string()).expect(&write_err_msg);
        cache.update_file_if_necessary().expect(&write_err_msg);
        println!("cargo:rerun-if-changed={}", out_path.display());
        println!("cargo:rerun-if-changed={}", include_path.display());
    }
    println!("cargo:rerun-if-changed=tests/test_includes_syntax.rs");
}
<|endoftext|>


<commit_before>use ssz::{impl_decode_via_from, impl_encode_via_from, Decodable, DecodeError, Encodable};
/// Available RPC methods types and ids.
use ssz_derive::{Decode, Encode};
use types::{BeaconBlockBody, BeaconBlockHeader, Epoch, Hash256, Slot};

#[derive(Debug)]
/// Available Serenity Libp2p RPC methods
pub enum RPCMethod {
    /// Initialise handshake between connecting peers.
    Hello,
    /// Terminate a connection providing a reason.
    Goodbye,
    /// Requests a number of beacon block roots.
    BeaconBlockRoots,
    /// Requests a number of beacon block headers.
    BeaconBlockHeaders,
    /// Requests a number of beacon block bodies.
    BeaconBlockBodies,
    /// Requests values for a merkle proof for the current blocks state root.
    BeaconChainState, // Note: experimental, not complete.
    /// Unknown method received.
    Unknown,
}

impl From<u16> for RPCMethod {
    fn from(method_id: u16) -> Self {
        match method_id {
            0 => RPCMethod::Hello,
            1 => RPCMethod::Goodbye,
            10 => RPCMethod::BeaconBlockRoots,
            11 => RPCMethod::BeaconBlockHeaders,
            12 => RPCMethod::BeaconBlockBodies,
            13 => RPCMethod::BeaconChainState,

            _ => RPCMethod::Unknown,
        }
    }
}

impl Into<u16> for RPCMethod {
    fn into(self) -> u16 {
        match self {
            RPCMethod::Hello => 0,
            RPCMethod::Goodbye => 1,
            RPCMethod::BeaconBlockRoots => 10,
            RPCMethod::BeaconBlockHeaders => 11,
            RPCMethod::BeaconBlockBodies => 12,
            RPCMethod::BeaconChainState => 13,
            _ => 0,
        }
    }
}

#[derive(Debug, Clone)]
pub enum RPCRequest {
    Hello(HelloMessage),
    Goodbye(GoodbyeReason),
    BeaconBlockRoots(BeaconBlockRootsRequest),
    BeaconBlockHeaders(BeaconBlockHeadersRequest),
    BeaconBlockBodies(BeaconBlockBodiesRequest),
    BeaconChainState(BeaconChainStateRequest),
}

impl RPCRequest {
    pub fn method_id(&self) -> u16 {
        let method = match self {
            RPCRequest::Hello(_) => RPCMethod::Hello,
            RPCRequest::Goodbye(_) => RPCMethod::Goodbye,
            RPCRequest::BeaconBlockRoots(_) => RPCMethod::BeaconBlockRoots,
            RPCRequest::BeaconBlockHeaders(_) => RPCMethod::BeaconBlockHeaders,
            RPCRequest::BeaconBlockBodies(_) => RPCMethod::BeaconBlockBodies,
            RPCRequest::BeaconChainState(_) => RPCMethod::BeaconChainState,
        };
        method.into()
    }
}

#[derive(Debug, Clone)]
pub enum RPCResponse {
    Hello(HelloMessage),
    BeaconBlockRoots(BeaconBlockRootsResponse),
    BeaconBlockHeaders(BeaconBlockHeadersResponse),
    BeaconBlockBodies(BeaconBlockBodiesResponse),
    BeaconChainState(BeaconChainStateResponse),
}

impl RPCResponse {
    pub fn method_id(&self) -> u16 {
        let method = match self {
            RPCResponse::Hello(_) => RPCMethod::Hello,
            RPCResponse::BeaconBlockRoots(_) => RPCMethod::BeaconBlockRoots,
            RPCResponse::BeaconBlockHeaders(_) => RPCMethod::BeaconBlockHeaders,
            RPCResponse::BeaconBlockBodies(_) => RPCMethod::BeaconBlockBodies,
            RPCResponse::BeaconChainState(_) => RPCMethod::BeaconChainState,
        };
        method.into()
    }
}

/* Request/Response data structures for RPC methods */

/// The HELLO request/response handshake message.
#[derive(Encode, Decode, Clone, Debug)]
pub struct HelloMessage {
    /// The network ID of the peer.
    pub network_id: u8,
    /// The peers last finalized root.
    pub latest_finalized_root: Hash256,
    /// The peers last finalized epoch.
    pub latest_finalized_epoch: Epoch,
    /// The peers last block root.
    pub best_root: Hash256,
    /// The peers last slot.
    pub best_slot: Slot,
}

/// The reason given for a `Goodbye` message.
///
/// Note: any unknown `u64::into(n)` will resolve to `GoodbyeReason::Unknown` for any unknown `n`,
/// however `GoodbyeReason::Unknown.into()` will go into `0_u64`. Therefore de-serializing then
/// re-serializing may not return the same bytes.
#[derive(Debug, Clone)]
pub enum GoodbyeReason {
    ClientShutdown,
    IrreleventNetwork,
    Fault,
    Unknown,
}

impl From<u64> for GoodbyeReason {
    fn from(id: u64) -> GoodbyeReason {
        match id {
            1 => GoodbyeReason::ClientShutdown,
            2 => GoodbyeReason::IrreleventNetwork,
            3 => GoodbyeReason::Fault,
            _ => GoodbyeReason::Unknown,
        }
    }
}

impl Into<u64> for GoodbyeReason {
    fn into(self) -> u64 {
        match self {
            GoodbyeReason::Unknown => 0,
            GoodbyeReason::ClientShutdown => 1,
            GoodbyeReason::IrreleventNetwork => 2,
            GoodbyeReason::Fault => 3,
        }
    }
}

impl_encode_via_from!(GoodbyeReason, u64);
impl_decode_via_from!(GoodbyeReason, u64);

/// Request a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockRootsRequest {
    /// The starting slot of the requested blocks.
    pub start_slot: Slot,
    /// The number of blocks from the start slot.
    pub count: u64, // this must be less than 32768. //TODO: Enforce this in the lower layers
}

/// Response containing a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockRootsResponse {
    /// List of requested blocks and associated slots.
    pub roots: Vec<BlockRootSlot>,
}

impl BeaconBlockRootsResponse {
    /// Returns `true` if each `self.roots.slot[i]` is higher than the preceeding `i`.
    pub fn slots_are_ascending(&self) -> bool {
        for i in 1..self.roots.len() {
            if self.roots[i - 1].slot >= self.roots[i].slot {
                return false;
            }
        }

        true
    }
}

/// Contains a block root and associated slot.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BlockRootSlot {
    /// The block root.
    pub block_root: Hash256,
    /// The block slot.
    pub slot: Slot,
}

/// Request a number of beacon block headers from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockHeadersRequest {
    /// The starting header hash of the requested headers.
    pub start_root: Hash256,
    /// The starting slot of the requested headers.
    pub start_slot: Slot,
    /// The maximum number of headers than can be returned.
    pub max_headers: u64,
    /// The maximum number of slots to skip between blocks.
    pub skip_slots: u64,
}

/// Response containing requested block headers.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockHeadersResponse {
    /// The list of requested beacon block headers.
    pub headers: Vec<BeaconBlockHeader>,
}

/// Request a number of beacon block bodies from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockBodiesRequest {
    /// The list of beacon block bodies being requested.
    pub block_roots: Vec<Hash256>,
}

/// Response containing the list of requested beacon block bodies.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockBodiesResponse {
    /// The list of beacon block bodies being requested.
    pub block_bodies: Vec<BeaconBlockBody>,
}

/// Request values for tree hashes which yield a blocks `state_root`.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconChainStateRequest {
    /// The tree hashes that a value is requested for.
    pub hashes: Vec<Hash256>,
}

/// Request values for tree hashes which yield a blocks `state_root`.
// Note: TBD
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconChainStateResponse {
    /// The values corresponding the to the requested tree hashes.
    pub values: bool, //TBD - stubbed with encodeable bool
}
<commit_msg>Fix warnings in `rpc`<commit_after>//!Available RPC methods types and ids.

use ssz::{impl_decode_via_from, impl_encode_via_from};
use ssz_derive::{Decode, Encode};
use types::{BeaconBlockBody, BeaconBlockHeader, Epoch, Hash256, Slot};

#[derive(Debug)]
/// Available Serenity Libp2p RPC methods
pub enum RPCMethod {
    /// Initialise handshake between connecting peers.
    Hello,
    /// Terminate a connection providing a reason.
    Goodbye,
    /// Requests a number of beacon block roots.
    BeaconBlockRoots,
    /// Requests a number of beacon block headers.
    BeaconBlockHeaders,
    /// Requests a number of beacon block bodies.
    BeaconBlockBodies,
    /// Requests values for a merkle proof for the current blocks state root.
    BeaconChainState, // Note: experimental, not complete.
    /// Unknown method received.
    Unknown,
}

impl From<u16> for RPCMethod {
    fn from(method_id: u16) -> Self {
        match method_id {
            0 => RPCMethod::Hello,
            1 => RPCMethod::Goodbye,
            10 => RPCMethod::BeaconBlockRoots,
            11 => RPCMethod::BeaconBlockHeaders,
            12 => RPCMethod::BeaconBlockBodies,
            13 => RPCMethod::BeaconChainState,

            _ => RPCMethod::Unknown,
        }
    }
}

impl Into<u16> for RPCMethod {
    fn into(self) -> u16 {
        match self {
            RPCMethod::Hello => 0,
            RPCMethod::Goodbye => 1,
            RPCMethod::BeaconBlockRoots => 10,
            RPCMethod::BeaconBlockHeaders => 11,
            RPCMethod::BeaconBlockBodies => 12,
            RPCMethod::BeaconChainState => 13,
            _ => 0,
        }
    }
}

#[derive(Debug, Clone)]
pub enum RPCRequest {
    Hello(HelloMessage),
    Goodbye(GoodbyeReason),
    BeaconBlockRoots(BeaconBlockRootsRequest),
    BeaconBlockHeaders(BeaconBlockHeadersRequest),
    BeaconBlockBodies(BeaconBlockBodiesRequest),
    BeaconChainState(BeaconChainStateRequest),
}

impl RPCRequest {
    pub fn method_id(&self) -> u16 {
        let method = match self {
            RPCRequest::Hello(_) => RPCMethod::Hello,
            RPCRequest::Goodbye(_) => RPCMethod::Goodbye,
            RPCRequest::BeaconBlockRoots(_) => RPCMethod::BeaconBlockRoots,
            RPCRequest::BeaconBlockHeaders(_) => RPCMethod::BeaconBlockHeaders,
            RPCRequest::BeaconBlockBodies(_) => RPCMethod::BeaconBlockBodies,
            RPCRequest::BeaconChainState(_) => RPCMethod::BeaconChainState,
        };
        method.into()
    }
}

#[derive(Debug, Clone)]
pub enum RPCResponse {
    Hello(HelloMessage),
    BeaconBlockRoots(BeaconBlockRootsResponse),
    BeaconBlockHeaders(BeaconBlockHeadersResponse),
    BeaconBlockBodies(BeaconBlockBodiesResponse),
    BeaconChainState(BeaconChainStateResponse),
}

impl RPCResponse {
    pub fn method_id(&self) -> u16 {
        let method = match self {
            RPCResponse::Hello(_) => RPCMethod::Hello,
            RPCResponse::BeaconBlockRoots(_) => RPCMethod::BeaconBlockRoots,
            RPCResponse::BeaconBlockHeaders(_) => RPCMethod::BeaconBlockHeaders,
            RPCResponse::BeaconBlockBodies(_) => RPCMethod::BeaconBlockBodies,
            RPCResponse::BeaconChainState(_) => RPCMethod::BeaconChainState,
        };
        method.into()
    }
}

/* Request/Response data structures for RPC methods */

/// The HELLO request/response handshake message.
#[derive(Encode, Decode, Clone, Debug)]
pub struct HelloMessage {
    /// The network ID of the peer.
    pub network_id: u8,
    /// The peers last finalized root.
    pub latest_finalized_root: Hash256,
    /// The peers last finalized epoch.
    pub latest_finalized_epoch: Epoch,
    /// The peers last block root.
    pub best_root: Hash256,
    /// The peers last slot.
    pub best_slot: Slot,
}

/// The reason given for a `Goodbye` message.
///
/// Note: any unknown `u64::into(n)` will resolve to `GoodbyeReason::Unknown` for any unknown `n`,
/// however `GoodbyeReason::Unknown.into()` will go into `0_u64`. Therefore de-serializing then
/// re-serializing may not return the same bytes.
#[derive(Debug, Clone)]
pub enum GoodbyeReason {
    ClientShutdown,
    IrreleventNetwork,
    Fault,
    Unknown,
}

impl From<u64> for GoodbyeReason {
    fn from(id: u64) -> GoodbyeReason {
        match id {
            1 => GoodbyeReason::ClientShutdown,
            2 => GoodbyeReason::IrreleventNetwork,
            3 => GoodbyeReason::Fault,
            _ => GoodbyeReason::Unknown,
        }
    }
}

impl Into<u64> for GoodbyeReason {
    fn into(self) -> u64 {
        match self {
            GoodbyeReason::Unknown => 0,
            GoodbyeReason::ClientShutdown => 1,
            GoodbyeReason::IrreleventNetwork => 2,
            GoodbyeReason::Fault => 3,
        }
    }
}

impl_encode_via_from!(GoodbyeReason, u64);
impl_decode_via_from!(GoodbyeReason, u64);

/// Request a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockRootsRequest {
    /// The starting slot of the requested blocks.
    pub start_slot: Slot,
    /// The number of blocks from the start slot.
    pub count: u64, // this must be less than 32768. //TODO: Enforce this in the lower layers
}

/// Response containing a number of beacon block roots from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockRootsResponse {
    /// List of requested blocks and associated slots.
    pub roots: Vec<BlockRootSlot>,
}

impl BeaconBlockRootsResponse {
    /// Returns `true` if each `self.roots.slot[i]` is higher than the preceeding `i`.
    pub fn slots_are_ascending(&self) -> bool {
        for i in 1..self.roots.len() {
            if self.roots[i - 1].slot >= self.roots[i].slot {
                return false;
            }
        }

        true
    }
}

/// Contains a block root and associated slot.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BlockRootSlot {
    /// The block root.
    pub block_root: Hash256,
    /// The block slot.
    pub slot: Slot,
}

/// Request a number of beacon block headers from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockHeadersRequest {
    /// The starting header hash of the requested headers.
    pub start_root: Hash256,
    /// The starting slot of the requested headers.
    pub start_slot: Slot,
    /// The maximum number of headers than can be returned.
    pub max_headers: u64,
    /// The maximum number of slots to skip between blocks.
    pub skip_slots: u64,
}

/// Response containing requested block headers.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockHeadersResponse {
    /// The list of requested beacon block headers.
    pub headers: Vec<BeaconBlockHeader>,
}

/// Request a number of beacon block bodies from a peer.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockBodiesRequest {
    /// The list of beacon block bodies being requested.
    pub block_roots: Vec<Hash256>,
}

/// Response containing the list of requested beacon block bodies.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconBlockBodiesResponse {
    /// The list of beacon block bodies being requested.
    pub block_bodies: Vec<BeaconBlockBody>,
}

/// Request values for tree hashes which yield a blocks `state_root`.
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconChainStateRequest {
    /// The tree hashes that a value is requested for.
    pub hashes: Vec<Hash256>,
}

/// Request values for tree hashes which yield a blocks `state_root`.
// Note: TBD
#[derive(Encode, Decode, Clone, Debug, PartialEq)]
pub struct BeaconChainStateResponse {
    /// The values corresponding the to the requested tree hashes.
    pub values: bool, //TBD - stubbed with encodeable bool
}
<|endoftext|>


<commit_before>use rustc::{declare_lint, hir, lint, lint_array, ty};
use crate::utils;

/// **What it does:** Checks for usage of the `offset` pointer method with a `usize` casted to an
/// `isize`.
///
/// **Why is this bad?** If we’re always increasing the pointer address, we can avoid the numeric
/// cast by using the `add` method instead.
///
/// **Known problems:** None
///
/// **Example:**
/// ```rust
/// let vec = vec![b'a', b'b', b'c'];
/// let ptr = vec.as_ptr();
/// let offset = 1_usize;
///
/// unsafe { ptr.offset(offset as isize); }
/// ```
///
/// Could be written:
///
/// ```rust
/// let vec = vec![b'a', b'b', b'c'];
/// let ptr = vec.as_ptr();
/// let offset = 1_usize;
///
/// unsafe { ptr.add(offset); }
/// ```
declare_clippy_lint! {
    pub PTR_OFFSET_WITH_CAST,
    complexity,
    "uneeded pointer offset cast"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl lint::LintPass for Pass {
    fn get_lints(&self) -> lint::LintArray {
        lint_array!(PTR_OFFSET_WITH_CAST)
    }
}

impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &lint::LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        // Check if the expressions is a ptr.offset method call
        let [receiver_expr, arg_expr] = match expr_as_ptr_offset_call(cx, expr) {
            Some(call_arg) => call_arg,
            None => return,
        };

        // Check if the argument to ptr.offset is a cast from usize
        let cast_lhs_expr = match expr_as_cast_from_usize(cx, arg_expr) {
            Some(cast_lhs_expr) => cast_lhs_expr,
            None => return,
        };

        utils::span_lint_and_sugg(
            cx,
            PTR_OFFSET_WITH_CAST,
            expr.span,
            "use of `offset` with a `usize` casted to an `isize`",
            "try",
            build_suggestion(cx, receiver_expr, cast_lhs_expr),
        );
    }
}

// If the given expression is a cast from a usize, return the lhs of the cast
fn expr_as_cast_from_usize<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    expr: &'tcx hir::Expr,
) -> Option<&'tcx hir::Expr> {
    if let hir::ExprKind::Cast(ref cast_lhs_expr, _) = expr.node {
        if is_expr_ty_usize(cx, &cast_lhs_expr) {
            return Some(cast_lhs_expr);
        }
    }
    None
}

// If the given expression is a ptr::offset method call, return the receiver and the arg of the
// method call.
fn expr_as_ptr_offset_call<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    expr: &'tcx hir::Expr,
) -> Option<[&'tcx hir::Expr; 2]> {
    if let hir::ExprKind::MethodCall(ref path_segment, _, ref args) = expr.node {
        if path_segment.ident.name == "offset" && is_expr_ty_raw_ptr(cx, &args[0]) {
            return Some([&args[0], &args[1]]);
        }
    }
    None
}

// Is the type of the expression a usize?
fn is_expr_ty_usize<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    expr: &hir::Expr,
) -> bool {
    cx.tables.expr_ty(expr) == cx.tcx.types.usize
}

// Is the type of the expression a raw pointer?
fn is_expr_ty_raw_ptr<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    expr: &hir::Expr,
) -> bool {
    if let ty::RawPtr(..) = cx.tables.expr_ty(expr).sty {
        true
    } else {
        false
    }
}

fn build_suggestion<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    receiver_expr: &hir::Expr,
    cast_lhs_expr: &hir::Expr,
) -> String {
    match (
        utils::snippet_opt(cx, receiver_expr.span),
        utils::snippet_opt(cx, cast_lhs_expr.span)
    ) {
        (Some(receiver), Some(cast_lhs)) => format!("{}.add({})", receiver, cast_lhs),
        _ => String::new(),
    }
}
<commit_msg>utilize .is_unsafe_ptr<commit_after>use rustc::{declare_lint, hir, lint, lint_array};
use crate::utils;

/// **What it does:** Checks for usage of the `offset` pointer method with a `usize` casted to an
/// `isize`.
///
/// **Why is this bad?** If we’re always increasing the pointer address, we can avoid the numeric
/// cast by using the `add` method instead.
///
/// **Known problems:** None
///
/// **Example:**
/// ```rust
/// let vec = vec![b'a', b'b', b'c'];
/// let ptr = vec.as_ptr();
/// let offset = 1_usize;
///
/// unsafe { ptr.offset(offset as isize); }
/// ```
///
/// Could be written:
///
/// ```rust
/// let vec = vec![b'a', b'b', b'c'];
/// let ptr = vec.as_ptr();
/// let offset = 1_usize;
///
/// unsafe { ptr.add(offset); }
/// ```
declare_clippy_lint! {
    pub PTR_OFFSET_WITH_CAST,
    complexity,
    "uneeded pointer offset cast"
}

#[derive(Copy, Clone, Debug)]
pub struct Pass;

impl lint::LintPass for Pass {
    fn get_lints(&self) -> lint::LintArray {
        lint_array!(PTR_OFFSET_WITH_CAST)
    }
}

impl<'a, 'tcx> lint::LateLintPass<'a, 'tcx> for Pass {
    fn check_expr(&mut self, cx: &lint::LateContext<'a, 'tcx>, expr: &'tcx hir::Expr) {
        // Check if the expressions is a ptr.offset method call
        let [receiver_expr, arg_expr] = match expr_as_ptr_offset_call(cx, expr) {
            Some(call_arg) => call_arg,
            None => return,
        };

        // Check if the argument to ptr.offset is a cast from usize
        let cast_lhs_expr = match expr_as_cast_from_usize(cx, arg_expr) {
            Some(cast_lhs_expr) => cast_lhs_expr,
            None => return,
        };

        utils::span_lint_and_sugg(
            cx,
            PTR_OFFSET_WITH_CAST,
            expr.span,
            "use of `offset` with a `usize` casted to an `isize`",
            "try",
            build_suggestion(cx, receiver_expr, cast_lhs_expr),
        );
    }
}

// If the given expression is a cast from a usize, return the lhs of the cast
fn expr_as_cast_from_usize<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    expr: &'tcx hir::Expr,
) -> Option<&'tcx hir::Expr> {
    if let hir::ExprKind::Cast(ref cast_lhs_expr, _) = expr.node {
        if is_expr_ty_usize(cx, &cast_lhs_expr) {
            return Some(cast_lhs_expr);
        }
    }
    None
}

// If the given expression is a ptr::offset method call, return the receiver and the arg of the
// method call.
fn expr_as_ptr_offset_call<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    expr: &'tcx hir::Expr,
) -> Option<[&'tcx hir::Expr; 2]> {
    if let hir::ExprKind::MethodCall(ref path_segment, _, ref args) = expr.node {
        if path_segment.ident.name == "offset" && is_expr_ty_raw_ptr(cx, &args[0]) {
            return Some([&args[0], &args[1]]);
        }
    }
    None
}

// Is the type of the expression a usize?
fn is_expr_ty_usize<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    expr: &hir::Expr,
) -> bool {
    cx.tables.expr_ty(expr) == cx.tcx.types.usize
}

// Is the type of the expression a raw pointer?
fn is_expr_ty_raw_ptr<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    expr: &hir::Expr,
) -> bool {
    cx.tables.expr_ty(expr).is_unsafe_ptr()
}

fn build_suggestion<'a, 'tcx>(
    cx: &lint::LateContext<'a, 'tcx>,
    receiver_expr: &hir::Expr,
    cast_lhs_expr: &hir::Expr,
) -> String {
    match (
        utils::snippet_opt(cx, receiver_expr.span),
        utils::snippet_opt(cx, cast_lhs_expr.span)
    ) {
        (Some(receiver), Some(cast_lhs)) => format!("{}.add({})", receiver, cast_lhs),
        _ => String::new(),
    }
}
<|endoftext|>


<commit_before>use rustc_hir::Mutability;
use rustc_index::bit_set::HybridBitSet;
use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{self, BasicBlock, Local, Location};
use rustc_middle::ty::TyCtxt;

use crate::transform::MirPass;

/// This pass looks for MIR that always copies the same local into the return place and eliminates
/// the copy by renaming all uses of that local to `_0`.
///
/// This allows LLVM to perform an optimization similar to the named return value optimization
/// (NRVO) that is guaranteed in C++. This avoids a stack allocation and `memcpy` for the
/// relatively common pattern of allocating a buffer on the stack, mutating it, and returning it by
/// value like so:
///
/// ```rust
/// fn foo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
///     let mut buf = [0; 1024];
///     init(&mut buf);
///     buf
/// }
/// ```
///
/// For now, this pass is very simple and only capable of eliminating a single copy. A more general
/// version of copy propagation, such as the one based on non-overlapping live ranges in [#47954] and
/// [#71003], could yield even more benefits.
///
/// [#47954]: https://github.com/rust-lang/rust/pull/47954
/// [#71003]: https://github.com/rust-lang/rust/pull/71003
pub struct RenameReturnPlace;

impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
        if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
            return;
        }

        let returned_local = match local_eligible_for_nrvo(body) {
            Some(l) => l,
            None => {
                debug!("`{:?}` was ineligible for NRVO", body.source.def_id());
                return;
            }
        };

        debug!(
            "`{:?}` was eligible for NRVO, making {:?} the return place",
            body.source.def_id(),
            returned_local
        );

        RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body(body);

        // Clean up the `NOP`s we inserted for statements made useless by our renaming.
        for block_data in body.basic_blocks_mut() {
            block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop);
        }

        // Overwrite the debuginfo of `_0` with that of the renamed local.
        let (renamed_decl, ret_decl) =
            body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE);

        // Sometimes, the return place is assigned a local of a different but coercable type, for
        // example `&mut T` instead of `&T`. Overwriting the `LocalInfo` for the return place means
        // its type may no longer match the return type of its function. This doesn't cause a
        // problem in codegen because these two types are layout-compatible, but may be unexpected.
        debug!("_0: {:?} = {:?}: {:?}", ret_decl.ty, returned_local, renamed_decl.ty);
        ret_decl.clone_from(renamed_decl);

        // The return place is always mutable.
        ret_decl.mutability = Mutability::Mut;
    }
}

/// MIR that is eligible for the NRVO must fulfill two conditions:
///   1. The return place must not be read prior to the `Return` terminator.
///   2. A simple assignment of a whole local to the return place (e.g., `_0 = _1`) must be the
///      only definition of the return place reaching the `Return` terminator.
///
/// If the MIR fulfills both these conditions, this function returns the `Local` that is assigned
/// to the return place along all possible paths through the control-flow graph.
fn local_eligible_for_nrvo(body: &mut mir::Body<'_>) -> Option<Local> {
    if IsReturnPlaceRead::run(body) {
        return None;
    }

    let mut copied_to_return_place = None;
    for block in body.basic_blocks().indices() {
        // Look for blocks with a `Return` terminator.
        if !matches!(body[block].terminator().kind, mir::TerminatorKind::Return) {
            continue;
        }

        // Look for an assignment of a single local to the return place prior to the `Return`.
        let returned_local = find_local_assigned_to_return_place(block, body)?;
        match body.local_kind(returned_local) {
            // FIXME: Can we do this for arguments as well?
            mir::LocalKind::Arg => return None,

            mir::LocalKind::ReturnPointer => bug!("Return place was assigned to itself?"),
            mir::LocalKind::Var | mir::LocalKind::Temp => {}
        }

        // If multiple different locals are copied to the return place. We can't pick a
        // single one to rename.
        if copied_to_return_place.map_or(false, |old| old != returned_local) {
            return None;
        }

        copied_to_return_place = Some(returned_local);
    }

    copied_to_return_place
}

fn find_local_assigned_to_return_place(
    start: BasicBlock,
    body: &mut mir::Body<'_>,
) -> Option<Local> {
    let mut block = start;
    let mut seen = HybridBitSet::new_empty(body.basic_blocks().len());

    // Iterate as long as `block` has exactly one predecessor that we have not yet visited.
    while seen.insert(block) {
        trace!("Looking for assignments to `_0` in {:?}", block);

        let local = body[block].statements.iter().rev().find_map(as_local_assigned_to_return_place);
        if local.is_some() {
            return local;
        }

        match body.predecessors()[block].as_slice() {
            &[pred] => block = pred,
            _ => return None,
        }
    }

    None
}

// If this statement is an assignment of an unprojected local to the return place,
// return that local.
fn as_local_assigned_to_return_place(stmt: &mir::Statement<'_>) -> Option<Local> {
    if let mir::StatementKind::Assign(box (lhs, rhs)) = &stmt.kind {
        if lhs.as_local() == Some(mir::RETURN_PLACE) {
            if let mir::Rvalue::Use(mir::Operand::Copy(rhs) | mir::Operand::Move(rhs)) = rhs {
                return rhs.as_local();
            }
        }
    }

    None
}

struct RenameToReturnPlace<'tcx> {
    to_rename: Local,
    tcx: TyCtxt<'tcx>,
}

/// Replaces all uses of `self.to_rename` with `_0`.
impl MutVisitor<'tcx> for RenameToReturnPlace<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_statement(&mut self, stmt: &mut mir::Statement<'tcx>, loc: Location) {
        // Remove assignments of the local being replaced to the return place, since it is now the
        // return place:
        //     _0 = _1
        if as_local_assigned_to_return_place(stmt) == Some(self.to_rename) {
            stmt.kind = mir::StatementKind::Nop;
            return;
        }

        // Remove storage annotations for the local being replaced:
        //     StorageLive(_1)
        if let mir::StatementKind::StorageLive(local) | mir::StatementKind::StorageDead(local) =
            stmt.kind
        {
            if local == self.to_rename {
                stmt.kind = mir::StatementKind::Nop;
                return;
            }
        }

        self.super_statement(stmt, loc)
    }

    fn visit_terminator(&mut self, terminator: &mut mir::Terminator<'tcx>, loc: Location) {
        // Ignore the implicit "use" of the return place in a `Return` statement.
        if let mir::TerminatorKind::Return = terminator.kind {
            return;
        }

        self.super_terminator(terminator, loc);
    }

    fn visit_local(&mut self, l: &mut Local, ctxt: PlaceContext, _: Location) {
        if *l == mir::RETURN_PLACE {
            assert_eq!(ctxt, PlaceContext::NonUse(NonUseContext::VarDebugInfo));
        } else if *l == self.to_rename {
            *l = mir::RETURN_PLACE;
        }
    }
}

struct IsReturnPlaceRead(bool);

impl IsReturnPlaceRead {
    fn run(body: &mir::Body<'_>) -> bool {
        let mut vis = IsReturnPlaceRead(false);
        vis.visit_body(body);
        vis.0
    }
}

impl Visitor<'tcx> for IsReturnPlaceRead {
    fn visit_local(&mut self, &l: &Local, ctxt: PlaceContext, _: Location) {
        if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() {
            self.0 = true;
        }
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, loc: Location) {
        // Ignore the implicit "use" of the return place in a `Return` statement.
        if let mir::TerminatorKind::Return = terminator.kind {
            return;
        }

        self.super_terminator(terminator, loc);
    }
}
<commit_msg>Rollup merge of #78556 - camelid:mir-opt-nrvo-docs, r=jyn514<commit_after>//! See the docs for [`RenameReturnPlace`].

use rustc_hir::Mutability;
use rustc_index::bit_set::HybridBitSet;
use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::{self, BasicBlock, Local, Location};
use rustc_middle::ty::TyCtxt;

use crate::transform::MirPass;

/// This pass looks for MIR that always copies the same local into the return place and eliminates
/// the copy by renaming all uses of that local to `_0`.
///
/// This allows LLVM to perform an optimization similar to the named return value optimization
/// (NRVO) that is guaranteed in C++. This avoids a stack allocation and `memcpy` for the
/// relatively common pattern of allocating a buffer on the stack, mutating it, and returning it by
/// value like so:
///
/// ```rust
/// fn foo(init: fn(&mut [u8; 1024])) -> [u8; 1024] {
///     let mut buf = [0; 1024];
///     init(&mut buf);
///     buf
/// }
/// ```
///
/// For now, this pass is very simple and only capable of eliminating a single copy. A more general
/// version of copy propagation, such as the one based on non-overlapping live ranges in [#47954] and
/// [#71003], could yield even more benefits.
///
/// [#47954]: https://github.com/rust-lang/rust/pull/47954
/// [#71003]: https://github.com/rust-lang/rust/pull/71003
pub struct RenameReturnPlace;

impl<'tcx> MirPass<'tcx> for RenameReturnPlace {
    fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
        if tcx.sess.opts.debugging_opts.mir_opt_level == 0 {
            return;
        }

        let returned_local = match local_eligible_for_nrvo(body) {
            Some(l) => l,
            None => {
                debug!("`{:?}` was ineligible for NRVO", body.source.def_id());
                return;
            }
        };

        debug!(
            "`{:?}` was eligible for NRVO, making {:?} the return place",
            body.source.def_id(),
            returned_local
        );

        RenameToReturnPlace { tcx, to_rename: returned_local }.visit_body(body);

        // Clean up the `NOP`s we inserted for statements made useless by our renaming.
        for block_data in body.basic_blocks_mut() {
            block_data.statements.retain(|stmt| stmt.kind != mir::StatementKind::Nop);
        }

        // Overwrite the debuginfo of `_0` with that of the renamed local.
        let (renamed_decl, ret_decl) =
            body.local_decls.pick2_mut(returned_local, mir::RETURN_PLACE);

        // Sometimes, the return place is assigned a local of a different but coercable type, for
        // example `&mut T` instead of `&T`. Overwriting the `LocalInfo` for the return place means
        // its type may no longer match the return type of its function. This doesn't cause a
        // problem in codegen because these two types are layout-compatible, but may be unexpected.
        debug!("_0: {:?} = {:?}: {:?}", ret_decl.ty, returned_local, renamed_decl.ty);
        ret_decl.clone_from(renamed_decl);

        // The return place is always mutable.
        ret_decl.mutability = Mutability::Mut;
    }
}

/// MIR that is eligible for the NRVO must fulfill two conditions:
///   1. The return place must not be read prior to the `Return` terminator.
///   2. A simple assignment of a whole local to the return place (e.g., `_0 = _1`) must be the
///      only definition of the return place reaching the `Return` terminator.
///
/// If the MIR fulfills both these conditions, this function returns the `Local` that is assigned
/// to the return place along all possible paths through the control-flow graph.
fn local_eligible_for_nrvo(body: &mut mir::Body<'_>) -> Option<Local> {
    if IsReturnPlaceRead::run(body) {
        return None;
    }

    let mut copied_to_return_place = None;
    for block in body.basic_blocks().indices() {
        // Look for blocks with a `Return` terminator.
        if !matches!(body[block].terminator().kind, mir::TerminatorKind::Return) {
            continue;
        }

        // Look for an assignment of a single local to the return place prior to the `Return`.
        let returned_local = find_local_assigned_to_return_place(block, body)?;
        match body.local_kind(returned_local) {
            // FIXME: Can we do this for arguments as well?
            mir::LocalKind::Arg => return None,

            mir::LocalKind::ReturnPointer => bug!("Return place was assigned to itself?"),
            mir::LocalKind::Var | mir::LocalKind::Temp => {}
        }

        // If multiple different locals are copied to the return place. We can't pick a
        // single one to rename.
        if copied_to_return_place.map_or(false, |old| old != returned_local) {
            return None;
        }

        copied_to_return_place = Some(returned_local);
    }

    copied_to_return_place
}

fn find_local_assigned_to_return_place(
    start: BasicBlock,
    body: &mut mir::Body<'_>,
) -> Option<Local> {
    let mut block = start;
    let mut seen = HybridBitSet::new_empty(body.basic_blocks().len());

    // Iterate as long as `block` has exactly one predecessor that we have not yet visited.
    while seen.insert(block) {
        trace!("Looking for assignments to `_0` in {:?}", block);

        let local = body[block].statements.iter().rev().find_map(as_local_assigned_to_return_place);
        if local.is_some() {
            return local;
        }

        match body.predecessors()[block].as_slice() {
            &[pred] => block = pred,
            _ => return None,
        }
    }

    None
}

// If this statement is an assignment of an unprojected local to the return place,
// return that local.
fn as_local_assigned_to_return_place(stmt: &mir::Statement<'_>) -> Option<Local> {
    if let mir::StatementKind::Assign(box (lhs, rhs)) = &stmt.kind {
        if lhs.as_local() == Some(mir::RETURN_PLACE) {
            if let mir::Rvalue::Use(mir::Operand::Copy(rhs) | mir::Operand::Move(rhs)) = rhs {
                return rhs.as_local();
            }
        }
    }

    None
}

struct RenameToReturnPlace<'tcx> {
    to_rename: Local,
    tcx: TyCtxt<'tcx>,
}

/// Replaces all uses of `self.to_rename` with `_0`.
impl MutVisitor<'tcx> for RenameToReturnPlace<'tcx> {
    fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    fn visit_statement(&mut self, stmt: &mut mir::Statement<'tcx>, loc: Location) {
        // Remove assignments of the local being replaced to the return place, since it is now the
        // return place:
        //     _0 = _1
        if as_local_assigned_to_return_place(stmt) == Some(self.to_rename) {
            stmt.kind = mir::StatementKind::Nop;
            return;
        }

        // Remove storage annotations for the local being replaced:
        //     StorageLive(_1)
        if let mir::StatementKind::StorageLive(local) | mir::StatementKind::StorageDead(local) =
            stmt.kind
        {
            if local == self.to_rename {
                stmt.kind = mir::StatementKind::Nop;
                return;
            }
        }

        self.super_statement(stmt, loc)
    }

    fn visit_terminator(&mut self, terminator: &mut mir::Terminator<'tcx>, loc: Location) {
        // Ignore the implicit "use" of the return place in a `Return` statement.
        if let mir::TerminatorKind::Return = terminator.kind {
            return;
        }

        self.super_terminator(terminator, loc);
    }

    fn visit_local(&mut self, l: &mut Local, ctxt: PlaceContext, _: Location) {
        if *l == mir::RETURN_PLACE {
            assert_eq!(ctxt, PlaceContext::NonUse(NonUseContext::VarDebugInfo));
        } else if *l == self.to_rename {
            *l = mir::RETURN_PLACE;
        }
    }
}

struct IsReturnPlaceRead(bool);

impl IsReturnPlaceRead {
    fn run(body: &mir::Body<'_>) -> bool {
        let mut vis = IsReturnPlaceRead(false);
        vis.visit_body(body);
        vis.0
    }
}

impl Visitor<'tcx> for IsReturnPlaceRead {
    fn visit_local(&mut self, &l: &Local, ctxt: PlaceContext, _: Location) {
        if l == mir::RETURN_PLACE && ctxt.is_use() && !ctxt.is_place_assignment() {
            self.0 = true;
        }
    }

    fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>, loc: Location) {
        // Ignore the implicit "use" of the return place in a `Return` statement.
        if let mir::TerminatorKind::Return = terminator.kind {
            return;
        }

        self.super_terminator(terminator, loc);
    }
}
<|endoftext|>


<commit_before>use crate::{
    characters::{Character, Characters},
    linebreak::{LineBreak, LineBreaker},
    lines::Lines,
    SectionGlyph, SectionText,
};
use ab_glyph::*;
use std::iter::{FusedIterator, Iterator};

#[derive(Clone, Debug, Default)]
pub(crate) struct VMetrics {
    pub ascent: f32,
    pub descent: f32,
    pub line_gap: f32,
}

impl VMetrics {
    #[inline]
    pub fn height(&self) -> f32 {
        self.ascent - self.descent
    }

    #[inline]
    pub fn max(self, other: Self) -> Self {
        if other.height() > self.height() {
            other
        } else {
            self
        }
    }
}

impl<F: Font> From<PxScaleFont<F>> for VMetrics {
    #[inline]
    fn from(scale_font: PxScaleFont<F>) -> Self {
        Self {
            ascent: scale_font.ascent(),
            descent: scale_font.descent(),
            line_gap: scale_font.line_gap(),
        }
    }
}

/// Single 'word' ie a sequence of `Character`s where the last is a line-break.
///
/// Glyphs are relatively positioned from (0, 0) in a left-top alignment style.
pub(crate) struct Word {
    pub glyphs: Vec<SectionGlyph>,
    /// pixel advance width of word includes ending spaces/invisibles
    pub layout_width: f32,
    /// pixel advance width of word not including any trailing spaces/invisibles
    pub layout_width_no_trail: f32,
    pub max_v_metrics: VMetrics,
    /// indicates the break after the word is a hard one
    pub hard_break: bool,
}

/// `Word` iterator.
pub(crate) struct Words<'a, 'b, L, F, S>
where
    L: LineBreaker,
    F: Font,
    S: Iterator<Item = SectionText<'a>>,
{
    pub(crate) characters: Characters<'a, 'b, L, F, S>,
}

impl<'a, 'b, L, F, S> Words<'a, 'b, L, F, S>
where
    L: LineBreaker,
    F: Font,
    S: Iterator<Item = SectionText<'a>>,
{
    pub(crate) fn lines(self, width_bound: f32) -> Lines<'a, 'b, L, F, S> {
        Lines {
            words: self.peekable(),
            width_bound,
        }
    }
}

impl<'a, L, F, S> Iterator for Words<'a, '_, L, F, S>
where
    L: LineBreaker,
    F: Font,
    S: Iterator<Item = SectionText<'a>>,
{
    type Item = Word;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        let mut glyphs = Vec::new();
        let mut caret = 0.0;
        let mut caret_no_trail = caret;
        let mut last_glyph_id = None;
        let mut max_v_metrics = VMetrics::default();
        let mut hard_break = false;
        let mut progress = false;

        for Character {
            mut glyph,
            scale_font,
            font_id,
            line_break,
            control,
            whitespace,
            section_index,
            byte_index,
        } in &mut self.characters
        {
            progress = true;

            max_v_metrics = max_v_metrics.max(scale_font.into());

            if let Some(id) = last_glyph_id.take() {
                caret += scale_font.kern(id, glyph.id);
            }
            last_glyph_id = Some(glyph.id);

            if !control {
                let advance_width = scale_font.h_advance(glyph.id);

                glyph.position = point(caret, 0.0);
                glyphs.push(SectionGlyph {
                    glyph,
                    font_id,
                    section_index,
                    byte_index,
                });
                caret += advance_width;

                if !whitespace {
                    // not an invisible trail
                    caret_no_trail = caret;
                }
            }

            if line_break.is_some() {
                if let Some(LineBreak::Hard(..)) = line_break {
                    hard_break = true
                }
                break;
            }
        }

        if progress {
            return Some(Word {
                glyphs,
                layout_width: caret,
                layout_width_no_trail: caret_no_trail,
                hard_break,
                max_v_metrics,
            });
        }

        None
    }
}

impl<'a, L, F, S> FusedIterator for Words<'a, '_, L, F, S>
where
    L: LineBreaker,
    F: Font,
    S: Iterator<Item = SectionText<'a>>,
{
}
<commit_msg>cargo fmt<commit_after>use crate::{
    characters::{Character, Characters},
    linebreak::{LineBreak, LineBreaker},
    lines::Lines,
    SectionGlyph, SectionText,
};
use ab_glyph::*;
use std::iter::{FusedIterator, Iterator};

#[derive(Clone, Debug, Default)]
pub(crate) struct VMetrics {
    pub ascent: f32,
    pub descent: f32,
    pub line_gap: f32,
}

impl VMetrics {
    #[inline]
    pub fn height(&self) -> f32 {
        self.ascent - self.descent
    }

    #[inline]
    pub fn max(self, other: Self) -> Self {
        if other.height() > self.height() {
            other
        } else {
            self
        }
    }
}

impl<F: Font> From<PxScaleFont<F>> for VMetrics {
    #[inline]
    fn from(scale_font: PxScaleFont<F>) -> Self {
        Self {
            ascent: scale_font.ascent(),
            descent: scale_font.descent(),
            line_gap: scale_font.line_gap(),
        }
    }
}

/// Single 'word' ie a sequence of `Character`s where the last is a line-break.
///
/// Glyphs are relatively positioned from (0, 0) in a left-top alignment style.
pub(crate) struct Word {
    pub glyphs: Vec<SectionGlyph>,
    /// pixel advance width of word includes ending spaces/invisibles
    pub layout_width: f32,
    /// pixel advance width of word not including any trailing spaces/invisibles
    pub layout_width_no_trail: f32,
    pub max_v_metrics: VMetrics,
    /// indicates the break after the word is a hard one
    pub hard_break: bool,
}

/// `Word` iterator.
pub(crate) struct Words<'a, 'b, L, F, S>
where
    L: LineBreaker,
    F: Font,
    S: Iterator<Item = SectionText<'a>>,
{
    pub(crate) characters: Characters<'a, 'b, L, F, S>,
}

impl<'a, 'b, L, F, S> Words<'a, 'b, L, F, S>
where
    L: LineBreaker,
    F: Font,
    S: Iterator<Item = SectionText<'a>>,
{
    pub(crate) fn lines(self, width_bound: f32) -> Lines<'a, 'b, L, F, S> {
        Lines {
            words: self.peekable(),
            width_bound,
        }
    }
}

impl<'a, L, F, S> Iterator for Words<'a, '_, L, F, S>
where
    L: LineBreaker,
    F: Font,
    S: Iterator<Item = SectionText<'a>>,
{
    type Item = Word;

    #[inline]
    fn next(&mut self) -> Option<Self::Item> {
        let mut glyphs = Vec::new();
        let mut caret = 0.0;
        let mut caret_no_trail = caret;
        let mut last_glyph_id = None;
        let mut max_v_metrics = VMetrics::default();
        let mut hard_break = false;
        let mut progress = false;

        for Character {
            mut glyph,
            scale_font,
            font_id,
            line_break,
            control,
            whitespace,
            section_index,
            byte_index,
        } in &mut self.characters
        {
            progress = true;

            max_v_metrics = max_v_metrics.max(scale_font.into());

            if let Some(id) = last_glyph_id.take() {
                caret += scale_font.kern(id, glyph.id);
            }
            last_glyph_id = Some(glyph.id);

            if !control {
                let advance_width = scale_font.h_advance(glyph.id);

                glyph.position = point(caret, 0.0);
                glyphs.push(SectionGlyph {
                    glyph,
                    font_id,
                    section_index,
                    byte_index,
                });
                caret += advance_width;

                if !whitespace {
                    // not an invisible trail
                    caret_no_trail = caret;
                }
            }

            if line_break.is_some() {
                if let Some(LineBreak::Hard(..)) = line_break {
                    hard_break = true
                }
                break;
            }
        }

        if progress {
            return Some(Word {
                glyphs,
                layout_width: caret,
                layout_width_no_trail: caret_no_trail,
                hard_break,
                max_v_metrics,
            });
        }

        None
    }
}

impl<'a, L, F, S> FusedIterator for Words<'a, '_, L, F, S>
where
    L: LineBreaker,
    F: Font,
    S: Iterator<Item = SectionText<'a>>,
{
}
<|endoftext|>


<commit_before>
use std::sync::Mutex;
use rand;
use rand::Rng;
use std::ptr;

static GRID_WDH : i32 = 256;

lazy_static! {
    static ref GRID: Mutex<Vec<u8>> = {
        let mut v = Vec::new();
        v.resize((GRID_WDH * GRID_WDH) as usize, 0);
        Mutex::new(v)
    };
}

#[no_mangle]
pub extern fn gol_randomize() -> () {
    let mut grid = GRID.lock().unwrap();
    let mut rng = rand::thread_rng();

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx = (x + y * GRID_WDH) as usize;
            grid[idx] = if rng.gen() { 1 } else { 0 };
        }
    }
}

#[no_mangle]
pub extern fn gol_step() -> () {
    let mut grid = GRID.lock().unwrap();

    let grid_size = (GRID_WDH * GRID_WDH) as usize;
    let mut new_grid = Vec::with_capacity(grid_size);
    unsafe { new_grid.set_len(grid_size); }

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let torus_idx = |x: i32, y: i32| -> u8 {
                let wrapx = if x < 0 { GRID_WDH - 1 } else { if x > GRID_WDH - 1 { 0 } else { x } };
                let wrapy = if y < 0 { GRID_WDH - 1 } else { if y > GRID_WDH - 1 { 0 } else { y } };
                let idx = wrapx + wrapy * GRID_WDH;
                grid[idx as usize]
            };

            let idx = (x + y * GRID_WDH) as usize;
            let alive = grid[idx];
            let alive_nb = torus_idx(x + 1, y    ) +
                           torus_idx(x    , y + 1) +
                           torus_idx(x - 1, y    ) +
                           torus_idx(x    , y - 1) +
                           torus_idx(x + 1, y + 1) +
                           torus_idx(x - 1, y - 1) +
                           torus_idx(x + 1, y - 1) +
                           torus_idx(x - 1, y + 1);

            new_grid[idx] = if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
        }
    }

    *grid = new_grid;
}

#[no_mangle]
pub extern fn gol_draw(w: i32, h: i32, fb: *mut u32) -> () {
    unsafe { ptr::write_bytes(fb, 64, (w * h) as usize); }

    let grid = GRID.lock().unwrap();

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx_grid = x + y * GRID_WDH;
            let idx_fb = x + y * w;
            unsafe {
                *fb.offset(idx_fb as isize) =
                    if grid[idx_grid as usize] == 1 { 0x00FFFFFF } else { 0 };
            }
        }
    }
}

<commit_msg>Center and bounds check GoL output, add some comments<commit_after>
use std::sync::Mutex;
use rand;
use rand::Rng;
use std::ptr;

static GRID_WDH : i32 = 256;

lazy_static! {
    static ref GRID: Mutex<Vec<u8>> = {
        let mut v = Vec::new();
        v.resize((GRID_WDH * GRID_WDH) as usize, 0);
        Mutex::new(v)
    };
}

#[no_mangle]
pub extern fn gol_randomize() -> () {
    let mut grid = GRID.lock().unwrap();
    let mut rng = rand::thread_rng();

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx = (x + y * GRID_WDH) as usize;
            grid[idx] = if rng.gen() { 1 } else { 0 };
        }
    }
}

#[no_mangle]
pub extern fn gol_step() -> () {

    // Allocate new grid without wasting time setting it to any value
    let grid_size = (GRID_WDH * GRID_WDH) as usize;
    let mut new_grid = Vec::with_capacity(grid_size);
    unsafe { new_grid.set_len(grid_size); }

    let mut grid = GRID.lock().unwrap();

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let torus_idx = |x: i32, y: i32| -> u8 {
                let wrapx = if x < 0 { GRID_WDH - 1 } else { if x > GRID_WDH - 1 { 0 } else { x } };
                let wrapy = if y < 0 { GRID_WDH - 1 } else { if y > GRID_WDH - 1 { 0 } else { y } };
                let idx = wrapx + wrapy * GRID_WDH;
                grid[idx as usize]
            };

            let idx = (x + y * GRID_WDH) as usize;
            let alive = grid[idx];
            let alive_nb = torus_idx(x + 1, y    ) +
                           torus_idx(x    , y + 1) +
                           torus_idx(x - 1, y    ) +
                           torus_idx(x    , y - 1) +
                           torus_idx(x + 1, y + 1) +
                           torus_idx(x - 1, y - 1) +
                           torus_idx(x + 1, y - 1) +
                           torus_idx(x - 1, y + 1);

            new_grid[idx] = if alive_nb == 3 || (alive == 1 && alive_nb == 2) { 1 } else { 0 };
        }
    }

    * grid = new_grid;
}

#[no_mangle]
pub extern fn gol_draw(w: i32, h: i32, fb: *mut u32) -> () {

    // Clear background
    unsafe { ptr::write_bytes(fb, 64, (w * h) as usize); }

    let grid = GRID.lock().unwrap();

    // Center
    let xoffs = w / 2 - GRID_WDH / 2;
    let yoffs = h / 2 - GRID_WDH / 2;

    for y in 0..GRID_WDH {
        for x in 0..GRID_WDH {
            let idx_fb = (xoffs + x) + (yoffs + y) * w;

            // Out of bounds check for the FB
            if idx_fb < 0 || idx_fb > w * h - 1 { continue; }

            let idx_grid = x + y * GRID_WDH;

            unsafe {
                * fb.offset(idx_fb as isize) =
                    if grid[idx_grid as usize] == 1 { 0x00FFFFFF } else { 0 };
            }
        }
    }
}

<|endoftext|>


<commit_before>use rustfft::num_complex::Complex;
use rustfft::Length;

use DCTnum;
use twiddles;
use dct3::DCT3;

/// DCT Type 3 implemention that recursively divides the problem in half. The problem size must be a power of two.
///
/// ~~~
/// // Computes a DCT Type 3 of size 1024
/// use rustdct::dct3::{DCT3, DCT3SplitRadix};
///
/// let mut input:  Vec<f32> = vec![0f32; 1024];
/// let mut output: Vec<f32> = vec![0f32; 1024];
///
/// let mut dct = DCT3SplitRadix::new(1024);
/// dct.process(&mut input, &mut output);
/// ~~~
pub struct DCT3SplitRadix<T> {
    twiddles: Box<[Complex<T>]>,
}

impl<T: DCTnum> DCT3SplitRadix<T> {
    /// Creates a new DCT3 context that will process signals of length `inner_fft.len()`.
    pub fn new(len: usize) -> Self {
        assert!(
            len.is_power_of_two() && len > 2,
            "The DCT3SplitRadix algorithm requires a power-of-two input size greater than two. Got {}", len
        );

        let twiddles: Vec<Complex<T>> = (0..(len/2))
            .map(|i| twiddles::single_twiddle(i, len * 4, true))
            .collect();

        Self {
            twiddles: twiddles.into_boxed_slice(),
        }
    }

    fn process_recursive(&self, input: &mut [T], output: &mut [T], twiddle_stride: usize) {
        match input.len() {
            1 => output[0] = input[0] * T::from_f32(0.5f32).unwrap(),
            2 => {
                let half = T::from_f32(0.5f32).unwrap();
                output[0] = input[0] * half + input[1] * T::FRAC_1_SQRT_2();
                output[1] = input[0] * half - input[1] * T::FRAC_1_SQRT_2();
            },
            _ => self.process_step(input, output, twiddle_stride),
        }
    }

    fn process_step(&self, input: &mut [T], output: &mut [T], twiddle_stride: usize) {
        let len = input.len();
        let half_len = len / 2;
        let quarter_len = len / 4;

        {
            // divide the output into 3 sub-lists to use for our inner DCTs, one of size N/2 and two of size N/4
            let (mut recursive_input_evens, mut recursive_input_odds) = output.split_at_mut(half_len);
            let (mut recursive_input_n1, mut recursive_input_n3) = recursive_input_odds.split_at_mut(quarter_len);

            // do the same pre-loop setup as DCT4ViaDCT3, and since we're skipping the first iteration of the loop we
            // to also set up the corresponding evens cells
            recursive_input_evens[0] = input[0];
            recursive_input_evens[1] = input[2];
            recursive_input_n1[0] = input[1] * T::from_usize(2).unwrap();
            recursive_input_n3[0] = input[len - 1] * T::from_usize(2).unwrap();

            // populate the recursive input arrays
            for i in 1..quarter_len {
                let k = 4 * i;

                // the evens are the easy ones - just copy straight over
                unsafe { *recursive_input_evens.get_unchecked_mut(i * 2) =     *input.get_unchecked(k) };
                unsafe { *recursive_input_evens.get_unchecked_mut(i * 2 + 1) = *input.get_unchecked(k + 2) };

                // for the odd ones we're going to do the same addition/subtraction we do in the setup for DCT4ViaDCT3
                unsafe { *recursive_input_n1.get_unchecked_mut(i) =               *input.get_unchecked(k - 1) + *input.get_unchecked(k + 1) };
                unsafe { *recursive_input_n3.get_unchecked_mut(quarter_len - i) = *input.get_unchecked(k - 1) - *input.get_unchecked(k + 1) };
            }

            //now that we're done with the input, divide it up the same way we did the output
            let (mut recursive_output_evens, mut recursive_output_odds) = input.split_at_mut(half_len);
            let (mut recursive_output_n1, mut recursive_output_n3) = recursive_output_odds.split_at_mut(quarter_len);

            //perform our recursive DCTs
            self.process_recursive(recursive_input_evens, recursive_output_evens, twiddle_stride * 2);
            self.process_recursive(recursive_input_n1, recursive_output_n1, twiddle_stride * 4);
            self.process_recursive(recursive_input_n3, recursive_output_n3, twiddle_stride * 4);
        }

        //we want the input array to stay split, but to playcate the borrow checker it's easier to just re-split it
        let (recursive_output_evens, recursive_output_odds) = input.split_at(half_len);
        let (recursive_output_n1, recursive_output_n3) = recursive_output_odds.split_at(quarter_len);

        //merge the results. we're going to combine 2 separate things:
        // - merging the two smaller DCT3 outputs into a DCT4 output
        // - marging the DCT4 outputand the larger DCT3 output into the final output
        for i in 0..quarter_len {
            let twiddle = unsafe { *self.twiddles.get_unchecked((i * 2 + 1) * twiddle_stride) };
            let cosine_value = recursive_output_n1[i];

            // flip the sign of every other sine value to finish the job of using a DCT3 to compute a DST3
            let sine_value = if i % 2 == 0 {
                recursive_output_n3[i]
            } else {
                -recursive_output_n3[i]
            };

            let lower_dct4 = cosine_value * twiddle.re + sine_value * twiddle.im;
            let upper_dct4 = cosine_value * twiddle.im - sine_value * twiddle.re;

            let lower_dct3 = unsafe { *recursive_output_evens.get_unchecked(i) };
            let upper_dct3 = unsafe { *recursive_output_evens.get_unchecked(half_len - i - 1) };

            *unsafe { output.get_unchecked_mut(i) } =                lower_dct3 + lower_dct4;
            *unsafe { output.get_unchecked_mut(len - i - 1) } =      lower_dct3 - lower_dct4;

            *unsafe { output.get_unchecked_mut(half_len - i - 1) } = upper_dct3 + upper_dct4;
            *unsafe { output.get_unchecked_mut(half_len + i) } =     upper_dct3 - upper_dct4;
        }
    }
}

impl<T: DCTnum> DCT3<T> for DCT3SplitRadix<T> {
    fn process(&mut self, input: &mut [T], output: &mut [T]) {
        assert!(input.len() == self.len());

        self.process_step(input, output, 1);
    }
}
impl<T> Length for DCT3SplitRadix<T> {
    fn len(&self) -> usize {
        self.twiddles.len() * 2
    }
}

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

    use test_utils::{compare_float_vectors, random_signal};

    /// Verify that our fast implementation of the DCT3 gives the same output as the slow version, for many different inputs
    #[test]
    fn test_dct3_splitradix() {
        for i in 2..6 {
            let size = 1 << i;
            let mut expected_input = random_signal(size);
            let mut actual_input = expected_input.clone();

            let mut expected_output = vec![0f32; size];
            let mut actual_output = vec![0f32; size];

            let mut naive_dct = DCT3Naive::new(size);
            naive_dct.process(&mut expected_input, &mut expected_output);

            let mut dct = DCT3SplitRadix::new(size);
            dct.process(&mut actual_input, &mut actual_output);

            assert!(
                compare_float_vectors(&actual_output, &expected_output),
                "len = {}",
                size
            );
        }
    }
}
<commit_msg>Readability improvements<commit_after>use rustfft::num_complex::Complex;
use rustfft::Length;

use DCTnum;
use twiddles;
use dct3::DCT3;

/// DCT Type 3 implemention that recursively divides the problem in half. The problem size must be a power of two.
///
/// ~~~
/// // Computes a DCT Type 3 of size 1024
/// use rustdct::dct3::{DCT3, DCT3SplitRadix};
///
/// let mut input:  Vec<f32> = vec![0f32; 1024];
/// let mut output: Vec<f32> = vec![0f32; 1024];
///
/// let mut dct = DCT3SplitRadix::new(1024);
/// dct.process(&mut input, &mut output);
/// ~~~
pub struct DCT3SplitRadix<T> {
    twiddles: Box<[Complex<T>]>,
}

impl<T: DCTnum> DCT3SplitRadix<T> {
    /// Creates a new DCT3 context that will process signals of length `len`.
    pub fn new(len: usize) -> Self {
        assert!(
            len.is_power_of_two() && len > 2,
            "The DCT3SplitRadix algorithm requires a power-of-two input size greater than two. Got {}", len
        );

        let twiddles: Vec<Complex<T>> = (0..(len/2))
            .map(|i| twiddles::single_twiddle(i, len * 4, true))
            .collect();

        Self {
            twiddles: twiddles.into_boxed_slice(),
        }
    }

    fn process_recursive(&self, input: &mut [T], output: &mut [T], twiddle_stride: usize) {
        match input.len() {
            1 => output[0] = input[0] * T::from_f32(0.5f32).unwrap(),
            2 => {
                let half = T::from_f32(0.5f32).unwrap();
                output[0] = input[0] * half + input[1] * T::FRAC_1_SQRT_2();
                output[1] = input[0] * half - input[1] * T::FRAC_1_SQRT_2();
            },
            _ => self.process_step(input, output, twiddle_stride),
        }
    }

    fn process_step(&self, input: &mut [T], output: &mut [T], twiddle_stride: usize) {
        let len = input.len();
        let half_len = len / 2;
        let quarter_len = len / 4;

        {
            // divide the output into 3 sub-lists to use for our inner DCTs, one of size N/2 and two of size N/4
            let (mut recursive_input_evens, mut recursive_input_odds) = output.split_at_mut(half_len);
            let (mut recursive_input_n1, mut recursive_input_n3) = recursive_input_odds.split_at_mut(quarter_len);

            // do the same pre-loop setup as DCT4ViaDCT3, and since we're skipping the first iteration of the loop we
            // to also set up the corresponding evens cells
            recursive_input_evens[0] = input[0];
            recursive_input_evens[1] = input[2];
            recursive_input_n1[0] = input[1] * T::from_usize(2).unwrap();
            recursive_input_n3[0] = input[len - 1] * T::from_usize(2).unwrap();

            // populate the recursive input arrays
            for i in 1..quarter_len {
                let k = 4 * i;

                unsafe {
                    // the evens are the easy ones - just copy straight over
                    *recursive_input_evens.get_unchecked_mut(i * 2) =     *input.get_unchecked(k);
                    *recursive_input_evens.get_unchecked_mut(i * 2 + 1) = *input.get_unchecked(k + 2);

                    // for the odd ones we're going to do the same addition/subtraction we do in the setup for DCT4ViaDCT3
                    *recursive_input_n1.get_unchecked_mut(i) =               *input.get_unchecked(k - 1) + *input.get_unchecked(k + 1);
                    *recursive_input_n3.get_unchecked_mut(quarter_len - i) = *input.get_unchecked(k - 1) - *input.get_unchecked(k + 1);
                }
            }

            //now that we're done with the input, divide it up the same way we did the output
            let (mut recursive_output_evens, mut recursive_output_odds) = input.split_at_mut(half_len);
            let (mut recursive_output_n1, mut recursive_output_n3) = recursive_output_odds.split_at_mut(quarter_len);

            //perform our recursive DCTs
            self.process_recursive(recursive_input_evens, recursive_output_evens, twiddle_stride * 2);
            self.process_recursive(recursive_input_n1, recursive_output_n1, twiddle_stride * 4);
            self.process_recursive(recursive_input_n3, recursive_output_n3, twiddle_stride * 4);
        }

        //we want the input array to stay split, but to playcate the borrow checker it's easier to just re-split it
        let (recursive_output_evens, recursive_output_odds) = input.split_at(half_len);
        let (recursive_output_n1, recursive_output_n3) = recursive_output_odds.split_at(quarter_len);

        //merge the results. we're going to combine 2 separate things:
        // - merging the two smaller DCT3 outputs into a DCT4 output
        // - marging the DCT4 outputand the larger DCT3 output into the final output
        for i in 0..quarter_len {
            let twiddle = unsafe { *self.twiddles.get_unchecked((i * 2 + 1) * twiddle_stride) };
            let cosine_value = recursive_output_n1[i];

            // flip the sign of every other sine value to finish the job of using a DCT3 to compute a DST3
            let sine_value = if i % 2 == 0 {
                recursive_output_n3[i]
            } else {
                -recursive_output_n3[i]
            };

            let lower_dct4 = cosine_value * twiddle.re + sine_value * twiddle.im;
            let upper_dct4 = cosine_value * twiddle.im - sine_value * twiddle.re;

            unsafe {
                let lower_dct3 = *recursive_output_evens.get_unchecked(i);
                let upper_dct3 = *recursive_output_evens.get_unchecked(half_len - i - 1);

                *output.get_unchecked_mut(i) =                lower_dct3 + lower_dct4;
                *output.get_unchecked_mut(len - i - 1) =      lower_dct3 - lower_dct4;

                *output.get_unchecked_mut(half_len - i - 1) = upper_dct3 + upper_dct4;
                *output.get_unchecked_mut(half_len + i) =     upper_dct3 - upper_dct4;
            }
        }
    }
}

impl<T: DCTnum> DCT3<T> for DCT3SplitRadix<T> {
    fn process(&mut self, input: &mut [T], output: &mut [T]) {
        assert!(input.len() == self.len());

        self.process_step(input, output, 1);
    }
}
impl<T> Length for DCT3SplitRadix<T> {
    fn len(&self) -> usize {
        self.twiddles.len() * 2
    }
}

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

    use test_utils::{compare_float_vectors, random_signal};

    /// Verify that our fast implementation of the DCT3 gives the same output as the slow version, for many different inputs
    #[test]
    fn test_dct3_splitradix() {
        for i in 2..6 {
            let size = 1 << i;
            let mut expected_input = random_signal(size);
            let mut actual_input = expected_input.clone();

            let mut expected_output = vec![0f32; size];
            let mut actual_output = vec![0f32; size];

            let mut naive_dct = DCT3Naive::new(size);
            naive_dct.process(&mut expected_input, &mut expected_output);

            let mut dct = DCT3SplitRadix::new(size);
            dct.process(&mut actual_input, &mut actual_output);

            assert!(
                compare_float_vectors(&actual_output, &expected_output),
                "len = {}",
                size
            );
        }
    }
}
<|endoftext|>


<commit_before><commit_msg>Change texturewood's wood grain axial orientation<commit_after><|endoftext|>