<commit_before>#![allow(dead_code)]

use std::io::{IoError, IoErrorKind, Reader};

struct Frame;

// TODO: there should be a way to signal IO error.
// This will be handled by the error reform RFCs, I think.
// For now, use IO error to indicate any failure.
pub type Error = IoError;

fn mk_err() -> Error {
    IoError {
        kind: IoErrorKind::OtherIoError,
        desc: "FLAC decoding error",
        detail: None
    }
}

struct FlacStream {
    metadata_blocks: Vec<MetadataBlock>
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_stream_header(input: &mut Reader) -> Result<(), Error> {
    // A FLAC stream starts with a 32-bit header 'fLaC' (big endian).
    const HEADER: u32 = 0x66_4c_61_43;
    let header = try!(input.read_be_u32());
    if header != HEADER { return Err(mk_err()); } // TODO: provide more error info.
    Ok(())
}

// TODO: should this be private or not?
#[deriving(Show)]
pub struct StreamInfo {
    pub min_block_size: u16,
    pub max_block_size: u16,
    pub min_frame_size: Option<u32>,
    pub max_frame_size: Option<u32>,
    pub sample_rate: u32,
    pub n_channels: u8,
    pub bits_per_sample: u8,
    pub n_samples: Option<u64>,
    pub md5sum: [u8, ..16]
}

// TODO: should this be private?
pub struct SeekPoint {
    pub sample: u64,
    pub offset: u64,
    pub n_samples: u16
}

// TODO: should this be private?
pub struct SeekTable {
    seekpoints: Vec<SeekPoint>
}

pub enum MetadataBlock {
    StreamInfo(StreamInfo),
    Padding { length: u32 },
    Application { id: u32, data: Vec<u8> },
    SeekTable(SeekTable),
    VorbisComment, // TODO
    CueSheet, // TODO
    Picture // TODO
}

// TODO: this should be private.
pub struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_metadata_block_header(input: &mut Reader) -> Result<MetadataBlockHeader, Error> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte & 1) == 1;
    let block_type = byte >> 1;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_uint_n(3)) as u32;

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length
    };
    Ok(header)
}

fn read_metadata_block(input: &mut Reader, block_type: u8, length: u32)
                       -> Result<MetadataBlock, Error> {
    match block_type {
        0 => {
            let streaminfo = try!(read_streaminfo_block(input));
            Ok(MetadataBlock::StreamInfo(streaminfo))
        },
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application { id: id, data: data })
        },
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        127 => Err(mk_err()), // TODO: "invalid, to avoid confusion with a frame sync code"
        _ => Err(mk_err()) // TODO: "reserved", is that an error or do we ignore it?
    }
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_streaminfo_block(input: &mut Reader) -> Result<StreamInfo, Error> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_uint_n(3)) as u32;
    let max_frame_size = try!(input.read_be_uint_n(3)) as u32;

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_byte());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = sample_rate_msb as u32 << 4 | sample_rate_lsb as u32 >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0x7) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_byte());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0xf;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = n_samples_msb as u64 << 32 | n_samples_lsb as u64;

    let mut md5sum = [0u8, ..16];
    try!(input.read_at_least(16, &mut md5sum));

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 { None } else { Some(min_frame_size) },
        max_frame_size: if max_frame_size == 0 { None } else { Some(max_frame_size) },
        sample_rate: sample_rate,
        n_channels: n_channels,
        bits_per_sample: bits_per_sample,
        n_samples: if n_samples == 0 { None } else { Some(n_samples) },
        md5sum: md5sum
    };

    Ok(stream_info)
}

fn read_padding_block(input: &mut Reader, length: u32) -> Result<(), Error> {
    // The specification dictates that all bits of the padding block must be 0.
    for _ in range(0, length) {
        if try!(input.read_byte()) != 0 {
            return Err(mk_err()); // TODO: error, nonzero bit in padding block.
        }
    }
    Ok(())
}

fn skip_block(input: &mut Reader, length: u32) -> Result<(), Error> {
    // Skip all the padding bytes.
    for _ in range(0, length) { try!(input.read_byte()); }
    Ok(())
}

fn read_application_block(input: &mut Reader, length: u32) -> Result<(u32, Vec<u8>), Error> {
    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    let data = try!(input.read_exact((length - 4) as uint));

    Ok((id, data))
}

struct MetadataBlockReader<'r, R> where R: 'r {
    input: &'r mut R,
    done: bool
}

type MetadataBlockResult = Result<MetadataBlock, Error>;

impl<'r, R> MetadataBlockReader<'r, R> where R: Reader {
    pub fn new(input: &'r mut R) -> MetadataBlockReader<'r, R> {
        MetadataBlockReader { input: input, done: false }
    }

    fn read_next(&mut self) -> MetadataBlockResult {
        let header = try!(read_metadata_block_header(self.input));
        let block = try!(read_metadata_block(self.input, header.block_type, header.length));
        self.done = header.is_last;
        Ok(block)
    }
}

impl<'r, R> Iterator<MetadataBlockResult>
    for MetadataBlockReader<'r, R>
    where R: Reader {

    fn next(&mut self) -> Option<MetadataBlockResult> {
        if self.done { None } else { Some(self.read_next()) }
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        if self.done { (0, Some(0)) } else { (1, None) }
    }
}

impl FlacStream {
    pub fn new(input: &mut Reader) -> Result<FlacStream, Error> {
        try!(read_stream_header(input));

        let hdr = try!(read_metadata_block_header(input));
        println!("type: {}, length: {}, last: {}",
                 hdr.block_type, hdr.length, hdr.is_last);

        let streaminfo = try!(read_streaminfo_block(input));
        println!("streaminfo: {}", streaminfo);
        // Read the STREAMINFO block
        // Read any metadata
        // Read frames

        let flac_stream = FlacStream {
            metadata_blocks: Vec::new()
        };

        Ok(flac_stream)
    }
}

#[test]
fn test_open_stream() {
    use std::io::File;
    let mut input = File::open(&Path::new("foo.flac")).unwrap();
    let flac_stream = FlacStream::new(&mut input).unwrap();
}
<commit_msg>read metadata blocks upon FlacStream construction<commit_after>#![allow(dead_code)]

use std::io::{IoError, IoErrorKind, Reader};

struct Frame;

// TODO: there should be a way to signal IO error.
// This will be handled by the error reform RFCs, I think.
// For now, use IO error to indicate any failure.
pub type Error = IoError;

fn mk_err() -> Error {
    IoError {
        kind: IoErrorKind::OtherIoError,
        desc: "FLAC decoding error",
        detail: None
    }
}

struct FlacStream {
    streaminfo: StreamInfo,
    metadata_blocks: Vec<MetadataBlock>
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_stream_header(input: &mut Reader) -> Result<(), Error> {
    // A FLAC stream starts with a 32-bit header 'fLaC' (big endian).
    const HEADER: u32 = 0x66_4c_61_43;
    let header = try!(input.read_be_u32());
    if header != HEADER { return Err(mk_err()); } // TODO: provide more error info.
    Ok(())
}

// TODO: should this be private or not?
#[deriving(Show)]
pub struct StreamInfo {
    pub min_block_size: u16,
    pub max_block_size: u16,
    pub min_frame_size: Option<u32>,
    pub max_frame_size: Option<u32>,
    pub sample_rate: u32,
    pub n_channels: u8,
    pub bits_per_sample: u8,
    pub n_samples: Option<u64>,
    pub md5sum: [u8, ..16]
}

// TODO: should this be private?
pub struct SeekPoint {
    pub sample: u64,
    pub offset: u64,
    pub n_samples: u16
}

// TODO: should this be private?
pub struct SeekTable {
    seekpoints: Vec<SeekPoint>
}

pub enum MetadataBlock {
    StreamInfo(StreamInfo),
    Padding { length: u32 },
    Application { id: u32, data: Vec<u8> },
    SeekTable(SeekTable),
    VorbisComment, // TODO
    CueSheet, // TODO
    Picture // TODO
}

// TODO: this should be private.
pub struct MetadataBlockHeader {
    is_last: bool,
    block_type: u8,
    length: u32
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_metadata_block_header(input: &mut Reader) -> Result<MetadataBlockHeader, Error> {
    let byte = try!(input.read_u8());

    // The first bit specifies whether this is the last block, the next 7 bits
    // specify the type of the metadata block to follow.
    let is_last = (byte & 1) == 1;
    let block_type = byte >> 1;

    // The length field is 24 bits, or 3 bytes.
    let length = try!(input.read_be_uint_n(3)) as u32;

    let header = MetadataBlockHeader {
        is_last: is_last,
        block_type: block_type,
        length: length
    };
    Ok(header)
}

fn read_metadata_block(input: &mut Reader, block_type: u8, length: u32)
                       -> Result<MetadataBlock, Error> {
    match block_type {
        0 => {
            let streaminfo = try!(read_streaminfo_block(input));
            Ok(MetadataBlock::StreamInfo(streaminfo))
        },
        1 => {
            try!(read_padding_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        2 => {
            let (id, data) = try!(read_application_block(input, length));
            Ok(MetadataBlock::Application { id: id, data: data })
        },
        3 => {
            // TODO: implement seektable reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        4 => {
            // TODO: implement Vorbis comment reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        5 => {
            // TODO: implement CUE sheet reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        6 => {
            // TODO: implement picture reading. For now, pretend it is padding.
            try!(skip_block(input, length));
            Ok(MetadataBlock::Padding { length: length })
        },
        127 => Err(mk_err()), // TODO: "invalid, to avoid confusion with a frame sync code"
        _ => Err(mk_err()) // TODO: "reserved", is that an error or do we ignore it?
    }
}

// TODO: this should be private, but it must be public for the test for now.
pub fn read_streaminfo_block(input: &mut Reader) -> Result<StreamInfo, Error> {
    let min_block_size = try!(input.read_be_u16());
    let max_block_size = try!(input.read_be_u16());

    // The frame size fields are 24 bits, or 3 bytes.
    let min_frame_size = try!(input.read_be_uint_n(3)) as u32;
    let max_frame_size = try!(input.read_be_uint_n(3)) as u32;

    // Next up are 20 bits that determine the sample rate.
    let sample_rate_msb = try!(input.read_be_u16());
    let sample_rate_lsb = try!(input.read_byte());

    // Stitch together the value from the first 16 bits,
    // and then the 4 most significant bits of the next byte.
    let sample_rate = sample_rate_msb as u32 << 4 | sample_rate_lsb as u32 >> 4;

    // Next three bits are the number of channels - 1. Mask them out and add 1.
    let n_channels_bps = sample_rate_lsb;
    let n_channels = ((n_channels_bps >> 1) & 0x7) + 1;

    // The final bit is the most significant of bits per sample - 1. Bits per
    // sample - 1 is 5 bits in total.
    let bps_msb = n_channels_bps & 1;
    let bps_lsb_n_samples = try!(input.read_byte());

    // Stitch together these values, add 1 because # - 1 is stored.
    let bits_per_sample = (bps_msb << 4 | (bps_lsb_n_samples >> 4)) + 1;

    // Number of samples in 36 bits, we have 4 already, 32 to go.
    let n_samples_msb = bps_lsb_n_samples & 0xf;
    let n_samples_lsb = try!(input.read_be_u32());
    let n_samples = n_samples_msb as u64 << 32 | n_samples_lsb as u64;

    let mut md5sum = [0u8, ..16];
    try!(input.read_at_least(16, &mut md5sum));

    let stream_info = StreamInfo {
        min_block_size: min_block_size,
        max_block_size: max_block_size,
        min_frame_size: if min_frame_size == 0 { None } else { Some(min_frame_size) },
        max_frame_size: if max_frame_size == 0 { None } else { Some(max_frame_size) },
        sample_rate: sample_rate,
        n_channels: n_channels,
        bits_per_sample: bits_per_sample,
        n_samples: if n_samples == 0 { None } else { Some(n_samples) },
        md5sum: md5sum
    };

    Ok(stream_info)
}

fn read_padding_block(input: &mut Reader, length: u32) -> Result<(), Error> {
    // The specification dictates that all bits of the padding block must be 0.
    for _ in range(0, length) {
        if try!(input.read_byte()) != 0 {
            return Err(mk_err()); // TODO: error, nonzero bit in padding block.
        }
    }
    Ok(())
}

fn skip_block(input: &mut Reader, length: u32) -> Result<(), Error> {
    // Skip all the padding bytes.
    for _ in range(0, length) { try!(input.read_byte()); }
    Ok(())
}

fn read_application_block(input: &mut Reader, length: u32) -> Result<(u32, Vec<u8>), Error> {
    let id = try!(input.read_be_u32());

    // Four bytes of the block have been used for the ID, the rest is payload.
    let data = try!(input.read_exact((length - 4) as uint));

    Ok((id, data))
}

/// Reads metadata blocks from a stream and exposes them as an iterator.
///
/// It is assumed that the next byte that the reader will read, is the first
/// byte of a metadata block header. This means that the iterator will yield at
/// least a single value. If the iterator ever yields an error, then no more
/// data will be read thereafter, and the next value will be `None`.
struct MetadataBlockReader<'r, R> where R: 'r {
    input: &'r mut R,
    done: bool
}

type MetadataBlockResult = Result<MetadataBlock, Error>;

impl<'r, R> MetadataBlockReader<'r, R> where R: Reader {
    pub fn new(input: &'r mut R) -> MetadataBlockReader<'r, R> {
        MetadataBlockReader { input: input, done: false }
    }

    fn read_next(&mut self) -> MetadataBlockResult {
        let header = try!(read_metadata_block_header(self.input));
        let block = try!(read_metadata_block(self.input, header.block_type,
                                                         header.length));
        self.done = header.is_last;
        Ok(block)
    }
}

impl<'r, R> Iterator<MetadataBlockResult>
    for MetadataBlockReader<'r, R>
    where R: Reader {

    fn next(&mut self) -> Option<MetadataBlockResult> {
        if self.done {
            None
        } else {
            let block = self.read_next();

            // After a failure, no more attempts to read will be made,
            // because we don't know where we are in the stream.
            if !block.is_ok() { self.done = true; }

            Some(block)
        }
    }

    fn size_hint(&self) -> (uint, Option<uint>) {
        if self.done { (0, Some(0)) } else { (1, None) }
    }
}

impl FlacStream {
    pub fn new<R>(input: &mut R) -> Result<FlacStream, Error>
        where R: Reader {
        // A flac stream first of all starts with a stream header.
        try!(read_stream_header(input));

        // Next are one or more metadata blocks. The flac specification
        // dictates that the streaminfo block is the first block. The metadata
        // block reader will yield at least one element, so the unwrap is safe.
        let mut metadata_iter = MetadataBlockReader::new(input);
        let streaminfo_block = try!(metadata_iter.next().unwrap());
        let streaminfo = match streaminfo_block {
            MetadataBlock::StreamInfo(info) => info,
            _ => return Err(mk_err()) // TODO: Error: streaminfo block must be the first block.
        };

        // There might be more metadata blocks, read and store them.
        let mut metadata_blocks = Vec::new();
        for block_result in metadata_iter {
            match block_result {
                Err(error) => return Err(error),
                Ok(block) => metadata_blocks.push(block)
            }
        }

        // Read frames

        let flac_stream = FlacStream {
            streaminfo: streaminfo,
            metadata_blocks: metadata_blocks
        };

        Ok(flac_stream)
    }
}

#[test]
fn test_open_stream() {
    use std::io::File;
    let mut input = File::open(&Path::new("foo.flac")).unwrap();
    let flac_stream = FlacStream::new(&mut input).unwrap();
}
<|endoftext|>


<commit_before>#![feature(associated_types)]

use std::ops::Deref;

pub mod graph {
    use std::collections::HashMap;

    #[derive(Debug)]
    pub struct Graph {
        elements: i64,
        vertices: HashMap<i64, Box<Vertex>>,
    }

    impl Graph {
        pub fn new() -> Box<Graph> {
            let vertices: HashMap<i64, Box<Vertex>> = HashMap::new();
            Box::new(Graph{elements:0, vertices:vertices})
        }

        pub fn add_vertex(&mut self) -> VertexProxy {
            let new_id = self.elements + 1;
            self.elements += 1;
            let mut v = Vertex::new(new_id);

            let ptr: *mut Box<Vertex> = &mut v as *mut Box<Vertex>;

            self.vertices.insert(new_id, v);

            // return the proxy which knows it's own id
            VertexProxy{id:new_id, v: ptr}
        }
    }

    /*
    I'm not sure on this, but it feels reasonable.  a vertex can own it's out_edges.
    this should? make it easier to manage the memory?

    additionally, it should cut down on the number of "things" i have to traverse
    if a vertex has 10k edges (5k in and out 5k out) then doing something like

    g(v).outV()

    should be faster to iterate over

    the cost is a little code complexity but i think that won't be too bad
     */
    #[derive(Debug)]
    struct Vertex {
        id: i64,
        out_edges: Vec<Edge>,
        in_edges: *mut Vec<Edge>,
    }

    impl Vertex {
        pub fn new(id: i64) -> Box<Vertex> {

            let mut edges : Vec<Edge> = Vec::new();
            let edges_ptr :    *mut Vec<Edge> = &mut edges;
            let out_edges: Vec<Edge> = Vec::new();
            let vertex = Vertex{id:id, out_edges: out_edges, in_edges:edges_ptr};
            let mut v = Box::new(vertex);
            return v;
        }

        pub fn add_out_edge(&mut self, edge: Edge ) {
            self.out_edges.push(edge)
        }

        pub fn add_in_edge() {

        }

    }

    #[derive(Debug)]
    pub struct VertexProxy {
        id: i64,
        v: *mut Box<Vertex>,
    }

    //let i: u32 = 1;
    //// explicit cast
    //let p_imm: *const u32 = &i as *const u32;
    //let mut m: u32 = 2;
    //// implicit coercion
    //let p_mut: *mut u32 = &mut m;
    //
    //unsafe {
    //let ref_imm: &u32 = &*p_imm;
    //let ref_mut: &mut u32 = &mut *p_mut;
    //}

    impl VertexProxy {
        pub fn add_edge(&mut self, to_vertex: &mut VertexProxy) {
            let in_vertex: &mut Box<Vertex>;
            let out_vertex: &mut Box<Vertex>;

            unsafe {
                in_vertex =  &mut *(self.v);
                out_vertex = &mut *(to_vertex.v);
            }

            // create the edge
            let mut e = Edge{from_vertex: self.v, to_vertex: to_vertex.v};
            in_vertex.add_out_edge(e);
        }
        pub fn query(self) {

        }
    }

    /*
    impl<T> Deref for DerefExample<T> {
        type Target = T;

        fn deref<'a>(&'a self) -> &'a T {
            &self.value
        }
    }
     */

    #[derive(Debug)]
    struct Edge {
        from_vertex: *const Box<Vertex>,
        to_vertex: *const Box<Vertex>
    }

    #[test]
    fn test_unsafe_vertex() {
        let mut g = Graph::new();
        let v1 = g.add_vertex();
        assert!(v1.id == 1);

        let v2 = g.add_vertex();
        assert!(v2.id == 2);
    }

    #[test]
    fn test_add_edge() {
        let mut g = Graph::new();
        let v1 = g.add_vertex();
        let v2 = g.add_vertex();
        v1.add_edge(&v2);

    }

}
<commit_msg>tests run<commit_after>
use std::ops::Deref;

pub mod graph {
    use std::collections::HashMap;

    #[derive(Debug)]
    pub struct Graph {
        elements: i64,
        vertices: HashMap<i64, Box<Vertex>>,
    }

    impl Graph {
        pub fn new() -> Box<Graph> {
            let vertices: HashMap<i64, Box<Vertex>> = HashMap::new();
            Box::new(Graph{elements:0, vertices:vertices})
        }

        pub fn add_vertex(&mut self) -> VertexProxy {
            let new_id = self.elements + 1;
            self.elements += 1;
            let mut v = Vertex::new(new_id);

            let ptr: *mut Box<Vertex> = &mut v as *mut Box<Vertex>;

            self.vertices.insert(new_id, v);

            // return the proxy which knows it's own id
            VertexProxy{id:new_id, v: ptr}
        }
    }

    /*
    I'm not sure on this, but it feels reasonable.  a vertex can own it's out_edges.
    this should? make it easier to manage the memory?

    additionally, it should cut down on the number of "things" i have to traverse
    if a vertex has 10k edges (5k in and out 5k out) then doing something like

    g(v).outV()

    should be faster to iterate over

    the cost is a little code complexity but i think that won't be too bad
     */
    #[derive(Debug)]
    struct Vertex {
        id: i64,
        out_edges: Vec<Edge>,
        in_edges: *mut Vec<Edge>,
    }

    impl Vertex {
        pub fn new(id: i64) -> Box<Vertex> {

            let mut edges : Vec<Edge> = Vec::new();
            let edges_ptr :    *mut Vec<Edge> = &mut edges;
            let out_edges: Vec<Edge> = Vec::new();
            let vertex = Vertex{id:id, out_edges: out_edges, in_edges:edges_ptr};
            let mut v = Box::new(vertex);
            return v;
        }

        pub fn add_out_edge(&mut self, edge: Edge ) {
            self.out_edges.push(edge)
        }

        pub fn add_in_edge() {

        }

    }

    #[derive(Debug)]
    pub struct VertexProxy {
        id: i64,
        v: *mut Box<Vertex>,
    }

    //let i: u32 = 1;
    //// explicit cast
    //let p_imm: *const u32 = &i as *const u32;
    //let mut m: u32 = 2;
    //// implicit coercion
    //let p_mut: *mut u32 = &mut m;
    //
    //unsafe {
    //let ref_imm: &u32 = &*p_imm;
    //let ref_mut: &mut u32 = &mut *p_mut;
    //}

    impl VertexProxy {
        pub fn add_edge(&mut self, to_vertex: &mut VertexProxy) {
            let in_vertex: &mut Box<Vertex>;
            let out_vertex: &mut Box<Vertex>;

            unsafe {
                in_vertex =  &mut *(self.v);
                out_vertex = &mut *(to_vertex.v);
            }

            // create the edge
            let mut e = Edge{from_vertex: self.v, to_vertex: to_vertex.v};
            in_vertex.add_out_edge(e);
        }
        pub fn query(self) {

        }
    }

    /*
    impl<T> Deref for DerefExample<T> {
        type Target = T;

        fn deref<'a>(&'a self) -> &'a T {
            &self.value
        }
    }
     */

    #[derive(Debug)]
    struct Edge {
        from_vertex: *const Box<Vertex>,
        to_vertex: *const Box<Vertex>
    }

    #[test]
    fn test_unsafe_vertex() {
        let mut g = Graph::new();
        let v1 = g.add_vertex();
        assert!(v1.id == 1);

        let v2 = g.add_vertex();
        assert!(v2.id == 2);
    }

    #[test]
    fn test_add_edge() {
        let mut g = Graph::new();
        let mut v1 = g.add_vertex();
        let mut v2 = g.add_vertex();

        v1.add_edge(&mut v2);

    }

}
<|endoftext|>


<commit_before>#![feature(core)]
extern crate core;
use core::fmt::Debug;

pub struct Expectation<Lhs: Debug> {
    to: To<Lhs>
}

pub struct To<Lhs: Debug>(Lhs);

impl<Lhs: Debug> To<Lhs> {
    fn be<T: Debug>(&self, rhs: T) -> &Self where Lhs: PartialEq<T> {
        self.equal(rhs)
    }

    fn equal<T: Debug>(&self, rhs: T) -> &Self where Lhs: PartialEq<T> {
        if self.0 != rhs {
            panic!("expected {:?} to equal {:?}", self.0, rhs);
        }
        &self
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation {
        to: To(lhs)
    }
}

mod test {
    #[test]
    fn test_expect_equal_int_to_pass() {
        super::expect(1).to.equal(1);
    }

    #[test]
    fn test_expect_be_int_to_pass() {
        super::expect(1).to.be(1);
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equal_int_to_fail() {
        super::expect(1).to.equal(2);
    }

    #[test]
    fn test_struct_cmp() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        super::expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to.equal(Foo{ a: 10u16, b: "Hello".to_string()});
    }
}
<commit_msg>Change to hamcrest-y style<commit_after>#![feature(core)]
extern crate core;
use core::fmt::Debug;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs: Debug> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

#[cfg(test)]
mod test {
    use super::{expect, equal};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }
}
<|endoftext|>


<commit_before>extern crate libloading;
#[macro_use]
extern crate lazy_static;

#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
pub mod ffi;

use std::os::raw::{c_char};
use std::ffi::{CString, CStr};
use std::ptr;
use std::mem;
use libloading::Library;

use ffi::{
    IVRCompositor,
    IVRSystem,
    IVRChaperone,
    IVRRenderModels,
    IVRCompositor_FnTable,
    IVRSystem_FnTable,
    // IVRChaperone_FnTable,
};

pub use ffi::{
    Texture,
    TextureID,
    TrackedDevicePose,
    HmdMatrix34,
    HmdMatrix44,
    EVREye as Eye,
    EVRInitError as InitError,
    EVRApplicationType as ApplicationType,
    EGraphicsAPIConvention as GraphicsAPIConvention,
    EVRSubmitFlags as SubmitFlags,
    EVRCompositorError as CompositorError,
    ETrackingUniverseOrigin as TrackingUniverseOrigin,
    EColorSpace as ColorSpace,
    VRTextureBounds as TextureBounds,
    ETrackedDeviceClass as TrackedDeviceClass,
    ETrackedControllerRole as TrackedControllerRole,
    EVRRenderModelError as RenderModelError,
    k_unMaxTrackedDeviceCount as MAX_TRACKED_DEVICE_COUNT
};

#[allow(non_snake_case)]
#[allow(dead_code)]
struct ApiFunctions {
    VR_InitInternal:            extern fn (peError: *mut InitError, eType: ApplicationType) -> usize,
    VR_ShutdownInternal:        extern fn (),
    VR_IsHmdPresent:            extern fn () -> ::std::os::raw::c_char,
    VR_GetStringForHmdError:    extern fn (error: InitError) -> *mut ::std::os::raw::c_char,
    VR_GetGenericInterface:     extern fn (pchInterfaceVersion: *const ::std::os::raw::c_char, peError: *mut InitError) -> usize,
    VR_IsRuntimeInstalled:      extern fn () -> ::std::os::raw::c_char,
    VR_GetVRInitErrorAsSymbol:  extern fn (error: InitError) -> *const ::std::os::raw::c_char,
    VR_GetVRInitErrorAsEnglishDescription:  extern fn (error: InitError) -> *const ::std::os::raw::c_char,
    lib: Library,
}

unsafe impl Sync for ApiFunctions {}

lazy_static! {
    static ref API: ApiFunctions = {
        let lib = Library::new("openvr_api.dll").unwrap();

        unsafe {
            ApiFunctions {
                VR_InitInternal:            *lib.get(b"VR_InitInternal\0").unwrap(),
                VR_ShutdownInternal:        *lib.get(b"VR_ShutdownInternal\0").unwrap(),
                VR_IsHmdPresent:            *lib.get(b"VR_IsHmdPresent\0").unwrap(),
                VR_GetStringForHmdError:    *lib.get(b"VR_GetStringForHmdError\0").unwrap(),
                VR_GetGenericInterface:     *lib.get(b"VR_GetGenericInterface\0").unwrap(),
                VR_IsRuntimeInstalled:      *lib.get(b"VR_IsRuntimeInstalled\0").unwrap(),
                VR_GetVRInitErrorAsSymbol:  *lib.get(b"VR_GetVRInitErrorAsSymbol\0").unwrap(),
                VR_GetVRInitErrorAsEnglishDescription: *lib.get(b"VR_GetVRInitErrorAsEnglishDescription\0").unwrap(),
                lib: lib,
            }
        }
    };
}

pub struct VRCompositor {
    i: *mut IVRCompositor
}

impl VRCompositor {
    fn new(vr_compositor: *mut IVRCompositor) -> Self {
        assert!(vr_compositor as *const _ != ptr::null());
        VRCompositor {
            i:  vr_compositor
        }
    }

    /// Updated scene texture to display. If bounds is NULL the entire texture will be used.
    /// https://github.com/ValveSoftware/openvr/wiki/IVRCompositor::Submit
    pub fn submit(
        &mut self,
        eye:            Eye,
        texture:        *mut Texture,
        bounds:         *mut TextureBounds,
        submit_flags:   SubmitFlags
    ) -> CompositorError {
        unsafe {
            ((*self.i).Submit)(eye, texture, bounds, submit_flags)
        }
    }

    /// Returns pose(s) to use to render scene.
    /// https://github.com/ValveSoftware/openvr/wiki/IVRCompositor::WaitGetPoses
    pub fn wait_get_poses(
        &mut self,
    ) -> [TrackedDevicePose; ffi::k_unMaxTrackedDeviceCount as usize] {
        unsafe {
            let mut render_poses = [TrackedDevicePose::default(); ffi::k_unMaxTrackedDeviceCount as usize];
            ((*self.i).WaitGetPoses)(
                (&mut render_poses[..]).as_mut_ptr(),
                render_poses.len() as u32,
                std::ptr::null_mut(),
                0
            );

            render_poses
        }
    }
}

pub struct VRChaperone {
    _i: *mut IVRChaperone
}

pub struct RenderModel {
}

pub struct VRRenderModels {
    i: *mut IVRRenderModels
}

impl VRRenderModels {
    pub fn load_render_model_async(
        &mut self,
        render_model_name: *const c_char
    ) -> Result<ffi::RenderModel, RenderModelError> {
        unsafe {
            let render_model: *mut *mut ffi::RenderModel = mem::zeroed();
            let error = ((*self.i).LoadRenderModel_Async)(render_model_name, render_model);
            if error == RenderModelError::None {
                Ok(**render_model)
            } else {
                Err(error)
            }
        }
    }

    pub fn free_render_model(&mut self, render_model: &mut ffi::RenderModel) {
        unsafe {
            ((*self.i).FreeRenderModel)(render_model)
        }
    }

    pub fn load_texture_async(
        &mut self,
        texture_id: TextureID
    ) -> Result<ffi::RenderModel_TextureMap, RenderModelError> {
        unsafe {
            let texture: *mut *mut ffi::RenderModel_TextureMap = mem::zeroed();
            let error = ((*self.i).LoadTexture_Async)(texture_id, texture);
            if error == RenderModelError::None {
                Ok(**texture)
            } else {
                Err(error)
            }
        }
    }

    pub fn free_texture(&mut self, texture: &mut ffi::RenderModel_TextureMap) {
        unsafe {
            ((*self.i).FreeTexture)(texture)
        }
    }
}

pub struct VRSystem {
    i: *mut IVRSystem
}

impl VRSystem {
    fn new(vr_system: *mut IVRSystem) -> Self {
        assert!(vr_system as *const _ != ptr::null());
        VRSystem {
            i:  vr_system
        }
    }

    /// Provides the game with the minimum size that it should use for its offscreen render
    /// target to minimize pixel stretching. This size is matched with the projection matrix
    // and distortion function and will change from display to display depending on resolution,
    // distortion, and field of view.
    pub fn get_recommended_render_target_size(&self) -> (u32, u32) {
        unsafe {
            let mut width = 0;
            let mut height = 0;
            ((*self.i).GetRecommendedRenderTargetSize)(&mut width, &mut height);
            (width, height)
        }
    }

    /// Returns the projection matrix to use for the specified eye.
    pub fn get_projection_matrix(
        &self,
        eye:                Eye,
        near_z:             f32,
        far_z:              f32,
        api:                GraphicsAPIConvention
    ) -> HmdMatrix44 {
        unsafe {
            ((*self.i).GetProjectionMatrix)(
                eye,
                near_z,
                far_z,
                api
            )
        }
    }

    /// Returns the transform between the view space and eye space.
    pub fn get_eye_to_head_transform(&self, eye: Eye) -> HmdMatrix34 {
        unsafe {
            ((*self.i).GetEyeToHeadTransform)(eye)
        }
    }

    /// Calculates updated poses for all devices.
    /// https://github.com/ValveSoftware/openvr/wiki/IVRSystem::GetDeviceToAbsoluteTrackingPose
    pub fn get_device_to_absolute_tracking_pose(
        &self,
        origin: TrackingUniverseOrigin,
        predicted_seconds_to_photons_from_now:  f32,
        tracked_device_pose_array: &mut [TrackedDevicePose]
    ) {
        unsafe {
            ((*self.i).GetDeviceToAbsoluteTrackingPose)(
                origin,
                predicted_seconds_to_photons_from_now,
                tracked_device_pose_array.as_mut_ptr(),
                tracked_device_pose_array.len() as u32
            )
        }
    }

    pub fn reset_seated_zero_pose(&self) {
        unsafe {
            ((*self.i).ResetSeatedZeroPose)()
        }
    }

    pub fn get_tracked_device_class(&self, device_index: usize) -> TrackedDeviceClass {
        unsafe {
            ((*self.i).GetTrackedDeviceClass)(device_index as ffi::TrackedDeviceIndex)
        }
    }

    pub fn get_controller_role_for_tracked_device_index(&self, device_index: usize) -> TrackedControllerRole {
        unsafe {
            ((*self.i).GetControllerRoleForTrackedDeviceIndex)(device_index as ffi::TrackedDeviceIndex)
        }
    }
}

impl std::fmt::Display for InitError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        unsafe {
            let err = CStr::from_ptr((API.VR_GetVRInitErrorAsEnglishDescription)(*self));
            write!(f, "{}", err.to_string_lossy())
        }
    }
}

impl std::error::Error for InitError {
    fn description(&self) -> &str {
        "init error"
    }
}

pub struct VRContext {
    pub system:     VRSystem,
    pub compositor: VRCompositor,

    // chaperone:         VRChaperone,
    // chaperone_setup:    IVRChaperoneSetup,
    // overlay:            IVROverlay,
    // render_models:      IVRRenderModels,
    // IVRExtendedDisplay: *mut IVRExtendedDisplay,
    // IVRSettings: *mut IVRSettings,
    // IVRApplications: *mut IVRApplications,
}

impl Drop for VRContext {
    fn drop(&mut self) {
        // VR_ShutdownInternal();
    }
}

pub fn initialize() -> Result<VRContext, InitError> {
    let mut err = InitError::None;
    let _hmd = (API.VR_InitInternal)(&mut err, ApplicationType::VRApplication_Scene);
    if err != InitError::None {
        Err(err)
    } else {

        let system = (API.VR_GetGenericInterface)(CString::new(IVRSystem_FnTable).unwrap().as_ptr(), &mut err) as *mut IVRSystem;
        if err != InitError::None {
            return Err(err);
        }
        let system = VRSystem::new(system);

        let compositor = (API.VR_GetGenericInterface)(CString::new(IVRCompositor_FnTable).unwrap().as_ptr(), &mut err) as *mut IVRCompositor;
        if err != InitError::None {
            return Err(err);
        }
        let compositor = VRCompositor::new(compositor);

        Ok(VRContext {
            system:     system,
            compositor: compositor
        })
    }
}

/// Returns true if the system believes that an HMD is present on the system.
pub fn is_hmd_present() -> bool {
    (API.VR_IsHmdPresent)() != 0
}

/// Returns true if the SteamVR runtime is installed.
pub fn is_runtime_installed() -> bool {
    (API.VR_IsRuntimeInstalled)() != 0
}

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

    #[test]
    fn runtime_installed() {
        assert!(is_runtime_installed());
    }

    #[test]
    fn hmd_present() {
        assert!(is_hmd_present());
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::error::Error;

    #[test]
    fn vr_init() {
        // NOTE: initializing seems to fail if a window has not been created

        // match init() {
        //     Err(err) => {
        //         println!("init failed: {} - {}", err, err.description());
        //         assert!(false);
        //     }
        //     Ok(context) => {
        //         context.system.get_recommended_render_target_size();
        //     }
        // }
    }
}
<commit_msg>basic controller state<commit_after>extern crate libloading;
#[macro_use]
extern crate lazy_static;

#[allow(non_camel_case_types)]
#[allow(non_snake_case)]
#[allow(non_upper_case_globals)]
pub mod ffi;

use std::os::raw::{c_char};
use std::ffi::{CString, CStr};
use std::ptr;
use std::mem;
use libloading::Library;

use ffi::{
    IVRCompositor,
    IVRSystem,
    IVRChaperone,
    IVRRenderModels,
    IVRCompositor_FnTable,
    IVRSystem_FnTable,
    // IVRChaperone_FnTable,
};

pub use ffi::{
    Texture,
    TextureID,
    TrackedDevicePose,
    HmdMatrix34,
    HmdMatrix44,
    EVREye as Eye,
    EVRInitError as InitError,
    EVRApplicationType as ApplicationType,
    EGraphicsAPIConvention as GraphicsAPIConvention,
    EVRSubmitFlags as SubmitFlags,
    EVRCompositorError as CompositorError,
    ETrackingUniverseOrigin as TrackingUniverseOrigin,
    EColorSpace as ColorSpace,
    VRTextureBounds as TextureBounds,
    ETrackedDeviceClass as TrackedDeviceClass,
    ETrackedControllerRole as TrackedControllerRole,
    EVRRenderModelError as RenderModelError,
    EVRControllerAxisType as ControllerAxisType,
    VRControllerState as ControllerState,
    k_unMaxTrackedDeviceCount as MAX_TRACKED_DEVICE_COUNT
};

#[allow(non_snake_case)]
#[allow(dead_code)]
struct ApiFunctions {
    VR_InitInternal:            extern fn (peError: *mut InitError, eType: ApplicationType) -> usize,
    VR_ShutdownInternal:        extern fn (),
    VR_IsHmdPresent:            extern fn () -> ::std::os::raw::c_char,
    VR_GetStringForHmdError:    extern fn (error: InitError) -> *mut ::std::os::raw::c_char,
    VR_GetGenericInterface:     extern fn (pchInterfaceVersion: *const ::std::os::raw::c_char, peError: *mut InitError) -> usize,
    VR_IsRuntimeInstalled:      extern fn () -> ::std::os::raw::c_char,
    VR_GetVRInitErrorAsSymbol:  extern fn (error: InitError) -> *const ::std::os::raw::c_char,
    VR_GetVRInitErrorAsEnglishDescription:  extern fn (error: InitError) -> *const ::std::os::raw::c_char,
    lib: Library,
}

unsafe impl Sync for ApiFunctions {}

lazy_static! {
    static ref API: ApiFunctions = {
        let lib = Library::new("openvr_api.dll").unwrap();

        unsafe {
            ApiFunctions {
                VR_InitInternal:            *lib.get(b"VR_InitInternal\0").unwrap(),
                VR_ShutdownInternal:        *lib.get(b"VR_ShutdownInternal\0").unwrap(),
                VR_IsHmdPresent:            *lib.get(b"VR_IsHmdPresent\0").unwrap(),
                VR_GetStringForHmdError:    *lib.get(b"VR_GetStringForHmdError\0").unwrap(),
                VR_GetGenericInterface:     *lib.get(b"VR_GetGenericInterface\0").unwrap(),
                VR_IsRuntimeInstalled:      *lib.get(b"VR_IsRuntimeInstalled\0").unwrap(),
                VR_GetVRInitErrorAsSymbol:  *lib.get(b"VR_GetVRInitErrorAsSymbol\0").unwrap(),
                VR_GetVRInitErrorAsEnglishDescription: *lib.get(b"VR_GetVRInitErrorAsEnglishDescription\0").unwrap(),
                lib: lib,
            }
        }
    };
}

pub struct VRCompositor {
    i: *mut IVRCompositor
}

impl VRCompositor {
    fn new(vr_compositor: *mut IVRCompositor) -> Self {
        assert!(vr_compositor as *const _ != ptr::null());
        VRCompositor {
            i:  vr_compositor
        }
    }

    /// Updated scene texture to display. If bounds is NULL the entire texture will be used.
    /// https://github.com/ValveSoftware/openvr/wiki/IVRCompositor::Submit
    pub fn submit(
        &mut self,
        eye:            Eye,
        texture:        *mut Texture,
        bounds:         *mut TextureBounds,
        submit_flags:   SubmitFlags
    ) -> CompositorError {
        unsafe {
            ((*self.i).Submit)(eye, texture, bounds, submit_flags)
        }
    }

    /// Returns pose(s) to use to render scene.
    /// https://github.com/ValveSoftware/openvr/wiki/IVRCompositor::WaitGetPoses
    pub fn wait_get_poses(
        &mut self,
    ) -> [TrackedDevicePose; ffi::k_unMaxTrackedDeviceCount as usize] {
        unsafe {
            let mut render_poses = [TrackedDevicePose::default(); ffi::k_unMaxTrackedDeviceCount as usize];
            ((*self.i).WaitGetPoses)(
                (&mut render_poses[..]).as_mut_ptr(),
                render_poses.len() as u32,
                std::ptr::null_mut(),
                0
            );

            render_poses
        }
    }
}

pub struct VRChaperone {
    _i: *mut IVRChaperone
}

pub struct RenderModel {
    ptr: *mut ffi::RenderModel
}

pub struct RenderModelTexture {
    ptr: *mut ffi::RenderModel_TextureMap
}

pub struct VRRenderModels {
    i: *mut IVRRenderModels
}

impl VRRenderModels {
    pub fn load_render_model_async(
        &mut self,
        render_model_name: *const c_char
    ) -> Result<RenderModel, RenderModelError> {
        unsafe {
            let render_model: *mut *mut ffi::RenderModel = mem::zeroed();
            let error = ((*self.i).LoadRenderModel_Async)(render_model_name, render_model);
            if error == RenderModelError::None {
                Ok(RenderModel {
                    ptr:    *render_model
                })
            } else {
                Err(error)
            }
        }
    }

    pub fn free_render_model(&mut self, render_model: RenderModel) {
        unsafe {
            ((*self.i).FreeRenderModel)(render_model.ptr)
        }
    }

    pub fn load_texture_async(
        &mut self,
        texture_id: TextureID
    ) -> Result<RenderModelTexture, RenderModelError> {
        unsafe {
            let texture: *mut *mut ffi::RenderModel_TextureMap = mem::zeroed();
            let error = ((*self.i).LoadTexture_Async)(texture_id, texture);
            if error == RenderModelError::None {
                Ok(RenderModelTexture {
                    ptr: *texture
                })
            } else {
                Err(error)
            }
        }
    }

    pub fn free_texture(&mut self, texture: RenderModelTexture) {
        unsafe {
            ((*self.i).FreeTexture)(texture.ptr)
        }
    }
}

pub struct VRSystem {
    i: *mut IVRSystem
}

impl VRSystem {
    fn new(vr_system: *mut IVRSystem) -> Self {
        assert!(vr_system as *const _ != ptr::null());
        VRSystem {
            i:  vr_system
        }
    }

    /// Provides the game with the minimum size that it should use for its offscreen render
    /// target to minimize pixel stretching. This size is matched with the projection matrix
    // and distortion function and will change from display to display depending on resolution,
    // distortion, and field of view.
    pub fn get_recommended_render_target_size(&self) -> (u32, u32) {
        unsafe {
            let mut width = 0;
            let mut height = 0;
            ((*self.i).GetRecommendedRenderTargetSize)(&mut width, &mut height);
            (width, height)
        }
    }

    /// Returns the projection matrix to use for the specified eye.
    pub fn get_projection_matrix(
        &self,
        eye:                Eye,
        near_z:             f32,
        far_z:              f32,
        api:                GraphicsAPIConvention
    ) -> HmdMatrix44 {
        unsafe {
            ((*self.i).GetProjectionMatrix)(
                eye,
                near_z,
                far_z,
                api
            )
        }
    }

    /// Returns the transform between the view space and eye space.
    pub fn get_eye_to_head_transform(&self, eye: Eye) -> HmdMatrix34 {
        unsafe {
            ((*self.i).GetEyeToHeadTransform)(eye)
        }
    }

    /// Calculates updated poses for all devices.
    /// https://github.com/ValveSoftware/openvr/wiki/IVRSystem::GetDeviceToAbsoluteTrackingPose
    pub fn get_device_to_absolute_tracking_pose(
        &self,
        origin: TrackingUniverseOrigin,
        predicted_seconds_to_photons_from_now:  f32,
        tracked_device_pose_array: &mut [TrackedDevicePose]
    ) {
        unsafe {
            ((*self.i).GetDeviceToAbsoluteTrackingPose)(
                origin,
                predicted_seconds_to_photons_from_now,
                tracked_device_pose_array.as_mut_ptr(),
                tracked_device_pose_array.len() as u32
            )
        }
    }

    pub fn reset_seated_zero_pose(&self) {
        unsafe {
            ((*self.i).ResetSeatedZeroPose)()
        }
    }

    pub fn get_tracked_device_class(&self, device_index: usize) -> TrackedDeviceClass {
        unsafe {
            ((*self.i).GetTrackedDeviceClass)(device_index as ffi::TrackedDeviceIndex)
        }
    }

    pub fn get_controller_role_for_tracked_device_index(&self, device_index: usize) -> TrackedControllerRole {
        unsafe {
            ((*self.i).GetControllerRoleForTrackedDeviceIndex)(device_index as ffi::TrackedDeviceIndex)
        }
    }

    pub fn get_controller_state(&self, device_index: usize) -> ControllerState {
        unsafe {
            let mut state = ControllerState::default();
            ((*self.i).GetControllerState)(device_index as ffi::TrackedDeviceIndex, &mut state);
            state
        }
    }
}

impl std::fmt::Display for InitError {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        unsafe {
            let err = CStr::from_ptr((API.VR_GetVRInitErrorAsEnglishDescription)(*self));
            write!(f, "{}", err.to_string_lossy())
        }
    }
}

impl std::error::Error for InitError {
    fn description(&self) -> &str {
        "init error"
    }
}

pub struct VRContext {
    pub system:     VRSystem,
    pub compositor: VRCompositor,

    // chaperone:         VRChaperone,
    // chaperone_setup:    IVRChaperoneSetup,
    // overlay:            IVROverlay,
    // render_models:      IVRRenderModels,
    // IVRExtendedDisplay: *mut IVRExtendedDisplay,
    // IVRSettings: *mut IVRSettings,
    // IVRApplications: *mut IVRApplications,
}

impl Drop for VRContext {
    fn drop(&mut self) {
        // VR_ShutdownInternal();
    }
}

pub fn initialize() -> Result<VRContext, InitError> {
    let mut err = InitError::None;
    let _hmd = (API.VR_InitInternal)(&mut err, ApplicationType::VRApplication_Scene);
    if err != InitError::None {
        Err(err)
    } else {

        let system = (API.VR_GetGenericInterface)(CString::new(IVRSystem_FnTable).unwrap().as_ptr(), &mut err) as *mut IVRSystem;
        if err != InitError::None {
            return Err(err);
        }
        let system = VRSystem::new(system);

        let compositor = (API.VR_GetGenericInterface)(CString::new(IVRCompositor_FnTable).unwrap().as_ptr(), &mut err) as *mut IVRCompositor;
        if err != InitError::None {
            return Err(err);
        }
        let compositor = VRCompositor::new(compositor);

        Ok(VRContext {
            system:     system,
            compositor: compositor
        })
    }
}

/// Returns true if the system believes that an HMD is present on the system.
pub fn is_hmd_present() -> bool {
    (API.VR_IsHmdPresent)() != 0
}

/// Returns true if the SteamVR runtime is installed.
pub fn is_runtime_installed() -> bool {
    (API.VR_IsRuntimeInstalled)() != 0
}

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

    #[test]
    fn runtime_installed() {
        assert!(is_runtime_installed());
    }

    #[test]
    fn hmd_present() {
        assert!(is_hmd_present());
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::error::Error;

    #[test]
    fn vr_init() {
        // NOTE: initializing seems to fail if a window has not been created

        // match init() {
        //     Err(err) => {
        //         println!("init failed: {} - {}", err, err.description());
        //         assert!(false);
        //     }
        //     Ok(context) => {
        //         context.system.get_recommended_render_target_size();
        //     }
        // }
    }
}
<|endoftext|>


<commit_before>use std::collections::VecDeque;
use std::collections::HashSet;

/// A graph is represeted by as a weighted
/// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix)
pub struct Graph {
  /// The underlaying graph represented here with weights as an i32 (should
  /// probably be generic) the graph is represented as an
  /// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix) of
  /// Optionals, where None indicates that there doesn't exist a vertex and
  /// Some<i32> indicates that There is a vertex of weight i32.
  graph: Vec<Vec<Option<i32>>>
}
impl Graph {
  /// `new` allows for initializing the graph struct with a given adjecency matrix
  ///
  /// ## Arguments
  /// * `input` - an adjecency matrix in made out of a two-dimensional `Vec` of
  ///    weights. Weights are represented as `i32`:s and can thus be positive or
  ///    negative numbers.
  ///
  /// ## Example
  /// ```ignore
  ///  let rawgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None],
  ///                      vec![   None,  Some(0),     None,     None,     None,     None],
  ///                      vec![   None,     None,  Some(0),     None,     None,     None],
  ///                      vec![   None,     None,     None,  Some(0), Some(50),     None],
  ///                      vec![   None,     None, Some(20),     None,  Some(0), Some(50)],
  ///                      vec![   None,     None,     None,     None,     None,  Some(0)]];
  /// let g = Graph::new(rawgraph);
  /// ```
  pub fn new(input: Vec<Vec<Option<i32>>>) -> Graph { Graph { graph: input } }

  /// `breadth_first_search` implements breadth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is breadth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn breadth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    return self.inner_search(start, target, true)
  }

  /// `depth_first_search` implements depth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is depth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn depth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    return self.inner_search(start, target, false)
  }

  fn inner_search(&self, start: usize, target: usize, bfs: bool) -> Option<VecDeque<usize>>  {
    let mut q: VecDeque<usize> = VecDeque::new();
    let mut discovered: HashSet<usize> = HashSet::new();
    let mut prev: Vec<usize> = Vec::with_capacity(self.graph.len());
    let mut pathfound = false;
    for _ in (0..self.graph.len()) { prev.push(0); }

    q.push_back(start);
    discovered.insert(start);

    while !q.is_empty() {
      let mut v: Option<usize>;
      if bfs {
        v = q.pop_front()
      } else {
        v = q.pop_back();
      }
      match v {
        None => {}, // q is empty
        Some(v) => { // we are working on a new layer
          if !discovered.contains(&v) { discovered.insert(v); }
          if v == target { pathfound = true; }
          for i in (0..self.graph[v].len()) {
            match self.graph[v][i] {
              None => {}, // no vertex between v and i
              Some(_) => {
                if !discovered.contains(&i) {
                  q.push_back(i);
                  prev[i]=v; //track prev (v) on i
                }
              }
            }
          }
        }
      }
    }
    if pathfound {
      let mut path: VecDeque<usize> = VecDeque::new();
      let mut curr = target;
      // backtrack over the prev array to construct the path
      while curr != start {
        path.push_front(curr);
        curr = prev[curr];
      }
      path.push_front(start);
      return Some(path)
    }
    return None
  }
}

#[test]
fn breadth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);
  match res {
    None => {
      println!("Breadth first search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Breadth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn breadth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("Breadth first search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Breadth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}

#[test]
fn depth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.depth_first_search(start, target);
  match res {
    None => {
      println!("Depth first search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Depth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn depth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.depth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("Depth first search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Depth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}
<commit_msg>Added a cost_of_path function which takes a path and returns the cost of it<commit_after>use std::collections::VecDeque;
use std::collections::HashSet;

/// A graph is represeted by as a weighted
/// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix)
pub struct Graph {
  /// The underlaying graph represented here with weights as an i32 (should
  /// probably be generic) the graph is represented as an
  /// [Adjenceny matrix](http://en.wikipedia.org/wiki/Adjacency_matrix) of
  /// Optionals, where None indicates that there doesn't exist a vertex and
  /// Some<i32> indicates that There is a vertex of weight i32.
  graph: Vec<Vec<Option<i32>>>
}
impl Graph {
  /// `new` allows for initializing the graph struct with a given adjecency matrix
  ///
  /// ## Arguments
  /// * `input` - an adjecency matrix in made out of a two-dimensional `Vec` of
  ///    weights. Weights are represented as `i32`:s and can thus be positive or
  ///    negative numbers.
  ///
  /// ## Example
  /// ```ignore
  ///  let rawgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None],
  ///                      vec![   None,  Some(0),     None,     None,     None,     None],
  ///                      vec![   None,     None,  Some(0),     None,     None,     None],
  ///                      vec![   None,     None,     None,  Some(0), Some(50),     None],
  ///                      vec![   None,     None, Some(20),     None,  Some(0), Some(50)],
  ///                      vec![   None,     None,     None,     None,     None,  Some(0)]];
  /// let g = Graph::new(rawgraph);
  /// ```
  pub fn new(input: Vec<Vec<Option<i32>>>) -> Graph { Graph { graph: input } }

  /// `breadth_first_search` implements breadth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is breadth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn breadth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    return self.inner_search(start, target, true)
  }

  /// `depth_first_search` implements depth first search from `start` to the
  /// `target` and returns the path found as a `VecDeque<usize>` of nodes. This
  /// is an optional type as there might not be a path.
  ///
  /// **NOTE** as this is depth first search this search ignores any assigned
  /// weight to nodes.
  ///
  /// ## Arguments
  /// * `start`  - an `usize` designating the start node, or row in the adjecency matrix
  /// * `target` - an `usize` designating the target node, or row in the adjecency matrix
  ///
  /// ## Returns
  /// Either the found path between start and target as a `VecDeque` of `usize`:s
  /// or `None` if there is no path.
  pub fn depth_first_search(&self, start: usize, target: usize) -> Option<VecDeque<usize>> {
    return self.inner_search(start, target, false)
  }

  fn inner_search(&self, start: usize, target: usize, bfs: bool) -> Option<VecDeque<usize>>  {
    let mut q: VecDeque<usize> = VecDeque::new();
    let mut discovered: HashSet<usize> = HashSet::new();
    let mut prev: Vec<usize> = Vec::with_capacity(self.graph.len());
    let mut pathfound = false;
    for _ in (0..self.graph.len()) { prev.push(0); }

    q.push_back(start);
    discovered.insert(start);

    while !q.is_empty() {
      let mut v: Option<usize>;
      if bfs {
        v = q.pop_front()
      } else {
        v = q.pop_back();
      }
      match v {
        None => {}, // q is empty
        Some(v) => { // we are working on a new layer
          if !discovered.contains(&v) { discovered.insert(v); }
          if v == target { pathfound = true; }
          for i in (0..self.graph[v].len()) {
            match self.graph[v][i] {
              None => {}, // no vertex between v and i
              Some(_) => {
                if !discovered.contains(&i) {
                  q.push_back(i);
                  prev[i]=v; //track prev (v) on i
                }
              }
            }
          }
        }
      }
    }
    if pathfound {
      let mut path: VecDeque<usize> = VecDeque::new();
      let mut curr = target;
      // backtrack over the prev array to construct the path
      while curr != start {
        path.push_front(curr);
        curr = prev[curr];
      }
      path.push_front(start);
      return Some(path)
    }
    return None
  }

  pub fn cost_of_path(&self, path: VecDeque<usize>) -> i32 {
    let mut cost = 0;
    for i in (0..path.len()-1) {
      match self.graph[path[i]][path[i+1]] {
        None => {},
        Some(c) => { cost = cost + c; }
      }
    }
    return cost
  }
}

#[test]
fn breadth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);
  match res {
    None => {
      println!("Breadth first search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Breadth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn breadth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.breadth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("Breadth first search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Breadth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}

#[test]
fn depth_first_search_test() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0), Some(50),  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 6;
  let g = Graph::new(testgraph);
  let res = g.depth_first_search(start, target);
  match res {
    None => {
      println!("Depth first search returned None");
      assert!(false);
    }
    Some(result) => {
      println!("Depth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
    }
  }
}

#[test]
fn depth_first_search_test_no_valid_path() {
  let testgraph = vec![vec![Some(0), Some(20), Some(80), Some(50),     None,     None, None],
                       vec![   None,  Some(0),     None,     None,     None,     None, None],
                       vec![   None,     None,  Some(0),     None,     None,     None,  Some(50)],
                       vec![   None,     None,     None,  Some(0), Some(50),     None, None],
                       vec![   None,     None, Some(20),     None,  Some(0),     None,  Some(40)],
                       vec![   None,     None,     None,     None,     None,  Some(0), None],
                       vec![   None,     None,     None,     None,     None,     None, Some(0)]];
  let start: usize = 0;
  let target: usize = 5; // There is no valid path between 0 and 5
  let g = Graph::new(testgraph);
  let res = g.depth_first_search(start, target);

  // The expected return value is None
  match res {
    None => {
      println!("Depth first search returned None");
      assert!(true);
    }
    Some(result) => {
      println!("Depth first search returned something: {:?}", result);
      assert_eq!(result[result.len()-1], target);
      assert_eq!(result[0], start);
      assert!(false);
    }
  }
}
<|endoftext|>


<commit_before>extern crate petgraph;

// XXX: Self-loops?

use petgraph::{Graph, Directed};
use petgraph::graph::{NodeIndex, IndexType};
use std::collections::HashSet;
use std::hash::Hash;

#[repr(u8)]
#[derive(Debug)]
pub enum TriadType {
    T003 = 0,
    T012,
    T102,
    T021D,

    T021U,
    T021C,
    T111D,
    T111U,

    T030T,
    T030C,
    T201,
    T120D,

    T120U,
    T120C,
    T210,
    T300
}

impl TriadType {
    #[inline(always)]
    fn from_u8(i: u8) -> TriadType {
        use std::mem;
        assert!(i < 16);
        unsafe { mem::transmute(i) }
    }
}

fn tricode<N, E, I: IndexType>(graph: &Graph<N, E, Directed, I>, v: NodeIndex<I>, u: NodeIndex<I>, w: NodeIndex<I>) -> usize {
    let mut tricode = 0;
    if let Some(_) = graph.find_edge(v, u) { tricode |= 1 << 0; }
    if let Some(_) = graph.find_edge(u, v) { tricode |= 1 << 1; }
    if let Some(_) = graph.find_edge(v, w) { tricode |= 1 << 2; }
    if let Some(_) = graph.find_edge(w, v) { tricode |= 1 << 3; }
    if let Some(_) = graph.find_edge(u, w) { tricode |= 1 << 4; }
    if let Some(_) = graph.find_edge(w, u) { tricode |= 1 << 5; }
    return tricode;
}

const TRITYPES: [u8;64] = [0, 1, 1, 2, 1, 3, 5, 7, 1, 5, 4, 6, 2, 7, 6, 10,
                           1, 5, 3, 7, 4, 8, 8, 12, 5, 9, 8, 13, 6, 13, 11, 14,
                           1, 4, 5, 6, 5, 8, 9, 13, 3, 8, 8, 11, 7, 12, 13, 14,
                           2, 6, 7, 10, 6, 11, 13, 14, 7, 13, 12, 14, 10, 14, 14, 15];

#[derive(Debug)]
pub struct TriadicCensus {
    census: [u64; 16],
}

impl TriadicCensus {
    /// Calculates the `distance` between two TriadicCensus structs, treated as
    /// points in a 16-dimensional space.
    pub fn distance(a: &TriadicCensus, b: &TriadicCensus) -> f64 {
        let mut sum = 0.0f64;
        for i in 0..16 {
            let va = a.census[i];
            let vb = b.census[i];
            let diff = (if va > vb { va - vb } else { vb - va }) as f64;
            sum += diff * diff;
        }
        sum.sqrt()
    }

    #[inline(always)]
    fn new() -> TriadicCensus {
        TriadicCensus{census: [0;16]}
    }

    #[inline(always)]
    fn add(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] += cnt;
    }

    #[inline(always)]
    fn set(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] = cnt;
    }

    #[inline(always)]
    pub fn get(&self, triad_type: TriadType) -> u64 {
        self.census[triad_type as usize]
    }

    #[inline(always)]
    pub fn as_slice<'a>(&'a self) -> &'a[u64] {
        &self.census[..]
    }

    pub fn from_graph<N, E, I: IndexType+Hash>(graph: &Graph<N, E, Directed, I>) -> TriadicCensus {
        let n = graph.node_count();

        let mut census = TriadicCensus::new();

        for i in 0..n {
            let v = NodeIndex::new(i);

            let mut neighbors_v = HashSet::new();
            for u in graph.neighbors_undirected(v) {
                if v < u {
                    neighbors_v.insert(u);
                }
            }

            for u in neighbors_v {
                let mut s = HashSet::new();
                for nu in graph.neighbors_undirected(u) { s.insert(nu); }
                for nv in graph.neighbors_undirected(v) { s.insert(nv); }
                let _ = s.remove(&u);
                let _ = s.remove(&v);

                let tri_type =
                    if graph.find_edge(v, u).is_some() && graph.find_edge(u, v).is_some() {
                        TriadType::T102
                    } else {
                        TriadType::T012
                    };

                let cnt = n as i64 - s.len() as i64 - 2;
                assert!(cnt >= 0);
                census.add(tri_type, cnt as u64);
                for w in s {
                    if u < w || (v < w && w < u && !(graph.find_edge(v, w).is_some() || graph.find_edge(w, v).is_some())) {
                       let tri_type = TriadType::from_u8(TRITYPES[tricode(graph, v, u, w)]);
                       census.add(tri_type, 1);
                    }
                }
            }
        }

        let mut sum = 0;
        for &cnt in &census.as_slice()[1..] {
            sum += cnt;
        }
        let n = n as u64;
        // Integer division below is guaranteed to produce an integral result
        census.set(TriadType::T003, (n * (n - 1) * (n - 2)) / 6 - sum);
        return census;
    }
}

#[test]
fn test_simple() {
    let mut g: Graph<(),()> = Graph::new();

    let n1 = g.add_node(());
    let n2 = g.add_node(());
    let n3 = g.add_node(());

    let c1 = TriadicCensus::from_graph(&g);
    assert_eq!(&[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c1.as_slice());

    g.add_edge(n1, n3, ());
    let c2 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c2.as_slice());

    let d = TriadicCensus::distance(&c1, &c2); // should be sqrt(2)
    assert!(d > 1.414 && d < 1.415);

    g.add_edge(n3, n1, ());
    let c3 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0], c3.as_slice());

    g.add_edge(n2, n3, ());
    let c4 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0], c4.as_slice());
}
<commit_msg>Add more tests<commit_after>extern crate petgraph;

// XXX: Self-loops?

use petgraph::{Graph, Directed};
use petgraph::graph::{NodeIndex, IndexType};
use std::collections::HashSet;
use std::hash::Hash;

#[repr(u8)]
#[derive(Debug)]
pub enum TriadType {
    T003 = 0,
    T012,
    T102,
    T021D,

    T021U,
    T021C,
    T111D,
    T111U,

    T030T,
    T030C,
    T201,
    T120D,

    T120U,
    T120C,
    T210,
    T300
}

impl TriadType {
    #[inline(always)]
    fn from_u8(i: u8) -> TriadType {
        use std::mem;
        assert!(i < 16);
        unsafe { mem::transmute(i) }
    }
}

fn tricode<N, E, I: IndexType>(graph: &Graph<N, E, Directed, I>, v: NodeIndex<I>, u: NodeIndex<I>, w: NodeIndex<I>) -> usize {
    let mut tricode = 0;
    if let Some(_) = graph.find_edge(v, u) { tricode |= 1 << 0; }
    if let Some(_) = graph.find_edge(u, v) { tricode |= 1 << 1; }
    if let Some(_) = graph.find_edge(v, w) { tricode |= 1 << 2; }
    if let Some(_) = graph.find_edge(w, v) { tricode |= 1 << 3; }
    if let Some(_) = graph.find_edge(u, w) { tricode |= 1 << 4; }
    if let Some(_) = graph.find_edge(w, u) { tricode |= 1 << 5; }
    return tricode;
}

const TRITYPES: [u8;64] = [0, 1, 1, 2, 1, 3, 5, 7, 1, 5, 4, 6, 2, 7, 6, 10,
                           1, 5, 3, 7, 4, 8, 8, 12, 5, 9, 8, 13, 6, 13, 11, 14,
                           1, 4, 5, 6, 5, 8, 9, 13, 3, 8, 8, 11, 7, 12, 13, 14,
                           2, 6, 7, 10, 6, 11, 13, 14, 7, 13, 12, 14, 10, 14, 14, 15];

#[derive(Debug)]
pub struct TriadicCensus {
    census: [u64; 16],
}

impl TriadicCensus {
    /// Calculates the `distance` between two TriadicCensus structs, treated as
    /// points in a 16-dimensional space.
    pub fn distance(a: &TriadicCensus, b: &TriadicCensus) -> f64 {
        let mut sum = 0.0f64;
        for i in 0..16 {
            let va = a.census[i];
            let vb = b.census[i];
            let diff = (if va > vb { va - vb } else { vb - va }) as f64;
            sum += diff * diff;
        }
        sum.sqrt()
    }

    #[inline(always)]
    fn new() -> TriadicCensus {
        TriadicCensus{census: [0;16]}
    }

    #[inline(always)]
    fn add(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] += cnt;
    }

    #[inline(always)]
    fn set(&mut self, triad_type: TriadType, cnt: u64) {
        self.census[triad_type as usize] = cnt;
    }

    #[inline(always)]
    pub fn get(&self, triad_type: TriadType) -> u64 {
        self.census[triad_type as usize]
    }

    #[inline(always)]
    pub fn as_slice<'a>(&'a self) -> &'a[u64] {
        &self.census[..]
    }

    /// XXX: Optimize: find_edge() is O(k) with k the number of edges.
    pub fn from_graph<N, E, I: IndexType+Hash>(graph: &Graph<N, E, Directed, I>) -> TriadicCensus {
        let n = graph.node_count();

        let mut census = TriadicCensus::new();

        for i in 0..n {
            let v = NodeIndex::new(i);

            let mut neighbors_v = HashSet::new();
            for u in graph.neighbors_undirected(v) {
                if v < u {
                    neighbors_v.insert(u);
                }
            }

            for u in neighbors_v {
                let mut s = HashSet::new();
                for nu in graph.neighbors_undirected(u) { s.insert(nu); }
                for nv in graph.neighbors_undirected(v) { s.insert(nv); }
                let _ = s.remove(&u);
                let _ = s.remove(&v);

                let tri_type =
                    if graph.find_edge(v, u).is_some() && graph.find_edge(u, v).is_some() {
                        TriadType::T102
                    } else {
                        TriadType::T012
                    };

                let cnt = n as i64 - s.len() as i64 - 2;
                assert!(cnt >= 0);
                census.add(tri_type, cnt as u64);
                for w in s {
                    if u < w || (v < w && w < u && !(graph.find_edge(v, w).is_some() || graph.find_edge(w, v).is_some())) {
                       let tri_type = TriadType::from_u8(TRITYPES[tricode(graph, v, u, w)]);
                       census.add(tri_type, 1);
                    }
                }
            }
        }

        let mut sum = 0;
        for &cnt in &census.as_slice()[1..] {
            sum += cnt;
        }
        let n = n as u64;
        // Integer division below is guaranteed to produce an integral result
        census.set(TriadType::T003, (n * (n - 1) * (n - 2)) / 6 - sum);
        return census;
    }
}

#[test]
fn test_simple() {
    let mut g: Graph<(),()> = Graph::new();

    let n1 = g.add_node(());
    let n2 = g.add_node(());
    let n3 = g.add_node(());

    let c1 = TriadicCensus::from_graph(&g);
    assert_eq!(&[1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c1.as_slice());

    g.add_edge(n1, n3, ());
    let c2 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0], c2.as_slice());

    let d = TriadicCensus::distance(&c1, &c2); // should be sqrt(2)
    assert!(d > 1.414 && d < 1.415);

    g.add_edge(n3, n1, ());
    let c3 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0], c3.as_slice());

    g.add_edge(n2, n3, ());
    let c4 = TriadicCensus::from_graph(&g);
    assert_eq!(&[0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0], c4.as_slice());
}

#[cfg(test)]
fn line_graph(n: u32) -> Graph<(),(), Directed> {
    let mut g: Graph<(),(), Directed> = Graph::new();

    let mut prev = g.add_node(());
    for _ in 0..n-1 {
        let cur = g.add_node(());
        g.add_edge(prev, cur, ());
        prev = cur;
    }
    return g;
}

#[cfg(test)]
fn circular_graph(n: u32) -> Graph<(),(), Directed> {
    let mut g: Graph<(),(), Directed> = Graph::new();

    let first = g.add_node(());
    let mut prev = first;
    for _ in 0..n-1 {
        let cur = g.add_node(());
        g.add_edge(prev, cur, ());
        prev = cur;
    }
    g.add_edge(prev, first, ());
    return g;
}

#[test]
fn test_line_graph() {
    // Result compared with igraph.triad_census().
    let c = TriadicCensus::from_graph(&line_graph(20));
    assert_eq!(&[816,306,0,0,0,18,0,0,0,0,0,0,0,0,0,0], c.as_slice());

    let c = TriadicCensus::from_graph(&line_graph(40));
    assert_eq!(&[8436,1406,0,0,0,38,0,0,0,0,0,0,0,0,0,0], c.as_slice());
}

#[test]
fn test_circular_graph() {
    // Result compared with igraph.triad_census().
    let c = TriadicCensus::from_graph(&circular_graph(20));
    assert_eq!(&[800,320,0,0,0,20,0,0,0,0,0,0,0,0,0,0], c.as_slice());

    let c = TriadicCensus::from_graph(&circular_graph(40));
    assert_eq!(&[8400,1440,0,0,0,40,0,0,0,0,0,0,0,0,0,0], c.as_slice());

}
<|endoftext|>


<commit_before>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::slice::Iter;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub trait WithLen {
    fn match_len(&self) -> usize;
}

impl<T> WithLen for Vec<T> {
    fn match_len(&self) -> usize { self.len() }
}

impl WithLen for String {
    fn match_len(&self) -> usize { self.chars().count() }
}

impl<'a> WithLen for &'a str {
    fn match_len(&self) -> usize { self.chars().count() }
}

pub trait WithIter<T> {
    fn match_iter(&self) -> Iter<T>;
}

impl<T> WithIter<T> for Vec<T> {
    fn match_iter(&self) -> Iter<T> { self.iter() }
}

pub struct Contains<T>(T);

impl<T: Debug + PartialEq, Lhs: Debug + WithIter<T>> Matcher<Lhs> for Contains<T> {
    fn matches(&self, lhs: &Lhs) -> bool {
        lhs.match_iter().any(|i| *i == self.0)
    }

    fn fail_msg(&self, lhs: &Lhs) -> String {
        format!("expected {:?} to contain {:?}", lhs, self.0)
    }
}

pub struct Empty;

impl<Lhs: Debug + WithLen> Matcher<Lhs> for Empty {
    fn matches(&self, rhs: &Lhs) -> bool {
        rhs.match_len() == 0
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to be empty", rhs)
    }
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: T) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

pub fn empty() -> Empty {
    Empty
}

pub fn contain<T: Debug>(rhs: T) -> Contains<T> {
    Contains(rhs)
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not, empty, contain};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }

    #[test]
    fn test_empty() {
        let v: Vec<usize> = Vec::new();
        expect(v).is(empty());
    }

    #[test]
    fn test_not_empty() {
        let v = vec![1, 2, 3];
        expect(v).is(not(empty()));
    }

    #[test]
    fn test_empty_string() {
        expect("".to_string()).is(empty());
    }

    #[test]
    fn test_not_empty_string() {
        expect("not-empty".to_string()).is(not(empty()));
    }

    #[test]
    fn test_empty_str() {
        expect("").is(empty());
    }

    #[test]
    fn test_not_empty_str() {
        expect("not-empty").is(not(empty()));
    }

    #[test]
    fn test_contains() {
        expect(vec![1, 2, 3]).to(contain(1));
    }

    #[test]
    fn test_not_contains() {
        expect(vec![1, 2, 3]).to(not(contain(10)));
    }
}
<commit_msg>Add contains for String with char's<commit_after>#![feature(core)]
extern crate core;
use core::fmt::Debug;
use std::marker::PhantomData;

pub struct Expectation<Lhs: Debug>(Lhs);

pub struct To<Lhs: Debug>(Lhs);

pub trait Matcher<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool;
    fn fail_msg(&self, rhs: &Lhs) -> String;
}

pub trait WithLen {
    fn match_len(&self) -> usize;
}

impl<T> WithLen for Vec<T> {
    fn match_len(&self) -> usize { self.len() }
}

impl WithLen for String {
    fn match_len(&self) -> usize { self.chars().count() }
}

impl<'a> WithLen for &'a str {
    fn match_len(&self) -> usize { self.chars().count() }
}

pub struct Contains<T>(T);

impl<T: Debug + PartialEq> Matcher<Vec<T>> for Contains<T> {
    fn matches(&self, lhs: &Vec<T>) -> bool {
        lhs.iter().any(|i| *i == self.0)
    }

    fn fail_msg(&self, lhs: &Vec<T>) -> String {
        format!("expected {:?} to contain {:?}", lhs, self.0)
    }
}

impl Matcher<String> for Contains<char> {
    fn matches(&self, lhs: &String) -> bool {
        lhs.chars().any(|i| i == self.0)
    }

    fn fail_msg(&self, lhs: &String) -> String {
        format!("expected {:?} to contain {:?}", lhs, self.0)
    }
}

pub struct Empty;

impl<Lhs: Debug + WithLen> Matcher<Lhs> for Empty {
    fn matches(&self, rhs: &Lhs) -> bool {
        rhs.match_len() == 0
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to be empty", rhs)
    }
}

pub struct Equal<Lhs: Debug>(Lhs);

impl<Lhs: Debug + PartialEq> Matcher<Lhs> for Equal<Lhs> {
    fn matches(&self, rhs: &Lhs) -> bool {
        &self.0 == rhs
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("expected {:?} to equal {:?}", rhs, self.0)
    }
}

pub struct Not<A, M>(M, PhantomData<A>) where A: Debug, M: Matcher<A>;

impl<Lhs: Debug, M: Matcher<Lhs>> Matcher<Lhs> for Not<Lhs, M> {
    fn matches(&self, rhs: &Lhs) -> bool {
        !self.0.matches(rhs)
    }

    fn fail_msg(&self, rhs: &Lhs) -> String {
        format!("not {}", self.0.fail_msg(rhs))
    }
}

impl<Lhs: Debug> Expectation<Lhs> {
    pub fn is<T>(&self, matcher: T) where T: Matcher<Lhs> {
        self.to(matcher)
    }

    pub fn to<T>(&self, matcher: T) where T: Matcher<Lhs> {
        if !matcher.matches(&self.0) {
            panic!(matcher.fail_msg(&self.0))
        }
    }
}

pub fn expect<T: Debug>(lhs: T) -> Expectation<T> {
    Expectation(lhs)
}

pub fn equal<T: Debug>(rhs: T) -> Equal<T> {
    Equal(rhs)
}

pub fn not<T: Debug, M: Matcher<T>>(rhs: M) -> Not<T, M> {
    Not(rhs, PhantomData)
}

pub fn empty() -> Empty {
    Empty
}

pub fn contain<T: Debug>(rhs: T) -> Contains<T> {
    Contains(rhs)
}

#[cfg(test)]
mod test {
    use super::{expect, equal, not, empty, contain};

    #[test]
    fn test_expect_equality() {
        expect(1).to(equal(1));
    }

    #[test]
    #[should_panic(expected="expected 1 to equal 2")]
    fn test_expect_not_equality_to_fail() {
        expect(1).to(equal(2));
    }

    #[test]
    fn test_partial_eq_equality() {
        #[derive(PartialEq, Debug)]
        struct Foo { a: u16, b: String }

        expect(Foo{ a: 10u16, b: "Hello".to_string()})
            .to(equal(Foo{ a: 10u16, b: "Hello".to_string()}));
    }

    #[test]
    fn test_invert_equality() {
        expect(1).to(not(equal(2)));
    }

    #[test]
    fn test_invert_invert_equality() {
        expect(1).to(not(not(equal(1))));
    }

    #[test]
    #[should_panic(expected="not expected 1 to equal 1")]
    fn test_invert_equality_equal_to_fail() {
        expect(1).to(not(equal(1)));
    }

    #[test]
    fn test_empty() {
        let v: Vec<usize> = Vec::new();
        expect(v).is(empty());
    }

    #[test]
    fn test_not_empty() {
        let v = vec![1, 2, 3];
        expect(v).is(not(empty()));
    }

    #[test]
    fn test_empty_string() {
        expect("".to_string()).is(empty());
    }

    #[test]
    fn test_not_empty_string() {
        expect("not-empty".to_string()).is(not(empty()));
    }

    #[test]
    fn test_empty_str() {
        expect("").is(empty());
    }

    #[test]
    fn test_not_empty_str() {
        expect("not-empty").is(not(empty()));
    }

    #[test]
    fn test_contains() {
        expect(vec![1, 2, 3]).to(contain(1));
    }

    #[test]
    fn test_not_contains() {
        expect(vec![1, 2, 3]).to(not(contain(10)));
    }

    #[test]
    fn test_contains_string_char() {
        expect("Hello, world!".to_string()).to(contain('H'));
    }

    #[test]
    fn test_not_contains_string_char() {
        expect("Hello, world!".to_string()).to(not(contain('Z')));
    }
}
<|endoftext|>