<commit_before>use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use generic_array::{ArrayLength, GenericArray};
use std::io::{Result, Error, ErrorKind, Read, Write};
use std::mem::size_of;
use std::default::Default;

/// A message that can be encoded and decoded according to the LCM protocol.
pub trait Message {
    /// Encodes a message into a buffer, with the message hash at the beginning.
    fn encode_with_hash(&self) -> Result<Vec<u8>> where Self: Sized {
        let hash = Self::hash();
        let size = hash.size() + self.size();
        let mut buffer = Vec::with_capacity(size);
        hash.encode(&mut buffer)?;
        self.encode(&mut buffer)?;
        Ok(buffer)
    }

    /// Decodes a message from a buffer,
    /// and also checks that the hash at the beginning is correct.
    fn decode_with_hash(mut buffer: &mut Read) -> Result<Self>
        where Self: Sized
    {
        let hash: u64 = Message::decode(&mut buffer)?;
        if hash != Self::hash() {
            return Err(Error::new(ErrorKind::Other, "Invalid hash"));
        }
        Message::decode(buffer)
    }

    /// Returns the message hash for this type.
    /// Returns `0` for all primitive types.
    /// Generated `Lcm` types should implement this function.
    fn hash() -> u64 where Self: Sized {
        0
    }

    /// Encodes a message into a buffer.
    /// `Lcm` uses a `Vec<u8>` with its capacity set to the value returned by [`size()`].
    fn encode(&self, buffer: &mut Write) -> Result<()>;

    /// Decodes a message from a buffer.
    fn decode(buffer: &mut Read) -> Result<Self> where Self: Sized;

    /// Returns the number of bytes this message is expected to take when encoded.
    fn size(&self) -> usize;
}

impl Message for bool {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let value: i8 = match *self {
            true => 1,
            false => 0,
        };
        value.encode(buffer)
    }

    fn decode(&mut self, buffer: &mut Read) -> Result<()> {
        let value = buffer.read_i8()?;
        *self = match value {
            0 => false,
            1 => true,
            _ => {
                return Err(Error::new(ErrorKind::InvalidData,
                                      "Booleans should be encoded as 0 or 1"))
            }
        };
        Ok(())
    }

    fn size(&self) -> usize {
        size_of::<i8>()
    }
}

impl Message for u8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u8(*self)
    }

    fn decode(&mut self, buffer: &mut Read) -> Result<()> {
        Ok(*self = buffer.read_u8()?)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i8(*self)
    }

    fn decode(&mut self, buffer: &mut Read) -> Result<()> {
        Ok(*self = buffer.read_i8()?)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i16 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self)
    }

    fn decode(&mut self, buffer: &mut Read) -> Result<()> {
        Ok(*self = buffer.read_i16::<BigEndian>()?)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self)
    }

    fn decode(&mut self, buffer: &mut Read) -> Result<()> {
        Ok(*self = buffer.read_i32::<BigEndian>()?)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self)
    }

    fn decode(&mut self, buffer: &mut Read) -> Result<()> {
        Ok(*self = buffer.read_i64::<BigEndian>()?)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f32::<BigEndian>(*self)
    }

    fn decode(&mut self, buffer: &mut Read) -> Result<()> {
        Ok(*self = buffer.read_f32::<BigEndian>()?)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f64::<BigEndian>(*self)
    }

    fn decode(&mut self, buffer: &mut Read) -> Result<()> {
        Ok(*self = buffer.read_f64::<BigEndian>()?)
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for String {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let len: i32 = self.len() as i32 + 1;
        len.encode(buffer)?;
        for &b in self.as_bytes() {
            b.encode(buffer)?;
        }
        (0 as u8).encode(buffer)?;
        Ok(())
    }

    fn decode(&mut self, buffer: &mut Read) -> Result<()> {
        let len = buffer.read_i32::<BigEndian>()? - 1;
        let mut buf = Vec::with_capacity(len as usize);
        buf.decode(buffer)?;
        *self = String::from_utf8(buf).map_err(|e| Error::new(ErrorKind::Other, e))?;
        match buffer.read_u8() {
            Ok(0) => Ok(()),
            Ok(_) => Err(Error::new(ErrorKind::InvalidData, "Expected null terminator")),
            Err(e) => Err(e),
        }
    }

    fn size(&self) -> usize {
        size_of::<i32>() + self.len() + 1
    }
}
<commit_msg>Update trait impls of primitive types.<commit_after>use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
use generic_array::{ArrayLength, GenericArray};
use std::io::{Result, Error, ErrorKind, Read, Write};
use std::mem::size_of;
use std::default::Default;

/// A message that can be encoded and decoded according to the LCM protocol.
pub trait Message {
    /// Encodes a message into a buffer, with the message hash at the beginning.
    fn encode_with_hash(&self) -> Result<Vec<u8>> where Self: Sized {
        let hash = Self::hash();
        let size = hash.size() + self.size();
        let mut buffer = Vec::with_capacity(size);
        hash.encode(&mut buffer)?;
        self.encode(&mut buffer)?;
        Ok(buffer)
    }

    /// Decodes a message from a buffer,
    /// and also checks that the hash at the beginning is correct.
    fn decode_with_hash(mut buffer: &mut Read) -> Result<Self>
        where Self: Sized
    {
        let hash: u64 = Message::decode(&mut buffer)?;
        if hash != Self::hash() {
            return Err(Error::new(ErrorKind::Other, "Invalid hash"));
        }
        Message::decode(buffer)
    }

    /// Returns the message hash for this type.
    /// Returns `0` for all primitive types.
    /// Generated `Lcm` types should implement this function.
    fn hash() -> u64 where Self: Sized {
        0
    }

    /// Encodes a message into a buffer.
    /// `Lcm` uses a `Vec<u8>` with its capacity set to the value returned by [`size()`].
    fn encode(&self, buffer: &mut Write) -> Result<()>;

    /// Decodes a message from a buffer.
    fn decode(buffer: &mut Read) -> Result<Self> where Self: Sized;

    /// Returns the number of bytes this message is expected to take when encoded.
    fn size(&self) -> usize;
}

impl Message for bool {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let value: i8 = match *self {
            true => 1,
            false => 0,
        };
        value.encode(buffer)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        let value = buffer.read_i8()?;
        match value {
            0 => Ok(false),
            1 => Ok(true),
            _ => Err(Error::new(ErrorKind::InvalidData,
                                "Booleans should be encoded as 0 or 1"))
        }
    }

    fn size(&self) -> usize {
        size_of::<i8>()
    }
}

impl Message for u8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u8(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_u8()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i8 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i8(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i8()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i16 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i16::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i16::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i32::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i32::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for u64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_u64::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_u64::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for i64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_i64::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_i64::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f32 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f32::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_f32::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for f64 {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        buffer.write_f64::<BigEndian>(*self)
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        buffer.read_f64::<BigEndian>()
    }

    fn size(&self) -> usize {
        size_of::<Self>()
    }
}

impl Message for String {
    fn encode(&self, buffer: &mut Write) -> Result<()> {
        let len: i32 = self.len() as i32 + 1;
        len.encode(buffer)?;
        for &b in self.as_bytes() {
            b.encode(buffer)?;
        }
        (0 as u8).encode(buffer)?;
        Ok(())
    }

    fn decode(buffer: &mut Read) -> Result<Self> {
        let len = buffer.read_i32::<BigEndian>()? - 1;
        let mut buf = Vec::with_capacity(len as usize);
        for _ in 0..len {
            buf.push(u8::decode(buffer)?)
        }
        let result = String::from_utf8(buf).map_err(|e| Error::new(ErrorKind::Other, e))?;
        match buffer.read_u8() {
            Ok(0) => Ok(result),
            Ok(_) => Err(Error::new(ErrorKind::InvalidData, "Expected null terminator")),
            Err(e) => Err(e),
        }
    }

    fn size(&self) -> usize {
        size_of::<i32>() + self.len() + 1
    }
}
<|endoftext|>


<commit_before>use std::fmt::{Display, Error, Formatter};

#[derive(Debug, PartialEq, Eq)]
pub enum BinOp {
    And,
    Minus,
    Or,
    Plus,
    Slash,
    Star,
}

#[derive(PartialEq, Eq, PartialOrd, Ord)]
pub enum Precedence {
    Const = 110,
    Sign = 100,
    Inc = 90,
    Mult = 60,
    Add = 50,
    And = 40,
    Or = 30,
}

impl BinOp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            BinOp::And => Precedence::And,
            BinOp::Or => Precedence::Or,
            BinOp::Minus | BinOp::Plus => Precedence::Add,
            BinOp::Slash | BinOp::Star => Precedence::Mult,
        }
    }

    pub fn is_commutative(&self) -> bool {
        match *self {
            BinOp::Minus | BinOp::Slash => false,
            _ => true
        }
    }
}

impl Display for BinOp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            BinOp::And => write!(fmt, "&&"),
            BinOp::Minus => write!(fmt, "-"),
            BinOp::Or => write!(fmt, "||"),
            BinOp::Plus => write!(fmt, "+"),
            BinOp::Slash => write!(fmt, "/"),
            BinOp::Star => write!(fmt, "*"),
        }
    }
}

#[derive(Debug)]
pub enum Exp {
    BinExp(Box<Exp>, BinOp, Box<Exp>),
    Bool(bool),
    Float(f64),
    Neg(Box<Exp>),
    Pos(Box<Exp>),
    PostDec(Box<Exp>),
    PostInc(Box<Exp>),
    PreDec(Box<Exp>),
    PreInc(Box<Exp>),
    Undefined,
    Var(String),
}

impl Exp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            Exp::BinExp(_, ref o, _) => o.precedence(),
            Exp::Bool(_) | Exp::Float(_) | Exp::Undefined | Exp::Var(_) => Precedence::Const,
            Exp::Neg(_) | Exp::Pos(_) => Precedence::Sign,
            Exp::PostDec(_) | Exp::PostInc(_) | Exp::PreDec(_) | Exp::PreInc(_) => Precedence::Inc,
        }
    }
}

macro_rules! group {
    ($e:expr, $p:expr) => {
        if $e.precedence() < $p {
            format!("({})", $e)
        } else {
            format!("{}", $e)
        }
    }
}

impl Display for Exp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            Exp::BinExp(ref e1, ref o, ref e2) => {
                let prec = self.precedence();

                // Put grouping parentheses if the left subexpression has a lower-precedence
                // operator, e.g. (1 + 2) * 3
                let left = if prec > e1.precedence() {
                    format!("({})", e1)
                } else {
                    format!("{}", e1)
                };

                let right_prec = e2.precedence();

                // Put grouping parentheses around the right subexpression if it has a
                // lower-precedence operator,  __OR__ if `o` is not commutative and the precedence
                // is the same, e.g. (1 + 2) * 3 __OR__ 1 - (2 + 3)
                let right = if prec > right_prec || (!o.is_commutative() && prec == right_prec) {
                    format!("({})", e2)
                } else {
                    format!("{}", e2)
                };

                write!(fmt, "{} {} {}", left, o, right)
            }
            Exp::Bool(b) => write!(fmt, "{}", b),
            Exp::Float(f) => write!(fmt, "{}", f),
            Exp::Neg(ref e) => write!(fmt, "-{}", group!(e, Precedence::Sign)),
            Exp::Pos(ref e) => write!(fmt, "+{}", group!(e, Precedence::Sign)),
            Exp::PostDec(ref e) => write!(fmt, "{}--", group!(e, Precedence::Inc)),
            Exp::PostInc(ref e) => write!(fmt, "{}++", group!(e, Precedence::Inc)),
            Exp::PreDec(ref e) => write!(fmt, "--{}", group!(e, Precedence::Inc)),
            Exp::PreInc(ref e) => write!(fmt, "++{}", group!(e, Precedence::Inc)),
            Exp::Undefined => write!(fmt, "undefined"),
            Exp::Var(ref v) => write!(fmt, "{}", v),
        }
    }
}

#[derive(Debug)]
pub enum Stmt {
    Assign(String, Exp),
    BareExp(Exp),
    Decl(String, Exp),
    If(Exp, Box<Stmt>, Option<Box<Stmt>>),
    Seq(Box<Stmt>, Box<Stmt>),
    While(Exp, Box<Stmt>),
}

impl Stmt {
    fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! indented_stmt {
            ($stmt:expr) => {
                try!($stmt.fmt_helper(&mut fmt, indent_level + 2))
            }
        }

        let indent : String = (0..indent_level).map(|_| " ").collect();

        match *self {
            Stmt::Assign(ref v, ref exp) => write!(fmt, "{}{} = {};\n", indent, v, exp),
            Stmt::BareExp(ref exp) => write!(fmt, "{}{};\n", indent, exp),
            Stmt::Decl(ref v, ref exp) => write!(fmt, "{}var {} = {};\n", indent, v, exp),
            Stmt::If(ref e, ref s, ref els) => {
                try!(write!(fmt, "{}if ({}) {{\n", indent, e));
                indented_stmt!(s);

                if let &Some(ref stmt) = els {
                    try!(write!(fmt, "{}else {{\n", indent));
                    indented_stmt!(stmt);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                Ok(())
            }
            Stmt::Seq(ref s1, ref s2) => write!(fmt, "{}{}{}{}", indent, s1, indent, s2),
            Stmt::While(ref exp, ref stmt) => {
                try!(write!(fmt, "{}while ({}) {{\n", indent, exp));
                try!(stmt.fmt_helper(&mut fmt, indent_level + 2));
                write!(fmt, "{}}}\n", indent)
            }
        }
    }
}

impl Display for Stmt {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}
<commit_msg>add clone to all the ast types<commit_after>use std::fmt::{Display, Error, Formatter};

#[derive(Clone, Debug, PartialEq, Eq)]
pub enum BinOp {
    And,
    Minus,
    Or,
    Plus,
    Slash,
    Star,
}

#[derive(Clone, PartialEq, Eq, PartialOrd, Ord)]
pub enum Precedence {
    Const = 110,
    Sign = 100,
    Inc = 90,
    Mult = 60,
    Add = 50,
    And = 40,
    Or = 30,
}

impl BinOp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            BinOp::And => Precedence::And,
            BinOp::Or => Precedence::Or,
            BinOp::Minus | BinOp::Plus => Precedence::Add,
            BinOp::Slash | BinOp::Star => Precedence::Mult,
        }
    }

    pub fn is_commutative(&self) -> bool {
        match *self {
            BinOp::Minus | BinOp::Slash => false,
            _ => true
        }
    }
}

impl Display for BinOp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            BinOp::And => write!(fmt, "&&"),
            BinOp::Minus => write!(fmt, "-"),
            BinOp::Or => write!(fmt, "||"),
            BinOp::Plus => write!(fmt, "+"),
            BinOp::Slash => write!(fmt, "/"),
            BinOp::Star => write!(fmt, "*"),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Exp {
    BinExp(Box<Exp>, BinOp, Box<Exp>),
    Bool(bool),
    Float(f64),
    Neg(Box<Exp>),
    Pos(Box<Exp>),
    PostDec(Box<Exp>),
    PostInc(Box<Exp>),
    PreDec(Box<Exp>),
    PreInc(Box<Exp>),
    Undefined,
    Var(String),
}

impl Exp {
    pub fn precedence(&self) -> Precedence {
        match *self {
            Exp::BinExp(_, ref o, _) => o.precedence(),
            Exp::Bool(_) | Exp::Float(_) | Exp::Undefined | Exp::Var(_) => Precedence::Const,
            Exp::Neg(_) | Exp::Pos(_) => Precedence::Sign,
            Exp::PostDec(_) | Exp::PostInc(_) | Exp::PreDec(_) | Exp::PreInc(_) => Precedence::Inc,
        }
    }
}

macro_rules! group {
    ($e:expr, $p:expr) => {
        if $e.precedence() < $p {
            format!("({})", $e)
        } else {
            format!("{}", $e)
        }
    }
}

impl Display for Exp {
    fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
        match *self {
            Exp::BinExp(ref e1, ref o, ref e2) => {
                let prec = self.precedence();

                // Put grouping parentheses if the left subexpression has a lower-precedence
                // operator, e.g. (1 + 2) * 3
                let left = if prec > e1.precedence() {
                    format!("({})", e1)
                } else {
                    format!("{}", e1)
                };

                let right_prec = e2.precedence();

                // Put grouping parentheses around the right subexpression if it has a
                // lower-precedence operator,  __OR__ if `o` is not commutative and the precedence
                // is the same, e.g. (1 + 2) * 3 __OR__ 1 - (2 + 3)
                let right = if prec > right_prec || (!o.is_commutative() && prec == right_prec) {
                    format!("({})", e2)
                } else {
                    format!("{}", e2)
                };

                write!(fmt, "{} {} {}", left, o, right)
            }
            Exp::Bool(b) => write!(fmt, "{}", b),
            Exp::Float(f) => write!(fmt, "{}", f),
            Exp::Neg(ref e) => write!(fmt, "-{}", group!(e, Precedence::Sign)),
            Exp::Pos(ref e) => write!(fmt, "+{}", group!(e, Precedence::Sign)),
            Exp::PostDec(ref e) => write!(fmt, "{}--", group!(e, Precedence::Inc)),
            Exp::PostInc(ref e) => write!(fmt, "{}++", group!(e, Precedence::Inc)),
            Exp::PreDec(ref e) => write!(fmt, "--{}", group!(e, Precedence::Inc)),
            Exp::PreInc(ref e) => write!(fmt, "++{}", group!(e, Precedence::Inc)),
            Exp::Undefined => write!(fmt, "undefined"),
            Exp::Var(ref v) => write!(fmt, "{}", v),
        }
    }
}

#[derive(Clone, Debug)]
pub enum Stmt {
    Assign(String, Exp),
    BareExp(Exp),
    Decl(String, Exp),
    If(Exp, Box<Stmt>, Option<Box<Stmt>>),
    Seq(Box<Stmt>, Box<Stmt>),
    While(Exp, Box<Stmt>),
}

impl Stmt {
    fn fmt_helper(&self, mut fmt: &mut Formatter, indent_level: i32) -> Result<(), Error> {
        macro_rules! indented_stmt {
            ($stmt:expr) => {
                try!($stmt.fmt_helper(&mut fmt, indent_level + 2))
            }
        }

        let indent : String = (0..indent_level).map(|_| " ").collect();

        match *self {
            Stmt::Assign(ref v, ref exp) => write!(fmt, "{}{} = {};\n", indent, v, exp),
            Stmt::BareExp(ref exp) => write!(fmt, "{}{};\n", indent, exp),
            Stmt::Decl(ref v, ref exp) => write!(fmt, "{}var {} = {};\n", indent, v, exp),
            Stmt::If(ref e, ref s, ref els) => {
                try!(write!(fmt, "{}if ({}) {{\n", indent, e));
                indented_stmt!(s);

                if let &Some(ref stmt) = els {
                    try!(write!(fmt, "{}else {{\n", indent));
                    indented_stmt!(stmt);
                    try!(write!(fmt, "{}}}\n", indent));
                }

                Ok(())
            }
            Stmt::Seq(ref s1, ref s2) => write!(fmt, "{}{}{}{}", indent, s1, indent, s2),
            Stmt::While(ref exp, ref stmt) => {
                try!(write!(fmt, "{}while ({}) {{\n", indent, exp));
                try!(stmt.fmt_helper(&mut fmt, indent_level + 2));
                write!(fmt, "{}}}\n", indent)
            }
        }
    }
}

impl Display for Stmt {
    fn fmt(&self, mut fmt: &mut Formatter) -> Result<(), Error> {
        self.fmt_helper(&mut fmt, 0)
    }
}
<|endoftext|>


<commit_before>use std::io;
use std::os::unix::io::RawFd;
use std::rc::Rc;

use cairo_sys;
use cairo::{self, Context, XCBSurface};
use futures::{future, Async, Future, Poll, Stream};
use futures::stream::MergedItem;
use mio::{self, PollOpt, Ready, Token};
use mio::event::Evented;
use mio::unix::EventedFd;
use tokio_core::reactor::{Handle, PollEvented};
use xcb;
use xcb_util::ewmh;

use text::{Color, Text};
use widgets::{WidgetList, Widget};

fn get_root_visual_type(conn: &xcb::Connection, screen: &xcb::Screen) -> xcb::Visualtype {
    for root in conn.get_setup().roots() {
        for allowed_depth in root.allowed_depths() {
            for visual in allowed_depth.visuals() {
                if visual.visual_id() == screen.root_visual() {
                    return visual;
                }
            }
        }
    }
    panic!("No visual type found");
}

/// Creates a `cairo::Surface` for the XCB window with the given `id`.
fn cairo_surface_for_xcb_window(conn: &xcb::Connection,
                                screen: &xcb::Screen,
                                id: u32,
                                width: i32,
                                height: i32)
                                -> cairo::Surface {
    let cairo_conn = unsafe {
        cairo::XCBConnection::from_raw_none(conn.get_raw_conn() as *mut cairo_sys::xcb_connection_t)
    };
    let visual = unsafe {
        cairo::XCBVisualType::from_raw_none(&mut get_root_visual_type(conn, screen).base as
                                            *mut xcb::ffi::xcb_visualtype_t as
                                            *mut cairo_sys::xcb_visualtype_t)
    };
    let drawable = cairo::XCBDrawable(id);
    cairo::Surface::create(&cairo_conn, &drawable, &visual, width, height)
}

pub struct Bar {
    conn: Rc<ewmh::Connection>,
    window_id: u32,
    screen_idx: usize,
    surface: cairo::Surface,
    contents: Vec<Vec<Text>>,
}

impl Bar {
    pub fn new() -> Bar {
        let (conn, screen_idx) = xcb::Connection::connect_with_xlib_display().unwrap();
        let screen_idx = screen_idx as usize;
        let id = conn.generate_id();

        let surface = {
            let screen = conn.get_setup()
                .roots()
                .nth(screen_idx)
                .expect("invalid screen");
            let values = [(xcb::CW_BACK_PIXEL, screen.black_pixel()),
                          (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE)];

            let (width, height) = (screen.width_in_pixels(), 100);

            xcb::create_window(&conn,
                               xcb::COPY_FROM_PARENT as u8,
                               id,
                               screen.root(),
                               0,
                               0,
                               width,
                               height,
                               10,
                               xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                               screen.root_visual(),
                               &values);

            cairo_surface_for_xcb_window(&conn, &screen, id, width as i32, height as i32)
        };

        let ewmh_conn = ewmh::Connection::connect(conn).map_err(|_| ()).unwrap();

        let bar = Bar {
            conn: Rc::new(ewmh_conn),
            window_id: id,
            screen_idx,
            surface,
            contents: Vec::new(),
        };
        bar.map_window();
        bar.flush();
        bar
    }

    fn flush(&self) {
        self.conn.flush();
    }

    fn map_window(&self) {
        xcb::map_window(&self.conn, self.window_id);
    }

    fn screen(&self) -> xcb::Screen {
        self.conn
            .get_setup()
            .roots()
            .nth(self.screen_idx)
            .expect("Invalid screen")
    }

    fn update_contents(&mut self, new_contents: Vec<Option<Vec<Text>>>) {
        for (i, opt) in new_contents.into_iter().enumerate() {
            if let Some(new) = opt {
                self.contents[i] = new;
            }
        }
    }

    fn render_text_blocks(&self, texts: Vec<Text>) {
        // Layout each block of text. After this, we can query the width of each
        // block, which will allow us to do more complex layout below.
        let mut layouts: Vec<_> = texts.into_iter().map(|t| t.layout(&self.surface)).collect();

        // Calculate how much free space we have after laying out all the
        // non-stretch blocks. Split the remaining space (if any) between the
        // stretch blocks. If there isn't enough space for the non-stretch blocks
        // do nothing and allow it to overflow.
        {
            let mut width = 0.0;
            let mut stretched = Vec::new();
            for layout in &mut layouts {
                if !layout.stretch() {
                    width += layout.width();
                } else {
                    stretched.push(layout);
                }
            }

            let remaining_width = self.screen().width_in_pixels() as f64 - width;
            let remaining_width = if remaining_width < 0.0 {
                0.0
            } else {
                remaining_width
            };
            let width_per_stretched = remaining_width / (stretched.len() as f64);
            for layout in &mut stretched {
                layout.set_width(width_per_stretched);
            }
        }

        // TODO: Set the height of the window and the height of each text block(?)
        // to the height of the largest bit of text.

        // Finally, just render each block of text in turn.
        let mut x = 0.0;
        for layout in &layouts {
            layout.render(x, 0.0);
            x += layout.width();
        }
    }

    fn expose(&self) {
        // Clear to black before re-painting.
        let context = Context::new(&self.surface);
        Color::black().apply_to_context(&context);
        context.paint();

        let flattened_contents = self.contents.clone().into_iter().flat_map(|v| v).collect();

        self.render_text_blocks(flattened_contents);
        self.conn.flush();
    }

    pub fn run_event_loop(mut self,
                          handle: &Handle,
                          widgets: Vec<Box<Widget>>)
                          -> Box<Future<Item = (), Error = ()>> {
        self.contents = vec![Vec::new(); widgets.len()];

        let events_stream = XcbEventStream::new(self.conn.clone(), handle);
        let widget_updates_stream = WidgetList::new(widgets);

        let event_loop = events_stream.merge(widget_updates_stream);
        let fut = event_loop.for_each(move |item| {
            let (xcb_event, widget_update) = match item {
                MergedItem::First(e) => (Some(e), None),
                MergedItem::Second(u) => (None, Some(u)),
                MergedItem::Both(e, u) => (Some(e), Some(u)),
            };

            if let Some(update) = widget_update {
                self.update_contents(update);
                self.expose();
            }
            if let Some(event) = xcb_event {
                match event.response_type() & !0x80 {
                    xcb::EXPOSE => self.expose(),
                    _ => {}
                }
            }

            future::ok(())
        });

        Box::new(fut)
    }
}

struct XcbEvented(Rc<ewmh::Connection>);

impl XcbEvented {
    fn fd(&self) -> RawFd {
        let conn: &xcb::Connection = &self.0;
        unsafe { xcb::ffi::base::xcb_get_file_descriptor(conn.get_raw_conn()) }
    }
}

impl Evented for XcbEvented {
    fn register(&self,
                poll: &mio::Poll,
                token: Token,
                interest: Ready,
                opts: PollOpt)
                -> io::Result<()> {
        EventedFd(&self.fd()).register(poll, token, interest, opts)
    }

    fn reregister(&self,
                  poll: &mio::Poll,
                  token: Token,
                  interest: Ready,
                  opts: PollOpt)
                  -> io::Result<()> {
        EventedFd(&self.fd()).reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        EventedFd(&self.fd()).deregister(poll)
    }
}

struct XcbEventStream {
    conn: Rc<ewmh::Connection>,
    poll: PollEvented<XcbEvented>,
    would_block: bool,
}

impl XcbEventStream {
    fn new(conn: Rc<ewmh::Connection>, handle: &Handle) -> XcbEventStream {
        let evented = XcbEvented(conn.clone());
        XcbEventStream {
            conn,
            poll: PollEvented::new(evented, handle).unwrap(),
            would_block: true,
        }
    }
}

impl Stream for XcbEventStream {
    type Item = xcb::GenericEvent;
    type Error = ();

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        if self.would_block {
            match self.poll.poll_read() {
                Async::Ready(()) => self.would_block = false,
                Async::NotReady => return Ok(Async::NotReady),
            }
        }

        match self.conn.poll_for_event() {
            Some(event) => Ok(Async::Ready(Some(event))),
            None => {
                self.would_block = true;
                self.poll.need_read();
                Ok(Async::NotReady)
            }
        }
    }
}
<commit_msg>Set EWMH properties to make us a dock!<commit_after>use std::io;
use std::os::unix::io::RawFd;
use std::rc::Rc;

use cairo_sys;
use cairo::{self, Context, XCBSurface};
use futures::{future, Async, Future, Poll, Stream};
use futures::stream::MergedItem;
use mio::{self, PollOpt, Ready, Token};
use mio::event::Evented;
use mio::unix::EventedFd;
use tokio_core::reactor::{Handle, PollEvented};
use xcb;
use xcb_util::ewmh;

use text::{Color, Text};
use widgets::{WidgetList, Widget};

fn get_root_visual_type(conn: &xcb::Connection, screen: &xcb::Screen) -> xcb::Visualtype {
    for root in conn.get_setup().roots() {
        for allowed_depth in root.allowed_depths() {
            for visual in allowed_depth.visuals() {
                if visual.visual_id() == screen.root_visual() {
                    return visual;
                }
            }
        }
    }
    panic!("No visual type found");
}

/// Creates a `cairo::Surface` for the XCB window with the given `id`.
fn cairo_surface_for_xcb_window(conn: &xcb::Connection,
                                screen: &xcb::Screen,
                                id: u32,
                                width: i32,
                                height: i32)
                                -> cairo::Surface {
    let cairo_conn = unsafe {
        cairo::XCBConnection::from_raw_none(conn.get_raw_conn() as *mut cairo_sys::xcb_connection_t)
    };
    let visual = unsafe {
        cairo::XCBVisualType::from_raw_none(&mut get_root_visual_type(conn, screen).base as
                                            *mut xcb::ffi::xcb_visualtype_t as
                                            *mut cairo_sys::xcb_visualtype_t)
    };
    let drawable = cairo::XCBDrawable(id);
    cairo::Surface::create(&cairo_conn, &drawable, &visual, width, height)
}

pub struct Bar {
    conn: Rc<ewmh::Connection>,
    window_id: u32,
    screen_idx: usize,
    surface: cairo::Surface,
    height: u16,
    contents: Vec<Vec<Text>>,
}

impl Bar {
    pub fn new() -> Bar {
        let (conn, screen_idx) = xcb::Connection::connect_with_xlib_display().unwrap();
        let screen_idx = screen_idx as usize;
        let id = conn.generate_id();

        // TODO: Intialize this to 0 and then update the height once we know how
        // big our contents are?
        let height = 100;

        let surface = {
            let screen = conn.get_setup()
                .roots()
                .nth(screen_idx)
                .expect("invalid screen");
            let values = [(xcb::CW_BACK_PIXEL, screen.black_pixel()),
                          (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE)];

            let width = screen.width_in_pixels();

            xcb::create_window(&conn,
                               xcb::COPY_FROM_PARENT as u8,
                               id,
                               screen.root(),
                               0,
                               0,
                               width,
                               height,
                               0,
                               xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                               screen.root_visual(),
                               &values);

            cairo_surface_for_xcb_window(&conn, &screen, id, width as i32, height as i32)
        };

        let ewmh_conn = ewmh::Connection::connect(conn).map_err(|_| ()).unwrap();

        let bar = Bar {
            conn: Rc::new(ewmh_conn),
            window_id: id,
            screen_idx,
            surface,
            height,
            contents: Vec::new(),
        };
        bar.set_ewmh_properties();
        bar.map_window();
        bar.flush();
        bar
    }

    fn flush(&self) {
        self.conn.flush();
    }

    fn map_window(&self) {
        xcb::map_window(&self.conn, self.window_id);
    }

    fn set_ewmh_properties(&self) {
        ewmh::set_wm_window_type(&self.conn, self.window_id, &[self.conn.WM_WINDOW_TYPE_DOCK()]);

        // TODO: Update _WM_STRUT_PARTIAL if the height/position of the bar changes?
        ewmh::set_wm_strut_partial(&self.conn, self.window_id, ewmh::StrutPartial {
            left: 0,
            right: 0,
            top: self.height as u32,
            bottom: 0,
            left_start_y: 0,
            left_end_y: 0,
            right_start_y: 0,
            right_end_y: 0,
            top_start_x: 0,
            top_end_x: 0,
            bottom_start_x: 0,
            bottom_end_x: 0,
        });
    }

    fn screen(&self) -> xcb::Screen {
        self.conn
            .get_setup()
            .roots()
            .nth(self.screen_idx)
            .expect("Invalid screen")
    }

    fn update_contents(&mut self, new_contents: Vec<Option<Vec<Text>>>) {
        for (i, opt) in new_contents.into_iter().enumerate() {
            if let Some(new) = opt {
                self.contents[i] = new;
            }
        }
    }

    fn render_text_blocks(&self, texts: Vec<Text>) {
        // Layout each block of text. After this, we can query the width of each
        // block, which will allow us to do more complex layout below.
        let mut layouts: Vec<_> = texts.into_iter().map(|t| t.layout(&self.surface)).collect();

        // Calculate how much free space we have after laying out all the
        // non-stretch blocks. Split the remaining space (if any) between the
        // stretch blocks. If there isn't enough space for the non-stretch blocks
        // do nothing and allow it to overflow.
        {
            let mut width = 0.0;
            let mut stretched = Vec::new();
            for layout in &mut layouts {
                if !layout.stretch() {
                    width += layout.width();
                } else {
                    stretched.push(layout);
                }
            }

            let remaining_width = self.screen().width_in_pixels() as f64 - width;
            let remaining_width = if remaining_width < 0.0 {
                0.0
            } else {
                remaining_width
            };
            let width_per_stretched = remaining_width / (stretched.len() as f64);
            for layout in &mut stretched {
                layout.set_width(width_per_stretched);
            }
        }

        // TODO: Set the height of the window and the height of each text block(?)
        // to the height of the largest bit of text.

        // Finally, just render each block of text in turn.
        let mut x = 0.0;
        for layout in &layouts {
            layout.render(x, 0.0);
            x += layout.width();
        }
    }

    fn expose(&self) {
        // Clear to black before re-painting.
        let context = Context::new(&self.surface);
        Color::black().apply_to_context(&context);
        context.paint();

        let flattened_contents = self.contents.clone().into_iter().flat_map(|v| v).collect();

        self.render_text_blocks(flattened_contents);
        self.conn.flush();
    }

    pub fn run_event_loop(mut self,
                          handle: &Handle,
                          widgets: Vec<Box<Widget>>)
                          -> Box<Future<Item = (), Error = ()>> {
        self.contents = vec![Vec::new(); widgets.len()];

        let events_stream = XcbEventStream::new(self.conn.clone(), handle);
        let widget_updates_stream = WidgetList::new(widgets);

        let event_loop = events_stream.merge(widget_updates_stream);
        let fut = event_loop.for_each(move |item| {
            let (xcb_event, widget_update) = match item {
                MergedItem::First(e) => (Some(e), None),
                MergedItem::Second(u) => (None, Some(u)),
                MergedItem::Both(e, u) => (Some(e), Some(u)),
            };

            if let Some(update) = widget_update {
                self.update_contents(update);
                self.expose();
            }
            if let Some(event) = xcb_event {
                match event.response_type() & !0x80 {
                    xcb::EXPOSE => self.expose(),
                    _ => {}
                }
            }

            future::ok(())
        });

        Box::new(fut)
    }
}

struct XcbEvented(Rc<ewmh::Connection>);

impl XcbEvented {
    fn fd(&self) -> RawFd {
        let conn: &xcb::Connection = &self.0;
        unsafe { xcb::ffi::base::xcb_get_file_descriptor(conn.get_raw_conn()) }
    }
}

impl Evented for XcbEvented {
    fn register(&self,
                poll: &mio::Poll,
                token: Token,
                interest: Ready,
                opts: PollOpt)
                -> io::Result<()> {
        EventedFd(&self.fd()).register(poll, token, interest, opts)
    }

    fn reregister(&self,
                  poll: &mio::Poll,
                  token: Token,
                  interest: Ready,
                  opts: PollOpt)
                  -> io::Result<()> {
        EventedFd(&self.fd()).reregister(poll, token, interest, opts)
    }

    fn deregister(&self, poll: &mio::Poll) -> io::Result<()> {
        EventedFd(&self.fd()).deregister(poll)
    }
}

struct XcbEventStream {
    conn: Rc<ewmh::Connection>,
    poll: PollEvented<XcbEvented>,
    would_block: bool,
}

impl XcbEventStream {
    fn new(conn: Rc<ewmh::Connection>, handle: &Handle) -> XcbEventStream {
        let evented = XcbEvented(conn.clone());
        XcbEventStream {
            conn,
            poll: PollEvented::new(evented, handle).unwrap(),
            would_block: true,
        }
    }
}

impl Stream for XcbEventStream {
    type Item = xcb::GenericEvent;
    type Error = ();

    fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
        if self.would_block {
            match self.poll.poll_read() {
                Async::Ready(()) => self.would_block = false,
                Async::NotReady => return Ok(Async::NotReady),
            }
        }

        match self.conn.poll_for_event() {
            Some(event) => Ok(Async::Ready(Some(event))),
            None => {
                self.would_block = true;
                self.poll.need_read();
                Ok(Async::NotReady)
            }
        }
    }
}
<|endoftext|>


<commit_before>use std::{
    io::{self, Error, ErrorKind},
    net::SocketAddr,
};

use async_trait::async_trait;
use tokio::net::{TcpListener, TcpStream};

use crate::{
    config::RedirType,
    local::redir::redir_ext::{TcpListenerRedirExt, TcpStreamRedirExt},
};

#[async_trait]
impl TcpListenerRedirExt for TcpListener {
    async fn bind_redir(_ty: RedirType, _addr: SocketAddr) -> io::Result<TcpListener> {
        let err = Error::new(
            ErrorKind::InvalidInput,
            "not supported tcp transparent proxy on Windows",
        );
        Err(err)
    }
}

impl TcpStreamRedirExt for TcpStream {
    fn destination_addr(&self, _ty: RedirType) -> io::Result<SocketAddr> {
        unreachable!("not supported tcp transparent on Windows")
    }
}
<commit_msg>add missing AcceptOpts on Windows TCP redir<commit_after>use std::{
    io::{self, Error, ErrorKind},
    net::SocketAddr,
};

use async_trait::async_trait;
use shadowsocks::net::AcceptOpts;
use tokio::net::{TcpListener, TcpStream};

use crate::{
    config::RedirType,
    local::redir::redir_ext::{TcpListenerRedirExt, TcpStreamRedirExt},
};

#[async_trait]
impl TcpListenerRedirExt for TcpListener {
    async fn bind_redir(_ty: RedirType, _addr: SocketAddr, _accept_opts: AcceptOpts) -> io::Result<TcpListener> {
        let err = Error::new(
            ErrorKind::InvalidInput,
            "not supported tcp transparent proxy on Windows",
        );
        Err(err)
    }
}

impl TcpStreamRedirExt for TcpStream {
    fn destination_addr(&self, _ty: RedirType) -> io::Result<SocketAddr> {
        unreachable!("not supported tcp transparent on Windows")
    }
}
<|endoftext|>


<commit_before>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! This module provides `Pruner` which manages a thread pruning old data in the background and is
//! meant to be triggered by other threads as they commit new data to the DB.

mod db_pruner;
pub(crate) mod event_store;
mod ledger_store;
pub(crate) mod state_store;
pub(crate) mod transaction_store;
pub(crate) mod worker;

use crate::metrics::DIEM_STORAGE_PRUNE_WINDOW;

use aptos_config::config::StoragePrunerConfig;
use aptos_infallible::Mutex;

use crate::{EventStore, LedgerStore, TransactionStore};
use aptos_types::transaction::Version;
use schemadb::DB;
use std::{
    sync::{
        mpsc::{channel, Sender},
        Arc,
    },
    thread::JoinHandle,
};
use worker::{Command, Worker};

/// The `Pruner` is meant to be part of a `AptosDB` instance and runs in the background to prune old
/// data.
///
/// It creates a worker thread on construction and joins it on destruction. When destructed, it
/// quits the worker thread eagerly without waiting for all pending work to be done.
#[derive(Debug)]
pub(crate) struct Pruner {
    /// DB version window, which dictates how many versions of state store
    /// to keep.
    state_store_prune_window: Version,
    /// DB version window, which dictates how many version of other stores like transaction, ledger
    /// info, events etc to keep.
    default_prune_window: Version,
    /// The worker thread handle, created upon Pruner instance construction and joined upon its
    /// destruction. It only becomes `None` after joined in `drop()`.
    worker_thread: Option<JoinHandle<()>>,
    /// The sender side of the channel talking to the worker thread.
    command_sender: Mutex<Sender<Command>>,
    /// (For tests) A way for the worker thread to inform the `Pruner` the pruning progress. If it
    /// sets value to `V`, all versions before `V` can no longer be accessed. This is protected by Mutex
    /// as this is accessed both by the Pruner thread and the worker thread.
    #[allow(dead_code)]
    least_readable_version: Arc<Mutex<Vec<Version>>>,
}

#[cfg(test)]
pub enum PrunerIndex {
    StateStorePrunerIndex,
    TransactionStorePrunerIndex,
    _LedgerStorePrunerIndex,
    EventStorePrunerIndex,
    WriteSetPrunerIndex,
}

impl Pruner {
    /// Creates a worker thread that waits on a channel for pruning commands.
    pub fn new(
        db: Arc<DB>,
        storage_pruner_config: StoragePrunerConfig,
        transaction_store: Arc<TransactionStore>,
        ledger_store: Arc<LedgerStore>,
        event_store: Arc<EventStore>,
    ) -> Self {
        let (command_sender, command_receiver) = channel();

        let least_readable_version = Arc::new(Mutex::new(vec![0, 0, 0, 0, 0, 0]));
        let worker_progress_clone = Arc::clone(&least_readable_version);

        DIEM_STORAGE_PRUNE_WINDOW.set(
            storage_pruner_config
                .state_store_prune_window
                .expect("State store pruner window is required") as i64,
        );
        let worker = Worker::new(
            db,
            transaction_store,
            ledger_store,
            event_store,
            command_receiver,
            least_readable_version,
            storage_pruner_config
                .max_version_to_prune_per_batch
                .expect("Max version to prune per batch is expected"),
        );
        let worker_thread = std::thread::Builder::new()
            .name("aptosdb_pruner".into())
            .spawn(move || worker.work())
            .expect("Creating pruner thread should succeed.");

        Self {
            state_store_prune_window: storage_pruner_config
                .state_store_prune_window
                .expect("State store prune window must be specified"),
            default_prune_window: storage_pruner_config
                .default_prune_window
                .expect("Default prune window must be specified"),
            worker_thread: Some(worker_thread),
            command_sender: Mutex::new(command_sender),
            least_readable_version: worker_progress_clone,
        }
    }

    pub fn get_state_store_pruner_window(&self) -> Version {
        self.state_store_prune_window
    }

    /// Sends pruning command to the worker thread when necessary.
    pub fn wake(&self, latest_version: Version) {
        let least_readable_state_store_version =
            latest_version.saturating_sub(self.state_store_prune_window);
        let least_readable_default_store_version =
            latest_version.saturating_sub(self.default_prune_window);

        self.command_sender
            .lock()
            .send(Command::Prune {
                target_db_versions: vec![
                    least_readable_state_store_version,
                    least_readable_default_store_version,
                    least_readable_default_store_version,
                    least_readable_default_store_version,
                    least_readable_default_store_version,
                    least_readable_default_store_version,
                ],
            })
            .expect("Receiver should not destruct prematurely.");
    }

    /// (For tests only.) Notifies the worker thread and waits for it to finish its job by polling
    /// an internal counter.
    #[cfg(test)]
    pub fn wake_and_wait(
        &self,
        latest_version: Version,
        pruner_index: usize,
    ) -> anyhow::Result<()> {
        use std::{
            thread::sleep,
            time::{Duration, Instant},
        };

        self.wake(latest_version);

        if latest_version > self.state_store_prune_window
            || latest_version > self.default_prune_window
        {
            let least_readable_state_store_version = latest_version - self.state_store_prune_window;
            // Assuming no big pruning chunks will be issued by a test.
            const TIMEOUT: Duration = Duration::from_secs(10);
            let end = Instant::now() + TIMEOUT;

            while Instant::now() < end {
                if *self
                    .least_readable_version
                    .lock()
                    .get(pruner_index)
                    .unwrap()
                    >= least_readable_state_store_version
                {
                    return Ok(());
                }
                sleep(Duration::from_millis(1));
            }
            anyhow::bail!("Timeout waiting for pruner worker.");
        }
        Ok(())
    }
}

impl Drop for Pruner {
    fn drop(&mut self) {
        self.command_sender
            .lock()
            .send(Command::Quit)
            .expect("Receiver should not destruct.");
        self.worker_thread
            .take()
            .expect("Worker thread must exist.")
            .join()
            .expect("Worker thread should join peacefully.");
    }
}
<commit_msg>Fix test<commit_after>// Copyright (c) Aptos
// SPDX-License-Identifier: Apache-2.0

//! This module provides `Pruner` which manages a thread pruning old data in the background and is
//! meant to be triggered by other threads as they commit new data to the DB.

mod db_pruner;
pub(crate) mod event_store;
mod ledger_store;
pub(crate) mod state_store;
pub(crate) mod transaction_store;
pub(crate) mod worker;

use crate::metrics::DIEM_STORAGE_PRUNE_WINDOW;

use aptos_config::config::StoragePrunerConfig;
use aptos_infallible::Mutex;

use crate::{EventStore, LedgerStore, TransactionStore};
use aptos_types::transaction::Version;
use schemadb::DB;
use std::{
    sync::{
        mpsc::{channel, Sender},
        Arc,
    },
    thread::JoinHandle,
};
use worker::{Command, Worker};

/// The `Pruner` is meant to be part of a `AptosDB` instance and runs in the background to prune old
/// data.
///
/// It creates a worker thread on construction and joins it on destruction. When destructed, it
/// quits the worker thread eagerly without waiting for all pending work to be done.
#[derive(Debug)]
pub(crate) struct Pruner {
    /// DB version window, which dictates how many versions of state store
    /// to keep.
    state_store_prune_window: Version,
    /// DB version window, which dictates how many version of other stores like transaction, ledger
    /// info, events etc to keep.
    default_prune_window: Version,
    /// The worker thread handle, created upon Pruner instance construction and joined upon its
    /// destruction. It only becomes `None` after joined in `drop()`.
    worker_thread: Option<JoinHandle<()>>,
    /// The sender side of the channel talking to the worker thread.
    command_sender: Mutex<Sender<Command>>,
    /// (For tests) A way for the worker thread to inform the `Pruner` the pruning progress. If it
    /// sets value to `V`, all versions before `V` can no longer be accessed. This is protected by Mutex
    /// as this is accessed both by the Pruner thread and the worker thread.
    #[allow(dead_code)]
    least_readable_version: Arc<Mutex<Vec<Version>>>,
}

#[cfg(test)]
pub enum PrunerIndex {
    StateStorePrunerIndex,
    TransactionStorePrunerIndex,
    _LedgerStorePrunerIndex,
    EventStorePrunerIndex,
    WriteSetPrunerIndex,
}

impl Pruner {
    /// Creates a worker thread that waits on a channel for pruning commands.
    pub fn new(
        db: Arc<DB>,
        storage_pruner_config: StoragePrunerConfig,
        transaction_store: Arc<TransactionStore>,
        ledger_store: Arc<LedgerStore>,
        event_store: Arc<EventStore>,
    ) -> Self {
        let (command_sender, command_receiver) = channel();

        let least_readable_version = Arc::new(Mutex::new(vec![0, 0, 0, 0, 0]));
        let worker_progress_clone = Arc::clone(&least_readable_version);

        DIEM_STORAGE_PRUNE_WINDOW.set(
            storage_pruner_config
                .state_store_prune_window
                .expect("State store pruner window is required") as i64,
        );
        let worker = Worker::new(
            db,
            transaction_store,
            ledger_store,
            event_store,
            command_receiver,
            least_readable_version,
            storage_pruner_config
                .max_version_to_prune_per_batch
                .expect("Max version to prune per batch is expected"),
        );
        let worker_thread = std::thread::Builder::new()
            .name("aptosdb_pruner".into())
            .spawn(move || worker.work())
            .expect("Creating pruner thread should succeed.");

        Self {
            state_store_prune_window: storage_pruner_config
                .state_store_prune_window
                .expect("State store prune window must be specified"),
            default_prune_window: storage_pruner_config
                .default_prune_window
                .expect("Default prune window must be specified"),
            worker_thread: Some(worker_thread),
            command_sender: Mutex::new(command_sender),
            least_readable_version: worker_progress_clone,
        }
    }

    pub fn get_state_store_pruner_window(&self) -> Version {
        self.state_store_prune_window
    }

    /// Sends pruning command to the worker thread when necessary.
    pub fn wake(&self, latest_version: Version) {
        let least_readable_state_store_version =
            latest_version.saturating_sub(self.state_store_prune_window);
        let least_readable_default_store_version =
            latest_version.saturating_sub(self.default_prune_window);

        self.command_sender
            .lock()
            .send(Command::Prune {
                target_db_versions: vec![
                    least_readable_state_store_version,
                    least_readable_default_store_version,
                    least_readable_default_store_version,
                    least_readable_default_store_version,
                    least_readable_default_store_version,
                ],
            })
            .expect("Receiver should not destruct prematurely.");
    }

    /// (For tests only.) Notifies the worker thread and waits for it to finish its job by polling
    /// an internal counter.
    #[cfg(test)]
    pub fn wake_and_wait(
        &self,
        latest_version: Version,
        pruner_index: usize,
    ) -> anyhow::Result<()> {
        use std::{
            thread::sleep,
            time::{Duration, Instant},
        };

        self.wake(latest_version);

        if latest_version > self.state_store_prune_window
            || latest_version > self.default_prune_window
        {
            let least_readable_state_store_version = latest_version - self.state_store_prune_window;
            // Assuming no big pruning chunks will be issued by a test.
            const TIMEOUT: Duration = Duration::from_secs(10);
            let end = Instant::now() + TIMEOUT;

            while Instant::now() < end {
                if *self
                    .least_readable_version
                    .lock()
                    .get(pruner_index)
                    .unwrap()
                    >= least_readable_state_store_version
                {
                    return Ok(());
                }
                sleep(Duration::from_millis(1));
            }
            anyhow::bail!("Timeout waiting for pruner worker.");
        }
        Ok(())
    }
}

impl Drop for Pruner {
    fn drop(&mut self) {
        self.command_sender
            .lock()
            .send(Command::Quit)
            .expect("Receiver should not destruct.");
        self.worker_thread
            .take()
            .expect("Worker thread must exist.")
            .join()
            .expect("Worker thread should join peacefully.");
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "rustcrypto_api")]
pub use stream_cipher::generic_array;

pub use ppv_lite86::Machine;
use ppv_lite86::{vec128_storage, ArithOps, BitOps32, LaneWords4, MultiLane, StoreBytes, Vec4};

pub(crate) const BLOCK: usize = 64;
pub(crate) const BLOCK64: u64 = BLOCK as u64;
const LOG2_BUFBLOCKS: u64 = 2;
const BUFBLOCKS: u64 = 1 << LOG2_BUFBLOCKS;
pub(crate) const BUFSZ64: u64 = BLOCK64 * BUFBLOCKS;
pub(crate) const BUFSZ: usize = BUFSZ64 as usize;

#[derive(Clone)]
pub struct ChaCha {
    pub(crate) b: vec128_storage,
    pub(crate) c: vec128_storage,
    pub(crate) d: vec128_storage,
}

#[derive(Clone)]
pub struct State<V> {
    pub(crate) a: V,
    pub(crate) b: V,
    pub(crate) c: V,
    pub(crate) d: V,
}

#[inline(always)]
pub(crate) fn round<V: ArithOps + BitOps32>(mut x: State<V>) -> State<V> {
    x.a += x.b;
    x.d = (x.d ^ x.a).rotate_each_word_right16();
    x.c += x.d;
    x.b = (x.b ^ x.c).rotate_each_word_right20();
    x.a += x.b;
    x.d = (x.d ^ x.a).rotate_each_word_right24();
    x.c += x.d;
    x.b = (x.b ^ x.c).rotate_each_word_right25();
    x
}

#[inline(always)]
pub(crate) fn diagonalize<V: LaneWords4>(mut x: State<V>) -> State<V> {
    // Since b has the critical data dependency, avoid rotating b to hide latency.
    //
    // The order of these statements is important for performance on pre-AVX2 Intel machines, which
    // are throughput-bound and operating near their superscalar limits during refill_wide. The
    // permutations here and in undiagonalize have been found in testing on Nehalem to be optimal.
    x.a = x.a.shuffle_lane_words1230();
    x.c = x.c.shuffle_lane_words3012();
    x.d = x.d.shuffle_lane_words2301();
    x
}

#[inline(always)]
pub(crate) fn undiagonalize<V: LaneWords4>(mut x: State<V>) -> State<V> {
    // The order of these statements is magic. See comment in diagonalize.
    x.c = x.c.shuffle_lane_words1230();
    x.d = x.d.shuffle_lane_words2301();
    x.a = x.a.shuffle_lane_words3012();
    x
}

impl ChaCha {
    pub fn new(key: &[u8; 32], nonce: &[u8]) -> Self {
        let ctr_nonce = [
            0,
            if nonce.len() == 12 {
                read_u32le(&nonce[0..4])
            } else {
                0
            },
            read_u32le(&nonce[nonce.len() - 8..nonce.len() - 4]),
            read_u32le(&nonce[nonce.len() - 4..]),
        ];
        let key0 = [
            read_u32le(&key[0..4]),
            read_u32le(&key[4..8]),
            read_u32le(&key[8..12]),
            read_u32le(&key[12..16]),
        ];
        let key1 = [
            read_u32le(&key[16..20]),
            read_u32le(&key[20..24]),
            read_u32le(&key[24..28]),
            read_u32le(&key[28..32]),
        ];

        ChaCha {
            b: key0.into(),
            c: key1.into(),
            d: ctr_nonce.into(),
        }
    }

    #[inline(always)]
    fn pos64<M: Machine>(&self, m: M) -> u64 {
        let d: M::u32x4 = m.unpack(self.d);
        ((d.extract(1) as u64) << 32) | d.extract(0) as u64
    }

    /// Set 64-bit block count, affecting next refill.
    #[inline(always)]
    pub(crate) fn seek64<M: Machine>(&mut self, m: M, blockct: u64) {
        let d: M::u32x4 = m.unpack(self.d);
        self.d = d
            .insert((blockct >> 32) as u32, 1)
            .insert(blockct as u32, 0)
            .into();
    }

    /// Set 32-bit block count, affecting next refill.
    #[inline(always)]
    pub(crate) fn seek32<M: Machine>(&mut self, m: M, blockct: u32) {
        let d: M::u32x4 = m.unpack(self.d);
        self.d = d.insert(blockct, 0).into();
    }

    /// Produce output from the current state.
    #[inline(always)]
    fn output_narrow<M: Machine>(&mut self, m: M, x: State<M::u32x4>, out: &mut [u8; BLOCK]) {
        let k = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);
        (x.a + k).write_le(&mut out[0..16]);
        (x.b + m.unpack(self.b)).write_le(&mut out[16..32]);
        (x.c + m.unpack(self.c)).write_le(&mut out[32..48]);
        (x.d + m.unpack(self.d)).write_le(&mut out[48..64]);
    }

    /// Add one to the block counter (no overflow check).
    #[inline(always)]
    fn inc_block_ct<M: Machine>(&mut self, m: M) {
        let mut pos = self.pos64(m);
        let d0: M::u32x4 = m.unpack(self.d);
        pos += 1;
        let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
        self.d = d1.into();
    }

    /// Produce 4 blocks of output, advancing the state
    #[inline(always)]
    pub fn refill4(&mut self, drounds: u32, out: &mut [u8; BUFSZ]) {
        refill_wide(self, drounds, out)
    }

    /// Produce a block of output, advancing the state
    #[inline(always)]
    pub fn refill(&mut self, drounds: u32, out: &mut [u8; BLOCK]) {
        refill_narrow(self, drounds, out)
    }

    #[inline(always)]
    pub(crate) fn refill_rounds(&mut self, drounds: u32) -> State<vec128_storage> {
        refill_narrow_rounds(self, drounds)
    }

    #[inline]
    pub fn set_stream_param(&mut self, param: u32, value: u64) {
        let mut d: [u32; 4] = self.d.into();
        let p0 = ((param << 1) | 1) as usize;
        let p1 = (param << 1) as usize;
        d[p0] = (value >> 32) as u32;
        d[p1] = value as u32;
        self.d = d.into();
    }

    #[inline]
    pub fn get_stream_param(&self, param: u32) -> u64 {
        let d: [u32; 4] = self.d.into();
        let p0 = ((param << 1) | 1) as usize;
        let p1 = (param << 1) as usize;
        ((d[p0] as u64) << 32) | d[p1] as u64
    }
}

#[inline(always)]
fn refill_wide_impl<Mach: Machine>(
    m: Mach,
    state: &mut ChaCha,
    drounds: u32,
    out: &mut [u8; BUFSZ],
) {
    let k = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);
    let mut pos = state.pos64(m);
    let d0: Mach::u32x4 = m.unpack(state.d);
    pos += 1;
    let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d2 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d3 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);

    let b = m.unpack(state.b);
    let c = m.unpack(state.c);
    let mut x = State {
        a: Mach::u32x4x4::from_lanes([k, k, k, k]),
        b: Mach::u32x4x4::from_lanes([b, b, b, b]),
        c: Mach::u32x4x4::from_lanes([c, c, c, c]),
        d: m.unpack(Mach::u32x4x4::from_lanes([d0, d1, d2, d3]).into()),
    };
    for _ in 0..drounds {
        x = round(x);
        x = undiagonalize(round(diagonalize(x)));
    }
    let mut pos = state.pos64(m);
    let d0: Mach::u32x4 = m.unpack(state.d);
    pos += 1;
    let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d2 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d3 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d4 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);

    let (a, b, c, d) = (
        x.a.to_lanes(),
        x.b.to_lanes(),
        x.c.to_lanes(),
        x.d.to_lanes(),
    );
    let sb = m.unpack(state.b);
    let sc = m.unpack(state.c);
    let sd = [m.unpack(state.d), d1, d2, d3];
    state.d = d4.into();
    let mut words = out.chunks_exact_mut(16);
    for ((((&a, &b), &c), &d), &sd) in a.iter().zip(&b).zip(&c).zip(&d).zip(&sd) {
        (a + k).write_le(words.next().unwrap());
        (b + sb).write_le(words.next().unwrap());
        (c + sc).write_le(words.next().unwrap());
        (d + sd).write_le(words.next().unwrap());
    }
}

dispatch!(m, Mach, {
    fn refill_wide(state: &mut ChaCha, drounds: u32, out: &mut [u8; BUFSZ]) {
        refill_wide_impl(m, state, drounds, out);
    }
});

/// Refill the buffer from a single-block round, updating the block count.
dispatch_light128!(m, Mach, {
    fn refill_narrow(state: &mut ChaCha, drounds: u32, out: &mut [u8; BLOCK]) {
        let x = refill_narrow_rounds(state, drounds);
        let x = State {
            a: m.unpack(x.a),
            b: m.unpack(x.b),
            c: m.unpack(x.c),
            d: m.unpack(x.d),
        };
        state.output_narrow(m, x, out);
        state.inc_block_ct(m);
    }
});

/// Single-block, rounds-only; shared by try_apply_keystream for tails shorter than BUFSZ
/// and XChaCha's setup step.
dispatch!(m, Mach, {
    fn refill_narrow_rounds(state: &mut ChaCha, drounds: u32) -> State<vec128_storage> {
        let k: Mach::u32x4 = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);
        let mut x = State {
            a: k,
            b: m.unpack(state.b),
            c: m.unpack(state.c),
            d: m.unpack(state.d),
        };
        for _ in 0..drounds {
            x = round(x);
            x = undiagonalize(round(diagonalize(x)));
        }
        State {
            a: x.a.into(),
            b: x.b.into(),
            c: x.c.into(),
            d: x.d.into(),
        }
    }
});

fn read_u32le(xs: &[u8]) -> u32 {
    assert_eq!(xs.len(), 4);
    u32::from(xs[0]) | (u32::from(xs[1]) << 8) | (u32::from(xs[2]) << 16) | (u32::from(xs[3]) << 24)
}

dispatch_light128!(m, Mach, {
    fn init_chacha_x(key: &[u8; 32], nonce: &[u8; 24], rounds: u32) -> ChaCha {
        let key0: Mach::u32x4 = m.read_le(&key[..16]);
        let key1: Mach::u32x4 = m.read_le(&key[16..]);
        let nonce0: Mach::u32x4 = m.read_le(&nonce[..16]);
        let mut state = ChaCha {
            b: key0.into(),
            c: key1.into(),
            d: nonce0.into(),
        };
        let x = refill_narrow_rounds(&mut state, rounds);
        let ctr_nonce1 = [0, 0, read_u32le(&nonce[16..20]), read_u32le(&nonce[20..24])];
        state.b = x.a;
        state.c = x.d;
        state.d = ctr_nonce1.into();
        state
    }
});
<commit_msg>ChaCha: derive PartialEq, Eq<commit_after>#[cfg(feature = "rustcrypto_api")]
pub use stream_cipher::generic_array;

pub use ppv_lite86::Machine;
use ppv_lite86::{vec128_storage, ArithOps, BitOps32, LaneWords4, MultiLane, StoreBytes, Vec4};

pub(crate) const BLOCK: usize = 64;
pub(crate) const BLOCK64: u64 = BLOCK as u64;
const LOG2_BUFBLOCKS: u64 = 2;
const BUFBLOCKS: u64 = 1 << LOG2_BUFBLOCKS;
pub(crate) const BUFSZ64: u64 = BLOCK64 * BUFBLOCKS;
pub(crate) const BUFSZ: usize = BUFSZ64 as usize;

/// Parameters of a ChaCha stream, including fixed parameters and current position.
#[derive(Clone, PartialEq, Eq)]
pub struct ChaCha {
    pub(crate) b: vec128_storage,
    pub(crate) c: vec128_storage,
    pub(crate) d: vec128_storage,
}

/// Working state of a ChaCha stream.
#[derive(Clone, PartialEq, Eq)]
pub struct State<V> {
    pub(crate) a: V,
    pub(crate) b: V,
    pub(crate) c: V,
    pub(crate) d: V,
}

#[inline(always)]
pub(crate) fn round<V: ArithOps + BitOps32>(mut x: State<V>) -> State<V> {
    x.a += x.b;
    x.d = (x.d ^ x.a).rotate_each_word_right16();
    x.c += x.d;
    x.b = (x.b ^ x.c).rotate_each_word_right20();
    x.a += x.b;
    x.d = (x.d ^ x.a).rotate_each_word_right24();
    x.c += x.d;
    x.b = (x.b ^ x.c).rotate_each_word_right25();
    x
}

#[inline(always)]
pub(crate) fn diagonalize<V: LaneWords4>(mut x: State<V>) -> State<V> {
    // Since b has the critical data dependency, avoid rotating b to hide latency.
    //
    // The order of these statements is important for performance on pre-AVX2 Intel machines, which
    // are throughput-bound and operating near their superscalar limits during refill_wide. The
    // permutations here and in undiagonalize have been found in testing on Nehalem to be optimal.
    x.a = x.a.shuffle_lane_words1230();
    x.c = x.c.shuffle_lane_words3012();
    x.d = x.d.shuffle_lane_words2301();
    x
}

#[inline(always)]
pub(crate) fn undiagonalize<V: LaneWords4>(mut x: State<V>) -> State<V> {
    // The order of these statements is magic. See comment in diagonalize.
    x.c = x.c.shuffle_lane_words1230();
    x.d = x.d.shuffle_lane_words2301();
    x.a = x.a.shuffle_lane_words3012();
    x
}

impl ChaCha {
    pub fn new(key: &[u8; 32], nonce: &[u8]) -> Self {
        let ctr_nonce = [
            0,
            if nonce.len() == 12 {
                read_u32le(&nonce[0..4])
            } else {
                0
            },
            read_u32le(&nonce[nonce.len() - 8..nonce.len() - 4]),
            read_u32le(&nonce[nonce.len() - 4..]),
        ];
        let key0 = [
            read_u32le(&key[0..4]),
            read_u32le(&key[4..8]),
            read_u32le(&key[8..12]),
            read_u32le(&key[12..16]),
        ];
        let key1 = [
            read_u32le(&key[16..20]),
            read_u32le(&key[20..24]),
            read_u32le(&key[24..28]),
            read_u32le(&key[28..32]),
        ];

        ChaCha {
            b: key0.into(),
            c: key1.into(),
            d: ctr_nonce.into(),
        }
    }

    #[inline(always)]
    fn pos64<M: Machine>(&self, m: M) -> u64 {
        let d: M::u32x4 = m.unpack(self.d);
        ((d.extract(1) as u64) << 32) | d.extract(0) as u64
    }

    /// Set 64-bit block count, affecting next refill.
    #[inline(always)]
    pub(crate) fn seek64<M: Machine>(&mut self, m: M, blockct: u64) {
        let d: M::u32x4 = m.unpack(self.d);
        self.d = d
            .insert((blockct >> 32) as u32, 1)
            .insert(blockct as u32, 0)
            .into();
    }

    /// Set 32-bit block count, affecting next refill.
    #[inline(always)]
    pub(crate) fn seek32<M: Machine>(&mut self, m: M, blockct: u32) {
        let d: M::u32x4 = m.unpack(self.d);
        self.d = d.insert(blockct, 0).into();
    }

    /// Produce output from the current state.
    #[inline(always)]
    fn output_narrow<M: Machine>(&mut self, m: M, x: State<M::u32x4>, out: &mut [u8; BLOCK]) {
        let k = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);
        (x.a + k).write_le(&mut out[0..16]);
        (x.b + m.unpack(self.b)).write_le(&mut out[16..32]);
        (x.c + m.unpack(self.c)).write_le(&mut out[32..48]);
        (x.d + m.unpack(self.d)).write_le(&mut out[48..64]);
    }

    /// Add one to the block counter (no overflow check).
    #[inline(always)]
    fn inc_block_ct<M: Machine>(&mut self, m: M) {
        let mut pos = self.pos64(m);
        let d0: M::u32x4 = m.unpack(self.d);
        pos += 1;
        let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
        self.d = d1.into();
    }

    /// Produce 4 blocks of output, advancing the state
    #[inline(always)]
    pub fn refill4(&mut self, drounds: u32, out: &mut [u8; BUFSZ]) {
        refill_wide(self, drounds, out)
    }

    /// Produce a block of output, advancing the state
    #[inline(always)]
    pub fn refill(&mut self, drounds: u32, out: &mut [u8; BLOCK]) {
        refill_narrow(self, drounds, out)
    }

    #[inline(always)]
    pub(crate) fn refill_rounds(&mut self, drounds: u32) -> State<vec128_storage> {
        refill_narrow_rounds(self, drounds)
    }

    #[inline]
    pub fn set_stream_param(&mut self, param: u32, value: u64) {
        let mut d: [u32; 4] = self.d.into();
        let p0 = ((param << 1) | 1) as usize;
        let p1 = (param << 1) as usize;
        d[p0] = (value >> 32) as u32;
        d[p1] = value as u32;
        self.d = d.into();
    }

    #[inline]
    pub fn get_stream_param(&self, param: u32) -> u64 {
        let d: [u32; 4] = self.d.into();
        let p0 = ((param << 1) | 1) as usize;
        let p1 = (param << 1) as usize;
        ((d[p0] as u64) << 32) | d[p1] as u64
    }
}

#[inline(always)]
fn refill_wide_impl<Mach: Machine>(
    m: Mach,
    state: &mut ChaCha,
    drounds: u32,
    out: &mut [u8; BUFSZ],
) {
    let k = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);
    let mut pos = state.pos64(m);
    let d0: Mach::u32x4 = m.unpack(state.d);
    pos += 1;
    let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d2 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d3 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);

    let b = m.unpack(state.b);
    let c = m.unpack(state.c);
    let mut x = State {
        a: Mach::u32x4x4::from_lanes([k, k, k, k]),
        b: Mach::u32x4x4::from_lanes([b, b, b, b]),
        c: Mach::u32x4x4::from_lanes([c, c, c, c]),
        d: m.unpack(Mach::u32x4x4::from_lanes([d0, d1, d2, d3]).into()),
    };
    for _ in 0..drounds {
        x = round(x);
        x = undiagonalize(round(diagonalize(x)));
    }
    let mut pos = state.pos64(m);
    let d0: Mach::u32x4 = m.unpack(state.d);
    pos += 1;
    let d1 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d2 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d3 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);
    pos += 1;
    let d4 = d0.insert((pos >> 32) as u32, 1).insert(pos as u32, 0);

    let (a, b, c, d) = (
        x.a.to_lanes(),
        x.b.to_lanes(),
        x.c.to_lanes(),
        x.d.to_lanes(),
    );
    let sb = m.unpack(state.b);
    let sc = m.unpack(state.c);
    let sd = [m.unpack(state.d), d1, d2, d3];
    state.d = d4.into();
    let mut words = out.chunks_exact_mut(16);
    for ((((&a, &b), &c), &d), &sd) in a.iter().zip(&b).zip(&c).zip(&d).zip(&sd) {
        (a + k).write_le(words.next().unwrap());
        (b + sb).write_le(words.next().unwrap());
        (c + sc).write_le(words.next().unwrap());
        (d + sd).write_le(words.next().unwrap());
    }
}

dispatch!(m, Mach, {
    fn refill_wide(state: &mut ChaCha, drounds: u32, out: &mut [u8; BUFSZ]) {
        refill_wide_impl(m, state, drounds, out);
    }
});

/// Refill the buffer from a single-block round, updating the block count.
dispatch_light128!(m, Mach, {
    fn refill_narrow(state: &mut ChaCha, drounds: u32, out: &mut [u8; BLOCK]) {
        let x = refill_narrow_rounds(state, drounds);
        let x = State {
            a: m.unpack(x.a),
            b: m.unpack(x.b),
            c: m.unpack(x.c),
            d: m.unpack(x.d),
        };
        state.output_narrow(m, x, out);
        state.inc_block_ct(m);
    }
});

/// Single-block, rounds-only; shared by try_apply_keystream for tails shorter than BUFSZ
/// and XChaCha's setup step.
dispatch!(m, Mach, {
    fn refill_narrow_rounds(state: &mut ChaCha, drounds: u32) -> State<vec128_storage> {
        let k: Mach::u32x4 = m.vec([0x6170_7865, 0x3320_646e, 0x7962_2d32, 0x6b20_6574]);
        let mut x = State {
            a: k,
            b: m.unpack(state.b),
            c: m.unpack(state.c),
            d: m.unpack(state.d),
        };
        for _ in 0..drounds {
            x = round(x);
            x = undiagonalize(round(diagonalize(x)));
        }
        State {
            a: x.a.into(),
            b: x.b.into(),
            c: x.c.into(),
            d: x.d.into(),
        }
    }
});

fn read_u32le(xs: &[u8]) -> u32 {
    assert_eq!(xs.len(), 4);
    u32::from(xs[0]) | (u32::from(xs[1]) << 8) | (u32::from(xs[2]) << 16) | (u32::from(xs[3]) << 24)
}

dispatch_light128!(m, Mach, {
    fn init_chacha_x(key: &[u8; 32], nonce: &[u8; 24], rounds: u32) -> ChaCha {
        let key0: Mach::u32x4 = m.read_le(&key[..16]);
        let key1: Mach::u32x4 = m.read_le(&key[16..]);
        let nonce0: Mach::u32x4 = m.read_le(&nonce[..16]);
        let mut state = ChaCha {
            b: key0.into(),
            c: key1.into(),
            d: nonce0.into(),
        };
        let x = refill_narrow_rounds(&mut state, rounds);
        let ctr_nonce1 = [0, 0, read_u32le(&nonce[16..20]), read_u32le(&nonce[20..24])];
        state.b = x.a;
        state.c = x.d;
        state.d = ctr_nonce1.into();
        state
    }
});
<|endoftext|>


<commit_before>use na::storage::Storage;
use na::{self, Point2, Real, U3, Vector, Vector1, Vector2, Vector3};
use std::mem;
use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};

/// A force with a linear and agular (torque) component.
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct Force2<N: Real> {
    /// The linear force.
    pub linear: Vector2<N>,
    /// The torque.
    pub angular: N,
}

impl<N: Real> Force2<N> {
    /// Creates a force from its linear and angular components.
    #[inline]
    pub fn new(linear: Vector2<N>, angular: N) -> Self {
        Force2 { linear, angular }
    }

    /// A zero force.
    #[inline]
    pub fn zero() -> Self {
        Self::new(na::zero(), N::zero())
    }

    /// Create a force from a slice where the entries 0 and 1 are for the linear part and 2 for the angular part.
    #[inline]
    pub fn from_slice(data: &[N]) -> Self {
        Self::new(Vector2::new(data[0], data[1]), data[2])
    }

    /// Create a force from a vector where the entries 0 and 1 are for the linear part and 2 for the angular part.
    #[inline]
    pub fn from_vector<S: Storage<N, U3>>(data: &Vector<N, U3, S>) -> Self {
        Self::new(Vector2::new(data[0], data[1]), data[2])
    }

    /// Create a pure torque.
    #[inline]
    pub fn torque(torque: N) -> Self {
        Self::new(na::zero(), torque)
    }

    /// Create a pure torque.
    #[inline]
    pub fn torque_from_vector(torque: Vector1<N>) -> Self {
        Self::new(na::zero(), torque.x)
    }

    /// Create a pure linear force.
    #[inline]
    pub fn linear(linear: Vector2<N>) -> Self {
        Self::new(linear, na::zero())
    }

    /// Creates the resultant of a linear force applied at the given point (relative to the center of mass).
    #[inline]
    pub fn linear_at_point(linear: Vector2<N>, point: &Point2<N>) -> Self {
        Self::new(linear, point.coords.perp(&linear))
    }

    /// Creates the resultant of a torque applied at the given point (relative to the center of mass).
    #[inline]
    pub fn torque_at_point(torque: N, point: &Point2<N>) -> Self {
        Self::new(point.coords * -torque, torque)
    }

    /// Creates the resultant of a torque applied at the given point (relative to the center of mass).
    #[inline]
    pub fn torque_from_vector_at_point(torque: Vector1<N>, point: &Point2<N>) -> Self {
        Self::torque_at_point(torque.x, point)
    }

    /// The angular part of the force.
    #[inline]
    pub fn angular_vector(&self) -> Vector1<N> {
        Vector1::new(self.angular)
    }

    /// This force seen as a slice.
    ///
    /// The two first entries contain the linear part and the third entry contais the angular part.
    #[inline]
    pub fn as_slice(&self) -> &[N] {
        self.as_vector().as_slice()
    }

    /// This force seen as a vector.
    ///
    /// The two first entries contain the linear part and the third entry contais the angular part.
    #[inline]
    pub fn as_vector(&self) -> &Vector3<N> {
        unsafe { mem::transmute(self) }
    }

    /// This force seen as a mutable vector.
    ///
    /// The two first entries contain the linear part and the third entry contais the angular part.
    #[inline]
    pub fn as_vector_mut(&mut self) -> &mut Vector3<N> {
        unsafe { mem::transmute(self) }
    }
}

impl<N: Real> Add<Force2<N>> for Force2<N> {
    type Output = Self;

    #[inline]
    fn add(self, rhs: Self) -> Self {
        Force2::new(self.linear + rhs.linear, self.angular + rhs.angular)
    }
}

impl<N: Real> AddAssign<Force2<N>> for Force2<N> {
    #[inline]
    fn add_assign(&mut self, rhs: Self) {
        self.linear += rhs.linear;
        self.angular += rhs.angular;
    }
}

impl<N: Real> Sub<Force2<N>> for Force2<N> {
    type Output = Self;

    #[inline]
    fn sub(self, rhs: Self) -> Self {
        Force2::new(self.linear - rhs.linear, self.angular - rhs.angular)
    }
}

impl<N: Real> SubAssign<Force2<N>> for Force2<N> {
    #[inline]
    fn sub_assign(&mut self, rhs: Self) {
        self.linear -= rhs.linear;
        self.angular -= rhs.angular;
    }
}

impl<N: Real> Mul<N> for Force2<N> {
    type Output = Self;

    #[inline]
    fn mul(self, rhs: N) -> Self {
        Force2::new(self.linear * rhs, self.angular * rhs)
    }
}

impl<N: Real> Neg for Force2<N> {
    type Output = Self;

    #[inline]
    fn neg(self) -> Self {
        Force2::new(-self.linear, -self.angular)
    }
}
<commit_msg>Fix typo<commit_after>use na::storage::Storage;
use na::{self, Point2, Real, U3, Vector, Vector1, Vector2, Vector3};
use std::mem;
use std::ops::{Add, AddAssign, Mul, Neg, Sub, SubAssign};

/// A force with a linear and angular (torque) component.
#[repr(C)]
#[derive(Copy, Clone, Debug)]
pub struct Force2<N: Real> {
    /// The linear force.
    pub linear: Vector2<N>,
    /// The torque.
    pub angular: N,
}

impl<N: Real> Force2<N> {
    /// Creates a force from its linear and angular components.
    #[inline]
    pub fn new(linear: Vector2<N>, angular: N) -> Self {
        Force2 { linear, angular }
    }

    /// A zero force.
    #[inline]
    pub fn zero() -> Self {
        Self::new(na::zero(), N::zero())
    }

    /// Create a force from a slice where the entries 0 and 1 are for the linear part and 2 for the angular part.
    #[inline]
    pub fn from_slice(data: &[N]) -> Self {
        Self::new(Vector2::new(data[0], data[1]), data[2])
    }

    /// Create a force from a vector where the entries 0 and 1 are for the linear part and 2 for the angular part.
    #[inline]
    pub fn from_vector<S: Storage<N, U3>>(data: &Vector<N, U3, S>) -> Self {
        Self::new(Vector2::new(data[0], data[1]), data[2])
    }

    /// Create a pure torque.
    #[inline]
    pub fn torque(torque: N) -> Self {
        Self::new(na::zero(), torque)
    }

    /// Create a pure torque.
    #[inline]
    pub fn torque_from_vector(torque: Vector1<N>) -> Self {
        Self::new(na::zero(), torque.x)
    }

    /// Create a pure linear force.
    #[inline]
    pub fn linear(linear: Vector2<N>) -> Self {
        Self::new(linear, na::zero())
    }

    /// Creates the resultant of a linear force applied at the given point (relative to the center of mass).
    #[inline]
    pub fn linear_at_point(linear: Vector2<N>, point: &Point2<N>) -> Self {
        Self::new(linear, point.coords.perp(&linear))
    }

    /// Creates the resultant of a torque applied at the given point (relative to the center of mass).
    #[inline]
    pub fn torque_at_point(torque: N, point: &Point2<N>) -> Self {
        Self::new(point.coords * -torque, torque)
    }

    /// Creates the resultant of a torque applied at the given point (relative to the center of mass).
    #[inline]
    pub fn torque_from_vector_at_point(torque: Vector1<N>, point: &Point2<N>) -> Self {
        Self::torque_at_point(torque.x, point)
    }

    /// The angular part of the force.
    #[inline]
    pub fn angular_vector(&self) -> Vector1<N> {
        Vector1::new(self.angular)
    }

    /// This force seen as a slice.
    ///
    /// The two first entries contain the linear part and the third entry contais the angular part.
    #[inline]
    pub fn as_slice(&self) -> &[N] {
        self.as_vector().as_slice()
    }

    /// This force seen as a vector.
    ///
    /// The two first entries contain the linear part and the third entry contais the angular part.
    #[inline]
    pub fn as_vector(&self) -> &Vector3<N> {
        unsafe { mem::transmute(self) }
    }

    /// This force seen as a mutable vector.
    ///
    /// The two first entries contain the linear part and the third entry contais the angular part.
    #[inline]
    pub fn as_vector_mut(&mut self) -> &mut Vector3<N> {
        unsafe { mem::transmute(self) }
    }
}

impl<N: Real> Add<Force2<N>> for Force2<N> {
    type Output = Self;

    #[inline]
    fn add(self, rhs: Self) -> Self {
        Force2::new(self.linear + rhs.linear, self.angular + rhs.angular)
    }
}

impl<N: Real> AddAssign<Force2<N>> for Force2<N> {
    #[inline]
    fn add_assign(&mut self, rhs: Self) {
        self.linear += rhs.linear;
        self.angular += rhs.angular;
    }
}

impl<N: Real> Sub<Force2<N>> for Force2<N> {
    type Output = Self;

    #[inline]
    fn sub(self, rhs: Self) -> Self {
        Force2::new(self.linear - rhs.linear, self.angular - rhs.angular)
    }
}

impl<N: Real> SubAssign<Force2<N>> for Force2<N> {
    #[inline]
    fn sub_assign(&mut self, rhs: Self) {
        self.linear -= rhs.linear;
        self.angular -= rhs.angular;
    }
}

impl<N: Real> Mul<N> for Force2<N> {
    type Output = Self;

    #[inline]
    fn mul(self, rhs: N) -> Self {
        Force2::new(self.linear * rhs, self.angular * rhs)
    }
}

impl<N: Real> Neg for Force2<N> {
    type Output = Self;

    #[inline]
    fn neg(self) -> Self {
        Force2::new(-self.linear, -self.angular)
    }
}
<|endoftext|>


<commit_before>use token::Token;
use logger::Logger;
use error::{Error, Result};

use std::collections::HashMap;
use std::path::{Path,PathBuf};
use std::borrow::Cow;
use std::fs;

use walkdir::WalkDir;

/// Resource Handler.
///
/// Its task is to make sure that some resource (image, link) is available
/// for the book and to list images used in Markdown files so they can be used for the book
#[derive(Debug)]
pub struct ResourceHandler<'r> {
    /// Maps an original url (e.g.) "foo/Readme.md" to a valid link
    /// (e.g.) chapter3.html
    links: HashMap<String, String>,
    /// Maps an original (local) file name to a new file name. Allows to
    // make sure all image files will be included in e.g. the Epub document.
    pub images: HashMap<String, String>,
    map_images: bool,
    logger: &'r Logger,
}

impl<'r> ResourceHandler<'r> {
    /// Creates a new, empty Resource Handler
    pub fn new(logger: &'r Logger) -> ResourceHandler {
        ResourceHandler {
            links: HashMap::new(),
            images: HashMap::new(),
            map_images: false,
            logger: logger,
        }
    }

    /// Turns on mapping for image files
    ///
    /// # Argument: an offset (should be book.root)
    pub fn set_images_mapping(&mut self, b: bool) {
        self.map_images = b;
    }

    /// Add a local image file and get the resulting transformed
    /// file name
    pub fn map_image<'a>(&'a mut self, file: Cow<'a, str>) -> Cow<'a, str> {
        // if image mapping is not activated, do nothing
        if !self.map_images {
            return file;
        }

        // If image is not local, do nothing either
        if !Self::is_local(file.as_ref()) {
            self.logger.warning("Resources: book includes non-local images which might cause problem for proper inclusion.");
            return file;
        }

        // If this image has already been registered, returns it
        if self.images.contains_key(file.as_ref()) {
            return Cow::Borrowed(self.images.get(file.as_ref()).unwrap());
        }

        // Else, create a new file name that has same extension
        let dest_file = if let Some(extension) = Path::new(file.as_ref()).extension() {
            format!("images/image_{}.{}", self.images.len(), extension.to_string_lossy())
        } else {
            format!("image_{}", self.images.len())
        };

        self.images.insert(file.into_owned(), dest_file.clone());
        Cow::Owned(dest_file)
    }

    /// Returns an iterator the the images files mapping
    pub fn images_mapping(&self) -> &HashMap<String,String> {
        &self.images
    }

    /// Add a match between an original file and a dest file
    pub fn add_link(&mut self, from: String, to: String) {
        self.links.insert(from, to);
    }

    /// Get a destination link from an original link
    pub fn get_link<'a>(&'a self, from: &'a str) -> &'a str {
        if let Some(link) = self.links.get(from) {
            link
        } else {
            self.logger.warning(format!("Resources: could not find a in-book match for link {}", from));
            from
        }
    }

    /// Tell whether a file name is a local resource or net
    pub fn is_local(path: &str) -> bool{
        !path.contains("://") // todo: use better algorithm
    }

    /// Add a path offset to all linked urls and images src
    pub fn add_offset(link_offset: &Path, image_offset: &Path, ast: &mut [Token]) {
        if link_offset == Path::new("") && image_offset == Path::new("") {
            //nothing do to
            return;
        }
        for mut token in ast {
            match *token {
                Token::Link(ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", link_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                },
                Token::Image (ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", image_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                },
                _ => {
                    if let Some(ref mut inner) = token.inner_mut() {
                            Self::add_offset(link_offset, image_offset, inner);
                    }
                }
            }
        }
    }

    /// Get the list of all files, walking recursively in directories
    ///
    /// # Arguments
    /// - list: a list of files
    /// - base: the path where to get them
    ///
    /// # Returns
    /// A list of files (relative to `base`), or an error.
    pub fn get_files(list: Vec<String>, base: &str) -> Result<Vec<String>> {
        let mut out:Vec<String> = vec!();
        let base = Path::new(base);
        for path in list.into_iter() {
            let abs_path = base.join(&path);
            let res= fs::metadata(&abs_path);
            match res {
                Err(err) => return Err(Error::Render(format!("error reading file {}: {}", abs_path.display(), err))),
                Ok(metadata) => {
                    if metadata.is_file() {
                        out.push(path);
                    } else if metadata.is_dir() {
                        let files = WalkDir::new(&abs_path)
                            .follow_links(true)
                            .into_iter()
                            .filter_map(|e| e.ok())
                            .filter(|e| e.file_type().is_file())
                            .map(|e| PathBuf::from(e.path().strip_prefix(base)
                                                   .unwrap()));
                        for file in files {
                            out.push(file.to_string_lossy().into_owned());
                        }
                    } else {
                        return Err(Error::Render(format!("error in epub rendering: {} is neither a file nor a directory", &path)));
                    }
                }
            }
        }
        Ok(out)
    }
}
<commit_msg>Fix ResourceHandler mapping image path for files w/o extensions<commit_after>use token::Token;
use logger::Logger;
use error::{Error, Result};

use std::collections::HashMap;
use std::path::{Path,PathBuf};
use std::borrow::Cow;
use std::fs;

use walkdir::WalkDir;

/// Resource Handler.
///
/// Its task is to make sure that some resource (image, link) is available
/// for the book and to list images used in Markdown files so they can be used for the book
#[derive(Debug)]
pub struct ResourceHandler<'r> {
    /// Maps an original url (e.g.) "foo/Readme.md" to a valid link
    /// (e.g.) chapter3.html
    links: HashMap<String, String>,
    /// Maps an original (local) file name to a new file name. Allows to
    // make sure all image files will be included in e.g. the Epub document.
    pub images: HashMap<String, String>,
    map_images: bool,
    logger: &'r Logger,
    base64: bool,
}

impl<'r> ResourceHandler<'r> {
    /// Creates a new, empty Resource Handler
    pub fn new(logger: &'r Logger) -> ResourceHandler {
        ResourceHandler {
            links: HashMap::new(),
            images: HashMap::new(),
            map_images: false,
            base64: false,
            logger: logger,
        }
    }

    /// Turns on mapping for image files
    ///
    /// # Argument: an offset (should be book.root)
    pub fn set_images_mapping(&mut self, b: bool) {
        self.map_images = b;
    }

    /// Add a local image file and get the resulting transformed
    /// file name
    pub fn map_image<'a>(&'a mut self, file: Cow<'a, str>) -> Cow<'a, str> {
        // if image mapping is not activated, do nothing
        if !self.map_images {
            return file;
        }

        // If image is not local, do nothing either
        if !Self::is_local(file.as_ref()) {
            self.logger.warning("Resources: book includes non-local images which might cause problem for proper inclusion.");
            return file;
        }

        // If this image has already been registered, returns it
        if self.images.contains_key(file.as_ref()) {
            return Cow::Borrowed(self.images.get(file.as_ref()).unwrap());
        }

        // Else, create a new file name that has same extension
        let dest_file = if let Some(extension) = Path::new(file.as_ref()).extension() {
            format!("images/image_{}.{}", self.images.len(), extension.to_string_lossy())
        } else {
            format!("images/image_{}", self.images.len())
        };

        self.images.insert(file.into_owned(), dest_file.clone());
        Cow::Owned(dest_file)
    }

    /// Returns an iterator the the images files mapping
    pub fn images_mapping(&self) -> &HashMap<String,String> {
        &self.images
    }

    /// Add a match between an original file and a dest file
    pub fn add_link(&mut self, from: String, to: String) {
        self.links.insert(from, to);
    }

    /// Get a destination link from an original link
    pub fn get_link<'a>(&'a self, from: &'a str) -> &'a str {
        if let Some(link) = self.links.get(from) {
            link
        } else {
            self.logger.warning(format!("Resources: could not find a in-book match for link {}", from));
            from
        }
    }

    /// Tell whether a file name is a local resource or net
    pub fn is_local(path: &str) -> bool{
        !path.contains("://") // todo: use better algorithm
    }

    /// Add a path offset to all linked urls and images src
    pub fn add_offset(link_offset: &Path, image_offset: &Path, ast: &mut [Token]) {
        if link_offset == Path::new("") && image_offset == Path::new("") {
            //nothing do to
            return;
        }
        for mut token in ast {
            match *token {
                Token::Link(ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", link_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                },
                Token::Image (ref mut url, _, ref mut v) => {
                    if ResourceHandler::is_local(url) {
                        let new_url = format!("{}", image_offset.join(&url).display());
                        *url = new_url;
                    }
                    Self::add_offset(link_offset, image_offset, v);
                },
                _ => {
                    if let Some(ref mut inner) = token.inner_mut() {
                            Self::add_offset(link_offset, image_offset, inner);
                    }
                }
            }
        }
    }

    /// Get the list of all files, walking recursively in directories
    ///
    /// # Arguments
    /// - list: a list of files
    /// - base: the path where to get them
    ///
    /// # Returns
    /// A list of files (relative to `base`), or an error.
    pub fn get_files(list: Vec<String>, base: &str) -> Result<Vec<String>> {
        let mut out:Vec<String> = vec!();
        let base = Path::new(base);
        for path in list.into_iter() {
            let abs_path = base.join(&path);
            let res= fs::metadata(&abs_path);
            match res {
                Err(err) => return Err(Error::Render(format!("error reading file {}: {}", abs_path.display(), err))),
                Ok(metadata) => {
                    if metadata.is_file() {
                        out.push(path);
                    } else if metadata.is_dir() {
                        let files = WalkDir::new(&abs_path)
                            .follow_links(true)
                            .into_iter()
                            .filter_map(|e| e.ok())
                            .filter(|e| e.file_type().is_file())
                            .map(|e| PathBuf::from(e.path().strip_prefix(base)
                                                   .unwrap()));
                        for file in files {
                            out.push(file.to_string_lossy().into_owned());
                        }
                    } else {
                        return Err(Error::Render(format!("error in epub rendering: {} is neither a file nor a directory", &path)));
                    }
                }
            }
        }
        Ok(out)
    }
}
<|endoftext|>