<commit_before>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, StreamProducer, many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
  output: Vec<i32>,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> io::Result<StreamReader<R>> {
    let producer  = ReadStream::new(reader);
    let error_str = "parser: couldn't parse the reader";

    Stream::from_stream_producer(producer, error_str)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_file(filename: &str) -> io::Result<StreamReader<File>> {
    File::open(filename).and_then(|file| {
      let producer  = ReadStream::new(file);
      let error_str = format!("parser: couldn't parse the given file {}",
                              filename);

      Stream::from_stream_producer(producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> io::Result<StreamBuffer> {
    let producer  = ByteStream::new(buffer);
    let error_str = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(producer, error_str)
  }

  fn from_stream_producer(mut producer: P, error_str: &str)
                          -> io::Result<Self> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    let is_error = many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    });

    if !is_error {
      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
        output: Vec::new(),
      })
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;

    if self.output.is_empty() {
      let channels    = self.info.channels as usize;
      let block_size  = self.info.max_block_size as usize;
      let output_size = block_size * channels;

      self.output.reserve_exact(output_size);

      unsafe { self.output.set_len(output_size) }
    }

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame<'a>(&'a mut self) -> Option<usize> {
    let stream_info = &self.info;

    loop {
      match self.producer.parse(|i| frame_parser(i, stream_info)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut self.output[start..end];

            subframe::decode(&subframe, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, &mut self.output);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P> where P: 'a + StreamProducer {
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a, P> Iterator for Iter<'a, P> where P: StreamProducer {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      if let Some(block_size) = self.stream.next_frame() {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a, P> IntoIterator for &'a mut Stream

 where P: StreamProducer {
  type Item     = i32;
  type IntoIter = Iter<'a, P>;

  #[inline]
  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<commit_msg>Borrow `self.output` once<commit_after>use metadata;
use frame;
use subframe;

use metadata::{Metadata, StreamInfo};
use frame::frame_parser;
use utility::{
  ErrorKind, ByteStream, ReadStream, StreamProducer, many_metadata,
};

use std::io;
use std::usize;
use std::fs::File;

/// FLAC stream that decodes and hold file information.
pub struct Stream
 {
  info: StreamInfo,
  metadata: Vec<Metadata>,
  producer: P,
  output: Vec<i32>,
}

/// Alias for a FLAC stream produced from `Read`.
pub type StreamReader<R>  = Stream<ReadStream<R>>;

/// Alias for a FLAC stream produced from a byte stream buffer.
pub type StreamBuffer<'a> = Stream<ByteStream<'a>>;

impl
 Stream
 where P: StreamProducer {
  /// Constructor for the default state of a FLAC stream.
  #[inline]
  pub fn new<R: io::Read>(reader: R) -> io::Result<StreamReader<R>> {
    let producer  = ReadStream::new(reader);
    let error_str = "parser: couldn't parse the reader";

    Stream::from_stream_producer(producer, error_str)
  }

  /// Returns information for the current stream.
  #[inline]
  pub fn info(&self) -> StreamInfo {
    self.info
  }

  /// Returns a slice of `Metadata`
  ///
  /// This slice excludes `StreamInfo`, which is located in `Stream::info`.
  /// Everything else is related to metadata for the FLAC stream is in the
  /// slice.
  #[inline]
  pub fn metadata(&self) -> &[Metadata] {
    &self.metadata
  }

  /// Constructs a decoder with the given file name.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::NotFound` is returned when the given filename isn't found.
  /// * `ErrorKind::InvalidData` is returned when the data within the file
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_file(filename: &str) -> io::Result<StreamReader<File>> {
    File::open(filename).and_then(|file| {
      let producer  = ReadStream::new(file);
      let error_str = format!("parser: couldn't parse the given file {}",
                              filename);

      Stream::from_stream_producer(producer, &error_str)
    })
  }

  /// Constructs a decoder with the given buffer.
  ///
  /// This constructor assumes that an entire FLAC file is in the buffer.
  ///
  /// # Failures
  ///
  /// * `ErrorKind::InvalidData` is returned when the data within the buffer
  ///   isn't valid FLAC data.
  #[inline]
  pub fn from_buffer(buffer: &[u8]) -> io::Result<StreamBuffer> {
    let producer  = ByteStream::new(buffer);
    let error_str = "parser: couldn't parse the buffer";

    Stream::from_stream_producer(producer, error_str)
  }

  fn from_stream_producer(mut producer: P, error_str: &str)
                          -> io::Result<Self> {
    let mut stream_info = StreamInfo::new();
    let mut metadata    = Vec::new();

    let is_error = many_metadata(&mut producer, |block| {
      if let metadata::Data::StreamInfo(info) = block.data {
        stream_info = info;
      } else {
        metadata.push(block);
      }
    });

    if !is_error {
      Ok(Stream {
        info: stream_info,
        metadata: metadata,
        producer: producer,
        output: Vec::new(),
      })
    } else {
      Err(io::Error::new(io::ErrorKind::InvalidData, error_str))
    }
  }

  /// Returns an iterator over the decoded samples.
  #[inline]
  pub fn iter(&mut self) -> Iter
 {
    let samples_left = self.info.total_samples;

    if self.output.is_empty() {
      let channels    = self.info.channels as usize;
      let block_size  = self.info.max_block_size as usize;
      let output_size = block_size * channels;

      self.output.reserve_exact(output_size);

      unsafe { self.output.set_len(output_size) }
    }

    Iter {
      stream: self,
      channel: 0,
      block_size: 0,
      sample_index: 0,
      samples_left: samples_left,
    }
  }

  fn next_frame<'a>(&'a mut self) -> Option<usize> {
    let stream_info = &self.info;
    let buffer      = &mut self.output;

    loop {
      match self.producer.parse(|i| frame_parser(i, stream_info)) {
        Ok(frame)                  => {
          let channels    = frame.header.channels as usize;
          let block_size  = frame.header.block_size as usize;
          let mut channel = 0;

          for subframe in &frame.subframes[0..channels] {
            let start  = channel * block_size;
            let end    = (channel + 1) * block_size;
            let output = &mut buffer[start..end];

            subframe::decode(&subframe, output);

            channel += 1;
          }

          frame::decode(frame.header.channel_assignment, buffer);

          return Some(block_size);
        }
        Err(ErrorKind::EndOfInput) => return None,
        Err(ErrorKind::Continue)   => continue,
        Err(_)                     => return None,
      }
    }
  }
}

/// An iterator over a reference of the decoded FLAC stream.
pub struct Iter<'a, P> where P: 'a + StreamProducer {
  stream: &'a mut Stream
,
  channel: usize,
  block_size: usize,
  sample_index: usize,
  samples_left: u64,
}

impl<'a, P> Iterator for Iter<'a, P> where P: StreamProducer {
  type Item = i32;

  fn next(&mut self) -> Option<Self::Item> {
    if self.sample_index == self.block_size {
      if let Some(block_size) = self.stream.next_frame() {
        self.sample_index = 0;
        self.block_size   = block_size;
      } else {
        return None;
      }
    }

    let channels = self.stream.info.channels as usize;
    let index    = self.sample_index + (self.channel * self.block_size);
    let sample   = self.stream.output[index];

    self.channel += 1;

    // Reset current channel
    if self.channel == channels {
      self.channel       = 0;
      self.sample_index += 1;
      self.samples_left -= 1;
    }

    Some(sample)
  }

  fn size_hint(&self) -> (usize, Option<usize>) {
    let samples_left = self.samples_left as usize;
    let max_value    = usize::max_value() as u64;

    // There is a chance that samples_left will be larger than a usize since
    // it is a u64. Make the upper bound None when it is.
    if self.samples_left > max_value {
      (samples_left, None)
    } else {
      (samples_left, Some(samples_left))
    }
  }
}

impl<'a, P> IntoIterator for &'a mut Stream

 where P: StreamProducer {
  type Item     = i32;
  type IntoIter = Iter<'a, P>;

  #[inline]
  fn into_iter(self) -> Self::IntoIter {
    self.iter()
  }
}
<|endoftext|>


<commit_before>use std::io;
use std::mem;
use std::sync::{Arc, mpsc};
use std::sync::atomic::{AtomicBool, Ordering};

use mio::{Token, EventSet, TryRead, TryWrite};
use ::{Action, Protocol, Transport};

pub type Action_ = Action;

pub struct Stream<P: Protocol, T: Transport> {
    transport: T,
    protocol: P,
    rx: mpsc::Receiver<Action>,
    is_queued: Arc<AtomicBool>,
    last_action: Option<Action>,
    reading: Reading,
    writing: Writing,
}

impl<P: Protocol, T: Transport> Stream<P, T> {

    pub fn new(transport: T, protocol: P, rx: mpsc::Receiver<Action_>, is_queued: Arc<AtomicBool>) -> Stream<P, T> {
        Stream {
            transport: transport,
            protocol: protocol,
            rx: rx,
            is_queued: is_queued,
            last_action: None,
            reading: Reading::Open(vec![0; 4096]),
            writing: Writing::Waiting(io::Cursor::new(vec![])),
        }
    }

    pub fn queue_writing(&mut self, data: Option<Vec<u8>>) {
        match (self.writing.can_write(), data) {
            (true, Some(bytes)) => {
                trace!("queue writing {} bytes", bytes.len());
                let mut buf = self.writing.close();
                buf.get_mut().extend(&bytes);
                self.writing.open(buf);
            },
            (true, None) => {
                trace!("queueing closing");
                self.writing.closing();
            },
            (false, data) => {
                trace!("cannot queue writing: {:?}", data);
            },
        }
        self.process_queue();
    }

    fn process_queue(&mut self) {
        if self.is_queued.swap(false, Ordering::Acquire) {
            while let Ok(action) = self.rx.try_recv() {
                match action {
                    Action::Write(data) => self.queue_writing(data),
                    other => trace!("unhandled queued action {:?}", other)
                }
            }
        }
    }

    pub fn close(&mut self) {
        self.queue_writing(None);
        self.reading = Reading::Closed;
    }

    pub fn ready(&mut self, token: Token, events: EventSet) {
        self.last_action = None;
        if events.is_error() {
            debug!("error event on {:?}", token);
        }

        if events.is_readable() {
            loop {
                //TODO: check if protocol paused
                if self.reading.is_paused() {
                    trace!("reading is paused");
                    break;
                }
                let mut buf = self.reading.close();
                match self.transport.try_read(&mut buf) {
                    Ok(Some(0)) => {
                        trace!("read eof {:?}", token);
                        self.protocol.on_eof();
                        break;
                    }
                    Ok(Some(n)) => {
                        trace!("read {} bytes {:?}", n, token);
                        self.protocol.on_data(&buf[..n]);
                        self.reading.open(buf);
                    }
                    Ok(None) => {
                        trace!("read would block {:?}", token);
                        self.reading.open(buf);
                        break;
                    }
                    Err(e) => {
                        self.on_error(e.into());
                        return;
                    }
                }
            }
        }

        if events.is_writable() {
            let is_closing = !self.writing.can_write();
            let mut buf = self.writing.close();
            while buf.position() < buf.get_ref().len() as u64 {
                match self.transport.try_write_buf(&mut buf) {
                    Ok(Some(0)) => {
                        trace!("===> write 0 means what again? {:?}", token);
                        break;
                    },
                    Ok(Some(n)) => {
                        trace!("wrote {} bytes {:?}", n, token);
                    },
                    Ok(None) => {
                        trace!("write would block {:?}", token);
                        break;
                    }
                    Err(e) => {
                        self.on_error(e.into());
                        return;
                    }
                }
            }

            if buf.position() == buf.get_ref().len() as u64 {
                buf.set_position(0);
                buf.get_mut().truncate(0);
                if is_closing {
                    //leave closed
                } else {
                    self.writing.open(buf);
                    self.writing.wait();
                }
            } else {
                self.writing.open(buf);
                if is_closing {
                    self.writing.closing();
                }
            }
        }
    }

    pub fn transport(&self) -> &T {
        &self.transport
    }

    pub fn action(&mut self) -> Action {
        let action = match (&self.reading, &self.writing) {
            (&Reading::Open(_), &Writing::Open(_)) |(&Reading::Open(_), &Writing::Closing(_)) => Action::Register(EventSet::readable() | EventSet::writable()),
            (&Reading::Closed, &Writing::Closed) => Action::Remove,

            (&Reading::Open(_), _) => Action::Register(EventSet::readable()),
            (_, &Writing::Open(_)) | (_, &Writing::Closing(_)) => Action::Register(EventSet::writable()),

            _ => Action::Wait
        };

        if let Some(ref last) = self.last_action {
            if *last == action {
                trace!("< Action is the same {:?}, Waiting", action);
                return Action::Wait
            }
        }
        self.last_action = Some(action.clone());
        action
    }

    fn on_error(&mut self, e: ::Error) {
        self.writing = Writing::Closed;
        self.reading = Reading::Closed;
        self.protocol.on_end(Some(e));
    }
}

enum Reading {
    Open(Vec<u8>),
    Paused(Vec<u8>),
    Closed
}

impl Reading {
    fn open(&mut self, buf: Vec<u8>) {
        mem::replace(self, Reading::Open(buf));
    }

    fn pause(&mut self) {
        let buf = self.close();
        mem::replace(self, Reading::Paused(buf));
    }

    fn is_paused(&self) -> bool {
        match *self {
            Reading::Paused(..) => true,
            _ => false
        }
    }

    fn close(&mut self) -> Vec<u8> {
        match mem::replace(self, Reading::Closed) {
            Reading::Open(buf) => buf,
            Reading::Paused(buf) => buf,
            _ => panic!("already closed")
        }
    }
}

enum Writing {
    Open(io::Cursor<Vec<u8>>),
    Waiting(io::Cursor<Vec<u8>>),
    Closing(io::Cursor<Vec<u8>>),
    Closed
}

impl Writing {
    fn open(&mut self, buf: io::Cursor<Vec<u8>>) {
        mem::replace(self, Writing::Open(buf));
    }

    fn wait(&mut self) {
        let buf = self.close();
        mem::replace(self, Writing::Waiting(buf));
    }

    fn closing(&mut self) {
        let buf = self.close();
        mem::replace(self, Writing::Closing(buf));
    }

    fn can_write(&self) -> bool {
        match *self {
            Writing::Open(_) | Writing::Waiting(_) => true,
            _ => false
        }
    }

    fn close(&mut self) -> io::Cursor<Vec<u8>> {
        match mem::replace(self, Writing::Closed) {
            Writing::Open(buf) => buf,
            Writing::Waiting(buf) => buf,
            Writing::Closing(buf) => buf,
            _ => panic!("already closed")
        }
    }
}

<commit_msg>close shop after eof<commit_after>use std::io;
use std::mem;
use std::sync::{Arc, mpsc};
use std::sync::atomic::{AtomicBool, Ordering};

use mio::{Token, EventSet, TryRead, TryWrite};
use ::{Action, Protocol, Transport};

pub type Action_ = Action;

pub struct Stream<P: Protocol, T: Transport> {
    transport: T,
    protocol: P,
    rx: mpsc::Receiver<Action>,
    is_queued: Arc<AtomicBool>,
    last_action: Option<Action>,
    reading: Reading,
    writing: Writing,
}

impl<P: Protocol, T: Transport> Stream<P, T> {

    pub fn new(transport: T, protocol: P, rx: mpsc::Receiver<Action_>, is_queued: Arc<AtomicBool>) -> Stream<P, T> {
        Stream {
            transport: transport,
            protocol: protocol,
            rx: rx,
            is_queued: is_queued,
            last_action: None,
            reading: Reading::Open(vec![0; 4096]),
            writing: Writing::Waiting(io::Cursor::new(vec![])),
        }
    }

    pub fn queue_writing(&mut self, data: Option<Vec<u8>>) {
        match (self.writing.can_write(), data) {
            (true, Some(bytes)) => {
                trace!("queue writing {} bytes", bytes.len());
                let mut buf = self.writing.close();
                buf.get_mut().extend(&bytes);
                self.writing.open(buf);
            },
            (true, None) => {
                trace!("queueing closing");
                self.writing.closing();
            },
            (false, data) => {
                trace!("cannot queue writing: {:?}", data);
            },
        }
        self.process_queue();
    }

    fn process_queue(&mut self) {
        if self.is_queued.swap(false, Ordering::Acquire) {
            while let Ok(action) = self.rx.try_recv() {
                match action {
                    Action::Write(data) => self.queue_writing(data),
                    other => trace!("unhandled queued action {:?}", other)
                }
            }
        }
    }

    pub fn close(&mut self) {
        self.queue_writing(None);
        self.reading = Reading::Closed;
    }

    fn abort(&mut self) {
        self.reading = Reading::Closed;
        self.writing = Writing::Closed;
        self.protocol.on_end(None);
    }

    pub fn ready(&mut self, token: Token, events: EventSet) {
        self.last_action = None;
        if events.is_error() {
            debug!("error event on {:?}", token);
        }

        if events.is_readable() {
            loop {
                //TODO: check if protocol paused
                if self.reading.is_paused() {
                    trace!("reading is paused");
                    break;
                }
                let mut buf = self.reading.close();
                match self.transport.try_read(&mut buf) {
                    Ok(Some(0)) => {
                        trace!("read eof {:?}", token);
                        self.protocol.on_eof();
                        self.abort();
                        break;
                    }
                    Ok(Some(n)) => {
                        trace!("read {} bytes {:?}", n, token);
                        self.protocol.on_data(&buf[..n]);
                        self.reading.open(buf);
                    }
                    Ok(None) => {
                        trace!("read would block {:?}", token);
                        self.reading.open(buf);
                        break;
                    }
                    Err(e) => {
                        self.on_error(e.into());
                        return;
                    }
                }
            }
        }

        if events.is_writable() {
            let is_closing = !self.writing.can_write();
            let mut buf = self.writing.close();
            while buf.position() < buf.get_ref().len() as u64 {
                match self.transport.try_write_buf(&mut buf) {
                    Ok(Some(0)) => {
                        error!("===> write 0 means what again? {:?}", token);
                        break;
                    },
                    Ok(Some(n)) => {
                        trace!("wrote {} bytes {:?}", n, token);
                    },
                    Ok(None) => {
                        trace!("write would block {:?}", token);
                        break;
                    }
                    Err(e) => {
                        self.on_error(e.into());
                        return;
                    }
                }
            }

            if buf.position() == buf.get_ref().len() as u64 {
                buf.set_position(0);
                buf.get_mut().truncate(0);
                if is_closing {
                    //leave closed
                } else {
                    self.writing.open(buf);
                    self.writing.wait();
                }
            } else {
                self.writing.open(buf);
                if is_closing {
                    self.writing.closing();
                }
            }
        }
    }

    pub fn transport(&self) -> &T {
        &self.transport
    }

    pub fn action(&mut self) -> Action {
        let action = match (&self.reading, &self.writing) {
            (&Reading::Open(_), &Writing::Open(_)) |(&Reading::Open(_), &Writing::Closing(_)) => Action::Register(EventSet::readable() | EventSet::writable()),
            (&Reading::Closed, &Writing::Closed) => Action::Remove,

            (&Reading::Open(_), _) => Action::Register(EventSet::readable()),
            (_, &Writing::Open(_)) | (_, &Writing::Closing(_)) => Action::Register(EventSet::writable()),

            _ => Action::Wait
        };

        if let Some(ref last) = self.last_action {
            if *last == action {
                trace!("< Action is the same {:?}, Waiting", action);
                return Action::Wait
            }
        }
        self.last_action = Some(action.clone());
        action
    }

    fn on_error(&mut self, e: ::Error) {
        self.writing = Writing::Closed;
        self.reading = Reading::Closed;
        self.protocol.on_end(Some(e));
    }
}

enum Reading {
    Open(Vec<u8>),
    Paused(Vec<u8>),
    Closed
}

impl Reading {
    fn open(&mut self, buf: Vec<u8>) {
        mem::replace(self, Reading::Open(buf));
    }

    fn pause(&mut self) {
        let buf = self.close();
        mem::replace(self, Reading::Paused(buf));
    }

    fn is_paused(&self) -> bool {
        match *self {
            Reading::Paused(..) => true,
            _ => false
        }
    }

    fn close(&mut self) -> Vec<u8> {
        match mem::replace(self, Reading::Closed) {
            Reading::Open(buf) => buf,
            Reading::Paused(buf) => buf,
            _ => panic!("already closed")
        }
    }
}

enum Writing {
    Open(io::Cursor<Vec<u8>>),
    Waiting(io::Cursor<Vec<u8>>),
    Closing(io::Cursor<Vec<u8>>),
    Closed
}

impl Writing {
    fn open(&mut self, buf: io::Cursor<Vec<u8>>) {
        mem::replace(self, Writing::Open(buf));
    }

    fn wait(&mut self) {
        let buf = self.close();
        mem::replace(self, Writing::Waiting(buf));
    }

    fn closing(&mut self) {
        let buf = self.close();
        mem::replace(self, Writing::Closing(buf));
    }

    fn can_write(&self) -> bool {
        match *self {
            Writing::Open(_) | Writing::Waiting(_) => true,
            _ => false
        }
    }

    fn close(&mut self) -> io::Cursor<Vec<u8>> {
        match mem::replace(self, Writing::Closed) {
            Writing::Open(buf) => buf,
            Writing::Waiting(buf) => buf,
            Writing::Closing(buf) => buf,
            _ => panic!("already closed")
        }
    }
}

<|endoftext|>


<commit_before>pub mod simple {
    use ::front::ast;

    pub fn function(fun: &ast::Node<ast::Function>) -> String {
        // arguments
        let args = fun.node
            .args
            .iter()
            .map(|ref arg| format!("{:?} {}", arg.type_, arg.name))
            .collect::<Vec<String>>()
            .join(", ");

        format!("{}:{}\t{} ({}) -> {:?}",
                fun.node.filename,
                fun.pos.line,
                fun.node.name,
                args,
                fun.node.ret_type)
    }

    pub fn statement(stmt: &ast::Node<ast::Statement>) -> String {
        match stmt.node {
            ast::Statement::Expression { .. } => "Expression".to_owned(),
            ast::Statement::Declaration { .. } => "Declaration".to_owned(),
            ast::Statement::Assignment { .. } => "Assignment".to_owned(),
            ast::Statement::If { .. } => "If".to_owned(),
            ast::Statement::While { .. } => "While".to_owned(),
            ast::Statement::Return { .. } => "Return".to_owned(),
            ast::Statement::Compound { .. } => "Compound".to_owned(),
        }
    }

    pub fn expression(expr: &ast::Node<ast::Expression>) -> String {
        match expr.node {
            ast::Expression::Literal { ref lit } => literal(lit),
            ast::Expression::Variable { ref var } => variable(var.as_ref()),
            ast::Expression::Call { ref function, .. } => format!("{}(..)", function),
            ast::Expression::Unary { ref op, .. } => format!("{:?} ", op),
            ast::Expression::Binary { ref op, .. } => format!(" {:?} ", op),
            ast::Expression::Parenthesis { .. } => "(  )".to_owned(),
        }
    }

    pub fn literal(lit: &ast::Literal) -> String {
        match *lit {
            ast::Literal::Bool(ref v) => format!("{}", v).to_owned(),
            ast::Literal::Int(ref v) => format!("{}", v).to_owned(),
            ast::Literal::Float(ref v) => format!("{}f", v).to_owned(),
            ast::Literal::Str(ref v) => format!("\"{}\"", v).to_owned(),
        }
    }

    pub fn variable(var: &ast::Variable) -> String {
        format!("{}_{} ({:?})", var.id, var.name, var.type_)
    }
}

pub mod dot {
    use ::front::ast;
    use super::simple;

    pub fn function(fun: &ast::Node<ast::Function>) -> String {
        format!("digraph {}_{} {{\n{}{}{}}}\n",
                fun.node.filename,
                fun.node.name,
                node(fun, &simple::function(fun)),
                edge(fun, &fun.node.body, "body"),
                statement(&fun.node.body))
    }

    fn statement(stmt: &ast::Node<ast::Statement>) -> String {
        let mut ret = node(stmt, &simple::statement(stmt));
        match stmt.node {
            ast::Statement::Expression { ref expr } => {
                ret.push_str(&expression(expr));
                ret.push_str(&edge(stmt, expr, "expr"));
            }
            ast::Statement::Declaration { ref var } => {
                ret.push_str(&node_var(var));
                ret.push_str(&edge_to_var(stmt, var))
            }
            ast::Statement::Assignment { ref var, ref expr } => {
                ret.push_str(&node_var(var));
                ret.push_str(&edge_to_var(stmt, var));
                ret.push_str(&expression(expr));
                ret.push_str(&edge(stmt, expr, "expr"));
            }
            ast::Statement::If { ref cond, ref on_true, ref on_false } => {
                ret.push_str(&expression(cond));
                ret.push_str(&edge(stmt, cond, "cond"));
                ret.push_str(&statement(on_true));
                ret.push_str(&edge(stmt, on_true, "on_true"));
                if let Some(ref else_part) = *on_false {
                    ret.push_str(&statement(else_part));
                    ret.push_str(&edge(stmt, else_part, "on_false"));
                }
            }
            ast::Statement::While { ref cond, ref body } => {
                ret.push_str(&expression(cond));
                ret.push_str(&edge(stmt, cond, "cond"));
                ret.push_str(&statement(body));
                ret.push_str(&edge(stmt, body, "body"));
            }
            ast::Statement::Return { expr: Some(ref expr) } => {
                ret.push_str(&expression(expr));
                ret.push_str(&edge(stmt, expr, "expr"));
            }
            ast::Statement::Compound { ref stmts, .. } => {
                for (i, s) in stmts.iter().enumerate() {
                    ret.push_str(&statement(s));
                    ret.push_str(&edge(stmt, s, &*i.to_string()));
                }
            }
            _ => (),
        }
        ret
    }

    fn expression(expr: &ast::Node<ast::Expression>) -> String {
        let mut ret = node(expr, &simple::expression(expr));
        match expr.node {
            ast::Expression::Call { ref args, .. } => {
                for (i, arg) in args.iter().enumerate() {
                    ret.push_str(&expression(arg));
                    ret.push_str(&edge(expr, arg, &*i.to_string()));
                }
            }
            ast::Expression::Unary { expr: ref e, .. } |
            ast::Expression::Parenthesis { expr: ref e } => {
                ret.push_str(&expression(e));
                ret.push_str(&edge(expr, e, "expr"));
            }
            ast::Expression::Binary { ref left, ref right, .. } => {
                ret.push_str(&expression(left));
                ret.push_str(&edge(expr, left, "left"));
                ret.push_str(&expression(right));
                ret.push_str(&edge(expr, right, "right"));
            }
            _ => (),
        }
        ret
    }

    fn node<N>(node: &ast::Node<N>, label: &str) -> String {
        format!("\t\"{:?}\" [shape=box, label=\"{}\"];\n",
                node as *const ast::Node<N>,
                label)
    }

    fn node_var(var: &ast::Variable) -> String {
        format!("\t\"{:?}\" [shape=box, label=\"{}\"];\n",
                var as *const ast::Variable,
                simple::variable(var))
    }

    fn edge<N, M>(from: &ast::Node<N>, to: &ast::Node<M>, label: &str) -> String {
        format!("\t\"{:?}\" -> \"{:?}\" [label=\"{}\"];\n",
                from as *const ast::Node<N>,
                to as *const ast::Node<M>,
                label)
    }

    fn edge_to_var<N>(from: &ast::Node<N>, to: &ast::Variable) -> String {
        format!("\t\"{:?}\" -> \"{:?}\" [label=\"var\"];\n",
                from as *const ast::Node<N>,
                to as *const ast::Variable)
    }
}
<commit_msg>Diag: Fancier dot output<commit_after>pub mod simple {
    use ::front::ast;

    pub fn function(fun: &ast::Node<ast::Function>) -> String {
        // arguments
        let args = fun.node
            .args
            .iter()
            .map(|ref arg| format!("{:?} {}", arg.type_, arg.name))
            .collect::<Vec<String>>()
            .join(", ");

        format!("{}:{}\t{} ({}) -> {:?}",
                fun.node.filename,
                fun.pos.line,
                fun.node.name,
                args,
                fun.node.ret_type)
    }

    pub fn statement(stmt: &ast::Node<ast::Statement>) -> String {
        match stmt.node {
            ast::Statement::Expression { .. } => "Expression".to_owned(),
            ast::Statement::Declaration { .. } => "Declaration".to_owned(),
            ast::Statement::Assignment { .. } => "Assignment".to_owned(),
            ast::Statement::If { .. } => "If".to_owned(),
            ast::Statement::While { .. } => "While".to_owned(),
            ast::Statement::Return { .. } => "Return".to_owned(),
            ast::Statement::Compound { .. } => "Compound".to_owned(),
        }
    }

    pub fn expression(expr: &ast::Node<ast::Expression>) -> String {
        match expr.node {
            ast::Expression::Literal { ref lit } => literal(lit),
            ast::Expression::Variable { ref var } => variable(var.as_ref()),
            ast::Expression::Call { ref function, .. } => format!("{}(..)", function),
            ast::Expression::Unary { ref op, .. } => format!("{:?} ", op),
            ast::Expression::Binary { ref op, .. } => format!(" {:?} ", op),
            ast::Expression::Parenthesis { .. } => "(  )".to_owned(),
        }
    }

    pub fn literal(lit: &ast::Literal) -> String {
        match *lit {
            ast::Literal::Bool(ref v) => format!("{}", v).to_owned(),
            ast::Literal::Int(ref v) => format!("{}", v).to_owned(),
            ast::Literal::Float(ref v) => format!("{}f", v).to_owned(),
            ast::Literal::Str(ref v) => format!("\"{}\"", v).to_owned(),
        }
    }

    pub fn variable(var: &ast::Variable) -> String {
        format!("{}_{} ({:?})", var.id, var.name, var.type_)
    }
}

pub mod dot {
    use ::front::ast;
    use super::simple;

    pub fn function(fun: &ast::Node<ast::Function>) -> String {
        let options = vec!["\tnodesep=0.6".to_owned()];
        format!("digraph \"{}_{}\" {{\n{}\n{}{}{}}}\n",
                fun.node.filename,
                fun.node.name,
                options.join("\n"),
                node(fun, &simple::function(fun)),
                edge(fun, &fun.node.body, "body"),
                statement(&fun.node.body))
    }

    fn statement(stmt: &ast::Node<ast::Statement>) -> String {
        let mut ret = node(stmt, &simple::statement(stmt));
        match stmt.node {
            ast::Statement::Expression { ref expr } => {
                ret.push_str(&expression(expr));
                ret.push_str(&edge(stmt, expr, "expr"));
            }
            ast::Statement::Declaration { ref var } => {
                ret.push_str(&node_var(var));
                ret.push_str(&edge_to_var(stmt, var))
            }
            ast::Statement::Assignment { ref var, ref expr } => {
                ret.push_str(&node_var(var));
                ret.push_str(&edge_to_var(stmt, var));
                ret.push_str(&expression(expr));
                ret.push_str(&edge(stmt, expr, "expr"));
            }
            ast::Statement::If { ref cond, ref on_true, ref on_false } => {
                ret.push_str(&expression(cond));
                ret.push_str(&edge(stmt, cond, "cond"));
                ret.push_str(&statement(on_true));
                ret.push_str(&edge(stmt, on_true, "on_true"));
                if let Some(ref else_part) = *on_false {
                    ret.push_str(&statement(else_part));
                    ret.push_str(&edge(stmt, else_part, "on_false"));
                }
            }
            ast::Statement::While { ref cond, ref body } => {
                ret.push_str(&expression(cond));
                ret.push_str(&edge(stmt, cond, "cond"));
                ret.push_str(&statement(body));
                ret.push_str(&edge(stmt, body, "body"));
            }
            ast::Statement::Return { expr: Some(ref expr) } => {
                ret.push_str(&expression(expr));
                ret.push_str(&edge(stmt, expr, "expr"));
            }
            ast::Statement::Compound { ref stmts, .. } => {
                for (i, s) in stmts.iter().enumerate() {
                    ret.push_str(&statement(s));
                    ret.push_str(&edge(stmt, s, &*i.to_string()));
                }
            }
            _ => (),
        }
        ret
    }

    fn expression(expr: &ast::Node<ast::Expression>) -> String {
        let mut ret = node(expr, &simple::expression(expr));
        match expr.node {
            ast::Expression::Call { ref args, .. } => {
                for (i, arg) in args.iter().enumerate() {
                    ret.push_str(&expression(arg));
                    ret.push_str(&edge(expr, arg, &*i.to_string()));
                }
            }
            ast::Expression::Unary { expr: ref e, .. } |
            ast::Expression::Parenthesis { expr: ref e } => {
                ret.push_str(&expression(e));
                ret.push_str(&edge(expr, e, "expr"));
            }
            ast::Expression::Binary { ref left, ref right, .. } => {
                ret.push_str(&expression(left));
                ret.push_str(&edge(expr, left, "left"));
                ret.push_str(&expression(right));
                ret.push_str(&edge(expr, right, "right"));
            }
            _ => (),
        }
        ret
    }

    fn node<N>(node: &ast::Node<N>, label: &str) -> String {
        format!("\t\"{:?}\" [shape=box, label=\"{}\", fontname=\"Monospace\"];\n",
                node as *const ast::Node<N>,
                label)
    }

    fn node_var(var: &ast::Variable) -> String {
        format!("\t\"{:?}\" [shape=box, label=\"{}\"];\n",
                var as *const ast::Variable,
                simple::variable(var))
    }

    fn edge<N, M>(from: &ast::Node<N>, to: &ast::Node<M>, label: &str) -> String {
        format!("\t\"{:?}\" -> \"{:?}\" [label=\"{}\"];\n",
                from as *const ast::Node<N>,
                to as *const ast::Node<M>,
                label)
    }

    fn edge_to_var<N>(from: &ast::Node<N>, to: &ast::Variable) -> String {
        format!("\t\"{:?}\" -> \"{:?}\" [label=\"var\"];\n",
                from as *const ast::Node<N>,
                to as *const ast::Variable)
    }
}
<|endoftext|>


<commit_before>use scroll::ctx::TryFromCtx;

use crate::common::*;
use crate::tpi::constants::*;

#[inline]
fn parse_optional_type_index<'t>(buf: &mut ParseBuffer<'t>) -> Result<Option<TypeIndex>> {
    let index = buf.parse()?;
    if index == TypeIndex(0) || index == TypeIndex(0xffff) {
        Ok(None)
    } else {
        Ok(Some(index))
    }
}

// TODO(ja): MOve these
#[inline]
fn parse_optional_id_index<'t>(buf: &mut ParseBuffer<'t>) -> Result<Option<IdIndex>> {
    Ok(match buf.parse()? {
        IdIndex(0) => None,
        index => Some(index),
    })
}

#[inline]
fn parse_string<'t>(leaf: u16, buf: &mut ParseBuffer<'t>) -> Result<RawString<'t>> {
    if leaf > LF_ST_MAX {
        buf.parse_cstring()
    } else {
        buf.parse_u8_pascal_string()
    }
}

/// Encapsulates parsed data about an `Id`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IdData<'t> {
    FunctionId(FunctionIdType<'t>),
    MemberFunctionId(MemberFunctionIdType<'t>),
    BuildInfoId(BuildInfoIdType),
    SubstringList(SubstringListType),
    StringId(StringIdType<'t>),
    UserDefinedTypeSource(UserDefinedTypeSourceType),
}

impl<'t> IdData<'t> {}

impl<'t> TryFromCtx<'t, scroll::Endian> for IdData<'t> {
    type Error = Error;
    type Size = usize;

    fn try_from_ctx(this: &'t [u8], _ctx: scroll::Endian) -> Result<(Self, Self::Size)> {
        let mut buf = ParseBuffer::from(this);
        let leaf = buf.parse_u16()?;

        let data = match leaf {
            LF_FUNC_ID => IdData::FunctionId(FunctionIdType {
                scope: parse_optional_id_index(&mut buf)?,
                function_type: buf.parse()?,
                name: parse_string(leaf, &mut buf)?,
            }),
            LF_MFUNC_ID => IdData::MemberFunctionId(MemberFunctionIdType {
                parent: parse_optional_type_index(&mut buf)?,
                function_type: buf.parse()?,
                name: parse_string(leaf, &mut buf)?,
            }),
            LF_BUILDINFO => IdData::BuildInfoId({
                let count = buf.parse::<u16>()?;
                let mut arguments = Vec::with_capacity(count as usize);
                for _ in 0..count {
                    arguments.push(buf.parse()?);
                }
                BuildInfoIdType { arguments }
            }),
            LF_SUBSTR_LIST => IdData::SubstringList({
                let count = buf.parse::<u32>()?;
                let mut substrings = Vec::with_capacity(count as usize);
                for _ in 0..count {
                    substrings.push(buf.parse()?);
                }
                SubstringListType { substrings }
            }),
            LF_STRING_ID => IdData::StringId(StringIdType {
                substrings: buf.parse()?,
                name: parse_string(leaf, &mut buf)?,
            }),
            LF_UDT_SRC_LINE | LF_UDT_MOD_SRC_LINE => {
                let mut udt = UserDefinedTypeSourceType {
                    udt: buf.parse()?,
                    source_file: buf.parse()?,
                    line: buf.parse()?,
                    module: None,
                };

                if leaf == LF_UDT_MOD_SRC_LINE {
                    udt.module = Some(buf.parse()?);
                }

                IdData::UserDefinedTypeSource(udt)
            }
            _ => return Err(Error::UnimplementedTypeKind(leaf)),
        };

        Ok((data, buf.pos()))
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FunctionIdType<'t> {
    /// Parent scope of this id.
    scope: Option<IdIndex>,
    /// Index of the function type declaration.
    function_type: TypeIndex,
    name: RawString<'t>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MemberFunctionIdType<'t> {
    /// Index of the parent type.
    parent: Option<TypeIndex>,
    /// Index of the member function type declaration.
    function_type: TypeIndex,
    /// Name of the member function.
    name: RawString<'t>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BuildInfoIdType {
    /// Indexes of build arguments.
    arguments: Vec<IdIndex>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct SubstringListType {
    /// The list of substrings.
    pub substrings: Vec<TypeIndex>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StringIdType<'t> {
    /// Index of the list of substrings.
    substrings: IdIndex,
    /// The string.
    name: RawString<'t>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct UserDefinedTypeSourceType {
    /// Index of the UDT's type definition.
    udt: TypeIndex,
    /// Index of the source file name.
    source_file: IdIndex,
    /// Line number in the source file.
    line: u32,
    /// Module that contributes this UDT definition.
    ///
    /// If None, the UDT is declared in the same module.
    module: Option<u16>,
}
<commit_msg>Fix parsing of ID types<commit_after>use scroll::ctx::TryFromCtx;

use crate::common::*;
use crate::tpi::constants::*;

// TODO(ja): MOve these
#[inline]
fn parse_optional_id_index<'t>(buf: &mut ParseBuffer<'t>) -> Result<Option<IdIndex>> {
    Ok(match buf.parse()? {
        IdIndex(0) => None,
        index => Some(index),
    })
}

#[inline]
fn parse_string<'t>(leaf: u16, buf: &mut ParseBuffer<'t>) -> Result<RawString<'t>> {
    if leaf > LF_ST_MAX {
        buf.parse_cstring()
    } else {
        buf.parse_u8_pascal_string()
    }
}

/// Encapsulates parsed data about an `Id`.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum IdData<'t> {
    Function(FunctionId<'t>),
    MemberFunction(MemberFunctionId<'t>),
    BuildInfo(BuildInfoId),
    StringList(StringListId),
    String(StringId<'t>),
    UserDefinedTypeSource(UserDefinedTypeSourceId),
}

impl<'t> IdData<'t> {}

impl<'t> TryFromCtx<'t, scroll::Endian> for IdData<'t> {
    type Error = Error;
    type Size = usize;

    fn try_from_ctx(this: &'t [u8], _ctx: scroll::Endian) -> Result<(Self, Self::Size)> {
        let mut buf = ParseBuffer::from(this);
        let leaf = buf.parse_u16()?;

        let data = match leaf {
            LF_FUNC_ID => IdData::Function(FunctionId {
                scope: parse_optional_id_index(&mut buf)?,
                function_type: buf.parse()?,
                name: parse_string(leaf, &mut buf)?,
            }),
            LF_MFUNC_ID => IdData::MemberFunction(MemberFunctionId {
                parent: buf.parse()?,
                function_type: buf.parse()?,
                name: parse_string(leaf, &mut buf)?,
            }),
            LF_BUILDINFO => IdData::BuildInfo({
                let count = buf.parse::<u16>()?;
                let mut arguments = Vec::with_capacity(count as usize);
                for _ in 0..count {
                    arguments.push(buf.parse()?);
                }
                BuildInfoId { arguments }
            }),
            LF_SUBSTR_LIST => IdData::StringList({
                let count = buf.parse::<u32>()?;
                let mut substrings = Vec::with_capacity(count as usize);
                for _ in 0..count {
                    substrings.push(buf.parse()?);
                }
                StringListId { substrings }
            }),
            LF_STRING_ID => IdData::String(StringId {
                substrings: parse_optional_id_index(&mut buf)?,
                name: parse_string(leaf, &mut buf)?,
            }),
            LF_UDT_SRC_LINE | LF_UDT_MOD_SRC_LINE => {
                let mut udt = UserDefinedTypeSourceId {
                    udt: buf.parse()?,
                    source_file: buf.parse()?,
                    line: buf.parse()?,
                    module: None,
                };

                if leaf == LF_UDT_MOD_SRC_LINE {
                    udt.module = Some(buf.parse()?);
                }

                IdData::UserDefinedTypeSource(udt)
            }
            _ => return Err(Error::UnimplementedTypeKind(leaf)),
        };

        Ok((data, buf.pos()))
    }
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct FunctionId<'t> {
    /// Parent scope of this id.
    pub scope: Option<IdIndex>,
    /// Index of the function type declaration.
    pub function_type: TypeIndex,
    /// Name of the function.
    pub name: RawString<'t>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct MemberFunctionId<'t> {
    /// Index of the parent type.
    pub parent: TypeIndex,
    /// Index of the member function type declaration.
    pub function_type: TypeIndex,
    /// Name of the member function.
    pub name: RawString<'t>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct BuildInfoId {
    /// Indexes of build arguments.
    pub arguments: Vec<IdIndex>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StringListId {
    /// The list of substrings.
    pub substrings: Vec<TypeIndex>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct StringId<'t> {
    /// Index of the list of substrings.
    pub substrings: Option<IdIndex>,
    /// The string.
    pub name: RawString<'t>,
}

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct UserDefinedTypeSourceId {
    /// Index of the UDT's type definition.
    pub udt: TypeIndex,
    /// Index of the source file name.
    pub source_file: IdIndex,
    /// Line number in the source file.
    pub line: u32,
    /// Module that contributes this UDT definition.
    ///
    /// If None, the UDT is declared in the same module.
    pub module: Option<u16>,
}
<|endoftext|>


<commit_before>use std::ops::{Deref, DerefMut};
use std::mem;
use std::collections::HashMap;
use property::Property;

use std::rc::Rc;
use edge::{RawEdge,Edge};
use graph::TraversableToVertex;

/*
* storing in & out edges seperately 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 ok
*/
#[derive(Debug, Clone)]
pub struct RawVertex {
    pub id: i64,
    pub properties: HashMap<String, Property>,
    // pointers on both sides, yay
    pub out_edges: Vec<Edge>,
    pub in_edges:  Vec<Edge>,
}

impl RawVertex {
    pub fn new(id: i64) -> Rc<Box<RawVertex>> {
        let mut props  = HashMap::new();
        Rc::new(Box::new(RawVertex{id:id,
                        properties: props,
                        out_edges: Vec::new(),
                        in_edges: Vec::new()}))
    }
}

#[derive(Clone, Debug)]
pub struct Vertex {
    pub id: i64,
    pub v: Rc<Box<RawVertex>>,
}

impl Vertex {

	pub fn new(id: i64) -> Vertex {
        let raw = RawVertex::new(id);
        Vertex{id:raw.id, v:raw}
	}

    pub fn add_edge(&mut self, to_vertex: &mut Vertex, label: &str) -> Edge {
        println!("add_edge() with label {}", label);

        // let in_vertex =  &mut *(self.v);
        // let out_vertex = &mut *(to_vertex.v);

        // why do i need the raw shit?
        // let mut in_vertex = self;
        // let mut out_vertex = to_vertex;
        // create the edge
        println!("adding vertex of edge {}", label.to_string());

        // keep it on the heap but manage it myself
        let edge = Edge::new(self.clone(),
                             to_vertex.clone(),
                             label.to_string());

        self.out_edges.push(edge.clone());
        to_vertex.in_edges.push(edge.clone());
        edge
    }

    // TODO switch to accepting a &str
    pub fn set_property(&mut self, field: &str, value: Property) {
        self.properties.insert(field.to_string(), value);
    }

    pub fn get_property(&self, field:&str) -> Option<&Property> {
        self.properties.get(&field.to_string())
    }

	pub fn outE(&self) -> Vec<Edge> {
		let mut result = Vec::new();
		for edge in self.out_edges.iter() {
			result.push(edge.clone());
		}
		result
	}

	pub fn inE(&self) -> Vec<Edge> {
		let mut result = Vec::new();
		for edge in self.in_edges.iter() {
			result.push(edge.clone());
		}
		result
	}

}

impl TraversableToVertex for Vertex {
	/* basic traversal operations
	   cannot be chained
	   look at traversal.rs for breadth first chaining
	*/

	/* returns all the outV vertex proxies
	   mainly for internal use
	*/
	fn outV(&self, labels: &[&str]) -> Vec<Vertex> {
		let mut result = Vec::new();

        // convert our labels to a vector of strings
        let mut labels_as_strings : Vec<String> = Vec::new();

        for l in labels {
            let s = l.to_string();
            labels_as_strings.push(l.to_string());
        }

		for edge in self.out_edges.iter() {
            if labels.is_empty() || labels_as_strings.contains(&edge.label) {
				result.push(edge.to_vertex.clone());
            }
		}
		result
	}
	fn inV(&self) -> Vec<Vertex> {
		let mut result = Vec::new();
		for edge in self.in_edges.iter() {
			result.push(edge.from_vertex.clone());
		}
		result
	}

}

impl Deref for Vertex {
    type Target = Rc<Box<RawVertex>>;

    fn deref<'a>(&'a self) -> &'a Rc<Box<RawVertex>> {
        &self.v
    }
}

impl DerefMut for Vertex {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Rc<Box<RawVertex>> {
        &mut self.v
    }
}
<commit_msg>fixed various rwlock issues<commit_after>use std::ops::{Deref, DerefMut};
use std::mem;
use std::collections::HashMap;
use property::Property;

use std::rc::Rc;
use edge::{RawEdge,Edge};
use graph::TraversableToVertex;
use std::sync::RwLock;

/*
* storing in & out edges seperately 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 ok
*/
#[derive(Debug, Clone)]
pub struct RawVertex {
    pub id: i64,
    pub properties: HashMap<String, Property>,
    // pointers on both sides, yay
    pub out_edges: Vec<Edge>,
    pub in_edges:  Vec<Edge>,
}

impl RawVertex {
    pub fn new(id: i64) -> Rc<Box<RwLock<RawVertex>>> {
        let mut props  = HashMap::new();

        let vertex = RawVertex{id:id,
                        properties: props,
                        out_edges: Vec::new(),
                        in_edges: Vec::new()};

        Rc::new(Box::new(RwLock::new(vertex)))
    }
}

#[derive(Clone, Debug)]
pub struct Vertex {
    pub id: i64,
    pub v: Rc<Box<RwLock<RawVertex>>>,
}

impl Vertex {

	pub fn new(id: i64) -> Vertex {
        let raw = RawVertex::new(id);
        Vertex{id:id, v:raw}
	}

    pub fn add_edge(&mut self, to_vertex: &mut Vertex, label: &str) -> Edge {
        println!("add_edge() with label {}", label);

        // let in_vertex =  &mut *(self.v);
        // let out_vertex = &mut *(to_vertex.v);

        // why do i need the raw shit?
        // let mut in_vertex = self;
        // let mut out_vertex = to_vertex;
        // create the edge
        println!("adding vertex of edge {}", label.to_string());

        // keep it on the heap but manage it myself
        let edge = Edge::new(self.clone(),
                             to_vertex.clone(),
                             label.to_string());

        self.write().unwrap().out_edges.push(edge.clone());
        // self.out_edges.push(edge.clone());

        to_vertex.write().unwrap().in_edges.push(edge.clone());
        edge
    }

    // TODO switch to accepting a &str
    pub fn set_property(&mut self, field: &str, value: Property) {
        self.write().unwrap().properties.insert(field.to_string(), value);
    }

    pub fn get_property(&self, field:&str) -> Option<&Property> {
        self.write().unwrap().properties.get(&field.to_string())
    }

	pub fn outE(&self) -> Vec<Edge> {
		let mut result = Vec::new();
		for edge in self.read().unwrap().out_edges.iter() {
			result.push(edge.clone());
		}
		result
	}

	pub fn inE(&self) -> Vec<Edge> {
		let mut result = Vec::new();
		for edge in self.read().unwrap().in_edges.iter() {
			result.push(edge.clone());
		}
		result
	}

}

impl TraversableToVertex for Vertex {
	/* basic traversal operations
	   cannot be chained
	   look at traversal.rs for breadth first chaining
	*/

	/* returns all the outV vertex proxies
	   mainly for internal use
	*/
	fn outV(&self, labels: &[&str]) -> Vec<Vertex> {
		let mut result = Vec::new();

        // convert our labels to a vector of strings
        let mut labels_as_strings : Vec<String> = Vec::new();

        for l in labels {
            let s = l.to_string();
            labels_as_strings.push(l.to_string());
        }

		for edge in self.out_edges.iter() {
            if labels.is_empty() || labels_as_strings.contains(&edge.label) {
				result.push(edge.to_vertex.clone());
            }
		}
		result
	}
	fn inV(&self) -> Vec<Vertex> {
		let mut result = Vec::new();
		for edge in self.in_edges.iter() {
			result.push(edge.from_vertex.clone());
		}
		result
	}

}

impl Deref for Vertex {
    type Target = Rc<Box<RwLock<RawVertex>>>;

    fn deref<'a>(&'a self) -> &'a Rc<Box<RwLock<RawVertex>>> {
        &self.v
    }
}

impl DerefMut for Vertex {
    fn deref_mut<'a>(&'a mut self) -> &'a mut Rc<Box<RwLock<RawVertex>>> {
        &mut self.v
    }
}
<|endoftext|>


<commit_before>use std::rc::Rc;

use xcb;
use cairo::{self, Context, XCBSurface};
use cairo_sys;

use text::{Color, Text};

fn get_root_visual_type(conn: &xcb::Connection, screen: &xcb::Screen) -> xcb::Visualtype {
    for root in conn.get_setup().roots() {
        for allowed_depth in root.allowed_depths() {
            for visual in allowed_depth.visuals() {
                if visual.visual_id() == screen.root_visual() {
                    return visual;
                }
            }
        }
    }
    panic!("No visual type found");
}

// TODO: impl Drop?
pub struct Window {
    conn: Rc<xcb::Connection>,
    screen_idx: usize,
    surface: cairo::Surface,
}

impl Window {
    pub fn new(conn: Rc<xcb::Connection>, screen_idx: usize) -> Window {
        let id = conn.generate_id();

        let surface = {
            let screen = conn.get_setup()
                .roots()
                .nth(screen_idx)
                .expect("invalid screen");
            let values = [(xcb::CW_BACK_PIXEL, screen.black_pixel()),
                          (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE)];

            let (width, height) = (screen.width_in_pixels(), 100);

            xcb::create_window(&conn,
                               xcb::COPY_FROM_PARENT as u8,
                               id,
                               screen.root(),
                               0,
                               0,
                               width,
                               height,
                               10,
                               xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                               screen.root_visual(),
                               &values);

            unsafe {
                let cairo_conn =
                    cairo::XCBConnection::from_raw_none(conn.get_raw_conn() as
                                                        *mut cairo_sys::xcb_connection_t);
                let visual =
                        cairo::XCBVisualType::from_raw_none(&mut get_root_visual_type(&conn,
                                                                                &screen)
                                                                         .base as
                                                            *mut xcb::ffi::xcb_visualtype_t as
                                                            *mut cairo_sys::xcb_visualtype_t);
                let drawable = cairo::XCBDrawable(id);
                cairo::Surface::create(&cairo_conn, &drawable, &visual, width as i32, height as i32)
                // TODO: Update surface width/height when window size changes.
            }
        };

        xcb::map_window(&conn, id);
        conn.flush();

        Window {
            conn,
            screen_idx,
            surface,
        }
    }

    fn screen(&self) -> xcb::Screen {
        self.conn
            .get_setup()
            .roots()
            .nth(self.screen_idx)
            .expect("Invalid screen")
    }

    pub fn expose(&self, texts: Vec<Text>) {
        // Clear to black before re-painting.
        let context = Context::new(&self.surface);
        Color::black().apply_to_context(&context);
        context.paint();

        self.render_text_blocks(texts);
        self.conn.flush();
    }

    fn render_text_blocks(&self, texts: Vec<Text>) {
        // Layout each block of text. After this, we can query the width of each
        // block, which will allow us to do more complex layout below.
        let mut layouts: Vec<_> = texts.into_iter().map(|t| t.layout(&self.surface)).collect();

        // Calculate how much free space we have after laying out all the
        // non-stretch blocks. Split the remaining space (if any) between the
        // stretch blocks. If there isn't enough space for the non-stretch blocks
        // do nothing and allow it to overflow.
        {
            let mut width = 0.0;
            let mut stretched = Vec::new();
            for layout in &mut layouts {
                if !layout.stretch() {
                    width += layout.width();
                } else {
                    stretched.push(layout);
                }
            }

            let remaining_width = self.screen().width_in_pixels() as f64 - width;
            let remaining_width = if remaining_width < 0.0 {
                0.0
            } else {
                remaining_width
            };
            let width_per_stretched = remaining_width / (stretched.len() as f64);
            for layout in &mut stretched {
                layout.set_width(width_per_stretched);
            }
        }

        // TODO: Set the height of the window and the height of each text block(?)
        // to the height of the largest bit of text.

        // Finally, just render each block of text in turn.
        let mut x = 0.0;
        for layout in &layouts {
            layout.render(x, 0.0);
            x += layout.width();
        }
    }
}
<commit_msg>Re-jig Window class.<commit_after>use std::rc::Rc;

use cairo::{self, Context, XCBSurface};
use cairo_sys;
use xcb;

use text::{Color, Text};

fn get_root_visual_type(conn: &xcb::Connection, screen: &xcb::Screen) -> xcb::Visualtype {
    for root in conn.get_setup().roots() {
        for allowed_depth in root.allowed_depths() {
            for visual in allowed_depth.visuals() {
                if visual.visual_id() == screen.root_visual() {
                    return visual;
                }
            }
        }
    }
    panic!("No visual type found");
}

/// Creates a `cairo::Surface` for the XCB window with the given `id`.
fn cairo_surface_for_xcb_window(conn: &xcb::Connection,
                                screen: &xcb::Screen,
                                id: u32,
                                width: i32,
                                height: i32)
                                -> cairo::Surface {
    let cairo_conn = unsafe {
        cairo::XCBConnection::from_raw_none(conn.get_raw_conn() as *mut cairo_sys::xcb_connection_t)
    };
    let visual = unsafe {
        cairo::XCBVisualType::from_raw_none(&mut get_root_visual_type(&conn, &screen).base as
                                            *mut xcb::ffi::xcb_visualtype_t as
                                            *mut cairo_sys::xcb_visualtype_t)
    };
    let drawable = cairo::XCBDrawable(id);
    cairo::Surface::create(&cairo_conn, &drawable, &visual, width, height)
}

// TODO: impl Drop?
pub struct Window {
    conn: Rc<xcb::Connection>,
    window_id: u32,
    screen_idx: usize,
    surface: cairo::Surface,
}

impl Window {
    pub fn new(conn: Rc<xcb::Connection>, screen_idx: usize) -> Window {
        let id = conn.generate_id();

        let surface = {
            let screen = conn.get_setup()
                .roots()
                .nth(screen_idx)
                .expect("invalid screen");
            let values = [(xcb::CW_BACK_PIXEL, screen.black_pixel()),
                          (xcb::CW_EVENT_MASK, xcb::EVENT_MASK_EXPOSURE)];

            let (width, height) = (screen.width_in_pixels(), 100);

            xcb::create_window(&conn,
                               xcb::COPY_FROM_PARENT as u8,
                               id,
                               screen.root(),
                               0,
                               0,
                               width,
                               height,
                               10,
                               xcb::WINDOW_CLASS_INPUT_OUTPUT as u16,
                               screen.root_visual(),
                               &values);

            cairo_surface_for_xcb_window(&conn, &screen, id, width as i32, height as i32)
        };

        let window = Window {
            conn,
            window_id: id,
            screen_idx,
            surface,
        };
        window.flush();
        window.map();
        window
    }

    fn flush(&self) {
        self.conn.flush();
    }

    fn map(&self) {
        xcb::map_window(&self.conn, self.window_id);
    }

    fn screen(&self) -> xcb::Screen {
        self.conn
            .get_setup()
            .roots()
            .nth(self.screen_idx)
            .expect("Invalid screen")
    }

    pub fn expose(&self, texts: Vec<Text>) {
        // Clear to black before re-painting.
        let context = Context::new(&self.surface);
        Color::black().apply_to_context(&context);
        context.paint();

        self.render_text_blocks(texts);
        self.conn.flush();
    }

    fn render_text_blocks(&self, texts: Vec<Text>) {
        // Layout each block of text. After this, we can query the width of each
        // block, which will allow us to do more complex layout below.
        let mut layouts: Vec<_> = texts.into_iter().map(|t| t.layout(&self.surface)).collect();

        // Calculate how much free space we have after laying out all the
        // non-stretch blocks. Split the remaining space (if any) between the
        // stretch blocks. If there isn't enough space for the non-stretch blocks
        // do nothing and allow it to overflow.
        {
            let mut width = 0.0;
            let mut stretched = Vec::new();
            for layout in &mut layouts {
                if !layout.stretch() {
                    width += layout.width();
                } else {
                    stretched.push(layout);
                }
            }

            let remaining_width = self.screen().width_in_pixels() as f64 - width;
            let remaining_width = if remaining_width < 0.0 {
                0.0
            } else {
                remaining_width
            };
            let width_per_stretched = remaining_width / (stretched.len() as f64);
            for layout in &mut stretched {
                layout.set_width(width_per_stretched);
            }
        }

        // TODO: Set the height of the window and the height of each text block(?)
        // to the height of the largest bit of text.

        // Finally, just render each block of text in turn.
        let mut x = 0.0;
        for layout in &layouts {
            layout.render(x, 0.0);
            x += layout.width();
        }
    }
}
<|endoftext|>


<commit_before>use num::{ Float, ToPrimitive, FromPrimitive };
use callback::Callable;
use frame::Frameable;
use color::{ Color, Colorable };
use label::{ FontSize, Labelable };
use dimensions::Dimensions;
use graphics;
use graphics::Graphics;
use graphics::character::CharacterCache;
use label;
use mouse::Mouse;
use point::Point;
use position::Positionable;
use rectangle;
use rectangle::{
    Corner
};
use ui_context::{ UIID, UiContext };
use utils::{
    clamp,
    map_range,
    val_to_string,
};
use vecmath::{
    vec2_add,
    vec2_sub,
};
use widget::Widget;

/// Represents the state of the xy_pad widget.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(XYPad, State, Widget::XYPad(State::Normal));

/// Check the current state of the button.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

/// Draw the crosshair.
fn draw_crosshair<B: Graphics>(
    win_w: f64,
    win_h: f64,
    graphics: &mut B,
    pos: Point,
    line_width: f64,
    vert_x: f64, hori_y: f64,
    pad_dim: Dimensions,
    color: Color
) {
    let draw_state = graphics::default_draw_state();
    let transform = graphics::abs_transform(win_w, win_h);
    let Color(col) = color;
    let line = graphics::Line::new(col, 0.5 * line_width);
    line.draw(
        [vert_x, pos[1], vert_x, pos[1] + pad_dim[1]],
        draw_state,
        transform,
        graphics
    );
    line.draw(
        [pos[0], hori_y, pos[0] + pad_dim[0], hori_y],
        draw_state,
        transform,
        graphics
    );
}

/// A context on which the builder pattern can be implemented.
pub struct XYPad<'a, X, Y, F> {
    ui_id: UIID,
    x: X, min_x: X, max_x: X,
    y: Y, min_y: Y, max_y: Y,
    line_width: f64,
    font_size: FontSize,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
}

impl <'a, X, Y, F> XYPad<'a, X, Y, F> {
    #[inline]
    pub fn line_width(self, width: f64) -> XYPad<'a, X, Y, F> {
        XYPad { line_width: width, ..self }
    }
    #[inline]
    pub fn value_font_size(self, size: FontSize) -> XYPad<'a, X, Y, F> {
        XYPad { font_size: size, ..self }
    }
}

impl<'a, X, Y, F> XYPad<'a, X, Y, F> {
    /// An xy_pad builder method to be implemented by the UiContext.
    pub fn new(ui_id: UIID,
              x_val: X, min_x: X, max_x: X,
              y_val: Y, min_y: Y, max_y: Y) -> XYPad<'a, X, Y, F> {
        XYPad {
            ui_id: ui_id,
            x: x_val, min_x: min_x, max_x: max_x,
            y: y_val, min_y: min_y, max_y: max_y,
            line_width: 1.0,
            font_size: 18u32,
            pos: [0.0, 0.0],
            dim: [128.0, 128.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }
}

impl<'a, X, Y, F> Colorable for XYPad<'a, X, Y, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, X, Y, F> Frameable for XYPad<'a, X, Y, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, X, Y, F> Callable<F> for XYPad<'a, X, Y, F> {
    fn callback(mut self, cb: F) -> Self {
        self.maybe_callback = Some(cb);
        self
    }
}

impl<'a, X, Y, F> Labelable<'a> for XYPad<'a, X, Y, F>
{
    fn label(mut self, text: &'a str) -> Self {
        self.maybe_label = Some(text);
        self
    }

    fn label_color(mut self, color: Color) -> Self {
        self.maybe_label_color = Some(color);
        self
    }

    fn label_font_size(mut self, size: FontSize) -> Self {
        self.maybe_label_font_size = Some(size);
        self
    }
}

impl<'a, X, Y, F> Positionable for XYPad<'a, X, Y, F> {
    fn point(mut self, pos: Point) -> Self {
        self.pos = pos;
        self
    }
}

/*
quack! {
    xy_pad: XYPad['a, X, Y, F]
    get:
        fn () -> Size [] { Size(xy_pad.dim) }
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::XYPad(State::Normal))
        }
        fn () -> Id [] { Id(xy_pad.ui_id) }
    set:
        fn (val: Size) [] { xy_pad.dim = val.0 }
    action:
}
*/

impl<'a, X, Y, F> ::draw::Drawable for XYPad<'a, X, Y, F>
    where
        X: Float + ToPrimitive + FromPrimitive + ToString,
        Y: Float + ToPrimitive + FromPrimitive + ToString,
        F: FnMut(X, Y) + 'a
{

    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {

        // Init.
        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let frame_w2 = frame_w * 2.0;
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        let pad_dim = vec2_sub(self.dim, [frame_w2; 2]);
        let pad_pos = vec2_add(self.pos, [frame_w, frame_w]);
        let is_over_pad = rectangle::is_over(pad_pos, mouse.pos, pad_dim);
        let new_state = get_new_state(is_over_pad, state, mouse);

        // Determine new values.
        let (new_x, new_y) = match (is_over_pad, new_state) {
            (_, State::Normal) | (_, State::Highlighted) => (self.x, self.y),
            (_, State::Clicked) => {
                let temp_x = clamp(mouse.pos[0], pad_pos[0], pad_pos[0] + pad_dim[0]);
                let temp_y = clamp(mouse.pos[1], pad_pos[1], pad_pos[1] + pad_dim[1]);
                (map_range(temp_x - self.pos[0], pad_dim[0], 0.0, self.min_x, self.max_x),
                 map_range(temp_y - self.pos[1], pad_dim[1], 0.0, self.min_y, self.max_y))
            }
        };

        // Callback if value is changed or the pad is clicked/released.
        match self.maybe_callback {
            Some(ref mut callback) => {
                if self.x != new_x || self.y != new_y { (*callback)(new_x, new_y) }
                else {
                    match (state, new_state) {
                        (State::Highlighted, State::Clicked)
                        | (State::Clicked, State::Highlighted) => (*callback)(new_x, new_y),
                        _ => (),
                    }
                }
            },
            None => (),
        }

        // Draw.
        let rect_state = new_state.as_rectangle_state();
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        rectangle::draw(uic.win_w, uic.win_h, graphics, rect_state, self.pos,
                        self.dim, maybe_frame, color);
        let (vert_x, hori_y) = match (is_over_pad, new_state) {
            (_, State::Normal) | (_, State::Highlighted) =>
                (pad_pos[0] + map_range(new_x, self.min_x, self.max_x, pad_dim[0], 0.0),
                 pad_pos[1] + map_range(new_y, self.min_y, self.max_y, pad_dim[1], 0.0)),
            (_, State::Clicked) =>
                (clamp(mouse.pos[0], pad_pos[0], pad_pos[0] + pad_dim[0]),
                 clamp(mouse.pos[1], pad_pos[1], pad_pos[1] + pad_dim[1])),
        };
        // Crosshair.
        draw_crosshair(uic.win_w, uic.win_h, graphics, pad_pos, self.line_width,
                       vert_x, hori_y, pad_dim, color.plain_contrast());
        // Label.
        if let Some(l_text) = self.maybe_label {
            let l_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
            let l_size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
            let l_w = label::width(uic, l_size, l_text);
            let l_x = pad_pos[0] + (pad_dim[0] - l_w) / 2.0;
            let l_y = pad_pos[1] + (pad_dim[1] - l_size as f64) / 2.0;
            let l_pos = [l_x, l_y];
            uic.draw_text(graphics, l_pos, l_size, l_color, l_text);
        }
        // xy value string.
        let x_string = val_to_string(self.x, self.max_x,
                                     self.max_x - self.min_x, self.dim[0] as usize);
        let y_string = val_to_string(self.y, self.max_y,
                                     self.max_y - self.min_y, self.dim[1] as usize);
        let xy_string = format!("{}, {}", x_string, y_string);
        let xy_string_w = label::width(uic, self.font_size, &xy_string);
        let xy_string_pos = {
            match rectangle::corner(pad_pos, [vert_x, hori_y], pad_dim) {
                Corner::TopLeft => [vert_x, hori_y],
                Corner::TopRight => [vert_x - xy_string_w, hori_y],
                Corner::BottomLeft => [vert_x, hori_y - self.font_size as f64],
                Corner::BottomRight => [vert_x - xy_string_w, hori_y - self.font_size as f64],
            }
        };
        uic.draw_text(graphics, xy_string_pos, self.font_size,
                    color.plain_contrast(), &xy_string);

        set_state(uic, self.ui_id, Widget::XYPad(new_state), self.pos, self.dim);

    }
}
<commit_msg>Implemented `Shapeable` for `XYPad`<commit_after>use num::{ Float, ToPrimitive, FromPrimitive };
use callback::Callable;
use frame::Frameable;
use color::{ Color, Colorable };
use label::{ FontSize, Labelable };
use dimensions::Dimensions;
use graphics;
use graphics::Graphics;
use graphics::character::CharacterCache;
use label;
use mouse::Mouse;
use point::Point;
use position::Positionable;
use shape::Shapeable;
use rectangle;
use rectangle::{
    Corner
};
use ui_context::{ UIID, UiContext };
use utils::{
    clamp,
    map_range,
    val_to_string,
};
use vecmath::{
    vec2_add,
    vec2_sub,
};
use widget::Widget;

/// Represents the state of the xy_pad widget.
#[derive(Debug, PartialEq, Clone, Copy)]
pub enum State {
    Normal,
    Highlighted,
    Clicked,
}

impl State {
    /// Return the associated Rectangle state.
    fn as_rectangle_state(&self) -> rectangle::State {
        match self {
            &State::Normal => rectangle::State::Normal,
            &State::Highlighted => rectangle::State::Highlighted,
            &State::Clicked => rectangle::State::Clicked,
        }
    }
}

widget_fns!(XYPad, State, Widget::XYPad(State::Normal));

/// Check the current state of the button.
fn get_new_state(is_over: bool,
                 prev: State,
                 mouse: Mouse) -> State {
    use mouse::ButtonState::{Down, Up};
    use self::State::{Normal, Highlighted, Clicked};
    match (is_over, prev, mouse.left) {
        (true,  Normal,  Down) => Normal,
        (true,  _,       Down) => Clicked,
        (true,  _,       Up)   => Highlighted,
        (false, Clicked, Down) => Clicked,
        _                      => Normal,
    }
}

/// Draw the crosshair.
fn draw_crosshair<B: Graphics>(
    win_w: f64,
    win_h: f64,
    graphics: &mut B,
    pos: Point,
    line_width: f64,
    vert_x: f64, hori_y: f64,
    pad_dim: Dimensions,
    color: Color
) {
    let draw_state = graphics::default_draw_state();
    let transform = graphics::abs_transform(win_w, win_h);
    let Color(col) = color;
    let line = graphics::Line::new(col, 0.5 * line_width);
    line.draw(
        [vert_x, pos[1], vert_x, pos[1] + pad_dim[1]],
        draw_state,
        transform,
        graphics
    );
    line.draw(
        [pos[0], hori_y, pos[0] + pad_dim[0], hori_y],
        draw_state,
        transform,
        graphics
    );
}

/// A context on which the builder pattern can be implemented.
pub struct XYPad<'a, X, Y, F> {
    ui_id: UIID,
    x: X, min_x: X, max_x: X,
    y: Y, min_y: Y, max_y: Y,
    line_width: f64,
    font_size: FontSize,
    pos: Point,
    dim: Dimensions,
    maybe_callback: Option<F>,
    maybe_color: Option<Color>,
    maybe_frame: Option<f64>,
    maybe_frame_color: Option<Color>,
    maybe_label: Option<&'a str>,
    maybe_label_color: Option<Color>,
    maybe_label_font_size: Option<u32>,
}

impl <'a, X, Y, F> XYPad<'a, X, Y, F> {
    #[inline]
    pub fn line_width(self, width: f64) -> XYPad<'a, X, Y, F> {
        XYPad { line_width: width, ..self }
    }
    #[inline]
    pub fn value_font_size(self, size: FontSize) -> XYPad<'a, X, Y, F> {
        XYPad { font_size: size, ..self }
    }
}

impl<'a, X, Y, F> XYPad<'a, X, Y, F> {
    /// An xy_pad builder method to be implemented by the UiContext.
    pub fn new(ui_id: UIID,
              x_val: X, min_x: X, max_x: X,
              y_val: Y, min_y: Y, max_y: Y) -> XYPad<'a, X, Y, F> {
        XYPad {
            ui_id: ui_id,
            x: x_val, min_x: min_x, max_x: max_x,
            y: y_val, min_y: min_y, max_y: max_y,
            line_width: 1.0,
            font_size: 18u32,
            pos: [0.0, 0.0],
            dim: [128.0, 128.0],
            maybe_callback: None,
            maybe_color: None,
            maybe_frame: None,
            maybe_frame_color: None,
            maybe_label: None,
            maybe_label_color: None,
            maybe_label_font_size: None,
        }
    }
}

impl<'a, X, Y, F> Colorable for XYPad<'a, X, Y, F> {
    fn color(mut self, color: Color) -> Self {
        self.maybe_color = Some(color);
        self
    }
}

impl<'a, X, Y, F> Frameable for XYPad<'a, X, Y, F> {
    fn frame(mut self, width: f64) -> Self {
        self.maybe_frame = Some(width);
        self
    }
    fn frame_color(mut self, color: Color) -> Self {
        self.maybe_frame_color = Some(color);
        self
    }
}

impl<'a, X, Y, F> Callable<F> for XYPad<'a, X, Y, F> {
    fn callback(mut self, cb: F) -> Self {
        self.maybe_callback = Some(cb);
        self
    }
}

impl<'a, X, Y, F> Labelable<'a> for XYPad<'a, X, Y, F>
{
    fn label(mut self, text: &'a str) -> Self {
        self.maybe_label = Some(text);
        self
    }

    fn label_color(mut self, color: Color) -> Self {
        self.maybe_label_color = Some(color);
        self
    }

    fn label_font_size(mut self, size: FontSize) -> Self {
        self.maybe_label_font_size = Some(size);
        self
    }
}

impl<'a, X, Y, F> Positionable for XYPad<'a, X, Y, F> {
    fn point(mut self, pos: Point) -> Self {
        self.pos = pos;
        self
    }
}

impl<'a, X, Y, F> Shapeable for XYPad<'a, X, Y, F> {
    fn get_dim(&self) -> Dimensions { self.dim }
    fn dim(mut self, dim: Dimensions) -> Self { self.dim = dim; self }
}

/*
quack! {
    xy_pad: XYPad['a, X, Y, F]
    get:
        fn () -> DefaultWidgetState [] {
            DefaultWidgetState(Widget::XYPad(State::Normal))
        }
        fn () -> Id [] { Id(xy_pad.ui_id) }
    set:
    action:
}
*/

impl<'a, X, Y, F> ::draw::Drawable for XYPad<'a, X, Y, F>
    where
        X: Float + ToPrimitive + FromPrimitive + ToString,
        Y: Float + ToPrimitive + FromPrimitive + ToString,
        F: FnMut(X, Y) + 'a
{

    fn draw<B, C>(&mut self, uic: &mut UiContext<C>, graphics: &mut B)
        where
            B: Graphics<Texture = <C as CharacterCache>::Texture>,
            C: CharacterCache
    {

        // Init.
        let state = *get_state(uic, self.ui_id);
        let mouse = uic.get_mouse_state();
        let frame_w = self.maybe_frame.unwrap_or(uic.theme.frame_width);
        let frame_w2 = frame_w * 2.0;
        let maybe_frame = match frame_w > 0.0 {
            true => Some((frame_w, self.maybe_frame_color.unwrap_or(uic.theme.frame_color))),
            false => None,
        };
        let pad_dim = vec2_sub(self.dim, [frame_w2; 2]);
        let pad_pos = vec2_add(self.pos, [frame_w, frame_w]);
        let is_over_pad = rectangle::is_over(pad_pos, mouse.pos, pad_dim);
        let new_state = get_new_state(is_over_pad, state, mouse);

        // Determine new values.
        let (new_x, new_y) = match (is_over_pad, new_state) {
            (_, State::Normal) | (_, State::Highlighted) => (self.x, self.y),
            (_, State::Clicked) => {
                let temp_x = clamp(mouse.pos[0], pad_pos[0], pad_pos[0] + pad_dim[0]);
                let temp_y = clamp(mouse.pos[1], pad_pos[1], pad_pos[1] + pad_dim[1]);
                (map_range(temp_x - self.pos[0], pad_dim[0], 0.0, self.min_x, self.max_x),
                 map_range(temp_y - self.pos[1], pad_dim[1], 0.0, self.min_y, self.max_y))
            }
        };

        // Callback if value is changed or the pad is clicked/released.
        match self.maybe_callback {
            Some(ref mut callback) => {
                if self.x != new_x || self.y != new_y { (*callback)(new_x, new_y) }
                else {
                    match (state, new_state) {
                        (State::Highlighted, State::Clicked)
                        | (State::Clicked, State::Highlighted) => (*callback)(new_x, new_y),
                        _ => (),
                    }
                }
            },
            None => (),
        }

        // Draw.
        let rect_state = new_state.as_rectangle_state();
        let color = self.maybe_color.unwrap_or(uic.theme.shape_color);
        rectangle::draw(uic.win_w, uic.win_h, graphics, rect_state, self.pos,
                        self.dim, maybe_frame, color);
        let (vert_x, hori_y) = match (is_over_pad, new_state) {
            (_, State::Normal) | (_, State::Highlighted) =>
                (pad_pos[0] + map_range(new_x, self.min_x, self.max_x, pad_dim[0], 0.0),
                 pad_pos[1] + map_range(new_y, self.min_y, self.max_y, pad_dim[1], 0.0)),
            (_, State::Clicked) =>
                (clamp(mouse.pos[0], pad_pos[0], pad_pos[0] + pad_dim[0]),
                 clamp(mouse.pos[1], pad_pos[1], pad_pos[1] + pad_dim[1])),
        };
        // Crosshair.
        draw_crosshair(uic.win_w, uic.win_h, graphics, pad_pos, self.line_width,
                       vert_x, hori_y, pad_dim, color.plain_contrast());
        // Label.
        if let Some(l_text) = self.maybe_label {
            let l_color = self.maybe_label_color.unwrap_or(uic.theme.label_color);
            let l_size = self.maybe_label_font_size.unwrap_or(uic.theme.font_size_medium);
            let l_w = label::width(uic, l_size, l_text);
            let l_x = pad_pos[0] + (pad_dim[0] - l_w) / 2.0;
            let l_y = pad_pos[1] + (pad_dim[1] - l_size as f64) / 2.0;
            let l_pos = [l_x, l_y];
            uic.draw_text(graphics, l_pos, l_size, l_color, l_text);
        }
        // xy value string.
        let x_string = val_to_string(self.x, self.max_x,
                                     self.max_x - self.min_x, self.dim[0] as usize);
        let y_string = val_to_string(self.y, self.max_y,
                                     self.max_y - self.min_y, self.dim[1] as usize);
        let xy_string = format!("{}, {}", x_string, y_string);
        let xy_string_w = label::width(uic, self.font_size, &xy_string);
        let xy_string_pos = {
            match rectangle::corner(pad_pos, [vert_x, hori_y], pad_dim) {
                Corner::TopLeft => [vert_x, hori_y],
                Corner::TopRight => [vert_x - xy_string_w, hori_y],
                Corner::BottomLeft => [vert_x, hori_y - self.font_size as f64],
                Corner::BottomRight => [vert_x - xy_string_w, hori_y - self.font_size as f64],
            }
        };
        uic.draw_text(graphics, xy_string_pos, self.font_size,
                    color.plain_contrast(), &xy_string);

        set_state(uic, self.ui_id, Widget::XYPad(new_state), self.pos, self.dim);

    }
}
<|endoftext|>


<commit_before>//! This crate provides the `#[quickcheck]` attribute. Its use is
//! documented in the `quickcheck` crate.

#![crate_name = "quickcheck_macros"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_root_url = "http://burntsushi.net/rustdoc/quickcheck")]

#![feature(plugin_registrar, managed_boxes)]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::codemap;
use syntax::parse::token;
use syntax::ext::base::{ExtCtxt, ItemModifier};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;

use rustc::plugin::Registry;

/// For the `#[quickcheck]` attribute. Do not use.
#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("quickcheck"),
                                  ItemModifier(box expand_meta_quickcheck));
}

/// Expands the `#[quickcheck]` attribute.
///
/// Expands:
/// ```
/// #[quickcheck]
/// fn check_something(_: uint) -> bool {
///     true
/// }
/// ```
/// to:
/// ```
/// #[test]
/// fn check_something() {
///     fn check_something(_: uint) -> bool {
///         true
///     }
///     ::quickcheck::quickcheck(check_something)
/// }
/// ```
fn expand_meta_quickcheck(cx: &mut ExtCtxt,
                          span: codemap::Span,
                          _: &ast::MetaItem,
                          item: P<ast::Item>) -> P<ast::Item> {
    match item.node {
        ast::ItemFn(..) | ast::ItemStatic(..) => {
            // Copy original function without attributes
            let prop = P(ast::Item {attrs: Vec::new(), ..(*item).clone()});
            // ::quickcheck::quickcheck
            let check_ident = token::str_to_ident("quickcheck");
            let check_path = vec!(check_ident, check_ident);
            // Wrap original function in new outer function, calling ::quickcheck::quickcheck()
            let fn_decl = P(codemap::respan(span, ast::DeclItem(prop.clone())));
            let inner_fn = P(codemap::respan(span, ast::StmtDecl(fn_decl, ast::DUMMY_NODE_ID)));
            let inner_ident = cx.expr_ident(span, prop.ident);
            let check_call = cx.expr_call_global(span, check_path, vec![inner_ident]);
            let body = cx.block(span, vec![inner_fn], Some(check_call));
            let test = cx.item_fn(span, item.ident, Vec::new(), cx.ty_nil(), body);

            // Copy attributes from original function
            let mut attrs = item.attrs.clone();
            // Add #[test] attribute
            attrs.push(cx.attribute(span, cx.meta_word(span, token::intern_and_get_ident("test"))));
            // Attach the attributes to the outer function
            P(ast::Item {attrs: attrs, ..(*test).clone()})
        },
        _ => {
            cx.span_err(span, "#[quickcheck] only supported on statics and functions");
            item
        }
    }
}
<commit_msg>Fix: `ItemModifier` variant has been renamed to `Modifier`<commit_after>//! This crate provides the `#[quickcheck]` attribute. Its use is
//! documented in the `quickcheck` crate.

#![crate_name = "quickcheck_macros"]
#![crate_type = "dylib"]
#![license = "MIT/ASL2"]
#![doc(html_root_url = "http://burntsushi.net/rustdoc/quickcheck")]

#![feature(plugin_registrar, managed_boxes)]

extern crate syntax;
extern crate rustc;

use syntax::ast;
use syntax::codemap;
use syntax::parse::token;
use syntax::ext::base::{ExtCtxt, Modifier};
use syntax::ext::build::AstBuilder;
use syntax::ptr::P;

use rustc::plugin::Registry;

/// For the `#[quickcheck]` attribute. Do not use.
#[plugin_registrar]
#[doc(hidden)]
pub fn plugin_registrar(reg: &mut Registry) {
    reg.register_syntax_extension(token::intern("quickcheck"),
                                  Modifier(box expand_meta_quickcheck));
}

/// Expands the `#[quickcheck]` attribute.
///
/// Expands:
/// ```
/// #[quickcheck]
/// fn check_something(_: uint) -> bool {
///     true
/// }
/// ```
/// to:
/// ```
/// #[test]
/// fn check_something() {
///     fn check_something(_: uint) -> bool {
///         true
///     }
///     ::quickcheck::quickcheck(check_something)
/// }
/// ```
fn expand_meta_quickcheck(cx: &mut ExtCtxt,
                          span: codemap::Span,
                          _: &ast::MetaItem,
                          item: P<ast::Item>) -> P<ast::Item> {
    match item.node {
        ast::ItemFn(..) | ast::ItemStatic(..) => {
            // Copy original function without attributes
            let prop = P(ast::Item {attrs: Vec::new(), ..(*item).clone()});
            // ::quickcheck::quickcheck
            let check_ident = token::str_to_ident("quickcheck");
            let check_path = vec!(check_ident, check_ident);
            // Wrap original function in new outer function, calling ::quickcheck::quickcheck()
            let fn_decl = P(codemap::respan(span, ast::DeclItem(prop.clone())));
            let inner_fn = P(codemap::respan(span, ast::StmtDecl(fn_decl, ast::DUMMY_NODE_ID)));
            let inner_ident = cx.expr_ident(span, prop.ident);
            let check_call = cx.expr_call_global(span, check_path, vec![inner_ident]);
            let body = cx.block(span, vec![inner_fn], Some(check_call));
            let test = cx.item_fn(span, item.ident, Vec::new(), cx.ty_nil(), body);

            // Copy attributes from original function
            let mut attrs = item.attrs.clone();
            // Add #[test] attribute
            attrs.push(cx.attribute(span, cx.meta_word(span, token::intern_and_get_ident("test"))));
            // Attach the attributes to the outer function
            P(ast::Item {attrs: attrs, ..(*test).clone()})
        },
        _ => {
            cx.span_err(span, "#[quickcheck] only supported on statics and functions");
            item
        }
    }
}
<|endoftext|>


<commit_before>use syntax;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;

/// Create a fake ExtCtxt to perform macro quasiquotes outside of rustc plugins
pub fn with_fake_extctxt<T>(f: |&ExtCtxt| -> T) -> T {
  let ps = syntax::parse::new_parse_sess();

  let mut cx = syntax::ext::base::ExtCtxt::new(&ps, Vec::new(),
    syntax::ext::expand::ExpansionConfig::default("rust-peg".to_string())
  );

  cx.bt_push(syntax::codemap::ExpnInfo{
    call_site: DUMMY_SP,
    callee: syntax::codemap::NameAndSpan {
      name: "".to_string(),
      format: syntax::codemap::MacroBang,
      span: None,
    }
  });

  f(&cx)
}
<commit_msg>unboxed closure update<commit_after>use syntax;
use syntax::codemap::DUMMY_SP;
use syntax::ext::base::ExtCtxt;

/// Create a fake ExtCtxt to perform macro quasiquotes outside of rustc plugins
pub fn with_fake_extctxt<T, F: Fn(&ExtCtxt) -> T>(f: F) -> T {
  let ps = syntax::parse::new_parse_sess();

  let mut cx = syntax::ext::base::ExtCtxt::new(&ps, Vec::new(),
    syntax::ext::expand::ExpansionConfig::default("rust-peg".to_string())
  );

  cx.bt_push(syntax::codemap::ExpnInfo{
    call_site: DUMMY_SP,
    callee: syntax::codemap::NameAndSpan {
      name: "".to_string(),
      format: syntax::codemap::MacroBang,
      span: None,
    }
  });

  f(&cx)
}
<|endoftext|>


<commit_before>use std::ptr;

use runtime::{Class, Messageable, Object, Sel, objc_msgSend};
use foundation::INSObject;

#[unsafe_no_drop_flag]
pub struct Id {
	ptr: *Object,
}

impl Id {
	pub fn nil() -> Id {
		Id { ptr: ptr::null() }
	}

	unsafe fn retain(&self) {
		let retain = Sel::register("retain");
		objc_msgSend(self.as_ptr(), retain);
	}

	unsafe fn release(&self) {
		let release = Sel::register("release");
		objc_msgSend(self.as_ptr(), release);
	}

	pub unsafe fn from_ptr(ptr: *Object) -> Id {
		let id = Id { ptr: ptr };
		id.retain();
		id
	}

	pub unsafe fn from_retained_ptr(ptr: *Object) -> Id {
		Id { ptr: ptr }
	}
}

impl Messageable for Id {
	unsafe fn as_ptr(&self) -> *Object {
		self.ptr
	}
}

impl Clone for Id {
	fn clone(&self) -> Id {
		unsafe {
			Id::from_ptr(self.ptr)
		}
	}
}

impl Drop for Id {
	fn drop(&mut self) {
		if !self.ptr.is_null() {
			unsafe {
				self.release();
			}
			self.ptr = ptr::null();
		}
	}
}

pub trait FromId {
	unsafe fn from_id(id: Id) -> Self;

	unsafe fn from_ptr(ptr: *Object) -> Self {
		FromId::from_id(Id::from_ptr(ptr))
	}

	unsafe fn from_retained_ptr(ptr: *Object) -> Self {
		FromId::from_id(Id::from_retained_ptr(ptr))
	}

	unsafe fn maybe_from_ptr(ptr: *Object) -> Option<Self> {
		if ptr.is_null() {
			None
		} else {
			Some(FromId::from_ptr(ptr))
		}
	}

	unsafe fn maybe_from_retained_ptr(ptr: *Object) -> Option<Self> {
		if ptr.is_null() {
			None
		} else {
			Some(FromId::from_retained_ptr(ptr))
		}
	}
}

pub struct ClassName<T> {
	name: &'static str,
}

impl<T> ClassName<T> {
	pub fn from_str(name: &'static str) -> ClassName<T> {
		ClassName { name: name }
	}

	pub fn as_str(&self) -> &'static str {
		self.name
	}
}

pub fn class<T: INSObject>() -> Class {
	let name: ClassName<T> = INSObject::class_name();
	Class::get(name.as_str())
}
<commit_msg>Use msg_send macro in Id as well.<commit_after>use std::ptr;

use runtime::{Class, Messageable, Object};
use foundation::INSObject;

#[unsafe_no_drop_flag]
pub struct Id {
	ptr: *Object,
}

impl Id {
	pub fn nil() -> Id {
		Id { ptr: ptr::null() }
	}

	unsafe fn retain(&self) {
		msg_send![self.as_ptr() retain];
	}

	unsafe fn release(&self) {
		msg_send![self.as_ptr() release];
	}

	pub unsafe fn from_ptr(ptr: *Object) -> Id {
		let id = Id { ptr: ptr };
		id.retain();
		id
	}

	pub unsafe fn from_retained_ptr(ptr: *Object) -> Id {
		Id { ptr: ptr }
	}
}

impl Messageable for Id {
	unsafe fn as_ptr(&self) -> *Object {
		self.ptr
	}
}

impl Clone for Id {
	fn clone(&self) -> Id {
		unsafe {
			Id::from_ptr(self.ptr)
		}
	}
}

impl Drop for Id {
	fn drop(&mut self) {
		if !self.ptr.is_null() {
			unsafe {
				self.release();
			}
			self.ptr = ptr::null();
		}
	}
}

pub trait FromId {
	unsafe fn from_id(id: Id) -> Self;

	unsafe fn from_ptr(ptr: *Object) -> Self {
		FromId::from_id(Id::from_ptr(ptr))
	}

	unsafe fn from_retained_ptr(ptr: *Object) -> Self {
		FromId::from_id(Id::from_retained_ptr(ptr))
	}

	unsafe fn maybe_from_ptr(ptr: *Object) -> Option<Self> {
		if ptr.is_null() {
			None
		} else {
			Some(FromId::from_ptr(ptr))
		}
	}

	unsafe fn maybe_from_retained_ptr(ptr: *Object) -> Option<Self> {
		if ptr.is_null() {
			None
		} else {
			Some(FromId::from_retained_ptr(ptr))
		}
	}
}

pub struct ClassName<T> {
	name: &'static str,
}

impl<T> ClassName<T> {
	pub fn from_str(name: &'static str) -> ClassName<T> {
		ClassName { name: name }
	}

	pub fn as_str(&self) -> &'static str {
		self.name
	}
}

pub fn class<T: INSObject>() -> Class {
	let name: ClassName<T> = INSObject::class_name();
	Class::get(name.as_str())
}
<|endoftext|>