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

use math;
use math::{Point2, Point3, Point4};
use modules::NoiseModule;
use num_traits::Float;
use std::f64::consts::PI;

/// Noise Module that rotates the input value around the origin before
/// returning the output value from the source module.
///
/// The get() method rotates the coordinates of the input value around the
/// origin before returning the output value from the source module.
///
/// The coordinate system of the input value is assumed to be "right-handed"
/// (_x_ increases to the right, _y_ increases upward, and _z_ increases inward).
pub struct RotatePoint<Source, T> {
    /// Source Module that outputs a value
    pub source: Source,

    /// _x_ rotation angle applied to the input value, in degrees. The
    /// default angle is set to 0.0 degrees.
    pub x_angle: T,

    /// _y_ rotation angle applied to the input value, in degrees. The
    /// default angle is set to 0.0 degrees.
    pub y_angle: T,

    /// _z_ rotation angle applied to the input value, in degrees. The
    /// default angle is set to 0.0 degrees.
    pub z_angle: T,

    /// _u_ rotation angle applied to the input value, in degrees. The
    /// default angle is set to 0.0 degrees.
    pub u_angle: T,
}

impl<Source, T> RotatePoint<Source, T>
    where T: Float,
{
    pub fn new(source: Source) -> RotatePoint<Source, T> {
        RotatePoint {
            source: source,
            x_angle: T::zero(),
            y_angle: T::zero(),
            z_angle: T::zero(),
            u_angle: T::zero(),
        }
    }

    /// Sets the rotation angle around the _x_ axis to apply to the input
    /// value.
    pub fn set_x_angle(self, x_angle: T) -> RotatePoint<Source, T> {
        RotatePoint { x_angle: x_angle, ..self }
    }

    /// Sets the rotation angle around the _y_ axis to apply to the input
    /// value.
    pub fn set_y_angle(self, y_angle: T) -> RotatePoint<Source, T> {
        RotatePoint { y_angle: y_angle, ..self }
    }

    /// Sets the rotation angle around the _z_ axis to apply to the input
    /// value.
    pub fn set_z_angle(self, z_angle: T) -> RotatePoint<Source, T> {
        RotatePoint { z_angle: z_angle, ..self }
    }

    /// Sets the rotation angle around the _u_ axis to apply to the input
    /// value.
    pub fn set_u_angle(self, u_angle: T) -> RotatePoint<Source, T> {
        RotatePoint { u_angle: u_angle, ..self }
    }

    /// Sets the rotation angles around all of the axes to apply to the input
    /// value.
    pub fn set_angles(self,
                      x_angle: T,
                      y_angle: T,
                      z_angle: T,
                      u_angle: T)
                      -> RotatePoint<Source, T> {
        RotatePoint {
            x_angle: x_angle,
            y_angle: y_angle,
            z_angle: z_angle,
            u_angle: u_angle,
            ..self
        }
    }
}

impl<Source, T> NoiseModule<Point2<T>> for RotatePoint<Source, T>
    where Source: NoiseModule<Point2<T>, Output = T>,
          T: Float,
{
    type Output = T;

    fn get(&self, point: Point2<T>) -> Self::Output {
        // In two dimensions, the plane is _xy_, and we rotate around the
        // z-axis.
        let x = point[0];
        let y = point[1];
        let theta = deg_to_rad(self.z_angle);

        let x2 = x * theta.cos() - y * theta.sin();
        let y2 = x * theta.sin() + y * theta.cos();

        // get the output value using the offset input value instead of the
        // original input value.
        self.source.get([x2, y2])
    }
}

impl<Source, T> NoiseModule<Point3<T>> for RotatePoint<Source, T>
    where Source: NoiseModule<Point3<T>, Output = T>,
          T: Float,
{
    type Output = T;

    fn get(&self, point: Point3<T>) -> Self::Output {
        // In three dimensions, we could rotate around any of the x, y, or z
        // axes. Need a more complicated function to handle this case.
        let x_cos = deg_to_rad(self.x_angle).cos();
        let y_cos = deg_to_rad(self.y_angle).cos();
        let z_cos = deg_to_rad(self.z_angle).cos();
        let x_sin = deg_to_rad(self.x_angle).sin();
        let y_sin = deg_to_rad(self.y_angle).sin();
        let z_sin = deg_to_rad(self.z_angle).sin();

        let x1 = x_sin * y_sin * z_sin + y_cos * z_cos;
        let y1 = x_cos * z_sin;
        let z1 = y_sin * z_cos - y_cos * x_sin * z_sin;
        let x2 = y_sin * x_sin * z_cos - y_cos * z_sin;
        let y2 = x_cos * z_cos;
        let z2 = -y_cos * x_sin * z_cos - y_sin * z_sin;
        let x3 = -y_sin * x_cos;
        let y3 = x_sin;
        let z3 = y_cos * x_cos;

        let x = (x1 * point[0]) + (y1 * point[1]) + (z1 * point[2]);
        let y = (x2 * point[0]) + (y2 * point[1]) + (z2 * point[2]);
        let z = (x3 * point[0]) + (y3 * point[1]) + (z3 * point[2]);

        // get the output value using the offset input value instead of the
        // original input value.
        self.source.get([x, y, z])
    }
}

impl<Source, T> NoiseModule<Point4<T>> for RotatePoint<Source, T>
    where Source: NoiseModule<Point4<T>, Output = T>,
          T: Float,
{
    type Output = T;

    fn get(&self, _point: Point4<T>) -> Self::Output {
        // 4d rotations are hard.
        panic!("4d not implemented!");
    }
}

fn deg_to_rad<T: Float>(x: T) -> T {
    (x / math::cast(180.0)) * math::cast(PI)
}
<commit_msg>Replace panic with unimplemented<commit_after>// Copyright (c) 2017 The Noise-rs Developers.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT
// or http://opensource.org/licenses/MIT>, at your option. All files in the
// project carrying such notice may not be copied, modified, or distributed
// except according to those terms.

use math;
use math::{Point2, Point3, Point4};
use modules::NoiseModule;
use num_traits::Float;
use std::f64::consts::PI;

/// Noise Module that rotates the input value around the origin before
/// returning the output value from the source module.
///
/// The get() method rotates the coordinates of the input value around the
/// origin before returning the output value from the source module.
///
/// The coordinate system of the input value is assumed to be "right-handed"
/// (_x_ increases to the right, _y_ increases upward, and _z_ increases inward).
pub struct RotatePoint<Source, T> {
    /// Source Module that outputs a value
    pub source: Source,

    /// _x_ rotation angle applied to the input value, in degrees. The
    /// default angle is set to 0.0 degrees.
    pub x_angle: T,

    /// _y_ rotation angle applied to the input value, in degrees. The
    /// default angle is set to 0.0 degrees.
    pub y_angle: T,

    /// _z_ rotation angle applied to the input value, in degrees. The
    /// default angle is set to 0.0 degrees.
    pub z_angle: T,

    /// _u_ rotation angle applied to the input value, in degrees. The
    /// default angle is set to 0.0 degrees.
    pub u_angle: T,
}

impl<Source, T> RotatePoint<Source, T>
    where T: Float,
{
    pub fn new(source: Source) -> RotatePoint<Source, T> {
        RotatePoint {
            source: source,
            x_angle: T::zero(),
            y_angle: T::zero(),
            z_angle: T::zero(),
            u_angle: T::zero(),
        }
    }

    /// Sets the rotation angle around the _x_ axis to apply to the input
    /// value.
    pub fn set_x_angle(self, x_angle: T) -> RotatePoint<Source, T> {
        RotatePoint { x_angle: x_angle, ..self }
    }

    /// Sets the rotation angle around the _y_ axis to apply to the input
    /// value.
    pub fn set_y_angle(self, y_angle: T) -> RotatePoint<Source, T> {
        RotatePoint { y_angle: y_angle, ..self }
    }

    /// Sets the rotation angle around the _z_ axis to apply to the input
    /// value.
    pub fn set_z_angle(self, z_angle: T) -> RotatePoint<Source, T> {
        RotatePoint { z_angle: z_angle, ..self }
    }

    /// Sets the rotation angle around the _u_ axis to apply to the input
    /// value.
    pub fn set_u_angle(self, u_angle: T) -> RotatePoint<Source, T> {
        RotatePoint { u_angle: u_angle, ..self }
    }

    /// Sets the rotation angles around all of the axes to apply to the input
    /// value.
    pub fn set_angles(self,
                      x_angle: T,
                      y_angle: T,
                      z_angle: T,
                      u_angle: T)
                      -> RotatePoint<Source, T> {
        RotatePoint {
            x_angle: x_angle,
            y_angle: y_angle,
            z_angle: z_angle,
            u_angle: u_angle,
            ..self
        }
    }
}

impl<Source, T> NoiseModule<Point2<T>> for RotatePoint<Source, T>
    where Source: NoiseModule<Point2<T>, Output = T>,
          T: Float,
{
    type Output = T;

    fn get(&self, point: Point2<T>) -> Self::Output {
        // In two dimensions, the plane is _xy_, and we rotate around the
        // z-axis.
        let x = point[0];
        let y = point[1];
        let theta = deg_to_rad(self.z_angle);

        let x2 = x * theta.cos() - y * theta.sin();
        let y2 = x * theta.sin() + y * theta.cos();

        // get the output value using the offset input value instead of the
        // original input value.
        self.source.get([x2, y2])
    }
}

impl<Source, T> NoiseModule<Point3<T>> for RotatePoint<Source, T>
    where Source: NoiseModule<Point3<T>, Output = T>,
          T: Float,
{
    type Output = T;

    fn get(&self, point: Point3<T>) -> Self::Output {
        // In three dimensions, we could rotate around any of the x, y, or z
        // axes. Need a more complicated function to handle this case.
        let x_cos = deg_to_rad(self.x_angle).cos();
        let y_cos = deg_to_rad(self.y_angle).cos();
        let z_cos = deg_to_rad(self.z_angle).cos();
        let x_sin = deg_to_rad(self.x_angle).sin();
        let y_sin = deg_to_rad(self.y_angle).sin();
        let z_sin = deg_to_rad(self.z_angle).sin();

        let x1 = x_sin * y_sin * z_sin + y_cos * z_cos;
        let y1 = x_cos * z_sin;
        let z1 = y_sin * z_cos - y_cos * x_sin * z_sin;
        let x2 = y_sin * x_sin * z_cos - y_cos * z_sin;
        let y2 = x_cos * z_cos;
        let z2 = -y_cos * x_sin * z_cos - y_sin * z_sin;
        let x3 = -y_sin * x_cos;
        let y3 = x_sin;
        let z3 = y_cos * x_cos;

        let x = (x1 * point[0]) + (y1 * point[1]) + (z1 * point[2]);
        let y = (x2 * point[0]) + (y2 * point[1]) + (z2 * point[2]);
        let z = (x3 * point[0]) + (y3 * point[1]) + (z3 * point[2]);

        // get the output value using the offset input value instead of the
        // original input value.
        self.source.get([x, y, z])
    }
}

impl<Source, T> NoiseModule<Point4<T>> for RotatePoint<Source, T>
    where Source: NoiseModule<Point4<T>, Output = T>,
          T: Float,
{
    type Output = T;

    fn get(&self, _point: Point4<T>) -> Self::Output {
        // 4d rotations are hard.
        unimplemented!();
    }
}

fn deg_to_rad<T: Float>(x: T) -> T {
    (x / math::cast(180.0)) * math::cast(PI)
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::sync::{Arc, Mutex, RwLock, Weak};

use actors::{Actor, ActorRef, ActorSystem, CanReceive, Message, Props};

/// Special messages issued by the actor system.
#[derive(Clone)]
pub enum SystemMessage {
    /// Restarts the actor by repa=lacing it with a new version created with its Props.
    Restart,

    /// Makes the actor launch its initialisation.
    Start,

    /// Tells an actor that its child failed.
    Failure(Arc<CanReceive>),
}

enum Ref<T> {
    StrongRef(Arc<T>),
    WeakRef(Weak<T>),
}

/// Main interface for accessing the main Actor information (system, mailbox, sender, props...).
pub struct ActorCell<Args: Message, M: Message, A: Actor<M> + 'static> {
    // We have an inner structure in order to be able to generate new ActorCell easily.
    inner_cell: Ref<InnerActorCell<Args, M, A>>,
}

impl<Args: Message, M: Message, A: Actor<M>> Clone for ActorCell<Args, M, A> {
    fn clone(&self) -> ActorCell<Args, M, A> {
        ActorCell {
            inner_cell: Ref::WeakRef(match self.inner_cell {
                Ref::StrongRef(ref inner) => Arc::downgrade(&inner),
                Ref::WeakRef(ref inner) => inner.clone(),
            })
        }
    }
}

impl<Args: Message, M: Message, A: Actor<M> + 'static> ActorCell<Args, M, A> {
    /// Creates a new ActorCell.
    pub fn new(actor: A, props: Props<Args, M, A>, system: ActorSystem, father: Arc<CanReceive>) -> ActorCell<Args, M, A> {
        ActorCell {
            inner_cell: Ref::StrongRef(Arc::new(InnerActorCell::new(actor, props, system, father))),
        }
    }

    /// Puts a message with its sender in the Actor's mailbox and schedules the Actor.
    pub fn receive_message(&self, message: M, sender: Arc<CanReceive >) {
        // TODO(gamazeps) make  a macro for this.
        let inner = match self.inner_cell {
            Ref::StrongRef(ref inner) => inner.clone(),
            Ref::WeakRef(ref inner) => match inner.upgrade() {
                Some(inner) => inner.clone(),
                None => {
                    println!("A message was send to a ref to a stopped actor");
                    return;
                },
            }
        };
        inner.receive_message(message, sender);
        inner.system.enqueue_actor(self.actor_ref());
    }

    /// Puts a system message with its sender in the Actor's system mailbox and schedules the Actor.
    pub fn receive_system_message(&self, system_message: SystemMessage) {
        // TODO(gamazeps) make  a macro for this.
        let inner = match self.inner_cell {
            Ref::StrongRef(ref inner) => inner.clone(),
            Ref::WeakRef(ref inner) => match inner.upgrade() {
                Some(inner) => inner,
                None => {
                    println!("A message was send to a ref to a stopped actor");
                    return;
                },
            }
        };
        inner.receive_system_message(system_message);
        inner.system.enqueue_actor(self.actor_ref());
    }

    /// Makes the Actor handle an envelope in its mailbaox.
    pub fn handle_envelope(&self) {
        // TODO(gamazeps) make  a macro for this.
        let inner = match self.inner_cell {
            Ref::StrongRef(ref inner) => inner.clone(),
            Ref::WeakRef(ref inner) => match inner.upgrade() {
                Some(inner) => inner,
                None => {
                    println!("A message was send to a ref to a stopped actor");
                    return;
                },
            }
        };
        inner.handle_envelope(self.clone());
    }
}

/// This is the API that Actors are supposed to see of their context while handling a message.
pub trait ActorContext<Args: Message, M: Message, A: Actor<M> + 'static> {
    /// Returns an ActorRef of the Actor.
    fn actor_ref(&self) -> ActorRef<Args, M, A>;

    /// Spawns an actor.
    ///
    /// Note that the supervision is not yet implemented so it does the same as creating an actor
    /// through the actor system.
    fn actor_of<ArgBis: Message, MBis: Message, ABis: Actor<MBis> + 'static>(&self, props: Props<ArgBis, MBis, ABis>) -> ActorRef<ArgBis, MBis, ABis>;

    /// Sends a Message to the targeted CanReceive<M>.
    fn tell<MessageTo: Message, T: CanReceive>(&self, to: T, message: MessageTo);

    /// Returns an Arc to the sender of the message being handled.
    fn sender(&self) -> Arc<CanReceive >;

    /// Children of the actor.
    fn children(&self) -> Vec<Arc<CanReceive>>;

    /// Lifecycle monitoring, list of monitored actors.
    fn monitoring(&self) -> Vec<Arc<CanReceive>>;
}

impl<Args: Message, M: Message, A: Actor<M> + 'static> ActorContext<Args, M, A> for ActorCell<Args, M, A> {
    fn actor_ref(&self) -> ActorRef<Args, M, A> {
        ActorRef::with_cell(self.clone())
    }

    fn actor_of<ArgBis: Message, MBis: Message, ABis: Actor<MBis> + 'static>(&self, props: Props<ArgBis, MBis, ABis>) -> ActorRef<ArgBis, MBis, ABis> {
        let actor = props.create();
        let inner = match self.inner_cell {
            Ref::StrongRef(ref inner) => inner.clone(),
            Ref::WeakRef(ref inner) => match inner.upgrade() {
                Some(inner) => inner.clone(),
                None => {
                    panic!("Tried to create an actor from the context of a no longer existing actor");
                },
            }
        };
        let inner_cell = InnerActorCell::new(actor, props, inner.system.clone(),
                                             Arc::new(self.actor_ref()));
        let actor_cell = ActorCell {
            inner_cell: Ref::StrongRef(Arc::new(inner_cell)),
        };
        let my_child = ActorRef::with_cell(actor_cell);
        let their_view = my_child.clone();
        {inner.children.lock().unwrap().push(Arc::new(my_child));}
        {inner.monitoring.lock().unwrap().push(Arc::new(their_view.clone()));}
        their_view.receive_system_message(SystemMessage::Start);
        their_view
    }

    fn tell<MessageTo: Message, T: CanReceive>(&self, to: T, message: MessageTo) {
        to.receive(Box::new(message), Arc::new(self.actor_ref()));
    }

    fn sender(&self) -> Arc<CanReceive > {
        let inner = match self.inner_cell {
            Ref::StrongRef(ref inner) => inner.clone(),
            Ref::WeakRef(ref inner) => match inner.upgrade() {
                Some(inner) => inner.clone(),
                None => {
                    panic!("Tried to get a sender from the context of a no longer existing actor");
                },
            }
        };
        let current_sender = inner.current_sender.lock().unwrap().as_ref().unwrap().clone();
        current_sender
    }

    fn children(&self) -> Vec<Arc<CanReceive>> {
        let inner = match self.inner_cell {
            Ref::StrongRef(ref inner) => inner.clone(),
            Ref::WeakRef(ref inner) => match inner.upgrade() {
                Some(inner) => inner.clone(),
                None => {
                    panic!("Tried to get the children from the context of a no longer existing actor");
                },
            }
        };
        let children = inner.children.lock().unwrap().clone();
        children
    }

    fn monitoring(&self) -> Vec<Arc<CanReceive>> {
        let inner = match self.inner_cell {
            Ref::StrongRef(ref inner) => inner.clone(),
            Ref::WeakRef(ref inner) => match inner.upgrade() {
                Some(inner) => inner.clone(),
                None => {
                    panic!("Tried to get the monitored actors from the context of a no longer existing actor");
                },
            }
        };
        let monitoring = inner.monitoring.lock().unwrap().clone();
        monitoring
    }
}

struct Failsafe {
    father: Arc<CanReceive>,
    child: Arc<CanReceive>,
    active: bool,
}

impl Failsafe {
    fn new(father: Arc<CanReceive>, child: Arc<CanReceive>) -> Failsafe {
        Failsafe {
            father: father,
            child: child,
            active: true,
        }
    }

    fn cancel(mut self) {
        self.active = false;
    }
}

impl Drop for Failsafe {
    fn drop(&mut self) {
        if self.active {
            self.father.receive_system_message(SystemMessage::Failure(self.child.clone()));
        }
    }
}

struct InnerActorCell<Args: Message, M: Message, A: Actor<M> + 'static> {
    actor: RwLock<A>,
    mailbox: Mutex<VecDeque<Envelope<M>>>,
    system_mailbox: Mutex<VecDeque<SystemMessage>>,
    props: Props<Args, M, A>,
    system: ActorSystem,
    current_sender: Mutex<Option<Arc<CanReceive>>>,
    busy: Mutex<()>,
    father: Arc<CanReceive>,
    children: Mutex<Vec<Arc<CanReceive>>>,
    monitoring: Mutex<Vec<Arc<CanReceive>>>,
    _monitored: Mutex<Vec<Arc<CanReceive>>>,
}

struct Envelope<M> {
    message: M,
    sender: Arc<CanReceive>,
}

impl<Args: Message, M: Message, A: Actor<M> + 'static> InnerActorCell<Args, M, A> {
    fn new(actor: A, props: Props<Args, M, A>, system: ActorSystem, father: Arc<CanReceive>) -> InnerActorCell<Args, M, A> {
        InnerActorCell {
            actor: RwLock::new(actor),
            mailbox: Mutex::new(VecDeque::new()),
            system_mailbox: Mutex::new(VecDeque::new()),
            props: props,
            system: system,
            current_sender: Mutex::new(None),
            busy: Mutex::new(()),
            father: father.clone(),
            children: Mutex::new(Vec::new()),
            monitoring: Mutex::new(Vec::new()),
            _monitored: Mutex::new(vec![father.clone()]),
        }
    }

    fn receive_envelope(&self, envelope: Envelope<M>) {
        self.mailbox.lock().unwrap().push_back(envelope);
    }

    fn receive_message(&self, message: M, sender: Arc<CanReceive>) {
        self.receive_envelope(Envelope{message: message, sender: sender});
    }

    fn receive_system_message(&self, system_message: SystemMessage) {
        self.system_mailbox.lock().unwrap().push_back(system_message);
    }

    fn handle_envelope(&self, context: ActorCell<Args, M, A>) {
        // Now we do not want users to be able to touch current_sender while the actor is busy.
        let _lock = self.busy.lock();
        let failsafe = Failsafe::new(self.father.clone(), Arc::new(context.actor_ref()));
        // System messages are handled first, so that we can restart an actor if he failed without
        // loosing the messages in the mailbox.
        // NOTE: This does not break the fact that messages sent by the same actor are treated in
        // the order they are sent (if all to the same target actor), as system messages must not
        // be sent by other actors by the user.
        if let Some(message) = self.system_mailbox.lock().unwrap().pop_front() {
            match message {
                SystemMessage::Restart => self.restart(),
                SystemMessage::Start => self.start(),
                SystemMessage::Failure(actor) => actor.receive_system_message(SystemMessage::Restart),
            }
            failsafe.cancel();
            return;
        }
        let envelope = match self.mailbox.lock().unwrap().pop_front() {
            Some(envelope) => envelope,
            None => {
                failsafe.cancel();
                return;
            }
        };
        {
            let mut current_sender = self.current_sender.lock().unwrap();
            *current_sender = Some(envelope.sender.clone());
        };
        {
            let actor = self.actor.read().unwrap();
            actor.receive(envelope.message, context);
        }
        failsafe.cancel();
    }

    fn start(&self) {
        self.actor.write().unwrap().pre_start();
    }

    fn restart(&self) {
        let mut actor = self.actor.write().unwrap();
        actor.pre_restart();
        *actor = self.props.create();
        actor.post_restart();
    }
}

impl<Args: Message, M: Message, A: Actor<M> + 'static> Drop for InnerActorCell<Args, M, A> {
    fn drop(&mut self) {
        println!("dropped an actor cell");
    }
}

<commit_msg>Added the macro<commit_after>use std::collections::VecDeque;
use std::sync::{Arc, Mutex, RwLock, Weak};

use actors::{Actor, ActorRef, ActorSystem, CanReceive, Message, Props};

/// Special messages issued by the actor system.
#[derive(Clone)]
pub enum SystemMessage {
    /// Restarts the actor by repa=lacing it with a new version created with its Props.
    Restart,

    /// Makes the actor launch its initialisation.
    Start,

    /// Tells an actor that its child failed.
    Failure(Arc<CanReceive>),
}

enum Ref<T> {
    StrongRef(Arc<T>),
    WeakRef(Weak<T>),
}

macro_rules! unwrap_inner {
    ($r:expr, $b:block) => {
        match $r {
            Ref::StrongRef(ref inner) => inner.clone(),
            Ref::WeakRef(ref inner) => match inner.upgrade() {
                Some(inner) => inner.clone(),
                None => {
                    $b
                },
            }
        }
    }
}

/// Main interface for accessing the main Actor information (system, mailbox, sender, props...).
pub struct ActorCell<Args: Message, M: Message, A: Actor<M> + 'static> {
    // We have an inner structure in order to be able to generate new ActorCell easily.
    inner_cell: Ref<InnerActorCell<Args, M, A>>,
}

impl<Args: Message, M: Message, A: Actor<M>> Clone for ActorCell<Args, M, A> {
    fn clone(&self) -> ActorCell<Args, M, A> {
        ActorCell {
            inner_cell: Ref::WeakRef(match self.inner_cell {
                Ref::StrongRef(ref inner) => Arc::downgrade(&inner),
                Ref::WeakRef(ref inner) => inner.clone(),
            })
        }
    }
}

impl<Args: Message, M: Message, A: Actor<M> + 'static> ActorCell<Args, M, A> {
    /// Creates a new ActorCell.
    pub fn new(actor: A, props: Props<Args, M, A>, system: ActorSystem, father: Arc<CanReceive>) -> ActorCell<Args, M, A> {
        ActorCell {
            inner_cell: Ref::StrongRef(Arc::new(InnerActorCell::new(actor, props, system, father))),
        }
    }

    /// Puts a message with its sender in the Actor's mailbox and schedules the Actor.
    pub fn receive_message(&self, message: M, sender: Arc<CanReceive >) {
        let inner = unwrap_inner!(self.inner_cell,
                                {
                                    println!("A message was send to a ref to a stopped actor");
                                    return;
                                });
        inner.receive_message(message, sender);
        inner.system.enqueue_actor(self.actor_ref());
    }

    /// Puts a system message with its sender in the Actor's system mailbox and schedules the Actor.
    pub fn receive_system_message(&self, system_message: SystemMessage) {
        let inner = unwrap_inner!(self.inner_cell,
                                {
                                    println!("A message was send to a ref to a stopped actor");
                                    return;
                                });
        inner.receive_system_message(system_message);
        inner.system.enqueue_actor(self.actor_ref());
    }

    /// Makes the Actor handle an envelope in its mailbaox.
    pub fn handle_envelope(&self) {
        let inner = unwrap_inner!(self.inner_cell,
                                {
                                    println!("A message was send to a ref to a stopped actor");
                                    return;
                                });
        inner.handle_envelope(self.clone());
    }
}

/// This is the API that Actors are supposed to see of their context while handling a message.
pub trait ActorContext<Args: Message, M: Message, A: Actor<M> + 'static> {
    /// Returns an ActorRef of the Actor.
    fn actor_ref(&self) -> ActorRef<Args, M, A>;

    /// Spawns an actor.
    ///
    /// Note that the supervision is not yet implemented so it does the same as creating an actor
    /// through the actor system.
    fn actor_of<ArgBis: Message, MBis: Message, ABis: Actor<MBis> + 'static>(&self, props: Props<ArgBis, MBis, ABis>) -> ActorRef<ArgBis, MBis, ABis>;

    /// Sends a Message to the targeted CanReceive<M>.
    fn tell<MessageTo: Message, T: CanReceive>(&self, to: T, message: MessageTo);

    /// Returns an Arc to the sender of the message being handled.
    fn sender(&self) -> Arc<CanReceive >;

    /// Children of the actor.
    fn children(&self) -> Vec<Arc<CanReceive>>;

    /// Lifecycle monitoring, list of monitored actors.
    fn monitoring(&self) -> Vec<Arc<CanReceive>>;
}

impl<Args: Message, M: Message, A: Actor<M> + 'static> ActorContext<Args, M, A> for ActorCell<Args, M, A> {
    fn actor_ref(&self) -> ActorRef<Args, M, A> {
        ActorRef::with_cell(self.clone())
    }

    fn actor_of<ArgBis: Message, MBis: Message, ABis: Actor<MBis> + 'static>(&self, props: Props<ArgBis, MBis, ABis>) -> ActorRef<ArgBis, MBis, ABis> {
        let inner = unwrap_inner!(self.inner_cell,
                                  {
                                    panic!("Tried to create an actor from the context of a no longer
                                           existing actor");
                                  });
        let actor = props.create();
        let inner_cell = InnerActorCell::new(actor, props, inner.system.clone(),
                                             Arc::new(self.actor_ref()));
        let actor_cell = ActorCell {
            inner_cell: Ref::StrongRef(Arc::new(inner_cell)),
        };
        let internal_ref = ActorRef::with_cell(actor_cell);
        let external_ref = internal_ref.clone();
        {inner.children.lock().unwrap().push(Arc::new(internal_ref));}
        {inner.monitoring.lock().unwrap().push(Arc::new(external_ref.clone()));}
        external_ref.receive_system_message(SystemMessage::Start);
        external_ref
    }

    fn tell<MessageTo: Message, T: CanReceive>(&self, to: T, message: MessageTo) {
        to.receive(Box::new(message), Arc::new(self.actor_ref()));
    }

    fn sender(&self) -> Arc<CanReceive > {
        let inner = unwrap_inner!(self.inner_cell,
                                  {
                                    panic!("Tried to get a sender from the context of a no longer
                                           existing actor");
                                  });
        let current_sender = inner.current_sender.lock().unwrap().as_ref().unwrap().clone();
        current_sender
    }

    fn children(&self) -> Vec<Arc<CanReceive>> {
        let inner = unwrap_inner!(self.inner_cell,
                                  {
                                      panic!("Tried to get the children from the context of a no
                                             longer existing actor");
                                  });
        let children = inner.children.lock().unwrap().clone();
        children
    }

    fn monitoring(&self) -> Vec<Arc<CanReceive>> {
        let inner = unwrap_inner!(self.inner_cell,
                                  {
                                      panic!("Tried to get the monitored actors from the context of
                                             a no longer existing actor");
                                  });
        let monitoring = inner.monitoring.lock().unwrap().clone();
        monitoring
    }
}

struct Failsafe {
    father: Arc<CanReceive>,
    child: Arc<CanReceive>,
    active: bool,
}

impl Failsafe {
    fn new(father: Arc<CanReceive>, child: Arc<CanReceive>) -> Failsafe {
        Failsafe {
            father: father,
            child: child,
            active: true,
        }
    }

    fn cancel(mut self) {
        self.active = false;
    }
}

impl Drop for Failsafe {
    fn drop(&mut self) {
        if self.active {
            self.father.receive_system_message(SystemMessage::Failure(self.child.clone()));
        }
    }
}

struct InnerActorCell<Args: Message, M: Message, A: Actor<M> + 'static> {
    actor: RwLock<A>,
    mailbox: Mutex<VecDeque<Envelope<M>>>,
    system_mailbox: Mutex<VecDeque<SystemMessage>>,
    props: Props<Args, M, A>,
    system: ActorSystem,
    current_sender: Mutex<Option<Arc<CanReceive>>>,
    busy: Mutex<()>,
    father: Arc<CanReceive>,
    children: Mutex<Vec<Arc<CanReceive>>>,
    monitoring: Mutex<Vec<Arc<CanReceive>>>,
    _monitored: Mutex<Vec<Arc<CanReceive>>>,
}

struct Envelope<M> {
    message: M,
    sender: Arc<CanReceive>,
}

impl<Args: Message, M: Message, A: Actor<M> + 'static> InnerActorCell<Args, M, A> {
    fn new(actor: A, props: Props<Args, M, A>, system: ActorSystem, father: Arc<CanReceive>) -> InnerActorCell<Args, M, A> {
        InnerActorCell {
            actor: RwLock::new(actor),
            mailbox: Mutex::new(VecDeque::new()),
            system_mailbox: Mutex::new(VecDeque::new()),
            props: props,
            system: system,
            current_sender: Mutex::new(None),
            busy: Mutex::new(()),
            father: father.clone(),
            children: Mutex::new(Vec::new()),
            monitoring: Mutex::new(Vec::new()),
            _monitored: Mutex::new(vec![father.clone()]),
        }
    }

    fn receive_envelope(&self, envelope: Envelope<M>) {
        self.mailbox.lock().unwrap().push_back(envelope);
    }

    fn receive_message(&self, message: M, sender: Arc<CanReceive>) {
        self.receive_envelope(Envelope{message: message, sender: sender});
    }

    fn receive_system_message(&self, system_message: SystemMessage) {
        self.system_mailbox.lock().unwrap().push_back(system_message);
    }

    fn handle_envelope(&self, context: ActorCell<Args, M, A>) {
        // Now we do not want users to be able to touch current_sender while the actor is busy.
        let _lock = self.busy.lock();
        let failsafe = Failsafe::new(self.father.clone(), Arc::new(context.actor_ref()));
        // System messages are handled first, so that we can restart an actor if he failed without
        // loosing the messages in the mailbox.
        // NOTE: This does not break the fact that messages sent by the same actor are treated in
        // the order they are sent (if all to the same target actor), as system messages must not
        // be sent by other actors by the user.
        if let Some(message) = self.system_mailbox.lock().unwrap().pop_front() {
            match message {
                SystemMessage::Restart => self.restart(),
                SystemMessage::Start => self.start(),
                SystemMessage::Failure(actor) => actor.receive_system_message(SystemMessage::Restart),
            }
            failsafe.cancel();
            return;
        }
        let envelope = match self.mailbox.lock().unwrap().pop_front() {
            Some(envelope) => envelope,
            None => {
                failsafe.cancel();
                return;
            }
        };
        {
            let mut current_sender = self.current_sender.lock().unwrap();
            *current_sender = Some(envelope.sender.clone());
        };
        {
            let actor = self.actor.read().unwrap();
            actor.receive(envelope.message, context);
        }
        failsafe.cancel();
    }

    fn start(&self) {
        self.actor.write().unwrap().pre_start();
    }

    fn restart(&self) {
        let mut actor = self.actor.write().unwrap();
        actor.pre_restart();
        *actor = self.props.create();
        actor.post_restart();
    }
}

impl<Args: Message, M: Message, A: Actor<M> + 'static> Drop for InnerActorCell<Args, M, A> {
    fn drop(&mut self) {
        println!("dropped an actor cell");
    }
}

<|endoftext|>


<commit_before>//! Panic support in the standard library.

#![stable(feature = "core_panic_info", since = "1.41.0")]

use crate::any::Any;
use crate::fmt;

/// A struct providing information about a panic.
///
/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
/// function.
///
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///     if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
///         println!("panic occurred: {:?}", s);
///     } else {
///         println!("panic occurred");
///     }
/// }));
///
/// panic!("Normal panic");
/// ```
#[lang = "panic_info"]
#[stable(feature = "panic_hooks", since = "1.10.0")]
#[derive(Debug)]
pub struct PanicInfo<'a> {
    payload: &'a (dyn Any + Send),
    message: Option<&'a fmt::Arguments<'a>>,
    location: &'a Location<'a>,
}

impl<'a> PanicInfo<'a> {
    #[unstable(
        feature = "panic_internals",
        reason = "internal details of the implementation of the `panic!` and related macros",
        issue = "none"
    )]
    #[doc(hidden)]
    #[inline]
    pub fn internal_constructor(
        message: Option<&'a fmt::Arguments<'a>>,
        location: &'a Location<'a>,
    ) -> Self {
        struct NoPayload;
        PanicInfo { location, message, payload: &NoPayload }
    }

    #[unstable(
        feature = "panic_internals",
        reason = "internal details of the implementation of the `panic!` and related macros",
        issue = "none"
    )]
    #[doc(hidden)]
    #[inline]
    pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
        self.payload = info;
    }

    /// Returns the payload associated with the panic.
    ///
    /// This will commonly, but not always, be a `&'static str` or [`String`].
    ///
    /// [`String`]: ../../std/string/struct.String.html
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
    ///         println!("panic occurred: {:?}", s);
    ///     } else {
    ///         println!("panic occurred");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn payload(&self) -> &(dyn Any + Send) {
        self.payload
    }

    /// If the `panic!` macro from the `core` crate (not from `std`)
    /// was used with a formatting string and some additional arguments,
    /// returns that message ready to be used for example with [`fmt::write`]
    #[unstable(feature = "panic_info_message", issue = "66745")]
    pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
        self.message
    }

    /// Returns information about the location from which the panic originated,
    /// if available.
    ///
    /// This method will currently always return [`Some`], but this may change
    /// in future versions.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred in file '{}' at line {}",
    ///             location.file(),
    ///             location.line(),
    ///         );
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn location(&self) -> Option<&Location<'_>> {
        // NOTE: If this is changed to sometimes return None,
        // deal with that case in std::panicking::default_hook and std::panicking::begin_panic_fmt.
        Some(&self.location)
    }
}

#[stable(feature = "panic_hook_display", since = "1.26.0")]
impl fmt::Display for PanicInfo<'_> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("panicked at ")?;
        if let Some(message) = self.message {
            write!(formatter, "'{}', ", message)?
        } else if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
            write!(formatter, "'{}', ", payload)?
        }
        // NOTE: we cannot use downcast_ref::<String>() here
        // since String is not available in libcore!
        // The payload is a String when `std::panic!` is called with multiple arguments,
        // but in that case the message is also available.

        self.location.fmt(formatter)
    }
}

/// A struct containing information about the location of a panic.
///
/// This structure is created by the [`PanicInfo::location`] method of [`PanicInfo`].
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///     if let Some(location) = panic_info.location() {
///         println!("panic occurred in file '{}' at line {}", location.file(), location.line());
///     } else {
///         println!("panic occurred but can't get location information...");
///     }
/// }));
///
/// panic!("Normal panic");
/// ```
///
/// # Comparisons
///
/// Comparisons for equality and ordering are made in file, line, then column priority.
/// Files are compared as strings, not `Path`, which could be unexpected.
/// See [`Location::file`]'s documentation for more discussion.
#[lang = "panic_location"]
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct Location<'a> {
    file: &'a str,
    line: u32,
    col: u32,
}

impl<'a> Location<'a> {
    /// Returns the source location of the caller of this function. If that function's caller is
    /// annotated then its call location will be returned, and so on up the stack to the first call
    /// within a non-tracked function body.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::panic::Location;
    ///
    /// /// Returns the [`Location`] at which it is called.
    /// #[track_caller]
    /// fn get_caller_location() -> &'static Location<'static> {
    ///     Location::caller()
    /// }
    ///
    /// /// Returns a [`Location`] from within this function's definition.
    /// fn get_just_one_location() -> &'static Location<'static> {
    ///     get_caller_location()
    /// }
    ///
    /// let fixed_location = get_just_one_location();
    /// assert_eq!(fixed_location.file(), file!());
    /// assert_eq!(fixed_location.line(), 14);
    /// assert_eq!(fixed_location.column(), 5);
    ///
    /// // running the same untracked function in a different location gives us the same result
    /// let second_fixed_location = get_just_one_location();
    /// assert_eq!(fixed_location.file(), second_fixed_location.file());
    /// assert_eq!(fixed_location.line(), second_fixed_location.line());
    /// assert_eq!(fixed_location.column(), second_fixed_location.column());
    ///
    /// let this_location = get_caller_location();
    /// assert_eq!(this_location.file(), file!());
    /// assert_eq!(this_location.line(), 28);
    /// assert_eq!(this_location.column(), 21);
    ///
    /// // running the tracked function in a different location produces a different value
    /// let another_location = get_caller_location();
    /// assert_eq!(this_location.file(), another_location.file());
    /// assert_ne!(this_location.line(), another_location.line());
    /// assert_ne!(this_location.column(), another_location.column());
    /// ```
    #[stable(feature = "track_caller", since = "1.46.0")]
    #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
    #[track_caller]
    pub const fn caller() -> &'static Location<'static> {
        crate::intrinsics::caller_location()
    }
}

impl<'a> Location<'a> {
    #![unstable(
        feature = "panic_internals",
        reason = "internal details of the implementation of the `panic!` and related macros",
        issue = "none"
    )]
    #[doc(hidden)]
    pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
        Location { file, line, col }
    }

    /// Returns the name of the source file from which the panic originated.
    ///
    /// # `&str`, not `&Path`
    ///
    /// The returned name refers to a source path on the compiling system, but it isn't valid to
    /// represent this directly as a `&Path`. The compiled code may run on a different system with
    /// a different `Path` implementation than the system providing the contents and this library
    /// does not currently have a different "host path" type.
    ///
    /// The most surprising behavior occurs when "the same" file is reachable via multiple paths in
    /// the module system (usually using the `#[path = "..."]` attribute or similar), which can
    /// cause what appears to be identical code to return differing values from this function.
    ///
    /// # Cross-compilation
    ///
    /// This value is not suitable for passing to `Path::new` or similar constructors when the host
    /// platform and target platform differ.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred in file '{}'", location.file());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn file(&self) -> &str {
        self.file
    }

    /// Returns the line number from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred at line {}", location.line());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn line(&self) -> u32 {
        self.line
    }

    /// Returns the column from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred at column {}", location.column());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_col", since = "1.25.0")]
    pub fn column(&self) -> u32 {
        self.col
    }
}

#[stable(feature = "panic_hook_display", since = "1.26.0")]
impl fmt::Display for Location<'_> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
    }
}

/// An internal trait used by libstd to pass data from libstd to `panic_unwind`
/// and other panic runtimes. Not intended to be stabilized any time soon, do
/// not use.
#[unstable(feature = "std_internals", issue = "none")]
#[doc(hidden)]
pub unsafe trait BoxMeUp {
    /// Take full ownership of the contents.
    /// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in libcore.
    ///
    /// After this method got called, only some dummy default value is left in `self`.
    /// Calling this method twice, or calling `get` after calling this method, is an error.
    ///
    /// The argument is borrowed because the panic runtime (`__rust_start_panic`) only
    /// gets a borrowed `dyn BoxMeUp`.
    fn take_box(&mut self) -> *mut (dyn Any + Send);

    /// Just borrow the contents.
    fn get(&mut self) -> &(dyn Any + Send);
}
<commit_msg>Enhance wording<commit_after>//! Panic support in the standard library.

#![stable(feature = "core_panic_info", since = "1.41.0")]

use crate::any::Any;
use crate::fmt;

/// A struct providing information about a panic.
///
/// `PanicInfo` structure is passed to a panic hook set by the [`set_hook`]
/// function.
///
/// [`set_hook`]: ../../std/panic/fn.set_hook.html
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///     if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
///         println!("panic occurred: {:?}", s);
///     } else {
///         println!("panic occurred");
///     }
/// }));
///
/// panic!("Normal panic");
/// ```
#[lang = "panic_info"]
#[stable(feature = "panic_hooks", since = "1.10.0")]
#[derive(Debug)]
pub struct PanicInfo<'a> {
    payload: &'a (dyn Any + Send),
    message: Option<&'a fmt::Arguments<'a>>,
    location: &'a Location<'a>,
}

impl<'a> PanicInfo<'a> {
    #[unstable(
        feature = "panic_internals",
        reason = "internal details of the implementation of the `panic!` and related macros",
        issue = "none"
    )]
    #[doc(hidden)]
    #[inline]
    pub fn internal_constructor(
        message: Option<&'a fmt::Arguments<'a>>,
        location: &'a Location<'a>,
    ) -> Self {
        struct NoPayload;
        PanicInfo { location, message, payload: &NoPayload }
    }

    #[unstable(
        feature = "panic_internals",
        reason = "internal details of the implementation of the `panic!` and related macros",
        issue = "none"
    )]
    #[doc(hidden)]
    #[inline]
    pub fn set_payload(&mut self, info: &'a (dyn Any + Send)) {
        self.payload = info;
    }

    /// Returns the payload associated with the panic.
    ///
    /// This will commonly, but not always, be a `&'static str` or [`String`].
    ///
    /// [`String`]: ../../std/string/struct.String.html
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(s) = panic_info.payload().downcast_ref::<&str>() {
    ///         println!("panic occurred: {:?}", s);
    ///     } else {
    ///         println!("panic occurred");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn payload(&self) -> &(dyn Any + Send) {
        self.payload
    }

    /// If the `panic!` macro from the `core` crate (not from `std`)
    /// was used with a formatting string and some additional arguments,
    /// returns that message ready to be used for example with [`fmt::write`]
    #[unstable(feature = "panic_info_message", issue = "66745")]
    pub fn message(&self) -> Option<&fmt::Arguments<'_>> {
        self.message
    }

    /// Returns information about the location from which the panic originated,
    /// if available.
    ///
    /// This method will currently always return [`Some`], but this may change
    /// in future versions.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred in file '{}' at line {}",
    ///             location.file(),
    ///             location.line(),
    ///         );
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn location(&self) -> Option<&Location<'_>> {
        // NOTE: If this is changed to sometimes return None,
        // deal with that case in std::panicking::default_hook and std::panicking::begin_panic_fmt.
        Some(&self.location)
    }
}

#[stable(feature = "panic_hook_display", since = "1.26.0")]
impl fmt::Display for PanicInfo<'_> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        formatter.write_str("panicked at ")?;
        if let Some(message) = self.message {
            write!(formatter, "'{}', ", message)?
        } else if let Some(payload) = self.payload.downcast_ref::<&'static str>() {
            write!(formatter, "'{}', ", payload)?
        }
        // NOTE: we cannot use downcast_ref::<String>() here
        // since String is not available in libcore!
        // The payload is a String when `std::panic!` is called with multiple arguments,
        // but in that case the message is also available.

        self.location.fmt(formatter)
    }
}

/// A struct containing information about the location of a panic.
///
/// This structure is created by [`PanicInfo::location()`].
///
/// # Examples
///
/// ```should_panic
/// use std::panic;
///
/// panic::set_hook(Box::new(|panic_info| {
///     if let Some(location) = panic_info.location() {
///         println!("panic occurred in file '{}' at line {}", location.file(), location.line());
///     } else {
///         println!("panic occurred but can't get location information...");
///     }
/// }));
///
/// panic!("Normal panic");
/// ```
///
/// # Comparisons
///
/// Comparisons for equality and ordering are made in file, line, then column priority.
/// Files are compared as strings, not `Path`, which could be unexpected.
/// See [`Location::file`]'s documentation for more discussion.
#[lang = "panic_location"]
#[derive(Copy, Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[stable(feature = "panic_hooks", since = "1.10.0")]
pub struct Location<'a> {
    file: &'a str,
    line: u32,
    col: u32,
}

impl<'a> Location<'a> {
    /// Returns the source location of the caller of this function. If that function's caller is
    /// annotated then its call location will be returned, and so on up the stack to the first call
    /// within a non-tracked function body.
    ///
    /// # Examples
    ///
    /// ```
    /// use core::panic::Location;
    ///
    /// /// Returns the [`Location`] at which it is called.
    /// #[track_caller]
    /// fn get_caller_location() -> &'static Location<'static> {
    ///     Location::caller()
    /// }
    ///
    /// /// Returns a [`Location`] from within this function's definition.
    /// fn get_just_one_location() -> &'static Location<'static> {
    ///     get_caller_location()
    /// }
    ///
    /// let fixed_location = get_just_one_location();
    /// assert_eq!(fixed_location.file(), file!());
    /// assert_eq!(fixed_location.line(), 14);
    /// assert_eq!(fixed_location.column(), 5);
    ///
    /// // running the same untracked function in a different location gives us the same result
    /// let second_fixed_location = get_just_one_location();
    /// assert_eq!(fixed_location.file(), second_fixed_location.file());
    /// assert_eq!(fixed_location.line(), second_fixed_location.line());
    /// assert_eq!(fixed_location.column(), second_fixed_location.column());
    ///
    /// let this_location = get_caller_location();
    /// assert_eq!(this_location.file(), file!());
    /// assert_eq!(this_location.line(), 28);
    /// assert_eq!(this_location.column(), 21);
    ///
    /// // running the tracked function in a different location produces a different value
    /// let another_location = get_caller_location();
    /// assert_eq!(this_location.file(), another_location.file());
    /// assert_ne!(this_location.line(), another_location.line());
    /// assert_ne!(this_location.column(), another_location.column());
    /// ```
    #[stable(feature = "track_caller", since = "1.46.0")]
    #[rustc_const_unstable(feature = "const_caller_location", issue = "47809")]
    #[track_caller]
    pub const fn caller() -> &'static Location<'static> {
        crate::intrinsics::caller_location()
    }
}

impl<'a> Location<'a> {
    #![unstable(
        feature = "panic_internals",
        reason = "internal details of the implementation of the `panic!` and related macros",
        issue = "none"
    )]
    #[doc(hidden)]
    pub const fn internal_constructor(file: &'a str, line: u32, col: u32) -> Self {
        Location { file, line, col }
    }

    /// Returns the name of the source file from which the panic originated.
    ///
    /// # `&str`, not `&Path`
    ///
    /// The returned name refers to a source path on the compiling system, but it isn't valid to
    /// represent this directly as a `&Path`. The compiled code may run on a different system with
    /// a different `Path` implementation than the system providing the contents and this library
    /// does not currently have a different "host path" type.
    ///
    /// The most surprising behavior occurs when "the same" file is reachable via multiple paths in
    /// the module system (usually using the `#[path = "..."]` attribute or similar), which can
    /// cause what appears to be identical code to return differing values from this function.
    ///
    /// # Cross-compilation
    ///
    /// This value is not suitable for passing to `Path::new` or similar constructors when the host
    /// platform and target platform differ.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred in file '{}'", location.file());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn file(&self) -> &str {
        self.file
    }

    /// Returns the line number from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred at line {}", location.line());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_hooks", since = "1.10.0")]
    pub fn line(&self) -> u32 {
        self.line
    }

    /// Returns the column from which the panic originated.
    ///
    /// # Examples
    ///
    /// ```should_panic
    /// use std::panic;
    ///
    /// panic::set_hook(Box::new(|panic_info| {
    ///     if let Some(location) = panic_info.location() {
    ///         println!("panic occurred at column {}", location.column());
    ///     } else {
    ///         println!("panic occurred but can't get location information...");
    ///     }
    /// }));
    ///
    /// panic!("Normal panic");
    /// ```
    #[stable(feature = "panic_col", since = "1.25.0")]
    pub fn column(&self) -> u32 {
        self.col
    }
}

#[stable(feature = "panic_hook_display", since = "1.26.0")]
impl fmt::Display for Location<'_> {
    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(formatter, "{}:{}:{}", self.file, self.line, self.col)
    }
}

/// An internal trait used by libstd to pass data from libstd to `panic_unwind`
/// and other panic runtimes. Not intended to be stabilized any time soon, do
/// not use.
#[unstable(feature = "std_internals", issue = "none")]
#[doc(hidden)]
pub unsafe trait BoxMeUp {
    /// Take full ownership of the contents.
    /// The return type is actually `Box<dyn Any + Send>`, but we cannot use `Box` in libcore.
    ///
    /// After this method got called, only some dummy default value is left in `self`.
    /// Calling this method twice, or calling `get` after calling this method, is an error.
    ///
    /// The argument is borrowed because the panic runtime (`__rust_start_panic`) only
    /// gets a borrowed `dyn BoxMeUp`.
    fn take_box(&mut self) -> *mut (dyn Any + Send);

    /// Just borrow the contents.
    fn get(&mut self) -> &(dyn Any + Send);
}
<|endoftext|>


<commit_before>extern crate c_ares_sys;

use std::fmt;
use std::mem;
use std::net::Ipv6Addr;
use std::os::raw::{
    c_int,
    c_uchar,
    c_void,
};
use std::ptr;
use std::slice;

use error::AresError;
use types::MAX_ADDRTTLS;
use utils::{
    ares_error,
    ipv6_address_from_bytes,
};

/// The result of a successful AAAA lookup.
pub struct AAAAResults {
    naddr6ttls: usize,
    addr6ttls: [c_ares_sys::Struct_ares_addr6ttl; MAX_ADDRTTLS],
}

/// The contents of a single AAAA record.
#[derive(Clone, Copy)]
pub struct AAAAResult<'a> {
    addr6ttl: &'a c_ares_sys::Struct_ares_addr6ttl,
}

impl AAAAResults {
    /// Obtain an `AAAAResults` from the response to an AAAA lookup.
    pub fn parse_from(data: &[u8]) -> Result<AAAAResults, AresError> {
        let mut results: AAAAResults = AAAAResults {
            naddr6ttls: MAX_ADDRTTLS,
            addr6ttls: unsafe { mem::uninitialized() },
        };
        let parse_status = unsafe {
            c_ares_sys::ares_parse_aaaa_reply(
                data.as_ptr(),
                data.len() as c_int,
                ptr::null_mut(),
                results.addr6ttls.as_mut_ptr(),
                &mut results.naddr6ttls as *mut _ as *mut c_int)
        };
        if parse_status != c_ares_sys::ARES_SUCCESS {
            Err(ares_error(parse_status))
        } else {
            Ok(results)
        }
    }

    /// Returns an iterator over the `AAAAResult` values in this `AAAAResults`.
    pub fn iter(&self) -> AAAAResultsIter {
        AAAAResultsIter {
            addr6ttls: self.addr6ttls[0 .. self.naddr6ttls].iter()
        }
    }
}

impl fmt::Display for AAAAResults {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "["));
        let mut first = true;
        for a_result in self {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{{{}}}", prefix, a_result));
        }
        try!(write!(fmt, "]"));
        Ok(())
    }
}

/// Iterator of `AAAAResult`s.
#[derive(Clone)]
pub struct AAAAResultsIter<'a> {
    addr6ttls: slice::Iter<'a, c_ares_sys::Struct_ares_addr6ttl>,
}

impl<'a> Iterator for AAAAResultsIter<'a> {
    type Item = AAAAResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.addr6ttls.next().map(|addr6ttl| AAAAResult { addr6ttl: addr6ttl })
    }
}

impl<'a> IntoIterator for &'a AAAAResults {
    type Item = AAAAResult<'a>;
    type IntoIter = AAAAResultsIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> AAAAResult<'a> {
    /// Returns the IPv6 address in this 'AAAAResult'.
    pub fn ipv6(&self) -> Ipv6Addr {
        let bytes = &self.addr6ttl.ip6addr._S6_un._bindgen_data_;
        ipv6_address_from_bytes(bytes)
    }

    /// Returns the time-to-live in this 'AAAAResult'.
    pub fn ttl(&self) -> i32 {
        self.addr6ttl.ttl as i32
    }
}

impl<'a> fmt::Display for AAAAResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "IPv6: {}, ", self.ipv6()));
        try!(write!(fmt, "TTL: {}, ", self.ttl()));
        Ok(())
    }
}

pub unsafe extern "C" fn query_aaaa_callback<F>(
    arg: *mut c_void,
    status: c_int,
    _timeouts: c_int,
    abuf: *mut c_uchar,
    alen: c_int)
    where F: FnOnce(Result<AAAAResults, AresError>) + 'static {
    let result = if status != c_ares_sys::ARES_SUCCESS {
        Err(ares_error(status))
    } else {
        let data = slice::from_raw_parts(abuf, alen as usize);
        AAAAResults::parse_from(data)
    };
    let handler = Box::from_raw(arg as *mut F);
    handler(result);
}
<commit_msg>s/a/aaaa<commit_after>extern crate c_ares_sys;

use std::fmt;
use std::mem;
use std::net::Ipv6Addr;
use std::os::raw::{
    c_int,
    c_uchar,
    c_void,
};
use std::ptr;
use std::slice;

use error::AresError;
use types::MAX_ADDRTTLS;
use utils::{
    ares_error,
    ipv6_address_from_bytes,
};

/// The result of a successful AAAA lookup.
pub struct AAAAResults {
    naddr6ttls: usize,
    addr6ttls: [c_ares_sys::Struct_ares_addr6ttl; MAX_ADDRTTLS],
}

/// The contents of a single AAAA record.
#[derive(Clone, Copy)]
pub struct AAAAResult<'a> {
    addr6ttl: &'a c_ares_sys::Struct_ares_addr6ttl,
}

impl AAAAResults {
    /// Obtain an `AAAAResults` from the response to an AAAA lookup.
    pub fn parse_from(data: &[u8]) -> Result<AAAAResults, AresError> {
        let mut results: AAAAResults = AAAAResults {
            naddr6ttls: MAX_ADDRTTLS,
            addr6ttls: unsafe { mem::uninitialized() },
        };
        let parse_status = unsafe {
            c_ares_sys::ares_parse_aaaa_reply(
                data.as_ptr(),
                data.len() as c_int,
                ptr::null_mut(),
                results.addr6ttls.as_mut_ptr(),
                &mut results.naddr6ttls as *mut _ as *mut c_int)
        };
        if parse_status != c_ares_sys::ARES_SUCCESS {
            Err(ares_error(parse_status))
        } else {
            Ok(results)
        }
    }

    /// Returns an iterator over the `AAAAResult` values in this `AAAAResults`.
    pub fn iter(&self) -> AAAAResultsIter {
        AAAAResultsIter {
            addr6ttls: self.addr6ttls[0 .. self.naddr6ttls].iter()
        }
    }
}

impl fmt::Display for AAAAResults {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "["));
        let mut first = true;
        for aaaa_result in self {
            let prefix = if first { "" } else { ", " };
            first = false;
            try!(write!(fmt, "{}{{{}}}", prefix, aaaa_result));
        }
        try!(write!(fmt, "]"));
        Ok(())
    }
}

/// Iterator of `AAAAResult`s.
#[derive(Clone)]
pub struct AAAAResultsIter<'a> {
    addr6ttls: slice::Iter<'a, c_ares_sys::Struct_ares_addr6ttl>,
}

impl<'a> Iterator for AAAAResultsIter<'a> {
    type Item = AAAAResult<'a>;
    fn next(&mut self) -> Option<Self::Item> {
        self.addr6ttls.next().map(|addr6ttl| AAAAResult { addr6ttl: addr6ttl })
    }
}

impl<'a> IntoIterator for &'a AAAAResults {
    type Item = AAAAResult<'a>;
    type IntoIter = AAAAResultsIter<'a>;

    fn into_iter(self) -> Self::IntoIter {
        self.iter()
    }
}

impl<'a> AAAAResult<'a> {
    /// Returns the IPv6 address in this 'AAAAResult'.
    pub fn ipv6(&self) -> Ipv6Addr {
        let bytes = &self.addr6ttl.ip6addr._S6_un._bindgen_data_;
        ipv6_address_from_bytes(bytes)
    }

    /// Returns the time-to-live in this 'AAAAResult'.
    pub fn ttl(&self) -> i32 {
        self.addr6ttl.ttl as i32
    }
}

impl<'a> fmt::Display for AAAAResult<'a> {
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(fmt, "IPv6: {}, ", self.ipv6()));
        try!(write!(fmt, "TTL: {}, ", self.ttl()));
        Ok(())
    }
}

pub unsafe extern "C" fn query_aaaa_callback<F>(
    arg: *mut c_void,
    status: c_int,
    _timeouts: c_int,
    abuf: *mut c_uchar,
    alen: c_int)
    where F: FnOnce(Result<AAAAResults, AresError>) + 'static {
    let result = if status != c_ares_sys::ARES_SUCCESS {
        Err(ares_error(status))
    } else {
        let data = slice::from_raw_parts(abuf, alen as usize);
        AAAAResults::parse_from(data)
    };
    let handler = Box::from_raw(arg as *mut F);
    handler(result);
}
<|endoftext|>


<commit_before>//! Node attributes.

use parser::binary::RootParser;
use parser::binary::error::{Result, Error, Warning};
use parser::binary::event::NodeHeader;
use parser::binary::reader::{ParserSource, ReadLittleEndian};
use parser::binary::utils::{AttributeValues, AttributeValue};
use self::array::read_array_attribute;
pub use self::array::{ArrayAttribute, ArrayAttributeReader};
use self::special::read_special_attribute;
pub use self::special::{SpecialAttribute, SpecialAttributeType};

mod array;
mod special;

/// Node attribute.
#[derive(Debug)]
pub struct Attributes<'a, R: 'a> {
    /// Number of all attributes.
    num_attributes: u64,
    /// Number of rest attributes.
    rest_attributes: u64,
    /// End offset of the previous attribute.
    prev_attr_end: Option<u64>,
    /// Parser.
    parser: &'a mut RootParser<R>,
}

impl<'a, R: 'a + ParserSource> Attributes<'a, R> {
    /// Returns number of all attributes.
    pub fn num_attributes(&self) -> u64 {
        self.num_attributes
    }

    /// Returns number of rest attributes.
    pub fn rest_attributes(&self) -> u64 {
        self.rest_attributes
    }

    /// Returns the next attribute if available.
    pub fn next_attribute(&mut self) -> Result<Option<Attribute<R>>> {
        if self.rest_attributes == 0 {
            return Ok(None);
        }

        // Skip unread part of the previous attribute if available.
        if let Some(prev_attr_end) = self.prev_attr_end {
            self.parser.source.skip_to(prev_attr_end)?;
            self.prev_attr_end = None;
        }

        self.rest_attributes -= 1;
        let type_code = self.parser.source.read_u8()?;
        let position = self.parser.source.position();
        match type_code {
            // Primitive type attributes.
            b'C' => {
                let raw = self.parser.source.read_u8()?;
                let val = (raw & 0x01) == 1;
                if raw != b'T' && raw != b'Y' {
                    self.parser.warn(Warning::InvalidBooleanAttributeValue {
                        got: raw,
                        assumed: val,
                        position: position,
                    });
                }
                Ok(Some(PrimitiveAttribute::Bool(val).into()))
            },
            b'Y' => Ok(Some(PrimitiveAttribute::I16(self.parser.source.read_i16()?).into())),
            b'I' => Ok(Some(PrimitiveAttribute::I32(self.parser.source.read_i32()?).into())),
            b'L' => Ok(Some(PrimitiveAttribute::I64(self.parser.source.read_i64()?).into())),
            b'F' => Ok(Some(PrimitiveAttribute::F32(self.parser.source.read_f32()?).into())),
            b'D' => Ok(Some(PrimitiveAttribute::F64(self.parser.source.read_f64()?).into())),
            // Special type attributes.
            b'R' | b'S' => {
                let (attr, end_offset) = read_special_attribute(&mut self.parser.source, type_code)?;
                self.prev_attr_end = Some(end_offset);
                Ok(Some(attr.into()))
            },
            // Array type attributes.
            b'b' | b'i' | b'l' | b'f' | b'd' => {
                let (attr, end_offset) = read_array_attribute(&mut self.parser.source, &mut self.parser.warnings, type_code)?;
                self.prev_attr_end = Some(end_offset);
                Ok(Some(attr.into()))
            },
            // Unknown type attributes.
            _ => {
                Err(Error::InvalidNodeAttributeTypeCode {
                    got: type_code,
                    position: position,
                })
            },
        }
    }

    /// Converts some attributes into values of specific types.
    pub fn convert_into<A: AttributeValues>(&mut self) -> Result<Option<A>> {
        A::from_attributes(self)
    }
}

impl<'a, R: 'a + ParserSource> From<PrimitiveAttribute> for Attribute<'a, R> {
    fn from(a: PrimitiveAttribute) -> Self {
        Attribute::Primitive(a)
    }
}

impl<'a, R: 'a + ParserSource> From<SpecialAttribute<'a, R>> for Attribute<'a, R> {
    fn from(a: SpecialAttribute<'a, R>) -> Self {
        Attribute::Special(a)
    }
}

impl<'a, R: 'a + ParserSource> From<ArrayAttribute<'a, R>> for Attribute<'a, R> {
    fn from(a: ArrayAttribute<'a, R>) -> Self {
        Attribute::Array(a)
    }
}

/// Creates a new `Attributes`.
pub fn new_attributes<'a, R: 'a>(
    parser: &'a mut RootParser<R>,
    header: &NodeHeader
) -> Attributes<'a, R> {
    Attributes {
        num_attributes: header.num_attributes,
        rest_attributes: header.num_attributes,
        prev_attr_end: None,
        parser: parser,
    }
}

/// Node attribute.
#[derive(Debug)]
pub enum Attribute<'a, R: 'a> {
    /// Primitive type value.
    Primitive(PrimitiveAttribute),
    /// Array type value.
    Array(ArrayAttribute<'a, R>),
    /// Special type value.
    Special(SpecialAttribute<'a, R>),
}

impl<'a, R: 'a + ParserSource> Attribute<'a, R> {
    /// Converts the attribute into a value of a specific type.
    pub fn convert_into<A: AttributeValue>(self) -> Result<Option<A>> {
        A::from_attribute(self)
    }
}

/// Attribute type of primitive value.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PrimitiveAttribute {
    /// Single `bool`.
    Bool(bool),
    /// Single `i16`.
    I16(i16),
    /// Single `i32`.
    I32(i32),
    /// Single `i64`.
    I64(i64),
    /// Single `f32`.
    F32(f32),
    /// Single `f64`.
    F64(f64),
}

impl PrimitiveAttribute {
    /// Converts floating-point number into `f32`.
    pub fn as_f32(&self) -> Option<f32> {
        match *self {
            PrimitiveAttribute::F32(v) => Some(v),
            PrimitiveAttribute::F64(v) => Some(v as f32),
            _ => None,
        }
    }

    /// Converts floating-point number into `f32`.
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            PrimitiveAttribute::F32(v) => Some(v as f64),
            PrimitiveAttribute::F64(v) => Some(v),
            _ => None,
        }
    }
}
<commit_msg>Prevent `Attributes` borrowing whole a parser<commit_after>//! Node attributes.

use parser::binary::{RootParser, Warnings};
use parser::binary::error::{Result, Error, Warning};
use parser::binary::event::NodeHeader;
use parser::binary::reader::{ParserSource, ReadLittleEndian};
use parser::binary::utils::{AttributeValues, AttributeValue};
use self::array::read_array_attribute;
pub use self::array::{ArrayAttribute, ArrayAttributeReader};
use self::special::read_special_attribute;
pub use self::special::{SpecialAttribute, SpecialAttributeType};

mod array;
mod special;

/// Node attribute.
#[derive(Debug)]
pub struct Attributes<'a, R: 'a> {
    /// Number of all attributes.
    num_attributes: u64,
    /// Number of rest attributes.
    rest_attributes: u64,
    /// End offset of the previous attribute.
    prev_attr_end: Option<u64>,
    /// Parser source.
    source: &'a mut R,
    /// Parser warnings.
    warnings: &'a mut Warnings,
}

impl<'a, R: 'a + ParserSource> Attributes<'a, R> {
    /// Returns number of all attributes.
    pub fn num_attributes(&self) -> u64 {
        self.num_attributes
    }

    /// Returns number of rest attributes.
    pub fn rest_attributes(&self) -> u64 {
        self.rest_attributes
    }

    /// Returns the next attribute if available.
    pub fn next_attribute(&mut self) -> Result<Option<Attribute<R>>> {
        if self.rest_attributes == 0 {
            return Ok(None);
        }

        // Skip unread part of the previous attribute if available.
        if let Some(prev_attr_end) = self.prev_attr_end {
            self.source.skip_to(prev_attr_end)?;
            self.prev_attr_end = None;
        }

        self.rest_attributes -= 1;
        let type_code = self.source.read_u8()?;
        let position = self.source.position();
        match type_code {
            // Primitive type attributes.
            b'C' => {
                let raw = self.source.read_u8()?;
                let val = (raw & 0x01) == 1;
                if raw != b'T' && raw != b'Y' {
                    self.warnings.warn(Warning::InvalidBooleanAttributeValue {
                        got: raw,
                        assumed: val,
                        position: position,
                    });
                }
                Ok(Some(PrimitiveAttribute::Bool(val).into()))
            },
            b'Y' => Ok(Some(PrimitiveAttribute::I16(self.source.read_i16()?).into())),
            b'I' => Ok(Some(PrimitiveAttribute::I32(self.source.read_i32()?).into())),
            b'L' => Ok(Some(PrimitiveAttribute::I64(self.source.read_i64()?).into())),
            b'F' => Ok(Some(PrimitiveAttribute::F32(self.source.read_f32()?).into())),
            b'D' => Ok(Some(PrimitiveAttribute::F64(self.source.read_f64()?).into())),
            // Special type attributes.
            b'R' | b'S' => {
                let (attr, end_offset) = read_special_attribute(self.source, type_code)?;
                self.prev_attr_end = Some(end_offset);
                Ok(Some(attr.into()))
            },
            // Array type attributes.
            b'b' | b'i' | b'l' | b'f' | b'd' => {
                let (attr, end_offset) = read_array_attribute(self.source, self.warnings, type_code)?;
                self.prev_attr_end = Some(end_offset);
                Ok(Some(attr.into()))
            },
            // Unknown type attributes.
            _ => {
                Err(Error::InvalidNodeAttributeTypeCode {
                    got: type_code,
                    position: position,
                })
            },
        }
    }

    /// Converts some attributes into values of specific types.
    pub fn convert_into<A: AttributeValues>(&mut self) -> Result<Option<A>> {
        A::from_attributes(self)
    }
}

impl<'a, R: 'a + ParserSource> From<PrimitiveAttribute> for Attribute<'a, R> {
    fn from(a: PrimitiveAttribute) -> Self {
        Attribute::Primitive(a)
    }
}

impl<'a, R: 'a + ParserSource> From<SpecialAttribute<'a, R>> for Attribute<'a, R> {
    fn from(a: SpecialAttribute<'a, R>) -> Self {
        Attribute::Special(a)
    }
}

impl<'a, R: 'a + ParserSource> From<ArrayAttribute<'a, R>> for Attribute<'a, R> {
    fn from(a: ArrayAttribute<'a, R>) -> Self {
        Attribute::Array(a)
    }
}

/// Creates a new `Attributes`.
pub fn new_attributes<'a, R: 'a>(
    parser: &'a mut RootParser<R>,
    header: &NodeHeader
) -> Attributes<'a, R> {
    let RootParser {
        ref mut source,
        ref mut warnings,
        ..
    } = *parser;
    Attributes {
        num_attributes: header.num_attributes,
        rest_attributes: header.num_attributes,
        prev_attr_end: None,
        source: source,
        warnings: warnings,
    }
}

/// Node attribute.
#[derive(Debug)]
pub enum Attribute<'a, R: 'a> {
    /// Primitive type value.
    Primitive(PrimitiveAttribute),
    /// Array type value.
    Array(ArrayAttribute<'a, R>),
    /// Special type value.
    Special(SpecialAttribute<'a, R>),
}

impl<'a, R: 'a + ParserSource> Attribute<'a, R> {
    /// Converts the attribute into a value of a specific type.
    pub fn convert_into<A: AttributeValue>(self) -> Result<Option<A>> {
        A::from_attribute(self)
    }
}

/// Attribute type of primitive value.
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum PrimitiveAttribute {
    /// Single `bool`.
    Bool(bool),
    /// Single `i16`.
    I16(i16),
    /// Single `i32`.
    I32(i32),
    /// Single `i64`.
    I64(i64),
    /// Single `f32`.
    F32(f32),
    /// Single `f64`.
    F64(f64),
}

impl PrimitiveAttribute {
    /// Converts floating-point number into `f32`.
    pub fn as_f32(&self) -> Option<f32> {
        match *self {
            PrimitiveAttribute::F32(v) => Some(v),
            PrimitiveAttribute::F64(v) => Some(v as f32),
            _ => None,
        }
    }

    /// Converts floating-point number into `f32`.
    pub fn as_f64(&self) -> Option<f64> {
        match *self {
            PrimitiveAttribute::F32(v) => Some(v as f64),
            PrimitiveAttribute::F64(v) => Some(v),
            _ => None,
        }
    }
}
<|endoftext|>


<commit_before>extern
{
	static end: u32;
}

static mut placement_address: u32 = 0;

pub fn setup()
{
	unsafe
	{
		placement_address = end;
	}
}

pub fn kmalloc(size: u32, align: bool) -> u32
{
	let mut pa = unsafe { placement_address };
	if align && (pa & 0xFFFFF000) != 0
	{
		pa &= 0xFFFFF000;
		pa += 0x1000;
	}
	unsafe
	{
		placement_address += size;
	}
	return pa;
}
<commit_msg>Removed some unused code<commit_after>extern
{
	static end: u32;
}

static mut placement_address: u32 = 0;

pub fn setup()
{
	unsafe
	{
		placement_address = end;
	}
}
<|endoftext|>


<commit_before>
use std::collections::HashMap;
use std::io::{self, Read};
use std::ops;

use value::{Value};
use eval::{FuncError, FuncResult};

macro_rules! math {
    ($name:ident, $op:path) => {
        pub fn $name(mut items: Vec<Value>) -> FuncResult {
            let mut total = match items.remove(0) {
                Value::Number(n) => n,
                _ => return Err(FuncError::InvalidArguments),
            };

            for item in items {
                match item {
                    Value::Number(next) => {
                        total = $op(total, next);
                    },
                    _ => return Err(FuncError::InvalidArguments),
                }
            }

            Ok(Value::Number(total))
        }
    }
}

pub fn print(vals: Vec<Value>) -> FuncResult {
    for val in vals {
        print!("{:?} ", val);
    }

    println!("");

    Ok(Value::Void)
}

pub fn read(vals: Vec<Value>) -> FuncResult {
    if vals.len() != 0 {
        return Err(FuncError::InvalidArguments);
    }

    let mut stdin = io::stdin();

    let mut input = String::new();
    match stdin.read_line(&mut input) {

        Ok(_) => {
            input.pop();
            Ok(Value::Str(input))
        }
        Err(err) => Err(FuncError::IoError(err)),
    }
}

pub fn str_fn(vals: Vec<Value>) -> FuncResult {
    let mut result = String::new();

    for val in vals {
        let string = match val {
            Value::Str(str) => str,
            other => format!("{:?}", other),
        };

        result.push_str(&string);
    }

    Ok(Value::Str(result))
}

pub fn eq(vals: Vec<Value>) -> FuncResult {
    for i in (0 .. vals.len() - 1) {
        if vals[i] != vals[i + 1] {
            return Ok(Value::Bool(false));
        }
    }

    Ok(Value::Bool(true))
}

pub fn and(vals: Vec<Value>) -> FuncResult {
    for val in vals {
        match val {
            Value::Bool(val) => {
                if !val {
                    return Ok(Value::Bool(false));
                }
            },
            _ => return Err(FuncError::InvalidArguments),
        }
    }

    Ok(Value::Bool(true))
}

pub fn or(vals: Vec<Value>) -> FuncResult {
    for val in vals {
        match val {
            Value::Bool(val) => {
                if val {
                    return Ok(Value::Bool(true));
                }
            },
            _ => return Err(FuncError::InvalidArguments),
        }
    }

    Ok(Value::Bool(false))
}

math!(add, ops::Add::add);
math!(sub, ops::Sub::sub);
math!(mul, ops::Mul::mul);
math!(div, ops::Div::div);
<commit_msg>String is no longer popped if EOF'd<commit_after>
use std::collections::HashMap;
use std::io::{self, Read};
use std::ops;

use value::{Value};
use eval::{FuncError, FuncResult};

macro_rules! math {
    ($name:ident, $op:path) => {
        pub fn $name(mut items: Vec<Value>) -> FuncResult {
            let mut total = match items.remove(0) {
                Value::Number(n) => n,
                _ => return Err(FuncError::InvalidArguments),
            };

            for item in items {
                match item {
                    Value::Number(next) => {
                        total = $op(total, next);
                    },
                    _ => return Err(FuncError::InvalidArguments),
                }
            }

            Ok(Value::Number(total))
        }
    }
}

pub fn print(vals: Vec<Value>) -> FuncResult {
    for val in vals {
        print!("{:?} ", val);
    }

    println!("");

    Ok(Value::Void)
}

pub fn read(vals: Vec<Value>) -> FuncResult {
    if vals.len() != 0 {
        return Err(FuncError::InvalidArguments);
    }

    let mut stdin = io::stdin();

    let mut input = String::new();
    match stdin.read_line(&mut input) {
        Ok(_) => {
            match input.pop() {
                None | Some('\n') => (),
                Some(ch) => {
                    input.push(ch);
                },
            }

            Ok(Value::Str(input))
        }
        Err(err) => Err(FuncError::IoError(err)),
    }
}

pub fn str_fn(vals: Vec<Value>) -> FuncResult {
    let mut result = String::new();

    for val in vals {
        let string = match val {
            Value::Str(str) => str,
            other => format!("{:?}", other),
        };

        result.push_str(&string);
    }

    Ok(Value::Str(result))
}

pub fn eq(vals: Vec<Value>) -> FuncResult {
    for i in (0 .. vals.len() - 1) {
        if vals[i] != vals[i + 1] {
            return Ok(Value::Bool(false));
        }
    }

    Ok(Value::Bool(true))
}

pub fn and(vals: Vec<Value>) -> FuncResult {
    for val in vals {
        match val {
            Value::Bool(val) => {
                if !val {
                    return Ok(Value::Bool(false));
                }
            },
            _ => return Err(FuncError::InvalidArguments),
        }
    }

    Ok(Value::Bool(true))
}

pub fn or(vals: Vec<Value>) -> FuncResult {
    for val in vals {
        match val {
            Value::Bool(val) => {
                if val {
                    return Ok(Value::Bool(true));
                }
            },
            _ => return Err(FuncError::InvalidArguments),
        }
    }

    Ok(Value::Bool(false))
}

math!(add, ops::Add::add);
math!(sub, ops::Sub::sub);
math!(mul, ops::Mul::mul);
math!(div, ops::Div::div);
<|endoftext|>


<commit_before>use std::io;

use crate::backend::Backend;
use crate::buffer::Cell;
use crate::layout::Rect;
use crate::style::{Color, Modifier};
use crossterm::error::ErrorKind;

pub struct CrosstermBackend {
    screen: crossterm::Screen,
}

impl Default for CrosstermBackend {
    fn default() -> CrosstermBackend {
        CrosstermBackend {
            screen: crossterm::Screen::default(),
        }
    }
}

impl CrosstermBackend {
    pub fn new() -> CrosstermBackend {
        CrosstermBackend::default()
    }

    pub fn with_screen(screen: crossterm::Screen) -> CrosstermBackend {
        CrosstermBackend { screen: screen }
    }

    pub fn screen(&self) -> &crossterm::Screen {
        &self.screen
    }
}

// TODO: consider associated Error type on Backend to allow custom error types
// per backend
fn convert_error(error: ErrorKind) -> io::Error {
    match error {
        ErrorKind::IoError(err) => err,
        ErrorKind::FmtError(err) => {
            io::Error::new(io::ErrorKind::Other, format!("Invalid formatting: {}", err))
        }
        ErrorKind::ResizingTerminalFailure(err) => io::Error::new(
            io::ErrorKind::Other,
            format!("Failed to resize terminal: {}", err),
        ),
        _ => io::Error::new(io::ErrorKind::Other, "Unknown crossterm error"),
    }
}

impl Backend for CrosstermBackend {
    fn clear(&mut self) -> io::Result<()> {
        let terminal = crossterm::terminal();
        terminal
            .clear(crossterm::ClearType::All)
            .map_err(convert_error)?;
        Ok(())
    }

    fn hide_cursor(&mut self) -> io::Result<()> {
        let cursor = crossterm::cursor();
        cursor.hide().map_err(convert_error)?;
        Ok(())
    }

    fn show_cursor(&mut self) -> io::Result<()> {
        let cursor = crossterm::cursor();
        cursor.show().map_err(convert_error)?;
        Ok(())
    }

    fn get_cursor(&mut self) -> io::Result<(u16, u16)> {
        let cursor = crossterm::cursor();
        Ok(cursor.pos())
    }

    fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> {
        let cursor = crossterm::cursor();
        cursor.goto(x, y).map_err(convert_error)
    }

    fn size(&self) -> io::Result<Rect> {
        let terminal = crossterm::terminal();
        let (width, height) = terminal.terminal_size();
        Ok(Rect::new(0, 0, width, height))
    }

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

    fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
    where
        I: Iterator<Item = (u16, u16, &'a Cell)>,
    {
        let cursor = crossterm::cursor();
        let crossterm = crossterm::Crossterm::from_screen(&self.screen);
        let mut last_y = 0;
        let mut last_x = 0;
        let mut first = true;
        for (x, y, cell) in content {
            if y != last_y || x != last_x + 1 || first {
                cursor.goto(x, y).map_err(convert_error)?;
                first = false;
            }
            last_x = x;
            last_y = y;

            let mut s = crossterm::style(&cell.symbol);
            if let Some(color) = cell.style.fg.into() {
                s = s.with(color)
            }
            if let Some(color) = cell.style.bg.into() {
                s = s.on(color)
            }
            if let Some(attr) = cell.style.modifier.into() {
                s = s.attr(attr)
            }
            crossterm.paint(s).map_err(convert_error)?;
        }
        Ok(())
    }
}

impl From<Color> for Option<crossterm::Color> {
    fn from(color: Color) -> Option<crossterm::Color> {
        match color {
            Color::Reset => None,
            Color::Black => Some(crossterm::Color::Black),
            Color::Red => Some(crossterm::Color::DarkRed),
            Color::Green => Some(crossterm::Color::DarkGreen),
            Color::Yellow => Some(crossterm::Color::DarkYellow),
            Color::Blue => Some(crossterm::Color::DarkBlue),
            Color::Magenta => Some(crossterm::Color::DarkMagenta),
            Color::Cyan => Some(crossterm::Color::DarkCyan),
            Color::Gray => Some(crossterm::Color::Grey),
            Color::DarkGray => Some(crossterm::Color::Grey),
            Color::LightRed => Some(crossterm::Color::Red),
            Color::LightGreen => Some(crossterm::Color::Green),
            Color::LightBlue => Some(crossterm::Color::Blue),
            Color::LightYellow => Some(crossterm::Color::Yellow),
            Color::LightMagenta => Some(crossterm::Color::Magenta),
            Color::LightCyan => Some(crossterm::Color::Cyan),
            Color::White => Some(crossterm::Color::White),
            Color::Rgb(r, g, b) => Some(crossterm::Color::Rgb { r, g, b }),
        }
    }
}

impl From<Modifier> for Option<crossterm::Attribute> {
    #[cfg(unix)]
    fn from(modifier: Modifier) -> Option<crossterm::Attribute> {
        match modifier {
            Modifier::Blink => Some(crossterm::Attribute::SlowBlink),
            Modifier::Bold => Some(crossterm::Attribute::Bold),
            Modifier::CrossedOut => Some(crossterm::Attribute::CrossedOut),
            Modifier::Faint => Some(crossterm::Attribute::Dim),
            Modifier::Invert => Some(crossterm::Attribute::Reverse),
            Modifier::Italic => Some(crossterm::Attribute::Italic),
            Modifier::Underline => Some(crossterm::Attribute::Underlined),
            _ => None,
        }
    }

    #[cfg(windows)]
    fn from(modifier: Modifier) -> Option<crossterm::Attribute> {
        match modifier {
            Modifier::Bold => Some(crossterm::Attribute::Bold),
            Modifier::Underline => Some(crossterm::Attribute::Underlined),
            _ => None,
        }
    }
}
<commit_msg>feat: crossterm backend can use alternate screen<commit_after>use std::io;

use crate::backend::Backend;
use crate::buffer::Cell;
use crate::layout::Rect;
use crate::style::{Color, Modifier};
use crossterm::error::ErrorKind;

pub struct CrosstermBackend {
    screen: crossterm::Screen,
    crossterm: crossterm::Crossterm,
    // Need to keep the AlternateScreen around even when not using it directly,
    // see https://github.com/TimonPost/crossterm/issues/88
    alternate_screen: Option<crossterm::AlternateScreen>,
}

impl Default for CrosstermBackend {
    fn default() -> CrosstermBackend {
        let screen = crossterm::Screen::default();
        let crossterm = crossterm::Crossterm::from_screen(&screen);
        CrosstermBackend {
            screen,
            crossterm,
            alternate_screen: None,
        }
    }
}

impl CrosstermBackend {
    pub fn new() -> CrosstermBackend {
        CrosstermBackend::default()
    }

    pub fn with_screen(screen: crossterm::Screen) -> CrosstermBackend {
        let crossterm = crossterm::Crossterm::from_screen(&screen);
        CrosstermBackend {
            screen,
            crossterm,
            alternate_screen: None,
        }
    }

    pub fn with_alternate_screen(screen: crossterm::Screen, raw_mode: bool) -> Result<CrosstermBackend, io::Error> {
        let alternate_screen = screen.enable_alternate_modes(raw_mode)?;
        let crossterm = crossterm::Crossterm::from_screen(&alternate_screen.screen);
        Ok(CrosstermBackend {
            screen,
            crossterm,
            alternate_screen: Some(alternate_screen),
        })
    }

    pub fn screen(&self) -> &crossterm::Screen {
        &self.screen
    }

    pub fn alternate_screen(&self) -> Option<&crossterm::AlternateScreen> {
        match &self.alternate_screen {
            Some(alt_screen) => Some(&alt_screen),
            None => None,
        }
    }

    pub fn crossterm(&self) -> &crossterm::Crossterm {
        &self.crossterm
    }
}

// TODO: consider associated Error type on Backend to allow custom error types
// per backend
fn convert_error(error: ErrorKind) -> io::Error {
    match error {
        ErrorKind::IoError(err) => err,
        ErrorKind::FmtError(err) => {
            io::Error::new(io::ErrorKind::Other, format!("Invalid formatting: {}", err))
        }
        ErrorKind::ResizingTerminalFailure(err) => io::Error::new(
            io::ErrorKind::Other,
            format!("Failed to resize terminal: {}", err),
        ),
        _ => io::Error::new(io::ErrorKind::Other, "Unknown crossterm error"),
    }
}

impl Backend for CrosstermBackend {
    fn clear(&mut self) -> io::Result<()> {
        let terminal = self.crossterm.terminal();
        terminal
            .clear(crossterm::ClearType::All)
            .map_err(convert_error)?;
        Ok(())
    }

    fn hide_cursor(&mut self) -> io::Result<()> {
        let cursor = self.crossterm.cursor();
        cursor.hide().map_err(convert_error)?;
        Ok(())
    }

    fn show_cursor(&mut self) -> io::Result<()> {
        let cursor = self.crossterm.cursor();
        cursor.show().map_err(convert_error)?;
        Ok(())
    }

    fn get_cursor(&mut self) -> io::Result<(u16, u16)> {
        let cursor = crossterm::cursor();
        Ok(cursor.pos())
    }

    fn set_cursor(&mut self, x: u16, y: u16) -> io::Result<()> {
        let cursor = crossterm::cursor();
        cursor.goto(x, y).map_err(convert_error)
    }

    fn size(&self) -> io::Result<Rect> {
        let terminal = self.crossterm.terminal();
        let (width, height) = terminal.terminal_size();
        Ok(Rect::new(0, 0, width, height))
    }

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

    fn draw<'a, I>(&mut self, content: I) -> io::Result<()>
    where
        I: Iterator<Item = (u16, u16, &'a Cell)>,
    {
        let cursor = self.crossterm.cursor();
        let mut last_y = 0;
        let mut last_x = 0;
        let mut first = true;
        for (x, y, cell) in content {
            if y != last_y || x != last_x + 1 || first {
                cursor.goto(x, y).map_err(convert_error)?;
                first = false;
            }
            last_x = x;
            last_y = y;
            let mut s = self.crossterm.style(&cell.symbol);
            if let Some(color) = cell.style.fg.into() {
                s = s.with(color)
            }
            if let Some(color) = cell.style.bg.into() {
                s = s.on(color)
            }
            if let Some(attr) = cell.style.modifier.into() {
                s = s.attr(attr)
            }
            self.crossterm.paint(s).map_err(convert_error)?;
        }
        Ok(())
    }
}

impl From<Color> for Option<crossterm::Color> {
    fn from(color: Color) -> Option<crossterm::Color> {
        match color {
            Color::Reset => None,
            Color::Black => Some(crossterm::Color::Black),
            Color::Red => Some(crossterm::Color::DarkRed),
            Color::Green => Some(crossterm::Color::DarkGreen),
            Color::Yellow => Some(crossterm::Color::DarkYellow),
            Color::Blue => Some(crossterm::Color::DarkBlue),
            Color::Magenta => Some(crossterm::Color::DarkMagenta),
            Color::Cyan => Some(crossterm::Color::DarkCyan),
            Color::Gray => Some(crossterm::Color::Grey),
            Color::DarkGray => Some(crossterm::Color::Grey),
            Color::LightRed => Some(crossterm::Color::Red),
            Color::LightGreen => Some(crossterm::Color::Green),
            Color::LightBlue => Some(crossterm::Color::Blue),
            Color::LightYellow => Some(crossterm::Color::Yellow),
            Color::LightMagenta => Some(crossterm::Color::Magenta),
            Color::LightCyan => Some(crossterm::Color::Cyan),
            Color::White => Some(crossterm::Color::White),
            Color::Rgb(r, g, b) => Some(crossterm::Color::Rgb { r, g, b }),
        }
    }
}

impl From<Modifier> for Option<crossterm::Attribute> {
    #[cfg(unix)]
    fn from(modifier: Modifier) -> Option<crossterm::Attribute> {
        match modifier {
            Modifier::Blink => Some(crossterm::Attribute::SlowBlink),
            Modifier::Bold => Some(crossterm::Attribute::Bold),
            Modifier::CrossedOut => Some(crossterm::Attribute::CrossedOut),
            Modifier::Faint => Some(crossterm::Attribute::Dim),
            Modifier::Invert => Some(crossterm::Attribute::Reverse),
            Modifier::Italic => Some(crossterm::Attribute::Italic),
            Modifier::Underline => Some(crossterm::Attribute::Underlined),
            _ => None,
        }
    }

    #[cfg(windows)]
    fn from(modifier: Modifier) -> Option<crossterm::Attribute> {
        match modifier {
            Modifier::Bold => Some(crossterm::Attribute::Bold),
            Modifier::Underline => Some(crossterm::Attribute::Underlined),
            _ => None,
        }
    }
}
<|endoftext|>