<commit_before>use sozu::channel::Channel;
use sozu::messages::{Order, Instance};
use sozu_command::data::{AnswerData,ConfigCommand,ConfigMessage,ConfigMessageAnswer,ConfigMessageStatus,RunState};

use std::collections::HashSet;
use rand::{thread_rng, Rng};

fn generate_id() -> String {
  let s: String = thread_rng().gen_ascii_chars().take(6).collect();
  format!("ID-{}", s)
}

pub fn save_state(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>, path: &str) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::SaveState(path.to_string()),
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          // do nothing here
          // for other messages, we would loop over read_message
          // until an error or ok message was sent
        },
        ConfigMessageStatus::Error => {
          println!("could not save proxy state: {}", message.message);
        },
        ConfigMessageStatus::Ok => {
          println!("Proxy state saved to {}", path);
        }
      }
    }
  }
}

pub fn load_state(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>, path: &str) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::LoadState(path.to_string()),
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          // do nothing here
          // for other messages, we would loop over read_message
          // until an error or ok message was sent
        },
        ConfigMessageStatus::Error => {
          println!("could not save proxy state: {}", message.message);
        },
        ConfigMessageStatus::Ok => {
          println!("Proxy state saved to {}", path);
        }
      }
    }
  }
}

pub fn dump_state(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::DumpState,
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          // do nothing here
          // for other messages, we would loop over read_message
          // until an error or ok message was sent
        },
        ConfigMessageStatus::Error => {
          println!("could not dump proxy state: {}", message.message);
        },
        ConfigMessageStatus::Ok => {
          println!("Proxy state:\n{}", message.message);
        }
      }
    }
  }
}

pub fn soft_stop(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  println!("shutting down proxy");
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ProxyConfiguration(Order::SoftStop),
    //FIXME: we should be able to soft stop one specific worker
    None,
  ));

  loop {
    match channel.read_message() {
      None          => println!("the proxy didn't answer"),
      Some(message) => {
        if &id != &message.id {
          println!("received message with invalid id: {:?}", message);
          return;
        }
        match message.status {
          ConfigMessageStatus::Processing => {
            println!("Proxy is processing: {}", message.message);
          },
          ConfigMessageStatus::Error => {
            println!("could not stop the proxy: {}", message.message);
          },
          ConfigMessageStatus::Ok => {
            println!("Proxy shut down: {}", message.message);
            break;
          }
        }
      }
    }
  }
}

pub fn hard_stop(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  println!("shutting down proxy");
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ProxyConfiguration(Order::HardStop),
    //FIXME: we should be able to soft stop one specific worker
    None,
  ));

  loop {
    match channel.read_message() {
      None          => println!("the proxy didn't answer"),
      Some(message) => {
        match message.status {
          ConfigMessageStatus::Processing => {
            println!("Proxy is processing: {}", message.message);
          },
          ConfigMessageStatus::Error => {
            println!("could not stop the proxy: {}", message.message);
          },
          ConfigMessageStatus::Ok => {
            if &id == &message.id {
              println!("Proxy shut down: {}", message.message);
              break;
            }
          }
        }
      }
    }
  }
}

pub fn upgrade(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ListWorkers,
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          println!("should have obtained an answer immediately");
          return;
        },
        ConfigMessageStatus::Error => {
          println!("could not get the worker list: {}", message.message);
          return
        },
        ConfigMessageStatus::Ok => {
          println!("Worker list:\n{:?}", message.data);
          if let Some(AnswerData::Workers(ref workers)) = message.data {
            let mut launching: HashSet<String> = HashSet::new();
            let mut stopping:  HashSet<String> = HashSet::new();

            for ref worker in workers.iter().filter(|worker| worker.run_state == RunState::Running) {
              let id = generate_id();
              let msg = ConfigMessage::new(
                id.clone(),
                ConfigCommand::LaunchWorker("BLAH".to_string()),
                None,
              );
              println!("sending message: {:?}", msg);
              channel.write_message(&msg);
              launching.insert(id);
            }

            for ref worker in workers.iter().filter(|worker| worker.run_state == RunState::Running) {
              let id = generate_id();
              let msg = ConfigMessage::new(
                id.clone(),
                ConfigCommand::ProxyConfiguration(Order::SoftStop),
                Some(worker.id),
              );
              println!("sending message: {:?}", msg);
              channel.write_message(&msg);
              stopping.insert(id);
            }

            loop {
              println!("launching: {:?}\nstopping: {:?}", launching, stopping);
              if launching.is_empty() && stopping.is_empty() {
                break;
              }
              match channel.read_message() {
                None          => println!("the proxy didn't answer"),
                Some(message) => {
                  println!("received message: {:?}", message);
                  match message.status {
                    ConfigMessageStatus::Processing => {
                    },
                    ConfigMessageStatus::Error => {
                      println!("error for message[{}]: {}", message.id, message.message);
                      if launching.contains(&message.id) {
                        launching.remove(&message.id);
                        println!("launch message with ID {} done", message.id);
                      }
                      if stopping.contains(&message.id) {
                        stopping.remove(&message.id);
                        println!("stop message with ID {} done", message.id);
                      }
                    },
                    ConfigMessageStatus::Ok => {
                      if launching.contains(&message.id) {
                        launching.remove(&message.id);
                        println!("launch message with ID {} done", message.id);
                      }
                      if stopping.contains(&message.id) {
                        stopping.remove(&message.id);
                        println!("stop message with ID {} done", message.id);
                      }
                    }
                  }
                }
              }
            }

            println!("worker upgrade done");
            let id = generate_id();
            channel.write_message(&ConfigMessage::new(
              id.clone(),
              ConfigCommand::UpgradeMaster,
              None,
            ));

            loop {
              match channel.read_message() {
                None          => println!("the proxy didn't answer"),
                Some(message) => {
                  if &id != &message.id {
                    println!("received message with invalid id: {:?}", message);
                    return;
                  }
                  match message.status {
                    ConfigMessageStatus::Processing => {
                      println!("master is processing: {}", message.message);
                    },
                    ConfigMessageStatus::Error => {
                      println!("could not upgrade the master: {}", message.message);
                      return;
                    },
                    ConfigMessageStatus::Ok => {
                      println!("successfully upgraded the master: {}", message.message);
                      return;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

pub fn status(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ListWorkers,
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          println!("should have obtained an answer immediately");
          return;
        },
        ConfigMessageStatus::Error => {
          println!("could not get the worker list: {}", message.message);
          return
        },
        ConfigMessageStatus::Ok => {
          println!("Worker list:\n{:?}", message.data);
          if let Some(AnswerData::Workers(ref workers)) = message.data {
            let mut expecting: HashSet<String> = HashSet::new();

            for ref worker in workers.iter().filter(|worker| worker.run_state == RunState::Running) {
              let id = generate_id();
              let msg = ConfigMessage::new(
                id.clone(),
                ConfigCommand::ProxyConfiguration(Order::Status),
                Some(worker.id),
              );
              println!("sending message: {:?}", msg);
              channel.write_message(&msg);
              expecting.insert(id);
            }

            loop {
              println!("expecting: {:?}", expecting);
              if expecting.is_empty() {
                break;
              }
              match channel.read_message() {
                None          => println!("the proxy didn't answer"),
                Some(message) => {
                  println!("received message: {:?}", message);
                  match message.status {
                    ConfigMessageStatus::Processing => {
                    },
                    ConfigMessageStatus::Error => {
                      println!("error for message[{}]: {}", message.id, message.message);
                      if expecting.contains(&message.id) {
                        expecting.remove(&message.id);
                        println!("status message with ID {} done", message.id);
                      }
                    },
                    ConfigMessageStatus::Ok => {
                      if expecting.contains(&message.id) {
                        expecting.remove(&message.id);
                        println!("status message with ID {} done", message.id);
                      }
                    }
                  }
                }
              }
            }

            println!("worker upgrade done");
          }
        }
      }
    }
  }
}

pub fn remove_backend(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>, app_id: &str, ip: &str, port: u16) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ProxyConfiguration(Order::RemoveInstance(Instance {
      app_id: String::from(app_id),
      ip_address: String::from(ip),
      port: port
    })),
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          // do nothing here
          // for other messages, we would loop over read_message
          // until an error or ok message was sent
        },
        ConfigMessageStatus::Error => {
          println!("could not remove backend : {}", message.message);
        },
        ConfigMessageStatus::Ok => {
          println!("backend {}:{} removed for app : {} ", ip, port, app_id);
        }
      }
    }
  }
}

pub fn add_backend(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>, app_id: &str, ip: &str, port: u16) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ProxyConfiguration(Order::AddInstance(Instance {
      app_id: String::from(app_id),
      ip_address: String::from(ip),
      port: port
    })),
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          // do nothing here
          // for other messages, we would loop over read_message
          // until an error or ok message was sent
        },
        ConfigMessageStatus::Error => {
          println!("could not add backend : {}", message.message);
        },
        ConfigMessageStatus::Ok => {
          println!("backend {}:{} added for app : {} ", ip, port, app_id);
        }
      }
    }
  }
}
<commit_msg>some refactoring<commit_after>use sozu::channel::Channel;
use sozu::messages::{Order, Instance};
use sozu_command::data::{AnswerData,ConfigCommand,ConfigMessage,ConfigMessageAnswer,ConfigMessageStatus,RunState};

use std::collections::HashSet;
use rand::{thread_rng, Rng};

fn generate_id() -> String {
  let s: String = thread_rng().gen_ascii_chars().take(6).collect();
  format!("ID-{}", s)
}

pub fn save_state(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>, path: &str) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::SaveState(path.to_string()),
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          // do nothing here
          // for other messages, we would loop over read_message
          // until an error or ok message was sent
        },
        ConfigMessageStatus::Error => {
          println!("could not save proxy state: {}", message.message);
        },
        ConfigMessageStatus::Ok => {
          println!("Proxy state saved to {}", path);
        }
      }
    }
  }
}

pub fn load_state(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>, path: &str) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::LoadState(path.to_string()),
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          // do nothing here
          // for other messages, we would loop over read_message
          // until an error or ok message was sent
        },
        ConfigMessageStatus::Error => {
          println!("could not save proxy state: {}", message.message);
        },
        ConfigMessageStatus::Ok => {
          println!("Proxy state saved to {}", path);
        }
      }
    }
  }
}

pub fn dump_state(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::DumpState,
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          // do nothing here
          // for other messages, we would loop over read_message
          // until an error or ok message was sent
        },
        ConfigMessageStatus::Error => {
          println!("could not dump proxy state: {}", message.message);
        },
        ConfigMessageStatus::Ok => {
          println!("Proxy state:\n{}", message.message);
        }
      }
    }
  }
}

pub fn soft_stop(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  println!("shutting down proxy");
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ProxyConfiguration(Order::SoftStop),
    //FIXME: we should be able to soft stop one specific worker
    None,
  ));

  loop {
    match channel.read_message() {
      None          => println!("the proxy didn't answer"),
      Some(message) => {
        if &id != &message.id {
          println!("received message with invalid id: {:?}", message);
          return;
        }
        match message.status {
          ConfigMessageStatus::Processing => {
            println!("Proxy is processing: {}", message.message);
          },
          ConfigMessageStatus::Error => {
            println!("could not stop the proxy: {}", message.message);
          },
          ConfigMessageStatus::Ok => {
            println!("Proxy shut down: {}", message.message);
            break;
          }
        }
      }
    }
  }
}

pub fn hard_stop(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  println!("shutting down proxy");
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ProxyConfiguration(Order::HardStop),
    //FIXME: we should be able to soft stop one specific worker
    None,
  ));

  loop {
    match channel.read_message() {
      None          => println!("the proxy didn't answer"),
      Some(message) => {
        match message.status {
          ConfigMessageStatus::Processing => {
            println!("Proxy is processing: {}", message.message);
          },
          ConfigMessageStatus::Error => {
            println!("could not stop the proxy: {}", message.message);
          },
          ConfigMessageStatus::Ok => {
            if &id == &message.id {
              println!("Proxy shut down: {}", message.message);
              break;
            }
          }
        }
      }
    }
  }
}

pub fn upgrade(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ListWorkers,
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          println!("should have obtained an answer immediately");
          return;
        },
        ConfigMessageStatus::Error => {
          println!("could not get the worker list: {}", message.message);
          return
        },
        ConfigMessageStatus::Ok => {
          println!("Worker list:\n{:?}", message.data);
          if let Some(AnswerData::Workers(ref workers)) = message.data {
            let mut launching: HashSet<String> = HashSet::new();
            let mut stopping:  HashSet<String> = HashSet::new();

            for ref worker in workers.iter().filter(|worker| worker.run_state == RunState::Running) {
              let id = generate_id();
              let msg = ConfigMessage::new(
                id.clone(),
                ConfigCommand::LaunchWorker("BLAH".to_string()),
                None,
              );
              println!("sending message: {:?}", msg);
              channel.write_message(&msg);
              launching.insert(id);
            }

            for ref worker in workers.iter().filter(|worker| worker.run_state == RunState::Running) {
              let id = generate_id();
              let msg = ConfigMessage::new(
                id.clone(),
                ConfigCommand::ProxyConfiguration(Order::SoftStop),
                Some(worker.id),
              );
              println!("sending message: {:?}", msg);
              channel.write_message(&msg);
              stopping.insert(id);
            }

            loop {
              println!("launching: {:?}\nstopping: {:?}", launching, stopping);
              if launching.is_empty() && stopping.is_empty() {
                break;
              }
              match channel.read_message() {
                None          => println!("the proxy didn't answer"),
                Some(message) => {
                  println!("received message: {:?}", message);
                  match message.status {
                    ConfigMessageStatus::Processing => {
                    },
                    ConfigMessageStatus::Error => {
                      println!("error for message[{}]: {}", message.id, message.message);
                      if launching.contains(&message.id) {
                        launching.remove(&message.id);
                        println!("launch message with ID {} done", message.id);
                      }
                      if stopping.contains(&message.id) {
                        stopping.remove(&message.id);
                        println!("stop message with ID {} done", message.id);
                      }
                    },
                    ConfigMessageStatus::Ok => {
                      if launching.contains(&message.id) {
                        launching.remove(&message.id);
                        println!("launch message with ID {} done", message.id);
                      }
                      if stopping.contains(&message.id) {
                        stopping.remove(&message.id);
                        println!("stop message with ID {} done", message.id);
                      }
                    }
                  }
                }
              }
            }

            println!("worker upgrade done");
            let id = generate_id();
            channel.write_message(&ConfigMessage::new(
              id.clone(),
              ConfigCommand::UpgradeMaster,
              None,
            ));

            loop {
              match channel.read_message() {
                None          => println!("the proxy didn't answer"),
                Some(message) => {
                  if &id != &message.id {
                    println!("received message with invalid id: {:?}", message);
                    return;
                  }
                  match message.status {
                    ConfigMessageStatus::Processing => {
                      println!("master is processing: {}", message.message);
                    },
                    ConfigMessageStatus::Error => {
                      println!("could not upgrade the master: {}", message.message);
                      return;
                    },
                    ConfigMessageStatus::Ok => {
                      println!("successfully upgraded the master: {}", message.message);
                      return;
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}

pub fn status(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ListWorkers,
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          println!("should have obtained an answer immediately");
          return;
        },
        ConfigMessageStatus::Error => {
          println!("could not get the worker list: {}", message.message);
          return
        },
        ConfigMessageStatus::Ok => {
          println!("Worker list:\n{:?}", message.data);
          if let Some(AnswerData::Workers(ref workers)) = message.data {
            let mut expecting: HashSet<String> = HashSet::new();

            for ref worker in workers.iter().filter(|worker| worker.run_state == RunState::Running) {
              let id = generate_id();
              let msg = ConfigMessage::new(
                id.clone(),
                ConfigCommand::ProxyConfiguration(Order::Status),
                Some(worker.id),
              );
              println!("sending message: {:?}", msg);
              channel.write_message(&msg);
              expecting.insert(id);
            }

            loop {
              println!("expecting: {:?}", expecting);
              if expecting.is_empty() {
                break;
              }
              match channel.read_message() {
                None          => println!("the proxy didn't answer"),
                Some(message) => {
                  println!("received message: {:?}", message);
                  match message.status {
                    ConfigMessageStatus::Processing => {
                    },
                    ConfigMessageStatus::Error => {
                      println!("error for message[{}]: {}", message.id, message.message);
                      if expecting.contains(&message.id) {
                        expecting.remove(&message.id);
                        println!("status message with ID {} done", message.id);
                      }
                    },
                    ConfigMessageStatus::Ok => {
                      if expecting.contains(&message.id) {
                        expecting.remove(&message.id);
                        println!("status message with ID {} done", message.id);
                      }
                    }
                  }
                }
              }
            }

            println!("worker upgrade done");
          }
        }
      }
    }
  }
}

pub fn remove_backend(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>, app_id: &str, ip: &str, port: u16) {
    let instance = Instance {
      app_id: String::from(app_id),
      ip_address: String::from(ip),
      port: port
    };

    backend_command(channel, Order::RemoveInstance(instance.clone()), instance, "remove");
}

pub fn add_backend(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>, app_id: &str, ip: &str, port: u16) {
  let instance = Instance {
      app_id: String::from(app_id),
      ip_address: String::from(ip),
      port: port
    };

  backend_command(channel, Order::AddInstance(instance.clone()), instance, "add");
}

fn backend_command(channel: &mut Channel<ConfigMessage,ConfigMessageAnswer>, order: Order, instance: Instance, action: &str) {
  let id = generate_id();
  channel.write_message(&ConfigMessage::new(
    id.clone(),
    ConfigCommand::ProxyConfiguration(order),
    None,
  ));

  match channel.read_message() {
    None          => println!("the proxy didn't answer"),
    Some(message) => {
      if id != message.id {
        println!("received message with invalid id: {:?}", message);
        return;
      }
      match message.status {
        ConfigMessageStatus::Processing => {
          // do nothing here
          // for other messages, we would loop over read_message
          // until an error or ok message was sent
        },
        ConfigMessageStatus::Error => {
          println!("could not {} backend : {}", action, message.message);
        },
        ConfigMessageStatus::Ok => {
          println!("backend {}:{} {} for app : {} ", instance.ip_address, instance.port, action, instance.app_id);
        }
      }
    }
  }
}
<|endoftext|>


<commit_before>use std::ops::Fn;
use std::error::FromError;
use std::sync::mpsc;

use std::path::Path as StdPath;

// @todo, change to std::io once stable.
use std::old_io as io;

//================================================================================
// Error:
//================================================================================

/**
 * `Error` contains all the possible errors for `fsnotify`.
 */
pub enum Error {
	Io( io::IoError ),
	NotifyError( String ),
	PathInvalid,
	NotImplemented,
}

impl FromError<io::IoError> for Error {
	fn from_error( from: io::IoError ) -> Error {
		Error::Io( from )
	}
}

//================================================================================
// Misc typedefs:
//================================================================================

pub type Path = StdPath;

/**
 * The `Result` of an operation, with either `T` (success), `Error` (failure).
 */
pub type NotifyResult<T> = Result<T, Error>;

/**
 * `R = NotifyResult<()`
 * Indicates either success or failure of an operation.
 */
pub type R = NotifyResult<()>;

//================================================================================
// Configuration:
//================================================================================

/**
 * `RecursionFilter`, a predicate function that, when recursion is enabled,
 * tells the `FsNotifier` if it should subscribe to a sub-directory.
 *
 * If the value returned is true, it will subscribe, otherwise, it will not.
 */
pub type RecursionFilter<'a> = Option<&'a (Fn( &Path ) -> bool + 'a)>;

/**
 * `RecursionLimit` denoted what the maximum recursion depth is starting
 * from a tree point that was explicitly added to the watch list.
 *
 * `None` means that there is no limit, it will do recursion forever.
 * `Some(0)` means that no recursion will happen at all.
 */
pub type RecursionLimit = Option<usize>;

/**
 * `Configuration` provides configuration for a `FsNotifier`.
 *
 * It configures what operations to subcribe to if applicable for the platform.
 * This lets you avoid tracking events of no interest.
 *
 * It also configures if symlinks should be followed or not (`follow_symlinks`).
 *
 * Lastly, it configures the `RecursionLimit`, and `RecursionFilter`.
 */
pub struct Configuration<'a> {
	subscribe: Operations,
	follow_symlinks: bool,
	recursion_limit: RecursionLimit,
	recursion_filter: RecursionFilter<'a>,
}

impl<'a> Configuration<'a> {
	pub fn is_recursive( &self ) -> bool {
		match self.recursion_limit {
			None => true,
			Some( limit ) => limit > 0
		}
	}
}

//================================================================================
// Events:
//================================================================================

mod operations;
use self::operations::Operations;

/**
 * Event:s are passed to the `EventSender`.
 * It has information about the path that the operations that happened on it.
 */
pub struct Event<'a> {
	pub path: Option<&'a Path>,
	pub op: NotifyResult<Operations>,
}

/**
 * `EventSender`, a `Sender` for an `Event`.
 */
pub type EventSender<'a> = mpsc::Sender<Event<'a>>;

//================================================================================
// Notifier trait:
//================================================================================

/**
 * FsNotifier, a trait, is the generic interface for
 * subscribing to file system change events.
 *
 * It provides 4 basic operations:
 * 	+ `.add( &Path )`
 * 	+ `.remove( &Path )`
 * 	+ `.start()`
 * 	+ `.stop()`
 *
 * As this trait deals with I/O interaction with the operating system, things can fail.
 * Thus, all methods return a `NotifyResult<T> = Result<T, Error>`.
 * All methods but the first, `.new(...)` return `R = NotifyResult<()>`,
 * indicating either success or failure of the operation.
 */
pub trait FsNotifier<'a> : Drop {
	/**
	 * Constructs a `FsNotifier`.
	 *
	 * The sender is an `EventSender` which the notifier will send events through.
	 * The config: `Configuration` contains information about how to handle recursion,
	 * symlinks and what file system operations that should be tracked.
	 *
	 * The returned value is a the notifier, wrapped in a `NotifyResult`.
	 * This is done because there might be I/O failures depending on the system.
	 */
	fn new( sender: EventSender<'a>, config: Configuration<'a> ) -> NotifyResult<Self>;

	/**
	 * Adds a path to track to the notifier.
	 *
	 * Returned is a Result<()>, that indicates either failure or success.
	 */
	fn add( &self, path: &Path ) -> R;

	/**
	 * Tells the notifier to stop tracking a path.
	 *
	 * Returned is a Result<()>, that indicates either failure or success.
	 */
	fn remove( &self, path: &Path ) -> R;

	/**
	 * Tells the notifier to start the tracking.
	 * This operation is blocking, therefore it should be wrapped in a thread.
	 *
	 * Returned is a Result<()>, that indicates either failure or success.
	 */
	fn start( &self ) -> R;

	/**
	 * Tells the notifier to stop the tracking.
	 *
	 * Returned is a Result<()>, that indicates either failure or success.
	 */
	fn stop( &self ) -> R;
}<commit_msg>fsnotify interface: improved documentation, new() now does no I/O operations.<commit_after>use std::ops::Fn;
use std::error::FromError;
use std::sync::mpsc;

use std::path::Path as StdPath;

// @todo, change to std::io once stable.
use std::old_io as io;

//================================================================================
// Error:
//================================================================================

/**
 * `Error` contains all the possible errors for `fsnotify`.
 */
pub enum Error {
	Io( io::IoError ),
	NotifyError( String ),
	PathInvalid,
	NotImplemented,
}

impl FromError<io::IoError> for Error {
	fn from_error( from: io::IoError ) -> Error {
		Error::Io( from )
	}
}

//================================================================================
// Misc typedefs:
//================================================================================

pub type Path = StdPath;

/**
 * The `Result` of an operation, with either `T` (success), `Error` (failure).
 */
pub type NotifyResult<T> = Result<T, Error>;

/**
 * `R = NotifyResult<()`
 * Indicates either success or failure of an operation.
 */
pub type R = NotifyResult<()>;

//================================================================================
// Configuration:
//================================================================================

/**
 * `RecursionFilter`, a predicate function that, when recursion is enabled,
 * tells the `FsNotifier` if it should subscribe to a sub-directory.
 *
 * If the value returned is true, it will subscribe, otherwise, it will not.
 */
pub type RecursionFilter<'a> = Option<&'a (Fn( &Path ) -> bool + 'a)>;

/**
 * `RecursionLimit` denoted what the maximum recursion depth is starting
 * from a tree point that was explicitly added to the watch list.
 *
 * `None` means that there is no limit, it will do recursion forever.
 * `Some(0)` means that no recursion will happen at all.
 */
pub type RecursionLimit = Option<usize>;

/**
 * `Configuration` provides configuration for a `FsNotifier`.
 *
 * The following configurations are available:
 * + `subscribe`: the operations to subcribe to if applicable for the platform.
 *    	This lets you avoid tracking events of no interest.
 * + `follow_symlinks`: should symlinks be followed?
 * + `auto_manage`: if a file is after calling `start()` which is not
 * 		explicitly tracked (i.e when recursion is enabled), should it be tracked?
 * + `recursion_limit`: see `RecursionLimit`.
 * + `recursion_filter`: see `RecursionFilter`.
 */
pub struct Configuration<'a> {
	subscribe:			Operations,
	follow_symlinks:	bool,
	auto_manage:		bool,
	recursion_limit:	RecursionLimit,
	recursion_filter:	RecursionFilter<'a>,
}

impl<'a> Configuration<'a> {
	pub fn is_recursive( &self ) -> bool {
		match self.recursion_limit {
			None => true,
			Some( limit ) => limit > 0
		}
	}
}

//================================================================================
// Events:
//================================================================================

mod operations;
use self::operations::Operations;

/**
 * Event:s are passed to the `EventSender`.
 * It has information about the path that the operations that happened on it.
 */
pub struct Event<'a> {
	pub path: Option<&'a Path>,
	pub op: NotifyResult<Operations>,
}

/**
 * `EventSender`, a `Sender` for an `Event`.
 */
pub type EventSender<'a> = mpsc::Sender<Event<'a>>;

//================================================================================
// Notifier trait:
//================================================================================

/**
 * FsNotifier, a trait, is the generic interface for
 * subscribing to file system change events.
 *
 * It provides 4 basic operations:
 * 	+ `.add( &Path )`
 * 	+ `.remove( &Path )`
 * 	+ `.start()`
 * 	+ `.stop()`
 *
 * As this trait deals with I/O interaction with the operating system, things can fail.
 * Thus, all methods return a `R = Result<(), Error>` indicating either success or failure.
 *
 * The
 */
pub trait FsNotifier<'a> : Drop {
	/**
	 * Constructs a `FsNotifier`.
	 *
	 * The sender is an `EventSender` which the notifier will send events through.
	 * The config: `Configuration` contains configuration information.
	 *
	 * This operation does no I/O operations and thus can't fail because of it.
	 */
	fn new( sender: EventSender<'a>, config: Configuration<'a> ) -> Self;

	/**
	 * Adds a path to track to the notifier.
	 * This can be done after calling `start()`.
	 *
	 * Returned is a `R`, that indicates either failure or success.
	 */
	fn add( &self, path: &Path ) -> R;

	/**
	 * Tells the notifier to stop tracking a path.
	 * This can be done after calling `start()`.
	 *
	 * Returned is a `R`, that indicates either failure or success.
	 */
	fn remove( &self, path: &Path ) -> R;

	/**
	 * Tells the notifier to start the tracking.
	 * This operation is blocking, therefore it should be wrapped in a thread.
	 *
	 * Returned is a `R`, that indicates either failure or success.
	 */
	fn start( &self ) -> R;

	/**
	 * Tells the notifier to stop the tracking.
	 *
	 * Returned is a `R`, that indicates either failure or success.
	 */
	fn stop( &self ) -> R;
}<|endoftext|>


<commit_before><commit_msg>Remove unused mut detected by latest nightly<commit_after><|endoftext|>


<commit_before>// extern crate bindgen;
#[cfg(target_env = "msvc")]
extern crate cc;
extern crate pkg_config;
extern crate num_cpus;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

// Automatically write bindings to libsass
//#[allow(dead_code)]
//fn write_bindings() {
//    let bindings = bindgen::Builder::default()
//        .header("libsass/include/sass.h")
//        .clang_arg("-Ilibsass/include")
//        // To avoid a test failing
//        .blacklist_type("max_align_t")
//        // we do static linking so it should be fine
//        // https://github.com/rust-lang/rust/issues/36927
//        .rustified_enum(".*")
//        .generate()
//        .expect("Unable to generate bindings");
//
//    // Write the bindings to the $OUT_DIR/bindings.rs file.
//    let out_path = PathBuf::from("src");
//    bindings
//        .write_to_file(out_path.join("bindings.rs"))
//        .expect("Couldn't write bindings!");
//}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => panic!("\n{} failed with {}\n", stringify!($e), e),
    })
}

fn cp_r(dir: &Path, dest: &Path) {
    for entry in t!(fs::read_dir(dir)) {
        let entry = t!(entry);
        let path = entry.path();
        let dst = dest.join(path.file_name().unwrap());
        if t!(fs::metadata(&path)).is_file() {
            t!(fs::copy(path, dst));
        } else {
            t!(fs::create_dir_all(&dst));
            cp_r(&path, &dst);
        }
    }
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().unwrap().join("libsass")
}

// linux/unix
#[cfg(not(target_env = "msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);
    let is_bsd = target.contains("dragonfly")
        || target.contains("freebsd")
        || target.contains("netbsd")
        || target.contains("openbsd");
    let libprobe = | lib: &str | -> bool {
      Command::new("cc")
        .arg("-xc++")
        .arg("-o/dev/null")
        .arg(format!("-l{}",lib))
        .arg("-shared")
        .stderr(Stdio::null())
        .status()
        .expect("")
        .success()
    };

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or(num_cpus::get().to_string());
    let r = Command::new(if is_bsd { "gmake" } else { "make" })
        .current_dir(&build)
        .args(&["--jobs", &jobs])
        .output()
        .expect("error running make");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("lib").display()
    );
    println!("cargo:rustc-link-lib=static=sass");

    if libprobe("c++_shared") {
        println!("cargo:rustc-link-lib=dylib=c++_shared");
    }
    else if libprobe("c++") {
        println!("cargo:rustc-link-lib=dylib=c++");
    }
    else if libprobe("stdc++") {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    }
    else {
        panic!("no c++ library found");
    }

}

// windows
#[cfg(target_env = "msvc")]
fn compile() {
    let src = get_libsass_folder();
    let target = env::var("TARGET").expect("TARGET not found in environment");
    let msvc_platform = if target.contains("x86_64") {
        "Win64"
    } else {
        "Win32"
    };
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);

    // Find an instance of devenv.exe from Visual Studio IDE in order to upgrade
    // libsass.sln to the current available IDE. Do nothing if no devenv.exe found
    let d = cc::windows_registry::find(target.as_str(), "devenv.exe");
    if let Some(mut d) = d {
        let d = d
            .args(&["/upgrade", "win\\libsass.sln"])
            .current_dir(&build)
            .output()
            .expect("error running devenv");
        if !d.status.success() {
            let err = String::from_utf8_lossy(&d.stderr);
            let out = String::from_utf8_lossy(&d.stdout);
            println!("Upgrade error:\nSTDERR:{}\nSTDOUT:{}", err, out);
        }
    }

    let search = Command::new("which")
        .args(&["msbuild.exe"])
        .output()
        .expect("Could not search for msbuild.exe on path");
    let mut msbuild = if search.status.success() {
        Command::new("msbuild.exe")
    } else {
        cc::windows_registry::find(target.as_str(), "msbuild.exe")
            .expect("Could not find msbuild.exe on the registry")
    };

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or(num_cpus::get().to_string());

    let r = msbuild
        .args(&[
            "win\\libsass.sln",
            "/p:LIBSASS_STATIC_LIB=1",
            "/p:Configuration=Release",
            "/p:WholeProgramOptimization=false",
            format!("/m:{}", jobs).as_str(),
            format!("/p:Platform={}", msvc_platform).as_str(),
        ])
        .current_dir(&build)
        .output()
        .expect("error running msbuild");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("win").join("bin").display()
    );
    println!("cargo:rustc-link-lib=static=libsass");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if let Ok(_) = pkg_config::find_library("libsass") {
        return;
    }

    compile();
}
<commit_msg>Update submodule inside build.rs<commit_after>// extern crate bindgen;
#[cfg(target_env = "msvc")]
extern crate cc;
extern crate pkg_config;
extern crate num_cpus;

use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::process::{Command, Stdio};

// Automatically write bindings to libsass
//#[allow(dead_code)]
//fn write_bindings() {
//    let bindings = bindgen::Builder::default()
//        .header("libsass/include/sass.h")
//        .clang_arg("-Ilibsass/include")
//        // To avoid a test failing
//        .blacklist_type("max_align_t")
//        // we do static linking so it should be fine
//        // https://github.com/rust-lang/rust/issues/36927
//        .rustified_enum(".*")
//        .generate()
//        .expect("Unable to generate bindings");
//
//    // Write the bindings to the $OUT_DIR/bindings.rs file.
//    let out_path = PathBuf::from("src");
//    bindings
//        .write_to_file(out_path.join("bindings.rs"))
//        .expect("Couldn't write bindings!");
//}

macro_rules! t {
    ($e:expr) => (match $e {
        Ok(n) => n,
        Err(e) => panic!("\n{} failed with {}\n", stringify!($e), e),
    })
}

fn cp_r(dir: &Path, dest: &Path) {
    for entry in t!(fs::read_dir(dir)) {
        let entry = t!(entry);
        let path = entry.path();
        let dst = dest.join(path.file_name().unwrap());
        if t!(fs::metadata(&path)).is_file() {
            t!(fs::copy(path, dst));
        } else {
            t!(fs::create_dir_all(&dst));
            cp_r(&path, &dst);
        }
    }
}

// CIs usually do it automatically but for normal users libsass would be missing
fn init_submodule() {
    Command::new("git")
        .arg("submodule")
        .arg("init")
        .stderr(Stdio::null())
        .status()
        .expect("")
        .success();
    Command::new("git")
        .arg("submodule")
        .arg("update")
        .stderr(Stdio::null())
        .status()
        .expect("")
        .success();
}

fn get_libsass_folder() -> PathBuf {
    env::current_dir().unwrap().join("libsass")
}

// linux/unix
#[cfg(not(target_env = "msvc"))]
fn compile() {
    let target = env::var("TARGET").expect("TARGET not found");
    let src = get_libsass_folder();
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);
    let is_bsd = target.contains("dragonfly")
        || target.contains("freebsd")
        || target.contains("netbsd")
        || target.contains("openbsd");
    let libprobe = | lib: &str | -> bool {
      Command::new("cc")
        .arg("-xc++")
        .arg("-o/dev/null")
        .arg(format!("-l{}",lib))
        .arg("-shared")
        .stderr(Stdio::null())
        .status()
        .expect("")
        .success()
    };

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or(num_cpus::get().to_string());
    let r = Command::new(if is_bsd { "gmake" } else { "make" })
        .current_dir(&build)
        .args(&["--jobs", &jobs])
        .output()
        .expect("error running make");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("lib").display()
    );
    println!("cargo:rustc-link-lib=static=sass");

    if libprobe("c++_shared") {
        println!("cargo:rustc-link-lib=dylib=c++_shared");
    }
    else if libprobe("c++") {
        println!("cargo:rustc-link-lib=dylib=c++");
    }
    else if libprobe("stdc++") {
        println!("cargo:rustc-link-lib=dylib=stdc++");
    }
    else {
        panic!("no c++ library found");
    }

}

// windows
#[cfg(target_env = "msvc")]
fn compile() {
    let src = get_libsass_folder();
    let target = env::var("TARGET").expect("TARGET not found in environment");
    let msvc_platform = if target.contains("x86_64") {
        "Win64"
    } else {
        "Win32"
    };
    let dest = PathBuf::from(env::var_os("OUT_DIR").unwrap());
    let build = dest.join("build");
    t!(fs::create_dir_all(&build));
    cp_r(&src, &build);

    // Find an instance of devenv.exe from Visual Studio IDE in order to upgrade
    // libsass.sln to the current available IDE. Do nothing if no devenv.exe found
    let d = cc::windows_registry::find(target.as_str(), "devenv.exe");
    if let Some(mut d) = d {
        let d = d
            .args(&["/upgrade", "win\\libsass.sln"])
            .current_dir(&build)
            .output()
            .expect("error running devenv");
        if !d.status.success() {
            let err = String::from_utf8_lossy(&d.stderr);
            let out = String::from_utf8_lossy(&d.stdout);
            println!("Upgrade error:\nSTDERR:{}\nSTDOUT:{}", err, out);
        }
    }

    let search = Command::new("which")
        .args(&["msbuild.exe"])
        .output()
        .expect("Could not search for msbuild.exe on path");
    let mut msbuild = if search.status.success() {
        Command::new("msbuild.exe")
    } else {
        cc::windows_registry::find(target.as_str(), "msbuild.exe")
            .expect("Could not find msbuild.exe on the registry")
    };

    let jobs = env::var("MAKE_LIBSASS_JOBS").unwrap_or(num_cpus::get().to_string());

    let r = msbuild
        .args(&[
            "win\\libsass.sln",
            "/p:LIBSASS_STATIC_LIB=1",
            "/p:Configuration=Release",
            "/p:WholeProgramOptimization=false",
            format!("/m:{}", jobs).as_str(),
            format!("/p:Platform={}", msvc_platform).as_str(),
        ])
        .current_dir(&build)
        .output()
        .expect("error running msbuild");

    if !r.status.success() {
        let err = String::from_utf8_lossy(&r.stderr);
        let out = String::from_utf8_lossy(&r.stdout);
        panic!("Build error:\nSTDERR:{}\nSTDOUT:{}", err, out);
    }

    println!(
        "cargo:rustc-link-search=native={}",
        build.join("win").join("bin").display()
    );
    println!("cargo:rustc-link-lib=static=libsass");
}

fn main() {
    // Uncomment the line below to generate bindings. Doesn't work on CI as it
    // requires additional tooling
    // write_bindings();

    // Is it already built?
    if let Ok(_) = pkg_config::find_library("libsass") {
        return;
    }

    init_submodule();
    compile();
}
<|endoftext|>


<commit_before><commit_msg>Add macros to print out statements<commit_after><|endoftext|>


<commit_before>#![feature(globs, macro_rules)]

extern crate debug;
extern crate piston;
extern crate sdl2_game_window;
extern crate gl;
extern crate hgl;
extern crate image;
extern crate libc;
extern crate cgmath;

use sdl2_game_window::GameWindowSDL2 as Window;
use piston::{
    AssetStore,
    GameIterator,
    GameIteratorSettings,
    GameWindow,
    GameWindowSettings,
    Render
};

use cam::{Camera, CameraSettings};
use fps_controller::FPSController;
use texture::Texture;

pub mod shader;
pub mod cube;
pub mod cam;
pub mod fps_controller;
pub mod texture;
pub mod vecmath;

fn main() {
    let mut window = Window::new(
        piston::shader_version::opengl::OpenGL_3_3,
        GameWindowSettings {
            title: "Hematite".to_string(),
            size: [600, 600], // [640, 480],
            fullscreen: false,
            exit_on_esc: true,
        }
    );

    window.capture_cursor(true);

    let asset_store = AssetStore::from_folder("../assets");

    // Load texture.
    let texture = asset_store.path("minecraft-texture.png").unwrap();
    let texture = Texture::from_path(&texture).unwrap();

    let game_iter_settings = GameIteratorSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    let shader = shader::Shader::new();
    let mut buffer = shader.new_buffer();

    shader.set_projection(CameraSettings {
        fov: 90.0,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: 1.0
    }.projection());

    let mut camera = Camera::new(0.5, 0.5, 4.0);
    let mut fps_controller = FPSController::new();
    camera.set_yaw_pitch(fps_controller.yaw, fps_controller.pitch);

    for e in GameIterator::new(&mut window, &game_iter_settings) {
        match e {
            Render(_args) => {
                let mut tri: Vec<[([f32, ..3], [f32, ..2], [f32, ..3]), ..3]> = vec![];
                for face in cube::FaceIterator::new() {
                    let v = face.vertices(0.0, 0.0, 0.0);
                    let (tx, ty) = texture::Grass.get_src_xy();
                    let t = texture.square(tx, ty);
                    let v = [
                        (v[0], t[3], [1.0, 0.0, 0.0]),
                        (v[1], t[2], [0.0, 1.0, 0.0]),
                        (v[2], t[1], [0.0, 0.0, 1.0]),
                        (v[3], t[0], [1.0, 0.0, 1.0])
                    ];
                    tri.push([v[0], v[1], v[2]]);
                    tri.push([v[1], v[3], v[2]]);
                }
                buffer.load_data(tri.as_slice());

                shader.set_view(camera.orthogonal());
                shader.bind();
                gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
                shader.render(&buffer);
            },
            e => fps_controller.event(&e, &mut camera),
        }
    }
}
<commit_msg>Don't capture the mouse cursor by default.<commit_after>#![feature(globs, macro_rules)]

extern crate debug;
extern crate piston;
extern crate sdl2_game_window;
extern crate gl;
extern crate hgl;
extern crate image;
extern crate libc;
extern crate cgmath;

use sdl2_game_window::GameWindowSDL2 as Window;
use piston::input;
use piston::{
    AssetStore,
    GameIterator,
    GameIteratorSettings,
    GameWindow,
    GameWindowSettings,
    Input,
    Render
};

use cam::{Camera, CameraSettings};
use fps_controller::FPSController;
use texture::Texture;

pub mod shader;
pub mod cube;
pub mod cam;
pub mod fps_controller;
pub mod texture;
pub mod vecmath;

fn main() {
    let mut window = Window::new(
        piston::shader_version::opengl::OpenGL_3_3,
        GameWindowSettings {
            title: "Hematite".to_string(),
            size: [600, 600], // [640, 480],
            fullscreen: false,
            exit_on_esc: true,
        }
    );

    let asset_store = AssetStore::from_folder("../assets");

    // Load texture.
    let texture = asset_store.path("minecraft-texture.png").unwrap();
    let texture = Texture::from_path(&texture).unwrap();

    let game_iter_settings = GameIteratorSettings {
        updates_per_second: 120,
        max_frames_per_second: 60,
    };

    let shader = shader::Shader::new();
    let mut buffer = shader.new_buffer();

    shader.set_projection(CameraSettings {
        fov: 90.0,
        near_clip: 0.1,
        far_clip: 1000.0,
        aspect_ratio: 1.0
    }.projection());

    let mut camera = Camera::new(0.5, 0.5, 4.0);
    let mut fps_controller = FPSController::new();
    camera.set_yaw_pitch(fps_controller.yaw, fps_controller.pitch);

    let mut capture_cursor = false;
    println!("Press C to capture mouse");

    let mut events = GameIterator::new(&mut window, &game_iter_settings);
    for e in events {
        match e {
            Render(_args) => {
                let mut tri: Vec<[([f32, ..3], [f32, ..2], [f32, ..3]), ..3]> = vec![];
                for face in cube::FaceIterator::new() {
                    let v = face.vertices(0.0, 0.0, 0.0);
                    let (tx, ty) = texture::Grass.get_src_xy();
                    let t = texture.square(tx, ty);
                    let v = [
                        (v[0], t[3], [1.0, 0.0, 0.0]),
                        (v[1], t[2], [0.0, 1.0, 0.0]),
                        (v[2], t[1], [0.0, 0.0, 1.0]),
                        (v[3], t[0], [1.0, 0.0, 1.0])
                    ];
                    tri.push([v[0], v[1], v[2]]);
                    tri.push([v[1], v[3], v[2]]);
                }
                buffer.load_data(tri.as_slice());

                shader.set_view(camera.orthogonal());
                shader.bind();
                gl::Clear(gl::COLOR_BUFFER_BIT | gl::DEPTH_BUFFER_BIT);
                shader.render(&buffer);
            }
            Input(input::KeyPress { key: input::keyboard::C }) => {
                println!("Turned cursor capture {}", if capture_cursor { "off" } else { "on" });
                capture_cursor = !capture_cursor;

                events.game_window.capture_cursor(capture_cursor);
            }
            Input(input::MouseRelativeMove { .. }) => {
                if !capture_cursor {
                    // Don't send the mouse event to the FPS controller.
                    continue;
                }
            }
            _ => {}
        }
        fps_controller.event(&e, &mut camera);
    }
}
<|endoftext|>


<commit_before>extern crate byteorder;

use std::collections::HashMap;
use std::io::Write;
use byteorder::{LittleEndian, WriteBytesExt};

#[derive(Hash, Eq, PartialEq, Clone, Debug)]
struct Frac(u64, u64);

type Memory = HashMap<Frac, f64>;

fn simplify(Frac(a, b): Frac) -> Frac {
    fn gcd(x: u64, y: u64) -> u64 {
        if y == 0 {
            x
        } else {
            gcd(y, x % y)
        }
    }

    let d = gcd(a, b);
    Frac(a/d, b/d)
}

/// judge a set of notes based on harmony.
/// range: floats in [0, 1] and lower is better.
fn judge_harmony(noteset: &[Frac], memory: &Memory) -> f64 {
    let mut harmony_sum = 0_f64;

    for &Frac(a1, b1) in noteset {
        for (&Frac(a2, b2), &familiarity) in memory.iter() {
            let Frac(a3, b3) = simplify(Frac(a1*b2, a2*b1));
            harmony_sum += familiarity * (a3 as f64) * (b3 as f64);
        }
    }
    let iterations = noteset.len()*memory.len();
    let avg_harmony = (harmony_sum as f64)/(iterations as f64);

    (1_f64 - 1_f64/(avg_harmony/5_f64).exp()).max(0_f64).min(1_f64)
}

/// judge a set of notes based on familiarity & novelty balance.
/// range: floats in [0, 1] and lower is better.
fn judge_novelty(noteset: &[Frac], memory: &Memory) -> f64 {
    if noteset.len() < 1 {
        panic!("judge_novelty: need at least 1 note");
    }

    let mut familiarity_sum = 0_f64;
    for note in noteset {
        let &familiarity = memory.get(note).unwrap_or(&0_f64);
        familiarity_sum += familiarity;
    }

    let avg_familiarity = familiarity_sum / (noteset.len() as f64);
    let target_familiarity = 0.1_f64;
    let disparity = (target_familiarity - avg_familiarity).abs();

    (1_f64 - 1_f64/disparity.exp()).max(0_f64).min(1_f64)
}

/// judge a set of notes.
/// range: floats in [0, 1] and lower is better.
fn judge(noteset: &[Frac], memory: &Memory) -> f64 {
    (judge_harmony(noteset, memory) + judge_novelty(noteset, memory))/2_f64
}

fn forget(memory: &mut Memory) {
    for (n, val) in memory.iter_mut() {
        *val *= 0.75;
    }
}

fn remember(note_set: &[Frac], memory: &mut Memory) {
    let increase = 0.1_f64;
    for note in note_set {
        let val = match memory.get(note) {
            Some(v) => v + increase,
            None => increase,
        };
        memory.insert(note.clone(), val);
    }
}

/// step to a set of notes that minimizes the judge function.
fn step_notes(note_set: &[Frac], memory: &Memory) -> Vec<Frac> {
    let mut best: Vec<Frac> = note_set.to_owned();
    let mut best_score = 1_f64;
    for i in 0..note_set.len() {
        for a in 1..12 {
            for b in 1..12 {
                let possibility = simplify(Frac(a, b));
                if (note_set.contains(&possibility)) {
                    continue;
                }
                let note_set2: Vec<Frac> = note_set[0..i].iter()
                                                         .chain(note_set[i+1..note_set.len()].iter())
                                                         .chain([possibility].iter())
                                                         .map(|n| n.clone())
                                                         .collect();
                let score = judge(&note_set2, memory);
                if score < best_score {
                    best = note_set2;
                    best_score = score;
                }
            }
        }
    }

    best
}

type PCM_Sample = i16;
static PCM_HZ: u64 = 44100_u64;
static STEPS_PER_SEC: u64 = 4;
static BASE_NOTE: f64 = 250_f64;
type Endianness = LittleEndian;

fn sine_wave(freq: f64, step: u64) -> f64 {
    (2.0*std::f64::consts::PI*(step as f64)*freq/(PCM_HZ as f64)).sin()
}

fn sine_waves(base_note: f64, fractions: &[Frac], step: u64) -> f64 {
    let mut sum = 0_f64;
    for &Frac(a, b) in fractions {
        let freq = (base_note / (b as f64)) * (a as f64);
        sum += sine_wave(freq, step);
    }

    sum / (fractions.len() as f64)
}

fn linear_envelope(sample: f64, duration: u64, progress: u64) -> f64 {
    sample * (progress as f64) / (duration as f64)
}

fn output_pcm() {
    let mut notes = vec![Frac(1, 2), Frac(1, 1), Frac(1, 3), Frac(1, 5), Frac(1, 7)];
    let mut memory = Memory::new();

    let mut j=0;
    for i in (0_u64..u64::max_value()).cycle() {
        if notes.len() > 10 {
            panic!(format!("{:?}", notes));
        }
        let sample = sine_waves(BASE_NOTE, &notes, i) *
                     (PCM_Sample::max_value() as f64);

        let enveloped = linear_envelope(sample, j, PCM_HZ/STEPS_PER_SEC);

        let bounded = enveloped.min(PCM_Sample::max_value() as f64 - 1_f64)
                               .max(PCM_Sample::min_value() as f64 + 1_f64);

        let as_sample: PCM_Sample = bounded as PCM_Sample;
        std::io::stdout().write_i16::<Endianness>(as_sample).unwrap();

        j += 1;
        if j == PCM_HZ/STEPS_PER_SEC {
            j = 0;
            forget(&mut memory);
            notes = step_notes(&notes, &memory);
            remember(&notes, &mut memory);
        }
    }
}

fn main() {
    output_pcm();
}
<commit_msg>Remove dead code<commit_after>extern crate byteorder;

use std::collections::HashMap;
use std::io::Write;
use byteorder::{LittleEndian, WriteBytesExt};

#[derive(Hash, Eq, PartialEq, Clone, Debug)]
struct Frac(u64, u64);

type Memory = HashMap<Frac, f64>;

fn simplify(Frac(a, b): Frac) -> Frac {
    fn gcd(x: u64, y: u64) -> u64 {
        if y == 0 {
            x
        } else {
            gcd(y, x % y)
        }
    }

    let d = gcd(a, b);
    Frac(a/d, b/d)
}

/// judge a set of notes based on harmony.
/// range: floats in [0, 1] and lower is better.
fn judge_harmony(noteset: &[Frac], memory: &Memory) -> f64 {
    let mut harmony_sum = 0_f64;

    for &Frac(a1, b1) in noteset {
        for (&Frac(a2, b2), &familiarity) in memory.iter() {
            let Frac(a3, b3) = simplify(Frac(a1*b2, a2*b1));
            harmony_sum += familiarity * (a3 as f64) * (b3 as f64);
        }
    }
    let iterations = noteset.len()*memory.len();
    let avg_harmony = (harmony_sum as f64)/(iterations as f64);

    (1_f64 - 1_f64/(avg_harmony/5_f64).exp()).max(0_f64).min(1_f64)
}

/// judge a set of notes based on familiarity & novelty balance.
/// range: floats in [0, 1] and lower is better.
fn judge_novelty(noteset: &[Frac], memory: &Memory) -> f64 {
    if noteset.len() < 1 {
        panic!("judge_novelty: need at least 1 note");
    }

    let mut familiarity_sum = 0_f64;
    for note in noteset {
        let &familiarity = memory.get(note).unwrap_or(&0_f64);
        familiarity_sum += familiarity;
    }

    let avg_familiarity = familiarity_sum / (noteset.len() as f64);
    let target_familiarity = 0.1_f64;
    let disparity = (target_familiarity - avg_familiarity).abs();

    (1_f64 - 1_f64/disparity.exp()).max(0_f64).min(1_f64)
}

/// judge a set of notes.
/// range: floats in [0, 1] and lower is better.
fn judge(noteset: &[Frac], memory: &Memory) -> f64 {
    (judge_harmony(noteset, memory) + judge_novelty(noteset, memory))/2_f64
}

fn forget(memory: &mut Memory) {
    for (n, val) in memory.iter_mut() {
        *val *= 0.75;
    }
}

fn remember(note_set: &[Frac], memory: &mut Memory) {
    let increase = 0.1_f64;
    for note in note_set {
        let val = match memory.get(note) {
            Some(v) => v + increase,
            None => increase,
        };
        memory.insert(note.clone(), val);
    }
}

/// step to a set of notes that minimizes the judge function.
fn step_notes(note_set: &[Frac], memory: &Memory) -> Vec<Frac> {
    let mut best: Vec<Frac> = note_set.to_owned();
    let mut best_score = 1_f64;
    for i in 0..note_set.len() {
        for a in 1..12 {
            for b in 1..12 {
                let possibility = simplify(Frac(a, b));
                if (note_set.contains(&possibility)) {
                    continue;
                }
                let note_set2: Vec<Frac> = note_set[0..i].iter()
                                                         .chain(note_set[i+1..note_set.len()].iter())
                                                         .chain([possibility].iter())
                                                         .map(|n| n.clone())
                                                         .collect();
                let score = judge(&note_set2, memory);
                if score < best_score {
                    best = note_set2;
                    best_score = score;
                }
            }
        }
    }

    best
}

type PCM_Sample = i16;
static PCM_HZ: u64 = 44100_u64;
static STEPS_PER_SEC: u64 = 4;
static BASE_NOTE: f64 = 250_f64;
type Endianness = LittleEndian;

fn sine_wave(freq: f64, step: u64) -> f64 {
    (2.0*std::f64::consts::PI*(step as f64)*freq/(PCM_HZ as f64)).sin()
}

fn sine_waves(base_note: f64, fractions: &[Frac], step: u64) -> f64 {
    let mut sum = 0_f64;
    for &Frac(a, b) in fractions {
        let freq = (base_note / (b as f64)) * (a as f64);
        sum += sine_wave(freq, step);
    }

    sum / (fractions.len() as f64)
}

fn linear_envelope(sample: f64, duration: u64, progress: u64) -> f64 {
    sample * (progress as f64) / (duration as f64)
}

fn output_pcm() {
    let mut notes = vec![Frac(1, 2), Frac(1, 1), Frac(1, 3), Frac(1, 5), Frac(1, 7)];
    let mut memory = Memory::new();

    let mut j=0;
    for i in (0_u64..u64::max_value()).cycle() {
        let sample = sine_waves(BASE_NOTE, &notes, i) *
                     (PCM_Sample::max_value() as f64);

        let enveloped = linear_envelope(sample, j, PCM_HZ/STEPS_PER_SEC);

        let bounded = enveloped.min(PCM_Sample::max_value() as f64 - 1_f64)
                               .max(PCM_Sample::min_value() as f64 + 1_f64);

        let as_sample: PCM_Sample = bounded as PCM_Sample;
        std::io::stdout().write_i16::<Endianness>(as_sample).unwrap();

        j += 1;
        if j == PCM_HZ/STEPS_PER_SEC {
            j = 0;
            forget(&mut memory);
            notes = step_notes(&notes, &memory);
            remember(&notes, &mut memory);
        }
    }
}

fn main() {
    output_pcm();
}
<|endoftext|>


<commit_before><commit_msg>enforcing a max peer handshake size of 512 bytes<commit_after><|endoftext|>


<commit_before>/*
  Rust is an Expression-Based Systems language.
  Declare main function
*/
fn main() {

    // Metaprogramming calling a macro and passing staticaly allocated string arg
    println!("Hello, world!");

    /*
      Variable binding expression.
      <let expression> is Full Pattern for Pattern Matching.
      Rust's Type Inference automatically determines an expression's Type.
      Alternatively be explicit and supply an expression's Type after a colon.
      Or simply annotate the Type in a comment to understand the Type Rust infers.
      Rust Bindings are immutable by Default.
      Mutable Bindings require 'mut' prefix for Type Safety.
    */
    let a: i32 = 5; // assign immutable binding 'a' with Type i32 and Value 5

    // If statement based on Branch concept
    if a == 5 {
      println!("x is five");
    } else {
      println!("x is not five");
    }

    let (x, y, z) = (1, 2, 3);  // assign immutable bindings x, y, z to 1, 2, 3

    let mut b: i32 = 10; // assign mutable binding 'b'
    b = 20; // re-assign to new Value

    /*
      Rust's 'If' is an Expression. It returns a value to initialise
      the 'Let' binding ("Declaration Statement") with. 'Let' is assigned an Expression.
      Assignment to an already bound variable is an Expression.
      Assignment Value in Rust is the special Unit Type () in Rust's Type System.
      In other languages 'If' is a Statements (does not return value).

      Rust's "Expression Statement" converts an Expression into a Statement.
      Semi-colons separate each Expression.
      Semi-colons convert Expression into Statement, throws Value away, returns Unit Type ()
      (causing Type Error when expect a different Type such as i32 to be valid)
    */
    let c: i32 = if b == 20 { 25 } else { 15 };  // Explicitely specify 'c' as of Integer Type
    println!("b is: {}", b); // Interpret interpolation with moustaches
    println!("c is: {}", c);

    incr(b, c); // Call Fn passing Args
    print_sum(b, c); // Call Fn passing Args

    // Compound Data Structure Type Tuple is simple fixed size ordered list where &str is String Slice
    let tuple1: (i32, &str) = (1, "hello"); // Mutable. Type annotated. Without: let x = (1, "hello");
    let mut tuple2: (i32, i32) = (1, 2); // Type annotated. Without: let x = (1, "hello");
    let tuple3: (i32, i32) = (3, 4);

    if tuple2 != tuple3 {
        tuple2 = tuple3; // Assign Tuple to another Mutable Tuple (with same Arity and Types)
        println!("tuple2 and tuple3 not equal so assigning");
    } else {
        println!("tuple2 and tuple3 do not have same Arity, Types, Order, and Value, not assigning");
    }

    /*
      Destructuring Let (access parameters of Tuple).
      Let statement performs Multiple Bindings assignments when LHS and RHS Pattern Match
    */
    let (t1, t2) = tuple2;

    println!("t1 and t2 is {}", t1 + t2); // Note: Expects t1 and t2 to be same Type

    // Tuples to return Multiple Values from a Function
    let (tnt1, tnt2) = next_two(5);
    println!("tnt1, tnt2 = {}, {}", tnt1, tnt2);

    try_structs();

    try_tuple_structs();

    try_newtype();
}

/*
  Rust Structs are of Record Type form similar to Tuples.
  Elements in Structs each have a Name (aka Field/Member) and a Type
*/

// Declare a Struct with a name (camel case). Values Immutable by Default
struct PointInSpace {
    x: i32,
    y: i32
}

fn try_structs() {
  // Create Instance (Mutable) of Struct using Let and set each Field (any order)
  let mut origin = PointInSpace { x: 0, y: 0 }; // origin: PointInSpace

  origin.x = 20;

  println!("Origin is at ({}, {})", origin.x, origin.y); // Dot Notation to access Fields
}

/*
  Rust Tuple Structs are a hybrid data type similar to Tuple and Struct.
  Elements in Tuple Structs DO NOT have a Name, they only have a Type.
  Structs are preferred over Tuple Structs since they have actual Names for Elements.
*/

// Declare a Tuple Struct.
// struct Color { i32, i32, i32 };
// struct PointInWater { i32, i32, i32 };

// Implement Tuple Structs using Structs (with element field names) as Tuple Structs not working
// and give error: expected `:`, found `,`
struct Color {
  red: i32,
  blue: i32,
  green: i32
}

struct PointInWater {
  x: i32,
  y: i32,
  z: i32
}

// fn try_tuple_structs() {
//   let black = Color(0, 0, 0);
//   let origin = Point(0, 0, 0);
// }

// Implement Tuple Structs using Structs (with element field names) as Tuple Structs not working:
// and give error: expected `:`, found `,`
fn try_tuple_structs() {
  let black = Color { red :0, blue: 0, green: 0 };
  let origin = PointInWater { x: 0, y: 0, z: 0 };
}

// Declare a Newtype.
struct Inches (i32);

// Newtypes are Tuple Structs with only One Element
fn try_newtype() {
  let length = Inches(10);
  // Extract inner Integer Type by Desctructing the Let
  let Inches(integer_length) = length; // Assigns length
  println!("Newtype length is {} inches", integer_length);
}

// Returned Tuple is a Single Value (containing Multiple Values)
fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) }

// All control paths must Return a Value
fn incr(m: i32, n: i32) -> i32 {
    if n < m {
      return n; // Early Return
    } else {
      println!("incrementing n from: {}", n);
      return n + 10;
    }
}

/*
  Rust forces Declare expected Type of incoming Fn Args. Type Inference in Fn body.
  Rust allows Declaration expected Type of outgoing Return Value after '->'
*/
fn print_sum(m: i32, n: i32) -> () { // Return the Unit Type () (aka nil)
    if m < n {
      println!("sum with m < n is: {}", m + n);
    } else {
      println!("sum with m >= n is: {}", m + n);
    }
}<commit_msg>Fixed Tuple Struct syntax<commit_after>/*
  Rust is an Expression-Based Systems language.
  Declare main function
*/
fn main() {

    // Metaprogramming calling a macro and passing staticaly allocated string arg
    println!("Hello, world!");

    /*
      Variable binding expression.
      <let expression> is Full Pattern for Pattern Matching.
      Rust's Type Inference automatically determines an expression's Type.
      Alternatively be explicit and supply an expression's Type after a colon.
      Or simply annotate the Type in a comment to understand the Type Rust infers.
      Rust Bindings are immutable by Default.
      Mutable Bindings require 'mut' prefix for Type Safety.
    */
    let a: i32 = 5; // assign immutable binding 'a' with Type i32 and Value 5

    // If statement based on Branch concept
    if a == 5 {
      println!("x is five");
    } else {
      println!("x is not five");
    }

    let (x, y, z) = (1, 2, 3);  // assign immutable bindings x, y, z to 1, 2, 3

    let mut b: i32 = 10; // assign mutable binding 'b'
    b = 20; // re-assign to new Value

    /*
      Rust's 'If' is an Expression. It returns a value to initialise
      the 'Let' binding ("Declaration Statement") with. 'Let' is assigned an Expression.
      Assignment to an already bound variable is an Expression.
      Assignment Value in Rust is the special Unit Type () in Rust's Type System.
      In other languages 'If' is a Statements (does not return value).

      Rust's "Expression Statement" converts an Expression into a Statement.
      Semi-colons separate each Expression.
      Semi-colons convert Expression into Statement, throws Value away, returns Unit Type ()
      (causing Type Error when expect a different Type such as i32 to be valid)
    */
    let c: i32 = if b == 20 { 25 } else { 15 };  // Explicitely specify 'c' as of Integer Type
    println!("b is: {}", b); // Interpret interpolation with moustaches
    println!("c is: {}", c);

    incr(b, c); // Call Fn passing Args
    print_sum(b, c); // Call Fn passing Args

    // Compound Data Structure Type Tuple is simple fixed size ordered list where &str is String Slice
    let tuple1: (i32, &str) = (1, "hello"); // Mutable. Type annotated. Without: let x = (1, "hello");
    let mut tuple2: (i32, i32) = (1, 2); // Type annotated. Without: let x = (1, "hello");
    let tuple3: (i32, i32) = (3, 4);

    if tuple2 != tuple3 {
        tuple2 = tuple3; // Assign Tuple to another Mutable Tuple (with same Arity and Types)
        println!("tuple2 and tuple3 not equal so assigning");
    } else {
        println!("tuple2 and tuple3 do not have same Arity, Types, Order, and Value, not assigning");
    }

    /*
      Destructuring Let (access parameters of Tuple).
      Let statement performs Multiple Bindings assignments when LHS and RHS Pattern Match
    */
    let (t1, t2) = tuple2;

    println!("t1 and t2 is {}", t1 + t2); // Note: Expects t1 and t2 to be same Type

    // Tuples to return Multiple Values from a Function
    let (tnt1, tnt2) = next_two(5);
    println!("tnt1, tnt2 = {}, {}", tnt1, tnt2);

    try_structs();

    try_tuple_structs();

    try_newtype();
}

/*
  Rust Structs are of Record Type form similar to Tuples.
  Elements in Structs each have a Name (aka Field/Member) and a Type
*/

// Declare a Struct with a name (camel case). Values Immutable by Default
struct PointInSpace {
    x: i32,
    y: i32
}

fn try_structs() {
  // Create Instance (Mutable) of Struct using Let and set each Field (any order)
  let mut origin = PointInSpace { x: 0, y: 0 }; // origin: PointInSpace

  origin.x = 20;

  println!("Origin is at ({}, {})", origin.x, origin.y); // Dot Notation to access Fields
}

/*
  Rust Tuple Structs are a hybrid data type similar to Tuple and Struct.
  Elements in Tuple Structs DO NOT have a Name, they only have a Type.
  Structs are preferred over Tuple Structs since they have actual Names for Elements.
  Note: Tuple Structs must use round brackets and colon
*/

struct Color (
  i32,
  i32,
  i32
);

struct PointInWater (
  i32,
  i32,
  i32
);

fn try_tuple_structs() {
  let black = Color(0, 0, 0);
  let origin = PointInWater(0, 0, 0);
}

// Declare a Newtype.
struct Inches (i32);

// Newtypes are Tuple Structs with only One Element
fn try_newtype() {
  let length = Inches(10);
  // Extract inner Integer Type by Desctructing the Let
  let Inches(integer_length) = length; // Assigns length
  println!("Newtype length is {} inches", integer_length);
}

// Returned Tuple is a Single Value (containing Multiple Values)
fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) }

// All control paths must Return a Value
fn incr(m: i32, n: i32) -> i32 {
    if n < m {
      return n; // Early Return
    } else {
      println!("incrementing n from: {}", n);
      return n + 10;
    }
}

/*
  Rust forces Declare expected Type of incoming Fn Args. Type Inference in Fn body.
  Rust allows Declaration expected Type of outgoing Return Value after '->'
*/
fn print_sum(m: i32, n: i32) -> () { // Return the Unit Type () (aka nil)
    if m < n {
      println!("sum with m < n is: {}", m + n);
    } else {
      println!("sum with m >= n is: {}", m + n);
    }
}<|endoftext|>


<commit_before><commit_msg>Fix some panics (#54)<commit_after><|endoftext|>


<commit_before>use std::os::env;
use std::io::buffered::BufferedReader;
use std::io;

fn get_working_dir() -> ~str {
    let elts: ~[(~str,~str)] = env();
    let mut working_dir = ~"";

    for elt in elts.iter() {
        let (ref s1, ref s2): (~str,~str) = *elt;
        if *s1 == ~"PWD" {
            working_dir = s2.clone();
        }
    }
    working_dir
}

fn match_cmd(cmd: &~str) -> ~[~str]{
    let mut cmd_arr: ~[~str] = ~[];

    if cmd.slice(0,2) == "cd" {
        cmd_arr.push(cmd.slice(0, 2).clone());
        cmd_arr.push(cmd.slice(3, cmd_arr.len()).clone());
        //println("done");
    }
    cmd_arr
}

fn read_stdin() {
    let mut reader = BufferedReader::new(io::stdin());
    while !reader.eof() {
        let line = reader.read_line();
        match line {
            Some(ref s) => {
                let cmd = match_cmd(s);
            },
            None => println("None")
        }
    }
}

fn main() {
    let working_dir = get_working_dir();
    print(format!("{}$ ", working_dir));
    std::io::stdio::flush();
    read_stdin();
}
<commit_msg>update<commit_after>use std::os::env;
use std::io::buffered::BufferedReader;
use std::io;
use std::io::process::ProcessConfig;

static DIRECTORY: &'static str = "Hello";

fn get_working_dir() -> ~str {
    let elts: ~[(~str,~str)] = env();
    let mut working_dir = ~"";

    for elt in elts.iter() {
        let (ref s1, ref s2): (~str,~str) = *elt;
        if *s1 == ~"PWD" {
            working_dir = s2.clone();
        }
    }
    working_dir
}

fn create_cmd(cmd: &str) -> ~[~str]{
    let mut cmd_arr: ~[~str] = ~[];
    for word in cmd.words() {
        let s: ~str = word.into_owned();
        cmd_arr.push(s);
    }
    cmd_arr
}

fn read_stdin() {
    let mut reader = BufferedReader::new(io::stdin());
    while !reader.eof() {
        let line = reader.read_line();
        match line {
            Some(ref s) => {
                let cmd = create_cmd(*s);
                let proc_config: ProcessConfig = ProcessConfig {
                    program = *cmd[0];
                };
            },
            None => println("None")
        }
    }
}

fn main() {
    let working_dir = get_working_dir();
    print(format!("{}$ ", working_dir));
    std::io::stdio::flush();
    read_stdin();
}
<|endoftext|>


<commit_before>use std::collections::HashMap;
use std::convert::Into;

use data::packet::Packet;
use data::frame::ArcFrame;
use data::value::Value;

use error::*;

pub trait Encoder {
    fn get_extradata(&self) -> Option<Vec<u8>>;
    fn send_frame(&mut self, pkt: &ArcFrame) -> Result<()>;
    fn receive_packet(&mut self) -> Result<Packet>;

    fn configure(&mut self) -> Result<()>;
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
    // fn get_option(&mut self, key: &str) -> Option<Value>;
}

pub struct Context {
    enc: Box<Encoder>,
    // TODO: Queue up packets/frames
    // TODO: Store here more information
    // TODO: Have a resource pool
    // format: Format
}

impl Context {
    // TODO: More constructors
    pub fn by_name(codecs: &Codecs, name: &str) -> Option<Context> {
        if let Some(builder) = codecs.by_name(name) {
            let enc = builder.create();
            Some(Context { enc: enc })
        } else {
            None
        }
    }

    pub fn configure(&mut self) -> Result<()> {
        self.enc.configure()
    }

    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
        where V: Into<Value<'a>>
    {
        // TODO: support more options
        self.enc.set_option(key, val.into())
    }

    pub fn get_extradata(&mut self) -> Option<Vec<u8>> {
        self.enc.get_extradata()
    }
    pub fn send_frame(&mut self, frame: &ArcFrame) -> Result<()> {
        self.enc.send_frame(frame)
    }
    // TODO: Return an Event?
    pub fn receive_packet(&mut self) -> Result<Packet> {
        self.enc.receive_packet()
    }

    // TODO: Explicitly flush the encoder
    // pub fn flush(&mut self) -> Result<()>
}

#[derive(Debug)]
pub struct Descr {
    pub codec: &'static str,
    pub name: &'static str,
    pub desc: &'static str,
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

pub trait Descriptor {
    fn create(&self) -> Box<Encoder>;
    fn describe<'a>(&'a self) -> &'a Descr;
}

pub struct Codecs {
    list: HashMap<&'static str, Vec<&'static Descriptor>>
}

pub use common::CodecList;

impl CodecList for Codecs {
    type D = Descriptor;
    fn new() -> Codecs {
        Codecs { list: HashMap::new() }
    }
    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Descriptor> {
        if let Some(descs) = self.list.get(name) {
            Some(descs[0])
        } else {
            None
        }
    }

    fn append(&mut self, desc: &'static Descriptor) {
        let codec_name = desc.describe().codec;

        self.list.entry(codec_name).or_insert(Vec::new()).push(desc);
    }
}

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

    mod dummy {
        use super::super::*;
        use std::rc::Rc;
        use data::pixel::Formaton;
        use super::super::super::error::ErrorKind;

        struct Enc {
            state: usize,
            w: Option<usize>,
            h: Option<usize>,
            format: Option<Rc<Formaton>>
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            fn create(&self) -> Box<Encoder> {
                box Enc { state: 0, w: None, h: None, format: None }
            }
            fn describe<'a>(&'a self) -> &'a Descr {
                &self.descr
            }
        }

        impl Encoder for Enc {
            fn configure(&mut self) -> Result<()> {
                if self.h.is_some() && self.w.is_some() && self.format.is_some() {
                    Ok(())
                } else {
                    Err(ErrorKind::ConfigurationIncomplete.into())
                }
            }
            fn get_extradata(&self) -> Option<Vec<u8>> {
                Some(vec![self.state as u8; 1])
            }
            fn send_frame(&mut self, _frame: &ArcFrame) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_packet(&mut self) -> Result<Packet> {
                let mut p = Packet::with_capacity(1);

                p.data.push(self.state as u8);

                Ok(p)
            }
            fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()> {
                match (key, val) {
                    ("w", Value::U64(v)) => self.w = Some(v as usize),
                    ("h", Value::U64(v)) => self.h = Some(v as usize),
                    ("format", Value::Formaton(f)) => self.format = Some(f),
                    _ => return Err(ErrorKind::Unsupported.into())
                }

                Ok(())
            }

        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy encoder",
                mime: "x-application/dummy",
            }
        };
    }
    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _enc = codecs.by_name("dummy");
    }
}
<commit_msg>codec: Add encoder flush()<commit_after>use std::collections::HashMap;
use std::convert::Into;

use data::packet::Packet;
use data::frame::ArcFrame;
use data::value::Value;

use error::*;

pub trait Encoder {
    fn get_extradata(&self) -> Option<Vec<u8>>;
    fn send_frame(&mut self, pkt: &ArcFrame) -> Result<()>;
    fn receive_packet(&mut self) -> Result<Packet>;
    fn flush(&mut self) -> Result<()>;

    fn configure(&mut self) -> Result<()>;
    fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()>;
    // fn get_option(&mut self, key: &str) -> Option<Value>;
}

pub struct Context {
    enc: Box<Encoder>,
    // TODO: Queue up packets/frames
    // TODO: Store here more information
    // TODO: Have a resource pool
    // format: Format
}

impl Context {
    // TODO: More constructors
    pub fn by_name(codecs: &Codecs, name: &str) -> Option<Context> {
        if let Some(builder) = codecs.by_name(name) {
            let enc = builder.create();
            Some(Context { enc: enc })
        } else {
            None
        }
    }

    pub fn configure(&mut self) -> Result<()> {
        self.enc.configure()
    }

    pub fn set_option<'a, V>(&mut self, key: &str, val: V) -> Result<()>
        where V: Into<Value<'a>>
    {
        // TODO: support more options
        self.enc.set_option(key, val.into())
    }

    pub fn get_extradata(&mut self) -> Option<Vec<u8>> {
        self.enc.get_extradata()
    }
    pub fn send_frame(&mut self, frame: &ArcFrame) -> Result<()> {
        self.enc.send_frame(frame)
    }
    // TODO: Return an Event?
    pub fn receive_packet(&mut self) -> Result<Packet> {
        self.enc.receive_packet()
    }

    pub fn flush(&mut self) -> Result<()> {
        self.enc.flush()
    }
}

#[derive(Debug)]
pub struct Descr {
    pub codec: &'static str,
    pub name: &'static str,
    pub desc: &'static str,
    pub mime: &'static str,
    // TODO more fields regarding capabilities
}

pub trait Descriptor {
    fn create(&self) -> Box<Encoder>;
    fn describe<'a>(&'a self) -> &'a Descr;
}

pub struct Codecs {
    list: HashMap<&'static str, Vec<&'static Descriptor>>
}

pub use common::CodecList;

impl CodecList for Codecs {
    type D = Descriptor;
    fn new() -> Codecs {
        Codecs { list: HashMap::new() }
    }
    // TODO more lookup functions
    fn by_name(&self, name: &str) -> Option<&'static Descriptor> {
        if let Some(descs) = self.list.get(name) {
            Some(descs[0])
        } else {
            None
        }
    }

    fn append(&mut self, desc: &'static Descriptor) {
        let codec_name = desc.describe().codec;

        self.list.entry(codec_name).or_insert(Vec::new()).push(desc);
    }
}

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

    mod dummy {
        use super::super::*;
        use std::rc::Rc;
        use data::pixel::Formaton;
        use super::super::super::error::ErrorKind;

        struct Enc {
            state: usize,
            w: Option<usize>,
            h: Option<usize>,
            format: Option<Rc<Formaton>>
        }

        pub struct Des {
            descr: Descr,
        }

        impl Descriptor for Des {
            fn create(&self) -> Box<Encoder> {
                box Enc { state: 0, w: None, h: None, format: None }
            }
            fn describe<'a>(&'a self) -> &'a Descr {
                &self.descr
            }
        }

        impl Encoder for Enc {
            fn configure(&mut self) -> Result<()> {
                if self.h.is_some() && self.w.is_some() && self.format.is_some() {
                    Ok(())
                } else {
                    Err(ErrorKind::ConfigurationIncomplete.into())
                }
            }
            fn get_extradata(&self) -> Option<Vec<u8>> {
                Some(vec![self.state as u8; 1])
            }
            fn send_frame(&mut self, _frame: &ArcFrame) -> Result<()> {
                self.state += 1;
                Ok(())
            }
            fn receive_packet(&mut self) -> Result<Packet> {
                let mut p = Packet::with_capacity(1);

                p.data.push(self.state as u8);

                Ok(p)
            }
            fn set_option<'a>(&mut self, key: &str, val: Value<'a>) -> Result<()> {
                match (key, val) {
                    ("w", Value::U64(v)) => self.w = Some(v as usize),
                    ("h", Value::U64(v)) => self.h = Some(v as usize),
                    ("format", Value::Formaton(f)) => self.format = Some(f),
                    _ => return Err(ErrorKind::Unsupported.into())
                }

                Ok(())
            }

        }

        pub const DUMMY_DESCR: &Des = &Des {
            descr: Descr {
                codec: "dummy",
                name: "dummy",
                desc: "Dummy encoder",
                mime: "x-application/dummy",
            }
        };
    }
    use self::dummy::DUMMY_DESCR;

    #[test]
    fn lookup() {
        let codecs = Codecs::from_list(&[DUMMY_DESCR]);

        let _enc = codecs.by_name("dummy");
    }
}
<|endoftext|>


<commit_before>// Copyright 2016 Walter Kuppens.
//
// 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.

use debugger::parser;
use nes::nes::NES;
use std::sync::mpsc::Receiver;
use std::io::{self, Write};

enum Command {
    Stop,
    Continue,
    Dump,
}

pub struct Debugger {
    receiver: Receiver<String>,
    stepping: bool,
}

impl Debugger {
    pub fn new(receiver: Receiver<String>) -> Self {
        Debugger {
            receiver: receiver,
            stepping: true,
        }
    }

    pub fn step(&mut self, nes: &mut NES) {
        match self.receiver.try_recv() {
            Ok(input) => {
                self.interpret(input);
            },
            Err(e) => {}, // Ignore empty and disconnect errors.
        };

        if self.stepping {
            nes.step();
        }
    }

    fn interpret(&self, input: String) {
        let args = match parser::input_to_arguments(input) {
            Ok(args) => args,
            Err(e) => {
                let mut stderr = io::stderr();
                writeln!(stderr, "nes-rs: {}", e).unwrap();
                return;
            },
        };
        println!("{:?}", args);
    }
}
<commit_msg>Commands now map to enums<commit_after>// Copyright 2016 Walter Kuppens.
//
// 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.

use debugger::parser;
use nes::nes::NES;
use std::io::{self, Write};
use std::sync::mpsc::Receiver;
use std::thread;
use std::time::Duration;

#[derive(Debug)]
enum Command {
    Stop,
    Continue,
    Dump,
}

pub struct Debugger {
    receiver: Receiver<String>,
    stepping: bool,
}

impl Debugger {
    pub fn new(receiver: Receiver<String>) -> Self {
        Debugger {
            receiver: receiver,
            stepping: true,
        }
    }

    /// Steps the CPU forward a single instruction, as well as executing any PPU
    /// and sound functionality that happens in-between.
    pub fn step(&mut self, nes: &mut NES) {
        // Input is received from another thread so the emulator can run without
        // the debugger prompt blocking it.
        match self.receiver.try_recv() {
            Ok(input) => self.interpret(input),
            Err(e) => {}, // Ignore empty and disconnect errors.
        };

        // If the debugger is in stepping mode, continue execution like normal,
        // otherwise the CPU and other peripherals should not update. In the
        // meantime, sleep the host CPU while we wait for input.
        if self.stepping {
            nes.step();
        } else {
            thread::sleep(Duration::from_millis(16));
        }
    }

    /// Parse a raw input string into a list of arguments and a command, then
    /// execute the command's functionality.
    fn interpret(&mut self, input: String) {
        // Parse the input from stdin and receive an array of arguments.
        let mut stderr = io::stderr();
        let args = match parser::input_to_arguments(input) {
            Ok(args) => args,
            Err(e) => {
                writeln!(stderr, "nes-rs: {}", e).unwrap();
                return;
            },
        };

        // Determine which command to execute given the first argument and
        // execute it's routine.
        let raw_command = if args.len() > 0 {
            &args[0]
        } else {
            writeln!(stderr, "nes-rs: no command specified").unwrap();
            return;
        };
        let command = match raw_command.to_lowercase().as_str() {
            // Full commands.
            "stop"     => Command::Stop,
            "continue" => Command::Continue,
            "dump"     => Command::Dump,
            // Aliases.
            "s" => Command::Stop,
            "c" => Command::Continue,
            "d" => Command::Dump,
            // Unknown command.
            _ => {
                writeln!(stderr, "nes-rs: unknown command specified").unwrap();
                return;
            },
        };
        self.execute_command(command, &args[1..]);
    }

    /// Executes a debugger command.
    fn execute_command(&mut self, command: Command, args: &[String]) {
        println!("{:?} => {:?}", command, args);
    }
}
<|endoftext|>