<commit_before>use utils::address::Address;
use utils::gas::Gas;

use vm::errors::MachineError;
use vm::{Memory, Machine, MachineStatus};

use std::str::FromStr;

use tiny_keccak::Keccak;
use sha2::Sha256;
use ripemd160::Ripemd160;
use secp256k1::{Secp256k1, RecoverableSignature, Message, RecoveryId, Error};
use digest::{Input, FixedOutput};

pub fn is_precompiled(address: Address) -> bool {
    let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
    let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
    let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
    let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

    address == ecrec_address ||
        address == sha256_address ||
        address == rip160_address ||
        address == id_address
}

impl<M: Memory + Default> Machine<M> {
    #[allow(unused_variables)]
    pub fn step_precompiled(&mut self) -> bool {
        let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
        let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
        let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
        let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

        if self.state.context.address == id_address {
            self.step_precompiled_id();
            return true;
        } else if self.state.context.address == rip160_address {
            self.step_precompiled_rip160();
            return true;
        } else if self.state.context.address == sha256_address {
            self.step_precompiled_sha256();
            return true;
        } else if self.state.context.address == ecrec_address {
            self.step_precompiled_ecrec();
            return true;
        } else {
            return false;
        }
    }

    fn step_precompiled_id(&mut self) {
        let gas = Gas::from(15u64) +
            Gas::from(3u64) * (Gas::from(self.state.context.data.len()) / Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            self.state.out = self.state.context.data.clone();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_rip160(&mut self) {
        let gas = Gas::from(600u64) +
            Gas::from(120u64) * (Gas::from(self.state.context.data.len()) / Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut ripemd = Ripemd160::default();
            ripemd.digest(&self.state.context.data);
            let fixed = ripemd.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..20 {
                result[i + 12] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_sha256(&mut self) {
        let gas = Gas::from(60u64) +
            Gas::from(12u64) * (Gas::from(self.state.context.data.len()) / Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut sha2 = Sha256::default();
            sha2.digest(&self.state.context.data);
            let fixed = sha2.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..32 {
                result[i] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_ecrec(&mut self) {
        let gas = Gas::from(3000u64);
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut data = [0u8; 128];
            for i in 0..self.state.context.data.len() {
                data[i] = self.state.context.data[i];
            }
            match kececrec(&data) {
                Ok(mut ret) => {
                    for i in 0..12 {
                        ret[i] = 0u8;
                    }
                    self.state.out = ret.as_ref().into();
                },
                Err(_) => (),
            }
            self.status = MachineStatus::ExitedOk;
        }
    }
}

fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
    let ecrec = Secp256k1::new();
    let message = Message::from_slice(&data[0..32])?;
    let recid = RecoveryId::from_i32(data[63] as i32)?;
    let sig = RecoverableSignature::from_compact(&ecrec, &data[64..128], recid)?;
    let recovered = ecrec.recover(&message, &sig)?;
    let key = recovered.serialize_vec(&ecrec, false);
    let mut kec = Keccak::new_keccak256();
    kec.update(&key);
    let mut ret = [0u8; 32];
    kec.finalize(&mut ret);
    Ok(ret)
}
<commit_msg>Precompiled contracts gas fix<commit_after>use utils::address::Address;
use utils::gas::Gas;

use vm::errors::MachineError;
use vm::{Memory, Machine, MachineStatus};

use std::str::FromStr;

use tiny_keccak::Keccak;
use sha2::Sha256;
use ripemd160::Ripemd160;
use secp256k1::{Secp256k1, RecoverableSignature, Message, RecoveryId, Error};
use digest::{Input, FixedOutput};

pub fn gas_div_ceil(a: Gas, b: Gas) -> Gas {
    if a % b == Gas::zero() {
        a / b
    } else {
        a / b + Gas::from(1u64)
    }
}

pub fn is_precompiled(address: Address) -> bool {
    let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
    let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
    let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
    let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

    address == ecrec_address ||
        address == sha256_address ||
        address == rip160_address ||
        address == id_address
}

impl<M: Memory + Default> Machine<M> {
    #[allow(unused_variables)]
    pub fn step_precompiled(&mut self) -> bool {
        let ecrec_address = Address::from_str("0x0000000000000000000000000000000000000001").unwrap();
        let sha256_address = Address::from_str("0x0000000000000000000000000000000000000002").unwrap();
        let rip160_address = Address::from_str("0x0000000000000000000000000000000000000003").unwrap();
        let id_address = Address::from_str("0x0000000000000000000000000000000000000004").unwrap();

        if self.state.context.address == id_address {
            self.step_precompiled_id();
            return true;
        } else if self.state.context.address == rip160_address {
            self.step_precompiled_rip160();
            return true;
        } else if self.state.context.address == sha256_address {
            self.step_precompiled_sha256();
            return true;
        } else if self.state.context.address == ecrec_address {
            self.step_precompiled_ecrec();
            return true;
        } else {
            return false;
        }
    }

    fn step_precompiled_id(&mut self) {
        let gas = Gas::from(15u64) +
            Gas::from(3u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                           Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            self.state.out = self.state.context.data.clone();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_rip160(&mut self) {
        let gas = Gas::from(600u64) +
            Gas::from(120u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                             Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut ripemd = Ripemd160::default();
            ripemd.digest(&self.state.context.data);
            let fixed = ripemd.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..20 {
                result[i + 12] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_sha256(&mut self) {
        let gas = Gas::from(60u64) +
            Gas::from(12u64) * gas_div_ceil(Gas::from(self.state.context.data.len()),
                                            Gas::from(32u64));
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut sha2 = Sha256::default();
            sha2.digest(&self.state.context.data);
            let fixed = sha2.fixed_result();
            let mut result: [u8; 32] = [0u8; 32];
            for i in 0..32 {
                result[i] = fixed[i];
            }
            self.state.out = result.as_ref().into();
            self.status = MachineStatus::ExitedOk;
        }
    }

    fn step_precompiled_ecrec(&mut self) {
        let gas = Gas::from(3000u64);
        if gas > self.state.context.gas_limit {
            self.state.used_gas = self.state.context.gas_limit;
            self.status = MachineStatus::ExitedErr(MachineError::EmptyGas);
        } else {
            self.state.used_gas = gas;
            let mut data = [0u8; 128];
            for i in 0..self.state.context.data.len() {
                data[i] = self.state.context.data[i];
            }
            match kececrec(&data) {
                Ok(mut ret) => {
                    for i in 0..12 {
                        ret[i] = 0u8;
                    }
                    self.state.out = ret.as_ref().into();
                },
                Err(_) => (),
            }
            self.status = MachineStatus::ExitedOk;
        }
    }
}

fn kececrec(data: &[u8]) -> Result<[u8; 32], Error> {
    let ecrec = Secp256k1::new();
    let message = Message::from_slice(&data[0..32])?;
    let recid = RecoveryId::from_i32(data[63] as i32)?;
    let sig = RecoverableSignature::from_compact(&ecrec, &data[64..128], recid)?;
    let recovered = ecrec.recover(&message, &sig)?;
    let key = recovered.serialize_vec(&ecrec, false);
    let mut kec = Keccak::new_keccak256();
    kec.update(&key);
    let mut ret = [0u8; 32];
    kec.finalize(&mut ret);
    Ok(ret)
}
<|endoftext|>


<commit_before>use super::frontend_prelude::*;

use crate::models::{CrateOwner, CrateOwnerInvitation, OwnerKind, User};
use crate::schema::{crate_owner_invitations, crate_owners, users};
use crate::views::{EncodableCrateOwnerInvitation, EncodablePublicUser, InvitationResponse};
use diesel::dsl::any;
use std::collections::HashSet;
use std::iter::FromIterator;

/// Handles the `GET /me/crate_owner_invitations` route.
pub fn list(req: &mut dyn RequestExt) -> EndpointResult {
    // Ensure that the user is authenticated
    let user = req.authenticate()?.user();

    // Load all pending invitations for the user
    let conn = &*req.db_read_only()?;
    let crate_owner_invitations: Vec<CrateOwnerInvitation> = crate_owner_invitations::table
        .filter(crate_owner_invitations::invited_user_id.eq(user.id))
        .load(&*conn)?;

    // Make a list of all related users and deduplicate it by using a `HashSet`
    let mut user_ids = HashSet::new();
    for invitation in &crate_owner_invitations {
        user_ids.insert(invitation.invited_by_user_id);
    }

    // Load all related users
    let users: Vec<User> = users::table
        .filter(users::id.eq(any(Vec::from_iter(user_ids))))
        .load(conn)?;

    // Turn `CrateOwnerInvitation` list into `EncodableCrateOwnerInvitation` list
    let crate_owner_invitations = crate_owner_invitations
        .into_iter()
        .map(|invitation| {
            let inviter_id = invitation.invited_by_user_id;
            let inviter_name = users
                .iter()
                .find(|user| user.id == inviter_id)
                .map(|user| user.gh_login.clone())
                .unwrap_or_default();

            let crate_name = invitation.crate_name(conn);
            EncodableCrateOwnerInvitation::from(invitation, inviter_name, crate_name)
        })
        .collect();

    // Turn `User` list into `EncodablePublicUser` list
    let users = users
        .into_iter()
        .map(|user| EncodablePublicUser::from(user))
        .collect();

    #[derive(Serialize)]
    struct R {
        crate_owner_invitations: Vec<EncodableCrateOwnerInvitation>,
        users: Vec<EncodablePublicUser>,
    }
    Ok(req.json(&R {
        crate_owner_invitations,
        users,
    }))
}

#[derive(Deserialize)]
struct OwnerInvitation {
    crate_owner_invite: InvitationResponse,
}

/// Handles the `PUT /me/crate_owner_invitations/:crate_id` route.
pub fn handle_invite(req: &mut dyn RequestExt) -> EndpointResult {
    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    let crate_invite: OwnerInvitation =
        serde_json::from_str(&body).map_err(|_| bad_request("invalid json request"))?;

    let crate_invite = crate_invite.crate_owner_invite;
    let user_id = req.authenticate()?.user_id();
    let conn = &*req.db_conn()?;

    if crate_invite.accepted {
        accept_invite(req, conn, crate_invite, user_id)
    } else {
        decline_invite(req, conn, crate_invite, user_id)
    }
}

/// Handles the `PUT /me/crate_owner_invitations/accept/:token` route.
pub fn handle_invite_with_token(req: &mut dyn RequestExt) -> EndpointResult {
    let conn = req.db_conn()?;
    let req_token = &req.params()["token"];

    let crate_owner_invite: CrateOwnerInvitation = crate_owner_invitations::table
        .filter(crate_owner_invitations::token.eq(req_token))
        .first(&*conn)?;

    let invite_reponse = InvitationResponse {
        crate_id: crate_owner_invite.crate_id,
        accepted: true,
    };
    accept_invite(
        req,
        &conn,
        invite_reponse,
        crate_owner_invite.invited_user_id,
    )
}

fn accept_invite(
    req: &dyn RequestExt,
    conn: &PgConnection,
    crate_invite: InvitationResponse,
    user_id: i32,
) -> EndpointResult {
    use diesel::{delete, insert_into};

    conn.transaction(|| {
        let pending_crate_owner: CrateOwnerInvitation = crate_owner_invitations::table
            .find((user_id, crate_invite.crate_id))
            .first(&*conn)?;

        insert_into(crate_owners::table)
            .values(&CrateOwner {
                crate_id: crate_invite.crate_id,
                owner_id: user_id,
                created_by: pending_crate_owner.invited_by_user_id,
                owner_kind: OwnerKind::User as i32,
                email_notifications: true,
            })
            .on_conflict(crate_owners::table.primary_key())
            .do_update()
            .set(crate_owners::deleted.eq(false))
            .execute(conn)?;
        delete(crate_owner_invitations::table.find((user_id, crate_invite.crate_id)))
            .execute(conn)?;

        #[derive(Serialize)]
        struct R {
            crate_owner_invitation: InvitationResponse,
        }
        Ok(req.json(&R {
            crate_owner_invitation: crate_invite,
        }))
    })
}

fn decline_invite(
    req: &dyn RequestExt,
    conn: &PgConnection,
    crate_invite: InvitationResponse,
    user_id: i32,
) -> EndpointResult {
    use diesel::delete;

    delete(crate_owner_invitations::table.find((user_id, crate_invite.crate_id))).execute(conn)?;

    #[derive(Serialize)]
    struct R {
        crate_owner_invitation: InvitationResponse,
    }

    Ok(req.json(&R {
        crate_owner_invitation: crate_invite,
    }))
}
<commit_msg>CrateOwnerInvitation: Turn `Vec<User>` into `HashMap<i32, User>` for faster lookups<commit_after>use super::frontend_prelude::*;

use crate::models::{CrateOwner, CrateOwnerInvitation, OwnerKind, User};
use crate::schema::{crate_owner_invitations, crate_owners, users};
use crate::views::{EncodableCrateOwnerInvitation, EncodablePublicUser, InvitationResponse};
use diesel::dsl::any;
use std::collections::{HashMap, HashSet};
use std::iter::FromIterator;

/// Handles the `GET /me/crate_owner_invitations` route.
pub fn list(req: &mut dyn RequestExt) -> EndpointResult {
    // Ensure that the user is authenticated
    let user = req.authenticate()?.user();

    // Load all pending invitations for the user
    let conn = &*req.db_read_only()?;
    let crate_owner_invitations: Vec<CrateOwnerInvitation> = crate_owner_invitations::table
        .filter(crate_owner_invitations::invited_user_id.eq(user.id))
        .load(&*conn)?;

    // Make a list of all related users and deduplicate it by using a `HashSet`
    let mut user_ids = HashSet::new();
    for invitation in &crate_owner_invitations {
        user_ids.insert(invitation.invited_by_user_id);
    }

    // Load all related users
    let users: Vec<User> = users::table
        .filter(users::id.eq(any(Vec::from_iter(user_ids))))
        .load(conn)?;

    let users: HashMap<i32, User> = users.into_iter().map(|user| (user.id, user)).collect();

    // Turn `CrateOwnerInvitation` list into `EncodableCrateOwnerInvitation` list
    let crate_owner_invitations = crate_owner_invitations
        .into_iter()
        .map(|invitation| {
            let inviter_id = invitation.invited_by_user_id;
            let inviter_name = users
                .get(&inviter_id)
                .map(|user| user.gh_login.clone())
                .unwrap_or_default();

            let crate_name = invitation.crate_name(conn);
            EncodableCrateOwnerInvitation::from(invitation, inviter_name, crate_name)
        })
        .collect();

    // Turn `User` list into `EncodablePublicUser` list
    let users = users
        .into_iter()
        .map(|(_, user)| EncodablePublicUser::from(user))
        .collect();

    #[derive(Serialize)]
    struct R {
        crate_owner_invitations: Vec<EncodableCrateOwnerInvitation>,
        users: Vec<EncodablePublicUser>,
    }
    Ok(req.json(&R {
        crate_owner_invitations,
        users,
    }))
}

#[derive(Deserialize)]
struct OwnerInvitation {
    crate_owner_invite: InvitationResponse,
}

/// Handles the `PUT /me/crate_owner_invitations/:crate_id` route.
pub fn handle_invite(req: &mut dyn RequestExt) -> EndpointResult {
    let mut body = String::new();
    req.body().read_to_string(&mut body)?;

    let crate_invite: OwnerInvitation =
        serde_json::from_str(&body).map_err(|_| bad_request("invalid json request"))?;

    let crate_invite = crate_invite.crate_owner_invite;
    let user_id = req.authenticate()?.user_id();
    let conn = &*req.db_conn()?;

    if crate_invite.accepted {
        accept_invite(req, conn, crate_invite, user_id)
    } else {
        decline_invite(req, conn, crate_invite, user_id)
    }
}

/// Handles the `PUT /me/crate_owner_invitations/accept/:token` route.
pub fn handle_invite_with_token(req: &mut dyn RequestExt) -> EndpointResult {
    let conn = req.db_conn()?;
    let req_token = &req.params()["token"];

    let crate_owner_invite: CrateOwnerInvitation = crate_owner_invitations::table
        .filter(crate_owner_invitations::token.eq(req_token))
        .first(&*conn)?;

    let invite_reponse = InvitationResponse {
        crate_id: crate_owner_invite.crate_id,
        accepted: true,
    };
    accept_invite(
        req,
        &conn,
        invite_reponse,
        crate_owner_invite.invited_user_id,
    )
}

fn accept_invite(
    req: &dyn RequestExt,
    conn: &PgConnection,
    crate_invite: InvitationResponse,
    user_id: i32,
) -> EndpointResult {
    use diesel::{delete, insert_into};

    conn.transaction(|| {
        let pending_crate_owner: CrateOwnerInvitation = crate_owner_invitations::table
            .find((user_id, crate_invite.crate_id))
            .first(&*conn)?;

        insert_into(crate_owners::table)
            .values(&CrateOwner {
                crate_id: crate_invite.crate_id,
                owner_id: user_id,
                created_by: pending_crate_owner.invited_by_user_id,
                owner_kind: OwnerKind::User as i32,
                email_notifications: true,
            })
            .on_conflict(crate_owners::table.primary_key())
            .do_update()
            .set(crate_owners::deleted.eq(false))
            .execute(conn)?;
        delete(crate_owner_invitations::table.find((user_id, crate_invite.crate_id)))
            .execute(conn)?;

        #[derive(Serialize)]
        struct R {
            crate_owner_invitation: InvitationResponse,
        }
        Ok(req.json(&R {
            crate_owner_invitation: crate_invite,
        }))
    })
}

fn decline_invite(
    req: &dyn RequestExt,
    conn: &PgConnection,
    crate_invite: InvitationResponse,
    user_id: i32,
) -> EndpointResult {
    use diesel::delete;

    delete(crate_owner_invitations::table.find((user_id, crate_invite.crate_id))).execute(conn)?;

    #[derive(Serialize)]
    struct R {
        crate_owner_invitation: InvitationResponse,
    }

    Ok(req.json(&R {
        crate_owner_invitation: crate_invite,
    }))
}
<|endoftext|>


<commit_before>//! leveldb iterators
//!
//! Iteration is one of the most important parts of leveldb. This module provides
//! Iterators to iterate over key, values and pairs of both.
use cbits::leveldb::{leveldb_iterator_t,leveldb_iter_seek_to_first,leveldb_iter_destroy,leveldb_iter_seek_to_last,
leveldb_create_iterator,leveldb_iter_valid,leveldb_iter_next,leveldb_iter_key,leveldb_iter_value,leveldb_readoptions_destroy};
use libc::{size_t};
use std::iter;
use super::Database;
use super::options::{ReadOptions,c_readoptions};
use super::db_key::{Key,from_u8};

#[allow(missing_docs)]
struct RawIterator {
  ptr: *mut leveldb_iterator_t,
}

#[allow(missing_docs)]
impl Drop for RawIterator {
  fn drop(&mut self) {
    unsafe { leveldb_iter_destroy(self.ptr) }
  }
}

/// An iterator over the leveldb keyspace.
///
/// Returns key and value as a tuple.
pub struct Iterator<'a, K: Key> {
  start: bool,
  // Iterator accesses the Database through a leveldb_iter_t pointer
  // but needs to hold the reference for lifetime tracking
  #[allow(dead_code)]
  database: &'a Database<K>,
  iter: RawIterator
}

/// An iterator over the leveldb keyspace.
///
/// Returns just the keys.
pub struct KeyIterator<'a, K: Key> {
  start: bool,
  // Iterator accesses the Database through a leveldb_iter_t pointer
  // but needs to hold the reference for lifetime tracking
  #[allow(dead_code)]
  database: &'a Database<K>,
  iter: RawIterator
}

/// An iterator over the leveldb keyspace.
///
/// Returns just the value.
pub struct ValueIterator<'a,K: Key> {
  start: bool,
  // Iterator accesses the Database through a leveldb_iter_t pointer
  // but needs to hold the reference for lifetime tracking
  #[allow(dead_code)]
  database: &'a Database<K>,
  iter: RawIterator
}

/// A trait to allow access to the three main iteration styles of leveldb.
pub trait Iterable<K: Key> {
  /// Return an Iterator iterating over (Key,Value) pairs
  fn iter(&self, options: ReadOptions) -> Iterator<K>;
  /// Returns an Iterator iterating over Keys only.
  fn keys_iter(&self, options: ReadOptions) -> KeyIterator<K>;
  /// Returns an Iterator iterating over Values only.
  fn value_iter(&self, options: ReadOptions) -> ValueIterator<K>;
}

impl<K: Key + Ord> Iterable<K> for Database<K> {
  fn iter(&self, options: ReadOptions) -> Iterator<K> {
    Iterator::new(self, options)
  }

  fn keys_iter(&self, options: ReadOptions) -> KeyIterator<K> {
    KeyIterator::new(self, options)
  }

  fn value_iter(&self, options: ReadOptions) -> ValueIterator<K> {
    ValueIterator::new(self, options)
  }
}

#[allow(missing_docs)]
trait LevelDBIterator<K: Key> {
  #[inline]
  fn raw_iterator(&self) -> *mut leveldb_iterator_t;

  #[inline]
  fn start(&self) -> bool;

  #[inline]
  fn started(&mut self);

  fn valid(&self) -> bool {
    unsafe { leveldb_iter_valid(self.raw_iterator()) != 0 }
  }

  fn seek_to_first(&self) {
    unsafe { leveldb_iter_seek_to_first(self.raw_iterator()) }
  }

  fn advance(&mut self) -> bool {
    unsafe {
      if !self.start() {
        leveldb_iter_next(self.raw_iterator());
      } else {
        self.started();
      }
    }
    self.valid()
  }

  fn seek_last(&self) {
    unsafe {
      leveldb_iter_seek_to_last(self.raw_iterator());
    }
  }

  fn key(&self) -> K {
    unsafe {
      let length: size_t = 0;
      let value = leveldb_iter_key(self.raw_iterator(),
                                   &length) as *const u8;
      from_u8(Vec::from_raw_buf(value, length as uint).as_slice())
    }
  }

  fn value(&self) -> Vec<u8> {
    unsafe {
      let length: size_t = 0;
      let value = leveldb_iter_value(self.raw_iterator(),
                                     &length) as *const u8;
      Vec::from_raw_buf(value, length as uint)
    }
  }
}

impl<'a, K: Key> Iterator<'a, K> {
  fn new(database: &'a Database<K>,
         options: ReadOptions) -> Iterator<'a,K> {
    unsafe {
      let c_readoptions = c_readoptions(options);
      let ptr = leveldb_create_iterator(database.database.ptr,
                                        c_readoptions);
      leveldb_readoptions_destroy(c_readoptions);
      leveldb_iter_seek_to_first(ptr);
      Iterator { start: true, iter: RawIterator { ptr: ptr }, database: database }
    }
  }

  /// return the last element of the iterator
  pub fn last(self) -> Option<(K,Vec<u8>)> {
    self.seek_last();
    Some((self.key(), self.value()))
  }
}

impl<'a, K: Key> LevelDBIterator<K> for Iterator<'a,K> {
  #[inline]
  fn raw_iterator(&self) -> *mut leveldb_iterator_t {
    self.iter.ptr
  }

  #[inline]
  fn start(&self) -> bool {
    self.start
  }

  #[inline]
  fn started(&mut self) {
    self.start = false
  }
}

impl<'a,K: Key> KeyIterator<'a,K> {
  fn new(database: &'a Database<K>,
         options: ReadOptions) -> KeyIterator<K> {
    unsafe {
      let c_readoptions = c_readoptions(options);
      let ptr = leveldb_create_iterator(database.database.ptr,
                                        c_readoptions);
      leveldb_readoptions_destroy(c_readoptions);
      leveldb_iter_seek_to_first(ptr);
      KeyIterator { start: true, iter: RawIterator { ptr: ptr }, database: database }
    }
  }

  /// return the last element of the iterator
  pub fn last(self) -> Option<K> {
    self.seek_last();
    Some(self.key())
  }
}

impl<'a,K: Key> LevelDBIterator<K> for KeyIterator<'a,K> {
  #[inline]
  fn raw_iterator(&self) -> *mut leveldb_iterator_t {
    self.iter.ptr
  }

  #[inline]
  fn start(&self) -> bool {
    self.start
  }

  #[inline]
  fn started(&mut self) {
    self.start = false
  }
}

impl<'a,K: Key> ValueIterator<'a,K> {
  fn new(database: &'a Database<K>,
         options: ReadOptions) -> ValueIterator<K> {
    unsafe {
      let c_readoptions = c_readoptions(options);
      let ptr = leveldb_create_iterator(database.database.ptr,
                                        c_readoptions);
      leveldb_readoptions_destroy(c_readoptions);
      leveldb_iter_seek_to_first(ptr);
      ValueIterator { start: true, iter: RawIterator { ptr: ptr }, database: database }
    }
  }

  /// return the last element of the iterator
  pub fn last(self) -> Option<Vec<u8>> {
     self.seek_last();
     Some(self.value())
  }
}

impl<'a,K: Key> LevelDBIterator<K> for ValueIterator<'a,K> {
  #[inline]
  fn raw_iterator(&self) -> *mut leveldb_iterator_t {
    self.iter.ptr
  }

  #[inline]
  fn start(&self) -> bool {
    self.start
  }

  #[inline]
  fn started(&mut self) {
    self.start = false
  }
}

impl<'a,K: Key> iter::Iterator<(K,Vec<u8>)> for Iterator<'a,K> {
  fn next(&mut self) -> Option<(K,Vec<u8>)> {
    if self.advance() {
      Some((self.key(), self.value()))
    } else {
      None
    }
  }
}

impl<'a, K: Key> iter::Iterator<K> for KeyIterator<'a,K> {
  fn next(&mut self) -> Option<K> {
    if self.advance() {
      Some(self.key())
    } else {
      None
    }
  }
}

impl<'a, K: Key> iter::Iterator<Vec<u8>> for ValueIterator<'a,K> {
  fn next(&mut self) -> Option<Vec<u8>> {
    if self.advance() {
      Some(self.value())
    } else {
      None
    }
  }
}
<commit_msg>Add seek() method<commit_after>//! leveldb iterators
//!
//! Iteration is one of the most important parts of leveldb. This module provides
//! Iterators to iterate over key, values and pairs of both.
use cbits::leveldb::{leveldb_iterator_t,leveldb_iter_seek_to_first,leveldb_iter_destroy,leveldb_iter_seek_to_last,
leveldb_create_iterator,leveldb_iter_valid,leveldb_iter_next,leveldb_iter_key,leveldb_iter_value,leveldb_readoptions_destroy, leveldb_iter_seek};
use libc::{size_t,c_char};
use std::iter;
use super::Database;
use super::options::{ReadOptions,c_readoptions};
use super::db_key::{Key,from_u8};

#[allow(missing_docs)]
struct RawIterator {
  ptr: *mut leveldb_iterator_t,
}

#[allow(missing_docs)]
impl Drop for RawIterator {
  fn drop(&mut self) {
    unsafe { leveldb_iter_destroy(self.ptr) }
  }
}

/// An iterator over the leveldb keyspace.
///
/// Returns key and value as a tuple.
pub struct Iterator<'a, K: Key> {
  start: bool,
  // Iterator accesses the Database through a leveldb_iter_t pointer
  // but needs to hold the reference for lifetime tracking
  #[allow(dead_code)]
  database: &'a Database<K>,
  iter: RawIterator
}

/// An iterator over the leveldb keyspace.
///
/// Returns just the keys.
pub struct KeyIterator<'a, K: Key> {
  start: bool,
  // Iterator accesses the Database through a leveldb_iter_t pointer
  // but needs to hold the reference for lifetime tracking
  #[allow(dead_code)]
  database: &'a Database<K>,
  iter: RawIterator
}

/// An iterator over the leveldb keyspace.
///
/// Returns just the value.
pub struct ValueIterator<'a,K: Key> {
  start: bool,
  // Iterator accesses the Database through a leveldb_iter_t pointer
  // but needs to hold the reference for lifetime tracking
  #[allow(dead_code)]
  database: &'a Database<K>,
  iter: RawIterator
}

/// A trait to allow access to the three main iteration styles of leveldb.
pub trait Iterable<K: Key> {
  /// Return an Iterator iterating over (Key,Value) pairs
  fn iter(&self, options: ReadOptions) -> Iterator<K>;
  /// Returns an Iterator iterating over Keys only.
  fn keys_iter(&self, options: ReadOptions) -> KeyIterator<K>;
  /// Returns an Iterator iterating over Values only.
  fn value_iter(&self, options: ReadOptions) -> ValueIterator<K>;
}

impl<K: Key + Ord> Iterable<K> for Database<K> {
  fn iter(&self, options: ReadOptions) -> Iterator<K> {
    Iterator::new(self, options)
  }

  fn keys_iter(&self, options: ReadOptions) -> KeyIterator<K> {
    KeyIterator::new(self, options)
  }

  fn value_iter(&self, options: ReadOptions) -> ValueIterator<K> {
    ValueIterator::new(self, options)
  }
}

#[allow(missing_docs)]
pub trait LevelDBIterator<K: Key> {
  #[inline]
  fn raw_iterator(&self) -> *mut leveldb_iterator_t;

  #[inline]
  fn start(&self) -> bool;

  #[inline]
  fn started(&mut self);

  fn valid(&self) -> bool {
    unsafe { leveldb_iter_valid(self.raw_iterator()) != 0 }
  }

  fn advance(&mut self) -> bool {
    unsafe {
      if !self.start() {
        leveldb_iter_next(self.raw_iterator());
      } else {
        self.started();
      }
    }
    self.valid()
  }

  fn key(&self) -> K {
    unsafe {
      let length: size_t = 0;
      let value = leveldb_iter_key(self.raw_iterator(),
                                   &length) as *const u8;
      from_u8(Vec::from_raw_buf(value, length as uint).as_slice())
    }
  }

  fn value(&self) -> Vec<u8> {
    unsafe {
      let length: size_t = 0;
      let value = leveldb_iter_value(self.raw_iterator(),
                                     &length) as *const u8;
      Vec::from_raw_buf(value, length as uint)
    }
  }
}

#[allow(missing_docs)]
pub trait LevelDBIteratorExt<K: Key> : LevelDBIterator<K> {
  fn seek_to_first(&self) {
    unsafe { leveldb_iter_seek_to_first(self.raw_iterator()) }
  }

  fn seek_to_last(&self) {
    unsafe { leveldb_iter_seek_to_last(self.raw_iterator()); }
  }

  fn seek(&self, key: K) {
    unsafe {
      key.as_slice(|k| {
        leveldb_iter_seek(self.raw_iterator(),
                          k.as_ptr() as *mut c_char,
                          k.len() as size_t);
      })
    }
  }
}

impl<'a, K: Key> Iterator<'a, K> {
  fn new(database: &'a Database<K>,
         options: ReadOptions) -> Iterator<'a,K> {
    unsafe {
      let c_readoptions = c_readoptions(options);
      let ptr = leveldb_create_iterator(database.database.ptr,
                                        c_readoptions);
      leveldb_readoptions_destroy(c_readoptions);
      leveldb_iter_seek_to_first(ptr);
      Iterator { start: true, iter: RawIterator { ptr: ptr }, database: database }
    }
  }

  /// return the last element of the iterator
  pub fn last(self) -> Option<(K,Vec<u8>)> {
    self.seek_to_last();
    Some((self.key(), self.value()))
  }
}

impl<'a, K: Key> LevelDBIterator<K> for Iterator<'a,K> {
  #[inline]
  fn raw_iterator(&self) -> *mut leveldb_iterator_t {
    self.iter.ptr
  }

  #[inline]
  fn start(&self) -> bool {
    self.start
  }

  #[inline]
  fn started(&mut self) {
    self.start = false
  }
}

impl<'a, K: Key> LevelDBIteratorExt<K> for Iterator<'a,K> { }

impl<'a,K: Key> KeyIterator<'a,K> {
  fn new(database: &'a Database<K>,
         options: ReadOptions) -> KeyIterator<K> {
    unsafe {
      let c_readoptions = c_readoptions(options);
      let ptr = leveldb_create_iterator(database.database.ptr,
                                        c_readoptions);
      leveldb_readoptions_destroy(c_readoptions);
      leveldb_iter_seek_to_first(ptr);
      KeyIterator { start: true, iter: RawIterator { ptr: ptr }, database: database }
    }
  }

  /// return the last element of the iterator
  pub fn last(self) -> Option<K> {
    self.seek_to_last();
    Some(self.key())
  }
}

impl<'a,K: Key> LevelDBIterator<K> for KeyIterator<'a,K> {
  #[inline]
  fn raw_iterator(&self) -> *mut leveldb_iterator_t {
    self.iter.ptr
  }

  #[inline]
  fn start(&self) -> bool {
    self.start
  }

  #[inline]
  fn started(&mut self) {
    self.start = false
  }
}

impl<'a, K: Key> LevelDBIteratorExt<K> for KeyIterator<'a,K> { }

impl<'a,K: Key> ValueIterator<'a,K> {
  fn new(database: &'a Database<K>,
         options: ReadOptions) -> ValueIterator<K> {
    unsafe {
      let c_readoptions = c_readoptions(options);
      let ptr = leveldb_create_iterator(database.database.ptr,
                                        c_readoptions);
      leveldb_readoptions_destroy(c_readoptions);
      leveldb_iter_seek_to_first(ptr);
      ValueIterator { start: true, iter: RawIterator { ptr: ptr }, database: database }
    }
  }

  /// return the last element of the iterator
  pub fn last(self) -> Option<Vec<u8>> {
     self.seek_to_last();
     Some(self.value())
  }
}

impl<'a,K: Key> LevelDBIterator<K> for ValueIterator<'a,K> {
  #[inline]
  fn raw_iterator(&self) -> *mut leveldb_iterator_t {
    self.iter.ptr
  }

  #[inline]
  fn start(&self) -> bool {
    self.start
  }

  #[inline]
  fn started(&mut self) {
    self.start = false
  }
}

impl<'a, K: Key> LevelDBIteratorExt<K> for ValueIterator<'a,K> { }

impl<'a,K: Key> iter::Iterator<(K,Vec<u8>)> for Iterator<'a,K> {
  fn next(&mut self) -> Option<(K,Vec<u8>)> {
    if self.advance() {
      Some((self.key(), self.value()))
    } else {
      None
    }
  }
}

impl<'a, K: Key> iter::Iterator<K> for KeyIterator<'a,K> {
  fn next(&mut self) -> Option<K> {
    if self.advance() {
      Some(self.key())
    } else {
      None
    }
  }
}

impl<'a, K: Key> iter::Iterator<Vec<u8>> for ValueIterator<'a,K> {
  fn next(&mut self) -> Option<Vec<u8>> {
    if self.advance() {
      Some(self.value())
    } else {
      None
    }
  }
}
<|endoftext|>


<commit_before>use super::*;

impl Editor {
    /// Get the x coordinate of the current cursor
    /// (if out of bound, it's the length which is given)
    pub fn x(&self) -> usize {
        let x = self.cursor().x;
        let y = self.cursor().y;
        if x > self.text[y].len() {
            self.text[y].len()
        } else {
            x
        }
    }

    /// Get y coordinate
    pub fn y(&self) -> usize {
        self.cursor().y
    }
}
<commit_msg>Make .y() saturating<commit_after>use super::*;

impl Editor {
    /// Get the x coordinate of the current cursor
    /// (if out of bound, it's the length which is given)
    pub fn x(&self) -> usize {
        let x = self.cursor().x;
        let y = self.cursor().y;
        if y >= self.text.len() {
            0
        } else {
            if x > self.text[y].len() {
                self.text[y].len()
            } else {
                x
            }
        }
    }

    /// Get y coordinate
    pub fn y(&self) -> usize {
        let y = self.cursor().y;
        if y >= self.text.len() {
            self.text.len() - 1
        } else {
            y
        }
    }
}
<|endoftext|>


<commit_before>//! This module is UNSTABLE, the reason is - recently added.

use std::convert::From;
use std::io::Write;

use super::super::value::{Float, Integer, ValueRef};
use super::FixedValueWriteError;
use super::ValueWriteError;
use super::WriteError;
use super::write_array_len;
use super::write_bin;
use super::write_bool;
use super::write_ext_meta;
use super::write_f32;
use super::write_f64;
use super::write_map_len;
use super::write_nil;
use super::write_sint;
use super::write_str;
use super::write_uint;

#[derive(Debug)]
pub struct Error(WriteError);

impl From<FixedValueWriteError> for Error {
    fn from(err: FixedValueWriteError) -> Error {
        match err {
            FixedValueWriteError(err) => Error(err)
        }
    }
}

impl From<ValueWriteError> for Error {
    fn from(err: ValueWriteError) -> Error {
        match err {
            ValueWriteError::InvalidMarkerWrite(err) => Error(err),
            ValueWriteError::InvalidDataWrite(err) => Error(err)
        }
    }
}

pub fn write_value_ref<W>(wr: &mut W, val: &ValueRef) -> Result<(), Error>
    where W: Write
{
    match val {
        &ValueRef::Nil => try!(write_nil(wr)),
        &ValueRef::Boolean(val) => try!(write_bool(wr, val)),
        &ValueRef::Integer(Integer::U64(val)) => {
            try!(write_uint(wr, val));
        }
        &ValueRef::Integer(Integer::I64(val)) => {
            try!(write_sint(wr, val));
        }
        // TODO: Replace with generic write_float(...).
        &ValueRef::Float(Float::F32(val)) => try!(write_f32(wr, val)),
        &ValueRef::Float(Float::F64(val)) => try!(write_f64(wr, val)),
        &ValueRef::String(val) => {
            try!(write_str(wr, val));
        }
        &ValueRef::Binary(val) => {
            try!(write_bin(wr, val));
        }
        &ValueRef::Array(ref val) => {
            let len = val.len() as u32;

            try!(write_array_len(wr, len));

            for item in val {
                try!(write_value_ref(wr, item));
            }
        }
        &ValueRef::Map(ref val) => {
            let len = val.len() as u32;

            try!(write_map_len(wr, len));

            for &(ref key, ref val) in val {
                try!(write_value_ref(wr, key));
                try!(write_value_ref(wr, val));
            }
        }
        &ValueRef::Ext(ty, data) => {
            try!(write_ext_meta(wr, data.len() as u32, ty));
            try!(wr.write_all(data).map_err(|err| ValueWriteError::InvalidDataWrite(WriteError(err))));
        }
    }

    Ok(())
}
<commit_msg>ValueRef: display trait for encode error.<commit_after>//! This module is UNSTABLE, the reason is - recently added.

use std::convert::From;
use std::fmt;
use std::io::Write;

use super::super::value::{Float, Integer, ValueRef};
use super::FixedValueWriteError;
use super::ValueWriteError;
use super::WriteError;
use super::write_array_len;
use super::write_bin;
use super::write_bool;
use super::write_ext_meta;
use super::write_f32;
use super::write_f64;
use super::write_map_len;
use super::write_nil;
use super::write_sint;
use super::write_str;
use super::write_uint;

#[derive(Debug)]
pub struct Error(WriteError);

impl fmt::Display for Error {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        match self {
            &Error(ref err) => err.fmt(fmt),
        }
    }
}

impl From<FixedValueWriteError> for Error {
    fn from(err: FixedValueWriteError) -> Error {
        match err {
            FixedValueWriteError(err) => Error(err)
        }
    }
}

impl From<ValueWriteError> for Error {
    fn from(err: ValueWriteError) -> Error {
        match err {
            ValueWriteError::InvalidMarkerWrite(err) => Error(err),
            ValueWriteError::InvalidDataWrite(err) => Error(err)
        }
    }
}

pub fn write_value_ref<W>(wr: &mut W, val: &ValueRef) -> Result<(), Error>
    where W: Write
{
    match val {
        &ValueRef::Nil => try!(write_nil(wr)),
        &ValueRef::Boolean(val) => try!(write_bool(wr, val)),
        &ValueRef::Integer(Integer::U64(val)) => {
            try!(write_uint(wr, val));
        }
        &ValueRef::Integer(Integer::I64(val)) => {
            try!(write_sint(wr, val));
        }
        // TODO: Replace with generic write_float(...).
        &ValueRef::Float(Float::F32(val)) => try!(write_f32(wr, val)),
        &ValueRef::Float(Float::F64(val)) => try!(write_f64(wr, val)),
        &ValueRef::String(val) => {
            try!(write_str(wr, val));
        }
        &ValueRef::Binary(val) => {
            try!(write_bin(wr, val));
        }
        &ValueRef::Array(ref val) => {
            let len = val.len() as u32;

            try!(write_array_len(wr, len));

            for item in val {
                try!(write_value_ref(wr, item));
            }
        }
        &ValueRef::Map(ref val) => {
            let len = val.len() as u32;

            try!(write_map_len(wr, len));

            for &(ref key, ref val) in val {
                try!(write_value_ref(wr, key));
                try!(write_value_ref(wr, val));
            }
        }
        &ValueRef::Ext(ty, data) => {
            try!(write_ext_meta(wr, data.len() as u32, ty));
            try!(wr.write_all(data).map_err(|err| ValueWriteError::InvalidDataWrite(WriteError(err))));
        }
    }

    Ok(())
}

#[cfg(test)]
mod test {
    #[test]
    fn display_trait() {
        use std::io;
        use super::super::WriteError;
        use super::Error;

        // Delegates to I/O Error.
        let err = Error(WriteError(io::Error::new(io::ErrorKind::Other, "unexpected EOF")));

        assert_eq!("err: error while writing MessagePack'ed value", format!("err: {}", err));
    }
}
<|endoftext|>


<commit_before>extern crate regex;
use regex::Regex;

use expression;
use expression::enums;

pub type Expression = expression::Expression;

pub fn parse_input(input: &String,
               numeric_regex: &Regex,
               function_regex: &Regex)
               -> (String, Result<Expression, String>) {
    // 1. Replace everthing except letters/numbers with their enums
    // 2. Then go through and replace things with Literals or functions
    let mut variable: String = String::new();
    let mut expr: Expression = Expression::new(Vec::new());
    let mut builder: String = String::new();
    for c in input.chars() {
        match c {
            '(' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Open);
            }
            ')' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Close);
            }
            '+' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Op(enums::Operator::Add));
            }
            '-' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                    expr.push(enums::Token::Op(enums::Operator::Sub));
                } else if builder.len() == 0 {
                    expr.push(enums::Token::Op(enums::Operator::Negate));
                }
            }
            '*' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Op(enums::Operator::Mul));
            }
            '/' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Op(enums::Operator::Div));
            }
            '^' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Op(enums::Operator::Pow));
            }
            ',' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Comma);
            }
            '=' => {
                if builder.len() > 0 {
                    variable = builder.clone();
                    builder = String::new();
                }
            }
            _ => {
                builder.push(c);
            }
        }
    }
    if builder.len() > 0 {
        if numeric_regex.is_match(&builder[..]) {
            expr.push(enums::Token::Literal(builder.clone()));
        } else if function_regex.is_match(&builder[..]) {
            expr.push(enums::map_string_to_func(&builder));
        } else {
            expr.push(enums::Token::Var(builder.clone()));
        }
    }
    let mut op_stack: Vec<enums::Token> = Vec::with_capacity(input.len());
    let mut out_queue: Vec<enums::Token> = Vec::with_capacity(input.len());
    for i in 0..expr.len() {
        let current_token = expr.get_token(i);
        match current_token {
            &enums::Token::Literal(ref x) => out_queue.push(enums::Token::Literal(x.clone())),
            &enums::Token::Func(ref x) => op_stack.push(enums::Token::Func(x.clone())),
            &enums::Token::Comma => {
                loop {
                    let stack_token = op_stack.pop();
                    if !stack_token.is_some() {
                        return (variable,
                                Err("Malformed Expression, comma but no Parenthesis".to_owned()));
                    }
                    let stack_token = stack_token.unwrap();
                    match stack_token {
                        enums::Token::Open => {
                            op_stack.push(stack_token);
                            break;
                        }
                        _ => out_queue.push(stack_token),
                    }
                }
            }
            &enums::Token::Op(ref o1) => {
                loop {
                    if op_stack.len() < 1 {
                        break;
                    }
                    let o2 = op_stack.pop().unwrap(); // top of stack, must exist based off of previous if
                    match o1 {
                        &enums::Operator::Negate => {
                            op_stack.push(o2);
                            break;
                        }
                        &enums::Operator::Pow => {
                            match o2 {
                                enums::Token::Op(enums::Operator::Negate) => out_queue.push(o2),
                                _ => {
                                    op_stack.push(o2);
                                    break;
                                }
                            }
                        }
                        &enums::Operator::Mul | &enums::Operator::Div => {
                            match o2 {
                                enums::Token::Op(enums::Operator::Negate) |
                                enums::Token::Op(enums::Operator::Pow) |
                                enums::Token::Op(enums::Operator::Mul) |
                                enums::Token::Op(enums::Operator::Div) => out_queue.push(o2),
                                _ => {
                                    op_stack.push(o2);
                                    break;
                                }
                            }
                        }
                        &enums::Operator::Add | &enums::Operator::Sub => {
                            match o2 {
                                enums::Token::Op(enums::Operator::Negate) |
                                enums::Token::Op(enums::Operator::Pow) |
                                enums::Token::Op(enums::Operator::Mul) |
                                enums::Token::Op(enums::Operator::Div) |
                                enums::Token::Op(enums::Operator::Add) |
                                enums::Token::Op(enums::Operator::Sub) => out_queue.push(o2),
                                _ => {
                                    op_stack.push(o2);
                                    break;
                                }
                            }
                        }
                    }
                }
                op_stack.push(enums::Token::Op(o1.clone()));
            }
            &enums::Token::Open => op_stack.push(enums::Token::Open),
            &enums::Token::Close => {
                loop {
                    let stack_token = op_stack.pop();
                    if !stack_token.is_some() {
                        return (variable,
                                Err("Malformed Expression, found a ) without (".to_owned()));
                    }
                    let stack_token = stack_token.unwrap();
                    match stack_token {
                        enums::Token::Open => break,
                        _ => out_queue.push(stack_token),
                    }
                }
                if op_stack.len() > 0 {
                    let next_stack_token = op_stack.pop().unwrap(); // must exist based off of previous if
                    match next_stack_token {
                        enums::Token::Func(ref x) => out_queue.push(enums::Token::Func(x.clone())),
                        _ => op_stack.push(next_stack_token),
                    }
                }
            }
            &enums::Token::Var(ref x) => out_queue.push(enums::Token::Var(x.clone())),
            &enums::Token::Unknown(ref x) => {
                let mut message: String = "You either misspelled a function, or it is not yet \
                                           implemented. The unknown string was: ".to_owned();
                message.push_str(x);
                return (variable, Err(message));
            }
            _ => break,
        }
    }
    while op_stack.len() > 0 {
        out_queue.push(op_stack.pop().unwrap()); // The item must exist
    }
    (variable, Ok(Expression::new(out_queue)))
}<commit_msg>Split the parsing into something simpler<commit_after>extern crate regex;
use regex::Regex;

use expression;
use expression::enums;

pub type Expression = expression::Expression;

pub fn parse_input(input: &String,
               numeric_regex: &Regex,
               function_regex: &Regex)
               -> (String, Result<Expression, String>) {
    let (variable, expr) = string_to_expr(input, numeric_regex, function_regex);
    convert_to_postfix(input, variable, expr)
}

fn string_to_expr(input: &String,
                  numeric_regex: &Regex,
	              function_regex: &Regex)
                  -> (String, Expression) {
    // 1. Replace everthing except letters/numbers with their enums
    // 2. Then go through and replace things with Literals or functions
    let mut variable: String = String::new();
    let mut expr: Expression = Expression::new(Vec::new());
    let mut builder: String = String::new();
    for c in input.chars() {
        match c {
            '(' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Open);
            }
            ')' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Close);
            }
            '+' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Op(enums::Operator::Add));
            }
            '-' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                    expr.push(enums::Token::Op(enums::Operator::Sub));
                } else if builder.len() == 0 {
                    expr.push(enums::Token::Op(enums::Operator::Negate));
                }
            }
            '*' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Op(enums::Operator::Mul));
            }
            '/' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Op(enums::Operator::Div));
            }
            '^' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Op(enums::Operator::Pow));
            }
            ',' => {
                if builder.len() > 0 {
                    if numeric_regex.is_match(&builder[..]) {
                        expr.push(enums::Token::Literal(builder.clone()));
                    } else if function_regex.is_match(&builder[..]) {
                        expr.push(enums::map_string_to_func(&builder));
                    } else {
                        expr.push(enums::Token::Var(builder.clone()));
                    }
                    builder = String::new();
                }
                expr.push(enums::Token::Comma);
            }
            '=' => {
                if builder.len() > 0 {
                    variable = builder.clone();
                    builder = String::new();
                }
            }
            _ => {
                builder.push(c);
            }
        }
    }
    if builder.len() > 0 {
        if numeric_regex.is_match(&builder[..]) {
            expr.push(enums::Token::Literal(builder.clone()));
        } else if function_regex.is_match(&builder[..]) {
            expr.push(enums::map_string_to_func(&builder));
        } else {
            expr.push(enums::Token::Var(builder.clone()));
        }
    }
    (variable, expr)
}

fn convert_to_postfix(input: &String, variable: String, expr: Expression) -> (String, Result<Expression, String>) {
    let mut op_stack: Vec<enums::Token> = Vec::with_capacity(input.len());
    let mut out_queue: Vec<enums::Token> = Vec::with_capacity(input.len());
    for i in 0..expr.len() {
        let current_token = expr.get_token(i);
        match current_token {
            &enums::Token::Literal(ref x) => out_queue.push(enums::Token::Literal(x.clone())),
            &enums::Token::Func(ref x) => op_stack.push(enums::Token::Func(x.clone())),
            &enums::Token::Comma => {
                loop {
                    let stack_token = op_stack.pop();
                    if !stack_token.is_some() {
                        return (variable,
                                Err("Malformed Expression, comma but no Parenthesis".to_owned()));
                    }
                    let stack_token = stack_token.unwrap();
                    match stack_token {
                        enums::Token::Open => {
                            op_stack.push(stack_token);
                            break;
                        }
                        _ => out_queue.push(stack_token),
                    }
                }
            }
            &enums::Token::Op(ref o1) => {
                loop {
                    if op_stack.len() < 1 {
                        break;
                    }
                    let o2 = op_stack.pop().unwrap(); // top of stack, must exist based off of previous if
                    match o1 {
                        &enums::Operator::Negate => {
                            op_stack.push(o2);
                            break;
                        }
                        &enums::Operator::Pow => {
                            match o2 {
                                enums::Token::Op(enums::Operator::Negate) => out_queue.push(o2),
                                _ => {
                                    op_stack.push(o2);
                                    break;
                                }
                            }
                        }
                        &enums::Operator::Mul | &enums::Operator::Div => {
                            match o2 {
                                enums::Token::Op(enums::Operator::Negate) |
                                enums::Token::Op(enums::Operator::Pow) |
                                enums::Token::Op(enums::Operator::Mul) |
                                enums::Token::Op(enums::Operator::Div) => out_queue.push(o2),
                                _ => {
                                    op_stack.push(o2);
                                    break;
                                }
                            }
                        }
                        &enums::Operator::Add | &enums::Operator::Sub => {
                            match o2 {
                                enums::Token::Op(enums::Operator::Negate) |
                                enums::Token::Op(enums::Operator::Pow) |
                                enums::Token::Op(enums::Operator::Mul) |
                                enums::Token::Op(enums::Operator::Div) |
                                enums::Token::Op(enums::Operator::Add) |
                                enums::Token::Op(enums::Operator::Sub) => out_queue.push(o2),
                                _ => {
                                    op_stack.push(o2);
                                    break;
                                }
                            }
                        }
                    }
                }
                op_stack.push(enums::Token::Op(o1.clone()));
            }
            &enums::Token::Open => op_stack.push(enums::Token::Open),
            &enums::Token::Close => {
                loop {
                    let stack_token = op_stack.pop();
                    if !stack_token.is_some() {
                        return (variable,
                                Err("Malformed Expression, found a ) without (".to_owned()));
                    }
                    let stack_token = stack_token.unwrap();
                    match stack_token {
                        enums::Token::Open => break,
                        _ => out_queue.push(stack_token),
                    }
                }
                if op_stack.len() > 0 {
                    let next_stack_token = op_stack.pop().unwrap(); // must exist based off of previous if
                    match next_stack_token {
                        enums::Token::Func(ref x) => out_queue.push(enums::Token::Func(x.clone())),
                        _ => op_stack.push(next_stack_token),
                    }
                }
            }
            &enums::Token::Var(ref x) => out_queue.push(enums::Token::Var(x.clone())),
            &enums::Token::Unknown(ref x) => {
                let mut message: String = "You either misspelled a function, or it is not yet \
                                           implemented. The unknown string was: ".to_owned();
                message.push_str(x);
                return (variable, Err(message));
            }
            _ => break,
        }
    }
    while op_stack.len() > 0 {
        out_queue.push(op_stack.pop().unwrap()); // The item must exist
    }
    (variable, Ok(Expression::new(out_queue)))
}<|endoftext|>


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

//! An implementation of SipHash 2-4.

use prelude::v1::*;

use ptr;
use super::Hasher;

/// An implementation of SipHash 2-4.
///
/// See: http://131002.net/siphash/
///
/// Consider this as a main "general-purpose" hash for all hashtables: it
/// runs at good speed (competitive with spooky and city) and permits
/// strong _keyed_ hashing. Key your hashtables from a strong RNG,
/// such as `rand::Rng`.
///
/// Although the SipHash algorithm is considered to be cryptographically
/// strong, this implementation has not been reviewed for such purposes.
/// As such, all cryptographic uses of this implementation are strongly
/// discouraged.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SipHasher {
    k0: u64,
    k1: u64,
    length: usize, // how many bytes we've processed
    // v0, v2 and v1, v3 show up in pairs in the algorithm,
    // and simd implementations of SipHash will use vectors
    // of v02 and v13. By placing them in this order in the struct,
    // the compiler can pick up on just a few simd optimizations by itself.
    v0: u64, // hash state
    v2: u64,
    v1: u64,
    v3: u64,
    tail: u64, // unprocessed bytes le
    ntail: usize, // how many bytes in tail are valid
}

// sadly, these macro definitions can't appear later,
// because they're needed in the following defs;
// this design could be improved.

macro_rules! u8to64_le {
    ($buf:expr, $i:expr) =>
    ($buf[0+$i] as u64 |
     ($buf[1+$i] as u64) << 8 |
     ($buf[2+$i] as u64) << 16 |
     ($buf[3+$i] as u64) << 24 |
     ($buf[4+$i] as u64) << 32 |
     ($buf[5+$i] as u64) << 40 |
     ($buf[6+$i] as u64) << 48 |
     ($buf[7+$i] as u64) << 56);
    ($buf:expr, $i:expr, $len:expr) =>
    ({
        let mut t = 0;
        let mut out = 0;
        while t < $len {
            out |= ($buf[t+$i] as u64) << t*8;
            t += 1;
        }
        out
    });
}

/// Load a full u64 word from a byte stream, in LE order. Use
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load u64 from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+8
#[inline]
unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
    debug_assert!(i + 8 <= buf.len());
    let mut data = 0u64;
    ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
    data.to_le()
}

macro_rules! rotl {
    ($x:expr, $b:expr) =>
    (($x << $b) | ($x >> (64_i32.wrapping_sub($b))))
}

macro_rules! compress {
    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
    ({
        $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
        $v0 = rotl!($v0, 32);
        $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
        $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
        $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
        $v2 = rotl!($v2, 32);
    })
}

impl SipHasher {
    /// Creates a new `SipHasher` with the two initial keys set to 0.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new() -> SipHasher {
        SipHasher::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher` that is keyed off the provided keys.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
        let mut state = SipHasher {
            k0: key0,
            k1: key1,
            length: 0,
            v0: 0,
            v1: 0,
            v2: 0,
            v3: 0,
            tail: 0,
            ntail: 0,
        };
        state.reset();
        state
    }

    #[inline]
    fn reset(&mut self) {
        self.length = 0;
        self.v0 = self.k0 ^ 0x736f6d6570736575;
        self.v1 = self.k1 ^ 0x646f72616e646f6d;
        self.v2 = self.k0 ^ 0x6c7967656e657261;
        self.v3 = self.k1 ^ 0x7465646279746573;
        self.ntail = 0;
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Hasher for SipHasher {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        let length = msg.len();
        self.length += length;

        let mut needed = 0;

        if self.ntail != 0 {
            needed = 8 - self.ntail;
            if length < needed {
                self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
                self.ntail += length;
                return
            }

            let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;

            self.v3 ^= m;
            compress!(self.v0, self.v1, self.v2, self.v3);
            compress!(self.v0, self.v1, self.v2, self.v3);
            self.v0 ^= m;

            self.ntail = 0;
        }

        // Buffered tail is now flushed, process new input.
        let len = length - needed;
        let left = len & 0x7;

        let mut i = needed;
        while i < len - left {
            let mi = unsafe { load_u64_le(msg, i) };

            self.v3 ^= mi;
            compress!(self.v0, self.v1, self.v2, self.v3);
            compress!(self.v0, self.v1, self.v2, self.v3);
            self.v0 ^= mi;

            i += 8;
        }

        self.tail = u8to64_le!(msg, i, left);
        self.ntail = left;
    }

    #[inline]
    fn finish(&self) -> u64 {
        let mut v0 = self.v0;
        let mut v1 = self.v1;
        let mut v2 = self.v2;
        let mut v3 = self.v3;

        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;

        v3 ^= b;
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        v0 ^= b;

        v2 ^= 0xff;
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);

        v0 ^ v1 ^ v2 ^ v3
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for SipHasher {
    #[inline]
    fn clone(&self) -> SipHasher {
        SipHasher {
            k0: self.k0,
            k1: self.k1,
            length: self.length,
            v0: self.v0,
            v1: self.v1,
            v2: self.v2,
            v3: self.v3,
            tail: self.tail,
            ntail: self.ntail,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Default for SipHasher {
    fn default() -> SipHasher {
        SipHasher::new()
    }
}
<commit_msg>Clarify documentation of `hash::SipHasher`<commit_after>// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

//! An implementation of SipHash 2-4.

use prelude::v1::*;

use ptr;
use super::Hasher;

/// An implementation of SipHash 2-4.
///
/// See: http://131002.net/siphash/
///
/// This is the default hashing function used by standard library (eg.
/// `collections::HashMap` uses it by default).
///
/// SipHash is a general-purpose hashing function: it runs at a good
/// speed (competitive with Spooky and City) and permits strong _keyed_
/// hashing. This lets you key your hashtables from a strong RNG, such
/// as [`rand::Rng`](https://doc.rust-lang.org/rand/rand/trait.Rng.html).
///
/// Although the SipHash algorithm is considered to be cryptographically
/// strong, this implementation has not been reviewed for such purposes.
/// As such, all cryptographic uses of this implementation are _strongly
/// discouraged_.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SipHasher {
    k0: u64,
    k1: u64,
    length: usize, // how many bytes we've processed
    // v0, v2 and v1, v3 show up in pairs in the algorithm,
    // and simd implementations of SipHash will use vectors
    // of v02 and v13. By placing them in this order in the struct,
    // the compiler can pick up on just a few simd optimizations by itself.
    v0: u64, // hash state
    v2: u64,
    v1: u64,
    v3: u64,
    tail: u64, // unprocessed bytes le
    ntail: usize, // how many bytes in tail are valid
}

// sadly, these macro definitions can't appear later,
// because they're needed in the following defs;
// this design could be improved.

macro_rules! u8to64_le {
    ($buf:expr, $i:expr) =>
    ($buf[0+$i] as u64 |
     ($buf[1+$i] as u64) << 8 |
     ($buf[2+$i] as u64) << 16 |
     ($buf[3+$i] as u64) << 24 |
     ($buf[4+$i] as u64) << 32 |
     ($buf[5+$i] as u64) << 40 |
     ($buf[6+$i] as u64) << 48 |
     ($buf[7+$i] as u64) << 56);
    ($buf:expr, $i:expr, $len:expr) =>
    ({
        let mut t = 0;
        let mut out = 0;
        while t < $len {
            out |= ($buf[t+$i] as u64) << t*8;
            t += 1;
        }
        out
    });
}

/// Load a full u64 word from a byte stream, in LE order. Use
/// `copy_nonoverlapping` to let the compiler generate the most efficient way
/// to load u64 from a possibly unaligned address.
///
/// Unsafe because: unchecked indexing at i..i+8
#[inline]
unsafe fn load_u64_le(buf: &[u8], i: usize) -> u64 {
    debug_assert!(i + 8 <= buf.len());
    let mut data = 0u64;
    ptr::copy_nonoverlapping(buf.get_unchecked(i), &mut data as *mut _ as *mut u8, 8);
    data.to_le()
}

macro_rules! rotl {
    ($x:expr, $b:expr) =>
    (($x << $b) | ($x >> (64_i32.wrapping_sub($b))))
}

macro_rules! compress {
    ($v0:expr, $v1:expr, $v2:expr, $v3:expr) =>
    ({
        $v0 = $v0.wrapping_add($v1); $v1 = rotl!($v1, 13); $v1 ^= $v0;
        $v0 = rotl!($v0, 32);
        $v2 = $v2.wrapping_add($v3); $v3 = rotl!($v3, 16); $v3 ^= $v2;
        $v0 = $v0.wrapping_add($v3); $v3 = rotl!($v3, 21); $v3 ^= $v0;
        $v2 = $v2.wrapping_add($v1); $v1 = rotl!($v1, 17); $v1 ^= $v2;
        $v2 = rotl!($v2, 32);
    })
}

impl SipHasher {
    /// Creates a new `SipHasher` with the two initial keys set to 0.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new() -> SipHasher {
        SipHasher::new_with_keys(0, 0)
    }

    /// Creates a `SipHasher` that is keyed off the provided keys.
    #[inline]
    #[stable(feature = "rust1", since = "1.0.0")]
    pub fn new_with_keys(key0: u64, key1: u64) -> SipHasher {
        let mut state = SipHasher {
            k0: key0,
            k1: key1,
            length: 0,
            v0: 0,
            v1: 0,
            v2: 0,
            v3: 0,
            tail: 0,
            ntail: 0,
        };
        state.reset();
        state
    }

    #[inline]
    fn reset(&mut self) {
        self.length = 0;
        self.v0 = self.k0 ^ 0x736f6d6570736575;
        self.v1 = self.k1 ^ 0x646f72616e646f6d;
        self.v2 = self.k0 ^ 0x6c7967656e657261;
        self.v3 = self.k1 ^ 0x7465646279746573;
        self.ntail = 0;
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Hasher for SipHasher {
    #[inline]
    fn write(&mut self, msg: &[u8]) {
        let length = msg.len();
        self.length += length;

        let mut needed = 0;

        if self.ntail != 0 {
            needed = 8 - self.ntail;
            if length < needed {
                self.tail |= u8to64_le!(msg, 0, length) << 8 * self.ntail;
                self.ntail += length;
                return
            }

            let m = self.tail | u8to64_le!(msg, 0, needed) << 8 * self.ntail;

            self.v3 ^= m;
            compress!(self.v0, self.v1, self.v2, self.v3);
            compress!(self.v0, self.v1, self.v2, self.v3);
            self.v0 ^= m;

            self.ntail = 0;
        }

        // Buffered tail is now flushed, process new input.
        let len = length - needed;
        let left = len & 0x7;

        let mut i = needed;
        while i < len - left {
            let mi = unsafe { load_u64_le(msg, i) };

            self.v3 ^= mi;
            compress!(self.v0, self.v1, self.v2, self.v3);
            compress!(self.v0, self.v1, self.v2, self.v3);
            self.v0 ^= mi;

            i += 8;
        }

        self.tail = u8to64_le!(msg, i, left);
        self.ntail = left;
    }

    #[inline]
    fn finish(&self) -> u64 {
        let mut v0 = self.v0;
        let mut v1 = self.v1;
        let mut v2 = self.v2;
        let mut v3 = self.v3;

        let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;

        v3 ^= b;
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        v0 ^= b;

        v2 ^= 0xff;
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);
        compress!(v0, v1, v2, v3);

        v0 ^ v1 ^ v2 ^ v3
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Clone for SipHasher {
    #[inline]
    fn clone(&self) -> SipHasher {
        SipHasher {
            k0: self.k0,
            k1: self.k1,
            length: self.length,
            v0: self.v0,
            v1: self.v1,
            v2: self.v2,
            v3: self.v3,
            tail: self.tail,
            ntail: self.ntail,
        }
    }
}

#[stable(feature = "rust1", since = "1.0.0")]
impl Default for SipHasher {
    fn default() -> SipHasher {
        SipHasher::new()
    }
}
<|endoftext|>


<commit_before>use std::ops::Deref;

use config::gobjects::GObject;
use env::Env;
use library;
use nameutil::*;
use super::*;
use super::child_properties::ChildProperties;
use super::imports::Imports;
use super::info_base::InfoBase;
use super::signatures::Signatures;
use traits::*;

#[derive(Default)]
pub struct Info {
    pub base: InfoBase,
    pub c_type: String,
    pub get_type: String,
    pub supertypes: Vec<general::StatusedTypeId>,
    pub generate_trait: bool,
    pub has_constructors: bool,
    pub has_methods: bool,
    pub has_functions: bool,
    pub signals: Vec<signals::Info>,
    pub trampolines: trampolines::Trampolines,
    pub properties: Vec<properties::Property>,
    pub child_properties: ChildProperties,
    pub signatures: Signatures,
}

impl Info {
    pub fn has_signals(&self) -> bool {
        self.signals.iter().any(|s| s.trampoline_name.is_ok())
    }
}

impl Deref for Info {
    type Target = InfoBase;

    fn deref(&self) -> &InfoBase {
        &self.base
    }
}

pub fn class(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info> {
    info!("Analyzing class {}", obj.name);
    let full_name = obj.name.clone();

    let class_tid = match env.library.find_type(0, &full_name) {
        Some(tid) => tid,
        None => return None,
    };

    let type_ = env.type_(class_tid);

    let name: String = split_namespace_name(&full_name).1.into();

    let klass: &library::Class = match type_.maybe_ref() {
        Some(klass) => klass,
        None => return None,
    };

    let mut imports = Imports::new();
    imports.add("glib::translate::*", None);
    imports.add("ffi", None);

    let supertypes = supertypes::analyze(env, class_tid, &mut imports);

    let mut generate_trait = obj.generate_trait;

    for child_tid in env.class_hierarchy.subtypes(class_tid) {
        let child_name = child_tid.full_name(&env.library);
        let status = env.config.objects.get(&child_name)
            .map(|o| o.status)
            .unwrap_or_default();
        if status.normal() {
            generate_trait = true;
            break;
        }
    }

    let mut trampolines = trampolines::Trampolines::with_capacity(klass.signals.len());
    let mut signatures = Signatures::with_capacity(klass.functions.len());

    let mut functions = functions::analyze(env, &klass.functions, class_tid, obj,
                                           &mut imports, Some(&mut signatures), Some(deps));
    let specials = special_functions::extract(&mut functions);
    // `copy` will duplicate an object while `clone` just adds a reference
    special_functions::unhide(&mut functions, &specials, special_functions::Type::Copy);
    special_functions::analyze_imports(&specials, &mut imports);

    let signals = signals::analyze(env, &klass.signals, class_tid, generate_trait,
                                   &mut trampolines, obj, &mut imports);
    let properties = properties::analyze(env, &klass.properties, class_tid, obj, &mut imports,
                                         &signatures, deps);

    let (version, deprecated_version) = info_base::versions(env, obj, &functions, klass.version,
         klass.deprecated_version);

    let child_properties = child_properties::analyze(env, obj.child_properties.as_ref(), class_tid,
                                                     &mut imports);

    let has_methods = functions.iter()
            .any(|f| f.kind == library::FunctionKind::Method);
    let has_signals = signals.iter().any(|s| s.trampoline_name.is_ok());

    // There's no point in generating a trait if there are no signals, methods, properties
    // and child properties: it would be empty
    if generate_trait && !has_signals && !has_methods && properties.is_empty() && child_properties.is_empty() {
        generate_trait = false;
    }

    if generate_trait && (!properties.is_empty() || has_signals) {
        imports.add("glib", None);
    }
    if generate_trait && (has_methods || !properties.is_empty() || !child_properties.is_empty() || has_signals) {
        imports.add("glib::object::IsA", None);
    }

    //don't `use` yourself
    imports.remove(&name);

    imports.clean_glib(env);

    let base = InfoBase {
        full_name: full_name,
        type_id: class_tid,
        name: name,
        functions: functions,
        specials: specials,
        imports: imports,
        version: version,
        deprecated_version: deprecated_version,
        cfg_condition: obj.cfg_condition.clone(),
    };

    // patch up trait methods in the symbol table
    if generate_trait {
        let mut symbols = env.symbols.borrow_mut();
        for func in base.methods() {
            if let Some(symbol) = symbols.by_c_name_mut(&func.glib_name) {
                symbol.make_trait_method();
            }
        }
    }

    let has_constructors = !base.constructors().is_empty();
    let has_functions = !base.functions().is_empty();

    let info = Info {
        base: base,
        c_type: klass.c_type.clone(),
        get_type: klass.glib_get_type.clone(),
        supertypes: supertypes,
        generate_trait: generate_trait,
        has_constructors: has_constructors,
        has_methods: has_methods,
        has_functions: has_functions,
        signals: signals,
        trampolines: trampolines,
        properties: properties,
        child_properties: child_properties,
        signatures: signatures,
    };

    Some(info)
}

pub fn interface(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info> {
    info!("Analyzing interface {}", obj.name);
    let full_name = obj.name.clone();

    let iface_tid = match env.library.find_type(0, &full_name) {
        Some(tid) => tid,
        None => return None,
    };

    let type_ = env.type_(iface_tid);

    let name: String = split_namespace_name(&full_name).1.into();

    let iface: &library::Interface = match type_.maybe_ref() {
        Some(iface) => iface,
        None => return None,
    };

    let mut imports = Imports::new();
    imports.add("glib::translate::*", None);
    imports.add("ffi", None);
    imports.add("glib::object::IsA", None);

    let supertypes = supertypes::analyze(env, iface_tid, &mut imports);

    let mut trampolines = trampolines::Trampolines::with_capacity(iface.signals.len());
    let mut signatures = Signatures::with_capacity(iface.functions.len());

    let functions = functions::analyze(env, &iface.functions, iface_tid, obj,
                                       &mut imports, Some(&mut signatures), Some(deps));

    let signals = signals::analyze(env, &iface.signals, iface_tid, true,
                                   &mut trampolines, obj, &mut imports);
    let properties = properties::analyze(env, &iface.properties, iface_tid, obj, &mut imports,
                                         &signatures, deps);

    let (version, deprecated_version) = info_base::versions(env, obj, &functions, iface.version,
         iface.deprecated_version);

    if !properties.is_empty() {
        imports.add("glib", None);
    }

    //don't `use` yourself
    imports.remove(&name);

    imports.clean_glib(env);

    let base = InfoBase {
        full_name: full_name,
        type_id: iface_tid,
        name: name,
        functions: functions,
        specials: Default::default(),
        imports: imports,
        version: version,
        deprecated_version: deprecated_version,
        cfg_condition: obj.cfg_condition.clone(),
    };

    let has_methods = !base.methods().is_empty();
    let has_functions = !base.functions().is_empty();

    let info = Info {
        base: base,
        c_type: iface.c_type.clone(),
        get_type: iface.glib_get_type.clone(),
        supertypes: supertypes,
        generate_trait: true,
        has_methods: has_methods,
        has_functions: has_functions,
        signals: signals,
        trampolines: trampolines,
        properties: properties,
        signatures: signatures,
        .. Default::default()
    };

    Some(info)
}
<commit_msg>Log an error if the user requests no trait to be generated but there are subtypes in this crate<commit_after>use std::ops::Deref;

use config::gobjects::GObject;
use env::Env;
use library;
use nameutil::*;
use super::*;
use super::child_properties::ChildProperties;
use super::imports::Imports;
use super::info_base::InfoBase;
use super::signatures::Signatures;
use traits::*;

#[derive(Default)]
pub struct Info {
    pub base: InfoBase,
    pub c_type: String,
    pub get_type: String,
    pub supertypes: Vec<general::StatusedTypeId>,
    pub generate_trait: bool,
    pub has_constructors: bool,
    pub has_methods: bool,
    pub has_functions: bool,
    pub signals: Vec<signals::Info>,
    pub trampolines: trampolines::Trampolines,
    pub properties: Vec<properties::Property>,
    pub child_properties: ChildProperties,
    pub signatures: Signatures,
}

impl Info {
    pub fn has_signals(&self) -> bool {
        self.signals.iter().any(|s| s.trampoline_name.is_ok())
    }
}

impl Deref for Info {
    type Target = InfoBase;

    fn deref(&self) -> &InfoBase {
        &self.base
    }
}

pub fn class(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info> {
    info!("Analyzing class {}", obj.name);
    let full_name = obj.name.clone();

    let class_tid = match env.library.find_type(0, &full_name) {
        Some(tid) => tid,
        None => return None,
    };

    let type_ = env.type_(class_tid);

    let name: String = split_namespace_name(&full_name).1.into();

    let klass: &library::Class = match type_.maybe_ref() {
        Some(klass) => klass,
        None => return None,
    };

    let mut imports = Imports::new();
    imports.add("glib::translate::*", None);
    imports.add("ffi", None);

    let supertypes = supertypes::analyze(env, class_tid, &mut imports);

    let mut generate_trait = obj.generate_trait;

    // Sanity check the user's configuration. It's unlikely that not generating
    // a trait is wanted if there are subtypes in this very crate
    if !generate_trait {
        for child_tid in env.class_hierarchy.subtypes(class_tid) {
            let child_name = child_tid.full_name(&env.library);
            let status = env.config.objects.get(&child_name)
                .map(|o| o.status)
                .unwrap_or_default();
            if status.normal() {
                error!("Not generating trait for {} although subtypes exist", full_name);
                break;
            }
        }
    }

    let mut trampolines = trampolines::Trampolines::with_capacity(klass.signals.len());
    let mut signatures = Signatures::with_capacity(klass.functions.len());

    let mut functions = functions::analyze(env, &klass.functions, class_tid, obj,
                                           &mut imports, Some(&mut signatures), Some(deps));
    let specials = special_functions::extract(&mut functions);
    // `copy` will duplicate an object while `clone` just adds a reference
    special_functions::unhide(&mut functions, &specials, special_functions::Type::Copy);
    special_functions::analyze_imports(&specials, &mut imports);

    let signals = signals::analyze(env, &klass.signals, class_tid, generate_trait,
                                   &mut trampolines, obj, &mut imports);
    let properties = properties::analyze(env, &klass.properties, class_tid, obj, &mut imports,
                                         &signatures, deps);

    let (version, deprecated_version) = info_base::versions(env, obj, &functions, klass.version,
         klass.deprecated_version);

    let child_properties = child_properties::analyze(env, obj.child_properties.as_ref(), class_tid,
                                                     &mut imports);

    let has_methods = functions.iter()
            .any(|f| f.kind == library::FunctionKind::Method);
    let has_signals = signals.iter().any(|s| s.trampoline_name.is_ok());

    // There's no point in generating a trait if there are no signals, methods, properties
    // and child properties: it would be empty
    if generate_trait && !has_signals && !has_methods && properties.is_empty() && child_properties.is_empty() {
        generate_trait = false;
    }

    if generate_trait && (!properties.is_empty() || has_signals) {
        imports.add("glib", None);
    }
    if generate_trait && (has_methods || !properties.is_empty() || !child_properties.is_empty() || has_signals) {
        imports.add("glib::object::IsA", None);
    }

    //don't `use` yourself
    imports.remove(&name);

    imports.clean_glib(env);

    let base = InfoBase {
        full_name: full_name,
        type_id: class_tid,
        name: name,
        functions: functions,
        specials: specials,
        imports: imports,
        version: version,
        deprecated_version: deprecated_version,
        cfg_condition: obj.cfg_condition.clone(),
    };

    // patch up trait methods in the symbol table
    if generate_trait {
        let mut symbols = env.symbols.borrow_mut();
        for func in base.methods() {
            if let Some(symbol) = symbols.by_c_name_mut(&func.glib_name) {
                symbol.make_trait_method();
            }
        }
    }

    let has_constructors = !base.constructors().is_empty();
    let has_functions = !base.functions().is_empty();

    let info = Info {
        base: base,
        c_type: klass.c_type.clone(),
        get_type: klass.glib_get_type.clone(),
        supertypes: supertypes,
        generate_trait: generate_trait,
        has_constructors: has_constructors,
        has_methods: has_methods,
        has_functions: has_functions,
        signals: signals,
        trampolines: trampolines,
        properties: properties,
        child_properties: child_properties,
        signatures: signatures,
    };

    Some(info)
}

pub fn interface(env: &Env, obj: &GObject, deps: &[library::TypeId]) -> Option<Info> {
    info!("Analyzing interface {}", obj.name);
    let full_name = obj.name.clone();

    let iface_tid = match env.library.find_type(0, &full_name) {
        Some(tid) => tid,
        None => return None,
    };

    let type_ = env.type_(iface_tid);

    let name: String = split_namespace_name(&full_name).1.into();

    let iface: &library::Interface = match type_.maybe_ref() {
        Some(iface) => iface,
        None => return None,
    };

    let mut imports = Imports::new();
    imports.add("glib::translate::*", None);
    imports.add("ffi", None);
    imports.add("glib::object::IsA", None);

    let supertypes = supertypes::analyze(env, iface_tid, &mut imports);

    let mut trampolines = trampolines::Trampolines::with_capacity(iface.signals.len());
    let mut signatures = Signatures::with_capacity(iface.functions.len());

    let functions = functions::analyze(env, &iface.functions, iface_tid, obj,
                                       &mut imports, Some(&mut signatures), Some(deps));

    let signals = signals::analyze(env, &iface.signals, iface_tid, true,
                                   &mut trampolines, obj, &mut imports);
    let properties = properties::analyze(env, &iface.properties, iface_tid, obj, &mut imports,
                                         &signatures, deps);

    let (version, deprecated_version) = info_base::versions(env, obj, &functions, iface.version,
         iface.deprecated_version);

    if !properties.is_empty() {
        imports.add("glib", None);
    }

    //don't `use` yourself
    imports.remove(&name);

    imports.clean_glib(env);

    let base = InfoBase {
        full_name: full_name,
        type_id: iface_tid,
        name: name,
        functions: functions,
        specials: Default::default(),
        imports: imports,
        version: version,
        deprecated_version: deprecated_version,
        cfg_condition: obj.cfg_condition.clone(),
    };

    let has_methods = !base.methods().is_empty();
    let has_functions = !base.functions().is_empty();

    let info = Info {
        base: base,
        c_type: iface.c_type.clone(),
        get_type: iface.glib_get_type.clone(),
        supertypes: supertypes,
        generate_trait: true,
        has_methods: has_methods,
        has_functions: has_functions,
        signals: signals,
        trampolines: trampolines,
        properties: properties,
        signatures: signatures,
        .. Default::default()
    };

    Some(info)
}
<|endoftext|>