<commit_before>use scope;
use std::any::Any;
use std::sync::mpsc::channel;
use std::sync::Mutex;

use super::{spawn, spawn_fifo};
use ThreadPoolBuilder;

#[test]
fn spawn_then_join_in_worker() {
    let (tx, rx) = channel();
    scope(move |_| {
        spawn(move || tx.send(22).unwrap());
    });
    assert_eq!(22, rx.recv().unwrap());
}

#[test]
fn spawn_then_join_outside_worker() {
    let (tx, rx) = channel();
    spawn(move || tx.send(22).unwrap());
    assert_eq!(22, rx.recv().unwrap());
}

#[test]
fn panic_fwd() {
    let (tx, rx) = channel();

    let tx = Mutex::new(tx);
    let panic_handler = move |err: Box<Any + Send>| {
        let tx = tx.lock().unwrap();
        if let Some(&msg) = err.downcast_ref::<&str>() {
            if msg == "Hello, world!" {
                tx.send(1).unwrap();
            } else {
                tx.send(2).unwrap();
            }
        } else {
            tx.send(3).unwrap();
        }
    };

    let builder = ThreadPoolBuilder::new().panic_handler(panic_handler);

    builder
        .build()
        .unwrap()
        .spawn(move || panic!("Hello, world!"));

    assert_eq!(1, rx.recv().unwrap());
}

/// Test what happens when the thread-pool is dropped but there are
/// still active asynchronous tasks. We expect the thread-pool to stay
/// alive and executing until those threads are complete.
#[test]
fn termination_while_things_are_executing() {
    let (tx0, rx0) = channel();
    let (tx1, rx1) = channel();

    // Create a thread-pool and spawn some code in it, but then drop
    // our reference to it.
    {
        let thread_pool = ThreadPoolBuilder::new().build().unwrap();
        thread_pool.spawn(move || {
            let data = rx0.recv().unwrap();

            // At this point, we know the "main" reference to the
            // `ThreadPool` has been dropped, but there are still
            // active threads. Launch one more.
            spawn(move || {
                tx1.send(data).unwrap();
            });
        });
    }

    tx0.send(22).unwrap();
    let v = rx1.recv().unwrap();
    assert_eq!(v, 22);
}

#[test]
fn custom_panic_handler_and_spawn() {
    let (tx, rx) = channel();

    // Create a parallel closure that will send panics on the
    // channel; since the closure is potentially executed in parallel
    // with itself, we have to wrap `tx` in a mutex.
    let tx = Mutex::new(tx);
    let panic_handler = move |e: Box<Any + Send>| {
        tx.lock().unwrap().send(e).unwrap();
    };

    // Execute an async that will panic.
    let builder = ThreadPoolBuilder::new().panic_handler(panic_handler);
    builder.build().unwrap().spawn(move || {
        panic!("Hello, world!");
    });

    // Check that we got back the panic we expected.
    let error = rx.recv().unwrap();
    if let Some(&msg) = error.downcast_ref::<&str>() {
        assert_eq!(msg, "Hello, world!");
    } else {
        panic!("did not receive a string from panic handler");
    }
}

#[test]
fn custom_panic_handler_and_nested_spawn() {
    let (tx, rx) = channel();

    // Create a parallel closure that will send panics on the
    // channel; since the closure is potentially executed in parallel
    // with itself, we have to wrap `tx` in a mutex.
    let tx = Mutex::new(tx);
    let panic_handler = move |e| {
        tx.lock().unwrap().send(e).unwrap();
    };

    // Execute an async that will (eventually) panic.
    const PANICS: usize = 3;
    let builder = ThreadPoolBuilder::new().panic_handler(panic_handler);
    builder.build().unwrap().spawn(move || {
        // launch 3 nested spawn-asyncs; these should be in the same
        // thread-pool and hence inherit the same panic handler
        for _ in 0..PANICS {
            spawn(move || {
                panic!("Hello, world!");
            });
        }
    });

    // Check that we get back the panics we expected.
    for _ in 0..PANICS {
        let error = rx.recv().unwrap();
        if let Some(&msg) = error.downcast_ref::<&str>() {
            assert_eq!(msg, "Hello, world!");
        } else {
            panic!("did not receive a string from panic handler");
        }
    }
}

macro_rules! test_order {
    ($outer_spawn:ident, $inner_spawn:ident) => {{
        let builder = ThreadPoolBuilder::new().num_threads(1);
        let pool = builder.build().unwrap();
        let (tx, rx) = channel();
        pool.install(move || {
            for i in 0..10 {
                let tx = tx.clone();
                $outer_spawn(move || {
                    for j in 0..10 {
                        let tx = tx.clone();
                        $inner_spawn(move || {
                            tx.send(i * 10 + j).unwrap();
                        });
                    }
                });
            }
        });
        rx.iter().collect::<Vec<i32>>()
    }};
}

#[test]
fn lifo_order() {
    // In the absense of stealing, `spawn()` jobs on a thread will run in LIFO order.
    let vec = test_order!(spawn, spawn);
    let expected: Vec<i32> = (0..100).rev().collect(); // LIFO -> reversed
    assert_eq!(vec, expected);
}

#[test]
fn fifo_order() {
    // In the absense of stealing, `spawn_fifo()` jobs on a thread will run in FIFO order.
    let vec = test_order!(spawn_fifo, spawn_fifo);
    let expected: Vec<i32> = (0..100).collect(); // FIFO -> natural order
    assert_eq!(vec, expected);
}

#[test]
fn lifo_fifo_order() {
    // LIFO on the outside, FIFO on the inside
    let vec = test_order!(spawn, spawn_fifo);
    let expected: Vec<i32> = (0..10)
        .rev()
        .flat_map(|i| (0..10).map(move |j| i * 10 + j))
        .collect();
    assert_eq!(vec, expected);
}

#[test]
fn fifo_lifo_order() {
    // FIFO on the outside, LIFO on the inside
    let vec = test_order!(spawn_fifo, spawn);
    let expected: Vec<i32> = (0..10)
        .flat_map(|i| (0..10).rev().map(move |j| i * 10 + j))
        .collect();
    assert_eq!(vec, expected);
}
<commit_msg>add tests mixing global spawns<commit_after>use scope;
use std::any::Any;
use std::sync::mpsc::channel;
use std::sync::Mutex;

use super::{spawn, spawn_fifo};
use ThreadPoolBuilder;

#[test]
fn spawn_then_join_in_worker() {
    let (tx, rx) = channel();
    scope(move |_| {
        spawn(move || tx.send(22).unwrap());
    });
    assert_eq!(22, rx.recv().unwrap());
}

#[test]
fn spawn_then_join_outside_worker() {
    let (tx, rx) = channel();
    spawn(move || tx.send(22).unwrap());
    assert_eq!(22, rx.recv().unwrap());
}

#[test]
fn panic_fwd() {
    let (tx, rx) = channel();

    let tx = Mutex::new(tx);
    let panic_handler = move |err: Box<Any + Send>| {
        let tx = tx.lock().unwrap();
        if let Some(&msg) = err.downcast_ref::<&str>() {
            if msg == "Hello, world!" {
                tx.send(1).unwrap();
            } else {
                tx.send(2).unwrap();
            }
        } else {
            tx.send(3).unwrap();
        }
    };

    let builder = ThreadPoolBuilder::new().panic_handler(panic_handler);

    builder
        .build()
        .unwrap()
        .spawn(move || panic!("Hello, world!"));

    assert_eq!(1, rx.recv().unwrap());
}

/// Test what happens when the thread-pool is dropped but there are
/// still active asynchronous tasks. We expect the thread-pool to stay
/// alive and executing until those threads are complete.
#[test]
fn termination_while_things_are_executing() {
    let (tx0, rx0) = channel();
    let (tx1, rx1) = channel();

    // Create a thread-pool and spawn some code in it, but then drop
    // our reference to it.
    {
        let thread_pool = ThreadPoolBuilder::new().build().unwrap();
        thread_pool.spawn(move || {
            let data = rx0.recv().unwrap();

            // At this point, we know the "main" reference to the
            // `ThreadPool` has been dropped, but there are still
            // active threads. Launch one more.
            spawn(move || {
                tx1.send(data).unwrap();
            });
        });
    }

    tx0.send(22).unwrap();
    let v = rx1.recv().unwrap();
    assert_eq!(v, 22);
}

#[test]
fn custom_panic_handler_and_spawn() {
    let (tx, rx) = channel();

    // Create a parallel closure that will send panics on the
    // channel; since the closure is potentially executed in parallel
    // with itself, we have to wrap `tx` in a mutex.
    let tx = Mutex::new(tx);
    let panic_handler = move |e: Box<Any + Send>| {
        tx.lock().unwrap().send(e).unwrap();
    };

    // Execute an async that will panic.
    let builder = ThreadPoolBuilder::new().panic_handler(panic_handler);
    builder.build().unwrap().spawn(move || {
        panic!("Hello, world!");
    });

    // Check that we got back the panic we expected.
    let error = rx.recv().unwrap();
    if let Some(&msg) = error.downcast_ref::<&str>() {
        assert_eq!(msg, "Hello, world!");
    } else {
        panic!("did not receive a string from panic handler");
    }
}

#[test]
fn custom_panic_handler_and_nested_spawn() {
    let (tx, rx) = channel();

    // Create a parallel closure that will send panics on the
    // channel; since the closure is potentially executed in parallel
    // with itself, we have to wrap `tx` in a mutex.
    let tx = Mutex::new(tx);
    let panic_handler = move |e| {
        tx.lock().unwrap().send(e).unwrap();
    };

    // Execute an async that will (eventually) panic.
    const PANICS: usize = 3;
    let builder = ThreadPoolBuilder::new().panic_handler(panic_handler);
    builder.build().unwrap().spawn(move || {
        // launch 3 nested spawn-asyncs; these should be in the same
        // thread-pool and hence inherit the same panic handler
        for _ in 0..PANICS {
            spawn(move || {
                panic!("Hello, world!");
            });
        }
    });

    // Check that we get back the panics we expected.
    for _ in 0..PANICS {
        let error = rx.recv().unwrap();
        if let Some(&msg) = error.downcast_ref::<&str>() {
            assert_eq!(msg, "Hello, world!");
        } else {
            panic!("did not receive a string from panic handler");
        }
    }
}

macro_rules! test_order {
    ($outer_spawn:ident, $inner_spawn:ident) => {{
        let builder = ThreadPoolBuilder::new().num_threads(1);
        let pool = builder.build().unwrap();
        let (tx, rx) = channel();
        pool.install(move || {
            for i in 0..10 {
                let tx = tx.clone();
                $outer_spawn(move || {
                    for j in 0..10 {
                        let tx = tx.clone();
                        $inner_spawn(move || {
                            tx.send(i * 10 + j).unwrap();
                        });
                    }
                });
            }
        });
        rx.iter().collect::<Vec<i32>>()
    }};
}

#[test]
fn lifo_order() {
    // In the absense of stealing, `spawn()` jobs on a thread will run in LIFO order.
    let vec = test_order!(spawn, spawn);
    let expected: Vec<i32> = (0..100).rev().collect(); // LIFO -> reversed
    assert_eq!(vec, expected);
}

#[test]
fn fifo_order() {
    // In the absense of stealing, `spawn_fifo()` jobs on a thread will run in FIFO order.
    let vec = test_order!(spawn_fifo, spawn_fifo);
    let expected: Vec<i32> = (0..100).collect(); // FIFO -> natural order
    assert_eq!(vec, expected);
}

#[test]
fn lifo_fifo_order() {
    // LIFO on the outside, FIFO on the inside
    let vec = test_order!(spawn, spawn_fifo);
    let expected: Vec<i32> = (0..10)
        .rev()
        .flat_map(|i| (0..10).map(move |j| i * 10 + j))
        .collect();
    assert_eq!(vec, expected);
}

#[test]
fn fifo_lifo_order() {
    // FIFO on the outside, LIFO on the inside
    let vec = test_order!(spawn_fifo, spawn);
    let expected: Vec<i32> = (0..10)
        .flat_map(|i| (0..10).rev().map(move |j| i * 10 + j))
        .collect();
    assert_eq!(vec, expected);
}

macro_rules! spawn_send {
    ($spawn:ident, $tx:ident, $i:expr) => {{
        let tx = $tx.clone();
        $spawn(move || tx.send($i).unwrap());
    }};
}

/// Test mixed spawns pushing a series of numbers, interleaved such
/// such that negative values are using the second kind of spawn.
macro_rules! test_mixed_order {
    ($pos_spawn:ident, $neg_spawn:ident) => {{
        let builder = ThreadPoolBuilder::new().num_threads(1);
        let pool = builder.build().unwrap();
        let (tx, rx) = channel();
        pool.install(move || {
            spawn_send!($pos_spawn, tx, 0);
            spawn_send!($neg_spawn, tx, -1);
            spawn_send!($pos_spawn, tx, 1);
            spawn_send!($neg_spawn, tx, -2);
            spawn_send!($pos_spawn, tx, 2);
            spawn_send!($neg_spawn, tx, -3);
            spawn_send!($pos_spawn, tx, 3);
        });
        rx.iter().collect::<Vec<i32>>()
    }};
}

#[test]
fn mixed_lifo_fifo_order() {
    let vec = test_mixed_order!(spawn, spawn_fifo);
    let expected = vec![3, -1, 2, -2, 1, -3, 0];
    assert_eq!(vec, expected);
}

#[test]
fn mixed_fifo_lifo_order() {
    let vec = test_mixed_order!(spawn_fifo, spawn);
    let expected = vec![0, -3, 1, -2, 2, -1, 3];
    assert_eq!(vec, expected);
}
<|endoftext|>


<commit_before>#[macro_use] extern crate libeuler;

/// If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The
/// sum of these multiples is 23.
///
/// Find the sum of all the multiples of 3 or 5 below 1000.
fn main() {
    solutions!{
        inputs: (max: i64 = 1000, fac1: i64 = 3, fac2: i64 = 5)

        sol naive {
            let mut sum = 0i64;

            for i in 0..max {
                sum += match i {
                    i if (i % fac1 == 0 || i % fac2 == 0) => i,
                    _ => 0
                }
            }

            sum
        }

        sol broken {
            -5
        }
    };
}
<commit_msg>Remove 'broken' from sol_0001<commit_after>#[macro_use] extern crate libeuler;

/// If we list all the natural numbers below 10 that are multiples of 3 or 5, we get 3, 5, 6 and 9. The
/// sum of these multiples is 23.
///
/// Find the sum of all the multiples of 3 or 5 below 1000.
fn main() {
    solutions!{
        inputs: (max: i64 = 1000, fac1: i64 = 3, fac2: i64 = 5)

        sol naive {
            let mut sum = 0i64;

            for i in 0..max {
                sum += match i {
                    i if (i % fac1 == 0 || i % fac2 == 0) => i,
                    _ => 0
                }
            }

            sum
        }
    };
}
<|endoftext|>


<commit_before><commit_msg>feat(cli): Add support for limiting number of CPU cycles<commit_after><|endoftext|>


<commit_before>use std::sync::Arc;
use std::time::Instant;

use async_trait::async_trait;
use bazel_protos::gen::build::bazel::remote::execution::v2 as remexec;
use bytes::Bytes;
use futures::{future, FutureExt};
use hashing::Fingerprint;
use log::{debug, warn};
use prost::Message;
use serde::{Deserialize, Serialize};
use sharded_lmdb::ShardedLmdb;
use store::Store;
use workunit_store::{
  in_workunit, Level, Metric, ObservationMetric, RunningWorkunit, WorkunitMetadata,
};

use crate::{
  Context, FallibleProcessResultWithPlatform, MultiPlatformProcess, Platform, Process,
  ProcessCacheScope, ProcessMetadata,
};

#[allow(dead_code)]
#[derive(Serialize, Deserialize)]
struct PlatformAndResponseBytes {
  platform: Platform,
  response_bytes: Vec<u8>,
}

#[derive(Clone)]
pub struct CommandRunner {
  underlying: Arc<dyn crate::CommandRunner>,
  process_execution_store: ShardedLmdb,
  file_store: Store,
  metadata: ProcessMetadata,
}

impl CommandRunner {
  pub fn new(
    underlying: Arc<dyn crate::CommandRunner>,
    process_execution_store: ShardedLmdb,
    file_store: Store,
    metadata: ProcessMetadata,
  ) -> CommandRunner {
    CommandRunner {
      underlying,
      process_execution_store,
      file_store,
      metadata,
    }
  }
}

#[async_trait]
impl crate::CommandRunner for CommandRunner {
  fn extract_compatible_request(&self, req: &MultiPlatformProcess) -> Option<Process> {
    self.underlying.extract_compatible_request(req)
  }

  async fn run(
    &self,
    context: Context,
    workunit: &mut RunningWorkunit,
    req: MultiPlatformProcess,
  ) -> Result<FallibleProcessResultWithPlatform, String> {
    let cache_lookup_start = Instant::now();
    let write_failures_to_cache = req
      .0
      .values()
      .any(|process| process.cache_scope == ProcessCacheScope::Always);
    let digest = crate::digest(req.clone(), &self.metadata);
    let key = digest.hash;

    let context2 = context.clone();
    let cache_read_result = in_workunit!(
      context.workunit_store.clone(),
      "local_cache_read".to_owned(),
      WorkunitMetadata {
        level: Level::Trace,
        desc: Some(format!("Local cache lookup: {}", req.user_facing_name())),
        ..WorkunitMetadata::default()
      },
      |workunit| async move {
        workunit.increment_counter(Metric::LocalCacheRequests, 1);

        match self.lookup(key).await {
          Ok(Some(result)) if result.exit_code == 0 || write_failures_to_cache => {
            let lookup_elapsed = cache_lookup_start.elapsed();
            workunit.increment_counter(Metric::LocalCacheRequestsCached, 1);
            if let Some(time_saved) = result.metadata.time_saved_from_cache(lookup_elapsed) {
              let time_saved = time_saved.as_millis() as u64;
              workunit.increment_counter(Metric::LocalCacheTotalTimeSavedMs, time_saved);
              context2
                .workunit_store
                .record_observation(ObservationMetric::LocalCacheTimeSavedMs, time_saved);
            }
            // When we successfully use the cache, we change the description and increase the level
            // (but not so much that it will be logged by default).
            workunit.update_metadata(|initial| WorkunitMetadata {
              desc: initial.desc.as_ref().map(|desc| format!("Hit: {}", desc)),
              level: Level::Debug,
              ..initial
            });
            Ok(result)
          }
          Err(err) => {
            debug!(
              "Error loading process execution result from local cache: {} - continuing to execute",
              err
            );
            workunit.increment_counter(Metric::LocalCacheReadErrors, 1);
            // Falling through to re-execute.
            Err(())
          }
          Ok(_) => {
            // Either we missed, or we hit for a failing result.
            workunit.increment_counter(Metric::LocalCacheRequestsUncached, 1);
            // Falling through to execute.
            Err(())
          }
        }
      }
      .boxed()
    )
    .await;

    if let Ok(result) = cache_read_result {
      workunit.update_metadata(|initial| WorkunitMetadata {
        desc: initial
          .desc
          .as_ref()
          .map(|desc| format!("Hit local cache: {}", desc)),
        ..initial
      });
      return Ok(result);
    }

    let result = self.underlying.run(context.clone(), workunit, req).await?;
    if result.exit_code == 0 || write_failures_to_cache {
      let result = result.clone();
      in_workunit!(
        context.workunit_store.clone(),
        "local_cache_write".to_owned(),
        WorkunitMetadata {
          level: Level::Trace,
          ..WorkunitMetadata::default()
        },
        |workunit| async move {
          if let Err(err) = self.store(key, &result).await {
            warn!(
              "Error storing process execution result to local cache: {} - ignoring and continuing",
              err
            );
            workunit.increment_counter(Metric::LocalCacheWriteErrors, 1);
          }
        }
      )
      .await;
    }
    Ok(result)
  }
}

impl CommandRunner {
  async fn lookup(
    &self,
    fingerprint: Fingerprint,
  ) -> Result<Option<FallibleProcessResultWithPlatform>, String> {
    use remexec::ExecuteResponse;

    // See whether there is a cache entry.
    let maybe_execute_response: Option<(ExecuteResponse, Platform)> = self
      .process_execution_store
      .load_bytes_with(fingerprint, move |bytes| {
        let decoded: PlatformAndResponseBytes = bincode::deserialize(bytes)
          .map_err(|err| format!("Could not deserialize platform and response: {}", err))?;
        let platform = decoded.platform;
        let execute_response = ExecuteResponse::decode(&decoded.response_bytes[..])
          .map_err(|e| format!("Invalid ExecuteResponse: {:?}", e))?;
        Ok((execute_response, platform))
      })
      .await?;

    // Deserialize the cache entry if it existed.
    let result = if let Some((execute_response, platform)) = maybe_execute_response {
      if let Some(ref action_result) = execute_response.result {
        crate::remote::populate_fallible_execution_result(
          self.file_store.clone(),
          action_result,
          platform,
          true,
        )
        .await?
      } else {
        return Err("action result missing from ExecuteResponse".into());
      }
    } else {
      return Ok(None);
    };

    // Ensure that all digests in the result are loadable, erroring if any are not.
    let _ = future::try_join_all(vec![
      self
        .file_store
        .ensure_local_has_file(result.stdout_digest)
        .boxed(),
      self
        .file_store
        .ensure_local_has_file(result.stderr_digest)
        .boxed(),
      self
        .file_store
        .ensure_local_has_recursive_directory(result.output_directory),
    ])
    .await?;

    Ok(Some(result))
  }

  async fn store(
    &self,
    fingerprint: Fingerprint,
    result: &FallibleProcessResultWithPlatform,
  ) -> Result<(), String> {
    let stdout_digest = result.stdout_digest;
    let stderr_digest = result.stderr_digest;

    let action_result = remexec::ActionResult {
      exit_code: result.exit_code,
      output_directories: vec![remexec::OutputDirectory {
        path: String::new(),
        tree_digest: Some((&result.output_directory).into()),
      }],
      stdout_digest: Some((&stdout_digest).into()),
      stderr_digest: Some((&stderr_digest).into()),
      execution_metadata: Some(result.metadata.clone().into()),
      ..remexec::ActionResult::default()
    };
    let execute_response = remexec::ExecuteResponse {
      cached_result: true,
      result: Some(action_result),
      ..remexec::ExecuteResponse::default()
    };

    // TODO: Should probably have a configurable lease time which is larger than default.
    // (This isn't super urgent because we don't ever actually GC this store. So also...)
    // TODO: GC the local process execution cache.

    let mut response_bytes = Vec::with_capacity(execute_response.encoded_len());
    execute_response
      .encode(&mut response_bytes)
      .map_err(|err| format!("Error serializing execute process result to cache: {}", err))?;

    let bytes_to_store = bincode::serialize(&PlatformAndResponseBytes {
      platform: result.platform,
      response_bytes,
    })
    .map(Bytes::from)
    .map_err(|err| {
      format!(
        "Error serializing platform and execute process result: {}",
        err
      )
    })?;

    self
      .process_execution_store
      .store_bytes(fingerprint, bytes_to_store, false)
      .await
  }
}
<commit_msg>Remove redundant cache lookup debug logging. (#12395)<commit_after>use std::sync::Arc;
use std::time::Instant;

use async_trait::async_trait;
use bazel_protos::gen::build::bazel::remote::execution::v2 as remexec;
use bytes::Bytes;
use futures::{future, FutureExt};
use hashing::Fingerprint;
use log::{debug, warn};
use prost::Message;
use serde::{Deserialize, Serialize};
use sharded_lmdb::ShardedLmdb;
use store::Store;
use workunit_store::{
  in_workunit, Level, Metric, ObservationMetric, RunningWorkunit, WorkunitMetadata,
};

use crate::{
  Context, FallibleProcessResultWithPlatform, MultiPlatformProcess, Platform, Process,
  ProcessCacheScope, ProcessMetadata,
};

#[allow(dead_code)]
#[derive(Serialize, Deserialize)]
struct PlatformAndResponseBytes {
  platform: Platform,
  response_bytes: Vec<u8>,
}

#[derive(Clone)]
pub struct CommandRunner {
  underlying: Arc<dyn crate::CommandRunner>,
  process_execution_store: ShardedLmdb,
  file_store: Store,
  metadata: ProcessMetadata,
}

impl CommandRunner {
  pub fn new(
    underlying: Arc<dyn crate::CommandRunner>,
    process_execution_store: ShardedLmdb,
    file_store: Store,
    metadata: ProcessMetadata,
  ) -> CommandRunner {
    CommandRunner {
      underlying,
      process_execution_store,
      file_store,
      metadata,
    }
  }
}

#[async_trait]
impl crate::CommandRunner for CommandRunner {
  fn extract_compatible_request(&self, req: &MultiPlatformProcess) -> Option<Process> {
    self.underlying.extract_compatible_request(req)
  }

  async fn run(
    &self,
    context: Context,
    workunit: &mut RunningWorkunit,
    req: MultiPlatformProcess,
  ) -> Result<FallibleProcessResultWithPlatform, String> {
    let cache_lookup_start = Instant::now();
    let write_failures_to_cache = req
      .0
      .values()
      .any(|process| process.cache_scope == ProcessCacheScope::Always);
    let digest = crate::digest(req.clone(), &self.metadata);
    let key = digest.hash;

    let context2 = context.clone();
    let cache_read_result = in_workunit!(
      context.workunit_store.clone(),
      "local_cache_read".to_owned(),
      WorkunitMetadata {
        level: Level::Trace,
        desc: Some(format!("Local cache lookup: {}", req.user_facing_name())),
        ..WorkunitMetadata::default()
      },
      |workunit| async move {
        workunit.increment_counter(Metric::LocalCacheRequests, 1);

        match self.lookup(key).await {
          Ok(Some(result)) if result.exit_code == 0 || write_failures_to_cache => {
            let lookup_elapsed = cache_lookup_start.elapsed();
            workunit.increment_counter(Metric::LocalCacheRequestsCached, 1);
            if let Some(time_saved) = result.metadata.time_saved_from_cache(lookup_elapsed) {
              let time_saved = time_saved.as_millis() as u64;
              workunit.increment_counter(Metric::LocalCacheTotalTimeSavedMs, time_saved);
              context2
                .workunit_store
                .record_observation(ObservationMetric::LocalCacheTimeSavedMs, time_saved);
            }
            // When we successfully use the cache, we change the description and increase the level
            // (but not so much that it will be logged by default).
            workunit.update_metadata(|initial| WorkunitMetadata {
              desc: initial.desc.as_ref().map(|desc| format!("Hit: {}", desc)),
              level: Level::Debug,
              ..initial
            });
            Ok(result)
          }
          Err(err) => {
            debug!(
              "Error loading process execution result from local cache: {} - continuing to execute",
              err
            );
            workunit.increment_counter(Metric::LocalCacheReadErrors, 1);
            // Falling through to re-execute.
            Err(())
          }
          Ok(_) => {
            // Either we missed, or we hit for a failing result.
            workunit.increment_counter(Metric::LocalCacheRequestsUncached, 1);
            // Falling through to execute.
            Err(())
          }
        }
      }
      .boxed()
    )
    .await;

    if let Ok(result) = cache_read_result {
      return Ok(result);
    }

    let result = self.underlying.run(context.clone(), workunit, req).await?;
    if result.exit_code == 0 || write_failures_to_cache {
      let result = result.clone();
      in_workunit!(
        context.workunit_store.clone(),
        "local_cache_write".to_owned(),
        WorkunitMetadata {
          level: Level::Trace,
          ..WorkunitMetadata::default()
        },
        |workunit| async move {
          if let Err(err) = self.store(key, &result).await {
            warn!(
              "Error storing process execution result to local cache: {} - ignoring and continuing",
              err
            );
            workunit.increment_counter(Metric::LocalCacheWriteErrors, 1);
          }
        }
      )
      .await;
    }
    Ok(result)
  }
}

impl CommandRunner {
  async fn lookup(
    &self,
    fingerprint: Fingerprint,
  ) -> Result<Option<FallibleProcessResultWithPlatform>, String> {
    use remexec::ExecuteResponse;

    // See whether there is a cache entry.
    let maybe_execute_response: Option<(ExecuteResponse, Platform)> = self
      .process_execution_store
      .load_bytes_with(fingerprint, move |bytes| {
        let decoded: PlatformAndResponseBytes = bincode::deserialize(bytes)
          .map_err(|err| format!("Could not deserialize platform and response: {}", err))?;
        let platform = decoded.platform;
        let execute_response = ExecuteResponse::decode(&decoded.response_bytes[..])
          .map_err(|e| format!("Invalid ExecuteResponse: {:?}", e))?;
        Ok((execute_response, platform))
      })
      .await?;

    // Deserialize the cache entry if it existed.
    let result = if let Some((execute_response, platform)) = maybe_execute_response {
      if let Some(ref action_result) = execute_response.result {
        crate::remote::populate_fallible_execution_result(
          self.file_store.clone(),
          action_result,
          platform,
          true,
        )
        .await?
      } else {
        return Err("action result missing from ExecuteResponse".into());
      }
    } else {
      return Ok(None);
    };

    // Ensure that all digests in the result are loadable, erroring if any are not.
    let _ = future::try_join_all(vec![
      self
        .file_store
        .ensure_local_has_file(result.stdout_digest)
        .boxed(),
      self
        .file_store
        .ensure_local_has_file(result.stderr_digest)
        .boxed(),
      self
        .file_store
        .ensure_local_has_recursive_directory(result.output_directory),
    ])
    .await?;

    Ok(Some(result))
  }

  async fn store(
    &self,
    fingerprint: Fingerprint,
    result: &FallibleProcessResultWithPlatform,
  ) -> Result<(), String> {
    let stdout_digest = result.stdout_digest;
    let stderr_digest = result.stderr_digest;

    let action_result = remexec::ActionResult {
      exit_code: result.exit_code,
      output_directories: vec![remexec::OutputDirectory {
        path: String::new(),
        tree_digest: Some((&result.output_directory).into()),
      }],
      stdout_digest: Some((&stdout_digest).into()),
      stderr_digest: Some((&stderr_digest).into()),
      execution_metadata: Some(result.metadata.clone().into()),
      ..remexec::ActionResult::default()
    };
    let execute_response = remexec::ExecuteResponse {
      cached_result: true,
      result: Some(action_result),
      ..remexec::ExecuteResponse::default()
    };

    // TODO: Should probably have a configurable lease time which is larger than default.
    // (This isn't super urgent because we don't ever actually GC this store. So also...)
    // TODO: GC the local process execution cache.

    let mut response_bytes = Vec::with_capacity(execute_response.encoded_len());
    execute_response
      .encode(&mut response_bytes)
      .map_err(|err| format!("Error serializing execute process result to cache: {}", err))?;

    let bytes_to_store = bincode::serialize(&PlatformAndResponseBytes {
      platform: result.platform,
      response_bytes,
    })
    .map(Bytes::from)
    .map_err(|err| {
      format!(
        "Error serializing platform and execute process result: {}",
        err
      )
    })?;

    self
      .process_execution_store
      .store_bytes(fingerprint, bytes_to_store, false)
      .await
  }
}
<|endoftext|>


<commit_before>// https://leetcode.com/problems/sort-the-jumbled-numbers/
pub fn sort_jumbled(mapping: Vec<i32>, nums: Vec<i32>) -> Vec<i32> {
    fn pad(s: &str, length: usize) -> String {
        "0".repeat(length) + &s.to_owned()
    }
    let mut sorted_nums = nums.clone();
    let longest = nums.iter().map(|a| a.to_string().len()).max().unwrap();
    sorted_nums.sort_by(|a, b| {
        let a: Vec<char> = a.to_string().chars().collect();
        let mut s1 = String::from("");
        for c in a {
            s1.push_str(&mapping[c as usize - '0' as usize].to_string());
        }
        let b: Vec<char> = b.to_string().chars().collect();
        let mut s2 = String::from("");
        for c in b {
            s2.push_str(&mapping[c as usize - '0' as usize].to_string());
        }
        let s1 = pad(&s1, longest - s1.len());
        let s2 = pad(&s2, longest - s2.len());
        s1.cmp(&s2)
    });
    sorted_nums
}

fn main() {
    println!(
        "{:?}",
        sort_jumbled(vec![8, 9, 4, 0, 2, 1, 3, 5, 7, 6], vec![991, 338, 38])
    ); // [338,38,991]
    println!(
        "{:?}",
        sort_jumbled(vec![8, 9, 4, 0, 2, 1, 3, 5, 7, 6], vec![991, 38, 338])
    ); // [38,338,991]
    println!(
        "{:?}",
        sort_jumbled(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], vec![789, 456, 123])
    ); // [123,456,789]
}
<commit_msg>Solve problem 2191<commit_after>// https://leetcode.com/problems/sort-the-jumbled-numbers/
pub fn sort_jumbled(mapping: Vec<i32>, nums: Vec<i32>) -> Vec<i32> {
    fn pad(s: &str, length: usize) -> String {
        "0".repeat(length) + &s.to_owned()
    }
    let longest = nums.iter().map(|a| a.to_string().len()).max().unwrap();
    let mut sorted_nums: Vec<(i32, String)> = nums
        .iter()
        .map(|a| {
            let chars: Vec<char> = a.to_string().chars().collect();
            let mut s = String::from("");
            for c in chars {
                s.push_str(&mapping[c as usize - '0' as usize].to_string());
            }
            (*a, pad(&s, longest - s.len()))
        })
        .collect();
    sorted_nums.sort_by(|a, b| a.1.cmp(&b.1));
    sorted_nums.iter().map(|a| a.0).collect()
}

fn main() {
    println!(
        "{:?}",
        sort_jumbled(vec![8, 9, 4, 0, 2, 1, 3, 5, 7, 6], vec![991, 338, 38])
    ); // [338,38,991]
    println!(
        "{:?}",
        sort_jumbled(vec![8, 9, 4, 0, 2, 1, 3, 5, 7, 6], vec![991, 38, 338])
    ); // [38,338,991]
    println!(
        "{:?}",
        sort_jumbled(vec![0, 1, 2, 3, 4, 5, 6, 7, 8, 9], vec![789, 456, 123])
    ); // [123,456,789]
}
<|endoftext|>


<commit_before>use ardite::{Error, Service};
use ardite::schema::{Definition};
use ardite::value::{Value, Object};
use inflections::Inflect;
use iron::Url;

use resource::Resource;
use resource::type_::Type;

pub struct Root;

impl Resource for Root {
  fn route<'a>(&self, definition: &'a Definition, next: String) -> Option<Box<Resource + 'a>> {
    if let Some(ref type_) = definition.get_type(&next.to_snake_case()) {
      Some(Box::new(Type::new(type_)))
    } else {
      None
    }
  }

  /// Gets an object containing all of the top level URLs exposed by this API.
  /// Such top level URLs contain:
  ///
  /// - URLs for type collections.
  fn get(&self, create_url: &Fn(Vec<String>) -> Url, service: &Service) -> Result<Value, Error> {
    let mut object = Object::new();

    for (name, _) in service.types() {
      let mut key = name.clone();
      key.push_str("_url");
      let value = value!(format!("{}", create_url(vec![name.clone()])));
      object.insert(key, value);
    }

    Ok(Value::Object(object))
  }
}
<commit_msg>feat(root): add collection to root URL key<commit_after>use ardite::{Error, Service};
use ardite::schema::{Definition};
use ardite::value::{Value, Object};
use inflections::Inflect;
use iron::Url;

use resource::Resource;
use resource::type_::Type;

pub struct Root;

impl Resource for Root {
  fn route<'a>(&self, definition: &'a Definition, next: String) -> Option<Box<Resource + 'a>> {
    if let Some(ref type_) = definition.get_type(&next.to_snake_case()) {
      Some(Box::new(Type::new(type_)))
    } else {
      None
    }
  }

  /// Gets an object containing all of the top level URLs exposed by this API.
  /// Such top level URLs contain:
  ///
  /// - URLs for type collections.
  fn get(&self, create_url: &Fn(Vec<String>) -> Url, service: &Service) -> Result<Value, Error> {
    let mut object = Object::new();

    for (name, _) in service.types() {
      let mut key = name.clone();
      key.push_str("_collection_url");
      let value = value!(format!("{}", create_url(vec![name.clone()])));
      object.insert(key, value);
    }

    Ok(Value::Object(object))
  }
}
<|endoftext|>


<commit_before><commit_msg>sliptream: Use a manually set stack size<commit_after><|endoftext|>


<commit_before>//! This module contains code to equate the input/output types appearing
//! in the MIR with the expected input/output types from the function
//! signature. This requires a bit of processing, as the expected types
//! are supplied to us before normalization and may contain opaque
//! `impl Trait` instances. In contrast, the input/output types found in
//! the MIR (specifically, in the special local variables for the
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).

use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::ty::Ty;

use rustc_index::vec::Idx;
use rustc_span::Span;

use crate::borrow_check::universal_regions::UniversalRegions;

use super::{Locations, TypeChecker};

impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
    pub(super) fn equate_inputs_and_outputs(
        &mut self,
        body: &Body<'tcx>,
        universal_regions: &UniversalRegions<'tcx>,
        normalized_inputs_and_output: &[Ty<'tcx>],
    ) {
        let (&normalized_output_ty, normalized_input_tys) =
            normalized_inputs_and_output.split_last().unwrap();

        let mir_def_id = body.source.def_id().expect_local();

        // If the user explicitly annotated the input types, extract
        // those.
        //
        // e.g., `|x: FxHashMap<_, &'static u32>| ...`
        let user_provided_sig;
        if !self.tcx().is_closure(mir_def_id.to_def_id()) {
            user_provided_sig = None;
        } else {
            let typeck_results = self.tcx().typeck(mir_def_id);
            user_provided_sig = match typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id())
            {
                None => None,
                Some(user_provided_poly_sig) => {
                    // Instantiate the canonicalized variables from
                    // user-provided signature (e.g., the `_` in the code
                    // above) with fresh variables.
                    let (poly_sig, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
                        body.span,
                        &user_provided_poly_sig,
                    );

                    // Replace the bound items in the fn sig with fresh
                    // variables, so that they represent the view from
                    // "inside" the closure.
                    Some(
                        self.infcx
                            .replace_bound_vars_with_fresh_vars(
                                body.span,
                                LateBoundRegionConversionTime::FnCall,
                                &poly_sig,
                            )
                            .0,
                    )
                }
            }
        };

        debug!(
            "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
            normalized_input_tys, body.local_decls
        );

        // Equate expected input tys with those in the MIR.
        for (&normalized_input_ty, argument_index) in normalized_input_tys.iter().zip(0..) {
            // In MIR, argument N is stored in local N+1.
            let local = Local::new(argument_index + 1);

            let mir_input_ty = body.local_decls[local].ty;
            let mir_input_span = body.local_decls[local].source_info.span;
            self.equate_normalized_input_or_output(
                normalized_input_ty,
                mir_input_ty,
                mir_input_span,
            );
        }

        if let Some(user_provided_sig) = user_provided_sig {
            for (&user_provided_input_ty, argument_index) in
                user_provided_sig.inputs().iter().zip(0..)
            {
                // In MIR, closures begin an implicit `self`, so
                // argument N is stored in local N+2.
                let local = Local::new(argument_index + 2);
                let mir_input_ty = body.local_decls[local].ty;
                let mir_input_span = body.local_decls[local].source_info.span;

                // If the user explicitly annotated the input types, enforce those.
                let user_provided_input_ty =
                    self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
                self.equate_normalized_input_or_output(
                    user_provided_input_ty,
                    mir_input_ty,
                    mir_input_span,
                );
            }
        }

        assert!(
            body.yield_ty.is_some() && universal_regions.yield_ty.is_some()
                || body.yield_ty.is_none() && universal_regions.yield_ty.is_none()
        );
        if let Some(mir_yield_ty) = body.yield_ty {
            let ur_yield_ty = universal_regions.yield_ty.unwrap();
            let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
            self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
        }

        // Return types are a bit more complex. They may contain opaque `impl Trait` types.
        let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
        let output_span = body.local_decls[RETURN_PLACE].source_info.span;
        if let Err(terr) = self.eq_opaque_type_and_type(
            mir_output_ty,
            normalized_output_ty,
            mir_def_id,
            Locations::All(output_span),
            ConstraintCategory::BoringNoLocation,
        ) {
            span_mirbug!(
                self,
                Location::START,
                "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
                normalized_output_ty,
                mir_output_ty,
                terr
            );
        };

        // If the user explicitly annotated the output types, enforce those.
        // Note that this only happens for closures.
        if let Some(user_provided_sig) = user_provided_sig {
            let user_provided_output_ty = user_provided_sig.output();
            let user_provided_output_ty =
                self.normalize(user_provided_output_ty, Locations::All(output_span));
            if let Err(err) = self.eq_opaque_type_and_type(
                mir_output_ty,
                user_provided_output_ty,
                mir_def_id,
                Locations::All(output_span),
                ConstraintCategory::BoringNoLocation,
            ) {
                span_mirbug!(
                    self,
                    Location::START,
                    "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
                    mir_output_ty,
                    user_provided_output_ty,
                    err
                );
            }
        }
    }

    fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
        debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);

        if let Err(terr) =
            self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
        {
            span_mirbug!(
                self,
                Location::START,
                "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
                a,
                b,
                terr
            );
        }
    }
}
<commit_msg>Zip -> Enumerate<commit_after>//! This module contains code to equate the input/output types appearing
//! in the MIR with the expected input/output types from the function
//! signature. This requires a bit of processing, as the expected types
//! are supplied to us before normalization and may contain opaque
//! `impl Trait` instances. In contrast, the input/output types found in
//! the MIR (specifically, in the special local variables for the
//! `RETURN_PLACE` the MIR arguments) are always fully normalized (and
//! contain revealed `impl Trait` values).

use rustc_infer::infer::LateBoundRegionConversionTime;
use rustc_middle::mir::*;
use rustc_middle::ty::Ty;

use rustc_index::vec::Idx;
use rustc_span::Span;

use crate::borrow_check::universal_regions::UniversalRegions;

use super::{Locations, TypeChecker};

impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
    pub(super) fn equate_inputs_and_outputs(
        &mut self,
        body: &Body<'tcx>,
        universal_regions: &UniversalRegions<'tcx>,
        normalized_inputs_and_output: &[Ty<'tcx>],
    ) {
        let (&normalized_output_ty, normalized_input_tys) =
            normalized_inputs_and_output.split_last().unwrap();

        let mir_def_id = body.source.def_id().expect_local();

        // If the user explicitly annotated the input types, extract
        // those.
        //
        // e.g., `|x: FxHashMap<_, &'static u32>| ...`
        let user_provided_sig;
        if !self.tcx().is_closure(mir_def_id.to_def_id()) {
            user_provided_sig = None;
        } else {
            let typeck_results = self.tcx().typeck(mir_def_id);
            user_provided_sig = match typeck_results.user_provided_sigs.get(&mir_def_id.to_def_id())
            {
                None => None,
                Some(user_provided_poly_sig) => {
                    // Instantiate the canonicalized variables from
                    // user-provided signature (e.g., the `_` in the code
                    // above) with fresh variables.
                    let (poly_sig, _) = self.infcx.instantiate_canonical_with_fresh_inference_vars(
                        body.span,
                        &user_provided_poly_sig,
                    );

                    // Replace the bound items in the fn sig with fresh
                    // variables, so that they represent the view from
                    // "inside" the closure.
                    Some(
                        self.infcx
                            .replace_bound_vars_with_fresh_vars(
                                body.span,
                                LateBoundRegionConversionTime::FnCall,
                                &poly_sig,
                            )
                            .0,
                    )
                }
            }
        };

        debug!(
            "equate_inputs_and_outputs: normalized_input_tys = {:?}, local_decls = {:?}",
            normalized_input_tys, body.local_decls
        );

        // Equate expected input tys with those in the MIR.
        for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
            // In MIR, argument N is stored in local N+1.
            let local = Local::new(argument_index + 1);

            let mir_input_ty = body.local_decls[local].ty;
            let mir_input_span = body.local_decls[local].source_info.span;
            self.equate_normalized_input_or_output(
                normalized_input_ty,
                mir_input_ty,
                mir_input_span,
            );
        }

        if let Some(user_provided_sig) = user_provided_sig {
            for (argument_index, &user_provided_input_ty) in
                user_provided_sig.inputs().iter().enumerate()
            {
                // In MIR, closures begin an implicit `self`, so
                // argument N is stored in local N+2.
                let local = Local::new(argument_index + 2);
                let mir_input_ty = body.local_decls[local].ty;
                let mir_input_span = body.local_decls[local].source_info.span;

                // If the user explicitly annotated the input types, enforce those.
                let user_provided_input_ty =
                    self.normalize(user_provided_input_ty, Locations::All(mir_input_span));
                self.equate_normalized_input_or_output(
                    user_provided_input_ty,
                    mir_input_ty,
                    mir_input_span,
                );
            }
        }

        assert!(
            body.yield_ty.is_some() && universal_regions.yield_ty.is_some()
                || body.yield_ty.is_none() && universal_regions.yield_ty.is_none()
        );
        if let Some(mir_yield_ty) = body.yield_ty {
            let ur_yield_ty = universal_regions.yield_ty.unwrap();
            let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
            self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty, yield_span);
        }

        // Return types are a bit more complex. They may contain opaque `impl Trait` types.
        let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
        let output_span = body.local_decls[RETURN_PLACE].source_info.span;
        if let Err(terr) = self.eq_opaque_type_and_type(
            mir_output_ty,
            normalized_output_ty,
            mir_def_id,
            Locations::All(output_span),
            ConstraintCategory::BoringNoLocation,
        ) {
            span_mirbug!(
                self,
                Location::START,
                "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
                normalized_output_ty,
                mir_output_ty,
                terr
            );
        };

        // If the user explicitly annotated the output types, enforce those.
        // Note that this only happens for closures.
        if let Some(user_provided_sig) = user_provided_sig {
            let user_provided_output_ty = user_provided_sig.output();
            let user_provided_output_ty =
                self.normalize(user_provided_output_ty, Locations::All(output_span));
            if let Err(err) = self.eq_opaque_type_and_type(
                mir_output_ty,
                user_provided_output_ty,
                mir_def_id,
                Locations::All(output_span),
                ConstraintCategory::BoringNoLocation,
            ) {
                span_mirbug!(
                    self,
                    Location::START,
                    "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`",
                    mir_output_ty,
                    user_provided_output_ty,
                    err
                );
            }
        }
    }

    fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>, span: Span) {
        debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b);

        if let Err(terr) =
            self.eq_types(a, b, Locations::All(span), ConstraintCategory::BoringNoLocation)
        {
            span_mirbug!(
                self,
                Location::START,
                "equate_normalized_input_or_output: `{:?}=={:?}` failed with `{:?}`",
                a,
                b,
                terr
            );
        }
    }
}
<|endoftext|>


<commit_before>use std::os;
use std::io::Writer;
use std::io::fs::File;
//use extra::time;

use http::server::{Request, ResponseWriter};
use http::headers::content_type::MediaType;

use super::utils::{get_url,not_found};

use views::{Action};

pub struct StaticFile;

impl Action for StaticFile  {
    fn render(&self, _out: &mut Writer) {
    }
}

pub struct StaticController;

impl StaticController {
    pub fn get (request: &Request, response: &mut ResponseWriter) -> Box<Action + 'static> {
        let working_dir = os::getcwd();
        let url = get_url(request);
        let mut file_path: PosixPath = working_dir.join(url.as_slice().slice_from(1));

        if file_path.exists() {
            if !file_path.is_file() {
                // try index.html, default.html in a directory
                file_path = file_path.join("index.html");
                if !file_path.exists() || !file_path.is_file() {
                    file_path = file_path.with_filename("default.html");
                    if !file_path.exists() || !file_path.is_file() {
                        not_found(request, response);
                        return box StaticFile as Box<Action>;
                    }
                }
            }

            let f = File::open(&file_path);
            match f {
                Ok(mut reader) => {
                    response.headers.content_type = match file_path.extension_str() {
                        Some("css") => {
                            Some(MediaType {
                                type_: String::from_str("text"),
                                subtype: String::from_str("css"),
                                parameters: vec!()
                            })
                        }
                        Some("js") => {
                            Some(MediaType {
                                type_: String::from_str("text"),
                                subtype: String::from_str("javascript"),
                                parameters: vec!()
                            })
                        }
                        _ => None
                    };

                    //let reader = f.get_mut_ref();
                    let file_contents = match reader.read_to_end() {
                        Ok(contents) => contents,
                        Err(msg) => fail!(msg)
                    };

                    response.headers.content_length = Some(file_contents.len());

                    drop(response.write(file_contents.as_slice()));
                },
                _ => {
                    not_found(request, response);
                }
            }
        }
        else {
            not_found(request, response);
        }

        return box StaticFile as Box<Action>
    }
}

<commit_msg>Update for rust changes<commit_after>use std::os;
use std::io::Writer;
use std::io::fs::File;
use std::io::fs::PathExtensions;
//use extra::time;

use http::server::{Request, ResponseWriter};
use http::headers::content_type::MediaType;

use super::utils::{get_url,not_found};

use views::{Action};

pub struct StaticFile;

impl Action for StaticFile  {
    fn render(&self, _out: &mut Writer) {
    }
}

pub struct StaticController;

impl StaticController {
    pub fn get (request: &Request, response: &mut ResponseWriter) -> Box<Action + 'static> {
        let working_dir = os::getcwd();
        let url = get_url(request);
        let mut file_path: PosixPath = working_dir.join(url.as_slice().slice_from(1));

        if file_path.exists() {
            if !file_path.is_file() {
                // try index.html, default.html in a directory
                file_path = file_path.join("index.html");
                if !file_path.exists() || !file_path.is_file() {
                    file_path = file_path.with_filename("default.html");
                    if !file_path.exists() || !file_path.is_file() {
                        not_found(request, response);
                        return box StaticFile as Box<Action>;
                    }
                }
            }

            let f = File::open(&file_path);
            match f {
                Ok(mut reader) => {
                    response.headers.content_type = match file_path.extension_str() {
                        Some("css") => {
                            Some(MediaType {
                                type_: String::from_str("text"),
                                subtype: String::from_str("css"),
                                parameters: vec!()
                            })
                        }
                        Some("js") => {
                            Some(MediaType {
                                type_: String::from_str("text"),
                                subtype: String::from_str("javascript"),
                                parameters: vec!()
                            })
                        }
                        _ => None
                    };

                    //let reader = f.get_mut_ref();
                    let file_contents = match reader.read_to_end() {
                        Ok(contents) => contents,
                        Err(msg) => fail!(msg)
                    };

                    response.headers.content_length = Some(file_contents.len());

                    drop(response.write(file_contents.as_slice()));
                },
                _ => {
                    not_found(request, response);
                }
            }
        }
        else {
            not_found(request, response);
        }

        return box StaticFile as Box<Action>
    }
}

<|endoftext|>


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

fn parse_type(iter: Box<Iterator<Item=&str>+'static>) -> &str { iter.next() }
//~^ ERROR missing lifetime specifier [E0106]
//~^^ HELP 2 elided lifetimes

fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
//~^ ERROR missing lifetime specifier [E0106]
//~^^ HELP 0 elided free lifetimes

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

fn parse_type(iter: Box<Iterator<Item=&str>+'static>) -> &str { iter.next() }
//~^ ERROR missing lifetime specifier [E0106]
//~^^ HELP 2 elided lifetimes

fn parse_type_2(iter: fn(&u8)->&u8) -> &str { iter() }
//~^ ERROR missing lifetime specifier [E0106]
//~^^ HELP lifetime cannot be derived

fn parse_type_3() -> &str { unimplemented!() }
//~^ ERROR missing lifetime specifier [E0106]
//~^^ HELP no value for it to be borrowed from

fn main() {}
<|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/. */

//! Tracking of pending loads in a document.
//! https://html.spec.whatwg.org/multipage/#the-end

use dom::bindings::js::JS;
use dom::document::Document;
use msg::constellation_msg::PipelineId;
use net_traits::{PendingAsyncLoad, LoadContext};
use net_traits::{RequestSource, AsyncResponseTarget};
use net_traits::{ResourceThreads, IpcSend};
use std::thread;
use url::Url;

#[derive(JSTraceable, PartialEq, Clone, Debug, HeapSizeOf)]
pub enum LoadType {
    Image(Url),
    Script(Url),
    Subframe(Url),
    Stylesheet(Url),
    PageSource(Url),
    Media(Url),
}

impl LoadType {
    fn url(&self) -> &Url {
        match *self {
            LoadType::Image(ref url) |
            LoadType::Script(ref url) |
            LoadType::Subframe(ref url) |
            LoadType::Stylesheet(ref url) |
            LoadType::Media(ref url) |
            LoadType::PageSource(ref url) => url,
        }
    }

    fn to_load_context(&self) -> LoadContext {
        match *self {
            LoadType::Image(_) => LoadContext::Image,
            LoadType::Script(_) => LoadContext::Script,
            LoadType::Subframe(_) | LoadType::PageSource(_) => LoadContext::Browsing,
            LoadType::Stylesheet(_) => LoadContext::Style,
            LoadType::Media(_) => LoadContext::AudioVideo,
        }
    }
}

/// Canary value ensuring that manually added blocking loads (ie. ones that weren't
/// created via DocumentLoader::prepare_async_load) are always removed by the time
/// that the owner is destroyed.
#[derive(JSTraceable, HeapSizeOf)]
#[must_root]
pub struct LoadBlocker {
    /// The document whose load event is blocked by this object existing.
    doc: JS<Document>,
    /// The load that is blocking the document's load event.
    load: Option<LoadType>,
}

impl LoadBlocker {
    /// Mark the document's load event as blocked on this new load.
    pub fn new(doc: &Document, load: LoadType) -> LoadBlocker {
        doc.add_blocking_load(load.clone());
        LoadBlocker {
            doc: JS::from_ref(doc),
            load: Some(load),
        }
    }

    /// Remove this load from the associated document's list of blocking loads.
    pub fn terminate(blocker: &mut Option<LoadBlocker>) {
        if let Some(this) = blocker.as_mut() {
            this.doc.finish_load(this.load.take().unwrap());
        }
        *blocker = None;
    }

    /// Return the url associated with this load.
    pub fn url(&self) -> Option<&Url> {
        self.load.as_ref().map(LoadType::url)
    }
}

impl Drop for LoadBlocker {
    fn drop(&mut self) {
        if !thread::panicking() {
            assert!(self.load.is_none());
        }
    }
}

#[derive(JSTraceable, HeapSizeOf)]
pub struct DocumentLoader {
    resource_threads: ResourceThreads,
    pipeline: Option<PipelineId>,
    blocking_loads: Vec<LoadType>,
    events_inhibited: bool,
}

impl DocumentLoader {
    pub fn new(existing: &DocumentLoader) -> DocumentLoader {
        DocumentLoader::new_with_threads(existing.resource_threads.clone(), None, None)
    }

    pub fn new_with_threads(resource_threads: ResourceThreads,
                            pipeline: Option<PipelineId>,
                            initial_load: Option<Url>) -> DocumentLoader {
        let initial_loads = initial_load.into_iter().map(LoadType::PageSource).collect();

        DocumentLoader {
            resource_threads: resource_threads,
            pipeline: pipeline,
            blocking_loads: initial_loads,
            events_inhibited: false,
        }
    }

    /// Add a load to the list of blocking loads.
    pub fn add_blocking_load(&mut self, load: LoadType) {
        self.blocking_loads.push(load);
    }

    /// Create a new pending network request, which can be initiated at some point in
    /// the future.
    pub fn prepare_async_load(&mut self,
                              load: LoadType,
                              referrer: &Document) -> PendingAsyncLoad {
        let context = load.to_load_context();
        let url = load.url().clone();
        self.add_blocking_load(load);
        let client_chan = referrer.window().custom_message_chan();
        PendingAsyncLoad::new(context,
                              self.resource_threads.sender(),
                              url,
                              self.pipeline,
                              referrer.get_referrer_policy(),
                              Some(referrer.url().clone()),
                              RequestSource::Window(client_chan))
    }

    /// Create and initiate a new network request.
    pub fn load_async(&mut self,
                      load: LoadType,
                      listener: AsyncResponseTarget,
                      referrer: &Document) {
        let pending = self.prepare_async_load(load, referrer);
        pending.load_async(listener)
    }

    /// Mark an in-progress network request complete.
    pub fn finish_load(&mut self, load: &LoadType) {
        let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == *load);
        self.blocking_loads.remove(idx.expect(&format!("unknown completed load {:?}", load)));
    }

    pub fn is_blocked(&self) -> bool {
        // TODO: Ensure that we report blocked if parsing is still ongoing.
        !self.blocking_loads.is_empty()
    }

    pub fn inhibit_events(&mut self) {
        self.events_inhibited = true;
    }

    pub fn events_inhibited(&self) -> bool {
        self.events_inhibited
    }

    pub fn resource_threads(&self) -> &ResourceThreads {
        &self.resource_threads
    }
}
<commit_msg>Auto merge of #11974 - ConnorGBrewster:load_blocker_drop_debug_assert, r=asajeffrey<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/. */

//! Tracking of pending loads in a document.
//! https://html.spec.whatwg.org/multipage/#the-end

use dom::bindings::js::JS;
use dom::document::Document;
use msg::constellation_msg::PipelineId;
use net_traits::{PendingAsyncLoad, LoadContext};
use net_traits::{RequestSource, AsyncResponseTarget};
use net_traits::{ResourceThreads, IpcSend};
use std::thread;
use url::Url;

#[derive(JSTraceable, PartialEq, Clone, Debug, HeapSizeOf)]
pub enum LoadType {
    Image(Url),
    Script(Url),
    Subframe(Url),
    Stylesheet(Url),
    PageSource(Url),
    Media(Url),
}

impl LoadType {
    fn url(&self) -> &Url {
        match *self {
            LoadType::Image(ref url) |
            LoadType::Script(ref url) |
            LoadType::Subframe(ref url) |
            LoadType::Stylesheet(ref url) |
            LoadType::Media(ref url) |
            LoadType::PageSource(ref url) => url,
        }
    }

    fn to_load_context(&self) -> LoadContext {
        match *self {
            LoadType::Image(_) => LoadContext::Image,
            LoadType::Script(_) => LoadContext::Script,
            LoadType::Subframe(_) | LoadType::PageSource(_) => LoadContext::Browsing,
            LoadType::Stylesheet(_) => LoadContext::Style,
            LoadType::Media(_) => LoadContext::AudioVideo,
        }
    }
}

/// Canary value ensuring that manually added blocking loads (ie. ones that weren't
/// created via DocumentLoader::prepare_async_load) are always removed by the time
/// that the owner is destroyed.
#[derive(JSTraceable, HeapSizeOf)]
#[must_root]
pub struct LoadBlocker {
    /// The document whose load event is blocked by this object existing.
    doc: JS<Document>,
    /// The load that is blocking the document's load event.
    load: Option<LoadType>,
}

impl LoadBlocker {
    /// Mark the document's load event as blocked on this new load.
    pub fn new(doc: &Document, load: LoadType) -> LoadBlocker {
        doc.add_blocking_load(load.clone());
        LoadBlocker {
            doc: JS::from_ref(doc),
            load: Some(load),
        }
    }

    /// Remove this load from the associated document's list of blocking loads.
    pub fn terminate(blocker: &mut Option<LoadBlocker>) {
        if let Some(this) = blocker.as_mut() {
            this.doc.finish_load(this.load.take().unwrap());
        }
        *blocker = None;
    }

    /// Return the url associated with this load.
    pub fn url(&self) -> Option<&Url> {
        self.load.as_ref().map(LoadType::url)
    }
}

impl Drop for LoadBlocker {
    fn drop(&mut self) {
        if !thread::panicking() {
            debug_assert!(self.load.is_none());
        }
    }
}

#[derive(JSTraceable, HeapSizeOf)]
pub struct DocumentLoader {
    resource_threads: ResourceThreads,
    pipeline: Option<PipelineId>,
    blocking_loads: Vec<LoadType>,
    events_inhibited: bool,
}

impl DocumentLoader {
    pub fn new(existing: &DocumentLoader) -> DocumentLoader {
        DocumentLoader::new_with_threads(existing.resource_threads.clone(), None, None)
    }

    pub fn new_with_threads(resource_threads: ResourceThreads,
                            pipeline: Option<PipelineId>,
                            initial_load: Option<Url>) -> DocumentLoader {
        let initial_loads = initial_load.into_iter().map(LoadType::PageSource).collect();

        DocumentLoader {
            resource_threads: resource_threads,
            pipeline: pipeline,
            blocking_loads: initial_loads,
            events_inhibited: false,
        }
    }

    /// Add a load to the list of blocking loads.
    pub fn add_blocking_load(&mut self, load: LoadType) {
        self.blocking_loads.push(load);
    }

    /// Create a new pending network request, which can be initiated at some point in
    /// the future.
    pub fn prepare_async_load(&mut self,
                              load: LoadType,
                              referrer: &Document) -> PendingAsyncLoad {
        let context = load.to_load_context();
        let url = load.url().clone();
        self.add_blocking_load(load);
        let client_chan = referrer.window().custom_message_chan();
        PendingAsyncLoad::new(context,
                              self.resource_threads.sender(),
                              url,
                              self.pipeline,
                              referrer.get_referrer_policy(),
                              Some(referrer.url().clone()),
                              RequestSource::Window(client_chan))
    }

    /// Create and initiate a new network request.
    pub fn load_async(&mut self,
                      load: LoadType,
                      listener: AsyncResponseTarget,
                      referrer: &Document) {
        let pending = self.prepare_async_load(load, referrer);
        pending.load_async(listener)
    }

    /// Mark an in-progress network request complete.
    pub fn finish_load(&mut self, load: &LoadType) {
        let idx = self.blocking_loads.iter().position(|unfinished| *unfinished == *load);
        self.blocking_loads.remove(idx.expect(&format!("unknown completed load {:?}", load)));
    }

    pub fn is_blocked(&self) -> bool {
        // TODO: Ensure that we report blocked if parsing is still ongoing.
        !self.blocking_loads.is_empty()
    }

    pub fn inhibit_events(&mut self) {
        self.events_inhibited = true;
    }

    pub fn events_inhibited(&self) -> bool {
        self.events_inhibited
    }

    pub fn resource_threads(&self) -> &ResourceThreads {
        &self.resource_threads
    }
}
<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
extern crate glfw;
use self::glfw::{Context, Key, Action};

extern crate gl;
use self::gl::types::*;

use std::sync::mpsc::Receiver;
use std::ptr;
use std::mem;
use std::os::raw::c_void;
use std::ffi::CStr;
use std::path::Path;

use shader::Shader;
use camera::Camera;
use camera::Camera_Movement::*;
use model::Model;

use cgmath::{Matrix4, Vector3, vec3, Point3, Deg, perspective};
use cgmath::prelude::*;

use image;
use image::GenericImage;
use image::DynamicImage::*;

// settings
const SCR_WIDTH: u32 = 800;
const SCR_HEIGHT: u32 = 600;

pub fn main_3_1() {
    let mut camera = Camera {
        Position: Point3::new(0.0, 0.0, 3.0),
        ..Camera::default()
    };

    let mut firstMouse = true;
    let mut lastX: f32 = SCR_WIDTH as f32 / 2.0;
    let mut lastY: f32 = SCR_HEIGHT as f32 / 2.0;

    // timing
    let mut deltaTime: f32; // time between current frame and last frame
    let mut lastFrame: f32 = 0.0;

    // glfw: initialize and configure
    // ------------------------------
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    #[cfg(target_os = "macos")]
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    // glfw window creation
    // --------------------
    let (mut window, events) = glfw.create_window(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window");

    window.make_current();
    window.set_framebuffer_size_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_scroll_polling(true);

    // tell GLFW to capture our mouse
    window.set_cursor_mode(glfw::CursorMode::Disabled);

    // gl: load all OpenGL function pointers
    // ---------------------------------------
    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    let (ourShader, ourModel) = unsafe {
        // configure global opengl state
        // -----------------------------
        gl::Enable(gl::DEPTH_TEST);

        // build and compile shaders
        // -------------------------
        let ourShader = Shader::new("src/_3_model_loading/shaders/1.model_loading.vs", "src/_3_model_loading/shaders/1.model_loading.fs");

        // load models
        // -----------
        let ourModel = Model::new("resources/objects/nanosuit/nanosuit.obj");

        // draw in wireframe
        // gl::PolygonMode(gl::FRONT_AND_BACK, gl::LINE);

        (ourShader, ourModel)
    };

    // render loop
    // -----------
    while !window.should_close() {
        // per-frame time logic
        // --------------------
        let currentFrame = glfw.get_time() as f32;
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // events
        // -----
        process_events(&events, &mut firstMouse, &mut lastX, &mut lastY, &mut camera);

        // input
        // -----
        processInput(&mut window, deltaTime, &mut camera);

        // render
        // ------
        unsafe {
            gl::ClearColor(0.1, 0.1, 0.1, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            // don't forget to enable shader before setting uniforms
            ourShader.useProgram();

            // view/projection transformations
            let projection: Matrix4<f32> = perspective(Deg(camera.Zoom), (SCR_WIDTH / SCR_HEIGHT) as f32, 0.1, 100.0);
            let view = camera.GetViewMatrix();
            ourShader.setMat4(c_str!("projection"), &projection);
            ourShader.setMat4(c_str!("view"), &view);

            // render the loaded model
            let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -1.75, 0.0)); // translate it down so it's at the center of the scene
            model = model * Matrix4::from_scale(0.2);  // it's a bit too big for our scene, so scale it down
            ourShader.setMat4(c_str!("model"), &model);
            ourModel.Draw(&ourShader);
        }

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        window.swap_buffers();
        glfw.poll_events();
    }

}

fn process_events(events: &Receiver<(f64, glfw::WindowEvent)>,
                  firstMouse: &mut bool,
                  lastX: &mut f32,
                  lastY: &mut f32,
                  camera: &mut Camera) {
    for (_, event) in glfw::flush_messages(events) {
        match event {
            glfw::WindowEvent::FramebufferSize(width, height) => {
                // make sure the viewport matches the new window dimensions; note that width and
                // height will be significantly larger than specified on retina displays.
                unsafe { gl::Viewport(0, 0, width, height) }
            }
            glfw::WindowEvent::CursorPos(xpos, ypos) => {
                let (xpos, ypos) = (xpos as f32, ypos as f32);
                if *firstMouse {
                    *lastX = xpos;
                    *lastY = ypos;
                    *firstMouse = false;
                }

                let xoffset = xpos - *lastX;
                let yoffset = *lastY - ypos; // reversed since y-coordinates go from bottom to top

                *lastX = xpos;
                *lastY = ypos;

                camera.ProcessMouseMovement(xoffset, yoffset, true);
            }
            glfw::WindowEvent::Scroll(_xoffset, yoffset) => {
                camera.ProcessMouseScroll(yoffset as f32);
            }
            _ => {}
        }
    }
}

fn processInput(window: &mut glfw::Window, deltaTime: f32, camera: &mut Camera) {
    if window.get_key(Key::Escape) == Action::Press {
        window.set_should_close(true)
    }

    if window.get_key(Key::W) == Action::Press {
        camera.ProcessKeyboard(FORWARD, deltaTime);
    }
    if window.get_key(Key::S) == Action::Press {
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    }
    if window.get_key(Key::A) == Action::Press {
        camera.ProcessKeyboard(LEFT, deltaTime);
    }
    if window.get_key(Key::D) == Action::Press {
        camera.ProcessKeyboard(RIGHT, deltaTime);
    }

}

unsafe fn loadTexture(path: &str) -> u32 {
    let mut textureID = 0;

    gl::GenTextures(1, &mut textureID);
    let img = image::open(&Path::new(path)).expect("Texture failed to load");
    let format = match img {
        ImageLuma8(_) => gl::RED,
        ImageLumaA8(_) => gl::RG,
        ImageRgb8(_) => gl::RGB,
        ImageRgba8(_) => gl::RGBA,
    };

    let data = img.raw_pixels();

    gl::BindTexture(gl::TEXTURE_2D, textureID);
    gl::TexImage2D(gl::TEXTURE_2D, 0, format as i32, img.width() as i32, img.height() as i32,
        0, format, gl::UNSIGNED_BYTE, &data[0] as *const u8 as *const c_void);
    gl::GenerateMipmap(gl::TEXTURE_2D);

    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_S, gl::REPEAT as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::REPEAT as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::LINEAR_MIPMAP_LINEAR as i32);
    gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::LINEAR as i32);

    textureID
}
<commit_msg>remove unused code<commit_after>#![allow(non_upper_case_globals)]
#![allow(non_snake_case)]
extern crate glfw;
use self::glfw::{Context, Key, Action};

extern crate gl;

use std::sync::mpsc::Receiver;
use std::ffi::CStr;

use shader::Shader;
use camera::Camera;
use camera::Camera_Movement::*;
use model::Model;

use cgmath::{Matrix4, vec3, Point3, Deg, perspective};

// settings
const SCR_WIDTH: u32 = 800;
const SCR_HEIGHT: u32 = 600;

pub fn main_3_1() {
    let mut camera = Camera {
        Position: Point3::new(0.0, 0.0, 3.0),
        ..Camera::default()
    };

    let mut firstMouse = true;
    let mut lastX: f32 = SCR_WIDTH as f32 / 2.0;
    let mut lastY: f32 = SCR_HEIGHT as f32 / 2.0;

    // timing
    let mut deltaTime: f32; // time between current frame and last frame
    let mut lastFrame: f32 = 0.0;

    // glfw: initialize and configure
    // ------------------------------
    let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
    glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
    glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
    #[cfg(target_os = "macos")]
    glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));

    // glfw window creation
    // --------------------
    let (mut window, events) = glfw.create_window(SCR_WIDTH, SCR_HEIGHT, "LearnOpenGL", glfw::WindowMode::Windowed)
        .expect("Failed to create GLFW window");

    window.make_current();
    window.set_framebuffer_size_polling(true);
    window.set_cursor_pos_polling(true);
    window.set_scroll_polling(true);

    // tell GLFW to capture our mouse
    window.set_cursor_mode(glfw::CursorMode::Disabled);

    // gl: load all OpenGL function pointers
    // ---------------------------------------
    gl::load_with(|symbol| window.get_proc_address(symbol) as *const _);

    let (ourShader, ourModel) = unsafe {
        // configure global opengl state
        // -----------------------------
        gl::Enable(gl::DEPTH_TEST);

        // build and compile shaders
        // -------------------------
        let ourShader = Shader::new("src/_3_model_loading/shaders/1.model_loading.vs", "src/_3_model_loading/shaders/1.model_loading.fs");

        // load models
        // -----------
        let ourModel = Model::new("resources/objects/nanosuit/nanosuit.obj");

        // draw in wireframe
        // gl::PolygonMode(gl::FRONT_AND_BACK, gl::LINE);

        (ourShader, ourModel)
    };

    // render loop
    // -----------
    while !window.should_close() {
        // per-frame time logic
        // --------------------
        let currentFrame = glfw.get_time() as f32;
        deltaTime = currentFrame - lastFrame;
        lastFrame = currentFrame;

        // events
        // -----
        process_events(&events, &mut firstMouse, &mut lastX, &mut lastY, &mut camera);

        // input
        // -----
        processInput(&mut window, deltaTime, &mut camera);

        // render
        // ------
        unsafe {
            gl::ClearColor(0.1, 0.1, 0.1, 1.0);
            gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);

            // don't forget to enable shader before setting uniforms
            ourShader.useProgram();

            // view/projection transformations
            let projection: Matrix4<f32> = perspective(Deg(camera.Zoom), (SCR_WIDTH / SCR_HEIGHT) as f32, 0.1, 100.0);
            let view = camera.GetViewMatrix();
            ourShader.setMat4(c_str!("projection"), &projection);
            ourShader.setMat4(c_str!("view"), &view);

            // render the loaded model
            let mut model = Matrix4::<f32>::from_translation(vec3(0.0, -1.75, 0.0)); // translate it down so it's at the center of the scene
            model = model * Matrix4::from_scale(0.2);  // it's a bit too big for our scene, so scale it down
            ourShader.setMat4(c_str!("model"), &model);
            ourModel.Draw(&ourShader);
        }

        // glfw: swap buffers and poll IO events (keys pressed/released, mouse moved etc.)
        // -------------------------------------------------------------------------------
        window.swap_buffers();
        glfw.poll_events();
    }

}

fn process_events(events: &Receiver<(f64, glfw::WindowEvent)>,
                  firstMouse: &mut bool,
                  lastX: &mut f32,
                  lastY: &mut f32,
                  camera: &mut Camera) {
    for (_, event) in glfw::flush_messages(events) {
        match event {
            glfw::WindowEvent::FramebufferSize(width, height) => {
                // make sure the viewport matches the new window dimensions; note that width and
                // height will be significantly larger than specified on retina displays.
                unsafe { gl::Viewport(0, 0, width, height) }
            }
            glfw::WindowEvent::CursorPos(xpos, ypos) => {
                let (xpos, ypos) = (xpos as f32, ypos as f32);
                if *firstMouse {
                    *lastX = xpos;
                    *lastY = ypos;
                    *firstMouse = false;
                }

                let xoffset = xpos - *lastX;
                let yoffset = *lastY - ypos; // reversed since y-coordinates go from bottom to top

                *lastX = xpos;
                *lastY = ypos;

                camera.ProcessMouseMovement(xoffset, yoffset, true);
            }
            glfw::WindowEvent::Scroll(_xoffset, yoffset) => {
                camera.ProcessMouseScroll(yoffset as f32);
            }
            _ => {}
        }
    }
}

fn processInput(window: &mut glfw::Window, deltaTime: f32, camera: &mut Camera) {
    if window.get_key(Key::Escape) == Action::Press {
        window.set_should_close(true)
    }

    if window.get_key(Key::W) == Action::Press {
        camera.ProcessKeyboard(FORWARD, deltaTime);
    }
    if window.get_key(Key::S) == Action::Press {
        camera.ProcessKeyboard(BACKWARD, deltaTime);
    }
    if window.get_key(Key::A) == Action::Press {
        camera.ProcessKeyboard(LEFT, deltaTime);
    }
    if window.get_key(Key::D) == Action::Press {
        camera.ProcessKeyboard(RIGHT, deltaTime);
    }

}
<|endoftext|>


<commit_before><commit_msg>Enforce DHT ID sizes<commit_after><|endoftext|>