<commit_before>use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, decode};
use client;
use eventual::*;
use message::*;
use network::NetworkRead;
use std::fmt::Debug;
use std::io::Write;
use std::net::{SocketAddrV4, TcpListener, TcpStream};
use std::thread;
use std::time::Duration;
use time;

/// Current Unix timestamp
fn get_now() -> u64 {
    let now = time::get_time();
    let sec = now.sec;
    let nsec = now.nsec;
    // Consider using the Timespec directly instead.
    ((sec as u64) * 1_000_000) + (nsec as u64 / 1000)
}

/// Obtain one (any) valid response from all the shard responses.
fn read_one(key: &Key, responses: Vec<Future<InternodeResponse, Error>>) -> client::MessageResult {
    debug!("Reading one");

    Ok(sequence(responses)
           .await()
           .unwrap()
           .iter()
           .next()
           .map(|&(ref m, _)| {
               ResponseMessage {
                   message: m.clone().to_response(),
                   consistency: Consistency::One,
               }
           })
           .unwrap_or(ResponseMessage {
               message: Response::Error {
                   key: key.to_owned(),
                   message: "All the storage nodes replied with errors.".to_string(),
               },
               consistency: Consistency::One,
           }))
}

/// Obtain the newest `Value` among those stored in this shard's `StorageNode`s.
fn read_latest(key: &Key,
               responses: Vec<Future<InternodeResponse, Error>>)
               -> client::MessageResult {
    debug!("Reading quorum");

    let latest: Option<InternodeResponse> = sequence(responses)
                                                .reduce((0, None), |last, r| {
                                                    let (max_timestamp, max_response) = last;
                                                    debug!("Max timestamp so far: {:?}",
                                                           max_timestamp);
                                                    debug!("Max max_response so far: {:?}",
                                                           max_response);
                                                    match r.get_timestamp() {
                                                        Some(ts) => {
                                                            if ts >= max_timestamp {
                                                                (ts, Some(r.clone()))
                                                            } else {
                                                                (max_timestamp, max_response)
                                                            }
                                                        }
                                                        None => (max_timestamp, max_response),
                                                    }
                                                })
                                                .await()
                                                .unwrap()
                                                .1;

    debug!("Quorum read final response: {:?}", latest);

    match latest {
        Some(m) => {
            Ok(ResponseMessage {
                message: m.to_response(),
                consistency: Consistency::Latest,
            })
        }
        None => {
            Ok(ResponseMessage {
                message: Response::Error {
                    key: key.to_owned(),
                    message: "?".to_string(),
                },
                consistency: Consistency::Latest,
            })
        }
    }
}

/// Read from all nodes for this `Key`'s shard, and use `consistency` to
/// collate the `StorageNode`'s responses.
fn read(shards: &Vec<SocketAddrV4>, key: &Key, consistency: &Consistency) -> client::MessageResult {
    debug!("Read {:?} with {:?} consistency.", key, consistency);
    let mut responses: Vec<Future<InternodeResponse, Error>> = vec![];
    for shard in shards {
        let response = read_from_other_storage_node(&shard, &key);
        responses.push(response);
    }
    match consistency {
        &Consistency::One => read_one(key, responses),
        &Consistency::Latest => read_latest(key, responses),
    }
}

/// Write to all nodes for this `Key`'s shard, and use `consistency` to
/// determine when to acknowledge the write to the client.
fn write(shards: &Vec<SocketAddrV4>,
         key: &Key,
         value: &Value,
         consistency: &Consistency)
         -> client::MessageResult {
    let mut responses: Vec<Future<InternodeResponse, Error>> = vec![];
    for shard in shards {
        let response = write_to_other_storage_node(&shard, &key, &value);
        debug!("Write response for {:?}, {:?} @ Shard {:?}: {:?}",
               key,
               value,
               shard,
               response);
        responses.push(response);
    }
    let mut message = Response::Error {
        key: key.to_owned(),
        message: "Quorum write could not be accomplished.".to_string(),
    };

    let mut write_count = 0;
    for response_result in responses {
        match response_result.await() {
            Ok(response) => {
                match response {
                    InternodeResponse::WriteAck {key, timestamp} => {
                        write_count += 1;
                        if write_count >= (shards.len() / 2) + 1 {
                            debug!("Successful write to mayority of shards for {:?}", key);
                            message = Response::WriteAck {
                                key: key,
                                timestamp: timestamp,
                            };
                        }
                    }
                    _ => (),
                }
            }
            Err(_) => (),
        }
    }
    let r = ResponseMessage {
        message: message,
        consistency: consistency.to_owned(),
    };

    Ok(r)
}

fn read_from_other_storage_node(target: &SocketAddrV4,
                                key: &Key)
                                -> Future<InternodeResponse, Error> {
    debug!("Forwarding read request for {:?} to shard at {:?}.",
           key,
           target);
    let content = InternodeRequest::Read { key: key.to_owned() };
    client::Client::send_to_node(target, &content)
}

fn write_to_other_storage_node(target: &SocketAddrV4,
                               key: &Key,
                               value: &Value)
                               -> Future<InternodeResponse, Error> {
    debug!("Forwarding write request for {:?} to shard at {:?}.",
           key,
           target);
    let request = InternodeRequest::Write {
        key: key.to_owned(),
        value: value.to_owned(),
    };
    client::Client::send_to_node(target, &request)
}

/// Perform a client's `Request` in the appropriate shard and respond to the
/// client with a ResponseMessage.
pub fn handle_client(stream: &mut TcpStream, shards: &Vec<Vec<SocketAddrV4>>) {
    let mut value: Buffer = vec![];

    if stream.read_to_message_end(&mut value).is_err() {
        panic!("Couldn't read from stream.");
    }

    let request: Request = match decode(&value) {
        Ok(m) => m,
        Err(e) => panic!("Message decoding error! {:?}", e),
    };

    debug!("Message received: {:?}", request);

    let timestamp = get_now();
    let r = match request.action {
        Action::Read {key} => {
            let msg_shard = key.shard(shards.len());
            read(&shards[msg_shard], &key, &request.consistency)
        }
        Action::Write {key, content} => {
            let value = Value::Value {
                content: content.to_owned(),
                timestamp: timestamp,
            };
            let msg_shard = key.shard(shards.len());
            write(&shards[msg_shard], &key, &value, &request.consistency)
        }
        Action::Delete {key} => {
            let value = Value::Tombstone { timestamp: timestamp };
            let msg_shard = key.shard(shards.len());
            write(&shards[msg_shard], &key, &value, &request.consistency)
        }
    };
    debug!("Response to be sent: {:?}", r);
    let _ = match r {
        Ok(message) => {
            let encoded = encode(&message, SizeLimit::Infinite);
            match encoded {
                Ok(b) => {
                    match stream.write(&b) {
                        Ok(size) => debug!("Response sent (size: {})", size),
                        Err(e) => error!("Error sending message: {:?}, {:?}", message, e),
                    }
                }
                Err(e) => panic!("Message encoding error! {:?}", e),
            }
        }
        Err(e) => panic!("Communication error! {:?}", e),
    };
}

trait ClientHandler where Self: Debug {
    fn handle(&mut self, shards: &Vec<Vec<SocketAddrV4>>);
}

/// An sbahn aware stream
impl ClientHandler for TcpStream {
    fn handle(&mut self, shards: &Vec<Vec<SocketAddrV4>>) {
        debug!("Starting listener stream: {:?}", self);
        handle_client(self, &shards);
    }
}

/// Listen on `address` for incoming client requests, and perform them on the appropriate shards.
pub fn listen(address: &SocketAddrV4, shards: &Vec<Vec<SocketAddrV4>>) -> Future<(), ()> {
    let address = address.to_owned();
    let shards = shards.clone();

    let read_timeout = Some(Duration::from_millis(300));
    let write_timeout = Some(Duration::from_millis(300));

    Future::spawn(move || {
        let listener = TcpListener::bind(&address).unwrap();

        // Accept connections and process them, spawning a new thread for each one.
        for stream in listener.incoming() {
            let shards = shards.to_owned();
            match stream {
                Ok(stream) => {
                    let _ = stream.set_read_timeout(read_timeout);
                    let _ = stream.set_write_timeout(write_timeout);
                    thread::spawn(move || {
                        // connection succeeded
                        let mut stream = stream;
                        stream.handle(&shards);
                    });
                }
                Err(e) => error!("Connection failed!: {:?}", e),
            }
        }
    })
}
<commit_msg>Succeed on "latest" consistency read only when there's a quorum<commit_after>use bincode::SizeLimit;
use bincode::rustc_serialize::{encode, decode};
use client;
use eventual::*;
use message::*;
use network::NetworkRead;
use std::fmt::Debug;
use std::io::Write;
use std::net::{SocketAddrV4, TcpListener, TcpStream};
use std::thread;
use std::time::Duration;
use time;

/// Current Unix timestamp
fn get_now() -> u64 {
    let now = time::get_time();
    let sec = now.sec;
    let nsec = now.nsec;
    // Consider using the Timespec directly instead.
    ((sec as u64) * 1_000_000) + (nsec as u64 / 1000)
}

/// Obtain one (any) valid response from all the shard responses.
fn read_one(key: &Key, responses: Vec<Future<InternodeResponse, Error>>) -> client::MessageResult {
    debug!("Reading one");

    Ok(sequence(responses)
           .await()
           .unwrap()
           .iter()
           .next()
           .map(|&(ref m, _)| {
               ResponseMessage {
                   message: m.clone().to_response(),
                   consistency: Consistency::One,
               }
           })
           .unwrap_or(ResponseMessage {
               message: Response::Error {
                   key: key.to_owned(),
                   message: "All the storage nodes replied with errors.".to_string(),
               },
               consistency: Consistency::One,
           }))
}

/// Obtain the newest `Value` among those stored in this shard's `StorageNode`s.
fn read_latest(key: &Key,
               responses: Vec<Future<InternodeResponse, Error>>)
               -> client::MessageResult {
    debug!("Reading latest");
    let responses_needed = responses.len() / 2;
    let ((_, success_count), latest) =
        sequence(responses)
            .reduce(((0, 0), None), |last, r| {
                let ((max_timestamp, success_count), max_response) = last;
                debug!("Max timestamp so far: {:?}", max_timestamp);
                debug!("Max max_response so far: {:?}", max_response);
                match r.get_timestamp() {
                    Some(ts) => {
                        if ts >= max_timestamp {
                            ((ts, success_count + 1), Some(r.clone()))
                        } else {
                            ((max_timestamp, success_count + 1), max_response)
                        }
                    }
                    None => ((max_timestamp, success_count), max_response),
                }
            })
            .await()
            .unwrap();

    debug!("Quorum read final response: {:?}", latest);
    debug!("Nodes responed successfully: {:?}", success_count);
    debug!("Nodes needed for succesfull read: {:?}", responses_needed);

    if success_count <= responses_needed {
        info!("Not enough storage nodes succeeded: {:?} of at least {:?}",
              success_count,
              responses_needed);
        Ok(ResponseMessage {
            message: Response::Error {
                key: key.to_owned(),
                message: "Not enough storage nodes succeeded to give a response".to_string(),
            },
            consistency: Consistency::Latest,
        })
    } else {
        match latest {
            Some(m) => {
                Ok(ResponseMessage {
                    message: m.to_response(),
                    consistency: Consistency::Latest,
                })
            }
            None => {
                Ok(ResponseMessage {
                    message: Response::Error {
                        key: key.to_owned(),
                        message: "?".to_string(),
                    },
                    consistency: Consistency::Latest,
                })
            }
        }
    }
}

/// Read from all nodes for this `Key`'s shard, and use `consistency` to
/// collate the `StorageNode`'s responses.
fn read(shards: &Vec<SocketAddrV4>, key: &Key, consistency: &Consistency) -> client::MessageResult {
    debug!("Read {:?} with {:?} consistency.", key, consistency);
    let mut responses: Vec<Future<InternodeResponse, Error>> = vec![];
    for shard in shards {
        let response = read_from_other_storage_node(&shard, &key);
        responses.push(response);
    }
    match consistency {
        &Consistency::One => read_one(key, responses),
        &Consistency::Latest => read_latest(key, responses),
    }
}

/// Write to all nodes for this `Key`'s shard, and use `consistency` to
/// determine when to acknowledge the write to the client.
fn write(shards: &Vec<SocketAddrV4>,
         key: &Key,
         value: &Value,
         consistency: &Consistency)
         -> client::MessageResult {
    let mut responses: Vec<Future<InternodeResponse, Error>> = vec![];
    for shard in shards {
        let response = write_to_other_storage_node(&shard, &key, &value);
        debug!("Write response for {:?}, {:?} @ Shard {:?}: {:?}",
               key,
               value,
               shard,
               response);
        responses.push(response);
    }
    let mut message = Response::Error {
        key: key.to_owned(),
        message: "Quorum write could not be accomplished.".to_string(),
    };

    let mut write_count = 0;
    for response_result in responses {
        match response_result.await() {
            Ok(response) => {
                match response {
                    InternodeResponse::WriteAck {key, timestamp} => {
                        write_count += 1;
                        if write_count >= (shards.len() / 2) + 1 {
                            debug!("Successful write to mayority of shards for {:?}", key);
                            message = Response::WriteAck {
                                key: key,
                                timestamp: timestamp,
                            };
                        }
                    }
                    _ => (),
                }
            }
            Err(_) => (),
        }
    }
    let r = ResponseMessage {
        message: message,
        consistency: consistency.to_owned(),
    };

    Ok(r)
}

fn read_from_other_storage_node(target: &SocketAddrV4,
                                key: &Key)
                                -> Future<InternodeResponse, Error> {
    debug!("Forwarding read request for {:?} to shard at {:?}.",
           key,
           target);
    let content = InternodeRequest::Read { key: key.to_owned() };
    client::Client::send_to_node(target, &content)
}

fn write_to_other_storage_node(target: &SocketAddrV4,
                               key: &Key,
                               value: &Value)
                               -> Future<InternodeResponse, Error> {
    debug!("Forwarding write request for {:?} to shard at {:?}.",
           key,
           target);
    let request = InternodeRequest::Write {
        key: key.to_owned(),
        value: value.to_owned(),
    };
    client::Client::send_to_node(target, &request)
}

/// Perform a client's `Request` in the appropriate shard and respond to the
/// client with a ResponseMessage.
pub fn handle_client(stream: &mut TcpStream, shards: &Vec<Vec<SocketAddrV4>>) {
    let mut value: Buffer = vec![];

    if stream.read_to_message_end(&mut value).is_err() {
        panic!("Couldn't read from stream.");
    }

    let request: Request = match decode(&value) {
        Ok(m) => m,
        Err(e) => panic!("Message decoding error! {:?}", e),
    };

    debug!("Message received: {:?}", request);

    let timestamp = get_now();
    let r = match request.action {
        Action::Read {key} => {
            let msg_shard = key.shard(shards.len());
            read(&shards[msg_shard], &key, &request.consistency)
        }
        Action::Write {key, content} => {
            let value = Value::Value {
                content: content.to_owned(),
                timestamp: timestamp,
            };
            let msg_shard = key.shard(shards.len());
            write(&shards[msg_shard], &key, &value, &request.consistency)
        }
        Action::Delete {key} => {
            let value = Value::Tombstone { timestamp: timestamp };
            let msg_shard = key.shard(shards.len());
            write(&shards[msg_shard], &key, &value, &request.consistency)
        }
    };
    debug!("Response to be sent: {:?}", r);
    let _ = match r {
        Ok(message) => {
            let encoded = encode(&message, SizeLimit::Infinite);
            match encoded {
                Ok(b) => {
                    match stream.write(&b) {
                        Ok(size) => debug!("Response sent (size: {})", size),
                        Err(e) => error!("Error sending message: {:?}, {:?}", message, e),
                    }
                }
                Err(e) => panic!("Message encoding error! {:?}", e),
            }
        }
        Err(e) => panic!("Communication error! {:?}", e),
    };
}

trait ClientHandler where Self: Debug {
    fn handle(&mut self, shards: &Vec<Vec<SocketAddrV4>>);
}

/// An sbahn aware stream
impl ClientHandler for TcpStream {
    fn handle(&mut self, shards: &Vec<Vec<SocketAddrV4>>) {
        debug!("Starting listener stream: {:?}", self);
        handle_client(self, &shards);
    }
}

/// Listen on `address` for incoming client requests, and perform them on the appropriate shards.
pub fn listen(address: &SocketAddrV4, shards: &Vec<Vec<SocketAddrV4>>) -> Future<(), ()> {
    let address = address.to_owned();
    let shards = shards.clone();

    let read_timeout = Some(Duration::from_millis(300));
    let write_timeout = Some(Duration::from_millis(300));

    Future::spawn(move || {
        let listener = TcpListener::bind(&address).unwrap();

        // Accept connections and process them, spawning a new thread for each one.
        for stream in listener.incoming() {
            let shards = shards.to_owned();
            match stream {
                Ok(stream) => {
                    let _ = stream.set_read_timeout(read_timeout);
                    let _ = stream.set_write_timeout(write_timeout);
                    thread::spawn(move || {
                        // connection succeeded
                        let mut stream = stream;
                        stream.handle(&shards);
                    });
                }
                Err(e) => error!("Connection failed!: {:?}", e),
            }
        }
    })
}
<|endoftext|>


<commit_before>use std::mem;

use rustc::ty::{self, layout::{self, Size, Align}};
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::mir;

use rand::RngCore;

use crate::*;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Gets an instance for a path.
    fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
        let this = self.eval_context_ref();
        this.tcx
            .crates()
            .iter()
            .find(|&&krate| this.tcx.original_crate_name(krate).as_str() == path[0])
            .and_then(|krate| {
                let krate = DefId {
                    krate: *krate,
                    index: CRATE_DEF_INDEX,
                };
                let mut items = this.tcx.item_children(krate);
                let mut path_it = path.iter().skip(1).peekable();

                while let Some(segment) = path_it.next() {
                    for item in mem::replace(&mut items, Default::default()).iter() {
                        if item.ident.name.as_str() == *segment {
                            if path_it.peek().is_none() {
                                return Some(ty::Instance::mono(this.tcx.tcx, item.res.def_id()));
                            }

                            items = this.tcx.item_children(item.res.def_id());
                            break;
                        }
                    }
                }
                None
            })
            .ok_or_else(|| {
                let path = path.iter().map(|&s| s.to_owned()).collect();
                err_unsup!(PathNotFound(path)).into()
            })
    }

    /// Write a 0 of the appropriate size to `dest`.
    fn write_null(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
        self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest)
    }

    /// Test if this immediate equals 0.
    fn is_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, bool> {
        let this = self.eval_context_ref();
        let null = Scalar::from_int(0, this.memory().pointer_size());
        this.ptr_eq(val, null)
    }

    /// Turn a Scalar into an Option<NonNullScalar>
    fn test_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, Option<Scalar<Tag>>> {
        let this = self.eval_context_ref();
        Ok(if this.is_null(val)? {
            None
        } else {
            Some(val)
        })
    }

    /// Get the `Place` for a local
    fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Tag>> {
        let this = self.eval_context_mut();
        let place = mir::Place { base: mir::PlaceBase::Local(local), projection: None };
        this.eval_place(&place)
    }

    /// Generate some random bytes, and write them to `dest`.
    fn gen_random(
        &mut self,
        ptr: Scalar<Tag>,
        len: usize,
    ) -> InterpResult<'tcx>  {
        // Some programs pass in a null pointer and a length of 0
        // to their platform's random-generation function (e.g. getrandom())
        // on Linux. For compatibility with these programs, we don't perform
        // any additional checks - it's okay if the pointer is invalid,
        // since we wouldn't actually be writing to it.
        if len == 0 {
            return Ok(())
        }
        let this = self.eval_context_mut();

        let ptr = match this.memory().check_ptr_access(ptr, Size::from_bytes(len as u64), Align::from_bytes(1).unwrap())? {
            Some(ptr) => ptr,
            None => return Ok(()), // zero-sized access
        };

        let rng = this.memory_mut().extra.rng.get_mut();
        let mut data = vec![0; len];
        rng.fill_bytes(&mut data);

        let tcx = &{this.tcx.tcx};
        this.memory_mut().get_mut(ptr.alloc_id)?.write_bytes(tcx, ptr, &data)
    }

    /// Visits the memory covered by `place`, sensitive to freezing: the 3rd parameter
    /// will be true if this is frozen, false if this is in an `UnsafeCell`.
    fn visit_freeze_sensitive(
        &self,
        place: MPlaceTy<'tcx, Tag>,
        size: Size,
        mut action: impl FnMut(Pointer<Tag>, Size, bool) -> InterpResult<'tcx>,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_ref();
        trace!("visit_frozen(place={:?}, size={:?})", *place, size);
        debug_assert_eq!(size,
            this.size_and_align_of_mplace(place)?
            .map(|(size, _)| size)
            .unwrap_or_else(|| place.layout.size)
        );
        // Store how far we proceeded into the place so far. Everything to the left of
        // this offset has already been handled, in the sense that the frozen parts
        // have had `action` called on them.
        let mut end_ptr = place.ptr.assert_ptr();
        // Called when we detected an `UnsafeCell` at the given offset and size.
        // Calls `action` and advances `end_ptr`.
        let mut unsafe_cell_action = |unsafe_cell_ptr: Scalar<Tag>, unsafe_cell_size: Size| {
            let unsafe_cell_ptr = unsafe_cell_ptr.assert_ptr();
            debug_assert_eq!(unsafe_cell_ptr.alloc_id, end_ptr.alloc_id);
            debug_assert_eq!(unsafe_cell_ptr.tag, end_ptr.tag);
            // We assume that we are given the fields in increasing offset order,
            // and nothing else changes.
            let unsafe_cell_offset = unsafe_cell_ptr.offset;
            let end_offset = end_ptr.offset;
            assert!(unsafe_cell_offset >= end_offset);
            let frozen_size = unsafe_cell_offset - end_offset;
            // Everything between the end_ptr and this `UnsafeCell` is frozen.
            if frozen_size != Size::ZERO {
                action(end_ptr, frozen_size, /*frozen*/true)?;
            }
            // This `UnsafeCell` is NOT frozen.
            if unsafe_cell_size != Size::ZERO {
                action(unsafe_cell_ptr, unsafe_cell_size, /*frozen*/false)?;
            }
            // Update end end_ptr.
            end_ptr = unsafe_cell_ptr.wrapping_offset(unsafe_cell_size, this);
            // Done
            Ok(())
        };
        // Run a visitor
        {
            let mut visitor = UnsafeCellVisitor {
                ecx: this,
                unsafe_cell_action: |place| {
                    trace!("unsafe_cell_action on {:?}", place.ptr);
                    // We need a size to go on.
                    let unsafe_cell_size = this.size_and_align_of_mplace(place)?
                        .map(|(size, _)| size)
                        // for extern types, just cover what we can
                        .unwrap_or_else(|| place.layout.size);
                    // Now handle this `UnsafeCell`, unless it is empty.
                    if unsafe_cell_size != Size::ZERO {
                        unsafe_cell_action(place.ptr, unsafe_cell_size)
                    } else {
                        Ok(())
                    }
                },
            };
            visitor.visit_value(place)?;
        }
        // The part between the end_ptr and the end of the place is also frozen.
        // So pretend there is a 0-sized `UnsafeCell` at the end.
        unsafe_cell_action(place.ptr.ptr_wrapping_offset(size, this), Size::ZERO)?;
        // Done!
        return Ok(());

        /// Visiting the memory covered by a `MemPlace`, being aware of
        /// whether we are inside an `UnsafeCell` or not.
        struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
            where F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            ecx: &'ecx MiriEvalContext<'mir, 'tcx>,
            unsafe_cell_action: F,
        }

        impl<'ecx, 'mir, 'tcx, F>
            ValueVisitor<'mir, 'tcx, Evaluator<'tcx>>
        for
            UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
        where
            F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            type V = MPlaceTy<'tcx, Tag>;

            #[inline(always)]
            fn ecx(&self) -> &MiriEvalContext<'mir, 'tcx> {
                &self.ecx
            }

            // Hook to detect `UnsafeCell`.
            fn visit_value(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty);
                let is_unsafe_cell = match v.layout.ty.sty {
                    ty::Adt(adt, _) => Some(adt.did) == self.ecx.tcx.lang_items().unsafe_cell_type(),
                    _ => false,
                };
                if is_unsafe_cell {
                    // We do not have to recurse further, this is an `UnsafeCell`.
                    (self.unsafe_cell_action)(v)
                } else if self.ecx.type_is_freeze(v.layout.ty) {
                    // This is `Freeze`, there cannot be an `UnsafeCell`
                    Ok(())
                } else {
                    // Proceed further
                    self.walk_value(v)
                }
            }

            // Make sure we visit aggregrates in increasing offset order.
            fn visit_aggregate(
                &mut self,
                place: MPlaceTy<'tcx, Tag>,
                fields: impl Iterator<Item=InterpResult<'tcx, MPlaceTy<'tcx, Tag>>>,
            ) -> InterpResult<'tcx> {
                match place.layout.fields {
                    layout::FieldPlacement::Array { .. } => {
                        // For the array layout, we know the iterator will yield sorted elements so
                        // we can avoid the allocation.
                        self.walk_aggregate(place, fields)
                    }
                    layout::FieldPlacement::Arbitrary { .. } => {
                        // Gather the subplaces and sort them before visiting.
                        let mut places = fields.collect::<InterpResult<'tcx, Vec<MPlaceTy<'tcx, Tag>>>>()?;
                        places.sort_by_key(|place| place.ptr.assert_ptr().offset);
                        self.walk_aggregate(place, places.into_iter().map(Ok))
                    }
                    layout::FieldPlacement::Union { .. } => {
                        // Uh, what?
                        bug!("a union is not an aggregate we should ever visit")
                    }
                }
            }

            // We have to do *something* for unions.
            fn visit_union(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                // With unions, we fall back to whatever the type says, to hopefully be consistent
                // with LLVM IR.
                // FIXME: are we consistent, and is this really the behavior we want?
                let frozen = self.ecx.type_is_freeze(v.layout.ty);
                if frozen {
                    Ok(())
                } else {
                    (self.unsafe_cell_action)(v)
                }
            }

            // We should never get to a primitive, but always short-circuit somewhere above.
            fn visit_primitive(&mut self, _v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                bug!("we should always short-circuit before coming to a primitive")
            }
        }
    }
}
<commit_msg>Add semicolon<commit_after>use std::mem;

use rustc::ty::{self, layout::{self, Size, Align}};
use rustc::hir::def_id::{DefId, CRATE_DEF_INDEX};
use rustc::mir;

use rand::RngCore;

use crate::*;

impl<'mir, 'tcx> EvalContextExt<'mir, 'tcx> for crate::MiriEvalContext<'mir, 'tcx> {}

pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriEvalContextExt<'mir, 'tcx> {
    /// Gets an instance for a path.
    fn resolve_path(&self, path: &[&str]) -> InterpResult<'tcx, ty::Instance<'tcx>> {
        let this = self.eval_context_ref();
        this.tcx
            .crates()
            .iter()
            .find(|&&krate| this.tcx.original_crate_name(krate).as_str() == path[0])
            .and_then(|krate| {
                let krate = DefId {
                    krate: *krate,
                    index: CRATE_DEF_INDEX,
                };
                let mut items = this.tcx.item_children(krate);
                let mut path_it = path.iter().skip(1).peekable();

                while let Some(segment) = path_it.next() {
                    for item in mem::replace(&mut items, Default::default()).iter() {
                        if item.ident.name.as_str() == *segment {
                            if path_it.peek().is_none() {
                                return Some(ty::Instance::mono(this.tcx.tcx, item.res.def_id()));
                            }

                            items = this.tcx.item_children(item.res.def_id());
                            break;
                        }
                    }
                }
                None
            })
            .ok_or_else(|| {
                let path = path.iter().map(|&s| s.to_owned()).collect();
                err_unsup!(PathNotFound(path)).into()
            })
    }

    /// Write a 0 of the appropriate size to `dest`.
    fn write_null(&mut self, dest: PlaceTy<'tcx, Tag>) -> InterpResult<'tcx> {
        self.eval_context_mut().write_scalar(Scalar::from_int(0, dest.layout.size), dest)
    }

    /// Test if this immediate equals 0.
    fn is_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, bool> {
        let this = self.eval_context_ref();
        let null = Scalar::from_int(0, this.memory().pointer_size());
        this.ptr_eq(val, null)
    }

    /// Turn a Scalar into an Option<NonNullScalar>
    fn test_null(&self, val: Scalar<Tag>) -> InterpResult<'tcx, Option<Scalar<Tag>>> {
        let this = self.eval_context_ref();
        Ok(if this.is_null(val)? {
            None
        } else {
            Some(val)
        })
    }

    /// Get the `Place` for a local
    fn local_place(&mut self, local: mir::Local) -> InterpResult<'tcx, PlaceTy<'tcx, Tag>> {
        let this = self.eval_context_mut();
        let place = mir::Place { base: mir::PlaceBase::Local(local), projection: None };
        this.eval_place(&place)
    }

    /// Generate some random bytes, and write them to `dest`.
    fn gen_random(
        &mut self,
        ptr: Scalar<Tag>,
        len: usize,
    ) -> InterpResult<'tcx>  {
        // Some programs pass in a null pointer and a length of 0
        // to their platform's random-generation function (e.g. getrandom())
        // on Linux. For compatibility with these programs, we don't perform
        // any additional checks - it's okay if the pointer is invalid,
        // since we wouldn't actually be writing to it.
        if len == 0 {
            return Ok(());
        }
        let this = self.eval_context_mut();

        let ptr = match this.memory().check_ptr_access(ptr, Size::from_bytes(len as u64), Align::from_bytes(1).unwrap())? {
            Some(ptr) => ptr,
            None => return Ok(()), // zero-sized access
        };

        let rng = this.memory_mut().extra.rng.get_mut();
        let mut data = vec![0; len];
        rng.fill_bytes(&mut data);

        let tcx = &{this.tcx.tcx};
        this.memory_mut().get_mut(ptr.alloc_id)?.write_bytes(tcx, ptr, &data)
    }

    /// Visits the memory covered by `place`, sensitive to freezing: the 3rd parameter
    /// will be true if this is frozen, false if this is in an `UnsafeCell`.
    fn visit_freeze_sensitive(
        &self,
        place: MPlaceTy<'tcx, Tag>,
        size: Size,
        mut action: impl FnMut(Pointer<Tag>, Size, bool) -> InterpResult<'tcx>,
    ) -> InterpResult<'tcx> {
        let this = self.eval_context_ref();
        trace!("visit_frozen(place={:?}, size={:?})", *place, size);
        debug_assert_eq!(size,
            this.size_and_align_of_mplace(place)?
            .map(|(size, _)| size)
            .unwrap_or_else(|| place.layout.size)
        );
        // Store how far we proceeded into the place so far. Everything to the left of
        // this offset has already been handled, in the sense that the frozen parts
        // have had `action` called on them.
        let mut end_ptr = place.ptr.assert_ptr();
        // Called when we detected an `UnsafeCell` at the given offset and size.
        // Calls `action` and advances `end_ptr`.
        let mut unsafe_cell_action = |unsafe_cell_ptr: Scalar<Tag>, unsafe_cell_size: Size| {
            let unsafe_cell_ptr = unsafe_cell_ptr.assert_ptr();
            debug_assert_eq!(unsafe_cell_ptr.alloc_id, end_ptr.alloc_id);
            debug_assert_eq!(unsafe_cell_ptr.tag, end_ptr.tag);
            // We assume that we are given the fields in increasing offset order,
            // and nothing else changes.
            let unsafe_cell_offset = unsafe_cell_ptr.offset;
            let end_offset = end_ptr.offset;
            assert!(unsafe_cell_offset >= end_offset);
            let frozen_size = unsafe_cell_offset - end_offset;
            // Everything between the end_ptr and this `UnsafeCell` is frozen.
            if frozen_size != Size::ZERO {
                action(end_ptr, frozen_size, /*frozen*/true)?;
            }
            // This `UnsafeCell` is NOT frozen.
            if unsafe_cell_size != Size::ZERO {
                action(unsafe_cell_ptr, unsafe_cell_size, /*frozen*/false)?;
            }
            // Update end end_ptr.
            end_ptr = unsafe_cell_ptr.wrapping_offset(unsafe_cell_size, this);
            // Done
            Ok(())
        };
        // Run a visitor
        {
            let mut visitor = UnsafeCellVisitor {
                ecx: this,
                unsafe_cell_action: |place| {
                    trace!("unsafe_cell_action on {:?}", place.ptr);
                    // We need a size to go on.
                    let unsafe_cell_size = this.size_and_align_of_mplace(place)?
                        .map(|(size, _)| size)
                        // for extern types, just cover what we can
                        .unwrap_or_else(|| place.layout.size);
                    // Now handle this `UnsafeCell`, unless it is empty.
                    if unsafe_cell_size != Size::ZERO {
                        unsafe_cell_action(place.ptr, unsafe_cell_size)
                    } else {
                        Ok(())
                    }
                },
            };
            visitor.visit_value(place)?;
        }
        // The part between the end_ptr and the end of the place is also frozen.
        // So pretend there is a 0-sized `UnsafeCell` at the end.
        unsafe_cell_action(place.ptr.ptr_wrapping_offset(size, this), Size::ZERO)?;
        // Done!
        return Ok(());

        /// Visiting the memory covered by a `MemPlace`, being aware of
        /// whether we are inside an `UnsafeCell` or not.
        struct UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
            where F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            ecx: &'ecx MiriEvalContext<'mir, 'tcx>,
            unsafe_cell_action: F,
        }

        impl<'ecx, 'mir, 'tcx, F>
            ValueVisitor<'mir, 'tcx, Evaluator<'tcx>>
        for
            UnsafeCellVisitor<'ecx, 'mir, 'tcx, F>
        where
            F: FnMut(MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
        {
            type V = MPlaceTy<'tcx, Tag>;

            #[inline(always)]
            fn ecx(&self) -> &MiriEvalContext<'mir, 'tcx> {
                &self.ecx
            }

            // Hook to detect `UnsafeCell`.
            fn visit_value(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                trace!("UnsafeCellVisitor: {:?} {:?}", *v, v.layout.ty);
                let is_unsafe_cell = match v.layout.ty.sty {
                    ty::Adt(adt, _) => Some(adt.did) == self.ecx.tcx.lang_items().unsafe_cell_type(),
                    _ => false,
                };
                if is_unsafe_cell {
                    // We do not have to recurse further, this is an `UnsafeCell`.
                    (self.unsafe_cell_action)(v)
                } else if self.ecx.type_is_freeze(v.layout.ty) {
                    // This is `Freeze`, there cannot be an `UnsafeCell`
                    Ok(())
                } else {
                    // Proceed further
                    self.walk_value(v)
                }
            }

            // Make sure we visit aggregrates in increasing offset order.
            fn visit_aggregate(
                &mut self,
                place: MPlaceTy<'tcx, Tag>,
                fields: impl Iterator<Item=InterpResult<'tcx, MPlaceTy<'tcx, Tag>>>,
            ) -> InterpResult<'tcx> {
                match place.layout.fields {
                    layout::FieldPlacement::Array { .. } => {
                        // For the array layout, we know the iterator will yield sorted elements so
                        // we can avoid the allocation.
                        self.walk_aggregate(place, fields)
                    }
                    layout::FieldPlacement::Arbitrary { .. } => {
                        // Gather the subplaces and sort them before visiting.
                        let mut places = fields.collect::<InterpResult<'tcx, Vec<MPlaceTy<'tcx, Tag>>>>()?;
                        places.sort_by_key(|place| place.ptr.assert_ptr().offset);
                        self.walk_aggregate(place, places.into_iter().map(Ok))
                    }
                    layout::FieldPlacement::Union { .. } => {
                        // Uh, what?
                        bug!("a union is not an aggregate we should ever visit")
                    }
                }
            }

            // We have to do *something* for unions.
            fn visit_union(&mut self, v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                // With unions, we fall back to whatever the type says, to hopefully be consistent
                // with LLVM IR.
                // FIXME: are we consistent, and is this really the behavior we want?
                let frozen = self.ecx.type_is_freeze(v.layout.ty);
                if frozen {
                    Ok(())
                } else {
                    (self.unsafe_cell_action)(v)
                }
            }

            // We should never get to a primitive, but always short-circuit somewhere above.
            fn visit_primitive(&mut self, _v: MPlaceTy<'tcx, Tag>) -> InterpResult<'tcx>
            {
                bug!("we should always short-circuit before coming to a primitive")
            }
        }
    }
}
<|endoftext|>


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

use fuse;
use fuse::{Filesystem, Request, ReplyAttr, ReplyDirectory, ReplyEntry, FileAttr};

use libc::{ENOSYS, ENOENT};

use time::Timespec;
use std;
use std::ffi::OsStr;
use std::fs;
use std::time::SystemTime;
use std::path::Path;

pub struct S3HierarchicalFilesystem<'a> {
    mount_path: &'a str,
    backing_path: &'a str,
    ino_paths: std::collections::HashMap<u64, String>,
}

impl<'a> S3HierarchicalFilesystem<'a> {
    pub fn mount(mp: &str, bp: &str) -> Result<()> {
        let mut fs = S3HierarchicalFilesystem {
            mount_path: mp,
            backing_path: bp,
            ino_paths: std::collections::HashMap::new(),
        };
        fs.ino_paths.insert(1, bp.to_string());
        fuse::mount(fs, &mp, &[]).chain_err(|| "mounting filesystem")
    }
}

fn filetype_tryfrom(ft: &fs::FileType) -> Result<fuse::FileType> {
    if ft.is_file() {
        return Ok(fuse::FileType::RegularFile);
    }
    if ft.is_dir() {
        return Ok(fuse::FileType::Directory);
    }
    if ft.is_symlink() {
        return Ok(fuse::FileType::Symlink);
    }
    bail!("unknown filetype")
}

fn timespec_from(st: &SystemTime) -> Timespec {
    if let Ok(dur_since_epoch) = st.duration_since(std::time::UNIX_EPOCH) {
        Timespec::new(dur_since_epoch.as_secs() as i64,
                      dur_since_epoch.subsec_nanos() as i32)
    } else {
        Timespec::new(0, 0)
    }
}

fn fileattr_from(m: &std::fs::Metadata) -> FileAttr {
    use std::os::unix::fs::{MetadataExt, PermissionsExt};
    use std::time::SystemTime;

    let kind = filetype_tryfrom(&m.file_type()).unwrap();
    let mode = m.permissions().mode();
    FileAttr {
        ino: m.ino(),
        size: m.len(),
        blocks: m.blocks(),
        atime: timespec_from(&m.accessed().unwrap_or(SystemTime::now())),
        mtime: timespec_from(&m.modified().unwrap_or(SystemTime::now())),
        ctime: Timespec::new(m.ctime(), m.ctime_nsec() as i32),
        crtime: timespec_from(&m.created().unwrap_or(SystemTime::now())),
        kind: kind,
        perm: mode as u16,
        nlink: m.nlink() as u32,
        uid: m.uid(),
        gid: m.gid(),
        rdev: m.rdev() as u32,
        flags: 0,
    }
}

macro_rules! unwrap_or_return_error {
    ($v:expr, $log:expr, $err:expr, $reply:ident) => (
        match $v {
            Some(v) => v,
            None => {
                error!($log);
                $reply.error($err);
                return;
            }
        }
    )
}

macro_rules! ok_or_return_error {
    ($v:expr, $err:expr, $reply:ident) => (
        match $v {
            Ok(v) => v,
            Err(e) => {
                error!("{:?}", e);
                $reply.error($err);
                return;
            }
        }
    )
}

impl<'a> Filesystem for S3HierarchicalFilesystem<'a> {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        info!("getattr(ino={})", ino);
        debug!("req: {:?}", _req);

        let path = unwrap_or_return_error!(self.ino_paths.get(&ino),
                                           "ino not found in cache",
                                           ENOENT,
                                           reply);
        let metadata = ok_or_return_error!(std::fs::metadata(path), ENOENT, reply);

        debug!("{:?}", metadata);
        let attr = fileattr_from(&metadata);
        let ttl = Timespec::new(1, 0);
        reply.attr(&ttl, &attr);
    }

    fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) {
        info!("lookup(parent={}, name={:?})", parent, name);

        let parent_path = unwrap_or_return_error!(self.ino_paths.get(&parent),
                                                  "ino not found in cache",
                                                  ENOSYS,
                                                  reply);

        let file_name =
            unwrap_or_return_error!(name.to_str(), "unable to read name", ENOSYS, reply);

        let path = Path::new(&parent_path).join(file_name);
        debug!("Path: {:?}", path);
        match std::fs::metadata(path) {
            Ok(metadata) => {
                debug!("{:?}", metadata);
                let attr = fileattr_from(&metadata);
                let ttl = Timespec::new(1, 0);
                debug!("warning: generation assumed 0");
                reply.entry(&ttl, &attr, 0);
                debug!("{:?}", attr);
            }
            Err(e) => {
                error!("{}", e);
                reply.error(ENOENT);
            }
        };
    }

    fn readdir(&mut self,
               _req: &Request,
               ino: u64,
               fh: u64,
               offset: u64,
               mut reply: ReplyDirectory) {
        use std::os::unix::fs::DirEntryExt;

        info!("readdir(ino={}, fh={}, offset={})", ino, fh, offset);
        trace!("{:?}", _req);

        let path = unwrap_or_return_error!(self.ino_paths.get(&ino),
                                           "ino not found in cache",
                                           ENOSYS,
                                           reply)
            .to_string();

        if offset == 0 {
            reply.add(ino, 0, fuse::FileType::Directory, ".");
            reply.add(ino, 1, fuse::FileType::Directory, "..");
        }

        let rd = ok_or_return_error!(fs::read_dir(path), ENOENT, reply);

        for (i, entry_opt) in rd.enumerate() {
            debug!("Found entry {}: {:?}", i, entry_opt);
            if ((i + 2) as u64) < offset {
                continue;
            };
            if let Ok(entry) = entry_opt {
                if let Ok(ft) = entry.file_type() {
                    if let Ok(filetype) = filetype_tryfrom(&ft) {
                        debug!("adding entry: {}, {}, {:?}, {:?}",
                               entry.ino(),
                               (i + 2) as u64,
                               filetype,
                               entry.file_name());
                        if reply.add(entry.ino(), (i + 2) as u64, filetype, entry.file_name()) {
                            debug!("out of space");
                            break;
                        }
                    }
                }
            };
        }
        debug!("returning stuff");
        reply.ok();
    }
}
<commit_msg>solved looping readdir<commit_after>use super::errors::*;

use fuse;
use fuse::{Filesystem, Request, ReplyAttr, ReplyDirectory, ReplyEntry, FileAttr};

use libc::{ENOSYS, ENOENT};

use time::Timespec;
use std;
use std::ffi::OsStr;
use std::fs;
use std::time::SystemTime;
use std::path::{Path, PathBuf};

pub struct S3HierarchicalFilesystem<'a> {
    mount_path: &'a str,
    backing_path: &'a str,
    ino_paths: std::collections::HashMap<u64, PathBuf>,
}

impl<'a> S3HierarchicalFilesystem<'a> {
    pub fn mount(mp: &str, bp: &str) -> Result<()> {
        let mut fs = S3HierarchicalFilesystem {
            mount_path: mp,
            backing_path: bp,
            ino_paths: std::collections::HashMap::new(),
        };
        fs.ino_paths.insert(1, PathBuf::from(bp));
        fuse::mount(fs, &mp, &[]).chain_err(|| "mounting filesystem")
    }
}

fn filetype_tryfrom(ft: &fs::FileType) -> Result<fuse::FileType> {
    if ft.is_file() {
        return Ok(fuse::FileType::RegularFile);
    }
    if ft.is_dir() {
        return Ok(fuse::FileType::Directory);
    }
    if ft.is_symlink() {
        return Ok(fuse::FileType::Symlink);
    }
    bail!("unknown filetype")
}

fn timespec_from(st: &SystemTime) -> Timespec {
    if let Ok(dur_since_epoch) = st.duration_since(std::time::UNIX_EPOCH) {
        Timespec::new(dur_since_epoch.as_secs() as i64,
                      dur_since_epoch.subsec_nanos() as i32)
    } else {
        Timespec::new(0, 0)
    }
}

fn fileattr_from(m: &std::fs::Metadata) -> FileAttr {
    use std::os::unix::fs::{MetadataExt, PermissionsExt};
    use std::time::SystemTime;

    let kind = filetype_tryfrom(&m.file_type()).unwrap();
    let mode = m.permissions().mode();
    FileAttr {
        ino: m.ino(),
        size: m.len(),
        blocks: m.blocks(),
        atime: timespec_from(&m.accessed().unwrap_or(SystemTime::now())),
        mtime: timespec_from(&m.modified().unwrap_or(SystemTime::now())),
        ctime: Timespec::new(m.ctime(), m.ctime_nsec() as i32),
        crtime: timespec_from(&m.created().unwrap_or(SystemTime::now())),
        kind: kind,
        perm: mode as u16,
        nlink: m.nlink() as u32,
        uid: m.uid(),
        gid: m.gid(),
        rdev: m.rdev() as u32,
        flags: 0,
    }
}

fn dir_from(entry_opt: std::io::Result<fs::DirEntry>) -> Option<(u64, fuse::FileType, String)> {
    use std::os::unix::fs::DirEntryExt;

    let mut result = None;
    if let Ok(entry) = entry_opt {
        if let Ok(fsfiletype) = entry.file_type() {
            if let Ok(filetype) = filetype_tryfrom(&fsfiletype) {
                if let Ok(filename) = entry.file_name().into_string() {
                    result = Some((entry.ino(), filetype, filename));
                }
            }
        }
    }
    result
}

macro_rules! unwrap_or_return_error {
    ($v:expr, $log:expr, $err:expr, $reply:ident) => (
        match $v {
            Some(v) => v,
            None => {
                error!($log);
                $reply.error($err);
                return;
            }
        }
    )
}

macro_rules! ok_or_return_error {
    ($v:expr, $err:expr, $reply:ident) => (
        match $v {
            Ok(v) => v,
            Err(e) => {
                error!("{:?}", e);
                $reply.error($err);
                return;
            }
        }
    )
}

impl<'a> Filesystem for S3HierarchicalFilesystem<'a> {
    fn getattr(&mut self, _req: &Request, ino: u64, reply: ReplyAttr) {
        info!("getattr(ino={})", ino);
        debug!("req: {:?}", _req);

        let path = unwrap_or_return_error!(self.ino_paths.get(&ino),
                                           "ino not found in cache",
                                           ENOENT,
                                           reply);
        let metadata = ok_or_return_error!(std::fs::metadata(path), ENOENT, reply);

        debug!("{:?}", metadata);
        let attr = fileattr_from(&metadata);
        let ttl = Timespec::new(1, 0);
        reply.attr(&ttl, &attr);
    }

    fn lookup(&mut self, _req: &Request, parent: u64, name: &OsStr, reply: ReplyEntry) {
        info!("lookup(parent={}, name={:?})", parent, name);

        let parent_path = unwrap_or_return_error!(self.ino_paths.get(&parent),
                                                  "ino not found in cache",
                                                  ENOSYS,
                                                  reply);

        let file_name =
            unwrap_or_return_error!(name.to_str(), "unable to read name", ENOSYS, reply);

        let path = Path::new(&parent_path).join(file_name);
        debug!("Path: {:?}", path);
        match path.metadata() {
            Ok(metadata) => {
                debug!("{:?}", metadata);
                let attr = fileattr_from(&metadata);
                let ttl = Timespec::new(1, 0);
                debug!("warning: generation assumed 0");
                reply.entry(&ttl, &attr, 0);
                debug!("{:?}", attr);
            }
            Err(e) => {
                info!("std::fs::metadata: {}", e);
                reply.error(ENOENT);
            }
        };
    }

    fn readdir(&mut self,
               _req: &Request,
               ino: u64,
               fh: u64,
               offset: u64,
               mut reply: ReplyDirectory) {

        info!("readdir(ino={}, fh={}, offset={})", ino, fh, offset);
        trace!("{:?}", _req);

        let path = {
            let x = unwrap_or_return_error!(self.ino_paths.get(&ino),
                                            "ino not found in cache",
                                            ENOSYS,
                                            reply);
            x.clone()
        };

        if offset < 1 {
            reply.add(ino, 0, fuse::FileType::Directory, ".");
            reply.add(ino, 1, fuse::FileType::Directory, "..");
        };

        let rd = ok_or_return_error!(path.read_dir(), ENOENT, reply);

        for (i, entry_opt) in rd.enumerate() {
            let entry_offset = (i + 2) as u64;
            if offset >= entry_offset {
                continue;
            };
            let (ino, filetype, filename) = match dir_from(entry_opt) {
                Some(x) => x,
                None => {
                    error!("unable to extract directory entry");
                    reply.error(ENOENT);
                    return;
                }
            };
            debug!("Adding: {}, {}, {:?}, {}",
                   ino,
                   entry_offset,
                   filetype,
                   filename);
            if reply.add(ino, entry_offset, filetype, &filename) {
                break;
            }
            self.ino_paths.insert(ino, path.join(filename));
        }
        reply.ok();
    }
}
<|endoftext|>


<commit_before>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
use std::net::{
    Ipv4Addr,
    Ipv6Addr,
};
use std::ptr;
use std::str;

use types::{
    AddressFamily,
    IpAddr,
};
use utils::address_family;

#[repr(C)]
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct hostent {
    pub h_name: *mut libc::c_char,
    pub h_aliases: *mut *mut libc::c_char,
    pub h_addrtype: libc::c_int,
    pub h_length: libc::c_int,
    pub h_addr_list: *mut *mut libc::c_char,
}

impl hostent {
    pub fn hostname(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(self.h_name);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }

    pub fn addresses(&self) -> HostAddressResultsIterator {
        match address_family(self.h_addrtype) {
            Some(family) => HostAddressResultsIterator {
                family: family,
                next: self.h_addr_list as *const *const _,
                phantom: PhantomData,
            },
            None => HostAddressResultsIterator {
                family: AddressFamily::INET,
                next: ptr::null_mut(),
                phantom: PhantomData,
            }
        }
    }

    pub fn aliases(&self) -> HostAliasResultsIterator {
        HostAliasResultsIterator {
            next: self.h_aliases as *const *const _,
            phantom: PhantomData,
        }
    }
}

impl fmt::Display for hostent {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "Hostname: {}, ", self.hostname()));
        try!(write!(fmt, "Addresses: ["));
        let mut first = true;
        for host_addr in self.addresses() {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{}", prefix, host_addr));
        }
        try!(write!(fmt, "], "));
        try!(write!(fmt, "Aliases: ["));
        let mut first = true;
        for host_alias in self.aliases() {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{}", prefix, host_alias));
        }
        try!(write!(fmt, "]"));
        Ok(())
    }
}

/// An alias, as retrieved from a host lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAliasResult<'a> {
    h_alias: *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

/// An address, as retrieved from a host lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAddressResult<'a> {
    family: AddressFamily,
    h_addr: *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> HostAddressResult<'a> {
    /// Returns the IP address in this `HostResult`.
    pub fn ip_address(&self) -> IpAddr {
        match self.family {
            AddressFamily::INET => {
                let ipv4 = self.ipv4_address();
                IpAddr::V4(ipv4)
            },
            AddressFamily::INET6 => {
                let ipv6 = self.ipv6_addr();
                IpAddr::V6(ipv6)
            },
        }
    }

    fn ipv4_address(&self) -> Ipv4Addr {
        let h_addr = self.h_addr;
        unsafe {
            Ipv4Addr::new(
                *h_addr as u8,
                *h_addr.offset(1) as u8,
                *h_addr.offset(2) as u8,
                *h_addr.offset(3) as u8)
        }
    }

    fn ipv6_addr(&self) -> Ipv6Addr {
        let h_addr = self.h_addr;
        unsafe {
            Ipv6Addr::new(
                ((*h_addr as u16) << 8) + *h_addr.offset(1) as u16,
                ((*h_addr.offset(2) as u16) << 8) + *h_addr.offset(3) as u16,
                ((*h_addr.offset(4) as u16) << 8) + *h_addr.offset(5) as u16,
                ((*h_addr.offset(6) as u16) << 8) + *h_addr.offset(7) as u16,
                ((*h_addr.offset(8) as u16) << 8) + *h_addr.offset(9) as u16,
                ((*h_addr.offset(10) as u16) << 8) + *h_addr.offset(11) as u16,
                ((*h_addr.offset(12) as u16) << 8) + *h_addr.offset(13) as u16,
                ((*h_addr.offset(14) as u16) << 8) + *h_addr.offset(15) as u16)
        }
    }
}

impl<'a> fmt::Display for HostAddressResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.ip_address().fmt(fmt)
    }
}

unsafe impl<'a> Send for HostAddressResult<'a> { }
unsafe impl<'a> Sync for HostAddressResult<'a> { }

#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAddressResultsIterator<'a> {
    family: AddressFamily,
    next: *const *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> Iterator for HostAddressResultsIterator<'a> {
    type Item = HostAddressResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let h_addr = unsafe { *self.next };
        if h_addr.is_null() {
            None
        } else {
            self.next = unsafe { self.next.offset(1) };
            let addr_result = HostAddressResult {
                family: self.family,
                h_addr: h_addr,
                phantom: PhantomData,
            };
            Some(addr_result)
        }
    }
}

unsafe impl<'a> Send for HostAddressResultsIterator<'a> { }
unsafe impl<'a> Sync for HostAddressResultsIterator<'a> { }

impl<'a> HostAliasResult<'a> {
    /// Returns the alias in this `HostAliasResult`.
    pub fn alias(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(self.h_alias);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }
}

impl<'a> fmt::Display for HostAliasResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.alias().fmt(fmt)
    }
}

unsafe impl<'a> Send for HostAliasResult<'a> { }
unsafe impl<'a> Sync for HostAliasResult<'a> { }

#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAliasResultsIterator<'a> {
    next: *const *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> Iterator for HostAliasResultsIterator<'a> {
    type Item = HostAliasResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let h_alias = unsafe { *self.next };
        if h_alias.is_null() {
            None
        } else {
            self.next = unsafe { self.next.offset(1) };
            let alias_result = HostAliasResult {
                h_alias: h_alias,
                phantom: PhantomData,
            };
            Some(alias_result)
        }
    }
}

unsafe impl<'a> Send for HostAliasResultsIterator<'a> { }
unsafe impl<'a> Sync for HostAliasResultsIterator<'a> { }
<commit_msg>User ptr::null() in preference to ptr::null_mut()<commit_after>extern crate c_ares_sys;
extern crate libc;

use std::ffi::CStr;
use std::fmt;
use std::marker::PhantomData;
use std::net::{
    Ipv4Addr,
    Ipv6Addr,
};
use std::ptr;
use std::str;

use types::{
    AddressFamily,
    IpAddr,
};
use utils::address_family;

#[repr(C)]
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct hostent {
    pub h_name: *mut libc::c_char,
    pub h_aliases: *mut *mut libc::c_char,
    pub h_addrtype: libc::c_int,
    pub h_length: libc::c_int,
    pub h_addr_list: *mut *mut libc::c_char,
}

impl hostent {
    pub fn hostname(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(self.h_name);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }

    pub fn addresses(&self) -> HostAddressResultsIterator {
        match address_family(self.h_addrtype) {
            Some(family) => HostAddressResultsIterator {
                family: family,
                next: self.h_addr_list as *const *const _,
                phantom: PhantomData,
            },
            None => HostAddressResultsIterator {
                family: AddressFamily::INET,
                next: ptr::null(),
                phantom: PhantomData,
            }
        }
    }

    pub fn aliases(&self) -> HostAliasResultsIterator {
        HostAliasResultsIterator {
            next: self.h_aliases as *const *const _,
            phantom: PhantomData,
        }
    }
}

impl fmt::Display for hostent {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "Hostname: {}, ", self.hostname()));
        try!(write!(fmt, "Addresses: ["));
        let mut first = true;
        for host_addr in self.addresses() {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{}", prefix, host_addr));
        }
        try!(write!(fmt, "], "));
        try!(write!(fmt, "Aliases: ["));
        let mut first = true;
        for host_alias in self.aliases() {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{}", prefix, host_alias));
        }
        try!(write!(fmt, "]"));
        Ok(())
    }
}

/// An alias, as retrieved from a host lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAliasResult<'a> {
    h_alias: *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

/// An address, as retrieved from a host lookup.
#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAddressResult<'a> {
    family: AddressFamily,
    h_addr: *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> HostAddressResult<'a> {
    /// Returns the IP address in this `HostResult`.
    pub fn ip_address(&self) -> IpAddr {
        match self.family {
            AddressFamily::INET => {
                let ipv4 = self.ipv4_address();
                IpAddr::V4(ipv4)
            },
            AddressFamily::INET6 => {
                let ipv6 = self.ipv6_addr();
                IpAddr::V6(ipv6)
            },
        }
    }

    fn ipv4_address(&self) -> Ipv4Addr {
        let h_addr = self.h_addr;
        unsafe {
            Ipv4Addr::new(
                *h_addr as u8,
                *h_addr.offset(1) as u8,
                *h_addr.offset(2) as u8,
                *h_addr.offset(3) as u8)
        }
    }

    fn ipv6_addr(&self) -> Ipv6Addr {
        let h_addr = self.h_addr;
        unsafe {
            Ipv6Addr::new(
                ((*h_addr as u16) << 8) + *h_addr.offset(1) as u16,
                ((*h_addr.offset(2) as u16) << 8) + *h_addr.offset(3) as u16,
                ((*h_addr.offset(4) as u16) << 8) + *h_addr.offset(5) as u16,
                ((*h_addr.offset(6) as u16) << 8) + *h_addr.offset(7) as u16,
                ((*h_addr.offset(8) as u16) << 8) + *h_addr.offset(9) as u16,
                ((*h_addr.offset(10) as u16) << 8) + *h_addr.offset(11) as u16,
                ((*h_addr.offset(12) as u16) << 8) + *h_addr.offset(13) as u16,
                ((*h_addr.offset(14) as u16) << 8) + *h_addr.offset(15) as u16)
        }
    }
}

impl<'a> fmt::Display for HostAddressResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.ip_address().fmt(fmt)
    }
}

unsafe impl<'a> Send for HostAddressResult<'a> { }
unsafe impl<'a> Sync for HostAddressResult<'a> { }

#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAddressResultsIterator<'a> {
    family: AddressFamily,
    next: *const *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> Iterator for HostAddressResultsIterator<'a> {
    type Item = HostAddressResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let h_addr = unsafe { *self.next };
        if h_addr.is_null() {
            None
        } else {
            self.next = unsafe { self.next.offset(1) };
            let addr_result = HostAddressResult {
                family: self.family,
                h_addr: h_addr,
                phantom: PhantomData,
            };
            Some(addr_result)
        }
    }
}

unsafe impl<'a> Send for HostAddressResultsIterator<'a> { }
unsafe impl<'a> Sync for HostAddressResultsIterator<'a> { }

impl<'a> HostAliasResult<'a> {
    /// Returns the alias in this `HostAliasResult`.
    pub fn alias(&self) -> &str {
        unsafe {
            let c_str = CStr::from_ptr(self.h_alias);
            str::from_utf8_unchecked(c_str.to_bytes())
        }
    }
}

impl<'a> fmt::Display for HostAliasResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        self.alias().fmt(fmt)
    }
}

unsafe impl<'a> Send for HostAliasResult<'a> { }
unsafe impl<'a> Sync for HostAliasResult<'a> { }

#[derive(Debug)]
#[allow(raw_pointer_derive)]
pub struct HostAliasResultsIterator<'a> {
    next: *const *const libc::c_char,
    phantom: PhantomData<&'a hostent>,
}

impl<'a> Iterator for HostAliasResultsIterator<'a> {
    type Item = HostAliasResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        let h_alias = unsafe { *self.next };
        if h_alias.is_null() {
            None
        } else {
            self.next = unsafe { self.next.offset(1) };
            let alias_result = HostAliasResult {
                h_alias: h_alias,
                phantom: PhantomData,
            };
            Some(alias_result)
        }
    }
}

unsafe impl<'a> Send for HostAliasResultsIterator<'a> { }
unsafe impl<'a> Sync for HostAliasResultsIterator<'a> { }
<|endoftext|>


<commit_before>use std;

use std::collections::HashMap;
use std::fmt::Display;
use std::path::Path;

use ::opcodes::{AddressingMode, OpCode};
use assembler::lexer::{Lexer, LexerError};
use assembler::parser::{Parser, ParserError};
use assembler::token::{LexerToken, ParserToken};

#[derive(Debug, PartialEq)]
pub struct Label(u16);

#[derive(Debug)]
pub struct AssemblerError {
    message: String,
}

impl AssemblerError {
    fn unknown_label<S>(label: S) -> AssemblerError
        where S: Into<String> + std::fmt::Display
    {
        AssemblerError::from(format!("Unknown label: '{}'", label))
    }

    fn relative_offset_too_large<S>(context: S) -> AssemblerError
        where S: Into<String> + Display
    {
        AssemblerError::from(format!("Branch too far: {}", context))
    }
}

impl From<String> for AssemblerError {
    fn from(error: String) -> AssemblerError {
        AssemblerError { message: error }
    }
}

impl From<LexerError> for AssemblerError {
    fn from(error: LexerError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

impl From<ParserError> for AssemblerError {
    fn from(error: ParserError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

pub struct Assembler {
    symbol_table: HashMap<String, Label>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { symbol_table: HashMap::new() }
    }

    pub fn assemble_string<S>(&mut self, code: S) -> Result<Vec<u8>, AssemblerError>
        where S: Into<String>
    {
        let code = code.into();
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_string(code)?;
        let mut parser = Parser::new();
        let tokens = parser.parse(tokens)?;

        Ok(self.assemble(tokens)?)
    }

    pub fn assemble_file<P>(&mut self, path: P) -> Result<Vec<u8>, AssemblerError>
        where P: AsRef<Path>
    {
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_file(path)?;
        let mut parser = Parser::new();
        let tokens = Vec::new(); // TODO: Fix

        Ok(self.assemble(tokens)?)
    }

    fn assemble(&mut self, tokens: Vec<ParserToken>) -> Result<Vec<u8>, AssemblerError> {
        // First, index the labels so we have addresses for them
        self.index_labels(&tokens);

        // Now assemble the code
        let mut result = Vec::new();
        let mut addr: u16 = 0;
        let mut last_addressing_mode = AddressingMode::Absolute;

        for token in tokens {
            if let ParserToken::OpCode(opcode) = token {
                result.push(opcode.code);
                addr += opcode.length as u16;
                last_addressing_mode = opcode.mode;
            } else if let ParserToken::RawByte(byte) = token {
                result.push(byte);
            } else if let ParserToken::LabelArg(ref label) = token {
                if let Some(&Label(label_addr)) = self.symbol_table.get(label) {
                    if last_addressing_mode == AddressingMode::Absolute {
                        let low_byte = (label_addr & 0xFF) as u8;
                        let high_byte = ((label_addr >> 8) & 0xFF) as u8;

                        result.push(low_byte);
                        result.push(high_byte);
                    } else {
                        // Its relative.. lets generate a relative branch
                        if addr > label_addr {
                            let distance = (label_addr as i16 - addr as i16) as i8;
                            if distance < -128 || distance > 127 {
                                return Err(AssemblerError::relative_offset_too_large(format!("Attempted jump to {} at {:04X}", label, addr)));
                            }
                            result.push(distance as u8);
                        } else {
                            let distance = label_addr - addr;
                            if distance > 127 {
                                return Err(AssemblerError::relative_offset_too_large(format!("Attempted jump to {} at {:04X}", label, addr)));
                            }
                            result.push(distance as u8);
                        }
                    }
                } else {
                    return Err(AssemblerError::unknown_label(label.clone()));
                }
            }
        }

        Ok(result)
    }

    /// Stores all labels in the code in a Symbol table for lookup later
    fn index_labels(&mut self, tokens: &[ParserToken]) {
        let mut addr: u16 = 0;

        for token in tokens {
            if let &ParserToken::Label(ref label) = token {
                // Insert a label with the specified memory address
                // as its offset
                self.symbol_table.insert(label.clone(), Label(addr));
            } else if let &ParserToken::OpCode(opcode) = token {
                // Add the length of this opcode to our
                // address offset
                addr += opcode.length as u16;
            }
        }
    }
}

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

    #[test]
    fn can_assemble_basic_code() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            LDA $4400
        ")
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44], &bytes[..]);
    }

    #[test]
    fn can_jump_to_label_behind() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            MAIN LDA $4400
            PHA
            JMP MAIN
        ")
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44, 0x48, 0x4C, 0x00, 0x00], &bytes[..]);
    }

    #[test]
    fn can_jump_to_label_with_colon_behind() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            MAIN:
                LDA $4400
                PHA
                JMP MAIN
        ")
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44, 0x48, 0x4C, 0x00, 0x00], &bytes[..]);
    }

    #[test]
    fn can_jump_to_label_ahead() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            JMP MAIN
            PHA
            LDX #15
            MAIN LDA $4400
            RTS
        ")
            .unwrap();

        assert_eq!(&[0x4C, 0x06, 0x00, 0x48, 0xA2, 0x0F, 0xAD, 0x00, 0x44, 0x60],
                   &bytes[..]);
    }

    #[test]
    fn can_use_variables() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN:
            LDX #15
            JMP MAIN_ADDRESS
        ")
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0x4C, 0x00, 0x00], &bytes[..]);
    }

    #[test]
    fn can_use_variables_assigned_to_variables() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN_ADDRESS_INDIRECT_ONE = MAIN_ADDRESS
            MAIN_ADDRESS_INDIRECT_TWO = MAIN_ADDRESS_INDIRECT_ONE
            MAIN:
            LDX #15
            JMP MAIN_ADDRESS_INDIRECT_TWO
        ")
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0x4C, 0x00, 0x00], &bytes[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            CLRMEM  LDA #$00
                    TAY
            CLRM1   STA ($FF),Y
                    INY
                    DEX
                    BNE CLRM1
                    RTS
        ")
            .unwrap();

        assert_eq!(&[0xA9, 0x00, 0xA8, 0x91, 0xFF, 0xC8, 0xCA, 0xD0, 0xFA, 0x60],
                   &bytes[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation_that_jumps_forward() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            JMP     CLRMEM
            LDA     #$00
            BEQ     CLRM1
            NOP
            NOP
            BRK
            CLRM1   STA ($FF),Y
                    INY
                    DEX
                    BNE CLRM1
                    RTS
            CLRMEM  LDA #$00
                    TAY
            JMP     CLRM1
        ")
            .unwrap();

        assert_eq!(&[0x4C, 0x11, 0x00, 0xA9, 0x00, 0xF0, 0x03, 0xEA, 0xEA, 0x00, 0x91, 0xFF,
                     0xC8, 0xCA, 0xD0, 0xFA, 0x60, 0xA9, 0x00, 0xA8, 0x4C, 0x0A, 0x00],
                   &bytes[..]);
    }
}<commit_msg>Add lowercase tests<commit_after>use std;

use std::collections::HashMap;
use std::fmt::Display;
use std::path::Path;

use ::opcodes::{AddressingMode, OpCode};
use assembler::lexer::{Lexer, LexerError};
use assembler::parser::{Parser, ParserError};
use assembler::token::{LexerToken, ParserToken};

#[derive(Debug, PartialEq)]
pub struct Label(u16);

#[derive(Debug)]
pub struct AssemblerError {
    message: String,
}

impl AssemblerError {
    fn unknown_label<S>(label: S) -> AssemblerError
        where S: Into<String> + std::fmt::Display
    {
        AssemblerError::from(format!("Unknown label: '{}'", label))
    }

    fn relative_offset_too_large<S>(context: S) -> AssemblerError
        where S: Into<String> + Display
    {
        AssemblerError::from(format!("Branch too far: {}", context))
    }
}

impl From<String> for AssemblerError {
    fn from(error: String) -> AssemblerError {
        AssemblerError { message: error }
    }
}

impl From<LexerError> for AssemblerError {
    fn from(error: LexerError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

impl From<ParserError> for AssemblerError {
    fn from(error: ParserError) -> AssemblerError {
        AssemblerError { message: error.message }
    }
}

pub struct Assembler {
    symbol_table: HashMap<String, Label>,
}

impl Assembler {
    pub fn new() -> Assembler {
        Assembler { symbol_table: HashMap::new() }
    }

    pub fn assemble_string<S>(&mut self, code: S) -> Result<Vec<u8>, AssemblerError>
        where S: Into<String>
    {
        let code = code.into();
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_string(code)?;
        let mut parser = Parser::new();
        let tokens = parser.parse(tokens)?;

        Ok(self.assemble(tokens)?)
    }

    pub fn assemble_file<P>(&mut self, path: P) -> Result<Vec<u8>, AssemblerError>
        where P: AsRef<Path>
    {
        let mut lexer = Lexer::new();
        let tokens = lexer.lex_file(path)?;
        let mut parser = Parser::new();
        let tokens = Vec::new(); // TODO: Fix

        Ok(self.assemble(tokens)?)
    }

    fn assemble(&mut self, tokens: Vec<ParserToken>) -> Result<Vec<u8>, AssemblerError> {
        // First, index the labels so we have addresses for them
        self.index_labels(&tokens);

        // Now assemble the code
        let mut result = Vec::new();
        let mut addr: u16 = 0;
        let mut last_addressing_mode = AddressingMode::Absolute;

        for token in tokens {
            // Push an opcode into the output and increment our address
            // offset
            if let ParserToken::OpCode(opcode) = token {
                result.push(opcode.code);
                addr += opcode.length as u16;
                last_addressing_mode = opcode.mode;
            } else if let ParserToken::RawByte(byte) = token {
                // Push raw bytes directly into the output
                result.push(byte);
            } else if let ParserToken::LabelArg(ref label) = token {
                // Labels as arguments should be in the symbol table, look
                // it up and calculate the address direction/location
                if let Some(&Label(label_addr)) = self.symbol_table.get(label) {
                    if last_addressing_mode == AddressingMode::Absolute {
                        let low_byte = (label_addr & 0xFF) as u8;
                        let high_byte = ((label_addr >> 8) & 0xFF) as u8;

                        result.push(low_byte);
                        result.push(high_byte);
                    } else {
                        // Its relative.. lets generate a relative branch
                        if addr > label_addr {
                            let distance = (label_addr as i16 - addr as i16) as i8;
                            if distance < -128 || distance > 127 {
                                return Err(AssemblerError::relative_offset_too_large(format!("Attempted jump to {} at {:04X}", label, addr)));
                            }
                            result.push(distance as u8);
                        } else {
                            let distance = label_addr - addr;
                            if distance > 127 {
                                return Err(AssemblerError::relative_offset_too_large(format!("Attempted jump to {} at {:04X}", label, addr)));
                            }
                            result.push(distance as u8);
                        }
                    }
                } else {
                    return Err(AssemblerError::unknown_label(label.clone()));
                }
            }
        }

        Ok(result)
    }

    /// Stores all labels in the code in a Symbol table for lookup later
    fn index_labels(&mut self, tokens: &[ParserToken]) {
        let mut addr: u16 = 0;

        for token in tokens {
            if let &ParserToken::Label(ref label) = token {
                // Insert a label with the specified memory address
                // as its offset
                self.symbol_table.insert(label.clone(), Label(addr));
            } else if let &ParserToken::OpCode(opcode) = token {
                // Add the length of this opcode to our
                // address offset
                addr += opcode.length as u16;
            }
        }
    }
}

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

    #[test]
    fn can_assemble_basic_code() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            LDA $4400
        ")
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44], &bytes[..]);
    }

    #[test]
    fn can_jump_to_label_behind() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            MAIN LDA $4400
            PHA
            JMP MAIN
        ")
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44, 0x48, 0x4C, 0x00, 0x00], &bytes[..]);
    }

    #[test]
    fn can_jump_to_label_with_colon_behind() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            MAIN:
                LDA $4400
                PHA
                JMP MAIN
        ")
            .unwrap();

        assert_eq!(&[0xAD, 0x00, 0x44, 0x48, 0x4C, 0x00, 0x00], &bytes[..]);
    }

    #[test]
    fn can_jump_to_label_ahead() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            JMP MAIN
            PHA
            LDX #15
            MAIN LDA $4400
            RTS
        ")
            .unwrap();

        assert_eq!(&[0x4C, 0x06, 0x00, 0x48, 0xA2, 0x0F, 0xAD, 0x00, 0x44, 0x60],
                   &bytes[..]);
    }

    #[test]
    fn can_use_variables() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN:
            LDX #15
            JMP MAIN_ADDRESS
        ")
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0x4C, 0x00, 0x00], &bytes[..]);
    }

    #[test]
    fn can_use_variables_assigned_to_variables() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN_ADDRESS_INDIRECT_ONE = MAIN_ADDRESS
            MAIN_ADDRESS_INDIRECT_TWO = MAIN_ADDRESS_INDIRECT_ONE
            MAIN:
            LDX #15
            JMP MAIN_ADDRESS_INDIRECT_TWO
        ")
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0x4C, 0x00, 0x00], &bytes[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            CLRMEM  LDA #$00
                    TAY
            CLRM1   STA ($FF),Y
                    INY
                    DEX
                    BNE CLRM1
                    RTS
        ")
            .unwrap();

        assert_eq!(&[0xA9, 0x00, 0xA8, 0x91, 0xFF, 0xC8, 0xCA, 0xD0, 0xFA, 0x60],
                   &bytes[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation_that_jumps_forward() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            jmp     clrmem
            lda     #$00
            beq     clrm1
            nop
            nop
            brk
            clrm1   sta ($ff),y
                    iny
                    dex
                    bne clrm1
                    rts
            clrmem  lda #$00
                    tay
            jmp     clrm1
        ")
            .unwrap();

        assert_eq!(&[0x4C, 0x11, 0x00, 0xA9, 0x00, 0xF0, 0x03, 0xEA, 0xEA, 0x00, 0x91, 0xFF,
                     0xC8, 0xCA, 0xD0, 0xFA, 0x60, 0xA9, 0x00, 0xA8, 0x4C, 0x0A, 0x00],
                   &bytes[..]);
    }

    #[test]
    fn can_assemble_clearmem_implementation_that_jumps_forward_and_is_lowercase() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            JMP     CLRMEM
            LDA     #$00
            BEQ     CLRM1
            NOP
            NOP
            BRK
            CLRM1   STA ($FF),Y
                    INY
                    DEX
                    BNE CLRM1
                    RTS
            CLRMEM  LDA #$00
                    TAY
            JMP     CLRM1
        ")
            .unwrap();

        assert_eq!(&[0x4C, 0x11, 0x00, 0xA9, 0x00, 0xF0, 0x03, 0xEA, 0xEA, 0x00, 0x91, 0xFF,
                     0xC8, 0xCA, 0xD0, 0xFA, 0x60, 0xA9, 0x00, 0xA8, 0x4C, 0x0A, 0x00],
                   &bytes[..]);
    }

    #[test]
    fn can_use_variables_for_indirect_addressing() {
        let mut assembler = Assembler::new();
        let bytes = assembler.assemble_string("
            MAIN_ADDRESS = $0000
            MAIN:
            LDX #15
            LDA (MAIN_ADDRESS),Y
        ")
            .unwrap();

        assert_eq!(&[0xA2, 0x0F, 0xB1, 0x00, 0x00], &bytes[..]);
    }
}<|endoftext|>


<commit_before>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

/// Builds the proto files needed for the network crate.
fn main() {
    let proto_files = [
        "src/proto/consensus.proto",
        "src/proto/network.proto",
        "src/proto/state_synchronizer.proto",
        "src/proto/admission_control.proto",
    ];

    let proto_files_prost = ["src/proto/network.proto", "src/proto/mempool.proto"];

    let includes = ["../types/src/proto", "src/proto"];

    for file in &proto_files {
        println!("cargo:rerun-if-changed={}", file);
    }

    for file in &proto_files_prost {
        println!("cargo:rerun-if-changed={}", file);
    }

    protoc_rust::run(protoc_rust::Args {
        out_dir: "src/proto",
        input: &proto_files,
        includes: &includes,
        customize: protoc_rust::Customize {
            carllerche_bytes_for_bytes: Some(true),
            carllerche_bytes_for_string: Some(true),
            ..Default::default()
        },
    })
    .expect("protoc");

    prost_build::compile_protos(&proto_files_prost, &includes).unwrap();
}
<commit_msg>[network] stop generating network protos with rust-protobuf<commit_after>// Copyright (c) The Libra Core Contributors
// SPDX-License-Identifier: Apache-2.0

/// Builds the proto files needed for the network crate.
fn main() {
    let proto_files = [
        "src/proto/consensus.proto",
        "src/proto/state_synchronizer.proto",
        "src/proto/admission_control.proto",
    ];

    let proto_files_prost = ["src/proto/network.proto", "src/proto/mempool.proto"];

    let includes = ["../types/src/proto", "src/proto"];

    for file in &proto_files {
        println!("cargo:rerun-if-changed={}", file);
    }

    for file in &proto_files_prost {
        println!("cargo:rerun-if-changed={}", file);
    }

    protoc_rust::run(protoc_rust::Args {
        out_dir: "src/proto",
        input: &proto_files,
        includes: &includes,
        customize: protoc_rust::Customize {
            carllerche_bytes_for_bytes: Some(true),
            carllerche_bytes_for_string: Some(true),
            ..Default::default()
        },
    })
    .expect("protoc");

    prost_build::compile_protos(&proto_files_prost, &includes).unwrap();
}
<|endoftext|>


<commit_before>// Transfer all crates from one user to another.
//
// Usage:
//      cargo run --bin transfer-crates from-user to-user

#![deny(warnings)]

extern crate cargo_registry;
extern crate postgres;
extern crate time;
extern crate semver;

use std::env;
use std::io;
use std::io::prelude::*;

use cargo_registry::{Crate, User};
use cargo_registry::owner::OwnerKind;
use cargo_registry::Model;

#[allow(dead_code)]
fn main() {
    let conn = cargo_registry::db::connect_now_old();
    {
        let tx = conn.transaction().unwrap();
        transfer(&tx);
        tx.set_commit();
        tx.finish().unwrap();
    }
}

fn transfer(tx: &postgres::transaction::Transaction) {
    let from = match env::args().nth(1) {
        None => {
            println!("needs a from-user argument");
            return;
        }
        Some(s) => s,
    };
    let to = match env::args().nth(2) {
        None => {
            println!("needs a to-user argument");
            return;
        }
        Some(s) => s,
    };

    let from = User::find_by_login(tx, &from).unwrap();
    let to = User::find_by_login(tx, &to).unwrap();

    if from.gh_id != to.gh_id {
        println!("====================================================");
        println!("WARNING");
        println!("");
        println!("this may not be the same github user, different github IDs");
        println!("");
        println!("from: {:?}", from.gh_id);
        println!("to:   {:?}", to.gh_id);

        get_confirm("continue?");
    }

    println!(
        "Are you sure you want to transfer crates from {} to {}",
        from.gh_login,
        to.gh_login
    );
    get_confirm("continue");

    let stmt = tx.prepare(
        "SELECT * FROM crate_owners
                                   WHERE owner_id = $1
                                     AND owner_kind = $2",
    ).unwrap();
    let rows = stmt.query(&[&from.id, &(OwnerKind::User as i32)]).unwrap();

    for row in rows.iter() {
        let krate = Crate::find(tx, row.get("crate_id")).unwrap();
        println!("transferring {}", krate.name);
        let owners = krate.owners_old(tx).unwrap();
        if owners.len() != 1 {
            println!("warning: not exactly one owner for {}", krate.name);
        }
    }

    tx.execute(
        "UPDATE crate_owners SET owner_id = $1
                             WHERE owner_id = $2",
        &[&to.id, &from.id],
    ).unwrap();

    get_confirm("commit?");
}

fn get_confirm(msg: &str) {
    print!("{} [y/N]: ", msg);
    io::stdout().flush().unwrap();
    let mut line = String::new();
    io::stdin().read_line(&mut line).unwrap();
    if !line.starts_with("y") {
        std::process::exit(0);
    }
}
<commit_msg>Port `bin/transfer-crates` over to Diesel<commit_after>// Transfer all crates from one user to another.
//
// Usage:
//      cargo run --bin transfer-crates from-user to-user

#![deny(warnings)]

extern crate cargo_registry;
extern crate diesel;
extern crate semver;

use diesel::prelude::*;
use diesel::pg::PgConnection;
use std::env;
use std::io;
use std::io::prelude::*;

use cargo_registry::{Crate, User};
use cargo_registry::owner::OwnerKind;
use cargo_registry::schema::*;

fn main() {
    let conn = cargo_registry::db::connect_now().unwrap();
    conn.transaction::<_, diesel::result::Error, _>(|| {
        transfer(&conn);
        Ok(())
    }).unwrap()
}

fn transfer(conn: &PgConnection) {
    let from = match env::args().nth(1) {
        None => {
            println!("needs a from-user argument");
            return;
        }
        Some(s) => s,
    };
    let to = match env::args().nth(2) {
        None => {
            println!("needs a to-user argument");
            return;
        }
        Some(s) => s,
    };

    let from = users::table
        .filter(users::gh_login.eq(from))
        .first::<User>(conn)
        .unwrap();
    let to = users::table
        .filter(users::gh_login.eq(to))
        .first::<User>(conn)
        .unwrap();

    if from.gh_id != to.gh_id {
        println!("====================================================");
        println!("WARNING");
        println!("");
        println!("this may not be the same github user, different github IDs");
        println!("");
        println!("from: {:?}", from.gh_id);
        println!("to:   {:?}", to.gh_id);

        get_confirm("continue?");
    }

    println!(
        "Are you sure you want to transfer crates from {} to {}",
        from.gh_login,
        to.gh_login
    );
    get_confirm("continue");

    let crate_owners = crate_owners::table
        .filter(crate_owners::owner_id.eq(from.id))
        .filter(crate_owners::owner_kind.eq(OwnerKind::User as i32));
    let crates = Crate::all()
        .filter(crates::id.eq_any(
            crate_owners.select(crate_owners::crate_id),
        ))
        .load::<Crate>(conn)
        .unwrap();

    for krate in crates {
        let owners = krate.owners(conn).unwrap();
        if owners.len() != 1 {
            println!("warning: not exactly one owner for {}", krate.name);
        }
    }

    diesel::update(crate_owners)
        .set(crate_owners::owner_id.eq(to.id))
        .execute(conn)
        .unwrap();

    get_confirm("commit?");
}

fn get_confirm(msg: &str) {
    print!("{} [y/N]: ", msg);
    io::stdout().flush().unwrap();
    let mut line = String::new();
    io::stdin().read_line(&mut line).unwrap();
    if !line.starts_with("y") {
        std::process::exit(0);
    }
}
<|endoftext|>