<commit_before>use crate::err::{self, Result};
use smallvec::{smallvec, SmallVec};
use std::collections::VecDeque;
use std::fmt;
use tui::layout::Rect;
use tui::style::{Color, Style};
use tui::widgets::Text;

/// A scrolling log to display messages along with their status.
///
/// # Example Output
///
/// ```
/// Message with ok status... ok
/// Message with failed status... failed
/// .. error cause
/// Message with pending status...
/// ```
pub struct StatusLog<'a> {
    items: VecDeque<LogItem<'a>>,
    draw_items: VecDeque<Text<'a>>,
    max_items: u16,
}

impl<'a> StatusLog<'a> {
    /// Create a new `StatusLog`.
    pub fn new() -> StatusLog<'a> {
        StatusLog {
            items: VecDeque::new(),
            draw_items: VecDeque::new(),
            max_items: 1,
        }
    }

    /// Trim the log so all items fit within the specified `size`.
    ///
    /// Assumes there is both a top and bottom border if `with_border` is true.
    pub fn adjust_to_size(&mut self, size: Rect, with_border: bool) {
        self.max_items = if with_border {
            // One border edge is 1 character tall
            size.height.saturating_sub(2)
        } else {
            size.height
        };

        while self.items.len() > self.max_items as usize {
            self.pop_front();
        }
    }

    /// Push a new `LogItem` to the log.
    ///
    /// # Example
    ///
    /// ```
    /// let mut log = StatusLog::new();
    /// log.push(LogItem::pending("Explicitly defined LogItem"));
    /// log.push("Implicitly defined LogItem with a pending status");
    /// ```
    pub fn push<I>(&mut self, item: I)
    where
        I: Into<LogItem<'a>>,
    {
        let item = item.into();
        self.draw_items.extend(item.text_items().iter().cloned());
        self.items.push_back(item);
    }

    /// Removes the first `LogItem` from the `StatusLog` if it exists.
    pub fn pop_front(&mut self) {
        let item = match self.items.pop_front() {
            Some(item) => item,
            None => return,
        };

        // Since we only allow pushing items to the back of the log, we can safely
        // pop all of the item's internal elements from the front of the draw list.
        for _ in 0..item.text_items().len() {
            self.draw_items.pop_front();
        }
    }

    /// Execute the function defined by `f` and pushes its result
    /// as a new `LogItem` with the description specified by `desc`.
    ///
    /// # Example
    ///
    /// ```
    /// let mut log = StatusLog::new();
    /// log.capture_status("Executing function 1", || Ok(()));
    /// ```
    pub fn capture_status<S, F>(&mut self, desc: S, f: F)
    where
        S: Into<String>,
        F: FnOnce() -> Result<()>,
    {
        let status = match f() {
            Ok(_) => LogItemStatus::Ok,
            Err(err) => LogItemStatus::Failed(Some(err)),
        };

        self.push(LogItem::with_status(desc, status));
    }

    /// Returns an iterator over all of the text items ready to be drawn.
    pub fn draw_items_iter(&self) -> impl Iterator<Item = &Text> {
        self.draw_items.iter()
    }
}

/// A log entry meant to be used with `StatusLog`.
pub struct LogItem<'a>(SmallVec<[Text<'a>; 3]>);

impl<'a> LogItem<'a> {
    /// Create a LogItem with the specified description and status.
    pub fn with_status<S>(desc: S, status: LogItemStatus) -> LogItem<'a>
    where
        S: Into<String>,
    {
        let text_items = LogItem::create_text_items(desc, status);
        LogItem(text_items)
    }

    /// Create a LogItem with its status set to `LogItemStatus::Pending`.
    pub fn pending<S>(desc: S) -> LogItem<'a>
    where
        S: Into<String>,
    {
        LogItem::with_status(desc, LogItemStatus::Pending)
    }

    /// Create a LogItem with its status set to `LogItemStatus::Failed`.
    pub fn failed<S, O>(desc: S, err: O) -> LogItem<'a>
    where
        S: Into<String>,
        O: Into<Option<err::Error>>,
    {
        LogItem::with_status(desc, LogItemStatus::Failed(err.into()))
    }

    fn create_text_items<S>(desc: S, status: LogItemStatus) -> SmallVec<[Text<'a>; 3]>
    where
        S: Into<String>,
    {
        let desc_text = if status.is_resolved() {
            Text::raw(format!("{}... ", desc.into()))
        } else {
            Text::raw(format!("{}...\n", desc.into()))
        };

        let mut text_items = smallvec![desc_text];

        // Beyond this point, we only need to resolve the status (if we have it)
        if !status.is_resolved() {
            return text_items;
        }

        let status_text = {
            let color = match status {
                LogItemStatus::Ok => Color::Green,
                LogItemStatus::Pending => Color::Yellow,
                LogItemStatus::Failed(_) => Color::Red,
            };

            Text::styled(format!("{}\n", status), Style::default().fg(color))
        };

        text_items.push(status_text);

        if let LogItemStatus::Failed(Some(err)) = &status {
            let err_text = Text::styled(format!(".. {}\n", err), Style::default().fg(Color::Red));
            text_items.push(err_text);
        }

        text_items
    }

    /// Returns a reference to all of the internal text elements.
    ///
    /// This method is useful for drawing the `LogItem`.
    pub fn text_items(&self) -> &SmallVec<[Text<'a>; 3]> {
        &self.0
    }
}

impl<'a, T> From<T> for LogItem<'a>
where
    T: Into<String>,
{
    fn from(value: T) -> Self {
        LogItem::pending(value)
    }
}

/// The result of a log event. Meant to be used with `LogItem`.
pub enum LogItemStatus {
    Ok,
    Pending,
    Failed(Option<err::Error>),
}

impl LogItemStatus {
    /// Returns true if the status indicates that it's not waiting for the result of an operation.
    pub fn is_resolved(&self) -> bool {
        match self {
            LogItemStatus::Ok | LogItemStatus::Failed(_) => true,
            LogItemStatus::Pending => false,
        }
    }
}

impl fmt::Display for LogItemStatus {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            LogItemStatus::Ok => write!(f, "ok"),
            LogItemStatus::Pending => write!(f, "pending"),
            LogItemStatus::Failed(_) => write!(f, "failed"),
        }
    }
}
<commit_msg>anup: improve documentation of interface::tui::component::log module<commit_after>use crate::err::{self, Result};
use smallvec::{smallvec, SmallVec};
use std::collections::VecDeque;
use std::fmt;
use tui::layout::Rect;
use tui::style::{Color, Style};
use tui::widgets::Text;

/// A scrolling log to display messages along with their status.
pub struct StatusLog<'a> {
    items: VecDeque<LogItem<'a>>,
    draw_items: VecDeque<Text<'a>>,
    max_items: u16,
}

impl<'a> StatusLog<'a> {
    /// Create a new `StatusLog`.
    pub fn new() -> StatusLog<'a> {
        StatusLog {
            items: VecDeque::new(),
            draw_items: VecDeque::new(),
            max_items: 1,
        }
    }

    /// Trims the `StatusLog` so all items fit within `size`.
    ///
    /// Assumes there is both a top and bottom border if `with_border` is true.
    pub fn adjust_to_size(&mut self, size: Rect, with_border: bool) {
        self.max_items = if with_border {
            // One border edge is 1 character tall
            size.height.saturating_sub(2)
        } else {
            size.height
        };

        while self.items.len() > self.max_items as usize {
            self.pop_front();
        }
    }

    /// Pushes a new `LogItem` to the end of the log.
    pub fn push<I>(&mut self, item: I)
    where
        I: Into<LogItem<'a>>,
    {
        let item = item.into();
        self.draw_items.extend(item.text_items().iter().cloned());
        self.items.push_back(item);
    }

    /// Removes the first `LogItem` from the `StatusLog` if it exists.
    pub fn pop_front(&mut self) {
        let item = match self.items.pop_front() {
            Some(item) => item,
            None => return,
        };

        // Since we only allow pushing items to the back of the log, we can safely
        // pop all of the item's internal elements from the front of the draw list.
        for _ in 0..item.text_items().len() {
            self.draw_items.pop_front();
        }
    }

    /// Executes the function defined by `f` and pushes its result
    /// to the end of the `StatusLog` with the description specified by `desc`.
    pub fn capture_status<S, F>(&mut self, desc: S, f: F)
    where
        S: Into<String>,
        F: FnOnce() -> Result<()>,
    {
        let status = match f() {
            Ok(_) => LogItemStatus::Ok,
            Err(err) => LogItemStatus::Failed(Some(err)),
        };

        self.push(LogItem::with_status(desc, status));
    }

    /// Returns an iterator over all of the text items ready to be drawn.
    pub fn draw_items_iter(&self) -> impl Iterator<Item = &Text> {
        self.draw_items.iter()
    }
}

/// A log entry meant to be used with `StatusLog`.
pub struct LogItem<'a>(SmallVec<[Text<'a>; 3]>);

impl<'a> LogItem<'a> {
    /// Create a LogItem with the specified description and status.
    pub fn with_status<S>(desc: S, status: LogItemStatus) -> LogItem<'a>
    where
        S: Into<String>,
    {
        let text_items = LogItem::create_text_items(desc, status);
        LogItem(text_items)
    }

    /// Create a LogItem with its status set to `LogItemStatus::Pending`.
    pub fn pending<S>(desc: S) -> LogItem<'a>
    where
        S: Into<String>,
    {
        LogItem::with_status(desc, LogItemStatus::Pending)
    }

    /// Create a LogItem with its status set to `LogItemStatus::Failed`.
    pub fn failed<S, O>(desc: S, err: O) -> LogItem<'a>
    where
        S: Into<String>,
        O: Into<Option<err::Error>>,
    {
        LogItem::with_status(desc, LogItemStatus::Failed(err.into()))
    }

    fn create_text_items<S>(desc: S, status: LogItemStatus) -> SmallVec<[Text<'a>; 3]>
    where
        S: Into<String>,
    {
        let desc_text = if status.is_resolved() {
            Text::raw(format!("{}... ", desc.into()))
        } else {
            Text::raw(format!("{}...\n", desc.into()))
        };

        let mut text_items = smallvec![desc_text];

        // Beyond this point, we only need to resolve the status (if we have it)
        if !status.is_resolved() {
            return text_items;
        }

        let status_text = {
            let color = match status {
                LogItemStatus::Ok => Color::Green,
                LogItemStatus::Pending => Color::Yellow,
                LogItemStatus::Failed(_) => Color::Red,
            };

            Text::styled(format!("{}\n", status), Style::default().fg(color))
        };

        text_items.push(status_text);

        if let LogItemStatus::Failed(Some(err)) = &status {
            let err_text = Text::styled(format!(".. {}\n", err), Style::default().fg(Color::Red));
            text_items.push(err_text);
        }

        text_items
    }

    /// Returns a reference to all of the internal text elements.
    ///
    /// This method is useful for drawing the `LogItem`.
    pub fn text_items(&self) -> &SmallVec<[Text<'a>; 3]> {
        &self.0
    }
}

impl<'a, T> From<T> for LogItem<'a>
where
    T: Into<String>,
{
    fn from(value: T) -> Self {
        LogItem::pending(value)
    }
}

/// The result of a log event. Meant to be used with `LogItem`.
pub enum LogItemStatus {
    Ok,
    Pending,
    Failed(Option<err::Error>),
}

impl LogItemStatus {
    /// Returns true if the status indicates that it's not waiting for the result of an operation.
    pub fn is_resolved(&self) -> bool {
        match self {
            LogItemStatus::Ok | LogItemStatus::Failed(_) => true,
            LogItemStatus::Pending => false,
        }
    }
}

impl fmt::Display for LogItemStatus {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self {
            LogItemStatus::Ok => write!(f, "ok"),
            LogItemStatus::Pending => write!(f, "pending"),
            LogItemStatus::Failed(_) => write!(f, "failed"),
        }
    }
}
<|endoftext|>


<commit_before>// binary.rs

pub use BASE16       = base16::BASE16;
pub use BASE32       = base32::BASE32_STD;
pub use BASE64       = base64::BASE64_STD;
pub use BASE32_HEX   = base32::BASE32_HEX;
pub use BASE64_URL   = base64::BASE64_URL;
pub use Base16Writer = base16::Base16Writer;
pub use Base32Writer = base32::Base32Writer;
pub use Base64Writer = base64::Base64Writer;
pub use Base32Reader = base32::Base32Reader;
pub use Base64Reader = base64::Base64Reader;

pub trait Encode {
    fn encode(&self, buf: &[const u8]) -> ~[u8];
}

pub trait Decode {
    fn decode(&self, buf: &[const u8]) -> ~[u8];
}

pub trait Convert {
    static fn convert(buf: &[const u8], to: self, from: self) -> ~[u8];
}

pub trait Codec : Encode, Decode, Convert {
}

// `end` indicates whether the Decode method have encountered paddings or not.
struct DecodeResult {
    end: bool,
    ndecoded: uint,
}

trait BinaryEncoder {
    fn encode(&self, dst: &[mut u8], src: &[const u8]);
    fn encoded_len(&self, src_length: uint) -> uint;
    fn encode_bytes(&self, src: &[const u8]) -> ~[u8];
}

trait BinaryDecoder {
    fn decode(&self, dst: &[mut u8], src: &[const u8]) -> DecodeResult;
    fn decoded_len(&self, src_length: uint) -> uint;
    fn decode_bytes(&self, src: &[const u8]) -> ~[u8];
}

pub enum Binary {
    Base16,
    Base32,
    Base64,
    Base32Hex,
    Base64Url,
}

pub impl Binary : Encode {
    fn encode(&self, buf: &[const u8]) -> ~[u8] {
        match *self {
            Base16    => base16::encode(buf),
            Base32    => base32::encode(buf),
            Base64    => base64::encode(buf),
            Base32Hex => base32::hex_encode(buf),
            Base64Url => base64::urlsafe_encode(buf)
        }
    }
}

pub impl Binary : Decode {
    fn decode(&self, buf: &[const u8]) -> ~[u8] {
        match *self {
            Base16    => base16::decode(buf),
            Base32    => base32::decode(buf),
            Base64    => base64::decode(buf),
            Base32Hex => base32::hex_decode(buf),
            Base64Url => base64::urlsafe_decode(buf)
        }
    }
}

pub impl Binary : Convert {
    static fn convert(buf: &[const u8], to: Binary, from: Binary) -> ~[u8] {
        let buf = from.decode(buf);
        let buf = to.encode(buf);
        move buf
    }
}
<commit_msg>Fix the "method not found" error<commit_after>// binary.rs

pub use BASE16       = base16::BASE16;
pub use BASE32       = base32::BASE32_STD;
pub use BASE64       = base64::BASE64_STD;
pub use BASE32_HEX   = base32::BASE32_HEX;
pub use BASE64_URL   = base64::BASE64_URL;
pub use Base16Writer = base16::Base16Writer;
pub use Base32Writer = base32::Base32Writer;
pub use Base64Writer = base64::Base64Writer;
pub use Base32Reader = base32::Base32Reader;
pub use Base64Reader = base64::Base64Reader;

pub trait Encode {
    fn encode(&self, buf: &[const u8]) -> ~[u8];
}

pub trait Decode {
    fn decode(&self, buf: &[const u8]) -> ~[u8];
}

pub trait Convert {
    static fn convert(buf: &[const u8], to: self, from: self) -> ~[u8];
}

pub trait Codec : Encode, Decode, Convert {
}

// `end` indicates whether the Decode method have encountered paddings or not.
struct DecodeResult {
    end: bool,
    ndecoded: uint,
}

trait BinaryEncoder {
    fn encode(&self, dst: &[mut u8], src: &[const u8]);
    fn encoded_len(&self, src_length: uint) -> uint;
    fn encode_bytes(&self, src: &[const u8]) -> ~[u8];
}

trait BinaryDecoder {
    fn decode(&self, dst: &[mut u8], src: &[const u8]) -> DecodeResult;
    fn decoded_len(&self, src_length: uint) -> uint;
    fn decode_bytes(&self, src: &[const u8]) -> ~[u8];
}

pub enum Binary {
    Base16,
    Base32,
    Base64,
    Base32Hex,
    Base64Url,
}

pub impl Binary : Encode {
    fn encode(&self, buf: &[const u8]) -> ~[u8] {
        match *self {
            Base16    => base16::encode(buf),
            Base32    => base32::encode(buf),
            Base64    => base64::encode(buf),
            Base32Hex => base32::hex_encode(buf),
            Base64Url => base64::urlsafe_encode(buf)
        }
    }
}

pub impl Binary : Decode {
    fn decode(&self, buf: &[const u8]) -> ~[u8] {
        match *self {
            Base16    => base16::decode(buf),
            Base32    => base32::decode(buf),
            Base64    => base64::decode(buf),
            Base32Hex => base32::hex_decode(buf),
            Base64Url => base64::urlsafe_decode(buf)
        }
    }
}

pub impl Binary : Convert {
    static fn convert(buf: &[const u8], to: Binary, from: Binary) -> ~[u8] {
        let buf = from.decode(buf);
        let buf = to.encode(buf);
        move buf
    }
}

pub impl Binary : Codec;
<|endoftext|>


<commit_before>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::hashmap::HashMap;
use std::gc::Gc;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;

#[deriving(Show)]
pub enum AttributeValue {
  UIntValue(uint),
  StrValue(String),
  RefValue(String),
}

pub enum AttributeType {
  StringAttribute,
  IntAttribute,
  RefAttribute,
}

#[deriving(Show)]
pub struct Attribute {
  pub value: AttributeValue,
  pub key_span: Span,
  pub value_span: Span,
}

impl Attribute {
  pub fn new(value: AttributeValue, key_span: Span, value_span: Span)
      -> Attribute {
    Attribute {
      value: value,
      key_span: key_span,
      value_span: value_span,
    }
  }
}

#[deriving(Show)]
pub struct Node {
  pub name: Option<String>,
  pub name_span: Span,

  pub path: String,
  pub path_span: Span,

  pub attributes: HashMap<String, Attribute>,
  pub subnodes: HashMap<String, Gc<Node>>,
}

impl Node {
  pub fn new(name: Option<String>, name_span: Span, path: String,
      path_span: Span) -> Node {
    Node {
      name: name,
      name_span: name_span,
      path: path,
      path_span: path_span,
      attributes: HashMap::new(),
      subnodes: HashMap::new(),
    }
  }

  pub fn get_attr<'a>(&'a self, key: &str) -> &'a Attribute {
    self.attributes.get(&key.to_str())
  }

  pub fn get_string_attr<'a>(&'a self, key: &str) -> Option<&'a String> {
    self.attributes.find(&key.to_str()).and_then(|av| match av.value {
      StrValue(ref s) => Some(s),
      _ => None,
    })
  }

  pub fn get_int_attr(&self, key: &str) -> Option<uint> {
    self.attributes.find(&key.to_str()).and_then(|av| match av.value {
      UIntValue(ref u) => Some(*u),
      _ => None,
    })
  }

  pub fn get_ref_attr<'a>(&'a self, key: &str) -> Option<&'a String> {
    self.attributes.find(&key.to_str()).and_then(|av| match av.value {
      RefValue(ref s) => Some(s),
      _ => None,
    })
  }

  pub fn get_required_string_attr<'a>(&'a self, cx: &ExtCtxt, key: &str)
      -> Option<&'a String> {
    match self.get_string_attr(key) {
      Some(val) => Some(val),
      None => {
        cx.parse_sess().span_diagnostic.span_err(self.name_span,
            format!("required string attribute `{}` is missing", key)
            .as_slice());
        None
      }
    }
  }

  pub fn get_required_int_attr<'a>(&'a self, cx: &ExtCtxt, key: &str)
      -> Option<uint> {
    match self.get_int_attr(key) {
      Some(val) => Some(val),
      None => {
        cx.parse_sess().span_diagnostic.span_err(self.name_span,
            format!("required integer attribute `{}` is missing", key)
            .as_slice());
        None
      }
    }
  }

  pub fn get_required_ref_attr<'a>(&'a self, cx: &ExtCtxt, key: &str)
      -> Option<&'a String> {
    match self.get_ref_attr(key) {
      Some(val) => Some(val),
      None => {
        cx.parse_sess().span_diagnostic.span_err(self.name_span,
            format!("required ref attribute `{}` is missing", key)
            .as_slice());
        None
      }
    }
  }

  pub fn expect_no_attributes(&self, cx: &ExtCtxt) -> bool {
    let mut ok = true;
    for (_, v) in self.attributes.iter() {
      ok = false;
      cx.parse_sess().span_diagnostic.span_err(v.key_span,
          "no attributes expected");
    }
    ok
  }

  pub fn expect_no_subnodes(&self, cx: &ExtCtxt) -> bool {
    let mut ok = true;
    for (_, sub) in self.subnodes.iter() {
      ok = false;
      cx.parse_sess().span_diagnostic.span_err(sub.name_span,
          "no subnodes expected");
    }
    ok
  }

  pub fn expect_attributes(&self, cx: &ExtCtxt,
      expectations: Vec<(&str, AttributeType)>) -> bool {
    let mut ok = true;
    for &(n, ref t) in expectations.iter() {
      match t {
        &StringAttribute => {
          if self.get_required_string_attr(cx, n).is_none() {ok = false}
        },
        &IntAttribute => {
          if self.get_required_int_attr(cx, n).is_none() {ok = false}
        },
        &RefAttribute => {
          if self.get_required_ref_attr(cx, n).is_none() {ok = false}
        },
      }
    }
    ok
  }

  pub fn get_by_path<'a>(&'a self, path: &str) -> Option<&'a Gc<Node>> {
    self.subnodes.find(&path.to_str())
  }
}

#[deriving(Show)]
pub struct PlatformTree {
  nodes: HashMap<String, Gc<Node>>,
  named: HashMap<String, Gc<Node>>,
}

impl PlatformTree {
  pub fn new(nodes: HashMap<String, Gc<Node>>, named: HashMap<String, Gc<Node>>)
      -> PlatformTree {
    PlatformTree {
      nodes: nodes,
      named: named,
    }
  }

  pub fn get_by_name<'a>(&'a self, name: &str) -> Option<&'a Gc<Node>> {
    self.named.find(&name.to_str())
  }

  pub fn get_by_path<'a>(&'a self, name: &str) -> Option<&'a Gc<Node>> {
    self.nodes.find(&name.to_str())
  }

  pub fn expect_subnodes(&self, cx: &ExtCtxt, expectations: &[&str]) -> bool {
    let mut ok = true;
    for (path, sub) in self.nodes.iter() {
      if !expectations.contains(&path.as_slice()) {
        ok = false;
        cx.parse_sess().span_diagnostic.span_err(sub.path_span,
            format!("unknown root node `{}`", path).as_slice());
      }
    }
    ok
  }
}
<commit_msg>Added node::Node.expect_subnodes.<commit_after>// Zinc, the bare metal stack for rust.
// Copyright 2014 Vladimir "farcaller" Pouzanov <farcaller@gmail.com>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use std::collections::hashmap::HashMap;
use std::gc::Gc;
use syntax::codemap::Span;
use syntax::ext::base::ExtCtxt;

#[deriving(Show)]
pub enum AttributeValue {
  UIntValue(uint),
  StrValue(String),
  RefValue(String),
}

pub enum AttributeType {
  StringAttribute,
  IntAttribute,
  RefAttribute,
}

#[deriving(Show)]
pub struct Attribute {
  pub value: AttributeValue,
  pub key_span: Span,
  pub value_span: Span,
}

impl Attribute {
  pub fn new(value: AttributeValue, key_span: Span, value_span: Span)
      -> Attribute {
    Attribute {
      value: value,
      key_span: key_span,
      value_span: value_span,
    }
  }
}

#[deriving(Show)]
pub struct Node {
  pub name: Option<String>,
  pub name_span: Span,

  pub path: String,
  pub path_span: Span,

  pub attributes: HashMap<String, Attribute>,
  pub subnodes: HashMap<String, Gc<Node>>,
}

impl Node {
  pub fn new(name: Option<String>, name_span: Span, path: String,
      path_span: Span) -> Node {
    Node {
      name: name,
      name_span: name_span,
      path: path,
      path_span: path_span,
      attributes: HashMap::new(),
      subnodes: HashMap::new(),
    }
  }

  pub fn get_attr<'a>(&'a self, key: &str) -> &'a Attribute {
    self.attributes.get(&key.to_str())
  }

  pub fn get_string_attr<'a>(&'a self, key: &str) -> Option<&'a String> {
    self.attributes.find(&key.to_str()).and_then(|av| match av.value {
      StrValue(ref s) => Some(s),
      _ => None,
    })
  }

  pub fn get_int_attr(&self, key: &str) -> Option<uint> {
    self.attributes.find(&key.to_str()).and_then(|av| match av.value {
      UIntValue(ref u) => Some(*u),
      _ => None,
    })
  }

  pub fn get_ref_attr<'a>(&'a self, key: &str) -> Option<&'a String> {
    self.attributes.find(&key.to_str()).and_then(|av| match av.value {
      RefValue(ref s) => Some(s),
      _ => None,
    })
  }

  pub fn get_required_string_attr<'a>(&'a self, cx: &ExtCtxt, key: &str)
      -> Option<&'a String> {
    match self.get_string_attr(key) {
      Some(val) => Some(val),
      None => {
        cx.parse_sess().span_diagnostic.span_err(self.name_span,
            format!("required string attribute `{}` is missing", key)
            .as_slice());
        None
      }
    }
  }

  pub fn get_required_int_attr<'a>(&'a self, cx: &ExtCtxt, key: &str)
      -> Option<uint> {
    match self.get_int_attr(key) {
      Some(val) => Some(val),
      None => {
        cx.parse_sess().span_diagnostic.span_err(self.name_span,
            format!("required integer attribute `{}` is missing", key)
            .as_slice());
        None
      }
    }
  }

  pub fn get_required_ref_attr<'a>(&'a self, cx: &ExtCtxt, key: &str)
      -> Option<&'a String> {
    match self.get_ref_attr(key) {
      Some(val) => Some(val),
      None => {
        cx.parse_sess().span_diagnostic.span_err(self.name_span,
            format!("required ref attribute `{}` is missing", key)
            .as_slice());
        None
      }
    }
  }

  pub fn expect_no_attributes(&self, cx: &ExtCtxt) -> bool {
    let mut ok = true;
    for (_, v) in self.attributes.iter() {
      ok = false;
      cx.parse_sess().span_diagnostic.span_err(v.key_span,
          "no attributes expected");
    }
    ok
  }

  pub fn expect_no_subnodes(&self, cx: &ExtCtxt) -> bool {
    let mut ok = true;
    for (_, sub) in self.subnodes.iter() {
      ok = false;
      cx.parse_sess().span_diagnostic.span_err(sub.name_span,
          "no subnodes expected");
    }
    ok
  }

  pub fn expect_attributes(&self, cx: &ExtCtxt,
      expectations: Vec<(&str, AttributeType)>) -> bool {
    let mut ok = true;
    for &(n, ref t) in expectations.iter() {
      match t {
        &StringAttribute => {
          if self.get_required_string_attr(cx, n).is_none() {ok = false}
        },
        &IntAttribute => {
          if self.get_required_int_attr(cx, n).is_none() {ok = false}
        },
        &RefAttribute => {
          if self.get_required_ref_attr(cx, n).is_none() {ok = false}
        },
      }
    }
    ok
  }

  pub fn expect_subnodes(&self, cx: &ExtCtxt, expectations: &[&str]) -> bool {
    let mut ok = true;
    for (path, sub) in self.subnodes.iter() {
      if !expectations.contains(&path.as_slice()) {
        ok = false;
        cx.parse_sess().span_diagnostic.span_err(sub.path_span,
            format!("unknown subnode `{}` in node `{}`",
                path, self.path).as_slice());
      }
    }
    ok
  }

  pub fn get_by_path<'a>(&'a self, path: &str) -> Option<&'a Gc<Node>> {
    self.subnodes.find(&path.to_str())
  }
}

#[deriving(Show)]
pub struct PlatformTree {
  nodes: HashMap<String, Gc<Node>>,
  named: HashMap<String, Gc<Node>>,
}

impl PlatformTree {
  pub fn new(nodes: HashMap<String, Gc<Node>>, named: HashMap<String, Gc<Node>>)
      -> PlatformTree {
    PlatformTree {
      nodes: nodes,
      named: named,
    }
  }

  pub fn get_by_name<'a>(&'a self, name: &str) -> Option<&'a Gc<Node>> {
    self.named.find(&name.to_str())
  }

  pub fn get_by_path<'a>(&'a self, name: &str) -> Option<&'a Gc<Node>> {
    self.nodes.find(&name.to_str())
  }

  pub fn expect_subnodes(&self, cx: &ExtCtxt, expectations: &[&str]) -> bool {
    let mut ok = true;
    for (path, sub) in self.nodes.iter() {
      if !expectations.contains(&path.as_slice()) {
        ok = false;
        cx.parse_sess().span_diagnostic.span_err(sub.path_span,
            format!("unknown root node `{}`", path).as_slice());
      }
    }
    ok
  }
}
<|endoftext|>


<commit_before>use std::slice::Iter;

use Tree;
use Node;
use NodeId;
use tree::IteratorNew;

///
/// An Iterator over the ancestors of a `Node`.
///
/// Iterates over the ancestor `Node`s of a given `Node` in the `Tree`.  Each call to `next` will
/// return an immutable reference to the next `Node` up the `Tree`.
///
pub struct Ancestors<'a, T: 'a> {
    tree: &'a Tree<T>,
    node_id: Option<NodeId>,
}

impl<'a, T> IteratorNew<'a, T, Ancestors<'a, T>> for Ancestors<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> Ancestors<'a, T> {
        Ancestors {
            tree: tree,
            node_id: Some(node_id),
        }
    }
}

impl<'a, T> Iterator for Ancestors<'a, T> {
    type Item = &'a Node<T>;

    fn next(&mut self) -> Option<&'a Node<T>> {
        if let Some(current_id) = self.node_id.clone() {
            if let Some(parent_id) = self.tree.get_unsafe(&current_id).parent() {
                let parent = self.tree.get_unsafe(&parent_id);
                self.node_id = Some(parent_id.clone());
                return Some(parent);
            } else {
                self.node_id = None;
            }
        }
        None
    }
}

///
/// An Iterator over the ancestors of a `Node`.
///
/// Iterates over `NodeId`s instead of over the `Node`s themselves.
///
pub struct AncestorIds<'a, T: 'a> {
    tree: &'a Tree<T>,
    node_id: Option<NodeId>,
}

impl<'a, T> IteratorNew<'a, T, AncestorIds<'a, T>> for AncestorIds<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> AncestorIds<'a, T> {
        AncestorIds {
            tree: tree,
            node_id: Some(node_id),
        }
    }
}

impl<'a, T> Iterator for AncestorIds<'a, T> {
    type Item = &'a NodeId;

    fn next(&mut self) -> Option<&'a NodeId> {
        if let Some(current_id) = self.node_id.clone() {
            if let Some(parent_id) = self.tree.get_unsafe(&current_id).parent() {
                self.node_id = Some(parent_id.clone());
                return Some(parent_id);
            } else {
                self.node_id = None;
            }
        }
        None
    }
}

///
/// An Iterator over the children of a `Node`.
///
/// Iterates over the child `Node`s of a given `Node` in the `Tree`.  Each call to `next` will
/// return an immutable reference to the next child `Node`.
///
pub struct Children<'a, T: 'a> {
    tree: &'a Tree<T>,
    child_ids: Iter<'a, NodeId>,
}

impl<'a, T> IteratorNew<'a, T, Children<'a, T>> for Children<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> Children<'a, T> {
        Children {
            tree: tree,
            child_ids: tree.get_unsafe(&node_id).children().as_slice().iter(),
        }
    }
}

impl<'a, T> Iterator for Children<'a, T> {
    type Item = &'a Node<T>;

    fn next(&mut self) -> Option<&'a Node<T>> {
        if let Some(ref next_child_id) = self.child_ids.next() {
            return Some(self.tree.get_unsafe(next_child_id));
        }
        None
    }
}

///
/// An Iterator over the children of a `Node`.
///
/// Iterates over `NodeId`s instead of over the `Node`s themselves.
///
pub struct ChildrenIds<'a> {
    child_ids: Iter<'a, NodeId>,
}

impl<'a, T> IteratorNew<'a, T, ChildrenIds<'a>> for ChildrenIds<'a> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> ChildrenIds<'a> {
        ChildrenIds { child_ids: tree.get_unsafe(&node_id).children().as_slice().iter() }
    }
}

impl<'a> Iterator for ChildrenIds<'a> {
    type Item = &'a NodeId;

    fn next(&mut self) -> Option<&'a NodeId> {
        self.child_ids.next()
    }
}

pub struct PreOrderTraversal<'a, T: 'a> {
    tree: &'a Tree<T>,
    node_id: Option<NodeId>,
    future_data: Vec<&'a NodeId>,
}

impl<'a, T> IteratorNew<'a, T, PreOrderTraversal<'a, T>> for PreOrderTraversal<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> PreOrderTraversal<T> {
        PreOrderTraversal {
            tree: tree,
            node_id: Some(node_id),
            // over allocating, but all at once instead of re-sizing and re-allocating as we go
            future_data: Vec::with_capacity(tree.nodes.capacity()),
        }
    }
}

impl<'a, T> Iterator for PreOrderTraversal<'a, T> {
    type Item = &'a Node<T>;

    fn next(&mut self) -> Option<&'a Node<T>> {
        if let Some(node_id) = self.node_id.clone() {

            let node = self.tree.get_unsafe(&node_id);

            if !node.children().is_empty() {
                let mut children_ids = node.children().iter();

                // take the first child and set it as the next one to be processed
                self.node_id = children_ids.next().cloned();

                // reverse it because we will pop to get the next one later.
                let mut new_ids: Vec<&NodeId> = children_ids.rev().collect();

                self.future_data.append(&mut new_ids);
            } else {
                self.node_id = self.future_data.pop().cloned();
            }

            return Some(node);
        }
        None
    }
}

pub struct PostOrderTraversal<'a, T: 'a> {
    tree: &'a Tree<T>,
    index: usize,
    data: Vec<NodeId>,
}

impl<'a, T> PostOrderTraversal<'a, T> {
    fn process_nodes<'b>(&mut self, starting_id: NodeId) {
        let node = self.tree.get_unsafe(&starting_id);

        for child_id in node.children() {
            self.process_nodes(child_id.clone());
        }

        self.data.push(starting_id);
    }
}

impl<'a, T> IteratorNew<'a, T, PostOrderTraversal<'a, T>> for PostOrderTraversal<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> PostOrderTraversal<T> {
        let mut traversal = PostOrderTraversal {
            tree: tree,
            index: 0,
            // over allocating, but all at once instead of re-sizing and re-allocating as we go
            data: Vec::with_capacity(tree.nodes.capacity()),
        };

        traversal.process_nodes(node_id);
        traversal
    }
}

impl<'a, T> Iterator for PostOrderTraversal<'a, T> {
    type Item = &'a Node<T>;

    fn next(&mut self) -> Option<&'a Node<T>> {

        let id = self.data.get(self.index);
        self.index += 1;

        if let Some(node_id) = id {
            return Some(self.tree.get_unsafe(node_id));
        }

        None
    }
}

#[cfg(test)]
mod tests {

    use Tree;
    use Node;
    use InsertBehavior::*;

    #[test]
    fn test_ancestors() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let ancestors = tree.ancestors(&root_id).unwrap();
        assert_eq!(ancestors.count(), 0);

        let data = [0];
        for (index, node) in tree.ancestors(&node_1).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [1, 0];
        for (index, node) in tree.ancestors(&node_2).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [1, 0];
        for (index, node) in tree.ancestors(&node_3).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }
    }

    #[test]
    fn test_ancestor_ids() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let ancestor_ids = tree.ancestor_ids(&root_id).unwrap();
        assert_eq!(ancestor_ids.count(), 0);

        let data = [0];
        for (index, node_id) in tree.ancestor_ids(&node_1).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }

        let data = [1, 0];
        for (index, node_id) in tree.ancestor_ids(&node_2).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }

        let data = [1, 0];
        for (index, node_id) in tree.ancestor_ids(&node_3).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }
    }

    #[test]
    fn test_children() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let data = [1];
        for (index, node) in tree.children(&root_id).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [2, 3];
        for (index, node) in tree.children(&node_1).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let children = tree.children(&node_2).unwrap();
        assert_eq!(children.count(), 0);

        let children = tree.children(&node_3).unwrap();
        assert_eq!(children.count(), 0);
    }

    #[test]
    fn test_children_ids() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let data = [1];
        for (index, node_id) in tree.children_ids(&root_id).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }

        let data = [2, 3];
        for (index, node_id) in tree.children_ids(&node_1).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }

        let children_ids = tree.children_ids(&node_2).unwrap();
        assert_eq!(children_ids.count(), 0);

        let children_ids = tree.children_ids(&node_3).unwrap();
        assert_eq!(children_ids.count(), 0);
    }

    #[test]
    fn test_pre_order_traversal() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let data = [0, 1, 2, 3];
        for (index, node) in tree.traverse_pre_order(&root_id).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [1, 2, 3];
        for (index, node) in tree.traverse_pre_order(&node_1).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [2];
        for (index, node) in tree.traverse_pre_order(&node_2).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [3];
        for (index, node) in tree.traverse_pre_order(&node_3).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }
    }

    #[test]
    fn test_post_order_traversal() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let data = [2, 3, 1, 0];
        for (index, node) in tree.traverse_post_order(&root_id).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [2, 3, 1];
        for (index, node) in tree.traverse_post_order(&node_1).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [2];
        for (index, node) in tree.traverse_post_order(&node_2).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [3];
        for (index, node) in tree.traverse_post_order(&node_3).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }
    }
}
<commit_msg>add struct docs<commit_after>use std::slice::Iter;

use Tree;
use Node;
use NodeId;
use tree::IteratorNew;

///
/// An Iterator over the ancestors of a `Node`.
///
/// Iterates over the ancestor `Node`s of a given `Node` in the `Tree`.  Each call to `next` will
/// return an immutable reference to the next `Node` up the `Tree`.
///
pub struct Ancestors<'a, T: 'a> {
    tree: &'a Tree<T>,
    node_id: Option<NodeId>,
}

impl<'a, T> IteratorNew<'a, T, Ancestors<'a, T>> for Ancestors<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> Ancestors<'a, T> {
        Ancestors {
            tree: tree,
            node_id: Some(node_id),
        }
    }
}

impl<'a, T> Iterator for Ancestors<'a, T> {
    type Item = &'a Node<T>;

    fn next(&mut self) -> Option<&'a Node<T>> {
        if let Some(current_id) = self.node_id.clone() {
            if let Some(parent_id) = self.tree.get_unsafe(&current_id).parent() {
                let parent = self.tree.get_unsafe(&parent_id);
                self.node_id = Some(parent_id.clone());
                return Some(parent);
            } else {
                self.node_id = None;
            }
        }
        None
    }
}

///
/// An Iterator over the ancestors of a `Node`.
///
/// Iterates over `NodeId`s instead of over the `Node`s themselves.
///
pub struct AncestorIds<'a, T: 'a> {
    tree: &'a Tree<T>,
    node_id: Option<NodeId>,
}

impl<'a, T> IteratorNew<'a, T, AncestorIds<'a, T>> for AncestorIds<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> AncestorIds<'a, T> {
        AncestorIds {
            tree: tree,
            node_id: Some(node_id),
        }
    }
}

impl<'a, T> Iterator for AncestorIds<'a, T> {
    type Item = &'a NodeId;

    fn next(&mut self) -> Option<&'a NodeId> {
        if let Some(current_id) = self.node_id.clone() {
            if let Some(parent_id) = self.tree.get_unsafe(&current_id).parent() {
                self.node_id = Some(parent_id.clone());
                return Some(parent_id);
            } else {
                self.node_id = None;
            }
        }
        None
    }
}

///
/// An Iterator over the children of a `Node`.
///
/// Iterates over the child `Node`s of a given `Node` in the `Tree`.  Each call to `next` will
/// return an immutable reference to the next child `Node`.
///
pub struct Children<'a, T: 'a> {
    tree: &'a Tree<T>,
    child_ids: Iter<'a, NodeId>,
}

impl<'a, T> IteratorNew<'a, T, Children<'a, T>> for Children<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> Children<'a, T> {
        Children {
            tree: tree,
            child_ids: tree.get_unsafe(&node_id).children().as_slice().iter(),
        }
    }
}

impl<'a, T> Iterator for Children<'a, T> {
    type Item = &'a Node<T>;

    fn next(&mut self) -> Option<&'a Node<T>> {
        if let Some(ref next_child_id) = self.child_ids.next() {
            return Some(self.tree.get_unsafe(next_child_id));
        }
        None
    }
}

///
/// An Iterator over the children of a `Node`.
///
/// Iterates over `NodeId`s instead of over the `Node`s themselves.
///
pub struct ChildrenIds<'a> {
    child_ids: Iter<'a, NodeId>,
}

impl<'a, T> IteratorNew<'a, T, ChildrenIds<'a>> for ChildrenIds<'a> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> ChildrenIds<'a> {
        ChildrenIds { child_ids: tree.get_unsafe(&node_id).children().as_slice().iter() }
    }
}

impl<'a> Iterator for ChildrenIds<'a> {
    type Item = &'a NodeId;

    fn next(&mut self) -> Option<&'a NodeId> {
        self.child_ids.next()
    }
}

///
/// An Iterator over the sub-tree relative to a given `Node`.
///
/// Iterates over all of the `Node`s in the sub-tree of a given `Node` in the `Tree`.  Each call to
/// `next` will return an immutable reference to the next `Node` in Pre-Order Traversal order.
///
pub struct PreOrderTraversal<'a, T: 'a> {
    tree: &'a Tree<T>,
    node_id: Option<NodeId>,
    future_data: Vec<&'a NodeId>,
}

impl<'a, T> IteratorNew<'a, T, PreOrderTraversal<'a, T>> for PreOrderTraversal<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> PreOrderTraversal<T> {
        PreOrderTraversal {
            tree: tree,
            node_id: Some(node_id),
            // over allocating, but all at once instead of re-sizing and re-allocating as we go
            future_data: Vec::with_capacity(tree.nodes.capacity()),
        }
    }
}

impl<'a, T> Iterator for PreOrderTraversal<'a, T> {
    type Item = &'a Node<T>;

    fn next(&mut self) -> Option<&'a Node<T>> {
        if let Some(node_id) = self.node_id.clone() {

            let node = self.tree.get_unsafe(&node_id);

            if !node.children().is_empty() {
                let mut children_ids = node.children().iter();

                // take the first child and set it as the next one to be processed
                self.node_id = children_ids.next().cloned();

                // reverse it because we will pop to get the next one later.
                let mut new_ids: Vec<&NodeId> = children_ids.rev().collect();

                self.future_data.append(&mut new_ids);
            } else {
                self.node_id = self.future_data.pop().cloned();
            }

            return Some(node);
        }
        None
    }
}

///
/// An Iterator over the sub-tree relative to a given `Node`.
///
/// Iterates over all of the `Node`s in the sub-tree of a given `Node` in the `Tree`.  Each call to
/// `next` will return an immutable reference to the next `Node` in Post-Order Traversal order.
///
pub struct PostOrderTraversal<'a, T: 'a> {
    tree: &'a Tree<T>,
    index: usize,
    data: Vec<NodeId>,
}

impl<'a, T> PostOrderTraversal<'a, T> {
    fn process_nodes<'b>(&mut self, starting_id: NodeId) {
        let node = self.tree.get_unsafe(&starting_id);

        for child_id in node.children() {
            self.process_nodes(child_id.clone());
        }

        self.data.push(starting_id);
    }
}

impl<'a, T> IteratorNew<'a, T, PostOrderTraversal<'a, T>> for PostOrderTraversal<'a, T> {
    fn new(tree: &'a Tree<T>, node_id: NodeId) -> PostOrderTraversal<T> {
        let mut traversal = PostOrderTraversal {
            tree: tree,
            index: 0,
            // over allocating, but all at once instead of re-sizing and re-allocating as we go
            data: Vec::with_capacity(tree.nodes.capacity()),
        };

        traversal.process_nodes(node_id);
        traversal
    }
}

impl<'a, T> Iterator for PostOrderTraversal<'a, T> {
    type Item = &'a Node<T>;

    fn next(&mut self) -> Option<&'a Node<T>> {

        let id = self.data.get(self.index);
        self.index += 1;

        if let Some(node_id) = id {
            return Some(self.tree.get_unsafe(node_id));
        }

        None
    }
}

#[cfg(test)]
mod tests {

    use Tree;
    use Node;
    use InsertBehavior::*;

    #[test]
    fn test_ancestors() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let ancestors = tree.ancestors(&root_id).unwrap();
        assert_eq!(ancestors.count(), 0);

        let data = [0];
        for (index, node) in tree.ancestors(&node_1).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [1, 0];
        for (index, node) in tree.ancestors(&node_2).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [1, 0];
        for (index, node) in tree.ancestors(&node_3).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }
    }

    #[test]
    fn test_ancestor_ids() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let ancestor_ids = tree.ancestor_ids(&root_id).unwrap();
        assert_eq!(ancestor_ids.count(), 0);

        let data = [0];
        for (index, node_id) in tree.ancestor_ids(&node_1).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }

        let data = [1, 0];
        for (index, node_id) in tree.ancestor_ids(&node_2).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }

        let data = [1, 0];
        for (index, node_id) in tree.ancestor_ids(&node_3).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }
    }

    #[test]
    fn test_children() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let data = [1];
        for (index, node) in tree.children(&root_id).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [2, 3];
        for (index, node) in tree.children(&node_1).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let children = tree.children(&node_2).unwrap();
        assert_eq!(children.count(), 0);

        let children = tree.children(&node_3).unwrap();
        assert_eq!(children.count(), 0);
    }

    #[test]
    fn test_children_ids() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let data = [1];
        for (index, node_id) in tree.children_ids(&root_id).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }

        let data = [2, 3];
        for (index, node_id) in tree.children_ids(&node_1).unwrap().enumerate() {
            assert_eq!(tree.get(node_id).unwrap().data(), &data[index]);
        }

        let children_ids = tree.children_ids(&node_2).unwrap();
        assert_eq!(children_ids.count(), 0);

        let children_ids = tree.children_ids(&node_3).unwrap();
        assert_eq!(children_ids.count(), 0);
    }

    #[test]
    fn test_pre_order_traversal() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let data = [0, 1, 2, 3];
        for (index, node) in tree.traverse_pre_order(&root_id).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [1, 2, 3];
        for (index, node) in tree.traverse_pre_order(&node_1).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [2];
        for (index, node) in tree.traverse_pre_order(&node_2).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [3];
        for (index, node) in tree.traverse_pre_order(&node_3).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }
    }

    #[test]
    fn test_post_order_traversal() {
        let mut tree = Tree::new();

        let root_id = tree.insert(Node::new(0), AsRoot).unwrap();
        let node_1 = tree.insert(Node::new(1), UnderNode(&root_id)).unwrap();
        let node_2 = tree.insert(Node::new(2), UnderNode(&node_1)).unwrap();
        let node_3 = tree.insert(Node::new(3), UnderNode(&node_1)).unwrap();

        let data = [2, 3, 1, 0];
        for (index, node) in tree.traverse_post_order(&root_id).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [2, 3, 1];
        for (index, node) in tree.traverse_post_order(&node_1).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [2];
        for (index, node) in tree.traverse_post_order(&node_2).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }

        let data = [3];
        for (index, node) in tree.traverse_post_order(&node_3).unwrap().enumerate() {
            assert_eq!(node.data(), &data[index]);
        }
    }
}
<|endoftext|>


<commit_before>use ra_syntax::ast;

use crate::HirDatabase;

#[derive(Debug, Clone)]
pub struct Documentation(String);

impl Documentation {
    pub fn new(s: &str) -> Self {
        Self(s.into())
    }

    pub fn contents(&self) -> &str {
        &self.0
    }
}

impl Into<String> for Documentation {
    fn into(self) -> String {
        self.contents().into()
    }
}

pub trait Docs {
    fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
}

pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
    let comments = node.doc_comment_text();
    if comments.is_empty() {
        None
    } else {
        Some(Documentation::new(&comments))
    }
}
<commit_msg>Add a comment<commit_after>use ra_syntax::ast;

use crate::HirDatabase;

/// Holds documentation
#[derive(Debug, Clone)]
pub struct Documentation(String);

impl Documentation {
    pub fn new(s: &str) -> Self {
        Self(s.into())
    }

    pub fn contents(&self) -> &str {
        &self.0
    }
}

impl Into<String> for Documentation {
    fn into(self) -> String {
        self.contents().into()
    }
}

pub trait Docs {
    fn docs(&self, db: &impl HirDatabase) -> Option<Documentation>;
}

pub(crate) fn docs_from_ast(node: &impl ast::DocCommentsOwner) -> Option<Documentation> {
    let comments = node.doc_comment_text();
    if comments.is_empty() {
        None
    } else {
        Some(Documentation::new(&comments))
    }
}
<|endoftext|>


<commit_before>//! A read-only Bounding Volume Tree.

use test::stats::Stats;
use std::collections::BinaryHeap;
use na::{Translation, Bounded};
use na;
use partitioning::{BVTVisitor, BVTTVisitor, BVTCostFn};
use bounding_volume::BoundingVolume;
use utils::data::ref_with_cost::RefWithCost;
use math::{Scalar, Vect};

/// A Boundig Volume Tree.
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct BVT<B, BV> {
    tree: Option<BVTNode<B, BV>>
}

/// A node of the bounding volume tree.
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub enum BVTNode<B, BV> {
    // XXX: give a faster access to the BV
    /// An internal node.
    Internal(BV, Box<BVTNode<B, BV>>, Box<BVTNode<B, BV>>),
    /// A leaf.
    Leaf(BV, B)
}

/// Result of a binary partition.
pub enum BinaryPartition<B, BV> {
    /// Result of the partitioning of one element.
    Part(B),
    /// Result of the partitioning of several elements.
    Parts(Vec<(B, BV)>, Vec<(B, BV)>)
}

impl<B, BV> BVT<B, BV> {
    // FIXME: add higher level constructors ?
    /// Builds a bounding volume tree using an user-defined construction function.
    pub fn new_with_partitioner<F: FnMut(uint, Vec<(B, BV)>) -> (BV, BinaryPartition<B, BV>)>
      (leaves:      Vec<(B, BV)>,
       partitioner: F)
          -> BVT<B, BV> {
        if leaves.len() == 0 {
            BVT {
                tree: None
            }
        }
        else {
            BVT {
                tree: Some(_new_with_partitioner(0, leaves, partitioner))
            }
        }
    }

    /// Visit this tree using… a visitor!
    pub fn visit<Vis: BVTVisitor<B, BV>>(&self, visitor: &mut Vis) {
        match self.tree {
            Some(ref t) => t.visit(visitor),
            None        => { }
        }
    }

    /// Visits the bounding volume traversal tree implicitely formed with `other`.
    pub fn visit_bvtt<Vis: BVTTVisitor<B, BV>>(&self, other: &BVT<B, BV>, visitor: &mut Vis) {
        match (&self.tree, &other.tree) {
            (&Some(ref ta), &Some(ref tb)) => ta.visit_bvtt(tb, visitor),
            _ => { }
        }
    }

    // FIXME: internalize the type parameter R using associated types.
    // FIXME: really return a ref to B ?
    /// Performs a best-fist-search on the tree.
    ///
    /// Returns the content of the best leaf nound, and a result of user-defined type.
    pub fn best_first_search<'a, N, BFS, R>(&'a self, algorithm: &mut BFS) -> Option<(&'a B, R)>
        where N:   Scalar,
              BFS: BVTCostFn<N, B, BV, R> {
        match self.tree {
            Some(ref t) => t.best_first_search(algorithm),
            None        => None
        }
    }

    /// Reference to the bounding volume of the tree root.
    pub fn root_bounding_volume<'r>(&'r self) -> Option<&'r BV> {
        match self.tree {
            Some(ref n) => {
                match *n {
                    BVTNode::Internal(ref bv, _, _) => Some(bv),
                    BVTNode::Leaf(ref bv, _) => Some(bv)
                }
            },
            None => None
        }
    }

    /// Computes the depth of this tree.
    pub fn depth(&self) -> uint {
        match self.tree {
            Some(ref n) => n.depth(),
            None        => 0
        }
    }
}

#[old_impl_check]
impl<N, V, B, BV> BVT<B, BV>
    where N:  Scalar,
          V:  Vect<N>,
          BV: Translation<V> + BoundingVolume<N> + Clone {
    /// Creates a balanced `BVT`.
    pub fn new_balanced(leaves: Vec<(B, BV)>) -> BVT<B, BV> {
        BVT::new_with_partitioner(leaves, median_partitioner)
    }
}

impl<B, BV> BVTNode<B, BV> {
    /// The bounding volume of this node.
    #[inline]
    pub fn bounding_volume<'a>(&'a self) -> &'a BV {
        match *self {
            BVTNode::Internal(ref bv, _, _) => bv,
            BVTNode::Leaf(ref bv, _)        => bv
        }
    }

    fn visit<Vis: BVTVisitor<B, BV>>(&self, visitor: &mut Vis) {
        match *self {
            BVTNode::Internal(ref bv, ref left, ref right) => {
                if visitor.visit_internal(bv) {
                    left.visit(visitor);
                    right.visit(visitor);
                }
            },
            BVTNode::Leaf(ref bv, ref b) => {
                visitor.visit_leaf(b, bv);
            }
        }
    }

    fn visit_bvtt<Vis: BVTTVisitor<B, BV>>(&self, other: &BVTNode<B, BV>, visitor: &mut Vis) {
        match (self, other) {
            (&BVTNode::Internal(ref bva, ref la, ref ra), &BVTNode::Internal(ref bvb, ref lb, ref rb)) => {
                if visitor.visit_internal_internal(bva, bvb) {
                    la.visit_bvtt(&**lb, visitor);
                    la.visit_bvtt(&**rb, visitor);
                    ra.visit_bvtt(&**lb, visitor);
                    ra.visit_bvtt(&**rb, visitor);
                }
            },
            (&BVTNode::Internal(ref bva, ref la, ref ra), &BVTNode::Leaf(ref bvb, ref bb)) => {
                if visitor.visit_internal_leaf(bva, bb, bvb) {
                    la.visit_bvtt(other, visitor);
                    ra.visit_bvtt(other, visitor);
                }
            },
            (&BVTNode::Leaf(ref bva, ref ba), &BVTNode::Internal(ref bvb, ref lb, ref rb)) => {
                if visitor.visit_leaf_internal(ba, bva, bvb) {
                    self.visit_bvtt(&**lb, visitor);
                    self.visit_bvtt(&**rb, visitor);
                }
            },
            (&BVTNode::Leaf(ref bva, ref ba), &BVTNode::Leaf(ref bvb, ref bb)) => {
                visitor.visit_leaf_leaf(ba, bva, bb, bvb)
            }
        }
    }

    fn best_first_search<'a, N, BFS, R>(&'a self, algorithm: &mut BFS) -> Option<(&'a B, R)>
        where N:   Scalar,
              BFS: BVTCostFn<N, B, BV, R> {
        let mut queue: BinaryHeap<RefWithCost<'a, N, BVTNode<B, BV>>> = BinaryHeap::new();
        let mut best_cost = Bounded::max_value();
        let mut result    = None;

        match algorithm.compute_bv_cost(self.bounding_volume()) {
            Some(cost) => queue.push(RefWithCost::new(self, cost)),
            None       => return None
        }

        loop {
            match queue.pop() {
                Some(node) => {
                    if -node.cost >= best_cost {
                        break; // solution found.
                    }

                    match *node.object {
                        BVTNode::Internal(_, ref left, ref right) => {
                            match algorithm.compute_bv_cost(left.bounding_volume()) {
                                Some(lcost) => {
                                    if lcost < best_cost {
                                        queue.push(RefWithCost::new(&**left, -lcost))
                                    }
                                },
                                None => { }
                            }

                            match algorithm.compute_bv_cost(right.bounding_volume()) {
                                Some(rcost) => {
                                    if rcost < best_cost {
                                        queue.push(RefWithCost::new(&**right, -rcost))
                                    }
                                },
                                None => { }
                            }
                        },
                        BVTNode::Leaf(_, ref b) => {
                            match algorithm.compute_b_cost(b) {
                                Some((candidate_cost, candidate_result)) => {
                                    if candidate_cost < best_cost {
                                        best_cost = candidate_cost;
                                        result    = Some((b, candidate_result));
                                    }
                                }
                                None => { }
                            }
                        }
                    }
                }
                None => break,
            }
        }

        result
    }

    fn depth(&self) -> uint {
        match *self {
            BVTNode::Internal(_, ref left, ref right) => 1 + na::max(left.depth(), right.depth()),
            BVTNode::Leaf(_, _) => 1
        }
    }
}

/// Construction function for a kdree to be used with `BVT::new_with_partitioner`.
pub fn median_partitioner_with_centers<N, V, B, BV, F: FnMut(&B, &BV) -> V>
        (depth:  uint,
         leaves: Vec<(B, BV)>,
         center: &mut F)
         -> (BV, BinaryPartition<B, BV>)
    where N: Scalar,
          V:  Vect<N>,
          BV: BoundingVolume<N> + Clone{
    if leaves.len() == 0 {
        panic!("Cannot build a tree without leaves.");
    }
    else if leaves.len() == 1 {
        let (b, bv) = leaves.into_iter().next().unwrap();
        (bv, BinaryPartition::Part(b))
    }
    else {
        let sep_axis = depth % na::dim::<V>();

        // compute the median along sep_axis
        let mut median = Vec::new();

        for l in leaves.iter() {
            let c = (*center)(&l.0, &l.1);
            median.push(c[sep_axis]);
        }

        let median = median.as_slice().median();

        // build the partitions
        let mut right = Vec::new();
        let mut left  = Vec::new();
        let mut bounding_bounding_volume = leaves[0].1.clone();

        let mut insert_left = false;

        for (b, bv) in leaves.into_iter() {
            bounding_bounding_volume.merge(&bv);

            let pos = (*center)(&b, &bv)[sep_axis];

            if pos < median || (pos == median && insert_left) {
                left.push((b, bv));
                insert_left = false;
            }
            else {
                right.push((b, bv));
                insert_left = true;
            }
        }

        // XXX: hack to avoid degeneracies.
        if left.len() == 0 {
            left.push(right.pop().unwrap());
        }
        else if right.len() == 0 {
            right.push(left.pop().unwrap());
        }

        (bounding_bounding_volume, BinaryPartition::Parts(left, right))
    }
}

/// Construction function for a kdree to be used with `BVT::new_with_partitioner`.
pub fn median_partitioner<N, V, B, BV>(depth:  uint,
                                       leaves: Vec<(B, BV)>)
                                       -> (BV, BinaryPartition<B, BV>)
    where N:  Scalar,
          V:  Vect<N>,
          BV: Translation<V> + BoundingVolume<N> + Clone {
    median_partitioner_with_centers(depth, leaves, &mut |_, bv| bv.translation())
}

fn _new_with_partitioner<B, BV, F: FnMut(uint, Vec<(B, BV)>) -> (BV, BinaryPartition<B, BV>)>
                            (depth:       uint,
                             leaves:      Vec<(B, BV)>,
                             partitioner: F)
                             -> BVTNode<B, BV> {
    __new_with_partitioner(depth, leaves, partitioner)
}

fn __new_with_partitioner<B, BV, F: FnMut(uint, Vec<(B, BV)>) -> (BV, BinaryPartition<B, BV>)>
                            (depth:       uint,
                             leaves:      Vec<(B, BV)>,
                             mut partitioner: F)
                             -> BVTNode<B, BV> {
    let (bv, partitions) = partitioner(depth, leaves);

    match partitions {
        BinaryPartition::Part(b)            => BVTNode::Leaf(bv, b),
        BinaryPartition::Parts(left, right) => {
            let left  = __new_with_partitioner(depth + 1, left, |i, p| partitioner(i, p));
            let right = __new_with_partitioner(depth + 1, right, |i, p| partitioner(i, p));
            BVTNode::Internal(bv, Box::new(left), Box::new(right))
        }
    }
}
<commit_msg>Fix an infinite monomorphization due to nested closures.<commit_after>//! A read-only Bounding Volume Tree.

use test::stats::Stats;
use std::collections::BinaryHeap;
use na::{Translation, Bounded};
use na;
use partitioning::{BVTVisitor, BVTTVisitor, BVTCostFn};
use bounding_volume::BoundingVolume;
use utils::data::ref_with_cost::RefWithCost;
use math::{Scalar, Vect};

/// A Boundig Volume Tree.
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct BVT<B, BV> {
    tree: Option<BVTNode<B, BV>>
}

/// A node of the bounding volume tree.
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub enum BVTNode<B, BV> {
    // XXX: give a faster access to the BV
    /// An internal node.
    Internal(BV, Box<BVTNode<B, BV>>, Box<BVTNode<B, BV>>),
    /// A leaf.
    Leaf(BV, B)
}

/// Result of a binary partition.
pub enum BinaryPartition<B, BV> {
    /// Result of the partitioning of one element.
    Part(B),
    /// Result of the partitioning of several elements.
    Parts(Vec<(B, BV)>, Vec<(B, BV)>)
}

impl<B, BV> BVT<B, BV> {
    // FIXME: add higher level constructors ?
    /// Builds a bounding volume tree using an user-defined construction function.
    pub fn new_with_partitioner<F: FnMut(uint, Vec<(B, BV)>) -> (BV, BinaryPartition<B, BV>)>
      (leaves:      Vec<(B, BV)>,
       partitioner: &mut F)
          -> BVT<B, BV> {
        if leaves.len() == 0 {
            BVT {
                tree: None
            }
        }
        else {
            BVT {
                tree: Some(_new_with_partitioner(0, leaves, partitioner))
            }
        }
    }

    /// Visit this tree using… a visitor!
    pub fn visit<Vis: BVTVisitor<B, BV>>(&self, visitor: &mut Vis) {
        match self.tree {
            Some(ref t) => t.visit(visitor),
            None        => { }
        }
    }

    /// Visits the bounding volume traversal tree implicitely formed with `other`.
    pub fn visit_bvtt<Vis: BVTTVisitor<B, BV>>(&self, other: &BVT<B, BV>, visitor: &mut Vis) {
        match (&self.tree, &other.tree) {
            (&Some(ref ta), &Some(ref tb)) => ta.visit_bvtt(tb, visitor),
            _ => { }
        }
    }

    // FIXME: internalize the type parameter R using associated types.
    // FIXME: really return a ref to B ?
    /// Performs a best-fist-search on the tree.
    ///
    /// Returns the content of the best leaf nound, and a result of user-defined type.
    pub fn best_first_search<'a, N, BFS, R>(&'a self, algorithm: &mut BFS) -> Option<(&'a B, R)>
        where N:   Scalar,
              BFS: BVTCostFn<N, B, BV, R> {
        match self.tree {
            Some(ref t) => t.best_first_search(algorithm),
            None        => None
        }
    }

    /// Reference to the bounding volume of the tree root.
    pub fn root_bounding_volume<'r>(&'r self) -> Option<&'r BV> {
        match self.tree {
            Some(ref n) => {
                match *n {
                    BVTNode::Internal(ref bv, _, _) => Some(bv),
                    BVTNode::Leaf(ref bv, _) => Some(bv)
                }
            },
            None => None
        }
    }

    /// Computes the depth of this tree.
    pub fn depth(&self) -> uint {
        match self.tree {
            Some(ref n) => n.depth(),
            None        => 0
        }
    }
}

#[old_impl_check]
impl<N, V, B, BV> BVT<B, BV>
    where N:  Scalar,
          V:  Vect<N>,
          BV: Translation<V> + BoundingVolume<N> + Clone {
    /// Creates a balanced `BVT`.
    pub fn new_balanced(leaves: Vec<(B, BV)>) -> BVT<B, BV> {
        BVT::new_with_partitioner(leaves, &mut median_partitioner)
    }
}

impl<B, BV> BVTNode<B, BV> {
    /// The bounding volume of this node.
    #[inline]
    pub fn bounding_volume<'a>(&'a self) -> &'a BV {
        match *self {
            BVTNode::Internal(ref bv, _, _) => bv,
            BVTNode::Leaf(ref bv, _)        => bv
        }
    }

    fn visit<Vis: BVTVisitor<B, BV>>(&self, visitor: &mut Vis) {
        match *self {
            BVTNode::Internal(ref bv, ref left, ref right) => {
                if visitor.visit_internal(bv) {
                    left.visit(visitor);
                    right.visit(visitor);
                }
            },
            BVTNode::Leaf(ref bv, ref b) => {
                visitor.visit_leaf(b, bv);
            }
        }
    }

    fn visit_bvtt<Vis: BVTTVisitor<B, BV>>(&self, other: &BVTNode<B, BV>, visitor: &mut Vis) {
        match (self, other) {
            (&BVTNode::Internal(ref bva, ref la, ref ra), &BVTNode::Internal(ref bvb, ref lb, ref rb)) => {
                if visitor.visit_internal_internal(bva, bvb) {
                    la.visit_bvtt(&**lb, visitor);
                    la.visit_bvtt(&**rb, visitor);
                    ra.visit_bvtt(&**lb, visitor);
                    ra.visit_bvtt(&**rb, visitor);
                }
            },
            (&BVTNode::Internal(ref bva, ref la, ref ra), &BVTNode::Leaf(ref bvb, ref bb)) => {
                if visitor.visit_internal_leaf(bva, bb, bvb) {
                    la.visit_bvtt(other, visitor);
                    ra.visit_bvtt(other, visitor);
                }
            },
            (&BVTNode::Leaf(ref bva, ref ba), &BVTNode::Internal(ref bvb, ref lb, ref rb)) => {
                if visitor.visit_leaf_internal(ba, bva, bvb) {
                    self.visit_bvtt(&**lb, visitor);
                    self.visit_bvtt(&**rb, visitor);
                }
            },
            (&BVTNode::Leaf(ref bva, ref ba), &BVTNode::Leaf(ref bvb, ref bb)) => {
                visitor.visit_leaf_leaf(ba, bva, bb, bvb)
            }
        }
    }

    fn best_first_search<'a, N, BFS, R>(&'a self, algorithm: &mut BFS) -> Option<(&'a B, R)>
        where N:   Scalar,
              BFS: BVTCostFn<N, B, BV, R> {
        let mut queue: BinaryHeap<RefWithCost<'a, N, BVTNode<B, BV>>> = BinaryHeap::new();
        let mut best_cost = Bounded::max_value();
        let mut result    = None;

        match algorithm.compute_bv_cost(self.bounding_volume()) {
            Some(cost) => queue.push(RefWithCost::new(self, cost)),
            None       => return None
        }

        loop {
            match queue.pop() {
                Some(node) => {
                    if -node.cost >= best_cost {
                        break; // solution found.
                    }

                    match *node.object {
                        BVTNode::Internal(_, ref left, ref right) => {
                            match algorithm.compute_bv_cost(left.bounding_volume()) {
                                Some(lcost) => {
                                    if lcost < best_cost {
                                        queue.push(RefWithCost::new(&**left, -lcost))
                                    }
                                },
                                None => { }
                            }

                            match algorithm.compute_bv_cost(right.bounding_volume()) {
                                Some(rcost) => {
                                    if rcost < best_cost {
                                        queue.push(RefWithCost::new(&**right, -rcost))
                                    }
                                },
                                None => { }
                            }
                        },
                        BVTNode::Leaf(_, ref b) => {
                            match algorithm.compute_b_cost(b) {
                                Some((candidate_cost, candidate_result)) => {
                                    if candidate_cost < best_cost {
                                        best_cost = candidate_cost;
                                        result    = Some((b, candidate_result));
                                    }
                                }
                                None => { }
                            }
                        }
                    }
                }
                None => break,
            }
        }

        result
    }

    fn depth(&self) -> uint {
        match *self {
            BVTNode::Internal(_, ref left, ref right) => 1 + na::max(left.depth(), right.depth()),
            BVTNode::Leaf(_, _) => 1
        }
    }
}

/// Construction function for a kdree to be used with `BVT::new_with_partitioner`.
pub fn median_partitioner_with_centers<N, V, B, BV, F: FnMut(&B, &BV) -> V>
        (depth:  uint,
         leaves: Vec<(B, BV)>,
         center: &mut F)
         -> (BV, BinaryPartition<B, BV>)
    where N: Scalar,
          V:  Vect<N>,
          BV: BoundingVolume<N> + Clone{
    if leaves.len() == 0 {
        panic!("Cannot build a tree without leaves.");
    }
    else if leaves.len() == 1 {
        let (b, bv) = leaves.into_iter().next().unwrap();
        (bv, BinaryPartition::Part(b))
    }
    else {
        let sep_axis = depth % na::dim::<V>();

        // compute the median along sep_axis
        let mut median = Vec::new();

        for l in leaves.iter() {
            let c = (*center)(&l.0, &l.1);
            median.push(c[sep_axis]);
        }

        let median = median.as_slice().median();

        // build the partitions
        let mut right = Vec::new();
        let mut left  = Vec::new();
        let mut bounding_bounding_volume = leaves[0].1.clone();

        let mut insert_left = false;

        for (b, bv) in leaves.into_iter() {
            bounding_bounding_volume.merge(&bv);

            let pos = (*center)(&b, &bv)[sep_axis];

            if pos < median || (pos == median && insert_left) {
                left.push((b, bv));
                insert_left = false;
            }
            else {
                right.push((b, bv));
                insert_left = true;
            }
        }

        // XXX: hack to avoid degeneracies.
        if left.len() == 0 {
            left.push(right.pop().unwrap());
        }
        else if right.len() == 0 {
            right.push(left.pop().unwrap());
        }

        (bounding_bounding_volume, BinaryPartition::Parts(left, right))
    }
}

/// Construction function for a kdree to be used with `BVT::new_with_partitioner`.
pub fn median_partitioner<N, V, B, BV>(depth:  uint,
                                       leaves: Vec<(B, BV)>)
                                       -> (BV, BinaryPartition<B, BV>)
    where N:  Scalar,
          V:  Vect<N>,
          BV: Translation<V> + BoundingVolume<N> + Clone {
    median_partitioner_with_centers(depth, leaves, &mut |_, bv| bv.translation())
}

fn _new_with_partitioner<B, BV, F: FnMut(uint, Vec<(B, BV)>) -> (BV, BinaryPartition<B, BV>)>
                            (depth:       uint,
                             leaves:      Vec<(B, BV)>,
                             partitioner: &mut F)
                             -> BVTNode<B, BV> {
    __new_with_partitioner(depth, leaves, partitioner)
}

fn __new_with_partitioner<B, BV, F: FnMut(uint, Vec<(B, BV)>) -> (BV, BinaryPartition<B, BV>)>
                            (depth:       uint,
                             leaves:      Vec<(B, BV)>,
                             partitioner: &mut F)
                             -> BVTNode<B, BV> {
    let (bv, partitions) = partitioner(depth, leaves);

    match partitions {
        BinaryPartition::Part(b)            => BVTNode::Leaf(bv, b),
        BinaryPartition::Parts(left, right) => {
            let left  = __new_with_partitioner(depth + 1, left, partitioner);
            let right = __new_with_partitioner(depth + 1, right, partitioner);
            BVTNode::Internal(bv, Box::new(left), Box::new(right))
        }
    }
}
<|endoftext|>


<commit_before>extern crate roboime_next;
#[macro_use] extern crate glium;
extern crate clap;
extern crate clock_ticks;
//extern crate image;
extern crate env_logger;
#[macro_use] extern crate log;

use std::error::Error;

pub mod models;
pub mod colors;
mod utils;
mod draw;

fn main_loop() -> Result<(), Box<Error>> {
    use std::env;
    use std::thread;
    //use std::io::Cursor;
    use std::time::Duration;
    use std::process::Command;
    use roboime_next::prelude::*;
    use roboime_next::{game, sim, ai};
    use clap::{Arg, App, AppSettings};
    use glium::{glutin, DisplayBuild, Surface};
    use log::LogLevelFilter;
    use env_logger::LogBuilder;
    //use image::image::GenericImage;
    use ::utils::*;

    let matches = App::new("robime-next-cli")
        .setting(AppSettings::ColoredHelp)
        .setting(AppSettings::DeriveDisplayOrder)
        .setting(AppSettings::TrailingVarArg)
        .about("Connect an AI to a Robocup SSL game through an stdio interface (like codingame).")
        .arg(Arg::with_name("blue")
             .short("b")
             .long("blue")
             .help("Play as the blue team."))
        .arg(Arg::with_name("yellow")
             .conflicts_with("blue")
             .short("y")
             .long("yellow")
             .help("Play as the yellow team. (default)"))
        .arg(Arg::with_name("right")
             .short("r")
             .long("right")
             .help("Play on the right side."))
        .arg(Arg::with_name("left")
             .short("l")
             .long("left")
             .help("Play on the left side. (default)"))
        .arg(Arg::with_name("v")
             .short("v")
             .multiple(true)
             .help("Sets the level of verbosity."))
        .arg(Arg::with_name("q")
             .conflicts_with("v")
             .long("quiet")
             .short("q")
             .help("Don't log warnings or errors."))
        //.arg(Arg::with_name("d")
        //     .long("debug")
        //     .short("d")
        //     .help("Enable debug logs."))
        .arg(Arg::with_name("AI")
             .required(true)
             .multiple(true)
             .value_name("COMMAND")
             .help("Command to start the AI, accepts arguments."))
        .get_matches();

    {
        let mut builder = LogBuilder::new();
        builder.format(|record| {
            format!("{} [{}] {}", record.level(), record.location().module_path(), record.args())
        });
        let verbosity = matches.occurrences_of("v");
        builder.filter(Some("roboime"), match verbosity {
            0 => LogLevelFilter::Warn,
            1 => LogLevelFilter::Info,
            2 => LogLevelFilter::Debug,
            _ => LogLevelFilter::Trace,
        });
        if matches.is_present("q") {
            builder.filter(Some("roboime"), LogLevelFilter::Off);
        }
        if let Ok(ref log) = env::var("RUST_LOG") {
           builder.parse(log);
        }
        try!(builder.init());
    }

    // building the display, ie. the main object
    let display = try!(glutin::WindowBuilder::new()
        .with_title(format!("RoboIME Next"))
        // 1 extra pixel to align the middle lines to the screen
        .with_dimensions(1041, 741)
        .with_depth_buffer(24)
        .with_gl(glutin::GlRequest::Latest)
        .with_multisampling(2)
        .with_vsync()
        .build_glium());

    let perspective = {
        let (width, height) = display.get_window().unwrap().get_inner_size_points().unwrap();
        perspective_matrix(width as f32, height as f32)
    };

    let is_yellow = {
        let mut yellow = true;
        if matches.is_present("blue")   { yellow = false; };
        if matches.is_present("yellow") { yellow = true; };
        yellow
    };

    let is_left = {
        let mut left = true;
        if matches.is_present("right") { left = false; };
        if matches.is_present("left")  { left = true; };
        left
    };

    let mut ai_cfg = {
        let ai_cmd: Vec<&str> = matches.values_of("AI").unwrap().collect();
        let (ai_program, ai_args) = (ai_cmd[0], &ai_cmd[1..]);
        let mut ai_command = Command::new(ai_program);
        ai_command.args(ai_args);
        let mut ai_cfg = ai::Interface::new(ai_command);
        ai_cfg.is_yellow(is_yellow);
        ai_cfg
    };

    let team_side = {
        use ::models::TeamSide::*;
        match (is_yellow, is_left) {
            (true,  true)  => YellowIsLeft,
            (true,  false) => BlueIsLeft,
            (false, false) => YellowIsLeft,
            (false, true)  => BlueIsLeft,
        }
    };

    let mut sim_state = sim::State::new(sim::TeamSide(sim::Color::yellow(is_yellow), sim::Side::left(is_left)));
    let mut draw_game = try!(draw::Game::new(&display)); draw_game.team_side(&display, team_side);
    let mut game_state = game::State::new();
    let mut ai = try!(ai_cfg.spawn());

    let mut accumulator = 0;
    let mut previous_clock = clock_ticks::precise_time_ns();
    let mut step_clock = previous_clock;
    let mut step_counter = 0;

    // init the AI
    debug!("Wait for AI to start...");
    try!(ai.push_init(&game_state));

    //drop(try!(rx.recv()));
    debug!("AI started, going on...");

    // debugger thread
    let debug = ai.debug.take().unwrap();
    let debugger = thread::spawn(move || {
        for line in debug {
            println!("AI> {}", line.unwrap());
        }
    });

    // the main loop
    'main: loop {

        // render the game state
        let view = view_matrix(&[0.0, 0.0, 10.0], &[0.0, 0.0, -1.0], &[0.0, 1.0, 0.0]);
        //let view = view_matrix(&[-4.0, -4.0, 4.0], &[1.0, 1.0, -1.0], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[4.0, -4.0, 4.0], &[-1.0, 1.0, -1.0], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[-0.2, -0.2, 0.6], &[0.2, 0.2, -0.6], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[1.0, 2.0, 3.0], &[1.0, 1.0, -3.0], &[0.0, 1.0, 0.0]);
        //let view = view_matrix(&[-4.0, 0.7, 1.6], &[-0.2, -0.2, -0.6], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[-5.0, -0.7, 1.6], &[0.2, 0.2, -0.6], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[4.0, 0.7, 1.6], &[0.2, -0.2, -0.6], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[5.0, -0.7, 1.6], &[-0.2, 0.2, -0.6], &[0.0, 0.0, 1.0]);
        let mut target = display.draw();
        {
            //let state = try!(game_state.read());
            let state = &game_state;
            try!(draw_game.draw_to(&mut target, &state, perspective, view));
        }
        try!(target.finish());

        // polling and handling the events received by the window
        for event in display.poll_events() {
            match event {
                glutin::Event::KeyboardInput(_, _, Some(glutin::VirtualKeyCode::Escape)) |
                glutin::Event::Closed => break 'main,
                _ => ()
            }
        }

        let now = clock_ticks::precise_time_ns();
        accumulator += now - previous_clock;
        previous_clock = now;

        const FIXED_TIME_STAMP: u64 = 16666667;
        while accumulator >= FIXED_TIME_STAMP {
            accumulator -= FIXED_TIME_STAMP;
            let now = clock_ticks::precise_time_ns();
            let delta = now - step_clock;
            if delta >= 1_000_000_000 {
                // expect ~60 steps per second
                info!("{:2} steps in {:.03} seconds", step_counter, delta as f32 * 1.0e-9);
                step_counter = 0;
                step_clock = now;
            }
            step_counter += 1;

            // game step
            try!(ai.push_state(&game_state));
            let cmd = try!(ai.read_command(&game_state));
            sim_state.step(cmd, FIXED_TIME_STAMP as f32 * 1.0e-9);
            sim_state.update_game(&mut game_state);
        }

        thread::sleep(Duration::from_millis(((FIXED_TIME_STAMP - accumulator) / 1_000_000) as u64));
    }

    try!(ai.quit());
    debug!("Waiting for AI to exit");
    // FIXME: error after a quit is a bug, silence it for now
    let _ = ai.join();
    let _ = debugger.join();
    info!("Bye!");

    Ok(())
}

fn main() {
    use std::process::exit;

    if let Err(err) = main_loop() {
        println!("Error: {}.", err.description());

        let mut err: &Error = &*err;
        while let Some(cause) = err.cause() {
            println!("- caused by: {}", cause.description());
            err = cause;
        }

        exit(1);
    }
}
<commit_msg>Pause (P) and single step (]) shortcuts.<commit_after>extern crate roboime_next;
#[macro_use] extern crate glium;
extern crate clap;
extern crate clock_ticks;
//extern crate image;
extern crate env_logger;
#[macro_use] extern crate log;

use std::error::Error;

pub mod models;
pub mod colors;
mod utils;
mod draw;

fn main_loop() -> Result<(), Box<Error>> {
    use std::env;
    use std::thread;
    //use std::io::Cursor;
    use std::time::Duration;
    use std::process::Command;
    use roboime_next::prelude::*;
    use roboime_next::{game, sim, ai};
    use clap::{Arg, App, AppSettings};
    use glium::{glutin, DisplayBuild, Surface};
    use log::LogLevelFilter;
    use env_logger::LogBuilder;
    //use image::image::GenericImage;
    use ::utils::*;

    let matches = App::new("robime-next-cli")
        .setting(AppSettings::ColoredHelp)
        .setting(AppSettings::DeriveDisplayOrder)
        .setting(AppSettings::TrailingVarArg)
        .about("Connect an AI to a Robocup SSL game through an stdio interface (like codingame).")
        .arg(Arg::with_name("blue")
             .short("b")
             .long("blue")
             .help("Play as the blue team."))
        .arg(Arg::with_name("yellow")
             .conflicts_with("blue")
             .short("y")
             .long("yellow")
             .help("Play as the yellow team. (default)"))
        .arg(Arg::with_name("right")
             .short("r")
             .long("right")
             .help("Play on the right side."))
        .arg(Arg::with_name("left")
             .conflicts_with("right")
             .short("l")
             .long("left")
             .help("Play on the left side. (default)"))
        .arg(Arg::with_name("pause")
             .short("p")
             .long("pause")
             .help("Start the simulator paused."))
        .arg(Arg::with_name("v")
             .short("v")
             .multiple(true)
             .help("Sets the level of verbosity."))
        .arg(Arg::with_name("q")
             .conflicts_with("v")
             .long("quiet")
             .short("q")
             .help("Don't log warnings or errors."))
        //.arg(Arg::with_name("d")
        //     .long("debug")
        //     .short("d")
        //     .help("Enable debug logs."))
        .arg(Arg::with_name("AI")
             .required(true)
             .multiple(true)
             .value_name("COMMAND")
             .help("Command to start the AI, accepts arguments."))
        .get_matches();

    {
        let mut builder = LogBuilder::new();
        builder.format(|record| {
            format!("{} [{}] {}", record.level(), record.location().module_path(), record.args())
        });
        let verbosity = matches.occurrences_of("v");
        builder.filter(Some("roboime"), match verbosity {
            0 => LogLevelFilter::Warn,
            1 => LogLevelFilter::Info,
            2 => LogLevelFilter::Debug,
            _ => LogLevelFilter::Trace,
        });
        if matches.is_present("q") {
            builder.filter(Some("roboime"), LogLevelFilter::Off);
        }
        if let Ok(ref log) = env::var("RUST_LOG") {
           builder.parse(log);
        }
        try!(builder.init());
    }

    // building the display, ie. the main object
    let display = try!(glutin::WindowBuilder::new()
        .with_title(format!("RoboIME Next"))
        // 1 extra pixel to align the middle lines to the screen
        .with_dimensions(1041, 741)
        .with_depth_buffer(24)
        .with_gl(glutin::GlRequest::Latest)
        .with_multisampling(2)
        .with_vsync()
        .build_glium());

    let perspective = {
        let (width, height) = display.get_window().unwrap().get_inner_size_points().unwrap();
        perspective_matrix(width as f32, height as f32)
    };

    let is_yellow = {
        let mut yellow = true;
        if matches.is_present("blue")   { yellow = false; };
        if matches.is_present("yellow") { yellow = true; };
        yellow
    };

    let is_left = {
        let mut left = true;
        if matches.is_present("right") { left = false; };
        if matches.is_present("left")  { left = true; };
        left
    };

    let mut is_paused = {
        let mut pause = false;
        if matches.is_present("pause") { pause = true; };
        pause
    };

    let mut single_shot = false;

    let mut ai_cfg = {
        let ai_cmd: Vec<&str> = matches.values_of("AI").unwrap().collect();
        let (ai_program, ai_args) = (ai_cmd[0], &ai_cmd[1..]);
        let mut ai_command = Command::new(ai_program);
        ai_command.args(ai_args);
        let mut ai_cfg = ai::Interface::new(ai_command);
        ai_cfg.is_yellow(is_yellow);
        ai_cfg
    };

    let team_side = {
        use ::models::TeamSide::*;
        match (is_yellow, is_left) {
            (true,  true)  => YellowIsLeft,
            (true,  false) => BlueIsLeft,
            (false, false) => YellowIsLeft,
            (false, true)  => BlueIsLeft,
        }
    };

    let mut sim_state = sim::State::new(sim::TeamSide(sim::Color::yellow(is_yellow), sim::Side::left(is_left)));
    let mut draw_game = try!(draw::Game::new(&display)); draw_game.team_side(&display, team_side);
    let mut game_state = game::State::new();
    let mut ai = try!(ai_cfg.spawn());

    let mut accumulator = 0;
    let mut previous_clock = clock_ticks::precise_time_ns();
    let mut step_clock = previous_clock;
    let mut step_counter = 0;

    // init the AI
    debug!("Wait for AI to start...");
    sim_state.update_game(&mut game_state);
    try!(ai.push_init(&game_state));

    //drop(try!(rx.recv()));
    debug!("AI started, going on...");

    // debugger thread
    let debug = ai.debug.take().unwrap();
    let debugger = thread::spawn(move || {
        for line in debug {
            println!("AI> {}", line.unwrap());
        }
    });

    // the main loop
    'main: loop {

        // render the game state
        let view = view_matrix(&[0.0, 0.0, 10.0], &[0.0, 0.0, -1.0], &[0.0, 1.0, 0.0]);
        //let view = view_matrix(&[-4.0, -4.0, 4.0], &[1.0, 1.0, -1.0], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[4.0, -4.0, 4.0], &[-1.0, 1.0, -1.0], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[-0.2, -0.2, 0.6], &[0.2, 0.2, -0.6], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[1.0, 2.0, 3.0], &[1.0, 1.0, -3.0], &[0.0, 1.0, 0.0]);
        //let view = view_matrix(&[-4.0, 0.7, 1.6], &[-0.2, -0.2, -0.6], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[-5.0, -0.7, 1.6], &[0.2, 0.2, -0.6], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[4.0, 0.7, 1.6], &[0.2, -0.2, -0.6], &[0.0, 0.0, 1.0]);
        //let view = view_matrix(&[5.0, -0.7, 1.6], &[-0.2, 0.2, -0.6], &[0.0, 0.0, 1.0]);
        let mut target = display.draw();
        {
            //let state = try!(game_state.read());
            let state = &game_state;
            try!(draw_game.draw_to(&mut target, &state, perspective, view));
        }
        try!(target.finish());

        // polling and handling the events received by the window
        for event in display.poll_events() {
            use glium::glutin::Event::*;
            use glium::glutin::ElementState::*;
            use glium::glutin::VirtualKeyCode;

            match event {
                KeyboardInput(_, _, Some(VirtualKeyCode::Escape)) |
                Closed => {
                    break 'main;
                }
                KeyboardInput(Pressed, _, Some(VirtualKeyCode::P)) => {
                    is_paused = !is_paused;
                }
                KeyboardInput(Pressed, _, Some(VirtualKeyCode::RBracket)) => {
                    single_shot = true;
                }
                KeyboardInput(Pressed, _, Some(VirtualKeyCode::R)) => {
                    // reset ball position and speed
                    sim_state.ball.pos.x = 0.0;
                    sim_state.ball.pos.y = 0.0;
                    sim_state.ball.vel.x = 0.0;
                    sim_state.ball.vel.y = 0.0;
                }
                _ => ()
            }
        }

        const FIXED_TIME_STEP: u64 = 16666667;

        let now = clock_ticks::precise_time_ns();
        if !is_paused {
            accumulator += now - previous_clock;

            while accumulator >= FIXED_TIME_STEP {
                accumulator -= FIXED_TIME_STEP;
                let now = clock_ticks::precise_time_ns();
                let delta = now - step_clock;
                if delta >= 1_000_000_000 {
                    // expect ~60 steps per second
                    info!("{:2} steps in {:.03} seconds", step_counter, delta as f32 * 1.0e-9);
                    step_counter = 0;
                    step_clock = now;
                }

                // game step
                try!(ai.push_state(&game_state));
                let cmd = try!(ai.read_command(&game_state));
                sim_state.step(cmd, FIXED_TIME_STEP as f32 * 1.0e-9);
                sim_state.update_game(&mut game_state);
                step_counter += 1;
            }
        }
        previous_clock = now;

        if single_shot {
            // XXX: is there a simple way to no duplicade this?
            // game step
            try!(ai.push_state(&game_state));
            let cmd = try!(ai.read_command(&game_state));
            sim_state.step(cmd, FIXED_TIME_STEP as f32 * 1.0e-9);
            sim_state.update_game(&mut game_state);
            single_shot = false;
        }

        thread::sleep(Duration::from_millis(((FIXED_TIME_STEP - accumulator) / 1_000_000) as u64));
    }

    try!(ai.quit());
    debug!("Waiting for AI to exit");
    // FIXME: error after a quit is a bug, silence it for now
    let _ = ai.join();
    let _ = debugger.join();
    info!("Bye!");

    Ok(())
}

fn main() {
    use std::process::exit;

    if let Err(err) = main_loop() {
        println!("Error: {}.", err.description());

        let mut err: &Error = &*err;
        while let Some(cause) = err.cause() {
            println!("- caused by: {}", cause.description());
            err = cause;
        }

        exit(1);
    }
}
<|endoftext|>