<commit_before>extern crate num_cpus;
extern crate itertools;
extern crate rand;
extern crate crossbeam;

use self::rand::{thread_rng, Rng};
use self::itertools::Itertools;
use self::crossbeam::{scope, ScopedJoinHandle};

use std::ops::Range;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::sync::{Mutex, RwLock, MutexGuard};
use std::sync::mpsc::{Sender, Receiver, channel};
use std::thread::spawn;

use task::{TaskGenerator, Task};
use candidate::{WorkingCandidate, Candidate};
use solution::Solution;
use scaling::{ScalingFunction, proportionate};
use result::{Result as AbcResult, Error as AbcError};

/// Manages the parameters of the ABC algorithm.
pub struct HiveBuilder<S: Solution> {
    workers: usize,
    observers: usize,
    retries: usize,
    builder: Mutex<S::Builder>,
    threads: usize,
    scale: Box<ScalingFunction>,
}

impl<S: Solution> HiveBuilder<S> {
    /// Creates a new hive.
    ///
    /// * `builder` - Factory-like state that can be used while generating solutions.
    /// * `workers` - Number of working solution candidates to maintain at a time.
    pub fn new(builder: S::Builder, workers: usize) -> HiveBuilder<S> {
        if workers == 0 {
            panic!("HiveBuilder must have at least one worker.");
        }

        HiveBuilder {
            workers: workers,
            observers: workers,
            retries: workers,

            builder: Mutex::new(builder),
            threads: num_cpus::get(),
            scale: proportionate(),
        }
    }

    /// Sets the number of "bees" that will pick a candidate to work on at random.
    ///
    /// This defaults to the number of workers.
    pub fn set_observers(mut self, observers: usize) -> HiveBuilder<S> {
        self.observers = observers;
        self
    }

    /// Sets the number of times a candidate can go unimproved before being reinitialized.
    ///
    /// This defaults to the number of workers.
    pub fn set_retries(mut self, retries: usize) -> HiveBuilder<S> {
        self.retries = retries;
        self
    }

    /// Sets the number of worker threads to use while running.
    pub fn set_threads(mut self, threads: usize) -> HiveBuilder<S> {
        self.threads = threads;
        self
    }

    /// Sets the scaling function for observers to use.
    pub fn set_scaling(mut self, scale: Box<ScalingFunction>) -> HiveBuilder<S> {
        self.scale = scale;
        self
    }

    /// Activates the `HiveBuilder` to create a runnable object.
    pub fn build(self) -> AbcResult<Hive<S>> {
        Hive::new(self)
    }
}

/// Runs the ABC algorithm, maintaining any necessary state.
pub struct Hive<S: Solution> {
    hive: HiveBuilder<S>,

    working: Vec<RwLock<WorkingCandidate<S>>>,
    best: Mutex<Candidate<S>>,

    tasks: Mutex<Option<TaskGenerator>>,
    streaming: Option<Mutex<Sender<Candidate<S>>>>,
}

impl<S: Solution> Hive<S> {
    fn new(hive: HiveBuilder<S>) -> AbcResult<Hive<S>> {
        let tokens: Mutex<Range<usize>> = Mutex::new(0..hive.workers);
        let candidates = Mutex::new(Vec::with_capacity(hive.workers));
        let mut handles = Vec::<ScopedJoinHandle<AbcResult<()>>>::with_capacity(hive.threads);

        try!(crossbeam::scope(|scope| {
            for _ in 0..hive.threads {
                handles.push(scope.spawn(|| {
                    while let Some(_) = tokens.lock().unwrap().next() {
                        let mut builder = try!(hive.builder.lock());
                        let solution = S::make(&mut builder);
                        drop(builder);
                        let candidate = Candidate::new(solution);
                        try!(candidates.lock()).push(candidate);
                    }
                    Ok(())
                }));
            }

            handles.drain(..)
                   .fold(Ok(()), |result, handle| result.and(handle.join()))
        }));

        let mut candidates = try!(candidates.into_inner());

        let best = {
            let best_candidate = candidates.iter()
                                           .fold1(|best, next| {
                                               if next.fitness > best.fitness {
                                                   next
                                               } else {
                                                   best
                                               }
                                           })
                                           .unwrap();
            Mutex::new(best_candidate.clone())
        };

        let working = candidates.drain(..)
                                .map(|c| RwLock::new(WorkingCandidate::new(c, hive.retries)))
                                .collect::<Vec<_>>();

        Ok(Hive {
            working: working,
            best: best,
            hive: hive,
            tasks: Mutex::new(None),
            streaming: None,
        })
    }

    fn current_working(&self) -> AbcResult<Vec<Candidate<S>>> {
        let mut current_working = Vec::with_capacity(self.working.len());
        for candidate_mutex in &self.working {
            let read_guard = try!(candidate_mutex.read());
            current_working.push(read_guard.candidate.clone())
        }
        Ok(current_working)
    }

    /// Returns a guard for the current best solution found by the hive.
    ///
    /// If the hive is running, you should drop the guard returned by this
    /// function as soon as convenient, since the logic of the hive can block
    /// on the availability of the associated mutex. If you plan on performing
    /// expensive computations, you should `drop` the guard as soon as
    /// possible, or acquire and clone it within a small block.
    pub fn get(&self) -> AbcResult<MutexGuard<Candidate<S>>> {
        self.best.lock().map_err(AbcError::from)
    }

    fn consider_improvement(&self, candidate: &Candidate<S>) -> AbcResult<()> {
        let mut best_guard = try!(self.best.lock());
        if candidate.fitness > best_guard.fitness {
            *best_guard = candidate.clone();
            if let Some(mutex) = self.streaming.as_ref() {
                // We're streaming, so we need to post the improved candidate.
                let sender_guard = try!(mutex.lock());
                // If this errors, the receiver was dropped, so we're done.
                if let Err(_) = sender_guard.send(candidate.clone()) {
                    try!(self.stop());
                }
            }
        }
        Ok(())
    }

    fn work_on(&self, current_working: &[Candidate<S>], n: usize) -> AbcResult<()> {
        let variant = Candidate::new(S::explore(current_working, n));
        let mut write_guard = try!(self.working[n].write());
        if variant.fitness > write_guard.candidate.fitness {
            *write_guard = WorkingCandidate::new(variant, self.hive.retries);
            try!(self.consider_improvement(&write_guard.candidate));
        } else {
            write_guard.deplete();
            // Scouting has been folded into the working process
            if write_guard.expired() {
                let mut builder = try!(self.hive.builder.lock());
                let solution = S::make(&mut builder);
                drop(builder);
                let candidate = Candidate::new(solution);
                *write_guard = WorkingCandidate::new(candidate, self.hive.retries);
                try!(self.consider_improvement(&write_guard.candidate));
            }
        }
        Ok(())
    }

    fn choose(&self, current_working: &[Candidate<S>]) -> usize {
        let fitnesses = (self.hive.scale)(current_working.iter()
                                                         .map(|candidate| candidate.fitness)
                                                         .collect::<Vec<f64>>());

        let running_totals = fitnesses.iter()
                                      .scan(0f64, |total, fitness| {
                                          *total += *fitness;
                                          Some(*total)
                                      })
                                      .collect::<Vec<f64>>();

        // Multiplying the choice point is equivalent to, and more efficient than, normalizing
        // all of the scaled fitnesses and having a choice point in [0,1)
        let total_fitness = running_totals.last().unwrap();
        let choice_point = thread_rng().next_f64() * total_fitness;

        for (i, total) in running_totals.iter().enumerate() {
            if *total > choice_point {
                return i;
            }
        }
        unreachable!();
    }

    fn execute(&self, task: &Task) -> AbcResult<()> {
        let current_working = try!(self.current_working());
        let index = match *task {
            Task::Worker(n) => n,
            Task::Observer(_) => self.choose(&current_working),
        };
        self.work_on(&current_working, index)
    }

    fn run(&self, tasks: TaskGenerator) -> AbcResult<()> {
        let mut guard = try!(self.tasks.lock());
        *guard = Some(tasks);
        drop(guard);

        let mut handles: Vec<ScopedJoinHandle<AbcResult<()>>> = Vec::new();

        scope(|scope| {
            for _ in 0..self.hive.threads {
                handles.push(scope.spawn(|| {
                    loop {
                        let mut guard = try!(self.tasks.lock());
                        let task = guard.as_mut().and_then(|gen| gen.next());
                        drop(guard);

                        match task {
                            Some(t) => try!(self.execute(&t)),
                            None => return Ok(()),
                        };
                    }
                }));
            }

            // Returns `Ok(())` only if all threads join cleanly, and the task
            // cycle is successfully cleared away.
            //
            // We avoid `try!` because we want all of the following logic to
            // execute unconditionally.
            handles.drain(..)
                   .fold(Ok(()), |result, handle| result.and(handle.join()))
                   .and(self.tasks
                            .lock()
                            .map(|mut tasks_guard| *tasks_guard = None)
                            .map_err(AbcError::from))
        })
    }

    /// Runs for a fixed number of rounds, then return the best solution found.
    ///
    /// If one of the worker threads panics while working, this will return
    /// `Err(abc::Error)`. Otherwise, it will return `Ok` with a `Candidate`.
    pub fn run_for_rounds(&self, rounds: usize) -> AbcResult<Candidate<S>> {
        let tasks = TaskGenerator::new(self.hive.workers, self.hive.observers).max_rounds(rounds);
        try!(self.run(tasks));
        self.get().map(|guard| guard.clone())
    }

    /// Runs indefinitely in the background, providing a stream of results.
    ///
    /// This method consumes the hive, which will run until the `HiveBuilder` object
    /// is dropped. It returns an `mpsc::Receiver`, which receives a
    /// `Candidate` each time the hive improves on its best solution.
    pub fn stream(mut self) -> Receiver<Candidate<S>> {
        let (sender, receiver) = channel();
        spawn(move || {
            let tasks = TaskGenerator::new(self.hive.workers, self.hive.observers);
            self.streaming = Some(Mutex::new(sender));
            self.run(tasks)
        });
        receiver
    }

    /// Stops a running hive.
    ///
    /// If a worker thread has panicked, this returns `Err(abc::Error)`.
    pub fn stop(&self) -> AbcResult<()> {
        let mut tasks_guard = try!(self.tasks.lock());
        Ok(tasks_guard.as_mut().map_or((), |t| t.stop()))
    }

    /// Returns the current round of a running hive.
    ///
    /// If a worker thread has panicked and poisoned the task generator lock,
    /// `get_round` will return `Err(abc::Error)`.
    ///
    /// If the hive has not been run, `get_round` will return `Ok(None)`.
    pub fn get_round(&self) -> AbcResult<Option<usize>> {
        let tasks_guard = try!(self.tasks.lock());
        Ok(tasks_guard.as_ref().map(|tasks| tasks.round))
    }
}

impl<S: Solution + Debug> Debug for Hive<S> {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        for mutex in (&self.working).iter() {
            let working = mutex.read().unwrap();
            try!(write!(f, "..{:?}..\n", working.candidate));
        }
        let best_candidate = self.get().unwrap();
        write!(f, ">>{:?}<<", *best_candidate)
    }
}

impl<S: Solution> Drop for Hive<S> {
    fn drop(&mut self) {
        self.stop().unwrap_or(())
    }
}
<commit_msg>Abstract candidate creation into method<commit_after>extern crate num_cpus;
extern crate itertools;
extern crate rand;
extern crate crossbeam;

use self::rand::{thread_rng, Rng};
use self::itertools::Itertools;
use self::crossbeam::{scope, ScopedJoinHandle};

use std::ops::Range;
use std::fmt::{Debug, Formatter, Result as FmtResult};
use std::sync::{Mutex, RwLock, MutexGuard};
use std::sync::mpsc::{Sender, Receiver, channel};
use std::thread::spawn;

use task::{TaskGenerator, Task};
use candidate::{WorkingCandidate, Candidate};
use solution::Solution;
use scaling::{ScalingFunction, proportionate};
use result::{Result as AbcResult, Error as AbcError};

/// Manages the parameters of the ABC algorithm.
pub struct HiveBuilder<S: Solution> {
    workers: usize,
    observers: usize,
    retries: usize,
    builder: Mutex<S::Builder>,
    threads: usize,
    scale: Box<ScalingFunction>,
}

impl<S: Solution> HiveBuilder<S> {
    /// Creates a new hive.
    ///
    /// * `builder` - Factory-like state that can be used while generating solutions.
    /// * `workers` - Number of working solution candidates to maintain at a time.
    pub fn new(builder: S::Builder, workers: usize) -> HiveBuilder<S> {
        if workers == 0 {
            panic!("HiveBuilder must have at least one worker.");
        }

        HiveBuilder {
            workers: workers,
            observers: workers,
            retries: workers,

            builder: Mutex::new(builder),
            threads: num_cpus::get(),
            scale: proportionate(),
        }
    }

    /// Sets the number of "bees" that will pick a candidate to work on at random.
    ///
    /// This defaults to the number of workers.
    pub fn set_observers(mut self, observers: usize) -> HiveBuilder<S> {
        self.observers = observers;
        self
    }

    /// Sets the number of times a candidate can go unimproved before being reinitialized.
    ///
    /// This defaults to the number of workers.
    pub fn set_retries(mut self, retries: usize) -> HiveBuilder<S> {
        self.retries = retries;
        self
    }

    /// Sets the number of worker threads to use while running.
    pub fn set_threads(mut self, threads: usize) -> HiveBuilder<S> {
        self.threads = threads;
        self
    }

    /// Sets the scaling function for observers to use.
    pub fn set_scaling(mut self, scale: Box<ScalingFunction>) -> HiveBuilder<S> {
        self.scale = scale;
        self
    }

    /// Activates the `HiveBuilder` to create a runnable object.
    pub fn build(self) -> AbcResult<Hive<S>> {
        Hive::new(self)
    }

    fn new_candidate(&self) -> AbcResult<Candidate<S>> {
        let mut builder = try!(self.builder.lock());
        let solution = S::make(&mut builder);
        drop(builder);
        Ok(Candidate::new(solution))
    }
}

/// Runs the ABC algorithm, maintaining any necessary state.
pub struct Hive<S: Solution> {
    hive: HiveBuilder<S>,

    working: Vec<RwLock<WorkingCandidate<S>>>,
    best: Mutex<Candidate<S>>,

    tasks: Mutex<Option<TaskGenerator>>,
    streaming: Option<Mutex<Sender<Candidate<S>>>>,
}

impl<S: Solution> Hive<S> {
    fn new(hive: HiveBuilder<S>) -> AbcResult<Hive<S>> {
        let tokens: Mutex<Range<usize>> = Mutex::new(0..hive.workers);
        let candidates = Mutex::new(Vec::with_capacity(hive.workers));
        let mut handles = Vec::<ScopedJoinHandle<AbcResult<()>>>::with_capacity(hive.threads);

        try!(crossbeam::scope(|scope| {
            for _ in 0..hive.threads {
                handles.push(scope.spawn(|| {
                    while let Some(_) = tokens.lock().unwrap().next() {
                        let candidate = try!(hive.new_candidate());
                        try!(candidates.lock()).push(candidate);
                    }
                    Ok(())
                }));
            }

            handles.drain(..)
                   .fold(Ok(()), |result, handle| result.and(handle.join()))
        }));

        let mut candidates = try!(candidates.into_inner());

        let best = {
            let best_candidate = candidates.iter()
                                           .fold1(|best, next| {
                                               if next.fitness > best.fitness {
                                                   next
                                               } else {
                                                   best
                                               }
                                           })
                                           .unwrap();
            Mutex::new(best_candidate.clone())
        };

        let working = candidates.drain(..)
                                .map(|c| RwLock::new(WorkingCandidate::new(c, hive.retries)))
                                .collect::<Vec<_>>();

        Ok(Hive {
            working: working,
            best: best,
            hive: hive,
            tasks: Mutex::new(None),
            streaming: None,
        })
    }

    fn current_working(&self) -> AbcResult<Vec<Candidate<S>>> {
        let mut current_working = Vec::with_capacity(self.working.len());
        for candidate_mutex in &self.working {
            let read_guard = try!(candidate_mutex.read());
            current_working.push(read_guard.candidate.clone())
        }
        Ok(current_working)
    }

    /// Returns a guard for the current best solution found by the hive.
    ///
    /// If the hive is running, you should drop the guard returned by this
    /// function as soon as convenient, since the logic of the hive can block
    /// on the availability of the associated mutex. If you plan on performing
    /// expensive computations, you should `drop` the guard as soon as
    /// possible, or acquire and clone it within a small block.
    pub fn get(&self) -> AbcResult<MutexGuard<Candidate<S>>> {
        self.best.lock().map_err(AbcError::from)
    }

    fn consider_improvement(&self, candidate: &Candidate<S>) -> AbcResult<()> {
        let mut best_guard = try!(self.best.lock());
        if candidate.fitness > best_guard.fitness {
            *best_guard = candidate.clone();
            if let Some(mutex) = self.streaming.as_ref() {
                // We're streaming, so we need to post the improved candidate.
                let sender_guard = try!(mutex.lock());
                // If this errors, the receiver was dropped, so we're done.
                if let Err(_) = sender_guard.send(candidate.clone()) {
                    try!(self.stop());
                }
            }
        }
        Ok(())
    }

    fn work_on(&self, current_working: &[Candidate<S>], n: usize) -> AbcResult<()> {
        let variant = Candidate::new(S::explore(current_working, n));
        let mut write_guard = try!(self.working[n].write());
        if variant.fitness > write_guard.candidate.fitness {
            *write_guard = WorkingCandidate::new(variant, self.hive.retries);
            try!(self.consider_improvement(&write_guard.candidate));
        } else {
            write_guard.deplete();
            // Scouting has been folded into the working process
            if write_guard.expired() {
                let candidate = try!(self.hive.new_candidate());
                *write_guard = WorkingCandidate::new(candidate, self.hive.retries);
                try!(self.consider_improvement(&write_guard.candidate));
            }
        }
        Ok(())
    }

    fn choose(&self, current_working: &[Candidate<S>]) -> usize {
        let fitnesses = (self.hive.scale)(current_working.iter()
                                                         .map(|candidate| candidate.fitness)
                                                         .collect::<Vec<f64>>());

        let running_totals = fitnesses.iter()
                                      .scan(0f64, |total, fitness| {
                                          *total += *fitness;
                                          Some(*total)
                                      })
                                      .collect::<Vec<f64>>();

        // Multiplying the choice point is equivalent to, and more efficient than, normalizing
        // all of the scaled fitnesses and having a choice point in [0,1)
        let total_fitness = running_totals.last().unwrap();
        let choice_point = thread_rng().next_f64() * total_fitness;

        for (i, total) in running_totals.iter().enumerate() {
            if *total > choice_point {
                return i;
            }
        }
        unreachable!();
    }

    fn execute(&self, task: &Task) -> AbcResult<()> {
        let current_working = try!(self.current_working());
        let index = match *task {
            Task::Worker(n) => n,
            Task::Observer(_) => self.choose(&current_working),
        };
        self.work_on(&current_working, index)
    }

    fn run(&self, tasks: TaskGenerator) -> AbcResult<()> {
        let mut guard = try!(self.tasks.lock());
        *guard = Some(tasks);
        drop(guard);

        let mut handles: Vec<ScopedJoinHandle<AbcResult<()>>> = Vec::new();

        scope(|scope| {
            for _ in 0..self.hive.threads {
                handles.push(scope.spawn(|| {
                    loop {
                        let mut guard = try!(self.tasks.lock());
                        let task = guard.as_mut().and_then(|gen| gen.next());
                        drop(guard);

                        match task {
                            Some(t) => try!(self.execute(&t)),
                            None => return Ok(()),
                        };
                    }
                }));
            }

            // Returns `Ok(())` only if all threads join cleanly, and the task
            // cycle is successfully cleared away.
            //
            // We avoid `try!` because we want all of the following logic to
            // execute unconditionally.
            handles.drain(..)
                   .fold(Ok(()), |result, handle| result.and(handle.join()))
                   .and(self.tasks
                            .lock()
                            .map(|mut tasks_guard| *tasks_guard = None)
                            .map_err(AbcError::from))
        })
    }

    /// Runs for a fixed number of rounds, then return the best solution found.
    ///
    /// If one of the worker threads panics while working, this will return
    /// `Err(abc::Error)`. Otherwise, it will return `Ok` with a `Candidate`.
    pub fn run_for_rounds(&self, rounds: usize) -> AbcResult<Candidate<S>> {
        let tasks = TaskGenerator::new(self.hive.workers, self.hive.observers).max_rounds(rounds);
        try!(self.run(tasks));
        self.get().map(|guard| guard.clone())
    }

    /// Runs indefinitely in the background, providing a stream of results.
    ///
    /// This method consumes the hive, which will run until the `HiveBuilder` object
    /// is dropped. It returns an `mpsc::Receiver`, which receives a
    /// `Candidate` each time the hive improves on its best solution.
    pub fn stream(mut self) -> Receiver<Candidate<S>> {
        let (sender, receiver) = channel();
        spawn(move || {
            let tasks = TaskGenerator::new(self.hive.workers, self.hive.observers);
            self.streaming = Some(Mutex::new(sender));
            self.run(tasks)
        });
        receiver
    }

    /// Stops a running hive.
    ///
    /// If a worker thread has panicked, this returns `Err(abc::Error)`.
    pub fn stop(&self) -> AbcResult<()> {
        let mut tasks_guard = try!(self.tasks.lock());
        Ok(tasks_guard.as_mut().map_or((), |t| t.stop()))
    }

    /// Returns the current round of a running hive.
    ///
    /// If a worker thread has panicked and poisoned the task generator lock,
    /// `get_round` will return `Err(abc::Error)`.
    ///
    /// If the hive has not been run, `get_round` will return `Ok(None)`.
    pub fn get_round(&self) -> AbcResult<Option<usize>> {
        let tasks_guard = try!(self.tasks.lock());
        Ok(tasks_guard.as_ref().map(|tasks| tasks.round))
    }
}

impl<S: Solution + Debug> Debug for Hive<S> {
    fn fmt(&self, f: &mut Formatter) -> FmtResult {
        for mutex in (&self.working).iter() {
            let working = mutex.read().unwrap();
            try!(write!(f, "..{:?}..\n", working.candidate));
        }
        let best_candidate = self.get().unwrap();
        write!(f, ">>{:?}<<", *best_candidate)
    }
}

impl<S: Solution> Drop for Hive<S> {
    fn drop(&mut self) {
        self.stop().unwrap_or(())
    }
}
<|endoftext|>


<commit_before>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! `GetPfmId` request and response.
//!
//! This module provides a Cerberus command that allows the querying of the reset state of the host
//! processor protected by Cerberus.

use crate::io::read::ReadZeroExt as _;
use crate::io::ReadInt as _;
use crate::protocol::cerberus::CommandType;

#[cfg(feature = "arbitrary-derive")]
use libfuzzer_sys::arbitrary::{self, Arbitrary};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

protocol_struct! {
    /// A command for requesting the PFM Version or Platform ID.
    ///
    /// The encoding of the response structure diverges from that of the
    /// specification. The spec requires that we know the original request in
    /// order to parse the response. As of now, we will be diverging from that.
    /// Instead, we encode and decode this with an extra byte that indicates
    /// whether the response contains an `IdentifierType::Version` or
    /// `IdentifierType::Platform` and the encoding of this follows that of the
    /// request.
    ///
    /// The encoding is as follows:
    ///
    /// 1 - PfmValidity (0 or 1)
    /// 2 - IdentifierType (as encoded in the request)
    /// 3:N - Identifier
    ///       - If `Version` this will be exactly 4 bytes
    ///       - If `Platform` this will be an ASCII string (not null terminated).
    type GetPfmId;
    const TYPE: CommandType = GetPfmId;

    struct Request {
        /// The port of the device whose PFM Id is being looked up.
        #[cfg_attr(feature = "serde", serde(with = "crate::serde::hex"))]
        pub port_id: u8,
        /// The PFM Region (Active or Pending).
        pub pfm_region: PfmRegion,
        /// The ID Type (Version or Platform).
        pub identifier: IdentifierType,
    }

    fn Request::from_wire(r, arena) {
        let port_id = r.read_le()?;
        let pfm_region = PfmRegion::from_wire(r, arena)?;
        let identifier = if r.remaining_data() > 0 {
            IdentifierType::from_wire(r, arena)?
        } else {
            // If missing, default identifier is `Version`
            IdentifierType::Version
        };
        Ok(Self {
            port_id,
            pfm_region,
            identifier,
        })
    }

    fn Request::to_wire(&self, w) {
        w.write_le(self.port_id)?;
        self.pfm_region.to_wire(&mut w)?;
        // TODO(#153): If `IdentifierType::Version` do we skip to save bytes?
        self.identifier.to_wire(&mut w)?;
        Ok(())
    }

    struct Response<'wire> {
        /// PFM validity.
        pub pfm_valid: PfmValidity,
        /// PFM Identifier (either Version or Platform).
        pub pfm_id: Identifier<'wire>,
    }

    fn Response::from_wire(r, arena) {
        let pfm_valid = PfmValidity::from_wire(r, arena)?;
        let identifier = IdentifierType::from_wire(r, arena)?;
        let pfm_id = match identifier {
            IdentifierType::Version => {
                let version: u32 = r.read_le()?;
                Identifier::Version {id: version}
            }
            IdentifierType::Platform => {
                let bytes = r.read_slice(r.remaining_data(), arena)?;
                Identifier::Platform{id: bytes}
            }
        };
        Ok(Self { pfm_valid, pfm_id })
    }

    fn Response::to_wire(&self, w) {
        self.pfm_valid.to_wire(&mut w)?;
        match self.pfm_id {
            Identifier::Version{id} => {
                IdentifierType::Version.to_wire(&mut w)?;
                w.write_le(id)?;
            }
            Identifier::Platform{id} => {
                IdentifierType::Platform.to_wire(&mut w)?;
                w.write_bytes(id)?;
            }
        }
        Ok(())
    }
}

wire_enum! {
    /// PFM Region.
    #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum PfmRegion: u8 {
        /// PFM Region Active
        Active = 0x00,
        /// PFM Region Pending
        Pending = 0x01,
    }
}

wire_enum! {
    /// The id type requested.
    #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum IdentifierType: u8 {
        /// PFM Version ID
        Version = 0x00,
        /// PFM Platform ID
        Platform = 0x01,
    }
}

wire_enum! {
    /// The id type requested.
    #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum PfmValidity: u8 {
        /// PFM is valid
        Valid = 0x00,
        /// PFM is invalid
        Invalid = 0x01,
    }
}

derive_borrowed!(PfmValidity);

derive_borrowed! {
    /// The PFM Identifier (either platform or version).
    // #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
    #[@static(
        derive(Clone, PartialEq, Eq, Debug),
        cfg_attr(feature = "serde", derive(serde::Deserialize)),
        cfg_attr(feature = "arbitrary-derive", derive(Arbitrary)),
    )]
    pub enum Identifier<'a> {
        /// Identifier of type Version. Set when `IdentifierType::Version` is set
        /// in request. Uses a 4-byte identifier.
        Version {
            /// The ID.
            id: u32,
        },
        /// Identifier of type Platform. Set when `IdentifierType::Platform` is set
        /// in request. Uses an ASCII delimited String.
        Platform {
            /// The ID.
            id: &'a [u8],
        },
    }
}

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

    round_trip_test! {
        request_round_trip: {
            bytes: &[0x7f, 0x01, 0x00],
            json: r#"{
                "port_id": "0x7f",
                "pfm_region": "Pending",
                "identifier": "Version"
            }"#,
            value: GetPfmIdRequest {
                port_id: 0x7f,
                pfm_region: PfmRegion::Pending,
                identifier: IdentifierType::Version
            },
        },
        response_round_trip: {
            bytes: &[0x00, 0x01, 0x01, 0x02, 0x03],
            json: r#"{
                "pfm_valid": "Valid",
                "pfm_id": {
                    "Platform": { "id": [1, 2, 3] }
                }
            }"#,
            value: GetPfmIdResponse {
                pfm_valid:  PfmValidity::Valid,
                pfm_id: Identifier::Platform{id: &[0x01, 0x02, 0x03]}
            },
        },
    }
}
<commit_msg>[cerberus] Added TODO to clean up PFM Identifier enum.<commit_after>// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

//! `GetPfmId` request and response.
//!
//! This module provides a Cerberus command that allows the querying of the reset state of the host
//! processor protected by Cerberus.

use crate::io::read::ReadZeroExt as _;
use crate::io::ReadInt as _;
use crate::protocol::cerberus::CommandType;

#[cfg(feature = "arbitrary-derive")]
use libfuzzer_sys::arbitrary::{self, Arbitrary};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};

protocol_struct! {
    /// A command for requesting the PFM Version or Platform ID.
    ///
    /// The encoding of the response structure diverges from that of the
    /// specification. The spec requires that we know the original request in
    /// order to parse the response. As of now, we will be diverging from that.
    /// Instead, we encode and decode this with an extra byte that indicates
    /// whether the response contains an `IdentifierType::Version` or
    /// `IdentifierType::Platform` and the encoding of this follows that of the
    /// request.
    ///
    /// The encoding is as follows:
    ///
    /// 1 - PfmValidity (0 or 1)
    /// 2 - IdentifierType (as encoded in the request)
    /// 3:N - Identifier
    ///       - If `Version` this will be exactly 4 bytes
    ///       - If `Platform` this will be an ASCII string (not null terminated).
    type GetPfmId;
    const TYPE: CommandType = GetPfmId;

    struct Request {
        /// The port of the device whose PFM Id is being looked up.
        #[cfg_attr(feature = "serde", serde(with = "crate::serde::hex"))]
        pub port_id: u8,
        /// The PFM Region (Active or Pending).
        pub pfm_region: PfmRegion,
        /// The ID Type (Version or Platform).
        pub identifier: IdentifierType,
    }

    fn Request::from_wire(r, arena) {
        let port_id = r.read_le()?;
        let pfm_region = PfmRegion::from_wire(r, arena)?;
        let identifier = if r.remaining_data() > 0 {
            IdentifierType::from_wire(r, arena)?
        } else {
            // If missing, default identifier is `Version`
            IdentifierType::Version
        };
        Ok(Self {
            port_id,
            pfm_region,
            identifier,
        })
    }

    fn Request::to_wire(&self, w) {
        w.write_le(self.port_id)?;
        self.pfm_region.to_wire(&mut w)?;
        // TODO(#153): If `IdentifierType::Version` do we skip to save bytes?
        self.identifier.to_wire(&mut w)?;
        Ok(())
    }

    struct Response<'wire> {
        /// PFM validity.
        pub pfm_valid: PfmValidity,
        /// PFM Identifier (either Version or Platform).
        pub pfm_id: Identifier<'wire>,
    }

    fn Response::from_wire(r, arena) {
        let pfm_valid = PfmValidity::from_wire(r, arena)?;
        let identifier = IdentifierType::from_wire(r, arena)?;
        let pfm_id = match identifier {
            IdentifierType::Version => {
                let version: u32 = r.read_le()?;
                Identifier::Version {id: version}
            }
            IdentifierType::Platform => {
                let bytes = r.read_slice(r.remaining_data(), arena)?;
                Identifier::Platform{id: bytes}
            }
        };
        Ok(Self { pfm_valid, pfm_id })
    }

    fn Response::to_wire(&self, w) {
        self.pfm_valid.to_wire(&mut w)?;
        match self.pfm_id {
            Identifier::Version{id} => {
                IdentifierType::Version.to_wire(&mut w)?;
                w.write_le(id)?;
            }
            Identifier::Platform{id} => {
                IdentifierType::Platform.to_wire(&mut w)?;
                w.write_bytes(id)?;
            }
        }
        Ok(())
    }
}

wire_enum! {
    /// PFM Region.
    #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum PfmRegion: u8 {
        /// PFM Region Active
        Active = 0x00,
        /// PFM Region Pending
        Pending = 0x01,
    }
}

wire_enum! {
    /// The id type requested.
    #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum IdentifierType: u8 {
        /// PFM Version ID
        Version = 0x00,
        /// PFM Platform ID
        Platform = 0x01,
    }
}

wire_enum! {
    /// The id type requested.
    #[cfg_attr(feature = "arbitrary-derive", derive(Arbitrary))]
    #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    pub enum PfmValidity: u8 {
        /// PFM is valid
        Valid = 0x00,
        /// PFM is invalid
        Invalid = 0x01,
    }
}

derive_borrowed!(PfmValidity);

derive_borrowed! {
    /// The PFM Identifier (either platform or version).
    // #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
    #[derive(Clone, Copy, PartialEq, Eq, Debug)]
    #[cfg_attr(feature = "serde", derive(serde::Serialize))]
    #[@static(
        derive(Clone, PartialEq, Eq, Debug),
        cfg_attr(feature = "serde", derive(serde::Deserialize)),
        cfg_attr(feature = "arbitrary-derive", derive(Arbitrary)),
    )]
    // TODO(#151): Change to tuple variants.
    pub enum Identifier<'a> {
        /// Identifier of type Version. Set when `IdentifierType::Version` is set
        /// in request. Uses a 4-byte identifier.
        Version {
            /// The ID.
            id: u32,
        },
        /// Identifier of type Platform. Set when `IdentifierType::Platform` is set
        /// in request. Uses an ASCII delimited String.
        Platform {
            /// The ID.
            id: &'a [u8],
        },
    }
}

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

    round_trip_test! {
        request_round_trip: {
            bytes: &[0x7f, 0x01, 0x00],
            json: r#"{
                "port_id": "0x7f",
                "pfm_region": "Pending",
                "identifier": "Version"
            }"#,
            value: GetPfmIdRequest {
                port_id: 0x7f,
                pfm_region: PfmRegion::Pending,
                identifier: IdentifierType::Version
            },
        },
        response_round_trip: {
            bytes: &[0x00, 0x01, 0x01, 0x02, 0x03],
            json: r#"{
                "pfm_valid": "Valid",
                "pfm_id": {
                    "Platform": { "id": [1, 2, 3] }
                }
            }"#,
            value: GetPfmIdResponse {
                pfm_valid:  PfmValidity::Valid,
                pfm_id: Identifier::Platform{id: &[0x01, 0x02, 0x03]}
            },
        },
    }
}
<|endoftext|>


<commit_before>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use core::ptr::Unique;
use core::convert;

use ::memory::{VAddr, Addr};

use alloc::{PAGE_SIZE, Allocator};

pub mod table;
use self::table::*;

extern {
    pub static mut HEAP_BASE: u8;
    pub static mut HEAP_TOP: u8;
    pub static mut STACK_BASE: u8;
    pub static mut STACK_TOP: u8;
}

/// A physical (linear) memory address is a 64-bit unsigned integer
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct PAddr(u64);

impl Addr<u64> for PAddr { }

impl_addr! { PAddr, u64 }

impl PAddr {
    #[inline] pub fn from_ptr(ptr: *mut u8) -> Self { PAddr(ptr as u64) }
    #[inline] pub const fn from_u64(u: u64) -> Self { PAddr(u) }
    #[inline] pub const fn as_u64(&self) -> u64 { self.0 }
}

macro_rules! table_idx {
    ( $($name:ident >> $shift:expr)* ) => {$(
        pub fn $name(&self) -> usize {
            (self.number >> $shift) & 0o777
        }
    )*};
}

#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Page { pub number: usize }

impl Page {
    /// Create a new `Page` containing the given virtual address
    pub fn containing_addr(addr: VAddr) -> Page {
        assert!( addr.as_usize() < 0x0000_8000_0000_0000 ||
                 addr.as_usize() >= 0xffff_8000_0000_0000
               , "invalid address: 0x{:x}", addr );
        Page { number: (addr / PAGE_SIZE).as_usize() }
    }

    /// Return the start virtual address of this page
    #[inline]
    pub fn start_addr(&self) -> VAddr {
        VAddr::from_usize(self.number * PAGE_SIZE)
    }

    /// Flush the page from memory
    pub unsafe fn flush(&self) {
        asm!("invlpg [$0]"
            :
            : "{rax}"(self.start_addr())
            : "memory"
            : "intel", "volatile")
    }

    table_idx!{
        pml4_index >> 27
        pdpt_index >> 18
        pd_index >> 9
        pt_index >> 0
    }

}

pub struct ActivePML4(Unique<Table<PML4Level>>);

impl ActivePML4 {

    pub unsafe fn new() -> Self {
        ActivePML4(Unique::new(PML4))
    }

    fn pml4(&self) -> &Table<PML4Level> {
        unsafe { self.0.get() }
    }

    fn pml4_mut(&mut self) -> &mut Table<PML4Level> {
        unsafe { self.0.get_mut() }
    }

    fn translate(&self, vaddr: VAddr) -> Option<PAddr> {
        self.translate_page(Page::containing_addr(vaddr))
            .map(|frame| {
                let offset = vaddr.as_usize() % PAGE_SIZE;
                PAddr::from(frame as u64 + offset as u64)
            })
    }

    pub fn translate_page(&self, page: Page) -> Option<*mut u8> {
        let pdpt = self.pml4().next_table(page.pml4_index());

        let huge_page = || pdpt.and_then(|pdpt| {
            let pdpt_entry = &pdpt[page.pdpt_index()];

            if pdpt_entry.flags().contains(HUGE_PAGE) {
                // If the PDPT entry contains the huge page flag, and the
                // entry points to the start frame of a page, then the pointed
                // frame is a 1GB huge page
                pdpt_entry.pointed_frame()
                    .map(|start_frame| {
                        assert!( start_frame as usize % table::N_ENTRIES == 0
                               , "Start frame must be aligned on a \
                                  1GB boundary!");
                        (start_frame as usize + page.pd_index()
                                              + page.pt_index()) as *mut u8
                    })

            } else {
                pdpt.next_table(page.pdpt_index())
                    .and_then(|pd| {
                        let pd_entry = &pd[page.pd_index()];

                        if pd_entry.flags().contains(HUGE_PAGE) {
                            pd_entry.pointed_frame()
                                .map(|start_frame|{
                                    assert!( (start_frame as usize %
                                             table::N_ENTRIES) == 0
                                         , "Start frame must be aligned!");
                                    (start_frame as usize + page.pt_index())
                                        as *mut u8
                                })
                        } else {
                            None
                        }
                    })
            }
        });

        pdpt.and_then(|pdpt| pdpt.next_table(page.pdpt_index()))
            .and_then(|pd| pd.next_table(page.pd_index()))
            .and_then(|pt| pt[page.pt_index()].pointed_frame())
            .or_else(huge_page)

    }

    pub fn identity_map<A: Allocator>( &mut self
                                     , frame: *mut u8
                                     , flags: EntryFlags
                                     , allocator: &mut A )  {
        self.map_to( Page::containing_addr(VAddr::from(frame))
                   , frame
                   , flags
                   , allocator )
    }

    pub fn map<A: Allocator>( &mut self
                            , page: Page
                            , flags: EntryFlags
                            , allocator: &mut A)
    {
        unsafe {
            self.map_to( page
                       , allocator.allocate(PAGE_SIZE, PAGE_SIZE)
                                  .expect("Couldn't map, out of frames!")
                       , flags
                       , allocator );
        }
    }

    pub fn map_to<A: Allocator>( &mut self
                               , page: Page
                               , frame: *mut u8
                               , flags: EntryFlags
                               , allocator: &mut A) {
        let mut pdpt = self.pml4_mut()
                           .create_next(page.pml4_index(), allocator);
        let mut pd   = pdpt.create_next(page.pdpt_index(), allocator);
        let mut pt   = pd.create_next(page.pd_index(), allocator);

        let idx = page.pt_index();

        assert!(pt[idx].is_unused()
               , "Could not map frame {:?}, page table entry {} is already \
                  in use!", frame, idx);
        pt[idx].set(frame, flags | PRESENT);
    }

}
<commit_msg>[x86_64] clean up more things in memory module<commit_after>//
//  SOS: the Stupid Operating System
//  by Hawk Weisman (hi@hawkweisman.me)
//
//  Copyright (c) 2015 Hawk Weisman
//  Released under the terms of the MIT license. See `LICENSE` in the root
//  directory of this repository for more information.
//
use core::ptr::Unique;
use core::convert;

use ::memory::{VAddr, Addr};

use alloc::{PAGE_SIZE, Allocator};

pub mod table;
use self::table::*;

extern {
    // It would be really nice if there was a less ugly way of doing this...
    pub static mut HEAP_BASE: u8;
    pub static mut HEAP_TOP: u8;
    pub static mut STACK_BASE: u8;
    pub static mut STACK_TOP: u8;
}

/// A physical (linear) memory address is a 64-bit unsigned integer
#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct PAddr(u64);

impl Addr<u64> for PAddr { }

impl_addr! { PAddr, u64 }

impl PAddr {
    #[inline] pub fn from_ptr(ptr: *mut u8) -> Self { PAddr(ptr as u64) }
    #[inline] pub const fn from_u64(u: u64) -> Self { PAddr(u) }
    #[inline] pub const fn as_u64(&self) -> u64 { self.0 }
}

macro_rules! table_idx {
    ( $($name:ident >> $shift:expr)* ) => {$(
        pub fn $name(&self) -> usize {
            (self.number >> $shift) & 0o777
        }
    )*};
}

#[derive(Copy, Clone, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct Page { pub number: usize }

impl Page {
    /// Create a new `Page` containing the given virtual address
    pub fn containing_addr(addr: VAddr) -> Page {
        assert!( addr.as_usize() < 0x0000_8000_0000_0000 ||
                 addr.as_usize() >= 0xffff_8000_0000_0000
               , "invalid address: 0x{:x}", addr );
        Page { number: (addr / PAGE_SIZE).as_usize() }
    }

    /// Return the start virtual address of this page
    #[inline]
    pub fn start_addr(&self) -> VAddr {
        VAddr::from(self.number * PAGE_SIZE)
    }

    /// Flush the page from memory
    pub unsafe fn flush(&self) {
        asm!("invlpg [$0]"
            :
            : "{rax}"(self.start_addr())
            : "memory"
            : "intel", "volatile")
    }

    table_idx!{
        pml4_index >> 27
        pdpt_index >> 18
        pd_index >> 9
        pt_index >> 0
    }

}

pub struct ActivePML4(Unique<Table<PML4Level>>);

impl ActivePML4 {

    pub unsafe fn new() -> Self {
        ActivePML4(Unique::new(PML4))
    }

    fn pml4(&self) -> &Table<PML4Level> {
        unsafe { self.0.get() }
    }

    fn pml4_mut(&mut self) -> &mut Table<PML4Level> {
        unsafe { self.0.get_mut() }
    }

    fn translate(&self, vaddr: VAddr) -> Option<PAddr> {
        self.translate_page(Page::containing_addr(vaddr))
            .map(|frame| {
                let offset = vaddr.as_usize() % PAGE_SIZE;
                PAddr::from(frame as u64 + offset as u64)
            })
    }

    pub fn translate_page(&self, page: Page) -> Option<*mut u8> {
        let pdpt = self.pml4().next_table(page.pml4_index());

        let huge_page = || pdpt.and_then(|pdpt| {
            let pdpt_entry = &pdpt[page.pdpt_index()];

            if pdpt_entry.flags().contains(HUGE_PAGE) {
                // If the PDPT entry contains the huge page flag, and the
                // entry points to the start frame of a page, then the pointed
                // frame is a 1GB huge page
                pdpt_entry.pointed_frame()
                    .map(|start_frame| {
                        assert!( start_frame as usize % table::N_ENTRIES == 0
                               , "Start frame must be aligned on a \
                                  1GB boundary!");
                        (start_frame as usize + page.pd_index()
                                              + page.pt_index()) as *mut u8
                    })

            } else {
                pdpt.next_table(page.pdpt_index())
                    .and_then(|pd| {
                        let pd_entry = &pd[page.pd_index()];

                        if pd_entry.flags().contains(HUGE_PAGE) {
                            pd_entry.pointed_frame()
                                .map(|start_frame|{
                                    assert!( (start_frame as usize %
                                             table::N_ENTRIES) == 0
                                         , "Start frame must be aligned!");
                                    (start_frame as usize + page.pt_index())
                                        as *mut u8
                                })
                        } else {
                            None
                        }
                    })
            }
        });

        pdpt.and_then(|pdpt| pdpt.next_table(page.pdpt_index()))
            .and_then(|pd| pd.next_table(page.pd_index()))
            .and_then(|pt| pt[page.pt_index()].pointed_frame())
            .or_else(huge_page)

    }

    pub fn identity_map<A: Allocator>( &mut self
                                     , frame: *mut u8
                                     , flags: EntryFlags
                                     , allocator: &mut A )  {
        self.map_to( Page::containing_addr(VAddr::from(frame))
                   , frame
                   , flags
                   , allocator )
    }

    pub fn map<A: Allocator>( &mut self
                            , page: Page
                            , flags: EntryFlags
                            , allocator: &mut A)
    {
        unsafe {
            self.map_to( page
                       , allocator.allocate(PAGE_SIZE, PAGE_SIZE)
                                  .expect("Couldn't map, out of frames!")
                       , flags
                       , allocator );
        }
    }

    pub fn map_to<A: Allocator>( &mut self
                               , page: Page
                               , frame: *mut u8
                               , flags: EntryFlags
                               , allocator: &mut A) {
        let mut pdpt = self.pml4_mut()
                           .create_next(page.pml4_index(), allocator);
        let mut pd   = pdpt.create_next(page.pdpt_index(), allocator);
        let mut pt   = pd.create_next(page.pd_index(), allocator);

        let idx = page.pt_index();

        assert!(pt[idx].is_unused()
               , "Could not map frame {:?}, page table entry {} is already \
                  in use!", frame, idx);
        pt[idx].set(frame, flags | PRESENT);
    }

}
<|endoftext|>


<commit_before>//!
//! Module for common/shared types of the various [`Device`](::backend::drm::Device)
//! and [`Surface`](::backend::drm::Surface) implementations of the `backend::drm` module.
//!

use drm::control::{connector, crtc, Mode, RawResourceHandle};

use std::path::PathBuf;

pub mod fallback;

/// Errors thrown by the [`LegacyDrmDevice`](::backend::drm::legacy::LegacyDrmDevice),
/// [`AtomicDrmDevice`](::backend::drm::atomic::AtomicDrmDevice)
/// and their surfaces: [`LegacyDrmSurface`](::backend::drm::legacy::LegacyDrmSurface)
/// and [`AtomicDrmSurface`](::backend::drm::atomic::AtomicDrmSurface).
#[derive(thiserror::Error, Debug)]
pub enum Error {
    /// Unable to acquire DRM master
    #[error("Failed to aquire DRM master")]
    DrmMasterFailed,
    /// The `DrmDevice` encountered an access error
    #[error("DRM access error: {errmsg} on device `{dev:?}`")]
    Access {
        /// Error message associated to the access error
        errmsg: &'static str,
        /// Device on which the error was generated
        dev: Option<PathBuf>,
        /// Underlying device error
        source: failure::Compat<drm::SystemError>,
    },
    /// Unable to determine device id of drm device
    #[error("Unable to determine device id of drm device")]
    UnableToGetDeviceId(#[source] nix::Error),
    /// Device is currently paused
    #[error("Device is currently paused, operation rejected")]
    DeviceInactive,
    /// Mode is not compatible with all given connectors
    #[error("Mode `{0:?}` is not compatible with all given connectors")]
    ModeNotSuitable(Mode),
    /// The given crtc is already in use by another backend
    #[error("Crtc `{0:?}` is already in use by another backend")]
    CrtcAlreadyInUse(crtc::Handle),
    /// This operation would result in a surface without connectors.
    #[error("Surface of crtc `{0:?}` would have no connectors, which is not accepted")]
    SurfaceWithoutConnectors(crtc::Handle),
    /// No encoder was found for a given connector on the set crtc
    #[error("No encoder found for the given connector '{connector:?}' on crtc `{crtc:?}`")]
    NoSuitableEncoder {
        /// Connector
        connector: connector::Handle,
        /// CRTC
        crtc: crtc::Handle,
    },
    /// No matching primary and cursor plane could be found for the given crtc
    #[error("No matching primary and cursor plane could be found for crtc {crtc:?} on {dev:?}")]
    NoSuitablePlanes {
        /// CRTC
        crtc: crtc::Handle,
        /// Device on which the error was generated
        dev: Option<PathBuf>,
    },
    /// The DrmDevice is missing a required property
    #[error("The DrmDevice is missing a required property '{name}' for handle ({handle:?})")]
    UnknownProperty {
        /// Property handle
        handle: RawResourceHandle,
        /// Property name
        name: &'static str,
    },
    /// Atomic Test failed for new properties
    #[error("Atomic Test failed for new properties on crtc ({0:?})")]
    TestFailed(crtc::Handle),
}
<commit_msg>drm: Make DRM errors print the actual access error<commit_after>//!
//! Module for common/shared types of the various [`Device`](::backend::drm::Device)
//! and [`Surface`](::backend::drm::Surface) implementations of the `backend::drm` module.
//!

use drm::control::{connector, crtc, Mode, RawResourceHandle};

use std::path::PathBuf;

pub mod fallback;

/// Errors thrown by the [`LegacyDrmDevice`](::backend::drm::legacy::LegacyDrmDevice),
/// [`AtomicDrmDevice`](::backend::drm::atomic::AtomicDrmDevice)
/// and their surfaces: [`LegacyDrmSurface`](::backend::drm::legacy::LegacyDrmSurface)
/// and [`AtomicDrmSurface`](::backend::drm::atomic::AtomicDrmSurface).
#[derive(thiserror::Error, Debug)]
pub enum Error {
    /// Unable to acquire DRM master
    #[error("Failed to aquire DRM master")]
    DrmMasterFailed,
    /// The `DrmDevice` encountered an access error
    #[error("DRM access error: {errmsg} on device `{dev:?}` ({source:})")]
    Access {
        /// Error message associated to the access error
        errmsg: &'static str,
        /// Device on which the error was generated
        dev: Option<PathBuf>,
        /// Underlying device error
        source: failure::Compat<drm::SystemError>,
    },
    /// Unable to determine device id of drm device
    #[error("Unable to determine device id of drm device")]
    UnableToGetDeviceId(#[source] nix::Error),
    /// Device is currently paused
    #[error("Device is currently paused, operation rejected")]
    DeviceInactive,
    /// Mode is not compatible with all given connectors
    #[error("Mode `{0:?}` is not compatible with all given connectors")]
    ModeNotSuitable(Mode),
    /// The given crtc is already in use by another backend
    #[error("Crtc `{0:?}` is already in use by another backend")]
    CrtcAlreadyInUse(crtc::Handle),
    /// This operation would result in a surface without connectors.
    #[error("Surface of crtc `{0:?}` would have no connectors, which is not accepted")]
    SurfaceWithoutConnectors(crtc::Handle),
    /// No encoder was found for a given connector on the set crtc
    #[error("No encoder found for the given connector '{connector:?}' on crtc `{crtc:?}`")]
    NoSuitableEncoder {
        /// Connector
        connector: connector::Handle,
        /// CRTC
        crtc: crtc::Handle,
    },
    /// No matching primary and cursor plane could be found for the given crtc
    #[error("No matching primary and cursor plane could be found for crtc {crtc:?} on {dev:?}")]
    NoSuitablePlanes {
        /// CRTC
        crtc: crtc::Handle,
        /// Device on which the error was generated
        dev: Option<PathBuf>,
    },
    /// The DrmDevice is missing a required property
    #[error("The DrmDevice is missing a required property '{name}' for handle ({handle:?})")]
    UnknownProperty {
        /// Property handle
        handle: RawResourceHandle,
        /// Property name
        name: &'static str,
    },
    /// Atomic Test failed for new properties
    #[error("Atomic Test failed for new properties on crtc ({0:?})")]
    TestFailed(crtc::Handle),
}
<|endoftext|>


<commit_before><commit_msg>Minor<commit_after><|endoftext|>


<commit_before>use super::Operation;
use buffer::GapBuffer;

/// A collection of operations that are run as a single/atomic operation. Useful for
/// composing related actions as a single event, from a history/undo standpoint.
pub struct OperationGroup {
    operations: Vec<Box<Operation>>,
}

impl Operation for OperationGroup {
    /// Runs all of the group's individual operations, in order.
    fn run(&mut self, buffer: &mut GapBuffer) {
        for operation in &mut self.operations {
            operation.run(buffer);
        }
    }

    /// Reverses all of the group's individual operations, in reverse order.
    fn reverse(&mut self, buffer: &mut GapBuffer) {
        for operation in &mut self.operations.iter_mut().rev() {
            operation.reverse(buffer);
        }
    }
}

impl OperationGroup {
    /// Adds an operation to the group.
    pub fn add(&mut self, operation: Box<Operation>) {
        self.operations.push(operation);
    }
}

pub fn new() -> OperationGroup {
    OperationGroup{ operations: Vec::new() }
}

#[cfg(test)]
mod tests {
    use super::new;
    use buffer::operations::insert;
    use buffer::Position;
    use buffer::operation::Operation;

    #[test]
    fn run_and_reverse_call_themselves_on_all_operations() {
        let mut group = new();
        let mut buffer = ::buffer::gap_buffer::new(String::new());

        // Push two insert operations into the group.
        let mut first = Box::new(insert::new("something".to_string(), Position{ line: 0, offset: 0 }));
        let mut second = Box::new(insert::new(" else".to_string(), Position{ line: 0, offset: 9 }));
        group.add(first);
        group.add(second);

        // Run the operation group.
        group.run(&mut buffer);

        assert_eq!(buffer.to_string(), "something else");

        // Reverse the operation group.
        group.reverse(&mut buffer);

        assert_eq!(buffer.to_string(), "");
    }
}
<commit_msg>Implent clone_operation for operation group type.<commit_after>use super::Operation;
use buffer::GapBuffer;

/// A collection of operations that are run as a single/atomic operation. Useful for
/// composing related actions as a single event, from a history/undo standpoint.
pub struct OperationGroup {
    operations: Vec<Box<Operation>>,
}

impl Operation for OperationGroup {
    /// Runs all of the group's individual operations, in order.
    fn run(&mut self, buffer: &mut GapBuffer) {
        for operation in &mut self.operations {
            operation.run(buffer);
        }
    }

    /// Reverses all of the group's individual operations, in reverse order.
    fn reverse(&mut self, buffer: &mut GapBuffer) {
        for operation in &mut self.operations.iter_mut().rev() {
            operation.reverse(buffer);
        }
    }

    /// Build a new operation group by manually cloning all of the groups individual operations.
    /// We can't derive this because operations are unsized and need some hand holding.
    fn clone_operation(&self) -> Box<Operation> {
        Box::new(OperationGroup{
            operations: self.operations.iter().map(|o| (*o).clone_operation()).collect()
        })
    }
}

impl OperationGroup {
    /// Adds an operation to the group.
    pub fn add(&mut self, operation: Box<Operation>) {
        self.operations.push(operation);
    }
}

pub fn new() -> OperationGroup {
    OperationGroup{ operations: Vec::new() }
}

#[cfg(test)]
mod tests {
    use super::new;
    use buffer::operations::insert;
    use buffer::Position;
    use buffer::operation::Operation;

    #[test]
    fn run_and_reverse_call_themselves_on_all_operations() {
        let mut group = new();
        let mut buffer = ::buffer::gap_buffer::new(String::new());

        // Push two insert operations into the group.
        let mut first = Box::new(insert::new("something".to_string(), Position{ line: 0, offset: 0 }));
        let mut second = Box::new(insert::new(" else".to_string(), Position{ line: 0, offset: 9 }));
        group.add(first);
        group.add(second);

        // Run the operation group.
        group.run(&mut buffer);

        assert_eq!(buffer.to_string(), "something else");

        // Reverse the operation group.
        group.reverse(&mut buffer);

        assert_eq!(buffer.to_string(), "");
    }
}
<|endoftext|>


<commit_before>/* This file is part of rpds.
 *
 * Foobar is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * rpds is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with rpds.  If not, see <http://www.gnu.org/licenses/>.
 */

use std::rc::Rc;
use std::fmt::Display;
use std::borrow::Borrow;

#[derive(Debug)]
pub struct List<T> {
    node: Rc<ListNode<T>>,
}

#[derive(Debug)]
enum ListNode<T> {
    Cons(T, Rc<ListNode<T>>),
    Nil,
}

impl<T> List<T> {
    pub fn new() -> List<T> {
        List {
            node: Rc::new(ListNode::Nil)
        }
    }

    pub fn head(&self) -> Option<&T> {
        match *self.node {
            ListNode::Cons(ref h, _) => Some(h),
            ListNode::Nil            => None,
        }
    }

    pub fn tail(&self) -> Option<List<T>> {
        match *self.node {
            ListNode::Cons(_, ref t) => Some(List { node: t.clone() }),
            ListNode::Nil            => None,
        }
    }

    pub fn cons(&self, v: T) -> List<T> {
        List {
            node: Rc::new(ListNode::Cons(v, self.node.clone()))
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            next: self.node.borrow()
        }
    }
}

impl<T> Display for List<T>
    where T: Display {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        fmt.write_str("[")?;

        let mut first = true;

        for v in self.iter() {
            if !first {
                fmt.write_str(", ")?;
            }
            v.fmt(fmt)?;
            first = false;
        }

        fmt.write_str("]")
    }
}

pub struct Iter<'a, T: 'a> {
    next: &'a ListNode<T>
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        match *self.next {
            ListNode::Cons(ref v, ref t) => {
                self.next = t;
                Some(v)
            },
            ListNode::Nil => None
        }
    }
}

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

    #[test]
    fn test_display() -> () {
        let empty_list: List<i32> = List::new();
        let singleton_list = List::new()
            .cons("hello");
        let list = List::new()
            .cons(3)
            .cons(2)
            .cons(1)
            .cons(0);

        assert_eq!(format!("{}", empty_list), "[]");
        assert_eq!(format!("{}", singleton_list), "[hello]");
        assert_eq!(format!("{}", list), "[0, 1, 2, 3]");
    }

    // TODO more tests.
}

/* TODO
 *
 * Implement traits:
 *  - impl<T> Sync for List<T> where T: Sync
 *  - impl<T> Send for List<T> where T: Send
 *  - impl<T> IntoIterator for List<T>
 *  - impl<'a, T> IntoIterator for &'a List<T>
 *  - impl<T> FromIterator<T> for LinkedList<T>
 *  - impl<T> Ord for List<T> where T: Ord
 *  - impl<T> Eq for List<T> where T: Eq
 *  - impl<T> PartialEq<List<T>> for List<T> where T: PartialEq<T>
 *  - impl<T> Clone for List<T> where T: Clone
 *  - impl<T> PartialOrd<List<T>> for List<T> where T: PartialOrd<T>
 *  - impl<T> Hash for List<T> where T: Hash
 *  - impl<T> Default for List<T>
 *
 *  for the Vector we also want extend (see https://doc.rust-lang.org/std/collections/struct.LinkedList.html)
 *  - impl<T> Debug for List<T> where T: Debug
 *  - impl<T> Display for List<T> where T: Display
 */
<commit_msg>Added more tests to list.<commit_after>/* This file is part of rpds.
 *
 * Foobar is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * rpds is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with rpds.  If not, see <http://www.gnu.org/licenses/>.
 */

use std::rc::Rc;
use std::fmt::Display;
use std::borrow::Borrow;

#[derive(Debug)]
pub struct List<T> {
    node: Rc<Node<T>>,
}

#[derive(Debug)]
enum Node<T> {
    Cons(T, Rc<Node<T>>),
    Nil,
}

impl<T> List<T> {
    pub fn new() -> List<T> {
        List {
            node: Rc::new(Node::Nil)
        }
    }

    pub fn head(&self) -> Option<&T> {
        match *self.node {
            Node::Cons(ref h, _) => Some(h),
            Node::Nil            => None,
        }
    }

    pub fn tail(&self) -> Option<List<T>> {
        match *self.node {
            Node::Cons(_, ref t) => Some(List { node: t.clone() }),
            Node::Nil            => None,
        }
    }

    pub fn cons(&self, v: T) -> List<T> {
        List {
            node: Rc::new(Node::Cons(v, self.node.clone()))
        }
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            next: self.node.borrow()
        }
    }
}

impl<'a, T> IntoIterator for &'a List<T> {
    type Item = &'a T;
    type IntoIter = Iter<'a, T>;

    fn into_iter(self) -> Iter<'a, T> {
        self.iter()
    }
}

impl<T> Display for List<T>
    where T: Display {
    fn fmt(&self, fmt: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
        fmt.write_str("[")?;

        let mut first = true;

        for v in self.iter() {
            if !first {
                fmt.write_str(", ")?;
            }
            v.fmt(fmt)?;
            first = false;
        }

        fmt.write_str("]")
    }
}

pub struct Iter<'a, T: 'a> {
    next: &'a Node<T>
}

impl<'a, T> Iterator for Iter<'a, T> {
    type Item = &'a T;

    fn next(&mut self) -> Option<&'a T> {
        match *self.next {
            Node::Cons(ref v, ref t) => {
                self.next = t;
                Some(v)
            },
            Node::Nil => None
        }
    }
}

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

    #[test]
    fn test_new() -> () {
        let empty_list: List<i32> = List::new();

        match *empty_list.node {
            Node::Nil => (),
            _         => panic!("should be nil"),
        }
    }

    #[test]
    fn test_head() -> () {
        let empty_list: List<i32> = List::new();
        let singleton_list = List::new()
            .cons("hello");
        let list = List::new()
            .cons(3)
            .cons(2)
            .cons(1)
            .cons(0);

        assert_eq!(empty_list.head(), None);
        assert_eq!(singleton_list.head(), Some(&"hello"));
        assert_eq!(list.head(), Some(&0));
    }

    #[test]
    fn test_tail() -> () {
        let empty_list: List<i32> = List::new();
        let singleton_list = List::new()
            .cons("hello");
        let list = List::new()
            .cons(3)
            .cons(2)
            .cons(1)
            .cons(0);

        assert!(empty_list.tail().is_none());
        assert_eq!(singleton_list.tail().unwrap().head(), None);
        assert_eq!(list.tail().unwrap().head(), Some(&1));
    }

    #[test]
    fn test_display() -> () {
        let empty_list: List<i32> = List::new();
        let singleton_list = List::new()
            .cons("hello");
        let list = List::new()
            .cons(3)
            .cons(2)
            .cons(1)
            .cons(0);

        assert_eq!(format!("{}", empty_list), "[]");
        assert_eq!(format!("{}", singleton_list), "[hello]");
        assert_eq!(format!("{}", list), "[0, 1, 2, 3]");
    }

    #[test]
    fn test_into_iterator() -> () {
        let list = List::new()
            .cons(3)
            .cons(2)
            .cons(1)
            .cons(0);
        let mut expected = 0;
        let mut left = 4;

        for n in &list {
            left -= 1;

            assert!(left >= 0);
            assert_eq!(*n, expected);

            expected += 1;
        }
    }
}

/* TODO
 *
 * Implement traits:
 *  - impl<T> Sync for List<T> where T: Sync
 *  - impl<T> Send for List<T> where T: Send
 *  - impl<T> IntoIterator for List<T>
 *  - impl<'a, T> IntoIterator for &'a List<T>
 *  - impl<T> FromIterator<T> for LinkedList<T>
 *  - impl<T> Ord for List<T> where T: Ord
 *  - impl<T> Eq for List<T> where T: Eq
 *  - impl<T> PartialEq<List<T>> for List<T> where T: PartialEq<T>
 *  - impl<T> Clone for List<T> where T: Clone
 *  - impl<T> PartialOrd<List<T>> for List<T> where T: PartialOrd<T>
 *  - impl<T> Hash for List<T> where T: Hash
 *  - impl<T> Default for List<T>
 *
 *  for the Vector we also want extend (see https://doc.rust-lang.org/std/collections/struct.LinkedList.html)
 *  - impl<T> Debug for List<T> where T: Debug
 *  - impl<T> Display for List<T> where T: Display
 */
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use construct::ConstructionResult;
use script_layout_interface::PartialPersistentLayoutData;

/// Data that layout associates with a node.
pub struct PersistentLayoutData {
    /// Data accessed by script_layout_interface. This must be first to allow
    /// casting between PersistentLayoutData and PartialPersistentLayoutData.
    pub base: PartialPersistentLayoutData,

    /// The current results of flow construction for this node. This is either a
    /// flow or a `ConstructionItem`. See comments in `construct.rs` for more
    /// details.
    pub flow_construction_result: ConstructionResult,

    pub before_flow_construction_result: ConstructionResult,

    pub after_flow_construction_result: ConstructionResult,

    pub details_summary_flow_construction_result: ConstructionResult,

    pub details_content_flow_construction_result: ConstructionResult,

    /// Various flags.
    pub flags: LayoutDataFlags,
}

impl PersistentLayoutData {
    /// Creates new layout data.
    pub fn new() -> PersistentLayoutData {
        PersistentLayoutData {
            base: PartialPersistentLayoutData::new(),
            flow_construction_result: ConstructionResult::None,
            before_flow_construction_result: ConstructionResult::None,
            after_flow_construction_result: ConstructionResult::None,
            details_summary_flow_construction_result: ConstructionResult::None,
            details_content_flow_construction_result: ConstructionResult::None,
            flags: LayoutDataFlags::empty(),
        }
    }
}

bitflags! {
    pub flags LayoutDataFlags: u8 {
        #[doc = "Whether a flow has been newly constructed."]
        const HAS_NEWLY_CONSTRUCTED_FLOW = 0x01,
        #[doc = "Whether this node has been traversed by layout."]
        const HAS_BEEN_TRAVERSED = 0x02,
    }
}
<commit_msg><commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use construct::ConstructionResult;
use script_layout_interface::PartialPersistentLayoutData;

/// Data that layout associates with a node.
#[repr(C)]
pub struct PersistentLayoutData {
    /// Data accessed by script_layout_interface. This must be first to allow
    /// casting between PersistentLayoutData and PartialPersistentLayoutData.
    pub base: PartialPersistentLayoutData,

    /// The current results of flow construction for this node. This is either a
    /// flow or a `ConstructionItem`. See comments in `construct.rs` for more
    /// details.
    pub flow_construction_result: ConstructionResult,

    pub before_flow_construction_result: ConstructionResult,

    pub after_flow_construction_result: ConstructionResult,

    pub details_summary_flow_construction_result: ConstructionResult,

    pub details_content_flow_construction_result: ConstructionResult,

    /// Various flags.
    pub flags: LayoutDataFlags,
}

impl PersistentLayoutData {
    /// Creates new layout data.
    pub fn new() -> PersistentLayoutData {
        PersistentLayoutData {
            base: PartialPersistentLayoutData::new(),
            flow_construction_result: ConstructionResult::None,
            before_flow_construction_result: ConstructionResult::None,
            after_flow_construction_result: ConstructionResult::None,
            details_summary_flow_construction_result: ConstructionResult::None,
            details_content_flow_construction_result: ConstructionResult::None,
            flags: LayoutDataFlags::empty(),
        }
    }
}

bitflags! {
    pub flags LayoutDataFlags: u8 {
        #[doc = "Whether a flow has been newly constructed."]
        const HAS_NEWLY_CONSTRUCTED_FLOW = 0x01,
        #[doc = "Whether this node has been traversed by layout."]
        const HAS_BEEN_TRAVERSED = 0x02,
    }
}
<|endoftext|>


<commit_before>use super::{Event, Max, Min, Prop, Mod, FDVar, Propagator};

#[cfg(test)]
use super::{Model, Var};

use std::rc::{Rc, Weak};

#[allow(dead_code)]
pub struct LtXY;

#[allow(dead_code)]
impl LtXY {
    pub fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>) {
        LtXYx::new(model.clone(), x.clone(), y.clone());
        LtXYy::new(model.clone(), x.clone(), y.clone());
    }
}

struct LtXYx : Prop;

#[allow(dead_code)]
impl LtXYx {
    fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>) -> Rc<Box<Propagator>> {
        let id = model.propagators.borrow().len();
        let this = LtXYx { model: model.downgrade(), id: id, vars: vec![x, y]};
        this.register();
        this.propagate();
        let p = Rc::new((box this) as Box<Propagator>);
        model.add_prop(p.clone());
        p
    }

    fn x(&self) -> Rc<FDVar> {
        self.vars.get(0).clone()
    }

    fn y(&self) -> Rc<FDVar> {
        self.vars.get(1).clone()
    }
}

impl Propagator for LtXYx {
    fn id(&self) -> uint {
        self.id
    }
    fn model(&self) -> Weak<Mod> {
        self.model.clone()
    }

    fn events(&self) -> Vec<(uint, Event)> {
        vec![(self.y().id, Max)]
    }

    fn propagate(&self) -> Vec<uint> {
        if self.x().max() < self.y().min() {
            // entailed
            self.unregister();
            vec![]
        } else if self.x().max() > self.y().max() - 1 {
            //if y.is_instanciated() {
            //   self.unregister();
            //}
            let max = self.y().max() - 1;
            self.x().set_max(max)
        } else {
            vec![]
        }
    }
}

struct LtXYy : Prop;

#[allow(dead_code)]
impl LtXYy {
    fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>) -> Rc<Box<Propagator>> {
        let id = model.propagators.borrow().len();
        let this = LtXYy { model: model.downgrade(), id: id, vars: vec![x, y]};
        this.register();
        this.propagate();
        let p = Rc::new((box this) as Box<Propagator>);
        model.add_prop(p.clone());
        p
    }

    fn x(&self) -> Rc<FDVar> {
        self.vars.get(0).clone()
    }

    fn y(&self) -> Rc<FDVar> {
        self.vars.get(1).clone()
    }
}

impl Propagator for LtXYy {
    fn id(&self) -> uint {
        self.id
    }
    fn model(&self) -> Weak<Mod> {
        self.model.clone()
    }

    fn events(&self) -> Vec<(uint, Event)> {
        vec![(self.x().id, Min)]
    }

    fn propagate(&self) -> Vec<uint> {
        if self.x().max() < self.y().min() {
            // entailed
            self.unregister();
            vec![]
        } else if self.y().min() < self.x().min() + 1 {
            //if y.is_instanciated() {
            //   self.unregister();
            //}
            let min = self.x().min() + 1;
            self.y().set_min(min)
        } else {
            vec![]
        }
    }
}

#[test]
fn it_does_propagate() {
    let m = Model::new();
    let x = Var::new(m.clone(), -2, 255, "x");
    let y = Var::new(m.clone(), -2, 255, "y");
    let p1 = LtXYx::new(m.clone(), x.clone(), y.clone());
    assert!(p1.id() == 0);
    assert!(x.max() == 254);
    let p2 = LtXYy::new(m.clone(), x.clone(), y.clone());
    assert!(p2.id() == 1);
    assert!(y.min() == -1);
}
<commit_msg>x < y + c<commit_after>use super::{Event, Max, Min, Prop, Mod, FDVar, Propagator};

#[cfg(test)]
use super::{Model, Var};

use std::rc::{Rc, Weak};

#[allow(dead_code)]
/// X < Y
pub struct LtXY;

#[allow(dead_code)]
/// X < Y + C
pub struct LtXYC;

#[allow(dead_code)]
impl LtXY {
    pub fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>) {
        LtXYC::new(model, x, y, 0);
    }
}

#[allow(dead_code)]
impl LtXYC {
    pub fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>, c: int) {
        LtXYCx::new(model.clone(), x.clone(), y.clone(), c);
        LtXYCy::new(model.clone(), x.clone(), y.clone(), c);
    }
}

struct LtXYCx : Prop {
    c: int
}

#[allow(dead_code)]
impl LtXYCx {
    fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>, c: int) -> Rc<Box<Propagator>> {
        let id = model.propagators.borrow().len();
        let this = LtXYCx { model: model.downgrade(), id: id, vars: vec![x, y], c: c};
        this.register();
        this.propagate();
        let p = Rc::new((box this) as Box<Propagator>);
        model.add_prop(p.clone());
        p
    }

    fn x(&self) -> Rc<FDVar> {
        self.vars.get(0).clone()
    }

    fn y(&self) -> Rc<FDVar> {
        self.vars.get(1).clone()
    }
}

impl Propagator for LtXYCx {
    fn id(&self) -> uint {
        self.id
    }
    fn model(&self) -> Weak<Mod> {
        self.model.clone()
    }

    fn events(&self) -> Vec<(uint, Event)> {
        vec![(self.y().id, Max)]
    }

    fn propagate(&self) -> Vec<uint> {
        if self.x().max() < self.y().min() + self.c {
            // entailed
            self.unregister();
            vec![]
        } else if self.x().max() > self.y().max() + self.c - 1 {
            //if y.is_instanciated() {
            //   self.unregister();
            //}
            let max = self.y().max() + self.c - 1;
            self.x().set_max(max)
        } else {
            vec![]
        }
    }
}

struct LtXYCy : Prop {
    c: int
}

#[allow(dead_code)]
impl LtXYCy {
    fn new(model: Rc<Mod>, x: Rc<FDVar>, y: Rc<FDVar>, c: int) -> Rc<Box<Propagator>> {
        let id = model.propagators.borrow().len();
        let this = LtXYCy { model: model.downgrade(), id: id, vars: vec![x, y], c: c};
        this.register();
        this.propagate();
        let p = Rc::new((box this) as Box<Propagator>);
        model.add_prop(p.clone());
        p
    }

    fn x(&self) -> Rc<FDVar> {
        self.vars.get(0).clone()
    }

    fn y(&self) -> Rc<FDVar> {
        self.vars.get(1).clone()
    }
}

impl Propagator for LtXYCy {
    fn id(&self) -> uint {
        self.id
    }
    fn model(&self) -> Weak<Mod> {
        self.model.clone()
    }

    fn events(&self) -> Vec<(uint, Event)> {
        vec![(self.x().id, Min)]
    }

    fn propagate(&self) -> Vec<uint> {
        if self.x().max() < self.y().min() + self.c {
            // entailed
            self.unregister();
            vec![]
        } else if self.y().min() < self.x().min() - self.c + 1 {
            //if y.is_instanciated() {
            //   self.unregister();
            //}
            let min = self.x().min() - self.c + 1;
            self.y().set_min(min)
        } else {
            vec![]
        }
    }
}

#[test]
fn it_does_propagate() {
    let m = Model::new();
    let x = Var::new(m.clone(), -2, 255, "x");
    let y = Var::new(m.clone(), -2, 255, "y");
    let p1 = LtXYCx::new(m.clone(), x.clone(), y.clone(), -2);
    assert!(p1.id() == 0);
    assert!(x.max() == 252);
    let p2 = LtXYCy::new(m.clone(), x.clone(), y.clone(), -2);
    assert!(p2.id() == 1);
    assert!(y.min() == 1);
}
<|endoftext|>


<commit_before>#![allow(unstable)]

use std::os;
use std::str::StrExt;
use std::old_io::File;
use tokenizer::Tokenizer;
use interpreter::Interpreter;

mod tokenizer;
mod operations;
mod interpreter;

fn main() {
    let arguments = os::args();
    match arguments.get(1) {
        Some(ref filename) => {
            match File::open(&Path::new(filename)).read_to_string() {
                Ok(s) => {
                    // TODO: I think we can make it simpler
                    let words: Vec<String> = s.replace("\n", " ").split(' ').collect::<Vec<&str>>().iter().map(|s| (*s).to_string()).collect();
                    let mut tokenizer = Tokenizer::new(words);
                    let ops = tokenizer.tokenize();
                    let mut interpreter = Interpreter::new(ops);
                    interpreter.run();
                },
                Err(error) => panic!("{}", error),
            }
        },
        None => println!("Usage: groot file.groot"),
    }
}
<commit_msg>BACON!<commit_after>#![allow(unstable)]

use std::os;
use std::str::StrExt;
use std::old_io::File;
use tokenizer::Tokenizer;
use interpreter::Interpreter;

mod tokenizer;
mod operations;
mod interpreter;

fn main() {
    let arguments = os::args();
    match arguments.get(1) {
        Some(ref filename) => {
            match File::open(&Path::new(filename)).read_to_string() {
                Ok(s) => {
                    // TODO: I think we can make it simpler
                    let words: Vec<String> = s.replace("\n", " ").split(' ').collect::<Vec<&str>>().iter().map(|s| (*s).to_string()).collect();
                    let mut tokenizer = Tokenizer::new(words);
                    let ops = tokenizer.tokenize();
                    let mut interpreter = Interpreter::new(ops);
                    interpreter.run();
                },
                Err(error) => panic!("{}", error),
            }
        },
        None => println!("Usage: bacon file.bacon"),
    }
}
<|endoftext|>


<commit_before>extern crate time;
use time::{Timespec, Duration};
use std::thread;
use std::ops::Add;
use std::io::{self, Write, Read};

macro_rules! printfl {
    ($($tt:tt)*) => {{
        use std::io::{self, Write};
        print!($($tt)*);
        io::stdout().flush().ok().expect("flush() fail");
    }}
}

pub struct ProgressBar {
    start_time: Timespec,
    total: usize,
    current: usize,
    is_finish: bool,
}

impl ProgressBar {
    pub fn new(total: usize) -> ProgressBar {
            ProgressBar {
                total: total,
                current: 0,
                start_time: time::get_time(),
                is_finish: false,
            }
    }

    fn add(&mut self, i: usize) -> usize {
        self.current += i;
        if self.current <= self.total {
            self.draw()
        };
        self.current
    }

    fn draw(&self) {
        let width = 143;    // replace to -> get_tty_size()
        let percent_box;
        let counter_box;
        let mut time_left_box = format!("");
        let speed_box;
        let mut bar_box = "[".to_string();
        let mut out;
        // precent box
        let percent = self.current as f64 / (self.total as f64 / 100f64);
        percent_box = format!(" {:.*} % ", 2, percent);
        // counter box
        counter_box = format!("{} / {} ", self.current, self.total);
        // time left box
        let from_start = time::get_time() - self.start_time;
        let per_entry = from_start / self.current as i32; // Why the hack
        let mut left = per_entry * (self.total - self.current) as i32;
        let sec_nano = Duration::seconds(1).num_nanoseconds().unwrap() as i32;
        left = (left / sec_nano) * sec_nano;
        if left.num_seconds() > 0 {
            time_left_box = format!("{}s", left.num_seconds());
        }
        // NOT WORKING: speed box
        let speed = (from_start / sec_nano) / self.current as i32;
        speed_box = format!("{}/s", speed.num_nanoseconds().unwrap() as f64);
        // bar_box - Add prefix & suffix(2)
        let size = width -
                   (percent_box.to_string() + &counter_box + &time_left_box + &speed_box).len();
        // Test if size > 0
        let curr_count = ((self.current as f64 / self.total as f64) * size as f64).ceil();
        let err_count = size as f64 - curr_count;
        bar_box = bar_box + &std::iter::repeat("=").take(curr_count as usize).collect::<String>();
        if self.current < self.total {
            bar_box = bar_box + ">";
        } else {
            bar_box = bar_box + "=";
        }
        bar_box = bar_box + &std::iter::repeat("-").take(err_count as usize).collect::<String>() +
                  "]";
        out = counter_box.to_string() + &bar_box + &percent_box + &time_left_box;
        // Print
        if out.len() < width {
            let gap = width - out.len();
            out = out + &std::iter::repeat(" ").take(gap as usize).collect::<String>();
        }
        printfl!("\r{}", out);
    }

    fn finish(&mut self) {
        if self.current < self.total {
            self.current = self.total;
            self.draw();
        }
        println!("");
        self.is_finish = true;
    }
}

// Implement io::Writer
impl Write for ProgressBar {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = buf.len();
        self.add(n);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

// TODO: Implement io::Reader

fn main() {
    let mut pb = ProgressBar::new(1000);
    for _ in 0..1000 {
        pb.add(1);
        thread::sleep_ms(2);
    }
    pb.finish();
    print!("The end!");

    /*let name = "/usr/share/dict/words";
    let mut file = std::fs::File::open(name).unwrap();
    let bytes = std::fs::metadata(name).unwrap().len() as i64;
    let mut pb = ProgressBar::new(bytes);
    std::io::copy(&mut file, &mut pb).unwrap();
    println!("Done");
    // Create example that use multiWriter and decorateWriter example too
    */
}
<commit_msg>config<commit_after>extern crate time;
use time::{Timespec, Duration};
use std::thread;
use std::ops::Add;
use std::io::{self, Write, Read};

macro_rules! printfl {
    ($($tt:tt)*) => {{
        use std::io::{self, Write};
        print!($($tt)*);
        io::stdout().flush().ok().expect("flush() fail");
    }}
}

pub struct ProgressBar {
    start_time: Timespec,
    total: usize,
    current: usize,
    is_finish: bool,
    show_bar: bool,
    show_speed: bool,
    show_percent: bool,
    show_counter: bool,
    show_time_left: bool,
}

impl ProgressBar {
    pub fn new(total: usize) -> ProgressBar {
            ProgressBar {
                total: total,
                current: 0,
                start_time: time::get_time(),
                is_finish: false,
                show_bar: true,
                show_speed: false,
                show_percent: true,
                show_counter: true,
                show_time_left: true,
            }
    }

    fn add(&mut self, i: usize) -> usize {
        self.current += i;
        if self.current <= self.total {
            self.draw()
        };
        self.current
    }

    fn draw(&self) {
        let width = 143;    // replace to -> get_tty_size()
        let percent_box;
        let counter_box;
        let mut time_left_box = format!("");
        let speed_box;
        let mut bar_box = "[".to_string();
        let mut out;
        // precent box
        let percent = self.current as f64 / (self.total as f64 / 100f64);
        percent_box = format!(" {:.*} % ", 2, percent);
        // counter box
        counter_box = format!("{} / {} ", self.current, self.total);
        // time left box
        let from_start = time::get_time() - self.start_time;
        let per_entry = from_start / self.current as i32; // Why the hack
        let mut left = per_entry * (self.total - self.current) as i32;
        let sec_nano = Duration::seconds(1).num_nanoseconds().unwrap() as i32;
        left = (left / sec_nano) * sec_nano;
        if left.num_seconds() > 0 {
            time_left_box = format!("{}s", left.num_seconds());
        }
        // NOT WORKING: speed box
        let speed = (from_start / sec_nano) / self.current as i32;
        speed_box = format!("{}/s", speed.num_nanoseconds().unwrap() as f64);
        // bar_box - Add prefix & suffix(2)
        let size = width -
                   (percent_box.to_string() + &counter_box + &time_left_box + &speed_box).len();
        // Test if size > 0
        let curr_count = ((self.current as f64 / self.total as f64) * size as f64).ceil();
        let err_count = size as f64 - curr_count;
        bar_box = bar_box + &std::iter::repeat("=").take(curr_count as usize).collect::<String>();
        if self.current < self.total {
            bar_box = bar_box + ">";
        } else {
            bar_box = bar_box + "=";
        }
        bar_box = bar_box + &std::iter::repeat("-").take(err_count as usize).collect::<String>() +
                  "]";
        out = counter_box.to_string() + &bar_box + &percent_box + &time_left_box;
        // Print
        if out.len() < width {
            let gap = width - out.len();
            out = out + &std::iter::repeat(" ").take(gap as usize).collect::<String>();
        }
        printfl!("\r{}", out);
    }

    fn finish(&mut self) {
        if self.current < self.total {
            self.current = self.total;
            self.draw();
        }
        println!("");
        self.is_finish = true;
    }
}

// Implement io::Writer
impl Write for ProgressBar {
    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
        let n = buf.len();
        self.add(n);
        Ok(buf.len())
    }
    fn flush(&mut self) -> io::Result<()> {
        Ok(())
    }
}

// TODO: Implement io::Reader

fn main() {
    let mut pb = ProgressBar::new(1000);
    for _ in 0..1000 {
        pb.add(1);
        thread::sleep_ms(2);
    }
    pb.finish();
    print!("The end!");

    /*let name = "/usr/share/dict/words";
    let mut file = std::fs::File::open(name).unwrap();
    let bytes = std::fs::metadata(name).unwrap().len() as i64;
    let mut pb = ProgressBar::new(bytes);
    std::io::copy(&mut file, &mut pb).unwrap();
    println!("Done");
    // Create example that use multiWriter and decorateWriter example too
    */
}
<|endoftext|>