<commit_before>//! # The Redox OS Kernel, version 2
//!
//! The Redox OS Kernel is a hybrid kernel that supports X86 systems and
//! provides Unix-like syscalls for primarily Rust applications
//!
//! ## Syscalls
//! Syscalls in Redox are often handled by userspace `schemes`.
//! The essential syscalls in Redox are as follows:
//!
//! ### Open
//! `open(path: &str, flags: usize) -> Result<file_descriptor: usize>`
//!
//! Open a file, providing a path as a `&str` and flags, defined elsewhere.
//!
//! Returns a number, known as a file descriptor, that is passed to other syscalls
//!
//! ### Close
//! `close(file_descriptor: usize) -> Result<()>`
//!
//! Close a file descriptor, providing the file descriptor from `open`
//!
//! Returns an error, `EBADF`, if the file descriptor was not found.
//!
//! This potential error is often ignored by userspace
//!
//! ### Duplicate
//! `dup(file_descriptor: usize) -> Result<file_descriptor: usize>`
//!
//! Duplicate a file descriptor, providing the file descriptor from `open`
//!
//! Returns a new file descriptor, or an error
//!
//! ### Read
//! `read(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
//!
//! Read from a file descriptor, providing the file descriptor from `open` and a mutable buffer
//!
//! Returns the number of bytes actually read, or an error
//!
//! ### Write
//! `write(file_descriptor: usize, buffer: &[u8]) -> Result<count: usize>`
//!
//! Write to a file descriptor, providing the file descriptor from `open` and a const buffer
//!
//! Returns the number of bytes actually written, or an error
//!
//! ### Stat
//! `fstat(file_descriptor: usize, stat: &mut Stat) -> Result<()>`
//!
//! Get information from a file descriptor, providing the file descriptor from `open`
//! and a mutable Stat struct, defined elsewhere.
//!
//! Returns an error if the operation failed
//!
//! ### Path
//! `fpath(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
//!
//! Read the path of a file descriptor, providing the file descriptor from `open` and
//! a mutable buffer.
//!
//! Returns the number of bytes actually read, or an error
//!
//! The buffer should be 4096 bytes, to ensure that the entire path will fit.
//! An error will be returned, `ENOBUFS`, if the buffer is not long enough for the name.
//! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry.

#![feature(lang_items)]
#![no_std]

#[macro_use]
extern crate bitflags;

use arch::interrupt::{set_interrupts, halt};

/// Architecture specific items
#[macro_use]
extern crate arch;

pub mod panic;

#[no_mangle]
pub extern fn kmain() {
    println!("TEST");

    unsafe { set_interrupts() };
    loop {
        unsafe { halt() };
    }
}
<commit_msg>Add comment<commit_after>//! # The Redox OS Kernel, version 2
//!
//! The Redox OS Kernel is a hybrid kernel that supports X86 systems and
//! provides Unix-like syscalls for primarily Rust applications
//!
//! ## Syscalls
//! Syscalls in Redox are often handled by userspace `schemes`.
//! The essential syscalls in Redox are as follows:
//!
//! ### Open
//! `open(path: &str, flags: usize) -> Result<file_descriptor: usize>`
//!
//! Open a file, providing a path as a `&str` and flags, defined elsewhere.
//!
//! Returns a number, known as a file descriptor, that is passed to other syscalls
//!
//! ### Close
//! `close(file_descriptor: usize) -> Result<()>`
//!
//! Close a file descriptor, providing the file descriptor from `open`
//!
//! Returns an error, `EBADF`, if the file descriptor was not found.
//!
//! This potential error is often ignored by userspace
//!
//! ### Duplicate
//! `dup(file_descriptor: usize) -> Result<file_descriptor: usize>`
//!
//! Duplicate a file descriptor, providing the file descriptor from `open`
//!
//! Returns a new file descriptor, or an error
//!
//! ### Read
//! `read(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
//!
//! Read from a file descriptor, providing the file descriptor from `open` and a mutable buffer
//!
//! Returns the number of bytes actually read, or an error
//!
//! ### Write
//! `write(file_descriptor: usize, buffer: &[u8]) -> Result<count: usize>`
//!
//! Write to a file descriptor, providing the file descriptor from `open` and a const buffer
//!
//! Returns the number of bytes actually written, or an error
//!
//! ### Stat
//! `fstat(file_descriptor: usize, stat: &mut Stat) -> Result<()>`
//!
//! Get information from a file descriptor, providing the file descriptor from `open`
//! and a mutable Stat struct, defined elsewhere.
//!
//! Returns an error if the operation failed
//!
//! ### Path
//! `fpath(file_descriptor: usize, buffer: &mut [u8]) -> Result<count: usize>`
//!
//! Read the path of a file descriptor, providing the file descriptor from `open` and
//! a mutable buffer.
//!
//! Returns the number of bytes actually read, or an error
//!
//! The buffer should be 4096 bytes, to ensure that the entire path will fit.
//! An error will be returned, `ENOBUFS`, if the buffer is not long enough for the name.
//! In this case, it is recommended to add one page, 4096 bytes, to the buffer and retry.

#![feature(lang_items)]
#![no_std]

#[macro_use]
extern crate bitflags;

use arch::interrupt::{set_interrupts, halt};

/// Architecture specific items
#[macro_use]
extern crate arch;

/// Intrinsics for panic handling
pub mod panic;

#[no_mangle]
pub extern fn kmain() {
    println!("TEST");

    unsafe { set_interrupts() };
    loop {
        unsafe { halt() };
    }
}
<|endoftext|>


<commit_before>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use BlockNumber;
use ed25519::{Signature, Public, pubkey_to_address, SIGNATURE_BYTES_LEN, HASH_BYTES_LEN, PUBKEY_BYTES_LEN};
use libproto::blockchain::{Transaction as ProtoTransaction, UnverifiedTransaction as ProtoUnverifiedTransaction, SignedTransaction as ProtoSignedTransaction, Crypto as ProtoCrypto};
use rlp::*;
use std::ops::{Deref, DerefMut};
use std::str::FromStr;
use util::{H256, Address, U256, Bytes, HeapSizeOf, H768};

// pub const STORE_ADDRESS: H160 =  H160( [0xff; 20] );
pub const STORE_ADDRESS: &str = "ffffffffffffffffffffffffffffffffffffffff";

#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    ParseError,
    InvalidHash,
    InvalidSignature,
    InvalidPubKey,
}

#[derive(Debug, Clone, PartialEq, Eq)]
/// Transaction action type.
pub enum Action {
    /// Just store the data.
    Store,
    /// Create creates new contract.
    Create,
    /// Calls contract at given address.
    /// In the case of a transfer, this is the receiver's address.'
    Call(Address),
}

impl Default for Action {
    fn default() -> Action {
        Action::Store
    }
}

impl Decodable for Action {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        if rlp.is_empty() {
            Ok(Action::Create)
        } else {
            let store_addr: Address = STORE_ADDRESS.into();
            let addr: Address = rlp.as_val()?;
            if addr == store_addr { Ok(Action::Store) } else { Ok(Action::Call(addr)) }
        }
    }
}

impl Encodable for Action {
    fn rlp_append(&self, s: &mut RlpStream) {
        let store_addr: Address = STORE_ADDRESS.into();
        match *self {
            Action::Create => s.append_internal(&""),
            Action::Call(ref addr) => s.append_internal(addr),
            Action::Store => s.append_internal(&store_addr),
        };
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
/// crypto type.
pub enum CryptoType {
    SECP,
    SM2,
}

impl Default for CryptoType {
    fn default() -> CryptoType {
        CryptoType::SECP
    }
}

impl Decodable for CryptoType {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        match rlp.as_val::<u8>()? {
            0 => Ok(CryptoType::SECP),
            1 => Ok(CryptoType::SM2),
            _ => Err(DecoderError::Custom("Unknown Type.")),
        }
    }
}

impl Encodable for CryptoType {
    fn rlp_append(&self, s: &mut RlpStream) {
        match *self {
            CryptoType::SECP => s.append_internal(&(0 as u8)),
            CryptoType::SM2 => s.append_internal(&(1 as u8)),
        };
    }
}

impl From<ProtoCrypto> for CryptoType {
    fn from(c: ProtoCrypto) -> CryptoType {
        match c {
            ProtoCrypto::SECP => CryptoType::SECP,
            ProtoCrypto::SM2 => CryptoType::SM2,
        }
    }
}

/// A set of information describing an externally-originating message call
/// or contract creation operation.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Transaction {
    /// Nonce.
    pub nonce: U256,
    /// Gas price.
    pub gas_price: U256,
    /// Gas paid up front for transaction execution.
    pub gas: U256,
    /// Action, can be either call or contract create.
    pub action: Action,
    /// Transfered value.
    pub value: U256,
    /// Transaction data.
    pub data: Bytes,
    /// valid before this block number
    pub block_limit: BlockNumber,
}

impl HeapSizeOf for Transaction {
    fn heap_size_of_children(&self) -> usize {
        self.data.heap_size_of_children()
    }
}

impl Decodable for Transaction {
    fn decode(d: &UntrustedRlp) -> Result<Self, DecoderError> {
        if d.item_count()? != 7 {
            return Err(DecoderError::RlpIncorrectListLen);
        }
        Ok(Transaction {
               nonce: d.val_at(0)?,
               gas_price: d.val_at(1)?,
               gas: d.val_at(2)?,
               action: d.val_at(3)?,
               value: d.val_at(4)?,
               data: d.val_at(5)?,
               block_limit: d.val_at(6)?,
           })
    }
}

impl Encodable for Transaction {
    fn rlp_append(&self, s: &mut RlpStream) {
        self.rlp_append_unsigned_transaction(s)
    }
}

// TODO: refactor transaction in protobuf,
// now using the same type `ProtoTransaction`,
// it's not a good design.
impl Transaction {
    pub fn new(plain_transaction: &ProtoTransaction) -> Result<Self, Error> {
        // let nonce = plain_transaction.nonce.parse::<u32>().map_err(|_| Error::ParseError)?;
        Ok(Transaction {
               nonce: U256::from_str(plain_transaction.get_nonce()).map_err(|_| Error::ParseError)?,
               gas_price: U256::default(),
               gas: U256::from(u64::max_value() / 100000),
               action: {
                   let to = plain_transaction.get_to();
                   match to.is_empty() {
                       true => Action::Create,
                       false => match to {
                           STORE_ADDRESS => Action::Store,
                           _ => Action::Call(Address::from_str(to).map_err(|_| Error::ParseError)?),
                       },
                   }
               },
               value: U256::default(),
               data: plain_transaction.get_data().into(),
               block_limit: plain_transaction.get_valid_until_block(),
           })

    }

    pub fn nonce(&self) -> &U256 {
        &self.nonce
    }

    pub fn action(&self) -> &Action {
        &self.action
    }

    // Specify the sender; this won't survive the serialize/deserialize process, but can be cloned.
    pub fn fake_sign(self, from: Address) -> SignedTransaction {
        let signature = Signature::default();
        SignedTransaction {
            transaction: UnverifiedTransaction {
                unsigned: self,
                signature: signature,
                hash: 0.into(),
                crypto_type: CryptoType::default(),
            },
            sender: from,
            public: Public::default(),
        }
    }

    /// Append object with a without signature into RLP stream
    pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream) {
        s.begin_list(7);
        s.append(&self.nonce);
        s.append(&self.gas_price);
        s.append(&self.gas);
        s.append(&self.action);
        s.append(&self.value);
        s.append(&self.data);
        s.append(&self.block_limit);
    }

    /// get the protobuf transaction
    pub fn proto_transaction(&self) -> ProtoTransaction {
        let mut pt = ProtoTransaction::new();
        pt.set_nonce(self.nonce.to_hex());
        pt.set_valid_until_block(self.block_limit);
        pt.set_data(self.data.clone());
        match self.action {
            Action::Create => pt.clear_to(),
            Action::Call(ref to) => pt.set_to(to.hex()),
            Action::Store => pt.set_to(STORE_ADDRESS.into()),
        }
        pt
    }
}

/// Signed transaction information without verified signature.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct UnverifiedTransaction {
    /// Plain Transaction.
    unsigned: Transaction,
    /// The signature
    signature: Signature,
    /// The Crypto Type
    crypto_type: CryptoType,
    /// Hash of the transaction
    hash: H256,
}

impl Deref for UnverifiedTransaction {
    type Target = Transaction;

    fn deref(&self) -> &Self::Target {
        &self.unsigned
    }
}

impl DerefMut for UnverifiedTransaction {
    fn deref_mut(&mut self) -> &mut Transaction {
        &mut self.unsigned
    }
}

impl Decodable for UnverifiedTransaction {
    fn decode(d: &UntrustedRlp) -> Result<Self, DecoderError> {
        if d.item_count()? != 4 {
            return Err(DecoderError::RlpIncorrectListLen);
        }
        Ok(UnverifiedTransaction {
               unsigned: d.val_at(0)?,
               signature: d.val_at(1)?,
               crypto_type: d.val_at(2)?,
               hash: d.val_at(3)?,
           })
    }
}

impl Encodable for UnverifiedTransaction {
    fn rlp_append(&self, s: &mut RlpStream) {
        self.rlp_append_sealed_transaction(s)
    }
}

impl UnverifiedTransaction {
    fn new(utx: &ProtoUnverifiedTransaction, hash: H256) -> Result<Self, Error> {

        if utx.get_signature().len() != SIGNATURE_BYTES_LEN {
            return Err(Error::InvalidSignature);
        }

        Ok(UnverifiedTransaction {
               unsigned: Transaction::new(utx.get_transaction())?,
               signature: Signature::from(H768::from(utx.get_signature())),
               crypto_type: CryptoType::from(utx.get_crypto()),
               hash: hash,
           })
    }

    /// Append object with a signature into RLP stream
    fn rlp_append_sealed_transaction(&self, s: &mut RlpStream) {
        s.begin_list(4);
        s.append(&self.unsigned);
        s.append(&self.signature);
        s.append(&self.crypto_type);
        s.append(&self.hash);
    }

    ///	Reference to unsigned part of this transaction.
    pub fn as_unsigned(&self) -> &Transaction {
        &self.unsigned
    }

    pub fn hash(&self) -> H256 {
        self.hash
    }

    /// get protobuf unverified transaction
    pub fn proto_unverified(&self) -> ProtoUnverifiedTransaction {
        let mut untx = ProtoUnverifiedTransaction::new();
        let tx = self.unsigned.proto_transaction();

        untx.set_transaction(tx);
        untx.set_signature(self.signature.to_vec());

        match self.crypto_type {
            CryptoType::SECP => untx.set_crypto(ProtoCrypto::SECP),
            CryptoType::SM2 => untx.set_crypto(ProtoCrypto::SM2),
        }
        untx
    }
}

/// A `UnverifiedTransaction` with successfully recovered `sender`.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct SignedTransaction {
    transaction: UnverifiedTransaction,
    sender: Address,
    public: Public,
}

/// RLP dose not support struct nesting well
impl Decodable for SignedTransaction {
    fn decode(d: &UntrustedRlp) -> Result<Self, DecoderError> {
        if d.item_count()? != 11 {
            return Err(DecoderError::RlpIncorrectListLen);
        }

        let public: H256 = d.val_at(10)?;

        Ok(SignedTransaction {
               transaction: UnverifiedTransaction {
                   unsigned: Transaction {
                       nonce: d.val_at(0)?,
                       gas_price: d.val_at(1)?,
                       gas: d.val_at(2)?,
                       action: d.val_at(3)?,
                       value: d.val_at(4)?,
                       data: d.val_at(5)?,
                       block_limit: d.val_at(6)?,
                   },
                   signature: d.val_at(7)?,
                   crypto_type: d.val_at(8)?,
                   hash: d.val_at(9)?,
               },
               sender: pubkey_to_address(&public),
               public: public,
           })
    }
}

/// RLP dose not support struct nesting well
impl Encodable for SignedTransaction {
    fn rlp_append(&self, s: &mut RlpStream) {
        s.begin_list(11);

        s.append(&self.nonce);
        s.append(&self.gas_price);
        s.append(&self.gas);
        s.append(&self.action);
        s.append(&self.value);
        s.append(&self.data);
        s.append(&self.block_limit);

        s.append(&self.signature);
        s.append(&self.crypto_type);
        s.append(&self.hash);
        //TODO: remove it
        s.append(&self.public);
    }
}

impl HeapSizeOf for SignedTransaction {
    fn heap_size_of_children(&self) -> usize {
        self.transaction.heap_size_of_children()
    }
}

impl Deref for SignedTransaction {
    type Target = UnverifiedTransaction;
    fn deref(&self) -> &Self::Target {
        &self.transaction
    }
}

impl DerefMut for SignedTransaction {
    fn deref_mut(&mut self) -> &mut UnverifiedTransaction {
        &mut self.transaction
    }
}

impl SignedTransaction {
    /// Try to verify transaction and recover sender.
    pub fn new(stx: &ProtoSignedTransaction) -> Result<Self, Error> {
        if stx.get_tx_hash().len() != HASH_BYTES_LEN {
            return Err(Error::InvalidHash);
        }

        if stx.get_signer().len() != PUBKEY_BYTES_LEN {
            return Err(Error::InvalidPubKey);
        }

        let tx_hash = H256::from(stx.get_tx_hash());
        let public = H256::from_slice(stx.get_signer());
        let sender = pubkey_to_address(&public);
        Ok(SignedTransaction {
               transaction: UnverifiedTransaction::new(stx.get_transaction_with_sig(), tx_hash)?,
               sender: sender,
               public: public,
           })
    }

    /// Returns transaction sender.
    pub fn sender(&self) -> &Address {
        &self.sender
    }

    /// Returns a public key of the sender.
    pub fn public_key(&self) -> &Public {
        &self.public
    }

    ///get protobuf of signed transaction
    pub fn protobuf(&self) -> ProtoSignedTransaction {
        let mut stx = ProtoSignedTransaction::new();
        let utx = self.transaction.proto_unverified();
        stx.set_transaction_with_sig(utx);
        stx.set_tx_hash(self.hash().to_vec());
        stx.set_signer(self.public.to_vec());
        stx
    }
}

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

    #[test]
    fn test_encode_and_decode() {
        let stx = SignedTransaction::default();
        stx.data = vec![1; 200];
        let stx_rlp = rlp::encode(&stx);
        let stx: SignedTransaction = rlp::decode(&stx_rlp);
        let stx_encoded = rlp::encode(&stx).into_vec();

        assert_eq!(stx_rlp, stx_encoded);
    }

    #[test]
    fn test_protobuf() {
        let mut stx = SignedTransaction::default();
        stx.gas = U256::from(u64::max_value() / 100000);
        let stx_rlp = rlp::encode(&stx);
        let stx_proto = stx.protobuf();
        let stx = SignedTransaction::new(&stx_proto).unwrap();
        let stx_encoded = rlp::encode(&stx).into_vec();
        let stx: SignedTransaction = rlp::decode(&stx_encoded);
        let stx_encoded = rlp::encode(&stx).into_vec();

        assert_eq!(stx_rlp, stx_encoded);
    }
}
<commit_msg>fix ci failed make bench error<commit_after>// CITA
// Copyright 2016-2017 Cryptape Technologies LLC.

// This program is free software: you can redistribute it
// and/or modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation,
// either version 3 of the License, or (at your option) any
// later version.

// This program is distributed in the hope that it will be
// useful, but WITHOUT ANY WARRANTY; without even the implied
// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
// PURPOSE. See the GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

use BlockNumber;
use ed25519::{Signature, Public, pubkey_to_address, SIGNATURE_BYTES_LEN, HASH_BYTES_LEN, PUBKEY_BYTES_LEN};
use libproto::blockchain::{Transaction as ProtoTransaction, UnverifiedTransaction as ProtoUnverifiedTransaction, SignedTransaction as ProtoSignedTransaction, Crypto as ProtoCrypto};
use rlp::*;
use std::ops::{Deref, DerefMut};
use std::str::FromStr;
use util::{H256, Address, U256, Bytes, HeapSizeOf, H768};

// pub const STORE_ADDRESS: H160 =  H160( [0xff; 20] );
pub const STORE_ADDRESS: &str = "ffffffffffffffffffffffffffffffffffffffff";

#[derive(Debug, PartialEq, Clone)]
pub enum Error {
    ParseError,
    InvalidHash,
    InvalidSignature,
    InvalidPubKey,
}

#[derive(Debug, Clone, PartialEq, Eq)]
/// Transaction action type.
pub enum Action {
    /// Just store the data.
    Store,
    /// Create creates new contract.
    Create,
    /// Calls contract at given address.
    /// In the case of a transfer, this is the receiver's address.'
    Call(Address),
}

impl Default for Action {
    fn default() -> Action {
        Action::Store
    }
}

impl Decodable for Action {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        if rlp.is_empty() {
            Ok(Action::Create)
        } else {
            let store_addr: Address = STORE_ADDRESS.into();
            let addr: Address = rlp.as_val()?;
            if addr == store_addr { Ok(Action::Store) } else { Ok(Action::Call(addr)) }
        }
    }
}

impl Encodable for Action {
    fn rlp_append(&self, s: &mut RlpStream) {
        let store_addr: Address = STORE_ADDRESS.into();
        match *self {
            Action::Create => s.append_internal(&""),
            Action::Call(ref addr) => s.append_internal(addr),
            Action::Store => s.append_internal(&store_addr),
        };
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
/// crypto type.
pub enum CryptoType {
    SECP,
    SM2,
}

impl Default for CryptoType {
    fn default() -> CryptoType {
        CryptoType::SECP
    }
}

impl Decodable for CryptoType {
    fn decode(rlp: &UntrustedRlp) -> Result<Self, DecoderError> {
        match rlp.as_val::<u8>()? {
            0 => Ok(CryptoType::SECP),
            1 => Ok(CryptoType::SM2),
            _ => Err(DecoderError::Custom("Unknown Type.")),
        }
    }
}

impl Encodable for CryptoType {
    fn rlp_append(&self, s: &mut RlpStream) {
        match *self {
            CryptoType::SECP => s.append_internal(&(0 as u8)),
            CryptoType::SM2 => s.append_internal(&(1 as u8)),
        };
    }
}

impl From<ProtoCrypto> for CryptoType {
    fn from(c: ProtoCrypto) -> CryptoType {
        match c {
            ProtoCrypto::SECP => CryptoType::SECP,
            ProtoCrypto::SM2 => CryptoType::SM2,
        }
    }
}

/// A set of information describing an externally-originating message call
/// or contract creation operation.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct Transaction {
    /// Nonce.
    pub nonce: U256,
    /// Gas price.
    pub gas_price: U256,
    /// Gas paid up front for transaction execution.
    pub gas: U256,
    /// Action, can be either call or contract create.
    pub action: Action,
    /// Transfered value.
    pub value: U256,
    /// Transaction data.
    pub data: Bytes,
    /// valid before this block number
    pub block_limit: BlockNumber,
}

impl HeapSizeOf for Transaction {
    fn heap_size_of_children(&self) -> usize {
        self.data.heap_size_of_children()
    }
}

impl Decodable for Transaction {
    fn decode(d: &UntrustedRlp) -> Result<Self, DecoderError> {
        if d.item_count()? != 7 {
            return Err(DecoderError::RlpIncorrectListLen);
        }
        Ok(Transaction {
               nonce: d.val_at(0)?,
               gas_price: d.val_at(1)?,
               gas: d.val_at(2)?,
               action: d.val_at(3)?,
               value: d.val_at(4)?,
               data: d.val_at(5)?,
               block_limit: d.val_at(6)?,
           })
    }
}

impl Encodable for Transaction {
    fn rlp_append(&self, s: &mut RlpStream) {
        self.rlp_append_unsigned_transaction(s)
    }
}

// TODO: refactor transaction in protobuf,
// now using the same type `ProtoTransaction`,
// it's not a good design.
impl Transaction {
    pub fn new(plain_transaction: &ProtoTransaction) -> Result<Self, Error> {
        // let nonce = plain_transaction.nonce.parse::<u32>().map_err(|_| Error::ParseError)?;
        Ok(Transaction {
               nonce: U256::from_str(plain_transaction.get_nonce()).map_err(|_| Error::ParseError)?,
               gas_price: U256::default(),
               gas: U256::from(u64::max_value() / 100000),
               action: {
                   let to = plain_transaction.get_to();
                   match to.is_empty() {
                       true => Action::Create,
                       false => match to {
                           STORE_ADDRESS => Action::Store,
                           _ => Action::Call(Address::from_str(to).map_err(|_| Error::ParseError)?),
                       },
                   }
               },
               value: U256::default(),
               data: plain_transaction.get_data().into(),
               block_limit: plain_transaction.get_valid_until_block(),
           })

    }

    pub fn nonce(&self) -> &U256 {
        &self.nonce
    }

    pub fn action(&self) -> &Action {
        &self.action
    }

    // Specify the sender; this won't survive the serialize/deserialize process, but can be cloned.
    pub fn fake_sign(self, from: Address) -> SignedTransaction {
        let signature = Signature::default();
        SignedTransaction {
            transaction: UnverifiedTransaction {
                unsigned: self,
                signature: signature,
                hash: 0.into(),
                crypto_type: CryptoType::default(),
            },
            sender: from,
            public: Public::default(),
        }
    }

    /// Append object with a without signature into RLP stream
    pub fn rlp_append_unsigned_transaction(&self, s: &mut RlpStream) {
        s.begin_list(7);
        s.append(&self.nonce);
        s.append(&self.gas_price);
        s.append(&self.gas);
        s.append(&self.action);
        s.append(&self.value);
        s.append(&self.data);
        s.append(&self.block_limit);
    }

    /// get the protobuf transaction
    pub fn proto_transaction(&self) -> ProtoTransaction {
        let mut pt = ProtoTransaction::new();
        pt.set_nonce(self.nonce.to_hex());
        pt.set_valid_until_block(self.block_limit);
        pt.set_data(self.data.clone());
        match self.action {
            Action::Create => pt.clear_to(),
            Action::Call(ref to) => pt.set_to(to.hex()),
            Action::Store => pt.set_to(STORE_ADDRESS.into()),
        }
        pt
    }
}

/// Signed transaction information without verified signature.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct UnverifiedTransaction {
    /// Plain Transaction.
    unsigned: Transaction,
    /// The signature
    signature: Signature,
    /// The Crypto Type
    crypto_type: CryptoType,
    /// Hash of the transaction
    hash: H256,
}

impl Deref for UnverifiedTransaction {
    type Target = Transaction;

    fn deref(&self) -> &Self::Target {
        &self.unsigned
    }
}

impl DerefMut for UnverifiedTransaction {
    fn deref_mut(&mut self) -> &mut Transaction {
        &mut self.unsigned
    }
}

impl Decodable for UnverifiedTransaction {
    fn decode(d: &UntrustedRlp) -> Result<Self, DecoderError> {
        if d.item_count()? != 4 {
            return Err(DecoderError::RlpIncorrectListLen);
        }
        Ok(UnverifiedTransaction {
               unsigned: d.val_at(0)?,
               signature: d.val_at(1)?,
               crypto_type: d.val_at(2)?,
               hash: d.val_at(3)?,
           })
    }
}

impl Encodable for UnverifiedTransaction {
    fn rlp_append(&self, s: &mut RlpStream) {
        self.rlp_append_sealed_transaction(s)
    }
}

impl UnverifiedTransaction {
    fn new(utx: &ProtoUnverifiedTransaction, hash: H256) -> Result<Self, Error> {

        if utx.get_signature().len() != SIGNATURE_BYTES_LEN {
            return Err(Error::InvalidSignature);
        }

        Ok(UnverifiedTransaction {
               unsigned: Transaction::new(utx.get_transaction())?,
               signature: Signature::from(H768::from(utx.get_signature())),
               crypto_type: CryptoType::from(utx.get_crypto()),
               hash: hash,
           })
    }

    /// Append object with a signature into RLP stream
    fn rlp_append_sealed_transaction(&self, s: &mut RlpStream) {
        s.begin_list(4);
        s.append(&self.unsigned);
        s.append(&self.signature);
        s.append(&self.crypto_type);
        s.append(&self.hash);
    }

    ///	Reference to unsigned part of this transaction.
    pub fn as_unsigned(&self) -> &Transaction {
        &self.unsigned
    }

    pub fn hash(&self) -> H256 {
        self.hash
    }

    /// get protobuf unverified transaction
    pub fn proto_unverified(&self) -> ProtoUnverifiedTransaction {
        let mut untx = ProtoUnverifiedTransaction::new();
        let tx = self.unsigned.proto_transaction();

        untx.set_transaction(tx);
        untx.set_signature(self.signature.to_vec());

        match self.crypto_type {
            CryptoType::SECP => untx.set_crypto(ProtoCrypto::SECP),
            CryptoType::SM2 => untx.set_crypto(ProtoCrypto::SM2),
        }
        untx
    }
}

/// A `UnverifiedTransaction` with successfully recovered `sender`.
#[derive(Default, Debug, Clone, PartialEq, Eq)]
pub struct SignedTransaction {
    transaction: UnverifiedTransaction,
    sender: Address,
    public: Public,
}

/// RLP dose not support struct nesting well
impl Decodable for SignedTransaction {
    fn decode(d: &UntrustedRlp) -> Result<Self, DecoderError> {
        if d.item_count()? != 11 {
            return Err(DecoderError::RlpIncorrectListLen);
        }

        let public: H256 = d.val_at(10)?;

        Ok(SignedTransaction {
               transaction: UnverifiedTransaction {
                   unsigned: Transaction {
                       nonce: d.val_at(0)?,
                       gas_price: d.val_at(1)?,
                       gas: d.val_at(2)?,
                       action: d.val_at(3)?,
                       value: d.val_at(4)?,
                       data: d.val_at(5)?,
                       block_limit: d.val_at(6)?,
                   },
                   signature: d.val_at(7)?,
                   crypto_type: d.val_at(8)?,
                   hash: d.val_at(9)?,
               },
               sender: pubkey_to_address(&public),
               public: public,
           })
    }
}

/// RLP dose not support struct nesting well
impl Encodable for SignedTransaction {
    fn rlp_append(&self, s: &mut RlpStream) {
        s.begin_list(11);

        s.append(&self.nonce);
        s.append(&self.gas_price);
        s.append(&self.gas);
        s.append(&self.action);
        s.append(&self.value);
        s.append(&self.data);
        s.append(&self.block_limit);

        s.append(&self.signature);
        s.append(&self.crypto_type);
        s.append(&self.hash);
        //TODO: remove it
        s.append(&self.public);
    }
}

impl HeapSizeOf for SignedTransaction {
    fn heap_size_of_children(&self) -> usize {
        self.transaction.heap_size_of_children()
    }
}

impl Deref for SignedTransaction {
    type Target = UnverifiedTransaction;
    fn deref(&self) -> &Self::Target {
        &self.transaction
    }
}

impl DerefMut for SignedTransaction {
    fn deref_mut(&mut self) -> &mut UnverifiedTransaction {
        &mut self.transaction
    }
}

impl SignedTransaction {
    /// Try to verify transaction and recover sender.
    pub fn new(stx: &ProtoSignedTransaction) -> Result<Self, Error> {
        if stx.get_tx_hash().len() != HASH_BYTES_LEN {
            return Err(Error::InvalidHash);
        }

        if stx.get_signer().len() != PUBKEY_BYTES_LEN {
            return Err(Error::InvalidPubKey);
        }

        let tx_hash = H256::from(stx.get_tx_hash());
        let public = H256::from_slice(stx.get_signer());
        let sender = pubkey_to_address(&public);
        Ok(SignedTransaction {
               transaction: UnverifiedTransaction::new(stx.get_transaction_with_sig(), tx_hash)?,
               sender: sender,
               public: public,
           })
    }

    /// Returns transaction sender.
    pub fn sender(&self) -> &Address {
        &self.sender
    }

    /// Returns a public key of the sender.
    pub fn public_key(&self) -> &Public {
        &self.public
    }

    ///get protobuf of signed transaction
    pub fn protobuf(&self) -> ProtoSignedTransaction {
        let mut stx = ProtoSignedTransaction::new();
        let utx = self.transaction.proto_unverified();
        stx.set_transaction_with_sig(utx);
        stx.set_tx_hash(self.hash().to_vec());
        stx.set_signer(self.public.to_vec());
        stx
    }
}

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

    #[test]
    fn test_encode_and_decode() {
        let mut stx = SignedTransaction::default();
        stx.data = vec![1; 200];
        let stx_rlp = rlp::encode(&stx);
        let stx: SignedTransaction = rlp::decode(&stx_rlp);
        let stx_encoded = rlp::encode(&stx).into_vec();

        assert_eq!(stx_rlp, stx_encoded);
    }

    #[test]
    fn test_protobuf() {
        let mut stx = SignedTransaction::default();
        stx.gas = U256::from(u64::max_value() / 100000);
        let stx_rlp = rlp::encode(&stx);
        let stx_proto = stx.protobuf();
        let stx = SignedTransaction::new(&stx_proto).unwrap();
        let stx_encoded = rlp::encode(&stx).into_vec();
        let stx: SignedTransaction = rlp::decode(&stx_encoded);
        let stx_encoded = rlp::encode(&stx).into_vec();

        assert_eq!(stx_rlp, stx_encoded);
    }
}
<|endoftext|>


<commit_before>use std::fs::File;
use std::fs::OpenOptions;
use std::fs;
use std::io::Write;
use std::fmt;
use std::path::PathBuf;
use time;

// Using Vec in `fds` for custom lookup functions that don't allocate. This is probably also
// possible with HashMap if the internals are exposed. Alternatively I guess we could implement a
// `Borrow` instance for `LogDest`.

pub struct Logger {
    log_dir: PathBuf,
    fds: Vec<(LogDest, File)>,
    debug_fd: File,
}

pub struct LogFile<'a> {
    fd: &'a File,
}

impl<'a> LogFile<'a> {
    pub fn write_line(&mut self, args: fmt::Arguments) {
        let now = time::now();
        write!(self.fd, "[{}] ", now.rfc822()).unwrap();
        self.fd.write_fmt(args).unwrap();
        writeln!(self.fd, "").unwrap();
    }
}

/// Log message destination
enum LogDest {
    // Server(String),
    Chan { serv: String, chan: String },
    /// For logging raw messages
    ServerRaw(String),
}

fn init_log_file(file: &mut Write) {
    let now = time::now();
    writeln!(file, "\nLogs started on {}\n", now.rfc822()).unwrap();
}

impl Logger {
    pub fn new(log_dir: PathBuf) -> Logger {
        let _ = fs::create_dir(&log_dir);

        let debug_logs = {
            let mut log_dir = log_dir.clone();
            log_dir.push("debug.log");
            let mut file = OpenOptions::new()
                .append(true)
                .create(true)
                .open(log_dir)
                .unwrap();
            init_log_file(&mut file);
            file
        };

        Logger {
            log_dir: log_dir,
            fds: vec![],
            debug_fd: debug_logs,
        }
    }

    // Stupid code below because of
    // https://users.rust-lang.org/t/weird-borrow-checker-error-for-loop-keeps-references-after-its-scope-ends/10929

    /*
    pub fn get_serv_logs(&mut self, serv_: &str) -> LogFile {
        let pos = self.fds.iter().position(|&(ref dest, _)| {
            if let &LogDest::Server(ref serv) = dest {
                serv == serv_
            } else {
                false
            }
        });

        match pos {
            Some(idx) => LogFile { fd: &mut self.fds[idx].1 },
            None => {
                let mut log_path = self.log_dir.clone();
                log_path.push(format!("{}.log", serv_));
                let mut file = OpenOptions::new().append(true).create(true).open(log_path).unwrap();
                init_log_file(&mut file);
                let idx = self.fds.len();
                self.fds.push((LogDest::Server(serv_.to_owned()), file));
                LogFile { fd: &mut self.fds[idx].1 }
            }
        }
    }
*/

    pub fn get_chan_logs(&mut self, serv_: &str, chan_: &str) -> LogFile {
        let pos = self.fds.iter().position(|&(ref dest, _)| {
            if let LogDest::Chan { ref serv, ref chan } = *dest {
                serv == serv_ && chan == chan_
            } else {
                false
            }
        });

        match pos {
            Some(idx) =>
                LogFile {
                    fd: &mut self.fds[idx].1,
                },
            None => {
                let mut log_path = self.log_dir.clone();
                log_path.push(format!("{}_{}.log", serv_, chan_));
                let mut file = OpenOptions::new()
                    .append(true)
                    .create(true)
                    .open(log_path)
                    .unwrap();
                init_log_file(&mut file);
                let idx = self.fds.len();
                self.fds.push((
                    LogDest::Chan {
                        serv: serv_.to_owned(),
                        chan: chan_.to_owned(),
                    },
                    file,
                ));
                LogFile {
                    fd: &mut self.fds[idx].1,
                }
            }
        }
    }

    pub fn get_raw_serv_logs(&mut self, serv_: &str) -> LogFile {
        let pos = self.fds.iter().position(|&(ref dest, _)| {
            if let LogDest::ServerRaw(ref serv) = *dest {
                serv == serv_
            } else {
                false
            }
        });

        match pos {
            Some(idx) =>
                LogFile {
                    fd: &mut self.fds[idx].1,
                },
            None => {
                let mut log_path = self.log_dir.clone();
                log_path.push(format!("{}_raw.log", serv_));
                let mut file = OpenOptions::new()
                    .append(true)
                    .create(true)
                    .open(log_path)
                    .unwrap();
                init_log_file(&mut file);
                let idx = self.fds.len();
                self.fds.push((LogDest::ServerRaw(serv_.to_owned()), file));
                LogFile {
                    fd: &mut self.fds[idx].1,
                }
            }
        }
    }

    pub fn get_debug_logs(&mut self) -> LogFile {
        LogFile {
            fd: &mut self.debug_fd,
        }
    }
}
<commit_msg>Deep create log dir<commit_after>use std::fs::File;
use std::fs::OpenOptions;
use std::fs;
use std::io::Write;
use std::fmt;
use std::path::PathBuf;
use time;

// Using Vec in `fds` for custom lookup functions that don't allocate. This is probably also
// possible with HashMap if the internals are exposed. Alternatively I guess we could implement a
// `Borrow` instance for `LogDest`.

pub struct Logger {
    log_dir: PathBuf,
    fds: Vec<(LogDest, File)>,
    debug_fd: File,
}

pub struct LogFile<'a> {
    fd: &'a File,
}

impl<'a> LogFile<'a> {
    pub fn write_line(&mut self, args: fmt::Arguments) {
        let now = time::now();
        write!(self.fd, "[{}] ", now.rfc822()).unwrap();
        self.fd.write_fmt(args).unwrap();
        writeln!(self.fd, "").unwrap();
    }
}

/// Log message destination
enum LogDest {
    // Server(String),
    Chan { serv: String, chan: String },
    /// For logging raw messages
    ServerRaw(String),
}

fn init_log_file(file: &mut Write) {
    let now = time::now();
    writeln!(file, "\nLogs started on {}\n", now.rfc822()).unwrap();
}

impl Logger {
    pub fn new(log_dir: PathBuf) -> Logger {
        let _ = fs::create_dir_all(&log_dir);

        let debug_logs = {
            let mut log_dir = log_dir.clone();
            log_dir.push("debug.log");
            let mut file = OpenOptions::new()
                .append(true)
                .create(true)
                .open(log_dir)
                .unwrap();
            init_log_file(&mut file);
            file
        };

        Logger {
            log_dir: log_dir,
            fds: vec![],
            debug_fd: debug_logs,
        }
    }

    // Stupid code below because of
    // https://users.rust-lang.org/t/weird-borrow-checker-error-for-loop-keeps-references-after-its-scope-ends/10929

    /*
    pub fn get_serv_logs(&mut self, serv_: &str) -> LogFile {
        let pos = self.fds.iter().position(|&(ref dest, _)| {
            if let &LogDest::Server(ref serv) = dest {
                serv == serv_
            } else {
                false
            }
        });

        match pos {
            Some(idx) => LogFile { fd: &mut self.fds[idx].1 },
            None => {
                let mut log_path = self.log_dir.clone();
                log_path.push(format!("{}.log", serv_));
                let mut file = OpenOptions::new().append(true).create(true).open(log_path).unwrap();
                init_log_file(&mut file);
                let idx = self.fds.len();
                self.fds.push((LogDest::Server(serv_.to_owned()), file));
                LogFile { fd: &mut self.fds[idx].1 }
            }
        }
    }
*/

    pub fn get_chan_logs(&mut self, serv_: &str, chan_: &str) -> LogFile {
        let pos = self.fds.iter().position(|&(ref dest, _)| {
            if let LogDest::Chan { ref serv, ref chan } = *dest {
                serv == serv_ && chan == chan_
            } else {
                false
            }
        });

        match pos {
            Some(idx) =>
                LogFile {
                    fd: &mut self.fds[idx].1,
                },
            None => {
                let mut log_path = self.log_dir.clone();
                log_path.push(format!("{}_{}.log", serv_, chan_));
                let mut file = OpenOptions::new()
                    .append(true)
                    .create(true)
                    .open(log_path)
                    .unwrap();
                init_log_file(&mut file);
                let idx = self.fds.len();
                self.fds.push((
                    LogDest::Chan {
                        serv: serv_.to_owned(),
                        chan: chan_.to_owned(),
                    },
                    file,
                ));
                LogFile {
                    fd: &mut self.fds[idx].1,
                }
            }
        }
    }

    pub fn get_raw_serv_logs(&mut self, serv_: &str) -> LogFile {
        let pos = self.fds.iter().position(|&(ref dest, _)| {
            if let LogDest::ServerRaw(ref serv) = *dest {
                serv == serv_
            } else {
                false
            }
        });

        match pos {
            Some(idx) =>
                LogFile {
                    fd: &mut self.fds[idx].1,
                },
            None => {
                let mut log_path = self.log_dir.clone();
                log_path.push(format!("{}_raw.log", serv_));
                let mut file = OpenOptions::new()
                    .append(true)
                    .create(true)
                    .open(log_path)
                    .unwrap();
                init_log_file(&mut file);
                let idx = self.fds.len();
                self.fds.push((LogDest::ServerRaw(serv_.to_owned()), file));
                LogFile {
                    fd: &mut self.fds[idx].1,
                }
            }
        }
    }

    pub fn get_debug_logs(&mut self) -> LogFile {
        LogFile {
            fd: &mut self.debug_fd,
        }
    }
}
<|endoftext|>


<commit_before>/**
Gets a reference to a `Class`.

Panics if no class with the given name can be found.
To check for a class that may not exist, use `Class::get`.

# Example
``` no_run
# #[macro_use] extern crate objc;
# fn main() {
let cls = class!(NSObject);
# }
```
*/
#[macro_export]
macro_rules! class {
    ($name:ident) => ({
        #[allow(deprecated)]
        #[inline(always)]
        fn get_class(name: &str) -> Option<&'static $crate::runtime::Class> {
            unsafe {
                #[cfg_attr(feature = "cargo-clippy", allow(replace_consts))]
                static CLASS: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT;
                // `Relaxed` should be fine since `objc_getClass` is thread-safe.
                let ptr = CLASS.load(::std::sync::atomic::Ordering::Relaxed) as *const $crate::runtime::Class;
                if ptr.is_null() {
                    let cls = $crate::runtime::objc_getClass(name.as_ptr() as *const _);
                    CLASS.store(cls as usize, ::std::sync::atomic::Ordering::Relaxed);
                    if cls.is_null() { None } else { Some(&*cls) }
                } else {
                    Some(&*ptr)
                }
            }
        }
        match get_class(concat!(stringify!($name), '\0')) {
            Some(cls) => cls,
            None => panic!("Class with name {} could not be found", stringify!($name)),
        }
    })
}

#[doc(hidden)]
#[macro_export]
macro_rules! sel_impl {
    // Declare a function to hide unsafety, otherwise we can trigger the
    // unused_unsafe lint; see rust-lang/rust#8472
    ($name:expr) => ({
        #[allow(deprecated)]
        #[inline(always)]
        fn register_sel(name: &str) -> $crate::runtime::Sel {
            unsafe {
                #[cfg_attr(feature = "cargo-clippy", allow(replace_consts))]
                static SEL: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT;
                let ptr = SEL.load(::std::sync::atomic::Ordering::Relaxed) as *const ::std::os::raw::c_void;
                // It should be fine to use `Relaxed` ordering here because `sel_registerName` is
                // thread-safe.
                if ptr.is_null() {
                    let sel = $crate::runtime::sel_registerName(name.as_ptr() as *const _);
                    SEL.store(sel.as_ptr() as usize, ::std::sync::atomic::Ordering::Relaxed);
                    sel
                } else {
                    $crate::runtime::Sel::from_ptr(ptr)
                }
            }
        }
        register_sel($name)
    })
}

/**
Registers a selector, returning a `Sel`.

# Example
```
# #[macro_use] extern crate objc;
# fn main() {
let sel = sel!(description);
let sel = sel!(setObject:forKey:);
# }
```
*/
#[macro_export]
macro_rules! sel {
    ($name:ident) => ({sel_impl!(concat!(stringify!($name), '\0'))});
    ($($name:ident :)+) => ({sel_impl!(concat!($(stringify!($name), ':'),+, '\0'))});
}

/**
Sends a message to an object.

The first argument can be any type that dereferences to a type that implements
`Message`, like a reference, pointer, or an `Id`.
The syntax is similar to the message syntax in Objective-C.
Variadic arguments are not currently supported.

# Example
``` no_run
# #[macro_use] extern crate objc;
# use objc::runtime::Object;
# fn main() {
# unsafe {
let obj: *mut Object;
# let obj: *mut Object = 0 as *mut Object;
let description: *const Object = msg_send![obj, description];
let _: () = msg_send![obj, setArg1:1 arg2:2];
# }
# }
```
*/
#[macro_export]
macro_rules! msg_send {
    (super($obj:expr, $superclass:expr), $name:ident) => ({
        let sel = sel!($name);
        match $crate::__send_super_message(&*$obj, $superclass, sel, ()) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
    (super($obj:expr, $superclass:expr), $($name:ident : $arg:expr)+) => ({
        let sel = sel!($($name:)+);
        match $crate::__send_super_message(&*$obj, $superclass, sel, ($($arg,)*)) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
    ($obj:expr, $name:ident) => ({
        let sel = sel!($name);
        match $crate::__send_message(&*$obj, sel, ()) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
    ($obj:expr, $($name:ident : $arg:expr)+) => ({
        let sel = sel!($($name:)+);
        match $crate::__send_message(&*$obj, sel, ($($arg,)*)) {
            Err(s) => panic!("{}", s),
            Ok(r) => r,
        }
    });
}
<commit_msg>Tweak msg_send! so return type cannot be omitted<commit_after>/**
Gets a reference to a `Class`.

Panics if no class with the given name can be found.
To check for a class that may not exist, use `Class::get`.

# Example
``` no_run
# #[macro_use] extern crate objc;
# fn main() {
let cls = class!(NSObject);
# }
```
*/
#[macro_export]
macro_rules! class {
    ($name:ident) => ({
        #[allow(deprecated)]
        #[inline(always)]
        fn get_class(name: &str) -> Option<&'static $crate::runtime::Class> {
            unsafe {
                #[cfg_attr(feature = "cargo-clippy", allow(replace_consts))]
                static CLASS: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT;
                // `Relaxed` should be fine since `objc_getClass` is thread-safe.
                let ptr = CLASS.load(::std::sync::atomic::Ordering::Relaxed) as *const $crate::runtime::Class;
                if ptr.is_null() {
                    let cls = $crate::runtime::objc_getClass(name.as_ptr() as *const _);
                    CLASS.store(cls as usize, ::std::sync::atomic::Ordering::Relaxed);
                    if cls.is_null() { None } else { Some(&*cls) }
                } else {
                    Some(&*ptr)
                }
            }
        }
        match get_class(concat!(stringify!($name), '\0')) {
            Some(cls) => cls,
            None => panic!("Class with name {} could not be found", stringify!($name)),
        }
    })
}

#[doc(hidden)]
#[macro_export]
macro_rules! sel_impl {
    // Declare a function to hide unsafety, otherwise we can trigger the
    // unused_unsafe lint; see rust-lang/rust#8472
    ($name:expr) => ({
        #[allow(deprecated)]
        #[inline(always)]
        fn register_sel(name: &str) -> $crate::runtime::Sel {
            unsafe {
                #[cfg_attr(feature = "cargo-clippy", allow(replace_consts))]
                static SEL: ::std::sync::atomic::AtomicUsize = ::std::sync::atomic::ATOMIC_USIZE_INIT;
                let ptr = SEL.load(::std::sync::atomic::Ordering::Relaxed) as *const ::std::os::raw::c_void;
                // It should be fine to use `Relaxed` ordering here because `sel_registerName` is
                // thread-safe.
                if ptr.is_null() {
                    let sel = $crate::runtime::sel_registerName(name.as_ptr() as *const _);
                    SEL.store(sel.as_ptr() as usize, ::std::sync::atomic::Ordering::Relaxed);
                    sel
                } else {
                    $crate::runtime::Sel::from_ptr(ptr)
                }
            }
        }
        register_sel($name)
    })
}

/**
Registers a selector, returning a `Sel`.

# Example
```
# #[macro_use] extern crate objc;
# fn main() {
let sel = sel!(description);
let sel = sel!(setObject:forKey:);
# }
```
*/
#[macro_export]
macro_rules! sel {
    ($name:ident) => ({sel_impl!(concat!(stringify!($name), '\0'))});
    ($($name:ident :)+) => ({sel_impl!(concat!($(stringify!($name), ':'),+, '\0'))});
}

/**
Sends a message to an object.

The first argument can be any type that dereferences to a type that implements
`Message`, like a reference, pointer, or an `Id`.
The syntax is similar to the message syntax in Objective-C.
Variadic arguments are not currently supported.

# Example
``` no_run
# #[macro_use] extern crate objc;
# use objc::runtime::Object;
# fn main() {
# unsafe {
let obj: *mut Object;
# let obj: *mut Object = 0 as *mut Object;
let description: *const Object = msg_send![obj, description];
let _: () = msg_send![obj, setArg1:1 arg2:2];
# }
# }
```
*/
#[macro_export]
macro_rules! msg_send {
    (super($obj:expr, $superclass:expr), $name:ident) => ({
        let sel = sel!($name);
        let result;
        match $crate::__send_super_message(&*$obj, $superclass, sel, ()) {
            Err(s) => panic!("{}", s),
            Ok(r) => result = r,
        }
        result
    });
    (super($obj:expr, $superclass:expr), $($name:ident : $arg:expr)+) => ({
        let sel = sel!($($name:)+);
        let result;
        match $crate::__send_super_message(&*$obj, $superclass, sel, ($($arg,)*)) {
            Err(s) => panic!("{}", s),
            Ok(r) => result = r,
        }
        result
    });
    ($obj:expr, $name:ident) => ({
        let sel = sel!($name);
        let result;
        match $crate::__send_message(&*$obj, sel, ()) {
            Err(s) => panic!("{}", s),
            Ok(r) => result = r,
        }
        result
    });
    ($obj:expr, $($name:ident : $arg:expr)+) => ({
        let sel = sel!($($name:)+);
        let result;
        match $crate::__send_message(&*$obj, sel, ($($arg,)*)) {
            Err(s) => panic!("{}", s),
            Ok(r) => result = r,
        }
        result
    });
}
<|endoftext|>


<commit_before>use RegT;

const PAGE_SHIFT: usize = 10;   // 1 kByte page size = (1<<10)
const PAGE_SIZE:  usize = (1<<PAGE_SHIFT);
const PAGE_MASK:  usize = PAGE_SIZE-1;
const HEAP_SIZE:  usize = 512 * PAGE_SIZE;
const NUM_PAGES:  usize = (1<<16) / PAGE_SIZE;
const NUM_LAYERS: usize = 4;

#[derive(Clone,Copy)]
struct Page {
    pub offset: usize,      // offset into heap
    pub writable: bool,     // true if the page is writable
    pub mapped: bool,       // true if currently mapped
}

impl Page {
    /// return a new, unmapped page
    pub fn new() -> Page {
        Page { offset: 0, writable: false, mapped: false }
    }
    /// map page to chunk of heap memory
    pub fn map(&mut self, offset: usize, writable: bool) {
        self.offset = offset;
        self.writable = writable;
        self.mapped = true;
    }
    /// unmap page
    pub fn unmap(&mut self) {
        self.offset = 0;
        self.writable = false;
        self.mapped = false;
    }
}

/// memory access (simplified, no memory mapping or bank switching)
pub struct Memory {
    pages: [Page; NUM_PAGES],                   // currently CPU-visible pages
    layers: [[Page; NUM_PAGES]; NUM_LAYERS],    // currently mapped layers
    heap: [u8; HEAP_SIZE],                      // all available physical memory
}

impl Memory {

    /// return new, unmapped memory object
    pub fn new() -> Memory {
        Memory {
            pages: [Page::new(); NUM_PAGES],
            layers: [[Page::new(); NUM_PAGES]; NUM_LAYERS],
            heap: [0; HEAP_SIZE]
        }
    }

    /// return new memory object with 64 kByte mapped, writable memory (for testing)
    pub fn new_64k() -> Memory {
        let mut mem = Memory::new();
        mem.map(0, 0, (1<<16), 0, true);
        mem
    }

    /// map a chunk of heap memory to CPU-mapped memory
    pub fn map(&mut self, layer: usize, heap_offset: usize, size: usize, addr: usize, writable: bool) {
        assert!((size & PAGE_MASK) == 0);
        assert!((addr & PAGE_MASK) == 0);
        let num = size >> PAGE_SHIFT;
        for i in 0..num {
            let map_offset = i * PAGE_SIZE;
            let page_index = ((addr + map_offset) & 0xFFFF) >> PAGE_SHIFT;
            let page = &mut self.layers[layer][page_index];
            page.map(heap_offset + map_offset, writable);
        }
        self.update_mapping();
    }

    /// unmap a chunk heap memory
    pub fn unmap(&mut self, layer: usize, size: usize, addr: usize) {
        assert!((size & PAGE_MASK) == 0);
        assert!((addr & PAGE_MASK) == 0);
        let num = size >> PAGE_SHIFT;
        for i in 0..num {
            let map_offset = i * PAGE_SIZE;
            let page_index = ((addr + map_offset) & 0xFFFF) >> PAGE_SHIFT;
            let page = &mut self.layers[layer][page_index];
            page.unmap();
        }
        self.update_mapping();
    }

    /// unmap all pages in a layer
    pub fn unmap_layer(&mut self, layer: usize) {
        for page in self.layers[layer].iter_mut() {
            page.unmap();
        }
        self.update_mapping();
    }

    /// unmap all pages in all layers
    pub fn umap_all(&mut self) {
        for layer in self.layers.iter_mut() {
            for page in layer.iter_mut() {
                page.unmap();
            }
        }
        self.update_mapping();
    }

    /// private method to update internal CPU-visible mapping from mapped layers
    fn update_mapping(&mut self) {
        // for each cpu-visible page, find the highest-priority layer
        // which maps this memory range and copy it into the
        // cpu-visible page
        for page_index in 0..NUM_PAGES {
            let mut layer_page: Option<&Page> = None;
            for layer_index in 0..NUM_LAYERS {
                if self.layers[layer_index][page_index].mapped {
                    layer_page = Some(&self.layers[layer_index][page_index]);
                    break;
                }
            }
            match layer_page {
                Some(page) => self.pages[page_index] = *page,
                None => self.pages[page_index].unmap()
            }
        }
    }

    /// read unsigned byte from 16-bit address
    #[inline(always)]
    pub fn r8(&self, addr: RegT) -> RegT {
        let uaddr = (addr & 0xFFFF) as usize;
        let page = &self.pages[uaddr >> PAGE_SHIFT];
        if page.mapped {
            let heap_offset = page.offset + (uaddr & PAGE_MASK);
            self.heap[heap_offset] as RegT
        }
        else {
            0xFF
        }
    }

    /// read signed byte from 16-bit address
    #[inline(always)]
    pub fn rs8(&self, addr: RegT) -> RegT {
        let uaddr = (addr & 0xFFFF) as usize;
        let page = &self.pages[uaddr >> PAGE_SHIFT];
        if page.mapped {
            let heap_offset = page.offset + (uaddr & PAGE_MASK);
            self.heap[heap_offset] as i8 as RegT
        }
        else {
            0xFF
        }
    }

    /// write unsigned byte to 16-bit address
    #[inline(always)]
    pub fn w8(&mut self, addr: RegT, val: RegT) {
        let uaddr = (addr & 0xFFFF) as usize;
        let page = &self.pages[uaddr >> PAGE_SHIFT];
        if page.mapped && page.writable {
            let heap_offset = page.offset + (uaddr & PAGE_MASK);
            self.heap[heap_offset] = val as u8;
        }
    }

    /// write unsigned byte, ignore write-protection flag
    pub fn w8f(&mut self, addr: RegT, val: RegT) {
        let uaddr = (addr & 0xFFFF) as usize;
        let page = &self.pages[uaddr >> PAGE_SHIFT];
        if page.mapped {
            let heap_offset = page.offset + (uaddr & PAGE_MASK);
            self.heap[heap_offset] = val as u8;
        }
    }

    /// read unsigned word from 16-bit address
    #[inline(always)]
    pub fn r16(&self, addr: RegT) -> RegT {
        let l = self.r8(addr);
        let h = self.r8(addr + 1);
        h<<8 | l
    }

    /// write unsigned word to 16-bit address
    #[inline(always)]
    pub fn w16(&mut self, addr: RegT, val: RegT) {
        let l = val & 0xff;
        let h = (val >> 8) & 0xff;
        self.w8(addr, l);
        self.w8(addr + 1, h);
    }

    /// write a whole chunk of memory, ignore write-protection
    pub fn write(&mut self, addr: RegT, data: &[u8]) {
        let mut offset = 0;
        for b in data {
            self.w8f(addr+offset, *b as RegT);
            offset += 1;
        }
    }
}

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

    #[test]
    fn mem_readwrite() {
        let mut mem = Memory::new_64k();
        mem.w8(0x1234, 0x12);
        assert!(mem.r8(0x1234) == 0x12);

        mem.w8(0x2345, 0x32);
        assert!(mem.r8(0x2345) == 0x32);

        mem.w16(0x1000, 0x1234);
        assert!(mem.r16(0x1000) == 0x1234);
        assert!(mem.r8(0x1000) == 0x34);
        assert!(mem.r8(0x1001) == 0x12);

        mem.w16(0xFFFF, 0x2233);
        assert!(mem.r16(0xFFFF) == 0x2233);
        assert!(mem.r8(0xFFFF) == 0x33);
        assert!(mem.r8(0x0000) == 0x22);
    }
}
<commit_msg>More Memory tests<commit_after>use std::mem;
use RegT;

const PAGE_SHIFT: usize = 10;   // 1 kByte page size = (1<<10)
const PAGE_SIZE:  usize = (1<<PAGE_SHIFT);
const PAGE_MASK:  usize = PAGE_SIZE-1;
const HEAP_SIZE:  usize = 512 * PAGE_SIZE;
const NUM_PAGES:  usize = (1<<16) / PAGE_SIZE;
const NUM_LAYERS: usize = 4;

#[derive(Clone,Copy)]
struct Page {
    pub offset: usize,      // offset into heap
    pub writable: bool,     // true if the page is writable
    pub mapped: bool,       // true if currently mapped
}

impl Page {
    /// return a new, unmapped page
    pub fn new() -> Page {
        Page { offset: 0, writable: false, mapped: false }
    }
    /// map page to chunk of heap memory
    pub fn map(&mut self, offset: usize, writable: bool) {
        self.offset = offset;
        self.writable = writable;
        self.mapped = true;
    }
    /// unmap page
    pub fn unmap(&mut self) {
        self.offset = 0;
        self.writable = false;
        self.mapped = false;
    }
}

/// memory access (simplified, no memory mapping or bank switching)
pub struct Memory {
    pages: [Page; NUM_PAGES],                   // currently CPU-visible pages
    layers: [[Page; NUM_PAGES]; NUM_LAYERS],    // currently mapped layers
    heap: [u8; HEAP_SIZE],                      // all available physical memory
}

impl Memory {

    /// return new, unmapped memory object
    pub fn new() -> Memory {
        Memory {
            pages: [Page::new(); NUM_PAGES],
            layers: [[Page::new(); NUM_PAGES]; NUM_LAYERS],
            heap: [0; HEAP_SIZE]
        }
    }

    /// return new memory object with 64 kByte mapped, writable memory (for testing)
    pub fn new_64k() -> Memory {
        let mut mem = Memory::new();
        mem.map(0, 0, 0, true, (1<<16));
        mem
    }

    /// map a chunk of uninitialized heap memory to CPU-mapped memory
    pub fn map(&mut self, layer: usize, heap_offset: usize, addr: usize, writable: bool, size: usize) {
        assert!((size & PAGE_MASK) == 0);
        assert!((addr & PAGE_MASK) == 0);
        let num = size >> PAGE_SHIFT;
        for i in 0..num {
            let map_offset = i * PAGE_SIZE;
            let page_index = ((addr + map_offset) & 0xFFFF) >> PAGE_SHIFT;
            let page = &mut self.layers[layer][page_index];
            page.map(heap_offset + map_offset, writable);
        }
        self.update_mapping();
    }

    /// map a chunk of heap memory, and initialize it
    pub fn map_bytes(&mut self, layer: usize, heap_offset: usize, addr: usize, writable: bool, content: &[u8]) {
        assert!((addr & PAGE_MASK) == 0);
        let size = mem::size_of_val(content);
        assert!((size & PAGE_MASK) == 0);
        self.map(layer, heap_offset, addr, writable, size);
        let dst = &mut self.heap[heap_offset..heap_offset+size];
        dst.clone_from_slice(content);
    }

    /// unmap a chunk heap memory
    pub fn unmap(&mut self, layer: usize, size: usize, addr: usize) {
        assert!((size & PAGE_MASK) == 0);
        assert!((addr & PAGE_MASK) == 0);
        let num = size >> PAGE_SHIFT;
        for i in 0..num {
            let map_offset = i * PAGE_SIZE;
            let page_index = ((addr + map_offset) & 0xFFFF) >> PAGE_SHIFT;
            let page = &mut self.layers[layer][page_index];
            page.unmap();
        }
        self.update_mapping();
    }

    /// unmap all pages in a layer
    pub fn unmap_layer(&mut self, layer: usize) {
        for page in self.layers[layer].iter_mut() {
            page.unmap();
        }
        self.update_mapping();
    }

    /// unmap all pages in all layers
    pub fn umap_all(&mut self) {
        for layer in self.layers.iter_mut() {
            for page in layer.iter_mut() {
                page.unmap();
            }
        }
        self.update_mapping();
    }

    /// private method to update internal CPU-visible mapping from mapped layers
    fn update_mapping(&mut self) {
        // for each cpu-visible page, find the highest-priority layer
        // which maps this memory range and copy it into the
        // cpu-visible page
        for page_index in 0..NUM_PAGES {
            let mut layer_page: Option<&Page> = None;
            for layer_index in 0..NUM_LAYERS {
                if self.layers[layer_index][page_index].mapped {
                    layer_page = Some(&self.layers[layer_index][page_index]);
                    break;
                }
            }
            match layer_page {
                Some(page) => self.pages[page_index] = *page,
                None => self.pages[page_index].unmap()
            }
        }
    }

    /// read unsigned byte from 16-bit address
    #[inline(always)]
    pub fn r8(&self, addr: RegT) -> RegT {
        let uaddr = (addr & 0xFFFF) as usize;
        let page = &self.pages[uaddr >> PAGE_SHIFT];
        if page.mapped {
            let heap_offset = page.offset + (uaddr & PAGE_MASK);
            self.heap[heap_offset] as RegT
        }
        else {
            0xFF
        }
    }

    /// read signed byte from 16-bit address
    #[inline(always)]
    pub fn rs8(&self, addr: RegT) -> RegT {
        let uaddr = (addr & 0xFFFF) as usize;
        let page = &self.pages[uaddr >> PAGE_SHIFT];
        if page.mapped {
            let heap_offset = page.offset + (uaddr & PAGE_MASK);
            self.heap[heap_offset] as i8 as RegT
        }
        else {
            0xFF
        }
    }

    /// write unsigned byte to 16-bit address
    #[inline(always)]
    pub fn w8(&mut self, addr: RegT, val: RegT) {
        let uaddr = (addr & 0xFFFF) as usize;
        let page = &self.pages[uaddr >> PAGE_SHIFT];
        if page.mapped && page.writable {
            let heap_offset = page.offset + (uaddr & PAGE_MASK);
            self.heap[heap_offset] = val as u8;
        }
    }

    /// write unsigned byte, ignore write-protection flag
    pub fn w8f(&mut self, addr: RegT, val: RegT) {
        let uaddr = (addr & 0xFFFF) as usize;
        let page = &self.pages[uaddr >> PAGE_SHIFT];
        if page.mapped {
            let heap_offset = page.offset + (uaddr & PAGE_MASK);
            self.heap[heap_offset] = val as u8;
        }
    }

    /// read unsigned word from 16-bit address
    #[inline(always)]
    pub fn r16(&self, addr: RegT) -> RegT {
        let l = self.r8(addr);
        let h = self.r8(addr + 1);
        h<<8 | l
    }

    /// write unsigned word to 16-bit address
    #[inline(always)]
    pub fn w16(&mut self, addr: RegT, val: RegT) {
        let l = val & 0xff;
        let h = (val >> 8) & 0xff;
        self.w8(addr, l);
        self.w8(addr + 1, h);
    }

    /// write a whole chunk of memory, ignore write-protection
    pub fn write(&mut self, addr: RegT, data: &[u8]) {
        let mut offset = 0;
        for b in data {
            self.w8f(addr+offset, *b as RegT);
            offset += 1;
        }
    }
}

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

    #[test]
    fn mem_readwrite() {
        let mut mem = Memory::new_64k();
        mem.w8(0x1234, 0x12);
        assert!(mem.r8(0x1234) == 0x12);

        mem.w8(0x2345, 0x32);
        assert!(mem.r8(0x2345) == 0x32);

        mem.w16(0x1000, 0x1234);
        assert!(mem.r16(0x1000) == 0x1234);
        assert!(mem.r8(0x1000) == 0x34);
        assert!(mem.r8(0x1001) == 0x12);

        mem.w16(0xFFFF, 0x2233);
        assert!(mem.r16(0xFFFF) == 0x2233);
        assert!(mem.r8(0xFFFF) == 0x33);
        assert!(mem.r8(0x0000) == 0x22);
    }

    #[test]
    fn mem_map() {
        let mut mem = Memory::new();
        const SIZE : usize = 0x4000;  // 16k
        let x11 = [0x11u8; SIZE];
        let x22 = [0x22u8; SIZE];
        let x33 = [0x33u8; SIZE];
        let x44 = [0x44u8; SIZE];
        mem.map_bytes(0, 0x0000, 0x0000, true, &x11);
        mem.map_bytes(0, 0x4000, 0x4000, true, &x22);
        mem.map_bytes(0, 0x8000, 0x8000, true, &x33);
        mem.map_bytes(0, 0xC000, 0xC000, false, &x44);
        assert!(mem.r8(0x0000) == 0x11);
        assert!(mem.r8(0x4000) == 0x22);
        assert!(mem.r8(0x8000) == 0x33);
        assert!(mem.r8(0xC000) == 0x44);
        assert!(mem.r8(0x3FFF) == 0x11);
        assert!(mem.r8(0x7FFF) == 0x22);
        assert!(mem.r8(0xBFFF) == 0x33);
        assert!(mem.r8(0xFFFF) == 0x44);
        assert!(mem.r16(0x3FFF) == 0x2211);
        assert!(mem.r16(0x7FFF) == 0x3322);
        assert!(mem.r16(0xBFFF) == 0x4433);
        assert!(mem.r16(0xFFFF) == 0x1144);
        mem.w16(0xBFFF, 0x1234);
        assert!(mem.r8(0xBFFF) == 0x34);
        assert!(mem.r8(0xC000) == 0x44);
        mem.unmap(0, 0x4000, SIZE);
        assert!(mem.r8(0x4000) == 0xFF);
        assert!(mem.r8(0x7FFF) == 0xFF);
        assert!(mem.r8(0x3FFF) == 0x11);
        assert!(mem.r8(0x8000) == 0x33);
        mem.w8(0x4000, 0x55);
        assert!(mem.r8(0x4000) == 0xFF);
        mem.w8(0x0000, 0x66);
        assert!(mem.r8(0x0000) == 0x66);
    }
}
<|endoftext|>


<commit_before>use super::schema::notes;
use rocket::{Request, Data, Outcome};
use rocket::data::{self, FromData};
use rocket::http::Status;
use rocket::Outcome::*;
use serde_json;
use rocket_contrib::JSON;

#[derive(Queryable)]
#[derive(Serialize,Deserialize)]
pub struct Note {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub pinned: bool,
}

#[derive(Insertable, Deserialize, AsChangeset)]
#[table_name="notes"]
pub struct NoteData {
    pub title: String,
    pub body: String,
    pub pinned: bool,
}

impl FromData for NoteData {
    type Error = String;

    fn from_data(req: &Request, data: Data) -> data::Outcome<Self, String> {
        let reader = data.open();
        let json_data: JSON<NoteData> = match serde_json::from_reader(reader).map(|val| JSON(val)) {
            Ok(value) => value,
            Err(e) => {
                return Failure((Status::BadRequest, e.to_string()))
            }
        };

        Success(NoteData {
            title: json_data.title.to_owned(),
            body: json_data.body.to_owned(),
            pinned: json_data.pinned
        })
    }
}
<commit_msg>Remove unused variable and import warnings<commit_after>use super::schema::notes;
use rocket::{Request, Data};
use rocket::data::{self, FromData};
use rocket::http::Status;
use rocket::Outcome::*;
use serde_json;
use rocket_contrib::JSON;

#[derive(Queryable)]
#[derive(Serialize,Deserialize)]
pub struct Note {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub pinned: bool,
}

#[derive(Insertable, Deserialize, AsChangeset)]
#[table_name="notes"]
pub struct NoteData {
    pub title: String,
    pub body: String,
    pub pinned: bool,
}

impl FromData for NoteData {
    type Error = String;

    #[allow(unused_variables)]
    fn from_data(req: &Request, data: Data) -> data::Outcome<Self, String> {
        let reader = data.open();
        let json_data: JSON<NoteData> = match serde_json::from_reader(reader).map(|val| JSON(val)) {
            Ok(value) => value,
            Err(e) => {
                return Failure((Status::BadRequest, e.to_string()))
            }
        };

        Success(NoteData {
            title: json_data.title.to_owned(),
            body: json_data.body.to_owned(),
            pinned: json_data.pinned
        })
    }
}
<|endoftext|>


<commit_before>/// For some reason, Pest cannot find the grammar file if listed in parser/mod.rs
use pest::Parser;
use pest::iterators::Pair;
use pest::inputs::StrInput;

use ast::Expression;

use std::f64;

const _GRAMMAR: &str = include_str!("grammar/grammar.pest");

#[derive(Parser)]
#[grammar = "grammar/grammar.pest"]
pub struct ExpressionParser;

fn parse_expression(input: Pair<Rule, StrInput>) -> Expression {
    match input.as_rule() {
        Rule::function_literal => {
            let mut pairs = input.into_inner();

            let name = pairs
                        .next()
                        .unwrap()
                        .into_span()
                        .as_str()
                        .to_string();

            let args_list = pairs
                            .next()
                            .unwrap()
                            .into_inner()
                            .into_iter()
                            .map(|r| r.into_span().as_str().to_string())
                            .collect();

            let body = Box::new(
                            parse_expression(pairs.next().unwrap()));

            Expression::FuncLiteral(name, args_list, body)
        }

        Rule::function_call_literal => {
            let mut pairs = input.into_inner();

            let name = pairs
                        .next()
                        .unwrap()
                        .into_span()
                        .as_str()
                        .to_string();

            let args = pairs
                        .into_iter()
                        .map(|r| Box::new(parse_expression(r)))
                        .collect();

            Expression::FuncCall(name, args)
        }

        Rule::list_literal =>
            Expression::List(input
                            .into_inner()
                            .into_iter()
                            .map(|r| Box::new(parse_expression(r)))
                            .collect()),

        Rule::boolean_literal =>
            Expression::Boolean(
                input.into_span().as_str().parse::<bool>().unwrap()
            ),

        Rule::string_literal =>
            Expression::String(input.into_span().as_str().to_string()),

        Rule::identifier_literal =>
            Expression::Identifier(input.into_span().as_str().to_string()),

        // TODO: For now, just convert the value into a normal f64. No formatting!
        Rule::decimal_digits_literal =>
            Expression::Number(
                input.into_span().as_str().parse::<f64>().unwrap()
            ),

        Rule::binary_digits_literal =>
            // The parse function does not support binary digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 2).unwrap())
            ),

        Rule::oct_digits_literal =>
            // The parse function does not support octal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 8).unwrap())
            ),

        Rule::hex_digits_literal =>
            // The parse function does not support hexadecimal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 16).unwrap())
            ),

        // Temporary
        _ => unreachable!()
    }

}

pub fn parse(input: &str) -> Result<Expression, String> {
    // TODO: Remove unwrap
    match ExpressionParser::parse_str(Rule::main, input) {
        Ok(mut pair) => Ok(parse_expression(pair.nth(0).unwrap().into_inner().nth(0).unwrap())),

        Err(e) => Err(format!("{}", e)),
    }
}
<commit_msg>Update parser<commit_after>/// For some reason, Pest cannot find the grammar file if listed in parser/mod.rs
use pest::Parser;
use pest::iterators::Pair;

use ast::Expression;

use std::f64;

const _GRAMMAR: &str = include_str!("grammar/grammar.pest");

#[derive(Parser)]
#[grammar = "grammar/grammar.pest"]
pub struct ExpressionParser;

fn parse_expression(input: Pair<Rule>) -> Expression {
    match input.as_rule() {
        Rule::function_literal => {
            let mut pairs = input.into_inner();

            let name = pairs
                        .next()
                        .unwrap()
                        .into_span()
                        .as_str()
                        .to_string();

            let args_list = pairs
                            .next()
                            .unwrap()
                            .into_inner()
                            .into_iter()
                            .map(|r| r.into_span().as_str().to_string())
                            .collect();

            let body = Box::new(
                            parse_expression(pairs.next().unwrap()));

            Expression::FuncLiteral(name, args_list, body)
        }

        Rule::function_call_literal => {
            let mut pairs = input.into_inner();

            let name = pairs
                        .next()
                        .unwrap()
                        .into_span()
                        .as_str()
                        .to_string();

            let args = pairs
                        .into_iter()
                        .map(|r| Box::new(parse_expression(r)))
                        .collect();

            Expression::FuncCall(name, args)
        }

        Rule::list_literal =>
            Expression::List(input
                            .into_inner()
                            .into_iter()
                            .map(|r| Box::new(parse_expression(r)))
                            .collect()),

        Rule::boolean_literal =>
            Expression::Boolean(
                input.into_span().as_str().parse::<bool>().unwrap()
            ),

        Rule::string_literal =>
            Expression::String(input.into_span().as_str().to_string()),

        Rule::identifier_literal =>
            Expression::Identifier(input.into_span().as_str().to_string()),

        // TODO: For now, just convert the value into a normal f64. No formatting!
        Rule::decimal_digits_literal =>
            Expression::Number(
                input.into_span().as_str().parse::<f64>().unwrap()
            ),

        Rule::binary_digits_literal =>
            // The parse function does not support binary digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 2).unwrap())
            ),

        Rule::oct_digits_literal =>
            // The parse function does not support octal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 8).unwrap())
            ),

        Rule::hex_digits_literal =>
            // The parse function does not support hexadecimal digits, so do it the hard way
            Expression::Number(
                f64::from(i32::from_str_radix(&input.into_span().as_str()[2..], 16).unwrap())
            ),

        // Temporary
        _ => unreachable!()
    }

}

pub fn parse(input: &str) -> Result<Expression, String> {
    // TODO: Remove unwrap
    match ExpressionParser::parse(Rule::main, input) {
        Ok(mut pair) => Ok(parse_expression(pair.nth(0).unwrap().into_inner().nth(0).unwrap())),

        Err(e) => Err(format!("{}", e)),
    }
}
<|endoftext|>


<commit_before>
use pair::Pair;
use error::{NcclError, ErrorKind};
use token::{Token, TokenKind};

pub struct Parser {
    current: usize,
    path: Vec<String>,
    tokens: Vec<Token>,
    pair: Pair,
    line: u64,
}

// nccl = (value (":" value)? newline indent value newline)*
// value = [^:]+
// newline = "\n" | "\r\n"
// indent = " "+ | "\t"

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Self {
        Parser {
            current: 0,
            path: vec![],
            tokens: tokens,
            pair: Pair::new("__top_level__"),
            line: 1,
        }
    }

    pub fn parse(&mut self) -> Result<Pair, NcclError> {
        while !self.is_at_end() {
            self.value()?;
            if self.peek().kind == TokenKind::Value {
                self.colon()?;
                self.value()?;
            }
            self.newline()?;
            self.indent()?;
            self.value()?;
            self.newline()?;
        }

        Ok(self.pair.clone())
    }

    fn add(&mut self, value: String) {
        //self.pair.add_vec(self.path, value);
    }

    fn value(&mut self) -> Result<(), NcclError> {
        if !self.is_at_end() {
            Ok(())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, "Expected value, found EOF", self.line))
        }
    }

    fn indent(&mut self) -> Result<(), NcclError> {
        if !self.is_at_end() {
            Ok(())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, "Expected indent, found EOF", self.line))
        }
    }

    fn newline(&mut self) -> Result<(), NcclError> {
        if !self.is_at_end() {
            self.line += 1;
            Ok(())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, "Expected newline, found EOF", self.line))
        }
    }

    fn colon(&mut self) -> Result<(), NcclError> {
        if !self.is_at_end() {
            Ok(())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, "Expected colon, found EOF", self.line))
        }
    }

    fn matches(&mut self, kind: TokenKind) -> bool {
        if self.check(kind) {
            self.advance();
            true
        } else {
            false
        }
    }

    fn check(&mut self, kind: TokenKind) -> bool {
        if self.is_at_end() {
            false
        } else {
            self.peek().kind == kind
        }
    }

    fn advance(&mut self) -> &Token {
        if !self.is_at_end() {
            self.current += 1;
        }

        self.previous()
    }

    fn is_at_end(&mut self) -> bool {
        self.peek().kind == TokenKind::EOF
    }

    fn peek(&mut self) -> &Token {
        &self.tokens[self.current]
    }

    fn previous(&mut self) -> &Token {
        &self.tokens[self.current - 1]
    }

    fn consume(&mut self, kind: TokenKind, message: &str) -> Result<&Token, NcclError> {
        if self.check(kind) {
            Ok(self.advance())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, message, self.line))
        }
    }
}

<commit_msg>update ebnf<commit_after>
use pair::Pair;
use error::{NcclError, ErrorKind};
use token::{Token, TokenKind};

pub struct Parser {
    current: usize,
    path: Vec<String>,
    tokens: Vec<Token>,
    pair: Pair,
    line: u64,
}

// nccl = pair+
// pair = value schema? newline key+
// schema = ": " value
// key = indent (pair | value) newline
// value = [^:]+
// newline = "\n" | "\r\n"
// indent = " "+ | "\t"

impl Parser {
    pub fn new(tokens: Vec<Token>) -> Self {
        Parser {
            current: 0,
            path: vec![],
            tokens: tokens,
            pair: Pair::new("__top_level__"),
            line: 1,
        }
    }

    pub fn parse(&mut self) -> Result<Pair, NcclError> {
        while !self.is_at_end() {
            self.value()?;
            if self.peek().kind == TokenKind::Value {
                self.colon()?;
                self.value()?;
            }
            self.newline()?;
            self.indent()?;
            self.value()?;
            self.newline()?;
        }

        Ok(self.pair.clone())
    }

    fn add(&mut self, value: String) {
        //self.pair.add_vec(self.path, value);
    }

    fn value(&mut self) -> Result<(), NcclError> {
        if !self.is_at_end() {
            Ok(())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, "Expected value, found EOF", self.line))
        }
    }

    fn indent(&mut self) -> Result<(), NcclError> {
        if !self.is_at_end() {
            Ok(())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, "Expected indent, found EOF", self.line))
        }
    }

    fn newline(&mut self) -> Result<(), NcclError> {
        if !self.is_at_end() {
            self.line += 1;
            Ok(())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, "Expected newline, found EOF", self.line))
        }
    }

    fn colon(&mut self) -> Result<(), NcclError> {
        if !self.is_at_end() {
            Ok(())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, "Expected colon, found EOF", self.line))
        }
    }

    fn matches(&mut self, kind: TokenKind) -> bool {
        if self.check(kind) {
            self.advance();
            true
        } else {
            false
        }
    }

    fn check(&mut self, kind: TokenKind) -> bool {
        if self.is_at_end() {
            false
        } else {
            self.peek().kind == kind
        }
    }

    fn advance(&mut self) -> &Token {
        if !self.is_at_end() {
            self.current += 1;
        }

        self.previous()
    }

    fn is_at_end(&mut self) -> bool {
        self.peek().kind == TokenKind::EOF
    }

    fn peek(&mut self) -> &Token {
        &self.tokens[self.current]
    }

    fn previous(&mut self) -> &Token {
        &self.tokens[self.current - 1]
    }

    fn consume(&mut self, kind: TokenKind, message: &str) -> Result<&Token, NcclError> {
        if self.check(kind) {
            Ok(self.advance())
        } else {
            Err(NcclError::new(ErrorKind::ParseError, message, self.line))
        }
    }
}

<|endoftext|>