<commit_before>use std::sync::{self, Arc, RwLock};
use std::vec::Vec;
use std::error;

use rocksdb::DB;
use protobuf::{self, Message};

use proto::metapb;
use proto::raftpb::{Entry, Snapshot, HardState, ConfState};
use proto::raft_serverpb::{RaftSnapshotData, KeyValue};
use raft::{self, Storage, RaftState, StorageError};
use raftserver::{Result, Error};
use super::keys;
use super::engine;
use super::region_meta::{RegionMeta, RAFT_INIT_LOG_INDEX, RAFT_INIT_LOG_TERM};

pub struct RegionStorage {
    engine: Arc<DB>,

    meta: Arc<RwLock<RegionMeta>>,
}

impl RegionStorage {
    pub fn new(engine: Arc<DB>, meta: Arc<RwLock<RegionMeta>>) -> RegionStorage {
        RegionStorage {
            engine: engine,
            meta: meta,
        }
    }
}

fn storage_error<E>(error: E) -> raft::Error
    where E: Into<Box<error::Error + Send + Sync>>
{
    raft::Error::Store(StorageError::Other(error.into()))
}

impl From<Error> for raft::Error {
    fn from(err: Error) -> raft::Error {
        storage_error(err)
    }
}

impl<T> From<sync::PoisonError<T>> for raft::Error {
    fn from(_: sync::PoisonError<T>) -> raft::Error {
        storage_error("lock failed")
    }
}

impl Storage for RegionStorage {
    fn initial_state(&self) -> raft::Result<RaftState> {
        let mut meta = try!(self.meta.write());
        let initialized = meta.is_initialized();
        let res: Option<HardState> = try!(engine::get_msg(self.engine.as_ref(),
                                                    &keys::raft_hard_state_key(meta.region_id)));

        let found = res.is_some();
        let mut hard_state = match res {
            Some(state) => state,
            None => HardState::new(),
        };

        if !found {
            if initialized {
                hard_state.set_term(RAFT_INIT_LOG_TERM);
                hard_state.set_commit(RAFT_INIT_LOG_INDEX);
                meta.last_index = RAFT_INIT_LOG_INDEX;
            } else {
                meta.last_index = 0;
            }
        } else if initialized && hard_state.get_commit() == 0 {
            hard_state.set_commit(RAFT_INIT_LOG_INDEX);
        }

        let mut conf_state = ConfState::new();
        if found || initialized {
            for p in meta.region.get_peers() {
                conf_state.mut_nodes().push(p.get_peer_id());
            }
        }

        Ok(RaftState {
            hard_state: hard_state,
            conf_state: conf_state,
        })
    }

    fn entries(&self, low: u64, high: u64, max_size: u64) -> raft::Result<Vec<Entry>> {
        if low > high {
            return Err(storage_error(format!("low: {} is greater that high: {}", low, high)));
        }

        let mut ents = vec![];
        let mut total_size: u64 = 0;
        let mut next_index = low;
        let mut exceeded_max_size = false;

        let meta = try!(self.meta.read());
        let start_key = keys::raft_log_key(meta.region_id, low);
        let end_key = keys::raft_log_key(meta.region_id, high);

        try!(engine::scan(self.engine.as_ref(),
                          &start_key,
                          &end_key,
                          &mut |_, value| -> Result<bool> {
                              let mut entry = Entry::new();
                              try!(entry.merge_from_bytes(value));

                              // May meet gap or has been compacted.
                              if entry.get_index() != next_index {
                                  return Ok(true);
                              }

                              next_index += 1;

                              // We only check if max_size > 0.
                              if max_size > 0 {
                                  total_size += entry.compute_size() as u64;
                                  exceeded_max_size = total_size > max_size;
                              }

                              ents.push(entry);

                              Ok(!exceeded_max_size)
                          }));

        // If we get the correct number of entries the total size exceeds max_size, returns.
        if ents.len() == (high - low) as usize || exceeded_max_size {
            return Ok(ents);
        }

        // Can we simplify following check?
        if ents.len() > 0 {
            // Here means we meet some error.
            if ents[0].get_index() > low {
                return Err(raft::Error::Store(StorageError::Compacted));
            }

            if meta.last_index <= next_index {
                return Err(raft::Error::Store(StorageError::Unavailable));
            }

            return Err(storage_error(format!("meet a gap in {} {} at index {}",
                                             low,
                                             high,
                                             next_index)));
        }

        let state = try!(meta.get_truncated_state());
        if state.get_index() >= low {
            // The truncated log index >= low.
            return Err(raft::Error::Store(StorageError::Compacted));
        }

        return Err(raft::Error::Store(StorageError::Unavailable));
    }

    fn term(&self, idx: u64) -> raft::Result<u64> {
        match self.entries(idx, idx + 1, 0) {
            Err(e@raft::Error::Store(StorageError::Compacted)) => {
                let meta = try!(self.meta.read());
                let state = try!(meta.get_truncated_state());
                if state.get_index() == idx {
                    return Ok(state.get_term());
                }
                return Err(e);

            }
            Err(e) => return Err(e),
            Ok(ents) => {
                if ents.len() == 0 {
                    return Ok(0);
                } else {
                    return Ok(ents[0].get_term());
                }
            }
        }
    }

    fn first_index(&self) -> raft::Result<u64> {
        let meta = try!(self.meta.read());
        let first_index = try!(meta.get_first_index());
        Ok(first_index)
    }

    fn last_index(&self) -> raft::Result<u64> {
        let meta = try!(self.meta.read());
        Ok(meta.last_index)
    }

    fn snapshot(&self) -> raft::Result<Snapshot> {
        let snap = self.engine.snapshot();

        // TODO: get applied_index and region info from snapshot.
        let meta = try!(self.meta.read());
        let applied_index = try!(meta.load_applied_index(&snap));

        let res: Option<metapb::Region> = try!(engine::get_msg(&snap,
                                            &keys::region_info_key(meta.region.get_start_key())));

        let region = match res {
            None => return Err(storage_error(format!("could not find region info"))),
            Some(region) => region,
        };

        let term = try!(self.term(applied_index));

        let mut snapshot = Snapshot::new();

        // Set snapshot metadata.
        snapshot.mut_metadata().set_index(applied_index);
        snapshot.mut_metadata().set_term(term);

        let mut conf_state = ConfState::new();
        for p in region.get_peers() {
            conf_state.mut_nodes().push(p.get_peer_id());
        }

        snapshot.mut_metadata().set_conf_state(conf_state);

        // Set snapshot data.
        let mut snap_data = RaftSnapshotData::new();
        snap_data.set_region(region);

        let mut data = vec![];
        try!(meta.snap_scan_region(&snap,
                                   &mut |key, value| {
                                       let mut kv = KeyValue::new();
                                       kv.set_key(key.to_vec());
                                       kv.set_value(value.to_vec());
                                       data.push(kv);
                                       Ok(true)
                                   }));

        snap_data.set_data(protobuf::RepeatedField::from_vec(data));

        let mut v = vec![];
        try!(snap_data.write_to_vec(&mut v));

        snapshot.set_data(v);

        Ok(snapshot)
    }
}
<commit_msg>raftserver: cleanup.<commit_after>use std::sync::{self, Arc, RwLock};
use std::vec::Vec;
use std::error;

use rocksdb::DB;
use protobuf::{self, Message};

use proto::metapb;
use proto::raftpb::{Entry, Snapshot, HardState, ConfState};
use proto::raft_serverpb::{RaftSnapshotData, KeyValue};
use raft::{self, Storage, RaftState, StorageError};
use raftserver::{Result, Error};
use super::keys;
use super::engine;
use super::region_meta::{RegionMeta, RAFT_INIT_LOG_INDEX, RAFT_INIT_LOG_TERM};

pub struct RegionStorage {
    engine: Arc<DB>,

    meta: Arc<RwLock<RegionMeta>>,
}

impl RegionStorage {
    pub fn new(engine: Arc<DB>, meta: Arc<RwLock<RegionMeta>>) -> RegionStorage {
        RegionStorage {
            engine: engine,
            meta: meta,
        }
    }
}

fn storage_error<E>(error: E) -> raft::Error
    where E: Into<Box<error::Error + Send + Sync>>
{
    raft::Error::Store(StorageError::Other(error.into()))
}

impl From<Error> for raft::Error {
    fn from(err: Error) -> raft::Error {
        storage_error(err)
    }
}

impl<T> From<sync::PoisonError<T>> for raft::Error {
    fn from(_: sync::PoisonError<T>) -> raft::Error {
        storage_error("lock failed")
    }
}

impl Storage for RegionStorage {
    fn initial_state(&self) -> raft::Result<RaftState> {
        let mut meta = try!(self.meta.write());
        let initialized = meta.is_initialized();
        let res: Option<HardState> = try!(engine::get_msg(self.engine.as_ref(),
                                                    &keys::raft_hard_state_key(meta.region_id)));

        let (mut hard_state, found) = res.map_or((HardState::new(), false), |e| (e, true));

        if !found {
            if initialized {
                hard_state.set_term(RAFT_INIT_LOG_TERM);
                hard_state.set_commit(RAFT_INIT_LOG_INDEX);
                meta.last_index = RAFT_INIT_LOG_INDEX;
            } else {
                meta.last_index = 0;
            }
        } else if initialized && hard_state.get_commit() == 0 {
            hard_state.set_commit(RAFT_INIT_LOG_INDEX);
        }

        let mut conf_state = ConfState::new();
        if found || initialized {
            for p in meta.region.get_peers() {
                conf_state.mut_nodes().push(p.get_peer_id());
            }
        }

        Ok(RaftState {
            hard_state: hard_state,
            conf_state: conf_state,
        })
    }

    fn entries(&self, low: u64, high: u64, max_size: u64) -> raft::Result<Vec<Entry>> {
        if low > high {
            return Err(storage_error(format!("low: {} is greater that high: {}", low, high)));
        }

        let mut ents = vec![];
        let mut total_size: u64 = 0;
        let mut next_index = low;
        let mut exceeded_max_size = false;

        let meta = try!(self.meta.read());
        let start_key = keys::raft_log_key(meta.region_id, low);
        let end_key = keys::raft_log_key(meta.region_id, high);

        try!(engine::scan(self.engine.as_ref(),
                          &start_key,
                          &end_key,
                          &mut |_, value| -> Result<bool> {
                              let mut entry = Entry::new();
                              try!(entry.merge_from_bytes(value));

                              // May meet gap or has been compacted.
                              if entry.get_index() != next_index {
                                  return Ok(true);
                              }

                              next_index += 1;

                              // We only check if max_size > 0.
                              if max_size > 0 {
                                  total_size += entry.compute_size() as u64;
                                  exceeded_max_size = total_size > max_size;
                              }

                              ents.push(entry);

                              Ok(!exceeded_max_size)
                          }));

        // If we get the correct number of entries the total size exceeds max_size, returns.
        if ents.len() == (high - low) as usize || exceeded_max_size {
            return Ok(ents);
        }

        // Can we simplify following check?
        if ents.len() > 0 {
            // Here means we meet some error.
            if ents[0].get_index() > low {
                return Err(raft::Error::Store(StorageError::Compacted));
            }

            if meta.last_index <= next_index {
                return Err(raft::Error::Store(StorageError::Unavailable));
            }

            return Err(storage_error(format!("meet a gap in {} {} at index {}",
                                             low,
                                             high,
                                             next_index)));
        }

        let state = try!(meta.get_truncated_state());
        if state.get_index() >= low {
            // The truncated log index >= low.
            return Err(raft::Error::Store(StorageError::Compacted));
        }

        return Err(raft::Error::Store(StorageError::Unavailable));
    }

    fn term(&self, idx: u64) -> raft::Result<u64> {
        match self.entries(idx, idx + 1, 0) {
            Err(e@raft::Error::Store(StorageError::Compacted)) => {
                let meta = try!(self.meta.read());
                let state = try!(meta.get_truncated_state());
                if state.get_index() == idx {
                    return Ok(state.get_term());
                }
                return Err(e);

            }
            Err(e) => return Err(e),
            Ok(ents) => {
                if ents.len() == 0 {
                    return Ok(0);
                } else {
                    return Ok(ents[0].get_term());
                }
            }
        }
    }

    fn first_index(&self) -> raft::Result<u64> {
        let meta = try!(self.meta.read());
        let first_index = try!(meta.get_first_index());
        Ok(first_index)
    }

    fn last_index(&self) -> raft::Result<u64> {
        let meta = try!(self.meta.read());
        Ok(meta.last_index)
    }

    fn snapshot(&self) -> raft::Result<Snapshot> {
        let snap = self.engine.snapshot();

        // TODO: get applied_index and region info from snapshot.
        let meta = try!(self.meta.read());
        let applied_index = try!(meta.load_applied_index(&snap));

        let res: Option<metapb::Region> = try!(engine::get_msg(&snap,
                                            &keys::region_info_key(meta.region.get_start_key())));

        let region = match res {
            None => return Err(storage_error(format!("could not find region info"))),
            Some(region) => region,
        };

        let term = try!(self.term(applied_index));

        let mut snapshot = Snapshot::new();

        // Set snapshot metadata.
        snapshot.mut_metadata().set_index(applied_index);
        snapshot.mut_metadata().set_term(term);

        let mut conf_state = ConfState::new();
        for p in region.get_peers() {
            conf_state.mut_nodes().push(p.get_peer_id());
        }

        snapshot.mut_metadata().set_conf_state(conf_state);

        // Set snapshot data.
        let mut snap_data = RaftSnapshotData::new();
        snap_data.set_region(region);

        let mut data = vec![];
        try!(meta.snap_scan_region(&snap,
                                   &mut |key, value| {
                                       let mut kv = KeyValue::new();
                                       kv.set_key(key.to_vec());
                                       kv.set_value(value.to_vec());
                                       data.push(kv);
                                       Ok(true)
                                   }));

        snap_data.set_data(protobuf::RepeatedField::from_vec(data));

        let mut v = vec![];
        try!(snap_data.write_to_vec(&mut v));

        snapshot.set_data(v);

        Ok(snapshot)
    }
}
<|endoftext|>


<commit_before>use std::hash::Hash;
use std::collections::HashMap;
use std::collections::hash_map::Entry;

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum TemporalRelation {
    Equal,
    Caused,
    EffectOf,
    Concurrent,
}

#[derive(PartialEq, Eq, Debug)]
pub struct VectorClock<HostType: Hash + Eq> {
    entries: HashMap<HostType, u64>,
}

impl<HostType: Clone + Hash + Eq> VectorClock<HostType> {
    pub fn new() -> VectorClock<HostType> {
        VectorClock {
            entries: HashMap::new(),
        }
    }

    pub fn incremented(&self, host: HostType) -> Self {
        let mut entries = self.entries.clone();

        {
            match entries.entry(host) {
                Entry::Vacant(e) => { e.insert(1); },
                Entry::Occupied(mut e) => {
                    let v = *e.get();
                    e.insert(v + 1);
                },
            };
        }

        VectorClock {
            entries: entries,
        }
    }

    pub fn temporal_relation(&self, other: &Self) -> TemporalRelation {
        if self == other {
            TemporalRelation::Equal
        }
        else if self.superseded_by(other) {
            TemporalRelation::Caused
        }
        else if other.superseded_by(self) {
            TemporalRelation::EffectOf
        }
        else {
            TemporalRelation::Concurrent
        }
    }

    fn superseded_by(&self, other: &Self) -> bool {
        let mut has_smaller = false;

        for (host, &self_n) in self.entries.iter() {
            let other_n = *other.entries.get(host).unwrap_or(&0);

            if self_n > other_n {
                return false;
            }

            has_smaller = has_smaller || (self_n < other_n);
        }

        for (host, &other_n) in other.entries.iter() {
            let self_n = *self.entries.get(host).unwrap_or(&0);

            if self_n > other_n {
                return false;
            }

            has_smaller = has_smaller || (self_n < other_n);
        }

        has_smaller
    }

    pub fn merge_with(&self, other: &Self) -> Self {
        let mut entries = self.entries.clone();

        for (host, &other_n) in other.entries.iter() {
            match entries.entry(host.clone()) {
                Entry::Vacant(e) => { e.insert(other_n); },
                Entry::Occupied(mut e) => {
                    let self_n = *e.get();

                    if other_n > self_n {
                        e.insert(other_n);
                    }
                }
            }
        }

        VectorClock {
            entries: entries,
        }
    }
}

#[cfg(test)]
mod test {
    use super::{VectorClock, TemporalRelation};

    type StrVectorClock = VectorClock<&'static str>;

    #[test]
    fn test_empty_ordering() {
        let c1 = StrVectorClock::new();
        let c2 = StrVectorClock::new();

        assert_eq!(c1, c2);

        assert!(c1.temporal_relation(&c2) == TemporalRelation::Equal);
        assert!(c2.temporal_relation(&c1) == TemporalRelation::Equal);
    }

    #[test]
    fn test_incremented_ordering() {
        let c1 = StrVectorClock::new();
        let c2 = c1.incremented("A");

        assert!(!(c1 == c2));

        assert!(c1.temporal_relation(&c2) == TemporalRelation::Caused);
        assert!(c2.temporal_relation(&c1) == TemporalRelation::EffectOf);
    }

    #[test]
    fn test_diverged() {
        let base = StrVectorClock::new();
        let c1 = base.incremented("A");
        let c2 = base.incremented("B");

        assert!(!(c1 == c2));

        assert!(c1.temporal_relation(&c2) == TemporalRelation::Concurrent);
        assert!(c2.temporal_relation(&c1) == TemporalRelation::Concurrent);
    }

    #[test]
    fn test_merged() {
        let base = StrVectorClock::new();
        let c1 = base.incremented("A");
        let c2 = base.incremented("B");

        let m = c1.merge_with(&c2);

        assert!(m.temporal_relation(&c1) == TemporalRelation::EffectOf);
        assert!(c1.temporal_relation(&m) == TemporalRelation::Caused);

        assert!(m.temporal_relation(&c2) == TemporalRelation::EffectOf);
        assert!(c2.temporal_relation(&m) == TemporalRelation::Caused);
    }
}
<commit_msg>Remove unnecessary scope<commit_after>use std::hash::Hash;
use std::collections::HashMap;
use std::collections::hash_map::Entry;

#[derive(Debug, PartialEq, Eq, Copy, Clone)]
pub enum TemporalRelation {
    Equal,
    Caused,
    EffectOf,
    Concurrent,
}

#[derive(PartialEq, Eq, Debug)]
pub struct VectorClock<HostType: Hash + Eq> {
    entries: HashMap<HostType, u64>,
}

impl<HostType: Clone + Hash + Eq> VectorClock<HostType> {
    pub fn new() -> VectorClock<HostType> {
        VectorClock {
            entries: HashMap::new(),
        }
    }

    pub fn incremented(&self, host: HostType) -> Self {
        let mut entries = self.entries.clone();

        match entries.entry(host) {
            Entry::Vacant(e) => { e.insert(1); },
            Entry::Occupied(mut e) => {
                let v = *e.get();
                e.insert(v + 1);
            },
        };

        VectorClock {
            entries: entries,
        }
    }

    pub fn temporal_relation(&self, other: &Self) -> TemporalRelation {
        if self == other {
            TemporalRelation::Equal
        }
        else if self.superseded_by(other) {
            TemporalRelation::Caused
        }
        else if other.superseded_by(self) {
            TemporalRelation::EffectOf
        }
        else {
            TemporalRelation::Concurrent
        }
    }

    fn superseded_by(&self, other: &Self) -> bool {
        let mut has_smaller = false;

        for (host, &self_n) in self.entries.iter() {
            let other_n = *other.entries.get(host).unwrap_or(&0);

            if self_n > other_n {
                return false;
            }

            has_smaller = has_smaller || (self_n < other_n);
        }

        for (host, &other_n) in other.entries.iter() {
            let self_n = *self.entries.get(host).unwrap_or(&0);

            if self_n > other_n {
                return false;
            }

            has_smaller = has_smaller || (self_n < other_n);
        }

        has_smaller
    }

    pub fn merge_with(&self, other: &Self) -> Self {
        let mut entries = self.entries.clone();

        for (host, &other_n) in other.entries.iter() {
            match entries.entry(host.clone()) {
                Entry::Vacant(e) => { e.insert(other_n); },
                Entry::Occupied(mut e) => {
                    let self_n = *e.get();

                    if other_n > self_n {
                        e.insert(other_n);
                    }
                }
            }
        }

        VectorClock {
            entries: entries,
        }
    }
}

#[cfg(test)]
mod test {
    use super::{VectorClock, TemporalRelation};

    type StrVectorClock = VectorClock<&'static str>;

    #[test]
    fn test_empty_ordering() {
        let c1 = StrVectorClock::new();
        let c2 = StrVectorClock::new();

        assert_eq!(c1, c2);

        assert!(c1.temporal_relation(&c2) == TemporalRelation::Equal);
        assert!(c2.temporal_relation(&c1) == TemporalRelation::Equal);
    }

    #[test]
    fn test_incremented_ordering() {
        let c1 = StrVectorClock::new();
        let c2 = c1.incremented("A");

        assert!(!(c1 == c2));

        assert!(c1.temporal_relation(&c2) == TemporalRelation::Caused);
        assert!(c2.temporal_relation(&c1) == TemporalRelation::EffectOf);
    }

    #[test]
    fn test_diverged() {
        let base = StrVectorClock::new();
        let c1 = base.incremented("A");
        let c2 = base.incremented("B");

        assert!(!(c1 == c2));

        assert!(c1.temporal_relation(&c2) == TemporalRelation::Concurrent);
        assert!(c2.temporal_relation(&c1) == TemporalRelation::Concurrent);
    }

    #[test]
    fn test_merged() {
        let base = StrVectorClock::new();
        let c1 = base.incremented("A");
        let c2 = base.incremented("B");

        let m = c1.merge_with(&c2);

        assert!(m.temporal_relation(&c1) == TemporalRelation::EffectOf);
        assert!(c1.temporal_relation(&m) == TemporalRelation::Caused);

        assert!(m.temporal_relation(&c2) == TemporalRelation::EffectOf);
        assert!(c2.temporal_relation(&m) == TemporalRelation::Caused);
    }
}
<|endoftext|>


<commit_before>
//! Experimental: custom audio stuff

// Note to self
// A sample is a single i16 (Or whatever `SampleData` is)
// A frame is one i16 per channel

use std::f32::consts::PI;

use window::Window;

const CHANNELS: usize = 2;
type SampleData = i16;

pub struct AudioSystem {
    backend: AudioBackend,
    frame_counter: u64,
}

impl AudioSystem {
    pub fn initialize(window: &Window) -> Option<AudioSystem> {
        let backend_settings = BackendSettings {
            sample_rate: 44100,
            duration_in_secs: 2,
        };

        let backend = match AudioBackend::initialize(window, backend_settings) {
            Some(b) => b,
            None => {
                return None;
            },
        };

        Some(AudioSystem {
            backend,
            frame_counter: 0,
        })
    }

    pub fn tick(&mut self) {
        self.backend.write_wave(&mut self.frame_counter);
    }
}

#[derive(Copy, Clone)]
struct BackendSettings {
    sample_rate: u32,
    duration_in_secs: u32,
}

#[cfg(target_os = "windows")]
use self::windows::*;

#[cfg(target_os = "windows")]
mod windows {
    use super::*;

    extern crate winapi;
    extern crate kernel32;

    use std::mem;
    use std::slice;
    use std::ptr;

    // We access all ffi stuff through `ffi::whatever` instead of through each apis specific
    // bindings. This allows us to easily add custom stuff that is missing in bindings.
    mod ffi {
        #![allow(non_camel_case_types)]

        pub(super) use super::winapi::*;
        pub(super) use super::kernel32::*;

        // Direct-sound functions
        pub(super) type DirectSoundCreate = extern "system" fn(LPGUID, *mut LPDIRECTSOUND, LPUNKNOWN) -> HRESULT;
    }

    pub(super) struct AudioBackend {
        sample_rate: u32, // Samples per second
        buffer_size: usize, // Total size of secondary buffer, in bytes
        playing: bool,
        secondary_buffer: &'static mut ffi::IDirectSoundBuffer,
    }

    impl AudioBackend {
        pub fn initialize(
            window: &Window,
            backend_settings: BackendSettings
        ) -> Option<AudioBackend>
        {
            // Load library
            let lib_name = encode_wide("dsound.dll");
            let dsound_lib = unsafe { ffi::LoadLibraryW(lib_name.as_ptr()) };

            if dsound_lib.is_null() {
                println!("Could not load \"dsound.dll\"");
                // Don't panic, just run without sound
                return None;
            }

            // Create DirectSound object
            let direct_sound_create = {
                let name = b"DirectSoundCreate\0";
                let address = unsafe { ffi::GetProcAddress(dsound_lib, name.as_ptr() as *const _) };

                if address.is_null() {
                    println!("Could not load DirectSoundCreate from dsound.dll");
                    return None;
                } else {
                    unsafe { mem::transmute::<_, ffi::DirectSoundCreate>(address) }
                }
            };

            let mut dsound: ffi::LPDIRECTSOUND = ptr::null_mut();
            let result = direct_sound_create(ptr::null_mut(), &mut dsound, ptr::null_mut());
            if result != ffi::DS_OK {
                println!("Failed to create a direct sound object: {}", result);
                return None;
            }
            assert!(!dsound.is_null());
            let dsound = unsafe { &mut *dsound };

            let result = unsafe { dsound.SetCooperativeLevel(window.window_handle(), ffi::DSSCL_PRIORITY) };
            if result != ffi::DS_OK {
                println!("Failed to call DirectSound->SetCooperativeLevel. Error code: {}", result);
                return None;
            }

            // Create primary buffer (I think this is only used as a configuration object. This is
            // one of windows' wierd quircks, which don't really make sense anyways)
            let mut buffer_description: ffi::DSBUFFERDESC = unsafe { mem::zeroed() };
            buffer_description.dwSize = mem::size_of::<ffi::DSBUFFERDESC>() as u32;
            buffer_description.dwFlags = ffi::DSBCAPS_PRIMARYBUFFER;

            let mut primary_buffer: ffi::LPDIRECTSOUNDBUFFER = ptr::null_mut();
            let result = unsafe { dsound.CreateSoundBuffer(&buffer_description, &mut primary_buffer, ptr::null_mut()) };
            if result != ffi::DS_OK {
                println!("Failed to call DirectSound->CreateSoundBuffer. Error code: {}", result);
                return None;
            }
            assert!(!primary_buffer.is_null());
            let primary_buffer = unsafe { &mut *primary_buffer };

            let sample_rate      = backend_settings.sample_rate;
            let bytes_per_sample = mem::size_of::<SampleData>();
            let bytes_per_frame  = bytes_per_sample * CHANNELS;
            let bytes_per_second = bytes_per_frame * sample_rate as usize;
            let buffer_size      = bytes_per_second * backend_settings.duration_in_secs as usize;

            let mut wave_format = ffi::WAVEFORMATEX {
                wFormatTag:      ffi::WAVE_FORMAT_PCM,
                nChannels:       CHANNELS as u16,
                nSamplesPerSec:  backend_settings.sample_rate,
                nAvgBytesPerSec: bytes_per_second as u32,
                nBlockAlign:     bytes_per_frame as u16,
                wBitsPerSample:  8 * bytes_per_sample as u16,
                cbSize: 0,
                .. unsafe { mem::zeroed() }
            };
            let result = unsafe { primary_buffer.SetFormat(&wave_format) };
            if result != ffi::DS_OK {
                println!("Failed call to SoundBuffer->SetFormat. Error code: {}", result);
                return None;
            }

            // Create secondary buffer (which is the buffer we actually want)
            let mut buffer_description: ffi::DSBUFFERDESC = unsafe { mem::zeroed() };
            buffer_description.dwSize = mem::size_of::<ffi::DSBUFFERDESC>() as u32;
            buffer_description.dwBufferBytes = buffer_size as u32;
            buffer_description.lpwfxFormat = &mut wave_format;

            let mut secondary_buffer: ffi::LPDIRECTSOUNDBUFFER = ptr::null_mut();
            let result = unsafe { dsound.CreateSoundBuffer(&buffer_description, &mut secondary_buffer, ptr::null_mut()) };
            if result != ffi::DS_OK {
                println!("Failed call to SoundBuffer->SetFormat. Error code: {}", result);
                return None;
            }
            assert!(!secondary_buffer.is_null());
            let secondary_buffer = unsafe { &mut *secondary_buffer };

            Some(AudioBackend {
                sample_rate, buffer_size,
                playing: false,
                secondary_buffer,
            })
        }

        pub fn write_wave(&mut self, frame_counter: &mut u64) {
            let volume = 4000;
            let frequency = 256;
            let period = (self.sample_rate / frequency) as u64;

            // Ensure we are playing
            if !self.playing {
                self.playing = true;
                unsafe { self.secondary_buffer.Play(0, 0, ffi::DSBPLAY_LOOPING) };
            }

            // Figure out where and how much to write
            let mut write_cursor = 0;
            let mut play_cursor  = 0;
            let result = unsafe { self.secondary_buffer.GetCurrentPosition(
                &mut play_cursor,
                &mut write_cursor,
            )};
            if result != ffi::DS_OK {
                println!("Failed to get current buffer position. Error code: {}", result);
                return;
            }

            let play_cursor = play_cursor as usize;

            let bytes_per_sample = mem::size_of::<SampleData>();
            let bytes_per_frame = bytes_per_sample * CHANNELS as usize;

            let our_cursor = (*frame_counter as usize * bytes_per_frame) % self.buffer_size;
            let len = {
                if play_cursor == 0 && write_cursor == 0 {
                    self.buffer_size
                } else if our_cursor > play_cursor {
                    (self.buffer_size - our_cursor) + play_cursor
                } else {
                    play_cursor - our_cursor
                }
            };

            if len == 0 {
                return;
            }

            assert!(our_cursor < self.buffer_size);
            assert!(len <= self.buffer_size);

            // Lock secondary buffer, get write region
            let mut len1 = 0;
            let mut ptr1 = ptr::null_mut();
            let mut len2 = 0; // TODO docs say len2 or ptr2 must != 0 for them to be used
            let mut ptr2 = ptr::null_mut();

            let result = unsafe { self.secondary_buffer.Lock(
                our_cursor as u32, len as u32,
                &mut ptr1, &mut len1,
                &mut ptr2, &mut len2,
                0,
            )};

            if result != ffi::DS_OK {
                let result = unsafe { mem::transmute::<i32, u32>(result) };
                let msg = match result {
                    0x88780096 => "Buffer lost",
                    0x88780032 => "Invalid call",
                    0x80070057 => "Invalid parameter",
                    0x88780046 => "Priority level needed",
                    _ => "Unkown error",
                };

                println!("Failed to lock secondary buffer. Error code: 0x{:x} ({})", result, msg);
                return;
            }

            // Convert to slices so we can do safe code again
            let (slice1, slice2) = unsafe {(
                slice::from_raw_parts_mut(ptr1 as *mut SampleData, len1 as usize / bytes_per_sample),
                slice::from_raw_parts_mut(ptr2 as *mut SampleData, len2 as usize / bytes_per_sample),
            )};

            // Generate wave
            for frame in slice1.chunks_mut(CHANNELS) {
                assert!(frame.len() == CHANNELS);

                let t = (*frame_counter%period) as f32 / period as f32;
                *frame_counter += 1;

                let v = (t*2.0*PI).sin();
                let v = (v * volume as f32) as i16;

                for i in 0..CHANNELS {
                    frame[i] = v;
                }
            }

            for frame in slice2.chunks_mut(CHANNELS) {
                assert!(frame.len() == CHANNELS);

                let t = (*frame_counter%period) as f32 / period as f32;
                *frame_counter += 1;

                let v = (t*2.0*PI).sin();
                let v = (v * volume as f32) as i16;

                for i in 0..CHANNELS {
                    frame[i] = v;
                }
            }

            // Unlock buffer
            let result = unsafe { self.secondary_buffer.Unlock(
                ptr1, len1,
                ptr2, len2,
            )};
            if result != ffi::DS_OK {
                println!("Failed to unlock secondary buffer. Error code: {}", result);
            }
        }
    }

    fn encode_wide(s: &str) -> Vec<u16> {
        let mut data = Vec::with_capacity(s.len() + 1);
        for wchar in s.encode_utf16() {
            data.push(wchar);
        }
        data.push(0);
        data
    }
}
<commit_msg>Play sound even when window looses focus<commit_after>
//! Experimental: custom audio stuff

// Note to self
// A sample is a single i16 (Or whatever `SampleData` is)
// A frame is one i16 per channel

use std::f32::consts::PI;

use window::Window;

const CHANNELS: usize = 2;
type SampleData = i16;

pub struct AudioSystem {
    backend: AudioBackend,
    frame_counter: u64,
}

impl AudioSystem {
    pub fn initialize(window: &Window) -> Option<AudioSystem> {
        let backend_settings = BackendSettings {
            sample_rate: 44100,
            duration_in_secs: 2,
        };

        let backend = match AudioBackend::initialize(window, backend_settings) {
            Some(b) => b,
            None => {
                return None;
            },
        };

        Some(AudioSystem {
            backend,
            frame_counter: 0,
        })
    }

    pub fn tick(&mut self) {
        self.backend.write_wave(&mut self.frame_counter);
    }
}

#[derive(Copy, Clone)]
struct BackendSettings {
    sample_rate: u32,
    duration_in_secs: u32,
}

#[cfg(target_os = "windows")]
use self::windows::*;

#[cfg(target_os = "windows")]
mod windows {
    use super::*;

    extern crate winapi;
    extern crate kernel32;

    use std::mem;
    use std::slice;
    use std::ptr;

    // We access all ffi stuff through `ffi::whatever` instead of through each apis specific
    // bindings. This allows us to easily add custom stuff that is missing in bindings.
    mod ffi {
        #![allow(non_camel_case_types)]

        pub(super) use super::winapi::*;
        pub(super) use super::kernel32::*;

        // Direct-sound functions
        pub(super) type DirectSoundCreate = extern "system" fn(LPGUID, *mut LPDIRECTSOUND, LPUNKNOWN) -> HRESULT;
    }

    pub(super) struct AudioBackend {
        sample_rate: u32, // Samples per second
        buffer_size: usize, // Total size of secondary buffer, in bytes
        playing: bool,
        secondary_buffer: &'static mut ffi::IDirectSoundBuffer,
    }

    impl AudioBackend {
        pub fn initialize(
            window: &Window,
            backend_settings: BackendSettings
        ) -> Option<AudioBackend>
        {
            // Load library
            let lib_name = encode_wide("dsound.dll");
            let dsound_lib = unsafe { ffi::LoadLibraryW(lib_name.as_ptr()) };

            if dsound_lib.is_null() {
                println!("Could not load \"dsound.dll\"");
                // Don't panic, just run without sound
                return None;
            }

            // Create DirectSound object
            let direct_sound_create = {
                let name = b"DirectSoundCreate\0";
                let address = unsafe { ffi::GetProcAddress(dsound_lib, name.as_ptr() as *const _) };

                if address.is_null() {
                    println!("Could not load DirectSoundCreate from dsound.dll");
                    return None;
                } else {
                    unsafe { mem::transmute::<_, ffi::DirectSoundCreate>(address) }
                }
            };

            let mut dsound: ffi::LPDIRECTSOUND = ptr::null_mut();
            let result = direct_sound_create(ptr::null_mut(), &mut dsound, ptr::null_mut());
            if result != ffi::DS_OK {
                println!("Failed to create a direct sound object: {}", result);
                return None;
            }
            assert!(!dsound.is_null());
            let dsound = unsafe { &mut *dsound };

            let result = unsafe { dsound.SetCooperativeLevel(window.window_handle(), ffi::DSSCL_PRIORITY) };
            if result != ffi::DS_OK {
                println!("Failed to call DirectSound->SetCooperativeLevel. Error code: {}", result);
                return None;
            }

            // Create primary buffer (I think this is only used as a configuration object. This is
            // one of windows' wierd quircks, which don't really make sense anyways)
            let mut buffer_description: ffi::DSBUFFERDESC = unsafe { mem::zeroed() };
            buffer_description.dwSize = mem::size_of::<ffi::DSBUFFERDESC>() as u32;
            buffer_description.dwFlags = ffi::DSBCAPS_PRIMARYBUFFER;

            let mut primary_buffer: ffi::LPDIRECTSOUNDBUFFER = ptr::null_mut();
            let result = unsafe { dsound.CreateSoundBuffer(&buffer_description, &mut primary_buffer, ptr::null_mut()) };
            if result != ffi::DS_OK {
                println!("Failed to call DirectSound->CreateSoundBuffer. Error code: {}", result);
                return None;
            }
            assert!(!primary_buffer.is_null());
            let primary_buffer = unsafe { &mut *primary_buffer };

            let sample_rate      = backend_settings.sample_rate;
            let bytes_per_sample = mem::size_of::<SampleData>();
            let bytes_per_frame  = bytes_per_sample * CHANNELS;
            let bytes_per_second = bytes_per_frame * sample_rate as usize;
            let buffer_size      = bytes_per_second * backend_settings.duration_in_secs as usize;

            let mut wave_format = ffi::WAVEFORMATEX {
                wFormatTag:      ffi::WAVE_FORMAT_PCM,
                nChannels:       CHANNELS as u16,
                nSamplesPerSec:  backend_settings.sample_rate,
                nAvgBytesPerSec: bytes_per_second as u32,
                nBlockAlign:     bytes_per_frame as u16,
                wBitsPerSample:  8 * bytes_per_sample as u16,
                cbSize: 0,
                .. unsafe { mem::zeroed() }
            };
            let result = unsafe { primary_buffer.SetFormat(&wave_format) };
            if result != ffi::DS_OK {
                println!("Failed call to SoundBuffer->SetFormat. Error code: {}", result);
                return None;
            }

            // Create secondary buffer (which is the buffer we actually want)
            let mut buffer_description: ffi::DSBUFFERDESC = unsafe { mem::zeroed() };
            buffer_description.dwSize = mem::size_of::<ffi::DSBUFFERDESC>() as u32;
            buffer_description.dwBufferBytes = buffer_size as u32;
            buffer_description.lpwfxFormat = &mut wave_format;
            buffer_description.dwFlags = ffi::DSBCAPS_GLOBALFOCUS;

            let mut secondary_buffer: ffi::LPDIRECTSOUNDBUFFER = ptr::null_mut();
            let result = unsafe { dsound.CreateSoundBuffer(&buffer_description, &mut secondary_buffer, ptr::null_mut()) };
            if result != ffi::DS_OK {
                println!("Failed call to SoundBuffer->SetFormat. Error code: {}", result);
                return None;
            }
            assert!(!secondary_buffer.is_null());
            let secondary_buffer = unsafe { &mut *secondary_buffer };

            Some(AudioBackend {
                sample_rate, buffer_size,
                playing: false,
                secondary_buffer,
            })
        }

        pub fn write_wave(&mut self, frame_counter: &mut u64) {
            let volume = 4000;
            let frequency = 256;
            let period = (self.sample_rate / frequency) as u64;

            // Ensure we are playing
            if !self.playing {
                self.playing = true;
                unsafe { self.secondary_buffer.Play(0, 0, ffi::DSBPLAY_LOOPING) };
            }

            // Figure out where and how much to write
            let mut write_cursor = 0;
            let mut play_cursor  = 0;
            let result = unsafe { self.secondary_buffer.GetCurrentPosition(
                &mut play_cursor,
                &mut write_cursor,
            )};
            if result != ffi::DS_OK {
                println!("Failed to get current buffer position. Error code: {}", result);
                return;
            }

            let play_cursor = play_cursor as usize;

            let bytes_per_sample = mem::size_of::<SampleData>();
            let bytes_per_frame = bytes_per_sample * CHANNELS as usize;

            let our_cursor = (*frame_counter as usize * bytes_per_frame) % self.buffer_size;
            let len = {
                if play_cursor == 0 && write_cursor == 0 {
                    self.buffer_size
                } else if our_cursor > play_cursor {
                    (self.buffer_size - our_cursor) + play_cursor
                } else {
                    play_cursor - our_cursor
                }
            };

            if len == 0 {
                return;
            }

            assert!(our_cursor < self.buffer_size);
            assert!(len <= self.buffer_size);

            // Lock secondary buffer, get write region
            let mut len1 = 0;
            let mut ptr1 = ptr::null_mut();
            let mut len2 = 0; // TODO docs say len2 or ptr2 must != 0 for them to be used
            let mut ptr2 = ptr::null_mut();

            let result = unsafe { self.secondary_buffer.Lock(
                our_cursor as u32, len as u32,
                &mut ptr1, &mut len1,
                &mut ptr2, &mut len2,
                0,
            )};

            if result != ffi::DS_OK {
                let result = unsafe { mem::transmute::<i32, u32>(result) };
                let msg = match result {
                    0x88780096 => "Buffer lost",
                    0x88780032 => "Invalid call",
                    0x80070057 => "Invalid parameter",
                    0x88780046 => "Priority level needed",
                    _ => "Unkown error",
                };

                println!("Failed to lock secondary buffer. Error code: 0x{:x} ({})", result, msg);
                return;
            }

            // Convert to slices so we can do safe code again
            let (slice1, slice2) = unsafe {(
                slice::from_raw_parts_mut(ptr1 as *mut SampleData, len1 as usize / bytes_per_sample),
                slice::from_raw_parts_mut(ptr2 as *mut SampleData, len2 as usize / bytes_per_sample),
            )};

            // Generate wave
            for frame in slice1.chunks_mut(CHANNELS) {
                assert!(frame.len() == CHANNELS);

                let t = (*frame_counter%period) as f32 / period as f32;
                *frame_counter += 1;

                let v = (t*2.0*PI).sin();
                let v = (v * volume as f32) as SampleData;

                for i in 0..CHANNELS {
                    frame[i] = v;
                }
            }

            for frame in slice2.chunks_mut(CHANNELS) {
                assert!(frame.len() == CHANNELS);

                let t = (*frame_counter%period) as f32 / period as f32;
                *frame_counter += 1;

                let v = (t*2.0*PI).sin();
                let v = (v * volume as f32) as SampleData;

                for i in 0..CHANNELS {
                    frame[i] = v;
                }
            }

            // Unlock buffer
            let result = unsafe { self.secondary_buffer.Unlock(
                ptr1, len1,
                ptr2, len2,
            )};
            if result != ffi::DS_OK {
                println!("Failed to unlock secondary buffer. Error code: {}", result);
            }
        }
    }

    fn encode_wide(s: &str) -> Vec<u16> {
        let mut data = Vec::with_capacity(s.len() + 1);
        for wchar in s.encode_utf16() {
            data.push(wchar);
        }
        data.push(0);
        data
    }
}
<|endoftext|>


<commit_before>
pub struct Flat2dVec<T: Default + Clone> {
    data: Vec<T>,
    width: usize,
    height: usize
}

impl<T: Default + Clone> Flat2dVec<T> {
    pub fn new(width: usize, height: usize) -> Flat2dVec<T> {
        Flat2dVec {
            data: vec![T::default(); width * height],
            width: width,
            height: height
        }
    }

    fn
}

<commit_msg>implemented normal challenge<commit_after>
use std::fmt;

pub struct Flat2dArray<T: Default + Copy> {
  data: Vec<T>,
  width: usize,
  height: usize
}

impl<T: Default + Copy> Flat2dArray<T> {
  pub fn new(width: usize, height: usize) -> Flat2dArray<T> {
    Flat2dArray {
      data: vec![T::default(); width * height],
      width: width,
      height: height
    }
  }

  pub fn is_out_of_bounds(&self, x: usize, y: usize) -> bool {
    x >= self.width || y >= self.height
  }

  fn assert_not_out_of_bounds(&self, x: usize, y: usize) {
    if self.is_out_of_bounds(x, y) {
      panic!(format!("Out of bounds: {}, {}", x, y));
    }
  }

  fn get_index(&self, x: usize, y: usize) -> usize {
    self.assert_not_out_of_bounds(x, y);
    x + y * self.width
  }

  pub fn get(&self, x: usize, y: usize) -> T {
    let index = self.get_index(x, y);

    self.data[index]
  }

  pub fn set(&mut self, x: usize, y: usize, val: T) {
    let index = self.get_index(x, y);

    self.data[index] = val;
  }

  pub fn get_width(&self) -> usize {
    self.width
  }

  pub fn get_height(&self) -> usize {
    self.height
  }
}

impl<T> fmt::Display for Flat2dArray<T>
  where T: Default + Copy + fmt::Display {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
      writeln!(f, "width: {} height: {}", self.width, self.height);

      for y in 0 .. self.height {
        for x in 0 .. self.width {
          write!(f, "{: >3} ", self.get(x, y));
        }
        writeln!(f, "");
      }
      Ok(())
    }
}

pub fn construct_regular_matrix(width: usize, height: usize) -> Flat2dArray<usize> {
  let mut array: Flat2dArray<usize> = Flat2dArray::new(width, height);

  for y in 0..height {
    for x in 0..width {
      array.set(x, y, x + width * y);
    }
  }

  array
}

fn create_part_oblique<T>(array: &Flat2dArray<T>, start_x: usize, start_y: usize) -> Vec<T>
where T: Default + Copy {

  let mut x = start_x;
  let mut y = start_y;

  let mut part_result: Vec<T> = Vec::new();

  while !array.is_out_of_bounds(x, y) {
    part_result.push(array.get(x, y));

    if x == 0 {
      break;
    }

    x = x - 1;
    y = y + 1;
  }

  part_result
}

pub fn oblique<T>(array: &Flat2dArray<T>) -> Vec<Vec<T>>
where T: Default + Copy {
  let mut result: Vec<Vec<T>> = Vec::new();

  for start_x in 0..array.get_width() {
    let part_result = create_part_oblique(array, start_x, 0);
    result.push( part_result );
  }

  for start_y in 1..array.get_height() {
    let part_result = create_part_oblique(array, array.get_width() - 1, start_y);
    result.push( part_result );
  }

  result
}

#[cfg(test)]
mod tests {
  use std::fmt;
  use dp256::*;

  fn print_obliqued_vec<T: fmt::Display>(vv: &Vec<Vec<T>>) {
    println!("");
    for v in vv {
      for value in v {
        print!("{: >3}", value);
      }
      println!("");
    }
  }

  #[test]
  fn test_create() {
    let a2d: Flat2dArray<i32> = Flat2dArray::new( 5, 10 );

    assert_eq!( 5, a2d.get_width() );
    assert_eq!( 10, a2d.get_height() );
  }

  #[test]
  #[should_panic]
  fn test_out_of_bounds() {
    let a2d: Flat2dArray<i32> = Flat2dArray::new(5, 10);

    a2d.get(6, 5);
  }

  #[test]
  fn test_regular_matrix() {
    let a2d = construct_regular_matrix(10, 5);

    for x in 0 .. a2d.get_width() {
      for y in 0 .. a2d.get_height() {
        assert_eq!( x + y * a2d.get_width(), a2d.get(x, y) );
      }
    }

    println!("{}", a2d);
  }

  #[test]
  fn test_oblique() {
    let array = construct_regular_matrix(6, 6);

    let vec = oblique(&array);

    print_obliqued_vec(&vec);
  }

}
<|endoftext|>


<commit_before>use std::c_str::CString;
use std::error;
use std::fmt;
use std::str;
use libc;
use libc::c_int;

use {raw, ErrorCode};

/// A structure to represent errors coming out of libgit2.
pub struct Error {
    raw: raw::git_error,
}

impl Error {
    /// Returns the last error, or `None` if one is not available.
    pub fn last_error() -> Option<Error> {
        ::init();
        let mut raw = raw::git_error {
            message: 0 as *mut libc::c_char,
            klass: 0,
        };
        if unsafe { raw::giterr_detach(&mut raw) } == 0 {
            Some(Error { raw: raw })
        } else {
            None
        }
    }

    /// Creates a new error from the given string as the error.
    pub fn from_str(s: &str) -> Error {
        ::init();
        Error {
            raw: raw::git_error {
                message: unsafe { s.to_c_str().into_inner() as *mut _ },
                klass: raw::GIT_ERROR as libc::c_int,
            }
        }
    }

    /// Return the error code associated with this error.
    pub fn code(&self) -> ErrorCode {
        match self.raw_code() {
            raw::GIT_OK => super::ErrorCode::GenericError,
            raw::GIT_ERROR => super::ErrorCode::GenericError,
            raw::GIT_ENOTFOUND => super::ErrorCode::NotFound,
            raw::GIT_EEXISTS => super::ErrorCode::Exists,
            raw::GIT_EAMBIGUOUS => super::ErrorCode::Ambiguous,
            raw::GIT_EBUFS => super::ErrorCode::BufSize,
            raw::GIT_EUSER => super::ErrorCode::User,
            raw::GIT_EBAREREPO => super::ErrorCode::BareRepo,
            raw::GIT_EUNBORNBRANCH => super::ErrorCode::UnbornBranch,
            raw::GIT_EUNMERGED => super::ErrorCode::Unmerged,
            raw::GIT_ENONFASTFORWARD => super::ErrorCode::NotFastForward,
            raw::GIT_EINVALIDSPEC => super::ErrorCode::InvalidSpec,
            raw::GIT_EMERGECONFLICT => super::ErrorCode::MergeConflict,
            raw::GIT_ELOCKED => super::ErrorCode::Locked,
            raw::GIT_EMODIFIED => super::ErrorCode::Modified,
            raw::GIT_PASSTHROUGH => super::ErrorCode::GenericError,
            raw::GIT_ITEROVER => super::ErrorCode::GenericError,
        }
    }

    /// Return the raw error code associated with this error.
    pub fn raw_code(&self) -> raw::git_error_code {
        macro_rules! check( ($($e:ident),*) => (
            $(if self.raw.klass == raw::$e as c_int { raw::$e }) else *
            else {
                raw::GIT_ERROR
            }
        ) );
        check!(
            GIT_OK,
            GIT_ERROR,
            GIT_ENOTFOUND,
            GIT_EEXISTS,
            GIT_EAMBIGUOUS,
            GIT_EBUFS,
            GIT_EUSER,
            GIT_EBAREREPO,
            GIT_EUNBORNBRANCH,
            GIT_EUNMERGED,
            GIT_ENONFASTFORWARD,
            GIT_EINVALIDSPEC,
            GIT_EMERGECONFLICT,
            GIT_ELOCKED,
            GIT_EMODIFIED,
            GIT_PASSTHROUGH,
            GIT_ITEROVER
        )
    }

    /// Return the message associated with this error
    pub fn message(&self) -> String {
        let cstr = unsafe { CString::new(self.raw.message as *const _, false) };
        String::from_utf8_lossy(cstr.as_bytes_no_nul()).to_string()
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        unsafe { str::from_c_str(self.raw.message as *const _) }
    }

    fn detail(&self) -> Option<String> { Some(self.message()) }
}

impl fmt::Show for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "[{}] ", self.raw.klass));
        let cstr = unsafe { CString::new(self.raw.message as *const _, false) };
        f.write(cstr.as_bytes_no_nul())
    }
}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw.message as *mut libc::c_void) }
    }
}
<commit_msg>Implement Send for Error<commit_after>use std::c_str::CString;
use std::error;
use std::fmt;
use std::str;
use libc;
use libc::c_int;

use {raw, ErrorCode};

/// A structure to represent errors coming out of libgit2.
pub struct Error {
    raw: raw::git_error,
}

impl Error {
    /// Returns the last error, or `None` if one is not available.
    pub fn last_error() -> Option<Error> {
        ::init();
        let mut raw = raw::git_error {
            message: 0 as *mut libc::c_char,
            klass: 0,
        };
        if unsafe { raw::giterr_detach(&mut raw) } == 0 {
            Some(Error { raw: raw })
        } else {
            None
        }
    }

    /// Creates a new error from the given string as the error.
    pub fn from_str(s: &str) -> Error {
        ::init();
        Error {
            raw: raw::git_error {
                message: unsafe { s.to_c_str().into_inner() as *mut _ },
                klass: raw::GIT_ERROR as libc::c_int,
            }
        }
    }

    /// Return the error code associated with this error.
    pub fn code(&self) -> ErrorCode {
        match self.raw_code() {
            raw::GIT_OK => super::ErrorCode::GenericError,
            raw::GIT_ERROR => super::ErrorCode::GenericError,
            raw::GIT_ENOTFOUND => super::ErrorCode::NotFound,
            raw::GIT_EEXISTS => super::ErrorCode::Exists,
            raw::GIT_EAMBIGUOUS => super::ErrorCode::Ambiguous,
            raw::GIT_EBUFS => super::ErrorCode::BufSize,
            raw::GIT_EUSER => super::ErrorCode::User,
            raw::GIT_EBAREREPO => super::ErrorCode::BareRepo,
            raw::GIT_EUNBORNBRANCH => super::ErrorCode::UnbornBranch,
            raw::GIT_EUNMERGED => super::ErrorCode::Unmerged,
            raw::GIT_ENONFASTFORWARD => super::ErrorCode::NotFastForward,
            raw::GIT_EINVALIDSPEC => super::ErrorCode::InvalidSpec,
            raw::GIT_EMERGECONFLICT => super::ErrorCode::MergeConflict,
            raw::GIT_ELOCKED => super::ErrorCode::Locked,
            raw::GIT_EMODIFIED => super::ErrorCode::Modified,
            raw::GIT_PASSTHROUGH => super::ErrorCode::GenericError,
            raw::GIT_ITEROVER => super::ErrorCode::GenericError,
        }
    }

    /// Return the raw error code associated with this error.
    pub fn raw_code(&self) -> raw::git_error_code {
        macro_rules! check( ($($e:ident),*) => (
            $(if self.raw.klass == raw::$e as c_int { raw::$e }) else *
            else {
                raw::GIT_ERROR
            }
        ) );
        check!(
            GIT_OK,
            GIT_ERROR,
            GIT_ENOTFOUND,
            GIT_EEXISTS,
            GIT_EAMBIGUOUS,
            GIT_EBUFS,
            GIT_EUSER,
            GIT_EBAREREPO,
            GIT_EUNBORNBRANCH,
            GIT_EUNMERGED,
            GIT_ENONFASTFORWARD,
            GIT_EINVALIDSPEC,
            GIT_EMERGECONFLICT,
            GIT_ELOCKED,
            GIT_EMODIFIED,
            GIT_PASSTHROUGH,
            GIT_ITEROVER
        )
    }

    /// Return the message associated with this error
    pub fn message(&self) -> String {
        let cstr = unsafe { CString::new(self.raw.message as *const _, false) };
        String::from_utf8_lossy(cstr.as_bytes_no_nul()).to_string()
    }
}

impl error::Error for Error {
    fn description(&self) -> &str {
        unsafe { str::from_c_str(self.raw.message as *const _) }
    }

    fn detail(&self) -> Option<String> { Some(self.message()) }
}

impl fmt::Show for Error {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        try!(write!(f, "[{}] ", self.raw.klass));
        let cstr = unsafe { CString::new(self.raw.message as *const _, false) };
        f.write(cstr.as_bytes_no_nul())
    }
}

impl Drop for Error {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw.message as *mut libc::c_void) }
    }
}

unsafe impl Send for Error {}
<|endoftext|>


<commit_before>#![feature(dynamic_lib,path_relative_from,hashmap_hasher)]

extern crate libc;
extern crate errno;

use std::collections::hash_state::DefaultState;
use std::hash::{Hasher, SipHasher};

#[macro_use]
extern crate lazy_static;
lazy_static! {
    static ref DELAY_FDS: RwLock<HashSet<c_int, DefaultState<SipHasher>>>
                                                = RwLock::new(Default::default());
    static ref ERR_FDS: RwLock<HashSet<c_int, DefaultState<SipHasher>>>
                                                = RwLock::new(Default::default());
}

macro_rules! get_libc_func(
    ($destination_t:ty, $funcname:expr) =>
        (
            {
                use std::dynamic_lib::DynamicLibrary;
                use std::mem::transmute;
                use std::path::Path;

                let system_c_library: &str = "libc.so.6";

                unsafe {
                    let libc_dl = match DynamicLibrary::open(Some(Path::new(system_c_library))) {
                        Ok(libc) => libc,
                        Err(error) => panic!("Couldn't open libc: '{}'", error),
                    };

                    match libc_dl.symbol::<c_void>($funcname) {
                        Ok(open_func) => transmute::<* mut c_void, $destination_t>(open_func),
                        Err(error) => panic!("Couldn't '{}'", error),
                }
            }
        })
);

use errno::{Errno, set_errno};
use std::sync::RwLock;

use std::collections::hash_set::HashSet;

use libc::{c_char, c_int, c_void};

type OpenFunc = fn(* const c_char, c_int, libc::mode_t) -> c_int;
use libc::types::os::arch::posix88::ssize_t;
type ReadFunc = fn(fd: c_int, buf: * mut c_void, nbytes: c_int) -> ssize_t;
type WriteFunc = ReadFunc;
type CloseFunc = fn(fd: c_int) -> c_int;

use std::env;

fn get_delay_amount_ms() -> u32 {
    let default_delay_amount_ms = 200;

    match env::var("LIBFAULTINJ_DELAY_MS") {
        Ok(p) => match p.parse::<u32>() {
            Ok(i) => i,
            Err(_) => default_delay_amount_ms,
        },
        Err(_) => default_delay_amount_ms,
    }
}

use std::path::Path;

macro_rules! matchesPath(
        ($filename: expr, $env_name: expr) =>
    {
        match env::var($env_name) {
            Ok(p) => {
                let filename_path = Path::new(&$filename);
                let delay_path_match = (filename_path.relative_from(Path::new(&p))) != None;
                let filename_match = filename_path == Path::new(&p);

                delay_path_match || filename_match
            }
            Err(_) => false
        }
    });

fn initialize_sets() {
    let fd: c_int = 0;
    DELAY_FDS.read().unwrap().contains(&fd);
    ERR_FDS.read().unwrap().contains(&fd);
}

#[no_mangle]
pub extern "C" fn open(filename_: *const c_char, flags: c_int, mode: libc::mode_t) -> c_int {
    let filename: String = unsafe {
        std::ffi::CStr::from_ptr(filename_).to_string_lossy().into_owned()
    };
    let open_func = get_libc_func!(OpenFunc, "open");
    let fd: c_int = open_func(filename_, flags, mode);

    initialize_sets();

    if matchesPath!(filename, "LIBFAULTINJ_DELAY_PATH") {
        DELAY_FDS.write().unwrap().insert(fd);
    }

    fd
}

#[no_mangle]
pub extern "C" fn read(fd: c_int, buf: *mut c_void, nbytes: c_int) -> ssize_t {
    use std::thread;
    let read_func = get_libc_func!(ReadFunc, "read");

    let delay_match = DELAY_FDS.read().unwrap().contains(&fd);
    let err_match = ERR_FDS.read().unwrap().contains(&fd);

    let ret: ssize_t = read_func(fd, buf, nbytes);

    if delay_match {
        thread::sleep_ms(get_delay_amount_ms());
    }
    if err_match {
        use libc::consts::os::posix88::EIO;
        set_errno(Errno(EIO));

        return -1
    }

    ret
}

#[no_mangle]
pub extern "C" fn write(fd: c_int, buf: *mut c_void, nbytes: c_int) -> ssize_t {
    let write_func = get_libc_func!(WriteFunc, "write");

    let matches = DELAY_FDS.read().unwrap().contains(&fd);

    let ret: ssize_t = write_func(fd, buf, nbytes);

    if matches {
        use libc::consts::os::posix88::EIO;
        set_errno(Errno(EIO));

        return -1
    }

    ret
}

#[no_mangle]
pub extern "C" fn close(fd: c_int) -> c_int {
    let close_func = get_libc_func!(CloseFunc, "close");

    let ret: c_int = close_func(fd);

    let mut err_fds = ERR_FDS.write().unwrap();
    if err_fds.contains(&fd) {
        err_fds.remove(&fd);
    }

    let mut delay_fds = DELAY_FDS.write().unwrap();
    if delay_fds.contains(&fd) {
        delay_fds.remove(&fd);
    }

    ret
}
<commit_msg>Add lseek(), open64(), refactor open()<commit_after>#![feature(dynamic_lib,path_relative_from,hashmap_hasher)]

extern crate libc;
extern crate errno;

use std::collections::hash_state::DefaultState;
use std::hash::{Hasher, SipHasher};

#[macro_use]
extern crate lazy_static;
lazy_static! {
    static ref DELAY_FDS: RwLock<HashSet<c_int, DefaultState<SipHasher>>>
                                                = RwLock::new(Default::default());
    static ref ERR_FDS: RwLock<HashSet<c_int, DefaultState<SipHasher>>>
                                                = RwLock::new(Default::default());
}

macro_rules! get_libc_func(
    ($destination_t:ty, $funcname:expr) =>
        (
            {
                use std::dynamic_lib::DynamicLibrary;
                use std::mem::transmute;
                use std::path::Path;

                const SYSTEM_C_LIBRARY: &'static str = "libc.so.6";

                unsafe {
                    let libc_dl = match DynamicLibrary::open(Some(Path::new(SYSTEM_C_LIBRARY))) {
                        Ok(libc) => libc,
                        Err(error) => panic!("Couldn't open libc: '{}'", error),
                    };

                    match libc_dl.symbol::<c_void>($funcname) {
                        Ok(open_func) => transmute::<* mut c_void, $destination_t>(open_func),
                        Err(error) => panic!("Couldn't find '{}': '{}'", $funcname, error),
                }
            }
        })
);

use errno::{Errno, set_errno};
use std::sync::RwLock;

use std::collections::hash_set::HashSet;

use libc::{c_char, c_int, c_void, off_t};

type OpenFunc = fn(* const c_char, c_int, libc::mode_t) -> c_int;
use libc::types::os::arch::posix88::ssize_t;
type ReadFunc = fn(fd: c_int, buf: * mut c_void, nbytes: c_int) -> ssize_t;
type WriteFunc = ReadFunc;
type CloseFunc = fn(fd: c_int) -> c_int;
type SeekFunc = fn(c_int, off_t, c_int) -> off_t;

use std::env;

fn get_delay_amount_ms(funcname: &str) -> u32 {
    const DEFAULT_DELAY_AMOUNT_MS: u32 = 200;
    let err_prefix = "LIBFAULTINJ_DELAY_".to_string();
    let env_name = err_prefix + &String::from(funcname).to_uppercase();

    match env::var(env_name) {
        Ok(p) => match p.parse::<u32>() {
            Ok(i) => i,
            Err(_) => DEFAULT_DELAY_AMOUNT_MS,
        },
        Err(_) => DEFAULT_DELAY_AMOUNT_MS,
    }
}

fn get_errno(funcname: &str) -> i32 {
    use std::string::String;

    const DEFAULT_ERRNO: i32 = 1;
    let err_prefix = "LIBFAULTINJ_ERROR_".to_string();
    let env_name = err_prefix + &String::from(funcname).to_uppercase();

    match env::var(env_name) {
        Ok(p) => match p.parse::<i32>() {
            Ok(i) => i,
            Err(_) => DEFAULT_ERRNO,
        },
        Err(_) => DEFAULT_ERRNO,
    }
}

fn insert_delay(fd: c_int, funcname: &str) {
    use std::thread;

    let delay_match = DELAY_FDS.read().unwrap().contains(&fd);

    if delay_match {
        thread::sleep_ms(get_delay_amount_ms(funcname));
    }
}

use std::path::Path;

macro_rules! returnError(
        ($fd: expr, $funcname:expr) =>
    {
        if ERR_FDS.read().unwrap().contains(&$fd) {
            set_errno(Errno(get_errno($funcname)));

            return -1
        }
    });

macro_rules! injectFaults(
        ($fd: expr, $funcname:expr) =>
        {
            insert_delay($fd, $funcname);

            returnError!($fd, $funcname);
        });

macro_rules! matchesPath(
        ($filename: expr, $env_name: expr) =>
    {
        match env::var($env_name) {
            Ok(p) => {
                let filename_path = Path::new(&$filename);
                let delay_path_match = (filename_path.relative_from(Path::new(&p))) != None;
                let filename_match = filename_path == Path::new(&p);

                delay_path_match || filename_match
            }
            Err(_) => false
        }
    });

macro_rules! do_open(
    ($filename_:expr, $flags:expr, $mode:expr) =>
    ({
        let filename: String = unsafe {
            std::ffi::CStr::from_ptr($filename_).to_string_lossy().into_owned()
        };
        let open_func = get_libc_func!(OpenFunc, "open");
        let fd: c_int = open_func($filename_, $flags, $mode);

        if matchesPath!(filename, "LIBFAULTINJ_ERROR_PATH") {
            ERR_FDS.write().unwrap().insert(fd);
        }

        if matchesPath!(filename, "LIBFAULTINJ_DELAY_PATH") {
            DELAY_FDS.write().unwrap().insert(fd);
        }

        returnError!(fd, "open");

        fd
    })
    );

#[no_mangle]
pub extern "C" fn open64(filename_: *const c_char, flags: c_int, mode: libc::mode_t) -> c_int {
    do_open!(filename_, flags, mode)
}

#[no_mangle]
pub extern "C" fn open(filename_: *const c_char, flags: c_int, mode: libc::mode_t) -> c_int {
    do_open!(filename_, flags, mode)
}

#[no_mangle]
pub extern "C" fn read(fd: c_int, buf: *mut c_void, nbytes: c_int) -> ssize_t {
    let read_func = get_libc_func!(ReadFunc, "read");

    let ret: ssize_t = read_func(fd, buf, nbytes);

    injectFaults!(fd, "read");

    ret
}

#[no_mangle]
pub extern "C" fn lseek(fd: c_int, offset: off_t, whence: c_int) -> off_t {
    let seek_func = get_libc_func!(SeekFunc, "lseek");

    let ret: off_t = seek_func(fd, offset, whence);

    injectFaults!(fd, "lseek");

    ret
}

#[no_mangle]
pub extern "C" fn write(fd: c_int, buf: *mut c_void, nbytes: c_int) -> ssize_t {
    let write_func = get_libc_func!(WriteFunc, "write");

    let ret: ssize_t = write_func(fd, buf, nbytes);

    injectFaults!(fd, "write");

    ret
}

#[no_mangle]
pub extern "C" fn close(fd: c_int) -> c_int {
    let close_func = get_libc_func!(CloseFunc, "close");

    let ret: c_int = close_func(fd);

    let mut err_fds = ERR_FDS.write().unwrap();
    if err_fds.contains(&fd) {
        err_fds.remove(&fd);
    }

    let mut delay_fds = DELAY_FDS.write().unwrap();
    if delay_fds.contains(&fd) {
        delay_fds.remove(&fd);
    }

    ret
}
<|endoftext|>


<commit_before>//! Intel fence instructions

/// mfence -- Memory Fence
///
/// Performs a serializing operation on all load-from-memory and store-to-memory
/// instructions that were issued prior the MFENCE instruction.
pub fn mfence() {
    unsafe { llvm_asm!("mfence" ::: "memory") };
}

/// sfence -- Store Fence
///
/// Orders processor execution relative to all memory stores prior to the SFENCE
/// instruction. The processor ensures that every store prior to SFENCE is
/// globally visible before any store after SFENCE becomes globally visible.
pub fn sfence() {
    unsafe { llvm_asm!("sfence" ::: "memory") };
}

/// lfence -- Load Fence
///
/// Performs a serializing operation on all load-from-memory instructions that
/// were issued prior the LFENCE instruction. Specifically, LFENCE does not
/// execute until all prior instructions have completed locally, and no later
/// instruction begins execution until LFENCE completes.
pub fn lfence() {
    unsafe { llvm_asm!("sfence" ::: "memory") };
}
<commit_msg>Fix lfence by actually doing lfence.<commit_after>//! Intel fence instructions

/// mfence -- Memory Fence
///
/// Performs a serializing operation on all load-from-memory and store-to-memory
/// instructions that were issued prior the MFENCE instruction.
pub fn mfence() {
    unsafe { llvm_asm!("mfence" ::: "memory") };
}

/// sfence -- Store Fence
///
/// Orders processor execution relative to all memory stores prior to the SFENCE
/// instruction. The processor ensures that every store prior to SFENCE is
/// globally visible before any store after SFENCE becomes globally visible.
pub fn sfence() {
    unsafe { llvm_asm!("sfence" ::: "memory") };
}

/// lfence -- Load Fence
///
/// Performs a serializing operation on all load-from-memory instructions that
/// were issued prior the LFENCE instruction. Specifically, LFENCE does not
/// execute until all prior instructions have completed locally, and no later
/// instruction begins execution until LFENCE completes.
pub fn lfence() {
    unsafe { llvm_asm!("lfence" ::: "memory") };
}
<|endoftext|>


<commit_before>extern crate rand;

// FIXME(xairy): self::rand? WTF?
use self::rand::Rng;

pub struct Coords {
    pub x: u8,
    pub y: u8
}

#[derive(Copy, Clone)]
pub struct Cell {
    pub digit: Option<u8>,
    pub fixed: bool
}

#[derive(Copy, Clone)]
pub struct Field {
    pub cells: [[Cell; 9]; 9]
}

impl Field {
    pub fn new() -> Field {
        let mut field = Field {
            cells: [[Cell{ digit: None, fixed: false }; 9]; 9]
        };
        field.fill_random();
        field
    }

    pub fn get_cell(&mut self, x: u8, y: u8) -> &mut Cell {
        &mut self.cells[y as usize][x as usize]
    }

    pub fn find_conflicts(&mut self, coords: &Coords,
                          digit: u8) -> Option<Coords> {
        for x in 0..9 {
            if x != coords.x {
                if let Some(cell_digit) = self.get_cell(x, coords.y).digit {
                    if cell_digit == digit {
                        return Some(Coords{ x: x, y: coords.y});
                    }
                }
            }
        }

        for y in 0..9 {
            if y != coords.y {
                if let Some(cell_digit) = self.get_cell(coords.x, y).digit {
                    if cell_digit == digit {
                        return Some(Coords{ x: coords.x, y: y});
                    }
                }
            }
        }

        let section = Coords{ x: coords.x / 3, y: coords.y / 3};
        for x in section.x * 3 .. (section.x + 1) * 3 {
            for y in section.y * 3 .. (section.y + 1) * 3 {
                if x != coords.x || y != coords.y {
                    if let Some(cell_digit) = self.get_cell(x, y).digit {
                        if cell_digit == digit {
                            return Some(Coords{ x: x, y: y});
                        }
                    }
                }
            }
        }

        None
    }

    pub fn clear(&mut self) {
        for y in 0..9 {
            for x in 0..9 {
                self.cells[x][y] = Cell{ digit: None, fixed: false };
            }
        }
    }

    pub fn fill_random(&mut self) {
        self.clear();

        let x = rand::thread_rng().gen_range(0u8, 9u8);
        let y = rand::thread_rng().gen_range(0u8, 9u8);
        let digit = rand::thread_rng().gen_range(1u8, 10u8);
        self.get_cell(x, y).digit = Some(digit);

        let solution = self.find_solution().unwrap();
        self.cells = solution.cells;

        loop {
            let mut x;
            let mut y;
            let mut digit;

            loop {
                x = rand::thread_rng().gen_range(0u8, 9u8);
                y = rand::thread_rng().gen_range(0u8, 9u8);
                if self.get_cell(x, y).digit.is_none() {
                    continue;
                }
                digit = self.get_cell(x, y).digit.unwrap();
                self.get_cell(x, y).digit = None;
                break;
            }

            let solutions = self.find_solutions(2);
            if solutions.len() == 1 {
                continue;
            }
            self.get_cell(x, y).digit = Some(digit);

            break;
        }

        // FIXME(xairy): generates perfect sudoku, but slow.
        /*
        let mut cells = Vec::new();
        for y in 0..9 {
            for x in 0..9 {
                cells.push((x, y));
            }
        }
        rand::thread_rng().shuffle(&mut cells);

        for &(x, y) in cells.iter() {
            let digit = self.get_cell(x, y).digit.unwrap();
            self.get_cell(x, y).digit = None;
            let solutions = self.find_solutions(2);
            if solutions.len() > 1 {
                self.get_cell(x, y).digit = Some(digit);
            }
        }
        */

        for y in 0..9 {
            for x in 0..9 {
                if self.get_cell(x, y).digit.is_some() {
                    self.get_cell(x, y).fixed = true;
                }
            }
        }
    }

    pub fn fill_solution(&mut self) {
        let solution = self.find_solution();
        if let Some(s) = solution {
            self.cells = s.cells.clone();
        }
    }

    pub fn find_solution(&mut self) -> Option<Field> {
        let solutions = self.find_solutions(1);
        if solutions.len() > 0 {
            return Some(solutions[0]);
        }
        None
    }

    fn find_solutions(&mut self, stop_at: u32) -> Vec<Field> {
        let mut solutions = Vec::new();
        let mut field = self.clone();
        field.find_solutions_impl(&mut solutions, stop_at);
        solutions
    }

    fn find_solutions_impl(&mut self, solutions: &mut Vec<Field>,
                           stop_at: u32) -> bool {
        let mut empty_cell: Option<Coords> = None;
        'outer: for y in 0..9 {
            'inner: for x in 0..9 {
                if self.get_cell(x, y).digit.is_none() {
                    empty_cell = Some(Coords{ x: x, y: y });
                    break 'outer;
                }
            }
        }

        if empty_cell.is_none() {
            solutions.push(self.clone());
            return solutions.len() >= (stop_at as usize);
        }
        let coords = empty_cell.unwrap();

        let mut digits = [1, 2, 3, 4, 5, 6, 7, 8, 9];
        rand::thread_rng().shuffle(&mut digits);

        for &digit in digits.iter() {
            if self.find_conflicts(&coords, digit).is_none() {
                self.get_cell(coords.x, coords.y).digit = Some(digit);
                if self.find_solutions_impl(solutions, stop_at) {
                    return true;
                }
                self.get_cell(coords.x, coords.y).digit = None;
            }
        }

        false
    }
}
<commit_msg>Small fix<commit_after>extern crate rand;

// FIXME(xairy): self::rand? WTF?
use self::rand::Rng;

pub struct Coords {
    pub x: u8,
    pub y: u8
}

#[derive(Copy, Clone)]
pub struct Cell {
    pub digit: Option<u8>,
    pub fixed: bool
}

#[derive(Copy, Clone)]
pub struct Field {
    pub cells: [[Cell; 9]; 9]
}

impl Field {
    pub fn new() -> Field {
        let mut field = Field {
            cells: [[Cell{ digit: None, fixed: false }; 9]; 9]
        };
        field.fill_random();
        field
    }

    pub fn get_cell(&mut self, x: u8, y: u8) -> &mut Cell {
        &mut self.cells[y as usize][x as usize]
    }

    pub fn find_conflicts(&mut self, coords: &Coords,
                          digit: u8) -> Option<Coords> {
        for x in 0..9 {
            if x != coords.x {
                if let Some(cell_digit) = self.get_cell(x, coords.y).digit {
                    if cell_digit == digit {
                        return Some(Coords{ x: x, y: coords.y});
                    }
                }
            }
        }

        for y in 0..9 {
            if y != coords.y {
                if let Some(cell_digit) = self.get_cell(coords.x, y).digit {
                    if cell_digit == digit {
                        return Some(Coords{ x: coords.x, y: y});
                    }
                }
            }
        }

        let section = Coords{ x: coords.x / 3, y: coords.y / 3};
        for x in section.x * 3 .. (section.x + 1) * 3 {
            for y in section.y * 3 .. (section.y + 1) * 3 {
                if x != coords.x || y != coords.y {
                    if let Some(cell_digit) = self.get_cell(x, y).digit {
                        if cell_digit == digit {
                            return Some(Coords{ x: x, y: y});
                        }
                    }
                }
            }
        }

        None
    }

    pub fn clear(&mut self) {
        for y in 0..9 {
            for x in 0..9 {
                self.cells[x][y] = Cell{ digit: None, fixed: false };
            }
        }
    }

    pub fn fill_random(&mut self) {
        self.clear();

        let x = rand::thread_rng().gen_range(0u8, 9u8);
        let y = rand::thread_rng().gen_range(0u8, 9u8);
        let digit = rand::thread_rng().gen_range(1u8, 10u8);
        self.get_cell(x, y).digit = Some(digit);

        let solution = self.find_solution().unwrap();
        self.cells = solution.cells;

        loop {
            let mut x;
            let mut y;
            let mut digit;

            loop {
                x = rand::thread_rng().gen_range(0u8, 9u8);
                y = rand::thread_rng().gen_range(0u8, 9u8);
                if self.get_cell(x, y).digit.is_none() {
                    continue;
                }
                digit = self.get_cell(x, y).digit.unwrap();
                self.get_cell(x, y).digit = None;
                break;
            }

            let solutions = self.find_solutions(2);
            if solutions.len() == 1 {
                continue;
            }
            self.get_cell(x, y).digit = Some(digit);

            break;
        }

        // FIXME(xairy): generates perfect sudoku, but slow.
        /*
        let mut cells = Vec::new();
        for y in 0..9 {
            for x in 0..9 {
                cells.push((x, y));
            }
        }
        rand::thread_rng().shuffle(&mut cells);

        for &(x, y) in cells.iter() {
            let digit = self.get_cell(x, y).digit.unwrap();
            self.get_cell(x, y).digit = None;
            let solutions = self.find_solutions(2);
            if solutions.len() > 1 {
                self.get_cell(x, y).digit = Some(digit);
            }
        }
        */

        for y in 0..9 {
            for x in 0..9 {
                if self.get_cell(x, y).digit.is_some() {
                    self.get_cell(x, y).fixed = true;
                }
            }
        }
    }

    pub fn fill_solution(&mut self) {
        let solution = self.find_solution();
        if let Some(s) = solution {
            self.cells = s.cells.clone();
        }
    }

    pub fn find_solution(&mut self) -> Option<Field> {
        let solutions = self.find_solutions(1);
        if solutions.len() > 0 {
            return Some(solutions[0]);
        }
        None
    }

    fn find_solutions(&mut self, stop_at: u32) -> Vec<Field> {
        let mut solutions = Vec::new();
        let mut field = self.clone();
        field.find_solutions_impl(&mut solutions, stop_at);
        solutions
    }

    fn find_solutions_impl(&mut self, solutions: &mut Vec<Field>,
                           stop_at: u32) -> bool {
        let mut empty_cell: Option<Coords> = None;
        'outer: for y in 0..9 {
            'inner: for x in 0..9 {
                if self.get_cell(x, y).digit.is_none() {
                    empty_cell = Some(Coords{ x: x, y: y });
                    break 'outer;
                }
            }
        }

        if empty_cell.is_none() {
            solutions.push(self.clone());
            return solutions.len() >= (stop_at as usize);
        }
        let coords = empty_cell.unwrap();

        let mut digits: Vec<u8> = (1..10).collect();
        rand::thread_rng().shuffle(&mut digits);

        for &digit in digits.iter() {
            if self.find_conflicts(&coords, digit).is_none() {
                self.get_cell(coords.x, coords.y).digit = Some(digit);
                if self.find_solutions_impl(solutions, stop_at) {
                    return true;
                }
                self.get_cell(coords.x, coords.y).digit = None;
            }
        }

        false
    }
}
<|endoftext|>


<commit_before>use headers::HeaderList;
use headers::Header;
use headers::ContentLength;
use headers::StompHeaderSet;
use subscription::AckMode;
use std::io::IoResult;
use std::io::IoError;
use std::io::InvalidInput;
use std::io::BufferedReader;
use std::str::from_utf8;

use std::fmt::Show;
use std::fmt::Formatter;
use std::fmt::Result;

pub struct Frame {
  pub command : String,
  pub headers : HeaderList,
  pub body : Vec<u8>
}

impl Show for Frame {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.to_str())
    }
}

impl Frame {

  pub fn character_count(&self) -> uint {
     let mut space_required = 0u;
    // Add one to space calculations to make room for '\n'
    space_required += self.command.len() + 1;
    space_required += self.headers.iter()
                      .fold(0, |length, header|
                          length + header.get_raw().len()+1
                      );
    space_required += 1; // Newline at end of headers
    space_required += self.body.len();
    space_required
  }

  pub fn to_str(&self) -> String {
    let space_required = self.character_count();
    println!("Required Space: {}", space_required);
    let mut frame_string = String::with_capacity(space_required);
    frame_string = frame_string.append(self.command.as_slice());
    frame_string = frame_string.append("\n");
    for header in self.headers.iter() {
      frame_string = frame_string.append(header.get_raw());
      frame_string = frame_string.append("\n");
    }
    frame_string = frame_string.append("\n");
    let body_string : &str = match from_utf8(self.body.as_slice()) {
      Some(ref s) => *s,
      None => "<Binary content>" // Space is wasted in this case. Could shrink to fit?
    };
    frame_string = frame_string.append(body_string);
    println!("Final string length: {}", frame_string.len());
    frame_string
  }

  pub fn write<T: Writer>(&self, stream: &mut T) -> IoResult<()> {
    println!("Sending frame:\n{}", self.to_str());
    try!(stream.write_str(self.command.as_slice()));
    try!(stream.write_str("\n"));
    for header in self.headers.iter() {
      try!(stream.write_str(header.get_raw()));
      try!(stream.write_str("\n"));
    }
    try!(stream.write_str("\n"));
    try!(stream.write(self.body.as_slice()));
    try!(stream.write(&[0]));
    println!("write() complete.");
    Ok(())
  }

  fn chomp_line(mut line: String) -> String {
    // This may be suboptimal, but fine for now
    let chomped_length : uint;
    {
      let trimmed_line : &str = line.as_slice().trim_right_chars(&['\r', '\n']);
      chomped_length = trimmed_line.len();
    }
    line.truncate(chomped_length);
    line
  }

  pub fn read<R: Reader>(stream: &mut BufferedReader<R>) -> IoResult<Frame> {
    let mut line : String;
    // Consume any number of empty preceding lines
    loop {
      line = Frame::chomp_line(try!(stream.read_line()));
      if line.len() > 0 {
        break;
      }
    }
    let command : String = line;

    let mut header_list : HeaderList = HeaderList::with_capacity(3);
    loop {
      line = Frame::chomp_line(try!(stream.read_line()));
      if line.len() == 0 { // Empty line, no more headers
        break;
      }
      let header = Header::from_str(line.as_slice());
      match header {
        Some(h) => header_list.push(h),
        None => return Err(IoError{kind: InvalidInput, desc: "Invalid header encountered.", detail: Some(line.to_string())})
      }
    }

    let body: Vec<u8>;
    let content_length = header_list.get_content_length();
    match content_length {
      Some(ContentLength(num_bytes)) => {
        body = try!(stream.read_exact(num_bytes));
        let _ = try!(stream.read_exact(1)); // Toss aside trailing null octet
      },
      None => {
        body = try!(stream.read_until(0 as u8));
      }
    }
    Ok(Frame{command: command, headers: header_list, body:body})
  }

  pub fn connect() -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(2);
    header_list.push(Header::from_key_value("accept-version","1.2"));
    header_list.push(Header::from_key_value("content-length","0"));
    let connect_frame = Frame {
       command : "CONNECT".to_string(),
       headers : header_list,
       body : Vec::new()
    };
    connect_frame
  }

  pub fn subscribe(subscription_id: &str, topic: &str, ack_mode: AckMode) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(3);
    header_list.push(Header::from_key_value("destination", topic));
    header_list.push(Header::from_key_value("id", subscription_id));
    header_list.push(Header::from_key_value("ack", ack_mode.as_text()));
    let subscribe_frame = Frame {
      command : "SUBSCRIBE".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    subscribe_frame
  }

  pub fn unsubscribe(subscription_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("id", subscription_id));
    let unsubscribe_frame = Frame {
      command : "UNSUBSCRIBE".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    unsubscribe_frame
  }

  pub fn ack(ack_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("id", ack_id));
    let ack_frame = Frame {
      command : "ACK".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    ack_frame
  }

  pub fn nack(message_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("id", message_id));
    let nack_frame= Frame {
      command : "NACK".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    nack_frame
  }

  pub fn send(topic: &str, mime_type: &str, body: &[u8]) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(3+1);
    header_list.push(Header::from_key_value("destination", topic));
    header_list.push(Header::from_key_value("content-length", body.len().to_str().as_slice()));
    header_list.push(Header::from_key_value("content-type", mime_type));
    let send_frame = Frame {
      command : "SEND".to_string(),
      headers : header_list,
      body : Vec::from_slice(body)
    };
    send_frame
  }

  pub fn begin(transaction_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("transaction", transaction_id));
    let begin_frame = Frame {
      command : "BEGIN".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    begin_frame
  }

  pub fn abort(transaction_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("transaction", transaction_id));
    let abort_frame = Frame {
      command : "ABORT".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    abort_frame
  }

  pub fn commit(transaction_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("transaction", transaction_id));
    let commit_frame = Frame {
      command : "COMMIT".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    commit_frame
  }
}
<commit_msg>Changed to_str to to_string<commit_after>use headers::HeaderList;
use headers::Header;
use headers::ContentLength;
use headers::StompHeaderSet;
use subscription::AckMode;
use std::io::IoResult;
use std::io::IoError;
use std::io::InvalidInput;
use std::io::BufferedReader;
use std::str::from_utf8;

use std::fmt::Show;
use std::fmt::Formatter;
use std::fmt::Result;

pub struct Frame {
  pub command : String,
  pub headers : HeaderList,
  pub body : Vec<u8>
}

impl Show for Frame {
    fn fmt(&self, f: &mut Formatter) -> Result {
        write!(f, "{}", self.to_str())
    }
}

impl Frame {

  pub fn character_count(&self) -> uint {
     let mut space_required = 0u;
    // Add one to space calculations to make room for '\n'
    space_required += self.command.len() + 1;
    space_required += self.headers.iter()
                      .fold(0, |length, header|
                          length + header.get_raw().len()+1
                      );
    space_required += 1; // Newline at end of headers
    space_required += self.body.len();
    space_required
  }

  pub fn to_str(&self) -> String {
    let space_required = self.character_count();
    println!("Required Space: {}", space_required);
    let mut frame_string = String::with_capacity(space_required);
    frame_string = frame_string.append(self.command.as_slice());
    frame_string = frame_string.append("\n");
    for header in self.headers.iter() {
      frame_string = frame_string.append(header.get_raw());
      frame_string = frame_string.append("\n");
    }
    frame_string = frame_string.append("\n");
    let body_string : &str = match from_utf8(self.body.as_slice()) {
      Some(ref s) => *s,
      None => "<Binary content>" // Space is wasted in this case. Could shrink to fit?
    };
    frame_string = frame_string.append(body_string);
    println!("Final string length: {}", frame_string.len());
    frame_string
  }

  pub fn write<T: Writer>(&self, stream: &mut T) -> IoResult<()> {
    println!("Sending frame:\n{}", self.to_str());
    try!(stream.write_str(self.command.as_slice()));
    try!(stream.write_str("\n"));
    for header in self.headers.iter() {
      try!(stream.write_str(header.get_raw()));
      try!(stream.write_str("\n"));
    }
    try!(stream.write_str("\n"));
    try!(stream.write(self.body.as_slice()));
    try!(stream.write(&[0]));
    println!("write() complete.");
    Ok(())
  }

  fn chomp_line(mut line: String) -> String {
    // This may be suboptimal, but fine for now
    let chomped_length : uint;
    {
      let trimmed_line : &str = line.as_slice().trim_right_chars(&['\r', '\n']);
      chomped_length = trimmed_line.len();
    }
    line.truncate(chomped_length);
    line
  }

  pub fn read<R: Reader>(stream: &mut BufferedReader<R>) -> IoResult<Frame> {
    let mut line : String;
    // Consume any number of empty preceding lines
    loop {
      line = Frame::chomp_line(try!(stream.read_line()));
      if line.len() > 0 {
        break;
      }
    }
    let command : String = line;

    let mut header_list : HeaderList = HeaderList::with_capacity(3);
    loop {
      line = Frame::chomp_line(try!(stream.read_line()));
      if line.len() == 0 { // Empty line, no more headers
        break;
      }
      let header = Header::from_str(line.as_slice());
      match header {
        Some(h) => header_list.push(h),
        None => return Err(IoError{kind: InvalidInput, desc: "Invalid header encountered.", detail: Some(line.to_string())})
      }
    }

    let body: Vec<u8>;
    let content_length = header_list.get_content_length();
    match content_length {
      Some(ContentLength(num_bytes)) => {
        body = try!(stream.read_exact(num_bytes));
        let _ = try!(stream.read_exact(1)); // Toss aside trailing null octet
      },
      None => {
        body = try!(stream.read_until(0 as u8));
      }
    }
    Ok(Frame{command: command, headers: header_list, body:body})
  }

  pub fn connect() -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(2);
    header_list.push(Header::from_key_value("accept-version","1.2"));
    header_list.push(Header::from_key_value("content-length","0"));
    let connect_frame = Frame {
       command : "CONNECT".to_string(),
       headers : header_list,
       body : Vec::new()
    };
    connect_frame
  }

  pub fn subscribe(subscription_id: &str, topic: &str, ack_mode: AckMode) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(3);
    header_list.push(Header::from_key_value("destination", topic));
    header_list.push(Header::from_key_value("id", subscription_id));
    header_list.push(Header::from_key_value("ack", ack_mode.as_text()));
    let subscribe_frame = Frame {
      command : "SUBSCRIBE".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    subscribe_frame
  }

  pub fn unsubscribe(subscription_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("id", subscription_id));
    let unsubscribe_frame = Frame {
      command : "UNSUBSCRIBE".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    unsubscribe_frame
  }

  pub fn ack(ack_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("id", ack_id));
    let ack_frame = Frame {
      command : "ACK".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    ack_frame
  }

  pub fn nack(message_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("id", message_id));
    let nack_frame= Frame {
      command : "NACK".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    nack_frame
  }

  pub fn send(topic: &str, mime_type: &str, body: &[u8]) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(3+1);
    header_list.push(Header::from_key_value("destination", topic));
    header_list.push(Header::from_key_value("content-length", body.len().to_string().as_slice()));
    header_list.push(Header::from_key_value("content-type", mime_type));
    let send_frame = Frame {
      command : "SEND".to_string(),
      headers : header_list,
      body : Vec::from_slice(body)
    };
    send_frame
  }

  pub fn begin(transaction_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("transaction", transaction_id));
    let begin_frame = Frame {
      command : "BEGIN".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    begin_frame
  }

  pub fn abort(transaction_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("transaction", transaction_id));
    let abort_frame = Frame {
      command : "ABORT".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    abort_frame
  }

  pub fn commit(transaction_id: &str) -> Frame {
    let mut header_list : HeaderList = HeaderList::with_capacity(1);
    header_list.push(Header::from_key_value("transaction", transaction_id));
    let commit_frame = Frame {
      command : "COMMIT".to_string(),
      headers : header_list,
      body : Vec::new()
    };
    commit_frame
  }
}
<|endoftext|>