<commit_before>use crate::{
  ExecuteProcessRequest, ExecuteProcessRequestMetadata, FallibleExecuteProcessResult,
  MultiPlatformExecuteProcessRequest,
};
use boxfuture::{BoxFuture, Boxable};
use bytes::Bytes;
use digest::{Digest as DigestTrait, FixedOutput};
use futures::Future;
use hashing::{Digest, Fingerprint};
use log::{debug, warn};
use protobuf::Message;
use sha2::Sha256;
use sharded_lmdb::ShardedLmdb;
use std::sync::Arc;
use store::Store;
use workunit_store::WorkUnitStore;

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

impl crate::CommandRunner for CommandRunner {
  fn extract_compatible_request(
    &self,
    req: &MultiPlatformExecuteProcessRequest,
  ) -> Option<ExecuteProcessRequest> {
    self.underlying.extract_compatible_request(req)
  }

  // TODO: Maybe record WorkUnits for local cache checks.
  fn run(
    &self,
    req: MultiPlatformExecuteProcessRequest,
    workunit_store: WorkUnitStore,
  ) -> BoxFuture<FallibleExecuteProcessResult, String> {
    let digest = self.digest(req.clone());
    let key = digest.0;

    let command_runner = self.clone();
    self
      .lookup(key, workunit_store.clone())
      .then(move |maybe_result| {
        match maybe_result {
          Ok(Some(result)) => return futures::future::ok(result).to_boxed(),
          Err(err) => {
            warn!("Error loading process execution result from local cache: {} - continuing to execute", err);
            // Falling through to re-execute.
          },
          Ok(None) => {
            // Falling through to execute.
          },
        }
        command_runner
            .underlying
            .run(req, workunit_store)
            .and_then(move |result| {
              command_runner.store(key, &result).then(|store_result| {
                if let Err(err) = store_result {
                  debug!("Error storing process execution result to local cache: {} - ignoring and continuing", err);
                }
                Ok(result)
              })
            })
            .to_boxed()
      })
      .to_boxed()
  }
}

impl CommandRunner {
  fn bytes_to_digest(&self, bytes: &[u8]) -> Digest {
    let mut hasher = Sha256::default();
    hasher.input(bytes);

    Digest(
      Fingerprint::from_bytes_unsafe(&hasher.fixed_result()),
      bytes.len(),
    )
  }

  fn digest(&self, req: MultiPlatformExecuteProcessRequest) -> Digest {
    let mut hashes: Vec<String> = req
      .0
      .values()
      .map(|ref epr| crate::remote::make_execute_request(epr, self.metadata.clone()).unwrap())
      .map(|(_a, _b, er)| er.get_action_digest().get_hash().to_string())
      .collect();
    hashes.sort();
    self.bytes_to_digest(
      hashes
        .iter()
        .fold(String::new(), |mut acc, hash| {
          acc.push_str(&hash);
          acc
        })
        .as_bytes(),
    )
  }

  fn lookup(
    &self,
    fingerprint: Fingerprint,
    workunit_store: WorkUnitStore,
  ) -> impl Future<Item = Option<FallibleExecuteProcessResult>, Error = String> {
    let file_store = self.file_store.clone();
    self
      .process_execution_store
      .load_bytes_with(fingerprint, |bytes| {
        let mut execute_response = bazel_protos::remote_execution::ExecuteResponse::new();
        execute_response
          .merge_from_bytes(&bytes)
          .map_err(|e| format!("Invalid ExecuteResponse: {:?}", e))?;
        Ok(execute_response)
      })
      .and_then(move |maybe_execute_response| {
        if let Some(execute_response) = maybe_execute_response {
          crate::remote::populate_fallible_execution_result(
            file_store,
            execute_response,
            vec![],
            workunit_store,
          )
          .map(Some)
          .to_boxed()
        } else {
          futures::future::ok(None).to_boxed()
        }
      })
  }

  fn store(
    &self,
    fingerprint: Fingerprint,
    result: &FallibleExecuteProcessResult,
  ) -> impl Future<Item = (), Error = String> {
    let mut execute_response = bazel_protos::remote_execution::ExecuteResponse::new();
    execute_response.set_cached_result(true);
    let action_result = execute_response.mut_result();
    action_result.set_exit_code(result.exit_code);
    action_result.mut_output_directories().push({
      let mut directory = bazel_protos::remote_execution::OutputDirectory::new();
      directory.set_path(String::new());
      directory.set_tree_digest((&result.output_directory).into());
      directory
    });
    let process_execution_store = self.process_execution_store.clone();
    // 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.
    self
      .file_store
      .store_file_bytes(result.stdout.clone(), true)
      .join(
        self
          .file_store
          .store_file_bytes(result.stderr.clone(), true),
      )
      .and_then(move |(stdout_digest, stderr_digest)| {
        let action_result = execute_response.mut_result();
        action_result.set_stdout_digest((&stdout_digest).into());
        action_result.set_stderr_digest((&stderr_digest).into());
        execute_response
          .write_to_bytes()
          .map(Bytes::from)
          .map_err(|err| format!("Error serializing execute process result to cache: {}", err))
      })
      .and_then(move |bytes| process_execution_store.store_bytes(fingerprint, bytes, false))
  }
}

#[cfg(test)]
mod test {
  use crate::{CommandRunner as CommandRunnerTrait, ExecuteProcessRequestMetadata};
  use crate::{ExecuteProcessRequest, Platform};
  use hashing::EMPTY_DIGEST;
  use sharded_lmdb::ShardedLmdb;
  use std::collections::{BTreeMap, BTreeSet};
  use std::io::Write;
  use std::path::PathBuf;
  use std::sync::Arc;
  use std::time::Duration;
  use store::Store;
  use tempfile::TempDir;
  use testutil::data::TestData;
  use workunit_store::WorkUnitStore;

  #[test]
  fn roundtrip() {
    let runtime = task_executor::Executor::new();
    let work_dir = TempDir::new().unwrap();
    let store_dir = TempDir::new().unwrap();
    let store = Store::local_only(runtime.clone(), store_dir.path()).unwrap();
    let local = crate::local::CommandRunner::new(
      store.clone(),
      runtime.clone(),
      work_dir.path().to_owned(),
      true,
    );

    let script_dir = TempDir::new().unwrap();
    let script_path = script_dir.path().join("script");
    std::fs::File::create(&script_path)
      .and_then(|mut file| {
        writeln!(
          file,
          "echo -n {} > roland && echo Hello && echo >&2 World",
          TestData::roland().string(),
        )
      })
      .unwrap();

    let request = ExecuteProcessRequest {
      argv: vec![
        testutil::path::find_bash(),
        format!("{}", script_path.display()),
      ],
      env: BTreeMap::new(),
      input_files: EMPTY_DIGEST,
      output_files: vec![PathBuf::from("roland")].into_iter().collect(),
      output_directories: BTreeSet::new(),
      timeout: Duration::from_millis(1000),
      description: "bash".to_string(),
      unsafe_local_only_files_because_we_favor_speed_over_correctness_for_this_rule:
        hashing::EMPTY_DIGEST,
      jdk_home: None,
      target_platform: Platform::None,
    };

    let local_result = runtime.block_on(local.run(request.clone().into(), WorkUnitStore::new()));

    let cache_dir = TempDir::new().unwrap();
    let caching = crate::cache::CommandRunner {
      underlying: Arc::new(local),
      file_store: store.clone(),
      process_execution_store: ShardedLmdb::new(
        cache_dir.path().to_owned(),
        50 * 1024 * 1024,
        runtime.clone(),
      )
      .unwrap(),
      metadata: ExecuteProcessRequestMetadata {
        instance_name: None,
        cache_key_gen_version: None,
        platform_properties: vec![],
      },
    };

    let uncached_result =
      runtime.block_on(caching.run(request.clone().into(), WorkUnitStore::new()));

    assert_eq!(local_result, uncached_result);

    std::fs::remove_file(&script_path).unwrap();
    let cached_result = runtime.block_on(caching.run(request.into(), WorkUnitStore::new()));

    assert_eq!(uncached_result, cached_result);
  }
}
<commit_msg>No longer cache failed `ExecuteProcessResult`s (#8291)<commit_after>use crate::{
  ExecuteProcessRequest, ExecuteProcessRequestMetadata, FallibleExecuteProcessResult,
  MultiPlatformExecuteProcessRequest,
};
use boxfuture::{BoxFuture, Boxable};
use bytes::Bytes;
use digest::{Digest as DigestTrait, FixedOutput};
use futures::Future;
use hashing::{Digest, Fingerprint};
use log::{debug, warn};
use protobuf::Message;
use sha2::Sha256;
use sharded_lmdb::ShardedLmdb;
use std::sync::Arc;
use store::Store;
use workunit_store::WorkUnitStore;

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

impl crate::CommandRunner for CommandRunner {
  fn extract_compatible_request(
    &self,
    req: &MultiPlatformExecuteProcessRequest,
  ) -> Option<ExecuteProcessRequest> {
    self.underlying.extract_compatible_request(req)
  }

  // TODO: Maybe record WorkUnits for local cache checks.
  fn run(
    &self,
    req: MultiPlatformExecuteProcessRequest,
    workunit_store: WorkUnitStore,
  ) -> BoxFuture<FallibleExecuteProcessResult, String> {
    let digest = self.digest(req.clone());
    let key = digest.0;

    let command_runner = self.clone();
    self
      .lookup(key, workunit_store.clone())
      .then(move |maybe_result| {
        match maybe_result {
          Ok(Some(result)) => return futures::future::ok(result).to_boxed(),
          Err(err) => {
            warn!("Error loading process execution result from local cache: {} - continuing to execute", err);
            // Falling through to re-execute.
          },
          Ok(None) => {
            // Falling through to execute.
          },
        }
        command_runner
          .underlying
          .run(req, workunit_store)
          .and_then(move |result| {
            if result.exit_code == 0 {
              command_runner
                .store(key, &result)
                .then(|store_result| {
                  if let Err(err) = store_result {
                    debug!("Error storing process execution result to local cache: {} - ignoring and continuing", err);
                  }
                  Ok(result)
                }).to_boxed()
            } else {
              futures::future::ok(result).to_boxed()
            }
          })
          .to_boxed()
      })
      .to_boxed()
  }
}

impl CommandRunner {
  fn bytes_to_digest(&self, bytes: &[u8]) -> Digest {
    let mut hasher = Sha256::default();
    hasher.input(bytes);

    Digest(
      Fingerprint::from_bytes_unsafe(&hasher.fixed_result()),
      bytes.len(),
    )
  }

  fn digest(&self, req: MultiPlatformExecuteProcessRequest) -> Digest {
    let mut hashes: Vec<String> = req
      .0
      .values()
      .map(|ref epr| crate::remote::make_execute_request(epr, self.metadata.clone()).unwrap())
      .map(|(_a, _b, er)| er.get_action_digest().get_hash().to_string())
      .collect();
    hashes.sort();
    self.bytes_to_digest(
      hashes
        .iter()
        .fold(String::new(), |mut acc, hash| {
          acc.push_str(&hash);
          acc
        })
        .as_bytes(),
    )
  }

  fn lookup(
    &self,
    fingerprint: Fingerprint,
    workunit_store: WorkUnitStore,
  ) -> impl Future<Item = Option<FallibleExecuteProcessResult>, Error = String> {
    let file_store = self.file_store.clone();
    self
      .process_execution_store
      .load_bytes_with(fingerprint, |bytes| {
        let mut execute_response = bazel_protos::remote_execution::ExecuteResponse::new();
        execute_response
          .merge_from_bytes(&bytes)
          .map_err(|e| format!("Invalid ExecuteResponse: {:?}", e))?;
        Ok(execute_response)
      })
      .and_then(move |maybe_execute_response| {
        if let Some(execute_response) = maybe_execute_response {
          crate::remote::populate_fallible_execution_result(
            file_store,
            execute_response,
            vec![],
            workunit_store,
          )
          .map(Some)
          .to_boxed()
        } else {
          futures::future::ok(None).to_boxed()
        }
      })
  }

  fn store(
    &self,
    fingerprint: Fingerprint,
    result: &FallibleExecuteProcessResult,
  ) -> impl Future<Item = (), Error = String> {
    let mut execute_response = bazel_protos::remote_execution::ExecuteResponse::new();
    execute_response.set_cached_result(true);
    let action_result = execute_response.mut_result();
    action_result.set_exit_code(result.exit_code);
    action_result.mut_output_directories().push({
      let mut directory = bazel_protos::remote_execution::OutputDirectory::new();
      directory.set_path(String::new());
      directory.set_tree_digest((&result.output_directory).into());
      directory
    });
    let process_execution_store = self.process_execution_store.clone();
    // 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.
    self
      .file_store
      .store_file_bytes(result.stdout.clone(), true)
      .join(
        self
          .file_store
          .store_file_bytes(result.stderr.clone(), true),
      )
      .and_then(move |(stdout_digest, stderr_digest)| {
        let action_result = execute_response.mut_result();
        action_result.set_stdout_digest((&stdout_digest).into());
        action_result.set_stderr_digest((&stderr_digest).into());
        execute_response
          .write_to_bytes()
          .map(Bytes::from)
          .map_err(|err| format!("Error serializing execute process result to cache: {}", err))
      })
      .and_then(move |bytes| process_execution_store.store_bytes(fingerprint, bytes, false))
  }
}

#[cfg(test)]
mod test {
  use crate::{
    CommandRunner as CommandRunnerTrait, ExecuteProcessRequestMetadata,
    FallibleExecuteProcessResult,
  };
  use crate::{ExecuteProcessRequest, Platform};
  use hashing::EMPTY_DIGEST;
  use sharded_lmdb::ShardedLmdb;
  use std::collections::{BTreeMap, BTreeSet};
  use std::io::Write;
  use std::path::PathBuf;
  use std::sync::Arc;
  use std::time::Duration;
  use store::Store;
  use tempfile::TempDir;
  use testutil::data::TestData;
  use workunit_store::WorkUnitStore;

  struct RoundtripResults {
    uncached: Result<FallibleExecuteProcessResult, String>,
    maybe_cached: Result<FallibleExecuteProcessResult, String>,
  }

  fn run_roundtrip(script_exit_code: i8) -> RoundtripResults {
    let runtime = task_executor::Executor::new();
    let work_dir = TempDir::new().unwrap();
    let store_dir = TempDir::new().unwrap();
    let store = Store::local_only(runtime.clone(), store_dir.path()).unwrap();
    let local = crate::local::CommandRunner::new(
      store.clone(),
      runtime.clone(),
      work_dir.path().to_owned(),
      true,
    );

    let script_dir = TempDir::new().unwrap();
    let script_path = script_dir.path().join("script");
    std::fs::File::create(&script_path)
      .and_then(|mut file| {
        writeln!(
          file,
          "echo -n {} > roland && echo Hello && echo >&2 World; exit {}",
          TestData::roland().string(),
          script_exit_code
        )
      })
      .unwrap();

    let request = ExecuteProcessRequest {
      argv: vec![
        testutil::path::find_bash(),
        format!("{}", script_path.display()),
      ],
      env: BTreeMap::new(),
      input_files: EMPTY_DIGEST,
      output_files: vec![PathBuf::from("roland")].into_iter().collect(),
      output_directories: BTreeSet::new(),
      timeout: Duration::from_millis(1000),
      description: "bash".to_string(),
      unsafe_local_only_files_because_we_favor_speed_over_correctness_for_this_rule:
        hashing::EMPTY_DIGEST,
      jdk_home: None,
      target_platform: Platform::None,
    };

    let local_result = runtime.block_on(local.run(request.clone().into(), WorkUnitStore::new()));

    let cache_dir = TempDir::new().unwrap();
    let caching = crate::cache::CommandRunner {
      underlying: Arc::new(local),
      file_store: store.clone(),
      process_execution_store: ShardedLmdb::new(
        cache_dir.path().to_owned(),
        50 * 1024 * 1024,
        runtime.clone(),
      )
      .unwrap(),
      metadata: ExecuteProcessRequestMetadata {
        instance_name: None,
        cache_key_gen_version: None,
        platform_properties: vec![],
      },
    };

    let uncached_result =
      runtime.block_on(caching.run(request.clone().into(), WorkUnitStore::new()));

    assert_eq!(local_result, uncached_result);

    // Removing the file means that were the command to be run again without any caching, it would
    // fail due to a FileNotFound error. So, If the second run succeeds, that implies that the
    // cache was successfully used.
    std::fs::remove_file(&script_path).unwrap();
    let maybe_cached_result = runtime.block_on(caching.run(request.into(), WorkUnitStore::new()));

    RoundtripResults {
      uncached: uncached_result,
      maybe_cached: maybe_cached_result,
    }
  }

  #[test]
  fn cache_success() {
    let results = run_roundtrip(0);
    assert_eq!(results.uncached, results.maybe_cached);
  }

  #[test]
  fn failures_not_cached() {
    let results = run_roundtrip(1);
    assert_ne!(results.uncached, results.maybe_cached);
    assert_eq!(results.uncached.unwrap().exit_code, 1);
    assert_eq!(results.maybe_cached.unwrap().exit_code, 127); // aka the return code for file not found
  }
}
<|endoftext|>


<commit_before>// min-lldb-version: 310

// We have to ignore android because of this issue:
// https://github.com/rust-lang/rust/issues/74847
// ignore-android

// compile-flags:-g

// === GDB TESTS ===================================================================================

// gdb-command:run

// gdb-command:info args
// gdb-check:No arguments.
// gdb-command:continue

// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:frame variable
// lldbg-check:(unsigned long) = 111 (unsigned long) = 222
// lldbr-check:(unsigned long) = 111 (unsigned long) = 222
// lldb-command:continue

#![feature(naked_functions)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]

fn main() {
    naked(111, 222);
}

#[naked]
fn naked(x: usize, y: usize) {
    zzz(); // #break
}

fn zzz() { () }
<commit_msg>Rollup merge of #75224 - Aaron1011:fix/function-arguments-naked, r=Amanieu<commit_after>// min-lldb-version: 310

// We have to ignore android because of this issue:
// https://github.com/rust-lang/rust/issues/74847
// ignore-android
//
// We need to use inline assembly, so just use one platform
// only-x86_64

// compile-flags:-g

// === GDB TESTS ===================================================================================

// gdb-command:run

// gdb-command:info args
// gdb-check:No arguments.
// gdb-command:continue

// === LLDB TESTS ==================================================================================

// lldb-command:run

// lldb-command:frame variable
// lldbg-check:(unsigned long) = 111 (unsigned long) = 222
// lldbr-check:(unsigned long) = 111 (unsigned long) = 222
// lldb-command:continue

#![feature(asm)]
#![feature(naked_functions)]
#![feature(omit_gdb_pretty_printer_section)]
#![omit_gdb_pretty_printer_section]

fn main() {
    naked(111, 222);
}

#[naked]
extern "C" fn naked(x: usize, y: usize) {
    unsafe { asm!("ret"); } // #break
}
<|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 foxbox_taxonomy::manager::WatchGuard;
use foxbox_taxonomy::api::API;
use hyper::net::{ NetworkListener };
use iron::{ AfterMiddleware, Chain, Handler,
            HttpServerFactory, Iron, IronResult, Request,
            Response, ServerFactory };
use iron_cors::CORS;
use iron::error::{ IronError };
use iron::method::Method;
use iron::status::Status;
use mount::Mount;
use router::NoRoute;
use service_router;
use static_router;
use std::net::SocketAddr;
use std::thread;
use taxonomy_router;
use tls::SniServerFactory;
use traits::Controller;

const THREAD_COUNT: usize = 8;

struct Custom404;

impl AfterMiddleware for Custom404 {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        use std::io::Error as StdError;
        use std::io::ErrorKind;

        if let Some(_) = err.error.downcast::<NoRoute>() {
            // Router error
            return Ok(Response::with((Status::NotFound,
                                      format!("Unknown resource: {}", err))));
        } else if let Some(err) = err.error.downcast::<StdError>() {
            // StaticFile error
            if err.kind() == ErrorKind::NotFound {
                return Ok(Response::with((Status::NotFound,
                                          format!("Unknown resource: {}", err))));
            }
        }

        // Just let other errors go through, like 401.
        Err(err)
    }
}

struct Ping;

impl Handler for Ping {
    fn handle (&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::with(Status::Ok))
    }
}

pub struct HttpServer<T: Controller> {
    controller: T
}

impl<T: Controller> HttpServer<T> {
    pub fn new(controller: T) -> Self {
        HttpServer { controller: controller }
    }

    pub fn start<A>(&mut self, adapter_api: A)
        where A: API<WatchGuard=WatchGuard> + 'static {

        let router = service_router::create(self.controller.clone());
        let taxonomy_chain = taxonomy_router::create(self.controller.clone(),
                                                      adapter_api);

        let users_manager = self.controller.get_users_manager();
        let mut mount = Mount::new();
        mount.mount("/", static_router::create(users_manager.clone()))
             .mount("/ping", Ping)
             .mount("/services", router)
             .mount("/api/v1", taxonomy_chain)
             .mount("/users", users_manager.get_router_chain());

        let mut chain = Chain::new(mount);
        chain.link_after(Custom404);

        let cors = CORS::new(vec![
            (vec![Method::Get], "ping".to_owned()),
            (vec![Method::Get, Method::Post, Method::Put, Method::Delete],
             "services/:service/:command".to_owned()),
            (vec![Method::Get], "services/list".to_owned()),

            // Taxonomy router paths. Keep in sync with taxonomy_router.rs
            (vec![Method::Get, Method::Post], "api/v1/services".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/services/tags".to_owned()),
            (vec![Method::Get, Method::Post], "api/v1/channels/getters".to_owned()),
            (vec![Method::Get, Method::Post], "api/v1/channels/setters".to_owned()),
            (vec![Method::Put], "api/v1/channels/get".to_owned()),
            (vec![Method::Put], "api/v1/channels/set".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/channel/getters/tags".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/channel/setters/tags".to_owned())
        ]);
        chain.link_after(cors);

        let addrs: Vec<_> = self.controller.http_as_addrs().unwrap().collect();

        if self.controller.get_tls_enabled() {
            let mut certificate_manager = self.controller.get_certificate_manager();
            let server_factory = SniServerFactory::new(&mut certificate_manager);
            start_server(addrs, chain, server_factory);
        } else {
            start_server(addrs, chain, HttpServerFactory {});
        }
    }
}

fn start_server<TListener, T>(addrs: Vec<SocketAddr>, chain: Chain, factory: T)
    where TListener: NetworkListener + Send + 'static,
          T: ServerFactory<TListener> + Send + 'static {

    thread::Builder::new().name("HttpServer".to_owned())
                          .spawn(move || {
        Iron::new(chain)
             .listen_with(addrs[0], THREAD_COUNT, &factory, None)
             .unwrap();
    }).unwrap();
}

#[cfg(test)]
describe! ping {
    before_each {
        use mount::Mount;
        use iron::Headers;
        use iron::status::Status;
        use iron_test::request;
        use super::Ping;

        let mut mount = Mount::new();
        mount.mount("/ping", Ping);
    }

    it "should response 200 Ok" {
        let response = request::get("http://localhost:3000/ping",
                                    Headers::new(),
                                    &mount).unwrap();
        assert_eq!(response.status.unwrap(), Status::Ok);
    }
}

#[cfg(test)]
describe! cors {
    before_each {
        extern crate hyper;

        use foxbox_taxonomy::manager::AdapterManager;
        use iron::headers;
        use iron::method::Method;
        use std::thread;
        use std::time::Duration;
        use stubs::controller::ControllerStub;

        let taxo_manager = AdapterManager::new();

        let mut http_server = HttpServer::new(ControllerStub::new());
        http_server.start(taxo_manager);
    }

    it "should get the appropriate CORS headers" {
        let endpoints = vec![
            (vec![Method::Get, Method::Post, Method::Put],
             "services/:service/:command".to_owned()),
            (vec![Method::Get], "services/list".to_owned())
        ];
        // HACK: Let some time for the http server to start.
        thread::sleep(Duration::new(3, 0));
        let client = hyper::Client::new();
        for endpoint in endpoints {
            let (_, path) = endpoint;
            let path = "http://localhost:3000/".to_owned() +
                       &(path.replace(":", "foo"));
            let res = client.get(&path).send();
            let headers = &res.unwrap().headers;
            assert!(headers.has::<headers::AccessControlAllowOrigin>());
            assert!(headers.has::<headers::AccessControlAllowHeaders>());
            assert!(headers.has::<headers::AccessControlAllowMethods>());
        };
    }
}

<commit_msg>Add test for the 404 handler. r=fabrice<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 foxbox_taxonomy::manager::WatchGuard;
use foxbox_taxonomy::api::API;
use hyper::net::{ NetworkListener };
use iron::{ AfterMiddleware, Chain, Handler,
            HttpServerFactory, Iron, IronResult, Request,
            Response, ServerFactory };
use iron_cors::CORS;
use iron::error::{ IronError };
use iron::method::Method;
use iron::status::Status;
use mount::Mount;
use router::NoRoute;
use service_router;
use static_router;
use std::net::SocketAddr;
use std::thread;
use taxonomy_router;
use tls::SniServerFactory;
use traits::Controller;

const THREAD_COUNT: usize = 8;

struct Custom404;

impl AfterMiddleware for Custom404 {
    fn catch(&self, _: &mut Request, err: IronError) -> IronResult<Response> {
        use std::io::Error as StdError;
        use std::io::ErrorKind;

        if let Some(_) = err.error.downcast::<NoRoute>() {
            // Router error
            return Ok(Response::with((Status::NotFound,
                                      format!("Unknown resource: {}", err))));
        } else if let Some(err) = err.error.downcast::<StdError>() {
            // StaticFile error
            if err.kind() == ErrorKind::NotFound {
                return Ok(Response::with((Status::NotFound,
                                          format!("Unknown resource: {}", err))));
            }
        }

        // Just let other errors go through, like 401.
        Err(err)
    }
}

struct Ping;

impl Handler for Ping {
    fn handle (&self, _: &mut Request) -> IronResult<Response> {
        Ok(Response::with(Status::Ok))
    }
}

pub struct HttpServer<T: Controller> {
    controller: T
}

impl<T: Controller> HttpServer<T> {
    pub fn new(controller: T) -> Self {
        HttpServer { controller: controller }
    }

    pub fn start<A>(&mut self, adapter_api: A)
        where A: API<WatchGuard=WatchGuard> + 'static {

        let router = service_router::create(self.controller.clone());
        let taxonomy_chain = taxonomy_router::create(self.controller.clone(),
                                                      adapter_api);

        let users_manager = self.controller.get_users_manager();
        let mut mount = Mount::new();
        mount.mount("/", static_router::create(users_manager.clone()))
             .mount("/ping", Ping)
             .mount("/services", router)
             .mount("/api/v1", taxonomy_chain)
             .mount("/users", users_manager.get_router_chain());

        let mut chain = Chain::new(mount);
        chain.link_after(Custom404);

        let cors = CORS::new(vec![
            (vec![Method::Get], "ping".to_owned()),
            (vec![Method::Get, Method::Post, Method::Put, Method::Delete],
             "services/:service/:command".to_owned()),
            (vec![Method::Get], "services/list".to_owned()),

            // Taxonomy router paths. Keep in sync with taxonomy_router.rs
            (vec![Method::Get, Method::Post], "api/v1/services".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/services/tags".to_owned()),
            (vec![Method::Get, Method::Post], "api/v1/channels/getters".to_owned()),
            (vec![Method::Get, Method::Post], "api/v1/channels/setters".to_owned()),
            (vec![Method::Put], "api/v1/channels/get".to_owned()),
            (vec![Method::Put], "api/v1/channels/set".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/channel/getters/tags".to_owned()),
            (vec![Method::Post, Method::Delete], "api/v1/channel/setters/tags".to_owned())
        ]);
        chain.link_after(cors);

        let addrs: Vec<_> = self.controller.http_as_addrs().unwrap().collect();

        if self.controller.get_tls_enabled() {
            let mut certificate_manager = self.controller.get_certificate_manager();
            let server_factory = SniServerFactory::new(&mut certificate_manager);
            start_server(addrs, chain, server_factory);
        } else {
            start_server(addrs, chain, HttpServerFactory {});
        }
    }
}

fn start_server<TListener, T>(addrs: Vec<SocketAddr>, chain: Chain, factory: T)
    where TListener: NetworkListener + Send + 'static,
          T: ServerFactory<TListener> + Send + 'static {

    thread::Builder::new().name("HttpServer".to_owned())
                          .spawn(move || {
        Iron::new(chain)
             .listen_with(addrs[0], THREAD_COUNT, &factory, None)
             .unwrap();
    }).unwrap();
}

#[cfg(test)]
describe! ping {
    before_each {
        use mount::Mount;
        use iron::Headers;
        use iron::status::Status;
        use iron_test::request;
        use super::Ping;

        let mut mount = Mount::new();
        mount.mount("/ping", Ping);
    }

    it "should response 200 Ok" {
        let response = request::get("http://localhost:3000/ping",
                                    Headers::new(),
                                    &mount).unwrap();
        assert_eq!(response.status.unwrap(), Status::Ok);
    }
}

#[cfg(test)]
describe! http_server {
    before_each {
        extern crate hyper;

        use foxbox_taxonomy::manager::AdapterManager;
        use std::thread;
        use std::time::Duration;
        use stubs::controller::ControllerStub;

        let taxo_manager = AdapterManager::new();

        let mut http_server = HttpServer::new(ControllerStub::new());
        http_server.start(taxo_manager);
        // HACK: Let some time for the http server to start.
        thread::sleep(Duration::new(3, 0));
    }

    it "should get the appropriate CORS headers" {
        use iron::headers;
        use iron::method::Method;

        let endpoints = vec![
            (vec![Method::Get, Method::Post, Method::Put],
             "services/:service/:command".to_owned()),
            (vec![Method::Get], "services/list".to_owned())
        ];
        let client = hyper::Client::new();
        for endpoint in endpoints {
            let (_, path) = endpoint;
            let path = "http://localhost:3000/".to_owned() +
                       &(path.replace(":", "foo"));
            let res = client.get(&path).send();
            let headers = &res.unwrap().headers;
            assert!(headers.has::<headers::AccessControlAllowOrigin>());
            assert!(headers.has::<headers::AccessControlAllowHeaders>());
            assert!(headers.has::<headers::AccessControlAllowMethods>());
        };
    }

    it "should respond with 404" {
        use iron::status::Status;
        use std::io::Read;

        let client = hyper::Client::new();
        let path = "http://localhost:3000/foo/bar".to_owned();
        let mut res = client.get(&path).send().unwrap();
        assert_eq!(res.status, Status::NotFound);
        let mut body = String::new();
        res.read_to_string(&mut body).unwrap();
        assert_eq!(body, "Unknown resource: No such file or \
                   directory (os error 2)".to_owned());
    }
}

<|endoftext|>


<commit_before>use token;

pub struct Interpreter {
    tokenizer: token::Tokenizer,
    current: Option<token::Token>
}

impl Interpreter {
    pub fn new(text: token::Tokenizer) -> Self {
        Interpreter {
            tokenizer: text,
            current: None
        }
    }

    pub fn next(&mut self, kind: token::Kind) -> Option<token::Token> {
        let current = self.tokenizer.next();
        if let Some(token) = current {
            self.current = Some(token);
            self.current.clone()
        } else {
            panic!("Sintax error")
        }
    }

    pub fn expr(&mut self) -> String {
        let left = self.next(token::Kind::Integer);
        let op = self.next(token::Kind::Operator);
        let right = self.next(token::Kind::Integer);

        format!("{}", calc(left.unwrap(), op.unwrap(), right.unwrap()))
    }
}

fn calc(first: token::Token, operator: token::Token, second: token::Token) -> i32 {
    println!("{:?}", operator);
    match &*operator.value {
        "+" => first.as_integer() + second.as_integer(),
        "-" => first.as_integer() - second.as_integer(),
        "*" => first.as_integer() * second.as_integer(),
        "/" => first.as_integer() / second.as_integer(),
        _ => panic!("Sintax error")
    }
}

#[test]
fn it_sums() {
    let text = "5+1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("6", interpreter.expr());
}

#[test]
fn it_substract() {
    let text = "5-1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("4", interpreter.expr());
}

#[test]
fn it_multiplies() {
    let text = "5*2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("10", interpreter.expr());
}

#[test]
fn it_divide() {
    let text = "4/2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("2", interpreter.expr());
}
<commit_msg>fix: validate sintax for expression<commit_after>use token;

pub struct Interpreter {
    tokenizer: token::Tokenizer,
    current: Option<token::Token>
}

impl Interpreter {
    pub fn new(text: token::Tokenizer) -> Self {
        Interpreter {
            tokenizer: text,
            current: None
        }
    }

    pub fn next(&mut self, kind: token::Kind) -> Option<token::Token> {
        let current = self.tokenizer.next();
        if let Some(token) = current {
            if token.kind != kind {
                panic!("Sintax error")
            }
            self.current = Some(token);
        }
        self.current.clone()
    }

    pub fn expr(&mut self) -> String {
        let left = self.next(token::Kind::Integer);
        let op = self.next(token::Kind::Operator);
        let right = self.next(token::Kind::Integer);

        format!("{}", calc(left.unwrap(), op.unwrap(), right.unwrap()))
    }
}

fn calc(first: token::Token, operator: token::Token, second: token::Token) -> i32 {
    println!("{:?}", operator);
    match &*operator.value {
        "+" => first.as_integer() + second.as_integer(),
        "-" => first.as_integer() - second.as_integer(),
        "*" => first.as_integer() * second.as_integer(),
        "/" => first.as_integer() / second.as_integer(),
        _ => panic!("Sintax error")
    }
}

#[test]
fn it_sums() {
    let text = "5+1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("6", interpreter.expr());
}

#[test]
fn it_substract() {
    let text = "5-1";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("4", interpreter.expr());
}

#[test]
fn it_multiplies() {
    let text = "5*2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("10", interpreter.expr());
}

#[test]
fn it_divide() {
    let text = "4/2";
    let tokenizer = token::Tokenizer::new(String::from(text));
    let mut interpreter = Interpreter::new(tokenizer);

    assert_eq!("2", interpreter.expr());
}
<|endoftext|>


<commit_before>fn main() {
    let days = ["first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth",
                "ninth", "tenth", "eleventh", "twelfth"];

    let gifts = ["A Patridge in a Pear Tree",
                 "Two Turtle Doves and",
                 "Three French Hens",
                 "Four Calling Birds",
                 "Five Golden Rings",
                 "Six Geese a Laying",
                 "Seven Swans a Swimming",
                 "Eight Maids a Milking",
                 "Nine Ladies Dancing",
                 "Ten Lords a Leaping",
                 "Eleven Pipers Piping",
                 "Twelve Drummers Drumming"];

    for i in 0..12 {
        println!("On the {} day of Christmas,", days[i]);
        println!("My true love sent to me:");

        for j in (0..i + 1).rev() {
            println!("{}", gifts[j]);
        }
        println!()
    }
}
<commit_msg>Changed "sent" to "gave"<commit_after>fn main() {
    let days = ["first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth",
                "ninth", "tenth", "eleventh", "twelfth"];

    let gifts = ["A Patridge in a Pear Tree",
                 "Two Turtle Doves and",
                 "Three French Hens",
                 "Four Calling Birds",
                 "Five Golden Rings",
                 "Six Geese a Laying",
                 "Seven Swans a Swimming",
                 "Eight Maids a Milking",
                 "Nine Ladies Dancing",
                 "Ten Lords a Leaping",
                 "Eleven Pipers Piping",
                 "Twelve Drummers Drumming"];

    for i in 0..12 {
        println!("On the {} day of Christmas,", days[i]);
        println!("My true love gave to me:");

        for j in (0..i + 1).rev() {
            println!("{}", gifts[j]);
        }
        println!()
    }
}
<|endoftext|>


<commit_before>// The elements of an array can be accessed by their indices
// arr[4]
#[test]
fn array_index() {
  let arr: [i32; 5] = [1, 2, 3, 4, 5];
  assert!(arr[__] == 1);
}

// A new fixed size array can be created by declaring
// the type of its elements along with its length
// [i32; 0] = []
#[test]
fn array_empty() {
  let arr: __;
  assert!(arr.len() == 0);
}

// Attempting to access an array at an index that is
// out of its bounds will cause an error. Let's cause
// that error in this example.
#[test]
#[should_panic]
fn out_of_index() {
  let arr: [&'static str; 5] = ["rust", "is", "mostly", "for", "nerds"];
  arr[__];
}
<commit_msg>Add insert_at_index koan<commit_after>// The elements of an array can be accessed by their indices
// arr[4]
#[test]
fn array_index() {
  let arr: [i32; 5] = [1, 2, 3, 4, 5];
  assert!(arr[__] == 1);
}

// A new fixed size array can be created by declaring the type of its elements
// along with its length
// [i32; 0] = []
#[test]
fn array_empty() {
  let arr: __;
  assert!(arr.len() == 0);
}

// Attempting to access an array at an index that is
// out of its bounds will cause an error. Let's cause
// that error in this example.
#[test]
#[should_panic]
fn out_of_index() {
  let arr: [&'static str; 5] = ["rust", "is", "mostly", "for", "nerds"];
  arr[__];
}

// Elements can be replaced in an array at a certain index.
// hint: Without the 'mut' keyword, you won't be able to change data.
#[test]
fn insert_at_index() {
  let mut arr: [u8; 5] = [0, 1, 2, 3, 4];
  __ = 0;
  assert!(arr == [0, 1, 2, 3, 0]);
}
<|endoftext|>


<commit_before>#![crate_name = "uu_mknod"]

// This file is part of the uutils coreutils package.
//
// (c) Jian Zeng <anonymousknight96@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

extern crate getopts;
extern crate libc;

mod parsemode;

#[macro_use]
extern crate uucore;

use libc::{mode_t, dev_t};
use libc::{S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, S_IWOTH, S_IFIFO, S_IFBLK, S_IFCHR};

use getopts::Options;
use std::io::Write;

use std::ffi::CString;

static NAME: &'static str = "mknod";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

const MODE_RW_UGO: mode_t = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

#[inline(always)]
fn makedev(maj: u64, min: u64) -> dev_t {
    // pick up from <sys/sysmacros.h>
    ((min & 0xff) | ((maj & 0xfff) << 8) | (((min & !0xff)) << 12) |
     (((maj & !0xfff)) << 32)) as dev_t
}

#[cfg(windows)]
fn _makenod(path: CString, mode: mode_t, dev: dev_t) -> i32 {
    panic!("Unsupported for windows platform")
}

#[cfg(unix)]
fn _makenod(path: CString, mode: mode_t, dev: dev_t) -> i32 {
    unsafe { libc::mknod(path.as_ptr(), mode, dev) }
}

macro_rules! disp_err {
    ($($args:tt)+) => ({
        pipe_write!(&mut ::std::io::stderr(), "{}: ", NAME);
        pipe_writeln!(&mut ::std::io::stderr(), $($args)+);
        pipe_writeln!(&mut ::std::io::stderr(), "Try '{} --help' for more information.", NAME);
    })
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    // Linux-specific options, not implemented
    // opts.optflag("Z", "", "set the SELinux security context to default type");
    // opts.optopt("", "context", "like -Z, or if CTX is specified then set the SELinux or SMACK security context to CTX");
    opts.optopt("m",
                "mode",
                "set file permission bits to MODE, not a=rw - umask",
                "MODE");

    opts.optflag("", "help", "display this help and exit");
    opts.optflag("", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}\nTry '{} --help' for more information.", f, NAME),
    };

    if matches.opt_present("help") {
        println!(
"Usage: {0} [OPTION]... NAME TYPE [MAJOR MINOR]

Mandatory arguments to long options are mandatory for short options too.
  -m, --mode=MODE    set file permission bits to MODE, not a=rw - umask
      --help     display this help and exit
      --version  output version information and exit

Both MAJOR and MINOR must be specified when TYPE is b, c, or u, and they
must be omitted when TYPE is p.  If MAJOR or MINOR begins with 0x or 0X,
it is interpreted as hexadecimal; otherwise, if it begins with 0, as octal;
otherwise, as decimal.  TYPE may be:

  b      create a block (buffered) special file
  c, u   create a character (unbuffered) special file
  p      create a FIFO

NOTE: your shell may have its own version of mknod, which usually supersedes
the version described here.  Please refer to your shell's documentation
for details about the options it supports.", NAME);
        return 0;
    }

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    let mut last_umask: mode_t = 0;
    let mut newmode: mode_t = MODE_RW_UGO;
    if matches.opt_present("mode") {
        match parsemode::parse_mode(matches.opt_str("mode")) {
            Ok(parsed) => {
                if parsed > 0o777 {
                    show_info!("mode must specify only file permission bits");
                    return 1;
                }
                newmode = parsed;
            }
            Err(e) => {
                show_info!("{}", e);
                return 1;
            }
        }
        unsafe {
            last_umask = libc::umask(0);
        }
    }

    let mut ret = 0i32;
    match matches.free.len() {
        0 => disp_err!("missing operand"),
        1 => disp_err!("missing operand after ‘{}’", matches.free[0]),
        _ => {
            let args = &matches.free;
            let c_str = CString::new(args[0].as_str()).expect("Failed to convert to CString");

            // Only check the first character, to allow mnemonic usage like
            // 'mknod /dev/rst0 character 18 0'.
            let ch = args[1].chars().nth(0).expect("Failed to get the first char");

            if ch == 'p' {
                if args.len() > 2 {
                    show_info!("{}: extra operand ‘{}’", NAME, args[2]);
                    if args.len() == 4 {
                        eprintln!("Fifos do not have major and minor device numbers.");
                    }
                    eprintln!("Try '{} --help' for more information.", NAME);
                    return 1;
                }

                ret = _makenod(c_str, S_IFIFO | newmode, 0);
            } else {
                if args.len() < 4 {
                    show_info!("missing operand after ‘{}’", args[args.len() - 1]);
                    if args.len() == 2 {
                        eprintln!("Special files require major and minor device numbers.");
                    }
                    eprintln!("Try '{} --help' for more information.", NAME);
                    return 1;
                } else if args.len() > 4 {
                    disp_err!("extra operand ‘{}’", args[4]);
                    return 1;
                } else if !"bcu".contains(ch) {
                    disp_err!("invalid device type ‘{}’", args[1]);
                    return 1;
                }

                let maj = args[2].parse::<u64>();
                let min = args[3].parse::<u64>();
                if maj.is_err() {
                    show_info!("invalid major device number ‘{}’", args[2]);
                    return 1;
                } else if min.is_err() {
                    show_info!("invalid minor device number ‘{}’", args[3]);
                    return 1;
                }

                let (maj, min) = (maj.unwrap(), min.unwrap());
                let dev = makedev(maj, min);
                if ch == 'b' {
                    // block special file
                    ret = _makenod(c_str, S_IFBLK | newmode, dev);
                } else {
                    // char special file
                    ret = _makenod(c_str, S_IFCHR | newmode, dev);
                }
            }
        }
    }

    if last_umask != 0 {
        unsafe {
            libc::umask(last_umask);
        }
    }
    if ret == -1 {
        let c_str = CString::new(format!("{}: {}", NAME, matches.free[0]).as_str())
                        .expect("Failed to convert to CString");
        unsafe {
            libc::perror(c_str.as_ptr());
        }
    }

    ret
}
<commit_msg>mknod: remove repeated macro<commit_after>#![crate_name = "uu_mknod"]

// This file is part of the uutils coreutils package.
//
// (c) Jian Zeng <anonymousknight96@gmail.com>
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//

extern crate getopts;
extern crate libc;

mod parsemode;

#[macro_use]
extern crate uucore;

use libc::{mode_t, dev_t};
use libc::{S_IRUSR, S_IWUSR, S_IRGRP, S_IWGRP, S_IROTH, S_IWOTH, S_IFIFO, S_IFBLK, S_IFCHR};

use getopts::Options;
use std::io::Write;

use std::ffi::CString;

static NAME: &'static str = "mknod";
static VERSION: &'static str = env!("CARGO_PKG_VERSION");

const MODE_RW_UGO: mode_t = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH;

#[inline(always)]
fn makedev(maj: u64, min: u64) -> dev_t {
    // pick up from <sys/sysmacros.h>
    ((min & 0xff) | ((maj & 0xfff) << 8) | (((min & !0xff)) << 12) |
     (((maj & !0xfff)) << 32)) as dev_t
}

#[cfg(windows)]
fn _makenod(path: CString, mode: mode_t, dev: dev_t) -> i32 {
    panic!("Unsupported for windows platform")
}

#[cfg(unix)]
fn _makenod(path: CString, mode: mode_t, dev: dev_t) -> i32 {
    unsafe { libc::mknod(path.as_ptr(), mode, dev) }
}

pub fn uumain(args: Vec<String>) -> i32 {
    let mut opts = Options::new();

    // Linux-specific options, not implemented
    // opts.optflag("Z", "", "set the SELinux security context to default type");
    // opts.optopt("", "context", "like -Z, or if CTX is specified then set the SELinux or SMACK security context to CTX");
    opts.optopt("m",
                "mode",
                "set file permission bits to MODE, not a=rw - umask",
                "MODE");

    opts.optflag("", "help", "display this help and exit");
    opts.optflag("", "version", "output version information and exit");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => m,
        Err(f) => crash!(1, "{}\nTry '{} --help' for more information.", f, NAME),
    };

    if matches.opt_present("help") {
        println!(
"Usage: {0} [OPTION]... NAME TYPE [MAJOR MINOR]

Mandatory arguments to long options are mandatory for short options too.
  -m, --mode=MODE    set file permission bits to MODE, not a=rw - umask
      --help     display this help and exit
      --version  output version information and exit

Both MAJOR and MINOR must be specified when TYPE is b, c, or u, and they
must be omitted when TYPE is p.  If MAJOR or MINOR begins with 0x or 0X,
it is interpreted as hexadecimal; otherwise, if it begins with 0, as octal;
otherwise, as decimal.  TYPE may be:

  b      create a block (buffered) special file
  c, u   create a character (unbuffered) special file
  p      create a FIFO

NOTE: your shell may have its own version of mknod, which usually supersedes
the version described here.  Please refer to your shell's documentation
for details about the options it supports.", NAME);
        return 0;
    }

    if matches.opt_present("version") {
        println!("{} {}", NAME, VERSION);
        return 0;
    }

    let mut last_umask: mode_t = 0;
    let mut newmode: mode_t = MODE_RW_UGO;
    if matches.opt_present("mode") {
        match parsemode::parse_mode(matches.opt_str("mode")) {
            Ok(parsed) => {
                if parsed > 0o777 {
                    show_info!("mode must specify only file permission bits");
                    return 1;
                }
                newmode = parsed;
            }
            Err(e) => {
                show_info!("{}", e);
                return 1;
            }
        }
        unsafe {
            last_umask = libc::umask(0);
        }
    }

    let mut ret = 0i32;
    match matches.free.len() {
        0 => disp_err!("missing operand"),
        1 => disp_err!("missing operand after ‘{}’", matches.free[0]),
        _ => {
            let args = &matches.free;
            let c_str = CString::new(args[0].as_str()).expect("Failed to convert to CString");

            // Only check the first character, to allow mnemonic usage like
            // 'mknod /dev/rst0 character 18 0'.
            let ch = args[1].chars().nth(0).expect("Failed to get the first char");

            if ch == 'p' {
                if args.len() > 2 {
                    show_info!("{}: extra operand ‘{}’", NAME, args[2]);
                    if args.len() == 4 {
                        eprintln!("Fifos do not have major and minor device numbers.");
                    }
                    eprintln!("Try '{} --help' for more information.", NAME);
                    return 1;
                }

                ret = _makenod(c_str, S_IFIFO | newmode, 0);
            } else {
                if args.len() < 4 {
                    show_info!("missing operand after ‘{}’", args[args.len() - 1]);
                    if args.len() == 2 {
                        eprintln!("Special files require major and minor device numbers.");
                    }
                    eprintln!("Try '{} --help' for more information.", NAME);
                    return 1;
                } else if args.len() > 4 {
                    disp_err!("extra operand ‘{}’", args[4]);
                    return 1;
                } else if !"bcu".contains(ch) {
                    disp_err!("invalid device type ‘{}’", args[1]);
                    return 1;
                }

                let maj = args[2].parse::<u64>();
                let min = args[3].parse::<u64>();
                if maj.is_err() {
                    show_info!("invalid major device number ‘{}’", args[2]);
                    return 1;
                } else if min.is_err() {
                    show_info!("invalid minor device number ‘{}’", args[3]);
                    return 1;
                }

                let (maj, min) = (maj.unwrap(), min.unwrap());
                let dev = makedev(maj, min);
                if ch == 'b' {
                    // block special file
                    ret = _makenod(c_str, S_IFBLK | newmode, dev);
                } else {
                    // char special file
                    ret = _makenod(c_str, S_IFCHR | newmode, dev);
                }
            }
        }
    }

    if last_umask != 0 {
        unsafe {
            libc::umask(last_umask);
        }
    }
    if ret == -1 {
        let c_str = CString::new(format!("{}: {}", NAME, matches.free[0]).as_str())
                        .expect("Failed to convert to CString");
        unsafe {
            libc::perror(c_str.as_ptr());
        }
    }

    ret
}
<|endoftext|>


<commit_before>use std::io::Read;
use std::io::BufReader;
use std::io::Error as IoError;
use std::ascii::AsciiExt;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};
extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder};

enum DecodeStrategy {
    Bytes,
    Ascii,
}

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
    samples: u32,
    decoder: DecodeStrategy,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(read: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(read);
        let mut magic: [u8; 2] = [0, 0];
        try!(buf.read_exact(&mut magic[..])); // Skip magic constant
        if magic[0] != b'P' || (magic[1] != b'3' && magic[1] != b'6') {
            return Err(ImageError::FormatError("Expected magic constant for ppm, P3 or P6".to_string()));
        }

        // Remove this once the reader can read plain ppm
        if magic[1] == b'3' {
            return Err(ImageError::FormatError("Plain format is not yet supported".to_string()))
        }

        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));

        if !(maxwhite <= u16::max_value() as u32) {
            return Err(ImageError::FormatError("Image maxval is not less or equal to 65535".to_string()))
        }

        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
            samples: 3,
            decoder: DecodeStrategy::Bytes,
        })
    }

    /// Reads a string as well as a single whitespace after it, ignoring comments
    fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
        let mut bytes = Vec::new();

        // pair input bytes with a bool mask to remove comments
        let mark_comments = reader
            .bytes()
            .scan(true, |partof, read| {
                let byte = match read {
                    Err(err) => return Some((*partof, Err(err))),
                    Ok(byte) => byte,
                };
                let cur_enabled = *partof && byte != b'#';
                let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n');
                *partof = next_enabled;
                return Some((cur_enabled, Ok(byte)));
            });

        for (_, byte) in mark_comments.filter(|ref e| e.0) {
            match byte {
                Ok(b'\t') | Ok(b'\n') | Ok(b'\x0b') | Ok(b'\x0c') | Ok(b'\r') | Ok(b' ') => {
                    if !bytes.is_empty() {
                        break // We're done as we already have some content
                    }
                },
                Ok(byte) => {
                    bytes.push(byte);
                },
                Err(_) => break,
            }
        }

        if bytes.is_empty() {
            return Err(ImageError::FormatError("Unexpected eof".to_string()))
        }

        if !bytes.as_slice().is_ascii() {
            return Err(ImageError::FormatError("Non ascii character in preamble".to_string()))
        }

        String::from_utf8(bytes).map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }

    fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
        let s = try!(PPMDecoder::read_next_string(reader));
        s.parse::<u32>().map_err(|_| ImageError::FormatError("Invalid number in preamble".to_string()))
    }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match (self.bytewidth(), self.components()) {
            (1, 3) => Ok(ColorType::RGB(8)),
            (2, 3) => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*self.components()*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let opt_size = self.width.checked_mul(self.height)
            .map_or(None, |v| v.checked_mul(self.components()))
            .map_or(None, |v| v.checked_mul(self.bytewidth()));

        let size = match opt_size {
            Some(v) => v,
            None => return Err(ImageError::DimensionError),
        };

        let mut data = vec![0 as u8; size as usize];

        match self.reader.read_exact(&mut data) {
            Ok(_) => {},
            Err(e) => return Err(ImageError::IoError(e)),
        };

        if self.bytewidth() == 1 {
            Ok(DecodingResult::U8(data))
        } else {
            let mut out = vec![0 as u16; (self.width*self.height*3) as usize];
            for (o, i) in out.chunks_mut(1).zip(data.chunks(2)) {
                o[0] = BigEndian::read_u16(i);
            }
            Ok(DecodingResult::U16(out))
        }
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }

    fn components(&self) -> u32 {
        self.samples
    }
}

/// Tests parsing binary buffers were written based on and validated against `pamfile` from
/// netpbm (http://netpbm.sourceforge.net/).
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn minimal_form() {
        // Violates current specification (October 2016 ) but accepted by both netpbm and ImageMagick
        decode_minimal_image(&b"P61 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123\xFF"[..]); // Too long should not be an issue
    }

    #[test]
    fn comment_in_token() {
        decode_minimal_image(&b"P6 1 1 2#comment\n55 123"[..]); // Terminating LF
        decode_minimal_image(&b"P6 1 1 2#comment\r55 123"[..]); // Terminating CR
        decode_minimal_image(&b"P6 1 1#comment\n 255 123"[..]); // Comment after token
        decode_minimal_image(&b"P6 1 1 #comment\n255 123"[..]); // Comment before token
        decode_minimal_image(&b"P6#comment\n 1 1 255 123"[..]); // Begin of header
        decode_minimal_image(&b"P6 1 1 255#comment\n 123"[..]); // End of header
    }

    #[test]
    fn whitespace() {
        decode_minimal_image(&b"P6\x091\x091\x09255\x09123"[..]); // TAB
        decode_minimal_image(&b"P6\x0a1\x0a1\x0a255\x0a123"[..]); // LF
        decode_minimal_image(&b"P6\x0b1\x0b1\x0b255\x0b123"[..]); // VT
        decode_minimal_image(&b"P6\x0c1\x0c1\x0c255\x0c123"[..]); // FF
        decode_minimal_image(&b"P6\x0d1\x0d1\x0d255\x0d123"[..]); // CR
        // Spaces tested before
        decode_minimal_image(&b"P61\x09\x0a\x0b\x0c\x0d1 255 123"[..]); // All whitespace, combined
    }

    /// Tests for decoding error, assuming `encoded` is ppm encoding for the very simplistic image
    /// containing a single pixel with one byte values (1, 2, 3).
    fn decode_minimal_image(encoded: &[u8]) {
        let content = vec![49 as u8, 50, 51];
        let mut decoder = PPMDecoder::new(encoded).unwrap();

        assert_eq!(decoder.dimensions().unwrap(), (1, 1));
        assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
        assert_eq!(decoder.row_len().unwrap(), 3);
        assert_eq!(decoder.bytewidth(), 1);

        match decoder.read_image().unwrap() {
            DecodingResult::U8(image) => assert_eq!(image, content),
            _ => assert!(false),
        }
    }

    #[test]
    fn wrong_tag() {
        assert!(PPMDecoder::new(&b"P5 1 1 255 1"[..]).is_err());
    }

    #[test]
    fn invalid_characters() {
        assert!(PPMDecoder::new(&b"P6 1chars1 255 1"[..]).is_err()); // No text outside of comments
        assert!(PPMDecoder::new(&b"P6 1\xFF1 255 1"[..]).is_err()); // No invalid ascii chars
        assert!(PPMDecoder::new(&b"P6 0x01 1 255 1"[..]).is_err()); // Numbers only as decimal
    }

    /// These violate the narrow specification of ppm but are commonly supported in other programs.
    /// Fail fast and concise is important here as these might be received as input files.
    #[test]
    fn unsupported_extensions() {
        assert!(PPMDecoder::new(&b"P6 1 1 65536 1"[..]).is_err()); // No bitwidth above 16
    }
}
<commit_msg>Add potential ascii reader match<commit_after>use std::io::Read;
use std::io::BufReader;
use std::io::Error as IoError;
use std::ascii::AsciiExt;

use color::{ColorType};
use image::{DecodingResult, ImageDecoder, ImageResult, ImageError};
extern crate byteorder;
use self::byteorder::{BigEndian, ByteOrder};

enum DecodeStrategy {
    Bytes,
    Ascii,
}

/// PPM decoder
pub struct PPMDecoder<R> {
    reader: BufReader<R>,
    width: u32,
    height: u32,
    maxwhite: u32,
    samples: u32,
    decoder: DecodeStrategy,
}

impl<R: Read> PPMDecoder<R> {
    /// Create a new decoder that decodes from the stream ```r```
    pub fn new(read: R) -> ImageResult<PPMDecoder<R>> {
        let mut buf = BufReader::new(read);
        let mut magic: [u8; 2] = [0, 0];
        try!(buf.read_exact(&mut magic[..])); // Skip magic constant
        if magic[0] != b'P' || (magic[1] != b'3' && magic[1] != b'6') {
            return Err(ImageError::FormatError("Expected magic constant for ppm, P3 or P6".to_string()));
        }

        // Remove this once the reader can read plain ppm
        if magic[1] == b'3' {
            return Err(ImageError::FormatError("Plain format is not yet supported".to_string()))
        }

        let width = try!(PPMDecoder::read_next_u32(&mut buf));
        let height = try!(PPMDecoder::read_next_u32(&mut buf));
        let maxwhite = try!(PPMDecoder::read_next_u32(&mut buf));

        if !(maxwhite <= u16::max_value() as u32) {
            return Err(ImageError::FormatError("Image maxval is not less or equal to 65535".to_string()))
        }

        Ok(PPMDecoder {
            reader: buf,
            width: width,
            height: height,
            maxwhite: maxwhite,
            samples: 3,
            decoder: DecodeStrategy::Bytes,
        })
    }

    /// Reads a string as well as a single whitespace after it, ignoring comments
    fn read_next_string(reader: &mut BufReader<R>) -> ImageResult<String> {
        let mut bytes = Vec::new();

        // pair input bytes with a bool mask to remove comments
        let mark_comments = reader
            .bytes()
            .scan(true, |partof, read| {
                let byte = match read {
                    Err(err) => return Some((*partof, Err(err))),
                    Ok(byte) => byte,
                };
                let cur_enabled = *partof && byte != b'#';
                let next_enabled = cur_enabled || (byte == b'\r' || byte == b'\n');
                *partof = next_enabled;
                return Some((cur_enabled, Ok(byte)));
            });

        for (_, byte) in mark_comments.filter(|ref e| e.0) {
            match byte {
                Ok(b'\t') | Ok(b'\n') | Ok(b'\x0b') | Ok(b'\x0c') | Ok(b'\r') | Ok(b' ') => {
                    if !bytes.is_empty() {
                        break // We're done as we already have some content
                    }
                },
                Ok(byte) => {
                    bytes.push(byte);
                },
                Err(_) => break,
            }
        }

        if bytes.is_empty() {
            return Err(ImageError::FormatError("Unexpected eof".to_string()))
        }

        if !bytes.as_slice().is_ascii() {
            return Err(ImageError::FormatError("Non ascii character in preamble".to_string()))
        }

        String::from_utf8(bytes).map_err(|_| ImageError::FormatError("Couldn't read preamble".to_string()))
    }

    fn read_next_u32(reader: &mut BufReader<R>) -> ImageResult<u32> {
        let s = try!(PPMDecoder::read_next_string(reader));
        s.parse::<u32>().map_err(|_| ImageError::FormatError("Invalid number in preamble".to_string()))
    }
}

impl<R: Read> ImageDecoder for PPMDecoder<R> {
    fn dimensions(&mut self) -> ImageResult<(u32, u32)> {
        Ok((self.width, self.height))
    }

    fn colortype(&mut self) -> ImageResult<ColorType> {
        match (self.bytewidth(), self.components()) {
            (1, 3) => Ok(ColorType::RGB(8)),
            (2, 3) => Ok(ColorType::RGB(16)),
            _ => Err(ImageError::FormatError("Don't know how to decode PPM with more than 16 bits".to_string())),
        }
    }

    fn row_len(&mut self) -> ImageResult<usize> {
        Ok((self.width*self.components()*self.bytewidth()) as usize)
    }

    fn read_scanline(&mut self, _buf: &mut [u8]) -> ImageResult<u32> {
        unimplemented!();
    }

    fn read_image(&mut self) -> ImageResult<DecodingResult> {
        let pixelcount = self.width
            .checked_mul(self.height)
            .and_then(|v| v.checked_mul(self.components()));

        let pixelcount = match pixelcount {
            Some(v) => v,
            _ => return Err(ImageError::DimensionError),
        };

        self.read(pixelcount)
    }
}

impl<R: Read> PPMDecoder<R> {
    fn bytewidth(&self) -> u32 {
        if self.maxwhite < 256 { 1 } else { 2 }
    }

    fn components(&self) -> u32 {
        self.samples
    }

    fn read(&mut self, count: u32) -> ImageResult<DecodingResult> {
        if self.bytewidth() == 1 {
            let mut data = vec![0 as u8; count as usize];
            self.read_u8(&mut data)?;
            Ok(DecodingResult::U8(data))
        } else if self.bytewidth() == 2 {
            let mut data = vec![0 as u16; count as usize];
            self.read_u16(&mut data)?;
            Ok(DecodingResult::U16(data))
        } else {
            Err(ImageError::FormatError("Invalid sample bitwidth".to_string()))
        }
    }

    fn read_u8(&mut self, mut buffer: &mut [u8]) -> ImageResult<()> {
        match self.decoder {
            DecodeStrategy::Bytes => match self.reader.read_exact(&mut buffer) {
                    Ok(_) => Ok(()),
                    Err(e) => Err(ImageError::IoError(e)),
                },
            DecodeStrategy::Ascii => {
                    unimplemented!()
                }
        }
    }

    fn read_u16(&mut self, mut buffer: &mut [u16]) -> ImageResult<()> {
        match self.decoder {
            DecodeStrategy::Bytes => {
                    let mut bytebuffer = vec![0 as u8; buffer.len() * 2];
                    match self.reader.read_exact(&mut bytebuffer) {
                        Err(e) => return Err(ImageError::IoError(e)),
                        Ok(_) => {},
                    }
                    BigEndian::read_u16_into(&mut bytebuffer, &mut buffer);
                    Ok(())
                },
            DecodeStrategy::Ascii => {
                    unimplemented!()
                }
        }
    }
}

/// Tests parsing binary buffers were written based on and validated against `pamfile` from
/// netpbm (http://netpbm.sourceforge.net/).
#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn minimal_form() {
        // Violates current specification (October 2016 ) but accepted by both netpbm and ImageMagick
        decode_minimal_image(&b"P61 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123"[..]);
        decode_minimal_image(&b"P6 1 1 255 123\xFF"[..]); // Too long should not be an issue
    }

    #[test]
    fn comment_in_token() {
        decode_minimal_image(&b"P6 1 1 2#comment\n55 123"[..]); // Terminating LF
        decode_minimal_image(&b"P6 1 1 2#comment\r55 123"[..]); // Terminating CR
        decode_minimal_image(&b"P6 1 1#comment\n 255 123"[..]); // Comment after token
        decode_minimal_image(&b"P6 1 1 #comment\n255 123"[..]); // Comment before token
        decode_minimal_image(&b"P6#comment\n 1 1 255 123"[..]); // Begin of header
        decode_minimal_image(&b"P6 1 1 255#comment\n 123"[..]); // End of header
    }

    #[test]
    fn whitespace() {
        decode_minimal_image(&b"P6\x091\x091\x09255\x09123"[..]); // TAB
        decode_minimal_image(&b"P6\x0a1\x0a1\x0a255\x0a123"[..]); // LF
        decode_minimal_image(&b"P6\x0b1\x0b1\x0b255\x0b123"[..]); // VT
        decode_minimal_image(&b"P6\x0c1\x0c1\x0c255\x0c123"[..]); // FF
        decode_minimal_image(&b"P6\x0d1\x0d1\x0d255\x0d123"[..]); // CR
        // Spaces tested before
        decode_minimal_image(&b"P61\x09\x0a\x0b\x0c\x0d1 255 123"[..]); // All whitespace, combined
    }

    /// Tests for decoding error, assuming `encoded` is ppm encoding for the very simplistic image
    /// containing a single pixel with one byte values (1, 2, 3).
    fn decode_minimal_image(encoded: &[u8]) {
        let content = vec![49 as u8, 50, 51];
        let mut decoder = PPMDecoder::new(encoded).unwrap();

        assert_eq!(decoder.dimensions().unwrap(), (1, 1));
        assert_eq!(decoder.colortype().unwrap(), ColorType::RGB(8));
        assert_eq!(decoder.row_len().unwrap(), 3);
        assert_eq!(decoder.bytewidth(), 1);

        match decoder.read_image().unwrap() {
            DecodingResult::U8(image) => assert_eq!(image, content),
            _ => assert!(false),
        }
    }

    #[test]
    fn wrong_tag() {
        assert!(PPMDecoder::new(&b"P5 1 1 255 1"[..]).is_err());
    }

    #[test]
    fn invalid_characters() {
        assert!(PPMDecoder::new(&b"P6 1chars1 255 1"[..]).is_err()); // No text outside of comments
        assert!(PPMDecoder::new(&b"P6 1\xFF1 255 1"[..]).is_err()); // No invalid ascii chars
        assert!(PPMDecoder::new(&b"P6 0x01 1 255 1"[..]).is_err()); // Numbers only as decimal
    }

    /// These violate the narrow specification of ppm but are commonly supported in other programs.
    /// Fail fast and concise is important here as these might be received as input files.
    #[test]
    fn unsupported_extensions() {
        assert!(PPMDecoder::new(&b"P6 1 1 65536 1"[..]).is_err()); // No bitwidth above 16
    }
}
<|endoftext|>


<commit_before>//! Encoding of PPM Images

use std::io;
use std::io::Write;

use color;
use color::ColorType:: {
    Gray,
    Palette,
    GrayA,
    RGB,
    RGBA,
};

/// A representation of a PPM encoder.
pub struct PPMEncoder<'a, W: 'a> {
    w: &'a mut W
}

impl<'a, W: Write> PPMEncoder<'a, W> {
    /// Create a new PPMEncoder from the Writer ```w```.
    /// This function takes ownership of the Writer.
    pub fn new(w: &mut W) -> PPMEncoder<W> {
        PPMEncoder { w: w }
    }

    /// Encode the buffer ```im``` as a PPM image.
    /// ```width``` and ```height``` are the dimensions of the buffer.
    /// ```color``` is the buffers ColorType.
    pub fn encode(&mut self, im: &[u8], width: u32, height: u32, color: color::ColorType) -> io::Result<()> {
        let _ = try!(self.write_magic_number());
        let _ = try!(self.write_metadata(width, height, color));

        self.write_image(im, color, width, height)
    }

    fn write_magic_number(&mut self) -> io::Result<()> {
        write!(self.w, "P6\n")
    }

    fn write_metadata(&mut self, width: u32, height: u32, pixel_type: color::ColorType) -> io::Result<()> {
        let m = max_pixel_value(pixel_type);
        write!(self.w, "{0} {1}\n{2}\n", width, height, m)
    }

    fn write_image(
        &mut self,
        buf: &[u8],
        pixel_type: color::ColorType,
        width: u32,
        height: u32) -> io::Result<()> {

        assert!(buf.len() > 0);
        match pixel_type {
            Gray(8) => {
                for i in 0..(width * height) as usize {
                    let _ = try!(self.w.write_all(&[buf[i]]));
                    let _ = try!(self.w.write_all(&[buf[i]]));
                    let _ = try!(self.w.write_all(&[buf[i]]));
                }
            }

            RGB(8)  => try!(self.w.write_all(buf)),
            RGB(16) => try!(self.w.write_all(buf)),
            RGBA(8) => {
                for x in buf.chunks(4) {

                    let _ = try!(self.w.write_all(&[x[0]]));

                    let _ = try!(self.w.write_all(&[x[1]]));

                    let _ = try!(self.w.write_all(&[x[2]]));
                }
            }

            a => panic!(format!("not implemented: {:?}", a))
        }

        Ok(())
    }
}

fn max_pixel_value(pixel_type: color::ColorType) -> u16 {
    match pixel_type {
        Gray(n)    => 2u16.pow(n as u32) - 1,
        RGB(n)     => 2u16.pow(n as u32) - 1,
        Palette(n) => 2u16.pow(n as u32) - 1,
        GrayA(n)   => 2u16.pow(n as u32) - 1,
        RGBA(n)    => 2u16.pow(n as u32) - 1,
    }
}
<commit_msg>Get rid of some spurious whitespace in PPMEncoder<commit_after>//! Encoding of PPM Images

use std::io;
use std::io::Write;

use color;
use color::ColorType:: {
    Gray,
    Palette,
    GrayA,
    RGB,
    RGBA,
};

/// A representation of a PPM encoder.
pub struct PPMEncoder<'a, W: 'a> {
    w: &'a mut W
}

impl<'a, W: Write> PPMEncoder<'a, W> {
    /// Create a new PPMEncoder from the Writer ```w```.
    /// This function takes ownership of the Writer.
    pub fn new(w: &mut W) -> PPMEncoder<W> {
        PPMEncoder { w: w }
    }

    /// Encode the buffer ```im``` as a PPM image.
    /// ```width``` and ```height``` are the dimensions of the buffer.
    /// ```color``` is the buffers ColorType.
    pub fn encode(&mut self, im: &[u8], width: u32, height: u32, color: color::ColorType) -> io::Result<()> {
        let _ = try!(self.write_magic_number());
        let _ = try!(self.write_metadata(width, height, color));

        self.write_image(im, color, width, height)
    }

    fn write_magic_number(&mut self) -> io::Result<()> {
        write!(self.w, "P6\n")
    }

    fn write_metadata(&mut self, width: u32, height: u32, pixel_type: color::ColorType) -> io::Result<()> {
        let m = max_pixel_value(pixel_type);
        write!(self.w, "{0} {1}\n{2}\n", width, height, m)
    }

    fn write_image(
        &mut self,
        buf: &[u8],
        pixel_type: color::ColorType,
        width: u32,
        height: u32) -> io::Result<()> {

        assert!(buf.len() > 0);
        match pixel_type {
            Gray(8) => {
                for i in 0..(width * height) as usize {
                    let _ = try!(self.w.write_all(&[buf[i]]));
                    let _ = try!(self.w.write_all(&[buf[i]]));
                    let _ = try!(self.w.write_all(&[buf[i]]));
                }
            }
            RGB(8)  => try!(self.w.write_all(buf)),
            RGB(16) => try!(self.w.write_all(buf)),
            RGBA(8) => {
                for x in buf.chunks(4) {
                    let _ = try!(self.w.write_all(&[x[0]]));
                    let _ = try!(self.w.write_all(&[x[1]]));
                    let _ = try!(self.w.write_all(&[x[2]]));
                }
            }
            a => panic!(format!("not implemented: {:?}", a))
        }

        Ok(())
    }
}

fn max_pixel_value(pixel_type: color::ColorType) -> u16 {
    match pixel_type {
        Gray(n)    => 2u16.pow(n as u32) - 1,
        RGB(n)     => 2u16.pow(n as u32) - 1,
        Palette(n) => 2u16.pow(n as u32) - 1,
        GrayA(n)   => 2u16.pow(n as u32) - 1,
        RGBA(n)    => 2u16.pow(n as u32) - 1,
    }
}
<|endoftext|>


<commit_before>#[cfg(feature = "nightly")]
mod racer_bench {
    use racer::codecleaner::code_chunks;
    use racer::codeiter::iter_stmts;
    use racer::scopes::{mask_comments, mask_sub_scopes};

    use self::test::Bencher;
    use std::env::var;
    use std::io::Read;
    use std::fs::File;
    use std::path::PathBuf;

    fn get_rust_file_str(path: &[&str]) -> String {
        let mut src_path = match var("RUST_SRC_PATH") {
            Ok(env) => { PathBuf::from(&env) },
            _ => panic!("Cannot find $RUST_SRC_PATH")
        };
        for &s in path.iter() { src_path.push(s); }

        let mut s = String::new();
        File::open(&src_path).unwrap().read_to_string(&mut s).unwrap();
        s
    }

    #[bench]
    fn bench_code_chunks(b: &mut Bencher) {
        let src = &get_rust_file_str(&["libcollections", "bit.rs"]);
        b.iter(|| {
            test::black_box(code_chunks(src).collect::<Vec<_>>());
        });
    }

    #[bench]
    fn bench_iter_stmts(b: &mut Bencher) {
        let src = &get_rust_file_str(&["libcollections", "bit.rs"]);
        b.iter(|| {
            test::black_box(iter_stmts(src).collect::<Vec<_>>());
        });
    }

    #[bench]
    fn bench_mask_comments(b: &mut Bencher) {
        let src = &get_rust_file_str(&["libcollections", "bit.rs"]);
        b.iter(|| {
            test::black_box(mask_comments(src));
        });
    }

    #[bench]
    fn bench_mask_sub_scopes(b: &mut Bencher) {
        let src = &get_rust_file_str(&["libcollections", "bit.rs"]);
        b.iter(|| {
            test::black_box(mask_sub_scopes(src));
        });
    }
}
<commit_msg>Fix bench compilation error.<commit_after>#[cfg(feature = "nightly")]
mod racer_bench {
    extern crate test;

    use racer::codecleaner::code_chunks;
    use racer::codeiter::iter_stmts;
    use racer::scopes::{mask_comments, mask_sub_scopes};

    use self::test::Bencher;
    use std::env::var;
    use std::io::Read;
    use std::fs::File;
    use std::path::PathBuf;

    fn get_rust_file_str(path: &[&str]) -> String {
        let mut src_path = match var("RUST_SRC_PATH") {
            Ok(env) => { PathBuf::from(&env) },
            _ => panic!("Cannot find $RUST_SRC_PATH")
        };
        for &s in path.iter() { src_path.push(s); }

        let mut s = String::new();
        File::open(&src_path).unwrap().read_to_string(&mut s).unwrap();
        s
    }

    #[bench]
    fn bench_code_chunks(b: &mut Bencher) {
        let src = &get_rust_file_str(&["libcollections", "bit.rs"]);
        b.iter(|| {
            test::black_box(code_chunks(src).collect::<Vec<_>>());
        });
    }

    #[bench]
    fn bench_iter_stmts(b: &mut Bencher) {
        let src = &get_rust_file_str(&["libcollections", "bit.rs"]);
        b.iter(|| {
            test::black_box(iter_stmts(src).collect::<Vec<_>>());
        });
    }

    #[bench]
    fn bench_mask_comments(b: &mut Bencher) {
        let src = &get_rust_file_str(&["libcollections", "bit.rs"]);
        b.iter(|| {
            test::black_box(mask_comments(src));
        });
    }

    #[bench]
    fn bench_mask_sub_scopes(b: &mut Bencher) {
        let src = &get_rust_file_str(&["libcollections", "bit.rs"]);
        b.iter(|| {
            test::black_box(mask_sub_scopes(src));
        });
    }
}
<|endoftext|>