<commit_before>use counters::Counters;
use mysql;
use query::{self, event};
use std::sync::Arc;
use transaction::Transaction;
use utils;
use worker::{ApproveVec, Error, Result, SolidateVec};

const NULL_HASH: &str = "999999999999999999999999999999999999999999999999999999999999999999999999999999999";

pub struct Write {
  conn: mysql::Conn,
  counters: Arc<Counters>,
}

impl Write {
  pub fn new(mysql_uri: &str, counters: Arc<Counters>) -> Result<Self> {
    let conn = mysql::Conn::new(mysql_uri)?;
    Ok(Self { conn, counters })
  }

  pub fn perform(
    &mut self,
    transaction: &Transaction,
    verbose: bool,
    thread_number: usize,
  ) -> Result<(Option<ApproveVec>, Option<SolidateVec>)> {
    loop {
      let mut conn = self.conn.start_transaction(
        true,
        Some(mysql::IsolationLevel::RepeatableRead),
        Some(false),
      )?;
      match transaction_block(&mut conn, &self.counters, transaction) {
        Ok(data) => {
          conn.commit()?;
          return Ok(data);
        }
        Err(
          Error::Query(query::Error::Mysql(mysql::Error::MySqlError(ref err))),
        ) if err.code == 1213 => {
          if verbose {
            println!("[w#{}] Found a conflict; retrying", thread_number);
          }
          continue;
        }
        Err(err) => return Err(err),
      }
    }
  }
}

fn transaction_block(
  conn: &mut mysql::Transaction,
  counters: &Counters,
  transaction: &Transaction,
) -> Result<(Option<ApproveVec>, Option<SolidateVec>)> {
  let (current_tx, trunk_tx, branch_tx) = query::find_transactions(
    conn,
    transaction.hash(),
    transaction.trunk_hash(),
    transaction.branch_hash(),
  )?;
  if let Some(ref record) = current_tx {
    if record.id_trunk != 0 && record.id_branch != 0 {
      return Ok((None, None));
    }
  }
  let timestamp = utils::milliseconds_since_epoch()?;
  let trunk_tx =
    check_parent(conn, counters, trunk_tx, transaction.trunk_hash())?;
  let branch_tx = if transaction.branch_hash() != transaction.trunk_hash() {
    check_parent(conn, counters, branch_tx, transaction.branch_hash())?
  } else {
    trunk_tx.clone()
  };
  let id_address =
    query::fetch_address(conn, counters, transaction.address_hash())?;
  let id_bundle = query::fetch_bundle(
    conn,
    counters,
    timestamp,
    transaction.bundle_hash(),
    transaction.last_index(),
  )?;
  let mut solid = transaction.solid();
  let height = if solid != 0b11 && trunk_tx.solid == 0b11 {
    trunk_tx.height + 1
  } else {
    0
  };
  if trunk_tx.solid == 0b11 {
    solid |= 0b10;
  }
  if branch_tx.solid == 0b11 {
    solid |= 0b01;
  }
  let record = query::UpsertTransactionRecord {
    hash: transaction.hash(),
    tag: transaction.tag(),
    value: transaction.value(),
    timestamp: transaction.timestamp(),
    current_idx: transaction.current_index(),
    last_idx: transaction.last_index(),
    is_mst: transaction.is_milestone(),
    mst_a: transaction.is_milestone(),
    id_trunk: trunk_tx.id_tx,
    id_branch: branch_tx.id_tx,
    id_address,
    id_bundle,
    height,
    solid,
  };
  if current_tx.is_none() {
    query::insert_transaction(conn, counters, &record)?;
  } else {
    query::update_transaction(conn, &record)?;
  }
  if solid != 0b11 {
    event::unsolid_transaction(conn, timestamp)?;
  }
  event::new_transaction_received(conn, timestamp)?;
  let approve_data = if transaction.is_milestone() {
    event::milestone_received(conn, timestamp)?;
    Some(vec![trunk_tx.id_tx, branch_tx.id_tx])
  } else {
    None
  };
  let solidate_data = current_tx.and_then(|current_tx| if solid == 0b11 {
    Some(vec![(current_tx.id_tx, Some(height))])
  } else {
    None
  });
  Ok((approve_data, solidate_data))
}

fn check_parent(
  conn: &mut mysql::Transaction,
  counters: &Counters,
  transaction: Option<query::FindTransactionsResult>,
  hash: &str,
) -> Result<query::FindTransactionsResult> {
  match transaction {
    Some(record) => {
      let id_tx = record.id_tx;
      query::direct_approve_transaction(conn, id_tx)?;
      Ok(record)
    }
    None => {
      let (height, solid) = (0, if hash == NULL_HASH { 0b11 } else { 0b00 });
      let id_tx = query::insert_transaction_placeholder(
        conn,
        counters,
        hash,
        height,
        solid,
      )?;
      Ok(query::FindTransactionsResult {
        id_tx,
        height,
        solid,
        id_trunk: 0,
        id_branch: 0,
      })
    }
  }
}
<commit_msg>Ignore genesis tx<commit_after>use counters::Counters;
use mysql;
use query::{self, event};
use std::sync::Arc;
use transaction::Transaction;
use utils;
use worker::{ApproveVec, Error, Result, SolidateVec};

const NULL_HASH: &str = "999999999999999999999999999999999999999999999999999999999999999999999999999999999";

pub struct Write {
  conn: mysql::Conn,
  counters: Arc<Counters>,
}

impl Write {
  pub fn new(mysql_uri: &str, counters: Arc<Counters>) -> Result<Self> {
    let conn = mysql::Conn::new(mysql_uri)?;
    Ok(Self { conn, counters })
  }

  pub fn perform(
    &mut self,
    transaction: &Transaction,
    verbose: bool,
    thread_number: usize,
  ) -> Result<(Option<ApproveVec>, Option<SolidateVec>)> {
    loop {
      let mut conn = self.conn.start_transaction(
        true,
        Some(mysql::IsolationLevel::RepeatableRead),
        Some(false),
      )?;
      match transaction_block(&mut conn, &self.counters, transaction) {
        Ok(data) => {
          conn.commit()?;
          return Ok(data);
        }
        Err(
          Error::Query(query::Error::Mysql(mysql::Error::MySqlError(ref err))),
        ) if err.code == 1213 => {
          if verbose {
            println!("[w#{}] Found a conflict; retrying", thread_number);
          }
          continue;
        }
        Err(err) => return Err(err),
      }
    }
  }
}

fn transaction_block(
  conn: &mut mysql::Transaction,
  counters: &Counters,
  transaction: &Transaction,
) -> Result<(Option<ApproveVec>, Option<SolidateVec>)> {
  if transaction.hash() == NULL_HASH {
    return Ok((None, None));
  }
  let (current_tx, trunk_tx, branch_tx) = query::find_transactions(
    conn,
    transaction.hash(),
    transaction.trunk_hash(),
    transaction.branch_hash(),
  )?;
  if let Some(ref record) = current_tx {
    if record.id_trunk != 0 && record.id_branch != 0 {
      return Ok((None, None));
    }
  }
  let timestamp = utils::milliseconds_since_epoch()?;
  let trunk_tx =
    check_parent(conn, counters, trunk_tx, transaction.trunk_hash())?;
  let branch_tx = if transaction.branch_hash() != transaction.trunk_hash() {
    check_parent(conn, counters, branch_tx, transaction.branch_hash())?
  } else {
    trunk_tx.clone()
  };
  let id_address =
    query::fetch_address(conn, counters, transaction.address_hash())?;
  let id_bundle = query::fetch_bundle(
    conn,
    counters,
    timestamp,
    transaction.bundle_hash(),
    transaction.last_index(),
  )?;
  let mut solid = transaction.solid();
  let height = if solid != 0b11 && trunk_tx.solid == 0b11 {
    trunk_tx.height + 1
  } else {
    0
  };
  if trunk_tx.solid == 0b11 {
    solid |= 0b10;
  }
  if branch_tx.solid == 0b11 {
    solid |= 0b01;
  }
  let record = query::UpsertTransactionRecord {
    hash: transaction.hash(),
    tag: transaction.tag(),
    value: transaction.value(),
    timestamp: transaction.timestamp(),
    current_idx: transaction.current_index(),
    last_idx: transaction.last_index(),
    is_mst: transaction.is_milestone(),
    mst_a: transaction.is_milestone(),
    id_trunk: trunk_tx.id_tx,
    id_branch: branch_tx.id_tx,
    id_address,
    id_bundle,
    height,
    solid,
  };
  if current_tx.is_none() {
    query::insert_transaction(conn, counters, &record)?;
  } else {
    query::update_transaction(conn, &record)?;
  }
  if solid != 0b11 {
    event::unsolid_transaction(conn, timestamp)?;
  }
  event::new_transaction_received(conn, timestamp)?;
  let approve_data = if transaction.is_milestone() {
    event::milestone_received(conn, timestamp)?;
    Some(vec![trunk_tx.id_tx, branch_tx.id_tx])
  } else {
    None
  };
  let solidate_data = current_tx.and_then(|current_tx| if solid == 0b11 {
    Some(vec![(current_tx.id_tx, Some(height))])
  } else {
    None
  });
  Ok((approve_data, solidate_data))
}

fn check_parent(
  conn: &mut mysql::Transaction,
  counters: &Counters,
  transaction: Option<query::FindTransactionsResult>,
  hash: &str,
) -> Result<query::FindTransactionsResult> {
  match transaction {
    Some(record) => {
      let id_tx = record.id_tx;
      query::direct_approve_transaction(conn, id_tx)?;
      Ok(record)
    }
    None => {
      let (height, solid) = (0, if hash == NULL_HASH { 0b11 } else { 0b00 });
      let id_tx = query::insert_transaction_placeholder(
        conn,
        counters,
        hash,
        height,
        solid,
      )?;
      Ok(query::FindTransactionsResult {
        id_tx,
        height,
        solid,
        id_trunk: 0,
        id_branch: 0,
      })
    }
  }
}
<|endoftext|>


<commit_before>// See LICENSE file for copyright and license details.

#![feature(old_io, old_path, env)]

extern crate gl_generator;
extern crate khronos_api;

#[cfg(target_os = "windows")]
const GENERATOR: gl_generator::StructGenerator = gl_generator::StructGenerator;

#[cfg(not(target_os = "windows"))]
const GENERATOR: gl_generator::StaticStructGenerator = gl_generator::StaticStructGenerator;

fn main() {
    let dest = Path::new(std::env::var("OUT_DIR").unwrap());
    let mut file = std::old_io::File::create(&dest.join("gl_bindings.rs")).unwrap();
    gl_generator::generate_bindings(
        GENERATOR,
        gl_generator::registry::Ns::Gles2,
        gl_generator::Fallbacks::None,
        khronos_api::GL_XML,
        vec![],
        "2.0",
        "core",
        &mut file,
    ).unwrap();
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<commit_msg>Fixed #67: Removed 'feature(old)'<commit_after>// See LICENSE file for copyright and license details.

#![feature(old_io, old_path)]

extern crate gl_generator;
extern crate khronos_api;

#[cfg(target_os = "windows")]
const GENERATOR: gl_generator::StructGenerator = gl_generator::StructGenerator;

#[cfg(not(target_os = "windows"))]
const GENERATOR: gl_generator::StaticStructGenerator = gl_generator::StaticStructGenerator;

fn main() {
    let dest = Path::new(std::env::var("OUT_DIR").unwrap());
    let mut file = std::old_io::File::create(&dest.join("gl_bindings.rs")).unwrap();
    gl_generator::generate_bindings(
        GENERATOR,
        gl_generator::registry::Ns::Gles2,
        gl_generator::Fallbacks::None,
        khronos_api::GL_XML,
        vec![],
        "2.0",
        "core",
        &mut file,
    ).unwrap();
}

// vim: set tabstop=4 shiftwidth=4 softtabstop=4 expandtab:
<|endoftext|>


<commit_before>//! Defines `Module` and `Function` that act as containers.

use std::fmt::Debug;
use std::hash::Hash;
use std::collections::{HashMap, BTreeSet};
use petgraph::graph::NodeIndex;

use frontend::source::Source;
use middle::ssa::ssastorage::SSAStorage;

#[derive(Clone, Debug)]
pub struct RadecoModule {
    functions: HashMap<u64, RadecoFunction>,
}

#[derive(Clone, Debug)]
pub struct RadecoFunction {
    ssa: SSAStorage,
    call_ctx: Vec<CallContext>,
    callrefs: BTreeSet<u64>,
    callxrefs: BTreeSet<u64>,
}

impl Default for RadecoFunction {
    fn default() -> RadecoFunction {
        RadecoFunction {
            ssa: SSAStorage::new(),
            call_ctx: Vec::new(),
            callrefs: BTreeSet::new(),
            callxrefs: BTreeSet::new(),
        }
    }
}

impl RadecoFunction {
    fn new() -> RadecoFunction {
        RadecoFunction {
            ssa: SSAStorage::new(),
            call_ctx: Vec::new(),
            callrefs: BTreeSet::new(),
            callxrefs: BTreeSet::new(),
        }
    }
}

#[derive(Clone, Debug)]
pub struct CallContext {
    /// Start offset of caller (uniquely identifies a function).
    caller: u64,
    /// Start offset of callee (uniquely identifies a function).
    callee: u64,
    /// Translate a node in callees context into a node in caller's context.
    ctx_translate: HashMap<NodeIndex, NodeIndex>,
}

// From trait to construct a module from `Source`.
// Note that this conversion is expensive as the source is used to construct the SSA for all the
// function that it holds and perform basic analysis.
impl<'a, T: 'a + Source> From<&'a mut T> for RadecoModule {
    fn from(source: &'a mut T) -> RadecoModule {
        unimplemented!()
    }
}

impl RadecoModule {
    fn construct<S: Source>(source: &mut S) -> RadecoModule {
        unimplemented!()
    }
}

pub trait RFunction { }
pub trait RModule {
    type FnRef: Copy + Clone + Debug + Hash + Eq;

    fn callees_of(&self, &Self::FnRef) -> Vec<Self::FnRef>;
    fn callers_of(&self, &Self::FnRef) -> Vec<Self::FnRef>;
    fn functions(&self) -> Vec<Self::FnRef>;
}
<commit_msg>First complete implementation of module<commit_after>//! Defines `Module` and `Function` that act as containers.

use std::fmt::Debug;
use std::hash::Hash;
use std::collections::{BTreeSet, HashMap};

use r2pipe::structs::{LOpInfo, LRegInfo};

use petgraph::graph::NodeIndex;

use frontend::source::Source;
use frontend::ssaconstructor::SSAConstruct;
use middle::ssa::ssastorage::SSAStorage;

#[derive(Clone, Debug, Default)]
pub struct RadecoModule {
    functions: HashMap<u64, RadecoFunction>,
    fname: HashMap<String, u64>,
}

#[derive(Clone, Debug)]
pub struct RadecoFunction {
    ssa: SSAStorage,
    name: String,
    call_ctx: Vec<CallContext>,
    callrefs: BTreeSet<u64>,
    callxrefs: BTreeSet<u64>,
}

impl Default for RadecoFunction {
    fn default() -> RadecoFunction {
        RadecoFunction {
            ssa: SSAStorage::new(),
            call_ctx: Vec::new(),
            callrefs: BTreeSet::new(),
            callxrefs: BTreeSet::new(),
            name: String::new(),
        }
    }
}

impl RadecoFunction {
    fn new() -> RadecoFunction {
        RadecoFunction::default()
    }

    pub fn construct(reg_profile: &LRegInfo, insts: Vec<LOpInfo>) -> RadecoFunction {
        let mut rfn = RadecoFunction::default();
        {
            let mut constructor = SSAConstruct::new(&mut rfn.ssa, &reg_profile);
            constructor.run(insts);
        }
        rfn
    }
}

#[derive(Clone, Debug)]
pub struct CallContext {
    /// Start offset of caller (uniquely identifies a function).
    caller: u64,
    /// Start offset of callee (uniquely identifies a function).
    callee: u64,
    /// Offset the call. Note that this will belong to the caller function.
    call_site: u64,
    /// Translate a node in callees context into a node in caller's context.
    ctx_translate: HashMap<NodeIndex, NodeIndex>,
}

impl CallContext {
    pub fn new(caller: u64, callee: u64, call_site: u64) -> CallContext {
        CallContext {
            caller: caller,
            callee: callee,
            call_site: call_site,
            ctx_translate: HashMap::new(),
        }
    }
}

// From trait to construct a module from `Source`.
// Note that this conversion is expensive as the source is used to construct
// the SSA for all the
// function that it holds and perform basic analysis.
impl<'a, T: 'a + Source> From<&'a mut T> for RadecoModule {
    fn from(source: &'a mut T) -> RadecoModule {
        let reg_info = source.register_profile();
        let mut rmod = RadecoModule::default();
        for f in source.functions() {
            // TODO: Thread this part.
            if f.name.as_ref().unwrap().contains("imp") {
                continue
            }

            let offset = f.offset.expect("Invalid offset");
            let instructions = source.instructions_at(offset);
            let mut rfn = RadecoFunction::construct(&reg_info, instructions);
            rfn.name = f.name.as_ref().unwrap().clone();
            if let Some(ref callrefs) = f.callrefs {
                rfn.callrefs = callrefs.iter()
                                       .filter(|x| {
                                           match x.call_type {
                                               Some(ref c) if c == "C" => true,
                                               _ => false,
                                           }
                                       })
                                       .map(|x| x.addr.expect("Invalid address"))
                                       .collect::<BTreeSet<_>>();
            }

            if let Some(ref callxrefs) = f.codexrefs {
                rfn.callxrefs = callxrefs.iter()
                                       .filter(|x| {
                                           match x.call_type {
                                               Some(ref c) if c == "C" => true,
                                               _ => false,
                                           }
                                       })
                                       .map(|x| x.addr.expect("Invalid address"))
                                       .collect::<BTreeSet<_>>();
            }

            rmod.functions.insert(offset, rfn);
            rmod.fname.insert(f.name.unwrap(), offset);
        }
        rmod
    }
}

impl RadecoModule {
    fn construct<S: Source>(mut source: S) -> RadecoModule {
        RadecoModule::from(&mut source)
    }
}

pub trait RFunction { }
pub trait RModule {
    type FnRef: Copy + Clone + Debug + Hash + Eq;

    fn callees_of(&self, &Self::FnRef) -> Vec<Self::FnRef>;
    fn callers_of(&self, &Self::FnRef) -> Vec<Self::FnRef>;
    fn functions(&self) -> Vec<Self::FnRef>;
    fn function_by_ref(&self, &Self::FnRef) -> Box<&RFunction>;
}

#[cfg(test)]
mod test {
    use super::*;
    use r2pipe::r2::R2;
    use frontend::source::Source;
    use middle::ir_writer::IRWriter;
    use std::io;
    use middle::dce;

    #[test]
    fn module_test() {
        let mut r2 = R2::open(Some("./crowell_example.o")).expect("Failed to open r2");
        r2.init();
        let mut rmod = RadecoModule::from(&mut r2);
        for (ref addr, ref mut rfn) in rmod.functions.iter_mut() {
            {
                dce::collect(&mut rfn.ssa);
            }
            let mut writer: IRWriter = Default::default();
            writer.emit_il(Some(rfn.name.clone()), &rfn.ssa, &mut io::stdout());
        }
    }
}
<|endoftext|>


<commit_before>extern crate undo;

use undo::{UndoCmd, UndoStack};

#[derive(Debug)]
struct TxtCmd(char);

impl UndoCmd for TxtCmd {
    type Err = ();

    fn redo(&mut self) -> undo::Result<()> {
        Ok(())
    }

    fn undo(&mut self) -> undo::Result<()> {
        Ok(())
    }

    fn id(&self) -> Option<u64> {
        if self.0 == ' ' { None } else { Some(1) }
    }
}

fn foo() -> undo::Result<()> {
    let mut stack = UndoStack::new();
    stack.push(TxtCmd('a'))?;
    stack.push(TxtCmd('b'))?; // 'a' and 'b' is merged.
    stack.push(TxtCmd(' '))?;
    stack.push(TxtCmd('c'))?;
    stack.push(TxtCmd('d'))?; // 'c' and 'd' is merged.

    println!("{:#?}", stack);
    Ok(())
}

fn main() {
    foo().unwrap();
}
<commit_msg>Remove merge example<commit_after><|endoftext|>


<commit_before>// Copyright (c) 2016 The Rouille developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Low-level parsing of websocket frames.
//!
//! Usage:
//!
//! - Create a `StateMachine` with `StateMachine::new`.
//! - Whenever data is received on the socket, call `StateMachine::feed`.
//! - The returned iterator produces zero, one or multiple `Element` objects containing what was
//!   received.
//! - For `Element::Data`, the `Data` object is an iterator over the decoded bytes.
//! - If `Element::Error` is produced, immediately end the connection.
//!
//! Glossary:
//!
//! - A websocket stream is made of multiple *messages*.
//! - Each message is made of one or more *frames*. See https://tools.ietf.org/html/rfc6455#section-5.4.
//! - Each frame can be received progressively, where each packet is an `Element` object (below).

/// A websocket element decoded from the data given to `StateMachine::feed`.
#[derive(Debug, PartialEq, Eq)]
pub enum Element<'a> {
    /// A new frame has started.
    FrameStart {
        /// If true, this is the last frame of the message.
        fin: bool,
        /// Length of the frame in bytes.
        length: u64,
        /// Opcode. See https://tools.ietf.org/html/rfc6455#section-5.2.
        opcode: u8,
    },

    /// Data was received as part of the current frame.
    Data {
        /// The decoded data. An iterator that produces `u8`s.
        data: Data<'a>,
        /// If true, this is the last packet in the frame.
        last_in_frame: bool,
    },

    /// An error in the stream. The connection must be dropped ASAP.
    Error {
        /// A description of the error. Can or cannot be be returned to the client.
        desc: &'static str
    },
}

/// Decoded data. Implements `Iterator<Item = u8>`.
#[derive(Debug, PartialEq, Eq)]
pub struct Data<'a> {
    // Source data. Undecoded.
    data: &'a [u8],
    // Copy of the mask of the current frame.
    mask: u32,
    // Same as `StateMachineInner::InData::offset`. Updated at each iteration.
    offset: u8,
}

/// A websocket state machine. Contains partial data.
pub struct StateMachine {
    // Actual state.
    inner: StateMachineInner,
    // Contains the start of the header. Must be empty if `inner` is equal to `InData`.
    buffer: Vec<u8>,        // TODO: use SmallVec?
}

enum StateMachineInner {
    // If `StateMachine::inner` is `InHeader`, then `buffer` contains the start of the header.
    InHeader,
    // If `StateMachine::inner` is `InData`, then `buffer` must be empty.
    InData {
        // Mask to decode the message.
        mask: u32,
        // Value between 0 and 3 that indicates the number of bytes between the start of the data
        // and the next expected byte.
        offset: u8,
        // Number of bytes remaining in the frame.
        remaining_len: u64,
    }
}

impl StateMachine {
    /// Initializes a new state machine for a new stream. Expects to see a new frame as the first
    /// packet.
    pub fn new() -> StateMachine {
        StateMachine {
            inner: StateMachineInner::InHeader,
            buffer: Vec::with_capacity(14),
        }
    }

    /// Feeds data to the state machine. Returns an iterator to the list of elements that were
    /// received.
    #[inline]
    pub fn feed<'a>(&'a mut self, data: &'a [u8]) -> ElementsIter<'a> {
        ElementsIter {
            state: self,
            data: data,
        }
    }
}

/// Iterator to the list of elements that were received.
pub struct ElementsIter<'a> {
    state: &'a mut StateMachine,
    data: &'a [u8],
}

impl<'a> Iterator for ElementsIter<'a> {
    type Item = Element<'a>;

    fn next(&mut self) -> Option<Element<'a>> {
        if self.data.is_empty() {
            return None;
        }

        match self.state.inner {
            // First situation, we are in the header.
            StateMachineInner::InHeader => {
                // We need at least 6 bytes for a succesful header. Otherwise we just return.
                let total_buffered = self.state.buffer.len() + self.data.len();
                if total_buffered < 6 {
                    self.state.buffer.extend_from_slice(self.data);
                    self.data = &[];
                    return None;
                }

                // Retreive the first two bytes of the header.
                let (first_byte, second_byte) = {
                    let mut mask_iter = self.state.buffer.iter().chain(self.data.iter());
                    let first_byte = *mask_iter.next().unwrap();
                    let second_byte = *mask_iter.next().unwrap();
                    (first_byte, second_byte)
                };

                // Reserved bits must be zero, otherwise error.
                if (first_byte & 0x70) != 0 {
                    return Some(Element::Error {
                        desc: "Reserved bits must be zero"
                    });
                }

                // Client-to-server messages **must** be encoded.
                if (second_byte & 0x80) == 0 {
                    return Some(Element::Error {
                        desc: "Client-to-server messages must be masked"
                    });
                }

                // Find the length of the frame and the mask.
                let (length, mask) = match second_byte & 0x7f {
                    126 => {
                        if total_buffered < 8 {
                            self.state.buffer.extend_from_slice(self.data);
                            self.data = &[];
                            return None;
                        }

                        let mut mask_iter = self.state.buffer.iter().chain(self.data.iter()).skip(2);

                        let length = {
                            let a = *mask_iter.next().unwrap() as u64;
                            let b = *mask_iter.next().unwrap() as u64;
                            (a << 8) | (b << 0)
                        };

                        let mask = {
                            let a = *mask_iter.next().unwrap() as u32;
                            let b = *mask_iter.next().unwrap() as u32;
                            let c = *mask_iter.next().unwrap() as u32;
                            let d = *mask_iter.next().unwrap() as u32;
                            (a << 24) | (b << 16) | (c << 8) | (d << 0)
                        };

                        (length, mask)
                    },
                    127 => {
                        if total_buffered < 8 {
                            self.state.buffer.extend_from_slice(self.data);
                            self.data = &[];
                            return None;
                        }

                        let mut mask_iter = self.state.buffer.iter().chain(self.data.iter()).skip(2);

                        let length = {
                            let a = *mask_iter.next().unwrap() as u64;
                            let b = *mask_iter.next().unwrap() as u64;
                            let c = *mask_iter.next().unwrap() as u64;
                            let d = *mask_iter.next().unwrap() as u64;
                            let e = *mask_iter.next().unwrap() as u64;
                            let f = *mask_iter.next().unwrap() as u64;
                            let g = *mask_iter.next().unwrap() as u64;
                            let h = *mask_iter.next().unwrap() as u64;

                            // The most significant bit must be zero according to the specs.
                            if (a & 0x80) != 0 {
                                return Some(Element::Error {
                                    desc: "Most-significant bit of the length must be zero"
                                });
                            }

                            (a << 56) | (b << 48) | (c << 40) | (d << 32) |
                                (e << 24) | (f << 16) | (g << 8) | (h << 0)
                        };

                        let mask = {
                            let a = *mask_iter.next().unwrap() as u32;
                            let b = *mask_iter.next().unwrap() as u32;
                            let c = *mask_iter.next().unwrap() as u32;
                            let d = *mask_iter.next().unwrap() as u32;
                            (a << 24) | (b << 16) | (c << 8) | (d << 0)
                        };

                        (length, mask)
                    },
                    n => {
                        let mut mask_iter = self.state.buffer.iter().chain(self.data.iter()).skip(2);

                        let mask = {
                            let a = *mask_iter.next().unwrap() as u32;
                            let b = *mask_iter.next().unwrap() as u32;
                            let c = *mask_iter.next().unwrap() as u32;
                            let d = *mask_iter.next().unwrap() as u32;
                            (a << 24) | (b << 16) | (c << 8) | (d << 0)
                        };

                        (n as u64, mask)
                    },
                };

                // Builds a slice containing the start of the data.
                let data_start = {
                    let data_start_off = match second_byte & 0x7f {
                        126 => 8,
                        127 => 14,
                        _ => 6
                    };

                    assert!(self.state.buffer.len() < data_start_off);
                    &self.data[(data_start_off - self.state.buffer.len()) ..]
                };

                // Update ourselves for the next loop and return a FrameStart message.
                self.data = data_start;
                self.state.buffer.clear();
                self.state.inner = StateMachineInner::InData { mask: mask, remaining_len: length,
                                                               offset: 0 };
                Some(Element::FrameStart {
                    fin: (first_byte & 0x80) != 0,
                    length: length,
                    opcode: first_byte & 0xf,
                })
            },

            // Second situation, we are in the message and we don't have enough data to finish the
            // current frame.
            StateMachineInner::InData { mask, ref mut remaining_len, ref mut offset }
                if *remaining_len > self.data.len() as u64 =>
            {
                let data = Data {
                    data: self.data,
                    mask: mask,
                    offset: *offset,
                };

                *offset += (self.data.len() % 4) as u8;
                *offset %= 4;
                *remaining_len -= self.data.len() as u64;

                self.data = &[];

                Some(Element::Data { data: data, last_in_frame: false })
            },

            // Third situation, we have enough data to finish the frame.
            StateMachineInner::InData { mask, remaining_len, offset } => {
                debug_assert!(self.data.len() as u64 >= remaining_len);

                let data = Data {
                    data: &self.data[0 .. remaining_len as usize],
                    mask: mask,
                    offset: offset,
                };

                self.data = &self.data[remaining_len as usize ..];
                self.state.inner = StateMachineInner::InHeader;
                debug_assert!(self.state.buffer.is_empty());

                Some(Element::Data { data: data, last_in_frame: true })
            },
        }
    }
}

impl<'a> Iterator for Data<'a> {
    type Item = u8;

    #[inline]
    fn next(&mut self) -> Option<u8> {
        if self.data.is_empty() {
            return None;
        }

        let byte = self.data[0];
        let mask = ((self.mask >> (3 - self.offset) * 8) & 0xff) as u8;
        let decoded = byte ^ mask;

        self.data = &self.data[1..];
        self.offset = (self.offset + 1) % 4;

        Some(decoded)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let l = self.data.len();
        (l, Some(l))
    }
}

impl<'a> ExactSizeIterator for Data<'a> {
}

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

    #[test]
    fn basic() {
        let mut machine = StateMachine::new();

        let data = &[0x81, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58];
        let mut iter = machine.feed(data);

        assert_eq!(iter.next().unwrap(), Element::FrameStart {
            fin: true,
            length: 5,
            opcode: 1
        });

        match iter.next().unwrap() {
            Element::Data { data, last_in_frame } => {
                assert!(last_in_frame);
                assert_eq!(data.collect::<Vec<_>>(), b"Hello");
            }
            _ => panic!()
        }
    }
}
<commit_msg>Bugfix in low level websocket parser<commit_after>// Copyright (c) 2016 The Rouille developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.

//! Low-level parsing of websocket frames.
//!
//! Usage:
//!
//! - Create a `StateMachine` with `StateMachine::new`.
//! - Whenever data is received on the socket, call `StateMachine::feed`.
//! - The returned iterator produces zero, one or multiple `Element` objects containing what was
//!   received.
//! - For `Element::Data`, the `Data` object is an iterator over the decoded bytes.
//! - If `Element::Error` is produced, immediately end the connection.
//!
//! Glossary:
//!
//! - A websocket stream is made of multiple *messages*.
//! - Each message is made of one or more *frames*. See https://tools.ietf.org/html/rfc6455#section-5.4.
//! - Each frame can be received progressively, where each packet is an `Element` object (below).

/// A websocket element decoded from the data given to `StateMachine::feed`.
#[derive(Debug, PartialEq, Eq)]
pub enum Element<'a> {
    /// A new frame has started.
    FrameStart {
        /// If true, this is the last frame of the message.
        fin: bool,
        /// Length of the frame in bytes.
        length: u64,
        /// Opcode. See https://tools.ietf.org/html/rfc6455#section-5.2.
        opcode: u8,
    },

    /// Data was received as part of the current frame.
    Data {
        /// The decoded data. An iterator that produces `u8`s.
        data: Data<'a>,
        /// If true, this is the last packet in the frame.
        last_in_frame: bool,
    },

    /// An error in the stream. The connection must be dropped ASAP.
    Error {
        /// A description of the error. Can or cannot be be returned to the client.
        desc: &'static str
    },
}

/// Decoded data. Implements `Iterator<Item = u8>`.
#[derive(Debug, PartialEq, Eq)]
pub struct Data<'a> {
    // Source data. Undecoded.
    data: &'a [u8],
    // Copy of the mask of the current frame.
    mask: u32,
    // Same as `StateMachineInner::InData::offset`. Updated at each iteration.
    offset: u8,
}

/// A websocket state machine. Contains partial data.
pub struct StateMachine {
    // Actual state.
    inner: StateMachineInner,
    // Contains the start of the header. Must be empty if `inner` is equal to `InData`.
    buffer: Vec<u8>,        // TODO: use SmallVec?
}

enum StateMachineInner {
    // If `StateMachine::inner` is `InHeader`, then `buffer` contains the start of the header.
    InHeader,
    // If `StateMachine::inner` is `InData`, then `buffer` must be empty.
    InData {
        // Mask to decode the message.
        mask: u32,
        // Value between 0 and 3 that indicates the number of bytes between the start of the data
        // and the next expected byte.
        offset: u8,
        // Number of bytes remaining in the frame.
        remaining_len: u64,
    }
}

impl StateMachine {
    /// Initializes a new state machine for a new stream. Expects to see a new frame as the first
    /// packet.
    pub fn new() -> StateMachine {
        StateMachine {
            inner: StateMachineInner::InHeader,
            buffer: Vec::with_capacity(14),
        }
    }

    /// Feeds data to the state machine. Returns an iterator to the list of elements that were
    /// received.
    #[inline]
    pub fn feed<'a>(&'a mut self, data: &'a [u8]) -> ElementsIter<'a> {
        ElementsIter {
            state: self,
            data: data,
        }
    }
}

/// Iterator to the list of elements that were received.
pub struct ElementsIter<'a> {
    state: &'a mut StateMachine,
    data: &'a [u8],
}

impl<'a> Iterator for ElementsIter<'a> {
    type Item = Element<'a>;

    fn next(&mut self) -> Option<Element<'a>> {
        if self.data.is_empty() {
            return None;
        }

        match self.state.inner {
            // First situation, we are in the header.
            StateMachineInner::InHeader => {
                // We need at least 6 bytes for a succesful header. Otherwise we just return.
                let total_buffered = self.state.buffer.len() + self.data.len();
                if total_buffered < 6 {
                    self.state.buffer.extend_from_slice(self.data);
                    self.data = &[];
                    return None;
                }

                // Retreive the first two bytes of the header.
                let (first_byte, second_byte) = {
                    let mut mask_iter = self.state.buffer.iter().chain(self.data.iter());
                    let first_byte = *mask_iter.next().unwrap();
                    let second_byte = *mask_iter.next().unwrap();
                    (first_byte, second_byte)
                };

                // Reserved bits must be zero, otherwise error.
                if (first_byte & 0x70) != 0 {
                    return Some(Element::Error {
                        desc: "Reserved bits must be zero"
                    });
                }

                // Client-to-server messages **must** be encoded.
                if (second_byte & 0x80) == 0 {
                    return Some(Element::Error {
                        desc: "Client-to-server messages must be masked"
                    });
                }

                // Find the length of the frame and the mask.
                let (length, mask) = match second_byte & 0x7f {
                    126 => {
                        if total_buffered < 8 {
                            self.state.buffer.extend_from_slice(self.data);
                            self.data = &[];
                            return None;
                        }

                        let mut mask_iter = self.state.buffer.iter().chain(self.data.iter()).skip(2);

                        let length = {
                            let a = *mask_iter.next().unwrap() as u64;
                            let b = *mask_iter.next().unwrap() as u64;
                            (a << 8) | (b << 0)
                        };

                        let mask = {
                            let a = *mask_iter.next().unwrap() as u32;
                            let b = *mask_iter.next().unwrap() as u32;
                            let c = *mask_iter.next().unwrap() as u32;
                            let d = *mask_iter.next().unwrap() as u32;
                            (a << 24) | (b << 16) | (c << 8) | (d << 0)
                        };

                        (length, mask)
                    },
                    127 => {
                        if total_buffered < 14 {
                            self.state.buffer.extend_from_slice(self.data);
                            self.data = &[];
                            return None;
                        }

                        let mut mask_iter = self.state.buffer.iter().chain(self.data.iter()).skip(2);

                        let length = {
                            let a = *mask_iter.next().unwrap() as u64;
                            let b = *mask_iter.next().unwrap() as u64;
                            let c = *mask_iter.next().unwrap() as u64;
                            let d = *mask_iter.next().unwrap() as u64;
                            let e = *mask_iter.next().unwrap() as u64;
                            let f = *mask_iter.next().unwrap() as u64;
                            let g = *mask_iter.next().unwrap() as u64;
                            let h = *mask_iter.next().unwrap() as u64;

                            // The most significant bit must be zero according to the specs.
                            if (a & 0x80) != 0 {
                                return Some(Element::Error {
                                    desc: "Most-significant bit of the length must be zero"
                                });
                            }

                            (a << 56) | (b << 48) | (c << 40) | (d << 32) |
                                (e << 24) | (f << 16) | (g << 8) | (h << 0)
                        };

                        let mask = {
                            let a = *mask_iter.next().unwrap() as u32;
                            let b = *mask_iter.next().unwrap() as u32;
                            let c = *mask_iter.next().unwrap() as u32;
                            let d = *mask_iter.next().unwrap() as u32;
                            (a << 24) | (b << 16) | (c << 8) | (d << 0)
                        };

                        (length, mask)
                    },
                    n => {
                        let mut mask_iter = self.state.buffer.iter().chain(self.data.iter()).skip(2);

                        let mask = {
                            let a = *mask_iter.next().unwrap() as u32;
                            let b = *mask_iter.next().unwrap() as u32;
                            let c = *mask_iter.next().unwrap() as u32;
                            let d = *mask_iter.next().unwrap() as u32;
                            (a << 24) | (b << 16) | (c << 8) | (d << 0)
                        };

                        (n as u64, mask)
                    },
                };

                // Builds a slice containing the start of the data.
                let data_start = {
                    let data_start_off = match second_byte & 0x7f {
                        126 => 8,
                        127 => 14,
                        _ => 6
                    };

                    assert!(self.state.buffer.len() < data_start_off);
                    &self.data[(data_start_off - self.state.buffer.len()) ..]
                };

                // Update ourselves for the next loop and return a FrameStart message.
                self.data = data_start;
                self.state.buffer.clear();
                self.state.inner = StateMachineInner::InData { mask: mask, remaining_len: length,
                                                               offset: 0 };
                Some(Element::FrameStart {
                    fin: (first_byte & 0x80) != 0,
                    length: length,
                    opcode: first_byte & 0xf,
                })
            },

            // Second situation, we are in the message and we don't have enough data to finish the
            // current frame.
            StateMachineInner::InData { mask, ref mut remaining_len, ref mut offset }
                if *remaining_len > self.data.len() as u64 =>
            {
                let data = Data {
                    data: self.data,
                    mask: mask,
                    offset: *offset,
                };

                *offset += (self.data.len() % 4) as u8;
                *offset %= 4;
                *remaining_len -= self.data.len() as u64;

                self.data = &[];

                Some(Element::Data { data: data, last_in_frame: false })
            },

            // Third situation, we have enough data to finish the frame.
            StateMachineInner::InData { mask, remaining_len, offset } => {
                debug_assert!(self.data.len() as u64 >= remaining_len);

                let data = Data {
                    data: &self.data[0 .. remaining_len as usize],
                    mask: mask,
                    offset: offset,
                };

                self.data = &self.data[remaining_len as usize ..];
                self.state.inner = StateMachineInner::InHeader;
                debug_assert!(self.state.buffer.is_empty());

                Some(Element::Data { data: data, last_in_frame: true })
            },
        }
    }
}

impl<'a> Iterator for Data<'a> {
    type Item = u8;

    #[inline]
    fn next(&mut self) -> Option<u8> {
        if self.data.is_empty() {
            return None;
        }

        let byte = self.data[0];
        let mask = ((self.mask >> (3 - self.offset) * 8) & 0xff) as u8;
        let decoded = byte ^ mask;

        self.data = &self.data[1..];
        self.offset = (self.offset + 1) % 4;

        Some(decoded)
    }

    #[inline]
    fn size_hint(&self) -> (usize, Option<usize>) {
        let l = self.data.len();
        (l, Some(l))
    }
}

impl<'a> ExactSizeIterator for Data<'a> {
}

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

    #[test]
    fn basic() {
        let mut machine = StateMachine::new();

        let data = &[0x81, 0x85, 0x37, 0xfa, 0x21, 0x3d, 0x7f, 0x9f, 0x4d, 0x51, 0x58];
        let mut iter = machine.feed(data);

        assert_eq!(iter.next().unwrap(), Element::FrameStart {
            fin: true,
            length: 5,
            opcode: 1
        });

        match iter.next().unwrap() {
            Element::Data { data, last_in_frame } => {
                assert!(last_in_frame);
                assert_eq!(data.collect::<Vec<_>>(), b"Hello");
            }
            _ => panic!()
        }
    }
}
<|endoftext|>


<commit_before>//! varlink_parser crate for parsing [varlink](http://varlink.org) interface definition files.
//!
//! # Examples
//!
//! ```rust
//! use varlink_parser::IDL;
//! use std::convert::TryFrom;
//! let interface = IDL::try_from("
//! ## The Varlink Service Interface is provided by every varlink service. It
//! ## describes the service and the interfaces it implements.
//! interface org.varlink.service
//!
//! ## Get a list of all the interfaces a service provides and information
//! ## about the implementation.
//! method GetInfo() -> (
//! vendor: string,
//! product: string,
//! version: string,
//! url: string,
//! interfaces: []string
//! )
//!
//! ## Get the description of an interface that is implemented by this service.
//! method GetInterfaceDescription(interface: string) -> (description: string)
//!
//! ## The requested interface was not found.
//! error InterfaceNotFound (interface: string)
//!
//! ## The requested method was not found
//! error MethodNotFound (method: string)
//!
//! ## The interface defines the requested method, but the service does not
//! ## implement it.
//! error MethodNotImplemented (method: string)
//!
//! ## One of the passed parameters is invalid.
//! error InvalidParameter (parameter: string)
//! ").unwrap();
//!    assert_eq!(interface.name, "org.varlink.service");
//! ```

#![doc(
    html_logo_url = "https://varlink.org/images/varlink.png",
    html_favicon_url = "https://varlink.org/images/varlink-small.png"
)]

use self::varlink_grammar::ParseInterface;
use std::collections::BTreeMap;
use std::collections::HashSet;

use chainerror::prelude::v1::*;

mod format;

pub use crate::format::{Format, FormatColored};
use std::convert::TryFrom;

#[cfg(test)]
mod test;

mod varlink_grammar;

derive_str_context!(Error);

pub enum VType<'a> {
    Bool,
    Int,
    Float,
    String,
    Object,
    Typename(&'a str),
    Struct(Box<VStruct<'a>>),
    Enum(Box<VEnum<'a>>),
}

pub enum VTypeExt<'a> {
    Array(Box<VTypeExt<'a>>),
    Dict(Box<VTypeExt<'a>>),
    Option(Box<VTypeExt<'a>>),
    Plain(VType<'a>),
}

pub struct Argument<'a> {
    pub name: &'a str,
    pub vtype: VTypeExt<'a>,
}

pub struct VStruct<'a> {
    pub elts: Vec<Argument<'a>>,
}

pub struct VEnum<'a> {
    pub elts: Vec<&'a str>,
}

pub struct VError<'a> {
    pub name: &'a str,
    pub doc: &'a str,
    pub parm: VStruct<'a>,
}

pub enum VStructOrEnum<'a> {
    VStruct(Box<VStruct<'a>>),
    VEnum(Box<VEnum<'a>>),
}

pub struct Typedef<'a> {
    pub name: &'a str,
    pub doc: &'a str,
    pub elt: VStructOrEnum<'a>,
}

pub struct Method<'a> {
    pub name: &'a str,
    pub doc: &'a str,
    pub input: VStruct<'a>,
    pub output: VStruct<'a>,
}

enum MethodOrTypedefOrError<'a> {
    Error(VError<'a>),
    Typedef(Typedef<'a>),
    Method(Method<'a>),
}

pub struct IDL<'a> {
    pub description: &'a str,
    pub name: &'a str,
    pub doc: &'a str,
    pub methods: BTreeMap<&'a str, Method<'a>>,
    pub method_keys: Vec<&'a str>,
    pub typedefs: BTreeMap<&'a str, Typedef<'a>>,
    pub typedef_keys: Vec<&'a str>,
    pub errors: BTreeMap<&'a str, VError<'a>>,
    pub error_keys: Vec<&'a str>,
    pub error: HashSet<String>,
}

fn trim_doc(s: &str) -> &str {
    s.trim_matches(&[
        ' ', '\n', '\r', '\u{00A0}', '\u{FEFF}', '\u{1680}', '\u{180E}', '\u{2000}', '\u{2001}',
        '\u{2002}', '\u{2003}', '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}',
        '\u{2009}', '\u{200A}', '\u{202F}', '\u{205F}', '\u{3000}', '\u{2028}', '\u{2029}',
    ] as &[_])
}

impl<'a> IDL<'a> {
    fn from_token(
        description: &'a str,
        name: &'a str,
        mt: Vec<MethodOrTypedefOrError<'a>>,
        doc: &'a str,
    ) -> IDL<'a> {
        let mut i = IDL {
            description,
            name,
            doc,
            methods: BTreeMap::new(),
            method_keys: Vec::new(),
            typedefs: BTreeMap::new(),
            typedef_keys: Vec::new(),
            errors: BTreeMap::new(),
            error_keys: Vec::new(),
            error: HashSet::new(),
        };

        for o in mt {
            match o {
                MethodOrTypedefOrError::Method(m) => {
                    if i.error_keys.contains(&m.name) || i.typedef_keys.contains(&m.name) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of `{}`!",
                            i.name, m.name
                        ));
                    }

                    i.method_keys.push(m.name);
                    if let Some(d) = i.methods.insert(m.name, m) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of method `{}`!",
                            i.name, d.name
                        ));
                    };
                }
                MethodOrTypedefOrError::Typedef(t) => {
                    if i.error_keys.contains(&t.name) || i.method_keys.contains(&t.name) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of `{}`!",
                            i.name, t.name
                        ));
                    }
                    i.typedef_keys.push(t.name);
                    if let Some(d) = i.typedefs.insert(t.name, t) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of type `{}`!",
                            i.name, d.name
                        ));
                    };
                }
                MethodOrTypedefOrError::Error(e) => {
                    if i.typedef_keys.contains(&e.name) || i.method_keys.contains(&e.name) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of `{}`!",
                            i.name, e.name
                        ));
                    }
                    i.error_keys.push(e.name);
                    if let Some(d) = i.errors.insert(e.name, e) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of error `{}`!",
                            i.name, d.name
                        ));
                    };
                }
            };
        }

        i
    }
}

impl<'a> TryFrom<&'a str> for IDL<'a> {
    type Error = ChainError<Error>;

    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
        let interface = ParseInterface(value).map_context(|e| {
            let line = value.split('\n').nth(e.location.line - 1).unwrap();
            Error(format!(
                "Varlink parse error\n{}\n{marker:>col$}",
                line,
                marker = "^",
                col = e.location.column
            ))
        })?;

        if !interface.error.is_empty() {
            let mut v: Vec<_> = interface.error.into_iter().collect();
            v.sort();
            let s = v.join("\n");

            Err("Interface definition error".to_string())
                .context(Error(format!("Interface definition error: '{}'\n", s)))
        } else {
            Ok(interface)
        }
    }
}
<commit_msg>fix(parser): re-add `IDL::from_string`<commit_after>//! varlink_parser crate for parsing [varlink](http://varlink.org) interface definition files.
//!
//! # Examples
//!
//! ```rust
//! use varlink_parser::IDL;
//! use std::convert::TryFrom;
//! let interface = IDL::try_from("
//! ## The Varlink Service Interface is provided by every varlink service. It
//! ## describes the service and the interfaces it implements.
//! interface org.varlink.service
//!
//! ## Get a list of all the interfaces a service provides and information
//! ## about the implementation.
//! method GetInfo() -> (
//! vendor: string,
//! product: string,
//! version: string,
//! url: string,
//! interfaces: []string
//! )
//!
//! ## Get the description of an interface that is implemented by this service.
//! method GetInterfaceDescription(interface: string) -> (description: string)
//!
//! ## The requested interface was not found.
//! error InterfaceNotFound (interface: string)
//!
//! ## The requested method was not found
//! error MethodNotFound (method: string)
//!
//! ## The interface defines the requested method, but the service does not
//! ## implement it.
//! error MethodNotImplemented (method: string)
//!
//! ## One of the passed parameters is invalid.
//! error InvalidParameter (parameter: string)
//! ").unwrap();
//!    assert_eq!(interface.name, "org.varlink.service");
//! ```

#![doc(
    html_logo_url = "https://varlink.org/images/varlink.png",
    html_favicon_url = "https://varlink.org/images/varlink-small.png"
)]

use self::varlink_grammar::ParseInterface;
use std::collections::BTreeMap;
use std::collections::HashSet;

use chainerror::prelude::v1::*;

mod format;

pub use crate::format::{Format, FormatColored};
use std::convert::TryFrom;

#[cfg(test)]
mod test;

mod varlink_grammar;

derive_str_context!(Error);

pub enum VType<'a> {
    Bool,
    Int,
    Float,
    String,
    Object,
    Typename(&'a str),
    Struct(Box<VStruct<'a>>),
    Enum(Box<VEnum<'a>>),
}

pub enum VTypeExt<'a> {
    Array(Box<VTypeExt<'a>>),
    Dict(Box<VTypeExt<'a>>),
    Option(Box<VTypeExt<'a>>),
    Plain(VType<'a>),
}

pub struct Argument<'a> {
    pub name: &'a str,
    pub vtype: VTypeExt<'a>,
}

pub struct VStruct<'a> {
    pub elts: Vec<Argument<'a>>,
}

pub struct VEnum<'a> {
    pub elts: Vec<&'a str>,
}

pub struct VError<'a> {
    pub name: &'a str,
    pub doc: &'a str,
    pub parm: VStruct<'a>,
}

pub enum VStructOrEnum<'a> {
    VStruct(Box<VStruct<'a>>),
    VEnum(Box<VEnum<'a>>),
}

pub struct Typedef<'a> {
    pub name: &'a str,
    pub doc: &'a str,
    pub elt: VStructOrEnum<'a>,
}

pub struct Method<'a> {
    pub name: &'a str,
    pub doc: &'a str,
    pub input: VStruct<'a>,
    pub output: VStruct<'a>,
}

enum MethodOrTypedefOrError<'a> {
    Error(VError<'a>),
    Typedef(Typedef<'a>),
    Method(Method<'a>),
}

pub struct IDL<'a> {
    pub description: &'a str,
    pub name: &'a str,
    pub doc: &'a str,
    pub methods: BTreeMap<&'a str, Method<'a>>,
    pub method_keys: Vec<&'a str>,
    pub typedefs: BTreeMap<&'a str, Typedef<'a>>,
    pub typedef_keys: Vec<&'a str>,
    pub errors: BTreeMap<&'a str, VError<'a>>,
    pub error_keys: Vec<&'a str>,
    pub error: HashSet<String>,
}

fn trim_doc(s: &str) -> &str {
    s.trim_matches(&[
        ' ', '\n', '\r', '\u{00A0}', '\u{FEFF}', '\u{1680}', '\u{180E}', '\u{2000}', '\u{2001}',
        '\u{2002}', '\u{2003}', '\u{2004}', '\u{2005}', '\u{2006}', '\u{2007}', '\u{2008}',
        '\u{2009}', '\u{200A}', '\u{202F}', '\u{205F}', '\u{3000}', '\u{2028}', '\u{2029}',
    ] as &[_])
}

impl<'a> IDL<'a> {
    fn from_token(
        description: &'a str,
        name: &'a str,
        mt: Vec<MethodOrTypedefOrError<'a>>,
        doc: &'a str,
    ) -> IDL<'a> {
        let mut i = IDL {
            description,
            name,
            doc,
            methods: BTreeMap::new(),
            method_keys: Vec::new(),
            typedefs: BTreeMap::new(),
            typedef_keys: Vec::new(),
            errors: BTreeMap::new(),
            error_keys: Vec::new(),
            error: HashSet::new(),
        };

        for o in mt {
            match o {
                MethodOrTypedefOrError::Method(m) => {
                    if i.error_keys.contains(&m.name) || i.typedef_keys.contains(&m.name) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of `{}`!",
                            i.name, m.name
                        ));
                    }

                    i.method_keys.push(m.name);
                    if let Some(d) = i.methods.insert(m.name, m) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of method `{}`!",
                            i.name, d.name
                        ));
                    };
                }
                MethodOrTypedefOrError::Typedef(t) => {
                    if i.error_keys.contains(&t.name) || i.method_keys.contains(&t.name) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of `{}`!",
                            i.name, t.name
                        ));
                    }
                    i.typedef_keys.push(t.name);
                    if let Some(d) = i.typedefs.insert(t.name, t) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of type `{}`!",
                            i.name, d.name
                        ));
                    };
                }
                MethodOrTypedefOrError::Error(e) => {
                    if i.typedef_keys.contains(&e.name) || i.method_keys.contains(&e.name) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of `{}`!",
                            i.name, e.name
                        ));
                    }
                    i.error_keys.push(e.name);
                    if let Some(d) = i.errors.insert(e.name, e) {
                        i.error.insert(format!(
                            "Interface `{}`: multiple definitions of error `{}`!",
                            i.name, d.name
                        ));
                    };
                }
            };
        }

        i
    }

    #[deprecated(since = "4.1.0", note = "please use `IDL::try_from` instead")]
    pub fn from_string(s: &'a str) -> ChainResult<Self, Error> {
        IDL::try_from(s)
    }
}

impl<'a> TryFrom<&'a str> for IDL<'a> {
    type Error = ChainError<Error>;

    fn try_from(value: &'a str) -> Result<Self, Self::Error> {
        let interface = ParseInterface(value).map_context(|e| {
            let line = value.split('\n').nth(e.location.line - 1).unwrap();
            Error(format!(
                "Varlink parse error\n{}\n{marker:>col$}",
                line,
                marker = "^",
                col = e.location.column
            ))
        })?;

        if !interface.error.is_empty() {
            let mut v: Vec<_> = interface.error.into_iter().collect();
            v.sort();
            let s = v.join("\n");

            Err("Interface definition error".to_string())
                .context(Error(format!("Interface definition error: '{}'\n", s)))
        } else {
            Ok(interface)
        }
    }
}
<|endoftext|>


<commit_before>extern crate sfml;
#[macro_use]
extern crate log;
extern crate env_logger;

use sfml::window::{ContextSettings, VideoMode, window_style, event};
use sfml::graphics::RenderWindow;

mod engine_config;

fn fake_main() -> i32 {
    // Init'ing the log system is the first thing to try. Without it, nothing else
    // can be done or reported, so unwrap() will be used here and ONLY here.
    env_logger::init().unwrap();
    debug!("env_logger has been initialized successfully.");

    // TODO: Init Lua here.

    // Acquire the engine configuration. Failing this is a fatal error.
    let engine_config = match engine_config::get_engine_config() {
        Ok(config) => config,
        Err(error) => {
            error!("Failed to acquire engine configuration:\n\t{}", error);
            return 1;
        }
    };

    // TODO: Init the game state here.

    // Initialize the game window. If this can't be done, there's really no point in
    // continuing on.
    let mut window = match RenderWindow::new(VideoMode::new_init(engine_config.screen_width,
                                                                 engine_config.screen_height,
                                                                 32),
                                             "Game Title",
                                             window_style::CLOSE,
                                             &ContextSettings::default()) {
        Some(window) => window,
        None => {
            error!("Could not init a RenderWindow. There is likely a problem with your system.");
            return 1;
        }
    };
    // Set the game's maximum framerate.
    window.set_framerate_limit(engine_config.maximum_framerate);

    return 0;
}

fn main() {
    // Fake-main technique. This allows the main() function to return an int (i32) status code.
    std::process::exit(fake_main());
}
<commit_msg>Add barebones event loop.<commit_after>extern crate sfml;
#[macro_use]
extern crate log;
extern crate env_logger;

use sfml::window::{ContextSettings, VideoMode, window_style};
use sfml::window::event;
use sfml::graphics::RenderWindow;
use sfml::system::Clock;

mod engine_config;

fn fake_main() -> i32 {
    // Init'ing the log system is the first thing to try. Without it, nothing else
    // can be done or reported, so unwrap() will be used here and ONLY here.
    env_logger::init().unwrap();
    debug!("env_logger has been initialized successfully.");

    // TODO: Init Lua here.

    // Acquire the engine configuration. Failing this is a fatal error.
    let engine_config = match engine_config::get_engine_config() {
        Ok(config) => config,
        Err(error) => {
            error!("Failed to acquire engine configuration:\n\t{}", error);
            return 1;
        }
    };

    // TODO: Init the game state here.

    // Initialize the game window. If this can't be done, there's really no point in
    // continuing on.
    let mut window = match RenderWindow::new(VideoMode::new_init(engine_config.screen_width,
                                                                 engine_config.screen_height,
                                                                 32),
                                             "Game Title",
                                             window_style::CLOSE,
                                             &ContextSettings::default()) {
        Some(window) => window,
        None => {
            error!("Could not init a RenderWindow. There is likely a problem with your system.");
            return 1;
        }
    };
    // Set the game's maximum framerate.
    window.set_framerate_limit(engine_config.maximum_framerate);

    // Set up a clock to keep track of how long frames take.
    let frame_clock = Clock::new();
    while window.is_open() {
        // events() returns an iterator over all events in the queue.
        for current_event in window.events() {
            if current_event == event::Closed {
                window.close()
            }
        }
    }
    return 0;
}

fn main() {
    // Fake-main technique. This allows the main() function to return an int (i32) status code.
    std::process::exit(fake_main());
}
<|endoftext|>


<commit_before>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::BufferedStream;
use std::string::String;

fn main () {

    let listener = TcpListener::bind("127.0.0.1", 8099).unwrap();
    let mut acceptor = listener.listen().unwrap();

    fn handle_client(mut stream: BufferedStream<TcpStream>) {

        let mut body: String = stream.read_line().unwrap();
        body = body + "
You sent it!
";

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\n").unwrap(); // byte literal
        stream.write(b"Content-type: text/html\n").unwrap();
        stream.write(b"X-header: from bytes\n");
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\n\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<commit_msg>echo all headers<commit_after>use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};
use std::io::BufferedStream;
use std::string::String;

fn main () {

    let listener = TcpListener::bind("127.0.0.1", 8099).unwrap();
    let mut acceptor = listener.listen().unwrap();

    fn handle_client(mut stream: BufferedStream<TcpStream>) {

        let mut body: String = "
You sent it!
".to_string();

        let mut cur_line: String;
        loop {
            match stream.read_line() { // XXX: strange unwrap like thing
                Ok(line) => cur_line = line,
                Err(_) => break
            }
            body = body + cur_line + "
";
            if cur_line.len() == 2 { // TODO: make this check for \n\n explicitly
                break;
            }
        }

        let body_length = format!("Content-length: {}", body.len());

        stream.write(b"HTTP/1.1 200 OK\n").unwrap(); // byte literal
        stream.write(b"Content-type: text/html\n").unwrap();
        stream.write(b"X-header: from bytes\n");
        stream.write(body_length.into_bytes().as_slice()).unwrap();
        stream.write(b"\n\n").unwrap();
        stream.write(body.into_bytes().as_slice()).unwrap();
        stream.flush().unwrap();

        println!("Handling acceptor");
    }

    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { println!("connection failed: {}", e) }
            Ok(stream) => spawn(proc() {
                let bs = BufferedStream::new(stream);
                handle_client(bs)
            })
        }
    }

    drop(acceptor);
}
<|endoftext|>


<commit_before>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::ffi::{CString, OsStr};
use std::fmt;
use std::io;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::RawFd;

/// Mount options to pass to mount(2) for a FUSE filesystem. See the [official document](
/// https://www.kernel.org/doc/html/latest/filesystems/fuse.html#mount-options) for the
/// descriptions.
pub enum MountOption {
    FD(RawFd),
    RootMode(u32),
    UserId(libc::uid_t),
    GroupId(libc::gid_t),
    DefaultPermissions,
    AllowOther,
    MaxRead(u32),
    BlockSize(u32),
}

// Implement Display for ToString to convert to actual mount options.
impl fmt::Display for MountOption {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self {
            MountOption::FD(fd) => write!(f, "fd={}", fd),
            MountOption::RootMode(mode) => write!(f, "rootmode={:o}", mode),
            MountOption::UserId(uid) => write!(f, "user_id={}", uid),
            MountOption::GroupId(gid) => write!(f, "group_id={}", gid),
            MountOption::DefaultPermissions => write!(f, "default_permissions"),
            MountOption::AllowOther => write!(f, "allow_other"),
            MountOption::MaxRead(size) => write!(f, "max_read={}", size),
            MountOption::BlockSize(size) => write!(f, "blksize={}", size),
        }
    }
}

fn join_mount_options(options: &[MountOption]) -> String {
    if !options.is_empty() {
        let mut concat = options[0].to_string();
        for opt in &options[1..] {
            concat.push(',');
            concat.push_str(&opt.to_string());
        }
        concat
    } else {
        String::new()
    }
}

/// Initiates a FUSE mount at `mountpoint` directory with `flags` and `options` via mount(2). The
/// caller should provide a file descriptor (backed by /dev/fuse) with `MountOption::FD`. After
/// this function completes, the FUSE filesystem can start to handle the requests, e.g. via
/// `fuse::worker::start_message_loop()`.
///
/// This operation requires CAP_SYS_ADMIN privilege, but the privilege can be dropped afterward.
pub fn mount<P: AsRef<OsStr>>(
    mountpoint: P,
    name: &str,
    flags: libc::c_ulong,
    options: &[MountOption],
) -> Result<(), io::Error> {
    let mount_name = CString::new(name.as_bytes())?;
    let fs_type = CString::new(String::from("fuse.") + name)?;
    let mountpoint = CString::new(mountpoint.as_ref().as_bytes())?;
    let mount_options = CString::new(join_mount_options(options))?;

    // Safe because pointer arguments all points to null-terminiated CStrings.
    let retval = unsafe {
        libc::mount(
            mount_name.as_ptr(),
            mountpoint.as_ptr(),
            fs_type.as_ptr(),
            flags,
            mount_options.as_ptr() as *const std::ffi::c_void,
        )
    };
    if retval < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

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

    #[test]
    fn basic_options_concatenate_in_order() {
        assert_eq!("".to_string(), join_mount_options(&[]));

        assert_eq!(
            "fd=42".to_string(),
            join_mount_options(&[MountOption::FD(42),])
        );

        assert_eq!(
            "fd=42,rootmode=40111,allow_other,user_id=12,group_id=34,max_read=4096".to_string(),
            join_mount_options(&[
                MountOption::FD(42),
                MountOption::RootMode(
                    libc::S_IFDIR | libc::S_IXUSR | libc::S_IXGRP | libc::S_IXOTH
                ),
                MountOption::AllowOther,
                MountOption::UserId(12),
                MountOption::GroupId(34),
                MountOption::MaxRead(4096),
            ])
        );

        assert_eq!(
            "fd=42,default_permissions,user_id=12,group_id=34,max_read=4096".to_string(),
            join_mount_options(&[
                MountOption::FD(42),
                MountOption::DefaultPermissions,
                MountOption::UserId(12),
                MountOption::GroupId(34),
                MountOption::MaxRead(4096),
            ])
        );
    }
}
<commit_msg>fuse: support general mount options<commit_after>// Copyright 2020 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

use std::ffi::{CString, OsStr};
use std::fmt;
use std::io;
use std::os::unix::ffi::OsStrExt;
use std::os::unix::io::RawFd;

/// Mount options to pass to mount(2) for a FUSE filesystem. See the [official document](
/// https://www.kernel.org/doc/html/latest/filesystems/fuse.html#mount-options) for the
/// descriptions.
pub enum MountOption<'a> {
    FD(RawFd),
    RootMode(u32),
    UserId(libc::uid_t),
    GroupId(libc::gid_t),
    DefaultPermissions,
    AllowOther,
    MaxRead(u32),
    BlockSize(u32),
    // General mount options that are not specific to FUSE. Note that the value is not checked
    // or interpreted by this library, but by kernel.
    Extra(&'a str),
}

// Implement Display for ToString to convert to actual mount options.
impl<'a> fmt::Display for MountOption<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match &self {
            MountOption::FD(fd) => write!(f, "fd={}", fd),
            MountOption::RootMode(mode) => write!(f, "rootmode={:o}", mode),
            MountOption::UserId(uid) => write!(f, "user_id={}", uid),
            MountOption::GroupId(gid) => write!(f, "group_id={}", gid),
            MountOption::DefaultPermissions => write!(f, "default_permissions"),
            MountOption::AllowOther => write!(f, "allow_other"),
            MountOption::MaxRead(size) => write!(f, "max_read={}", size),
            MountOption::BlockSize(size) => write!(f, "blksize={}", size),
            MountOption::Extra(text) => write!(f, "{}", text),
        }
    }
}

fn join_mount_options(options: &[MountOption]) -> String {
    if !options.is_empty() {
        let mut concat = options[0].to_string();
        for opt in &options[1..] {
            concat.push(',');
            concat.push_str(&opt.to_string());
        }
        concat
    } else {
        String::new()
    }
}

/// Initiates a FUSE mount at `mountpoint` directory with `flags` and `options` via mount(2). The
/// caller should provide a file descriptor (backed by /dev/fuse) with `MountOption::FD`. After
/// this function completes, the FUSE filesystem can start to handle the requests, e.g. via
/// `fuse::worker::start_message_loop()`.
///
/// This operation requires CAP_SYS_ADMIN privilege, but the privilege can be dropped afterward.
pub fn mount<P: AsRef<OsStr>>(
    mountpoint: P,
    name: &str,
    flags: libc::c_ulong,
    options: &[MountOption],
) -> Result<(), io::Error> {
    let mount_name = CString::new(name.as_bytes())?;
    let fs_type = CString::new(String::from("fuse.") + name)?;
    let mountpoint = CString::new(mountpoint.as_ref().as_bytes())?;
    let mount_options = CString::new(join_mount_options(options))?;

    // Safe because pointer arguments all points to null-terminiated CStrings.
    let retval = unsafe {
        libc::mount(
            mount_name.as_ptr(),
            mountpoint.as_ptr(),
            fs_type.as_ptr(),
            flags,
            mount_options.as_ptr() as *const std::ffi::c_void,
        )
    };
    if retval < 0 {
        Err(io::Error::last_os_error())
    } else {
        Ok(())
    }
}

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

    #[test]
    fn basic_options_concatenate_in_order() {
        assert_eq!("".to_string(), join_mount_options(&[]));

        assert_eq!(
            "fd=42".to_string(),
            join_mount_options(&[MountOption::FD(42),])
        );

        assert_eq!(
            "fd=42,rootmode=40111,allow_other,user_id=12,group_id=34,max_read=4096".to_string(),
            join_mount_options(&[
                MountOption::FD(42),
                MountOption::RootMode(
                    libc::S_IFDIR | libc::S_IXUSR | libc::S_IXGRP | libc::S_IXOTH
                ),
                MountOption::AllowOther,
                MountOption::UserId(12),
                MountOption::GroupId(34),
                MountOption::MaxRead(4096),
            ])
        );

        assert_eq!(
            "fd=42,default_permissions,user_id=12,group_id=34,max_read=4096".to_string(),
            join_mount_options(&[
                MountOption::FD(42),
                MountOption::DefaultPermissions,
                MountOption::UserId(12),
                MountOption::GroupId(34),
                MountOption::MaxRead(4096),
            ])
        );

        assert_eq!(
            "option1=a,option2=b".to_string(),
            join_mount_options(&[MountOption::Extra("option1=a,option2=b"),])
        );
    }
}
<|endoftext|>


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

#[doc(keyword = "fn")]
//
/// The `fn` keyword.
///
/// The `fn` keyword is used to declare a function.
///
/// Example:
///
/// ```rust
/// fn some_function() {
///     // code goes in here
/// }
/// ```
///
/// For more information about functions, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html
mod fn_keyword { }

#[doc(keyword = "let")]
//
/// The `let` keyword.
///
/// The `let` keyword is used to declare a variable.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let x = 3; // We create a variable named `x` with the value `3`.
/// ```
///
/// By default, all variables are **not** mutable. If you want a mutable variable,
/// you'll have to use the `mut` keyword.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let mut x = 3; // We create a mutable variable named `x` with the value `3`.
///
/// x += 4; // `x` is now equal to `7`.
/// ```
///
/// For more information about the `let` keyword, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html
mod let_keyword { }
<commit_msg>Rollup merge of #53651 - GuillaumeGomez:struct-keyword, r=QuietMisdreavus<commit_after>// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#[doc(keyword = "fn")]
//
/// The `fn` keyword.
///
/// The `fn` keyword is used to declare a function.
///
/// Example:
///
/// ```rust
/// fn some_function() {
///     // code goes in here
/// }
/// ```
///
/// For more information about functions, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-03-how-functions-work.html
mod fn_keyword { }

#[doc(keyword = "let")]
//
/// The `let` keyword.
///
/// The `let` keyword is used to declare a variable.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let x = 3; // We create a variable named `x` with the value `3`.
/// ```
///
/// By default, all variables are **not** mutable. If you want a mutable variable,
/// you'll have to use the `mut` keyword.
///
/// Example:
///
/// ```rust
/// # #![allow(unused_assignments)]
/// let mut x = 3; // We create a mutable variable named `x` with the value `3`.
///
/// x += 4; // `x` is now equal to `7`.
/// ```
///
/// For more information about the `let` keyword, take a look at the [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch03-01-variables-and-mutability.html
mod let_keyword { }

#[doc(keyword = "struct")]
//
/// The `struct` keyword.
///
/// The `struct` keyword is used to define a struct type.
///
/// Example:
///
/// ```
/// struct Foo {
///     field1: u32,
///     field2: String,
/// }
/// ```
///
/// There are different kinds of structs. For more information, take a look at the
/// [Rust Book][book].
///
/// [book]: https://doc.rust-lang.org/book/second-edition/ch05-01-defining-structs.html
mod struct_keyword { }
<|endoftext|>


<commit_before>use std::time::Duration;

#[derive(Clone)]
pub struct FrameAnimator {
    max: u32,
    duration: Duration,
    repeat: bool,
    current: u32,
    elapsed: Option<Duration>,
}

impl FrameAnimator {
    pub fn new(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: 0,
            elapsed: None,
        }
    }

    pub fn frame(&self) -> u32 {
        self.current
    }

    pub fn is_active(&self) -> bool {
        self.elapsed.is_some()
    }

    pub fn animate(&mut self, delta: Duration) {
        match self.elapsed {
            None => self.restart(),
            Some(duration) => {
                let elapsed = duration + delta;
                if elapsed >= self.duration {
                    self.advance(elapsed);
                } else {
                    self.elapsed = Some(elapsed);
                }
            }
        }
    }

    pub fn num_frames(&self) -> u32 {
        self.max
    }

    fn advance(&mut self, elapsed: Duration) {
        let remaining = elapsed - self.duration;
        self.current = (self.current + 1) % self.max;
        self.elapsed = if self.current > 0 || self.repeat {
            Some(remaining)
        } else {
            None
        };
    }

    fn restart(&mut self) {
        self.current = 0;
        self.elapsed = Some(Duration::new(0, 0));
    }
}
<commit_msg>refactoring animator<commit_after>use std::time::Duration;

#[derive(Default)]
struct Info {
    current: u32,
    elapsed: Option<Duration>,
}

impl Info {
    fn restarted() -> Self {
        Self::new(0, Some(Duration::default()))
    }

    fn elapsed(current: u32, elapsed: Duration) -> Self {
        Self::new(current, Some(elapsed))
    }

    fn new(current: u32, elapsed: Option<Duration>) -> Self {
        Info {
            current: current,
            elapsed: elapsed,
        }
    }
}

#[derive(Clone)]
pub struct FrameAnimator {
    max: u32,
    duration: Duration,
    repeat: bool,
    current: u32,
    elapsed: Option<Duration>,
}

impl FrameAnimator {
    pub fn new(max: u32, duration: Duration, repeat: bool) -> FrameAnimator {
        FrameAnimator {
            max: max,
            duration: duration,
            repeat: repeat,
            current: 0,
            elapsed: None,
        }
    }

    pub fn frame(&self) -> u32 {
        self.current
    }

    pub fn is_active(&self) -> bool {
        self.elapsed.is_some()
    }

    pub fn animate(&mut self, delta: Duration) {
        let info = self.elapsed
            .map_or(Info::restarted(), |d| self.advance(d + delta));
        self.current = info.current;
        self.elapsed = info.elapsed;
    }

    pub fn num_frames(&self) -> u32 {
        self.max
    }

    fn advance(&self, elapsed: Duration) -> Info {
        elapsed.checked_sub(self.duration)
            .map_or(Info::elapsed(self.current, elapsed), |r| self.next(r))
    }

    fn next(&self, remaining: Duration) -> Info {
        let current = (self.current + 1) % self.max;
        if current > 0 || self.repeat {
            Info::elapsed(current, remaining)
        } else {
            Info::default()
        }
    }
}
<|endoftext|>