<commit_before>mod error;

use std::convert::{TryFrom, TryInto};

use fleetspeak::Packet;

use crate::action;
pub use self::error::{Error, ParseError};

pub type Result<T> = std::result::Result<T, Error>;

pub type Handler<R> = fn(&mut Action, R) -> Result<()>;

pub fn handle<R, M>(handler: Handler<R>, message: M) -> Result<()>
where
    R: action::Request,
    M: TryInto<Request<R>, Error=ParseError>,
{
    let request = message.try_into()?;

    let mut session = Action::new(request.session_id, request.request_id);
    handler(&mut session, request.data)
}

pub trait Session {
    fn send<R: action::Response>(&mut self, response: R) -> Result<()>;
}

pub struct Action {
    id: String,
    request_id: u64,
    next_response_id: u64,
}

impl Action {

    pub fn new(session_id: String, request_id: u64) -> Action {
        Action {
            id: session_id,
            request_id: request_id,
            next_response_id: 0,
        }
    }
}

impl Session for Action {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: self.id.clone(),
            request_id: Some(self.request_id),
            response_id: Some(self.next_response_id),
            data: response,
        }.send()?;

        self.next_response_id += 1;

        Ok(())
    }
}

pub struct Sink {
    id: &'static str,
}

impl Session for Sink {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }.send()
    }
}

pub fn startup() -> Sink {
    Sink { id: "/flows/F:Startup" }
}

// TODO: This type should not be exposed.
pub struct Request<R: action::Request> {
    pub name: String,
    pub session_id: String,
    pub request_id: u64,
    pub data: R,
}

impl<R: action::Request> TryFrom<rrg_proto::GrrMessage> for Request<R> {

    type Error = ParseError;

    fn try_from(message: rrg_proto::GrrMessage)
    -> std::result::Result<Request<R>, ParseError>
    {
        use ParseError::*;

        let name = message.name.ok_or(MissingField("action name"))?;
        let session_id = message.session_id.ok_or(MissingField("session id"))?;
        let request_id = message.request_id.ok_or(MissingField("request id"))?;

        let proto = match message.args {
            Some(bytes) => prost::Message::decode(&bytes[..])?,
            None => Default::default(),
        };

        Ok(Request {
            name: name,
            session_id: session_id,
            request_id: request_id,
            data: R::from_proto(proto),
        })
    }
}

struct Response<R: action::Response> {
    session_id: String,
    request_id: Option<u64>,
    response_id: Option<u64>,
    data: R,
}

impl<R: action::Response> Response<R> {

    fn send(self) -> Result<()> {
        let mut data = Vec::new();
        prost::Message::encode(&self.data.into_proto(), &mut data)?;

        let proto = rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: self.response_id,
            request_id: self.request_id,
            r#type: Some(rrg_proto::grr_message::Type::Message.into()),
            args_rdf_name: R::RDF_NAME.map(String::from),
            args: Some(data),
            ..Default::default()
        };

        fleetspeak::send(Packet {
            service: String::from("GRR"),
            kind: Some(String::from("GrrMessage")),
            data: proto,
        })?;

        Ok(())
    }
}
<commit_msg>Move session response encoding to a trait.<commit_after>mod error;

use std::convert::{TryFrom, TryInto};

use fleetspeak::Packet;

use crate::action;
pub use self::error::{Error, ParseError};

pub type Result<T> = std::result::Result<T, Error>;

pub type Handler<R> = fn(&mut Action, R) -> Result<()>;

pub fn handle<R, M>(handler: Handler<R>, message: M) -> Result<()>
where
    R: action::Request,
    M: TryInto<Request<R>, Error=ParseError>,
{
    let request = message.try_into()?;

    let mut session = Action::new(request.session_id, request.request_id);
    handler(&mut session, request.data)
}

pub trait Session {
    fn send<R: action::Response>(&mut self, response: R) -> Result<()>;
}

pub struct Action {
    id: String,
    request_id: u64,
    next_response_id: u64,
}

impl Action {

    pub fn new(session_id: String, request_id: u64) -> Action {
        Action {
            id: session_id,
            request_id: request_id,
            next_response_id: 0,
        }
    }
}

impl Session for Action {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: self.id.clone(),
            request_id: Some(self.request_id),
            response_id: Some(self.next_response_id),
            data: response,
        }.send()?;

        self.next_response_id += 1;

        Ok(())
    }
}

pub struct Sink {
    id: &'static str,
}

impl Session for Sink {

    fn send<R: action::Response>(&mut self, response: R) -> Result<()> {
        Response {
            session_id: String::from(self.id),
            request_id: None,
            response_id: None,
            data: response,
        }.send()
    }
}

pub fn startup() -> Sink {
    Sink { id: "/flows/F:Startup" }
}

// TODO: This type should not be exposed.
pub struct Request<R: action::Request> {
    pub name: String,
    pub session_id: String,
    pub request_id: u64,
    pub data: R,
}

impl<R: action::Request> TryFrom<rrg_proto::GrrMessage> for Request<R> {

    type Error = ParseError;

    fn try_from(message: rrg_proto::GrrMessage)
    -> std::result::Result<Request<R>, ParseError>
    {
        use ParseError::*;

        let name = message.name.ok_or(MissingField("action name"))?;
        let session_id = message.session_id.ok_or(MissingField("session id"))?;
        let request_id = message.request_id.ok_or(MissingField("request id"))?;

        let proto = match message.args {
            Some(bytes) => prost::Message::decode(&bytes[..])?,
            None => Default::default(),
        };

        Ok(Request {
            name: name,
            session_id: session_id,
            request_id: request_id,
            data: R::from_proto(proto),
        })
    }
}

struct Response<R: action::Response> {
    session_id: String,
    request_id: Option<u64>,
    response_id: Option<u64>,
    data: R,
}

impl<R: action::Response> Response<R> {

    fn send(self) -> Result<()> {
        let message: rrg_proto::GrrMessage = self.try_into()?;

        fleetspeak::send(Packet {
            service: String::from("GRR"),
            kind: Some(String::from("GrrMessage")),
            data: message,
        })?;

        Ok(())
    }
}

impl<R: action::Response> TryInto<rrg_proto::GrrMessage> for Response<R> {

    type Error = prost::EncodeError;

    fn try_into(self)
    -> std::result::Result<rrg_proto::GrrMessage, prost::EncodeError>
    {
        let mut data = Vec::new();
        prost::Message::encode(&self.data.into_proto(), &mut data)?;

        Ok(rrg_proto::GrrMessage {
            session_id: Some(self.session_id),
            response_id: self.response_id,
            request_id: self.request_id,
            r#type: Some(rrg_proto::grr_message::Type::Message.into()),
            args_rdf_name: R::RDF_NAME.map(String::from),
            args: Some(data),
            ..Default::default()
        })
    }
}
<|endoftext|>


<commit_before>use std::io::{self, Write};
use {Color, Style};

/// Extension to the `Write` trait.
///
/// This extension to the `Write` trait is capable of producing the correct ANSI escape sequences
/// for given commands, effectively controlling the terminal.
pub trait TermWrite {

    /// Print the CSI (control sequence introducer) followed by a byte string.
    fn csi(&mut self, b: &[u8]) -> io::Result<usize>;
    /// Print OSC (operating system command) followed by a byte string.
    fn osc(&mut self, b: &[u8]) -> io::Result<usize>;
    /// Print DSC (device control string) followed by a byte string.
    fn dsc(&mut self, b: &[u8]) -> io::Result<usize>;

    /// Clear the entire screen.
    fn clear(&mut self) -> io::Result<usize> {
        self.csi(b"2J")
    }
    /// Clear everything _after_ the cursor.
    fn clear_after(&mut self) -> io::Result<usize> {
        self.csi(b"J")
    }
    /// Clear everything _before_ the cursor.
    fn clear_before(&mut self) -> io::Result<usize> {
        self.csi(b"1J")
    }
    /// Clear the current line.
    fn clear_line(&mut self) -> io::Result<usize> {
        self.csi(b"2K")
    }
    /// Clear from the cursor until newline.
    fn clear_until_newline(&mut self) -> io::Result<usize> {
        self.csi(b"K")
    }
    /// Show the cursor.
    fn show_cursor(&mut self) -> io::Result<usize> {
        self.csi(b"?25h")
    }
    /// Hide the cursor.
    fn hide_cursor(&mut self) -> io::Result<usize> {
        self.csi(b"?25l")
    }
    /// Move the cursor `num` spaces to the left.
    fn move_cursor_left(&mut self, num: u32) -> io::Result<usize> {
        if num > 0 {
            self.csi(&[b'0' + (num / 10000) as u8,
                       b'0' + (num / 1000) as u8 % 10,
                       b'0' + (num / 100) as u8 % 10,
                       b'0' + (num / 10) as u8 % 10,
                       b'0' + num as u8 % 10,
                       b'C'])
        } else {
            Ok(0)
        }
    }
    /// Move the cursor `num` spaces to the right.
    fn move_cursor_right(&mut self, num: u32) -> io::Result<usize> {
        if num > 0 {
            self.csi(&[b'0' + (num / 10000) as u8,
                       b'0' + (num / 1000) as u8 % 10,
                       b'0' + (num / 100) as u8 % 10,
                       b'0' + (num / 10) as u8 % 10,
                       b'0' + num as u8 % 10,
                       b'D'])
        } else {
            Ok(0)
        }
    }

    // TODO
    // fn mode

    /// Reset the rendition mode.
    ///
    /// This will reset both the current style and color.
    fn reset(&mut self) -> io::Result<usize> {
        self.csi(b"m")
    }
    /// Restore the defaults.
    ///
    /// This will reset color, position, cursor state, and so on. It is recommended that you use
    /// this before you exit your program, to avoid messing up the user's terminal.
    fn restore(&mut self) -> io::Result<usize> {
        Ok(try!(self.reset()) + try!(self.clear()) + try!(self.goto(0, 0)) + try!(self.show_cursor()))
    }

    /// Go to a given position.
    ///
    /// The position is 0-based.
    fn goto(&mut self, mut x: u16, mut y: u16) -> io::Result<usize> {
        x += 1;
        y += 1;

        self.csi(&[
            b'0' + (y / 10000) as u8,
            b'0' + (y / 1000) as u8 % 10,
            b'0' + (y / 100) as u8 % 10,
            b'0' + (y / 10) as u8 % 10,
            b'0' + y as u8 % 10,
            b';',
            b'0' + (x / 10000) as u8,
            b'0' + (x / 1000) as u8 % 10,
            b'0' + (x / 100) as u8 % 10,
            b'0' + (x / 10) as u8 % 10,
            b'0' + x as u8 % 10,
            b'H',
        ])
    }
    /// Set graphic rendition.
    fn rendition(&mut self, r: u8) -> io::Result<usize> {
        self.csi(&[
            b'0' + r / 100,
            b'0' + r / 10 % 10,
            b'0' + r % 10,
            b'm',
        ])
    }
    /// Set foreground color.
    fn color(&mut self, color: Color) -> io::Result<usize> {
        let ansi = color.to_ansi_val();
        self.csi(&[
            b'3',
            b'8',
            b';',
            b'5',
            b';',
            b'0' + ansi / 100,
            b'0' + ansi / 10 % 10,
            b'0' + ansi % 10,
            b'm',
        ])
    }
    /// Set background color.
    fn bg_color(&mut self, color: Color) -> io::Result<usize> {
        let ansi = color.to_ansi_val();
        self.csi(&[
            b'4',
            b'8',
            b';',
            b'5',
            b';',
            b'0' + ansi / 100,
            b'0' + ansi / 10 % 10,
            b'0' + ansi % 10,
            b'm',
        ])
    }
    /// Set rendition mode (SGR).
    fn style(&mut self, mode: Style) -> io::Result<usize> {
        self.rendition(mode as u8)
    }
}

impl<W: Write> TermWrite for W {
    fn csi(&mut self, b: &[u8]) -> io::Result<usize> {
        Ok(try!(self.write(b"\x1B[")) + try!(self.write(b)))
    }
    fn osc(&mut self, b: &[u8]) -> io::Result<usize> {
        Ok(try!(self.write(b"\x1B]")) + try!(self.write(b)))
    }
    fn dsc(&mut self, b: &[u8]) -> io::Result<usize> {
        Ok(try!(self.write(b"\x1BP")) + try!(self.write(b)))
    }
}

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

    #[test]
    fn test_csi() {
        let mut buf = Cursor::new(Vec::new());
        buf.csi(b"bluh").unwrap();

        assert_eq!(buf.get_ref(), b"\x1B[bluh");

        buf.csi(b"blah").unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[bluh\x1B[blah");
    }
    #[test]
    fn test_csi_partial() {
        let mut buf = [0; 3];
        let mut buf = &mut buf[..];
        assert_eq!(buf.csi(b"blu").unwrap(), 3);
        assert_eq!(buf.csi(b"").unwrap(), 0);
        assert_eq!(buf.csi(b"nooooo").unwrap(), 0);
    }
    #[test]
    fn test_osc() {
        let mut buf = Cursor::new(Vec::new());
        buf.osc(b"bluh").unwrap();

        assert_eq!(buf.get_ref(), b"\x1B]bluh");

        buf.osc(b"blah").unwrap();
        assert_eq!(buf.get_ref(), b"\x1B]bluh\x1B]blah");
    }
    #[test]
    fn test_osc_partial() {
        let mut buf = [0; 3];
        let mut buf = &mut buf[..];
        assert_eq!(buf.osc(b"blu").unwrap(), 3);
        assert_eq!(buf.osc(b"").unwrap(), 0);
        assert_eq!(buf.osc(b"nooooo").unwrap(), 0);
    }
    #[test]
    fn test_dsc() {
        let mut buf = Cursor::new(Vec::new());
        buf.dsc(b"bluh").unwrap();

        assert_eq!(buf.get_ref(), b"\x1BPbluh");

        buf.dsc(b"blah").unwrap();
        assert_eq!(buf.get_ref(), b"\x1BPbluh\x1BPblah");
    }
    #[test]
    fn test_dsc_partial() {
        let mut buf = [0; 3];
        let mut buf = &mut buf[..];
        assert_eq!(buf.dsc(b"blu").unwrap(), 3);
        assert_eq!(buf.dsc(b"").unwrap(), 0);
        assert_eq!(buf.dsc(b"nooooo").unwrap(), 0);
    }
    #[test]
    fn test_clear() {
        let mut buf = Cursor::new(Vec::new());
        buf.clear().unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[2J");
        buf.clear().unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[2J\x1B[2J");
    }
    #[test]
    fn test_goto() {
        let mut buf = Cursor::new(Vec::new());
        buf.goto(34, 43).unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[00044;00035H");
        buf.goto(24, 45).unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[00044;00035H\x1B[00046;00025H");
    }
    #[test]
    fn test_style() {
        use Style;

        let mut buf = Cursor::new(Vec::new());
        buf.style(Style::Bold).unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[001m");
        buf.style(Style::Italic).unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[001m\x1B[003m");
    }
}
<commit_msg>fix cursor moving<commit_after>use std::io::{self, Write};
use {Color, Style};

/// Extension to the `Write` trait.
///
/// This extension to the `Write` trait is capable of producing the correct ANSI escape sequences
/// for given commands, effectively controlling the terminal.
pub trait TermWrite {

    /// Print the CSI (control sequence introducer) followed by a byte string.
    fn csi(&mut self, b: &[u8]) -> io::Result<usize>;
    /// Print OSC (operating system command) followed by a byte string.
    fn osc(&mut self, b: &[u8]) -> io::Result<usize>;
    /// Print DSC (device control string) followed by a byte string.
    fn dsc(&mut self, b: &[u8]) -> io::Result<usize>;

    /// Clear the entire screen.
    fn clear(&mut self) -> io::Result<usize> {
        self.csi(b"2J")
    }
    /// Clear everything _after_ the cursor.
    fn clear_after(&mut self) -> io::Result<usize> {
        self.csi(b"J")
    }
    /// Clear everything _before_ the cursor.
    fn clear_before(&mut self) -> io::Result<usize> {
        self.csi(b"1J")
    }
    /// Clear the current line.
    fn clear_line(&mut self) -> io::Result<usize> {
        self.csi(b"2K")
    }
    /// Clear from the cursor until newline.
    fn clear_until_newline(&mut self) -> io::Result<usize> {
        self.csi(b"K")
    }
    /// Show the cursor.
    fn show_cursor(&mut self) -> io::Result<usize> {
        self.csi(b"?25h")
    }
    /// Hide the cursor.
    fn hide_cursor(&mut self) -> io::Result<usize> {
        self.csi(b"?25l")
    }
    /// Move the cursor `num` spaces to the left.
    fn move_cursor_left(&mut self, num: u32) -> io::Result<usize> {
        if num > 0 {
            self.csi(&[b'0' + (num / 10000) as u8,
                       b'0' + (num / 1000) as u8 % 10,
                       b'0' + (num / 100) as u8 % 10,
                       b'0' + (num / 10) as u8 % 10,
                       b'0' + num as u8 % 10,
                       b'D'])
        } else {
            Ok(0)
        }
    }
    /// Move the cursor `num` spaces to the right.
    fn move_cursor_right(&mut self, num: u32) -> io::Result<usize> {
        if num > 0 {
            self.csi(&[b'0' + (num / 10000) as u8,
                       b'0' + (num / 1000) as u8 % 10,
                       b'0' + (num / 100) as u8 % 10,
                       b'0' + (num / 10) as u8 % 10,
                       b'0' + num as u8 % 10,
                       b'C'])
        } else {
            Ok(0)
        }
    }

    // TODO
    // fn mode

    /// Reset the rendition mode.
    ///
    /// This will reset both the current style and color.
    fn reset(&mut self) -> io::Result<usize> {
        self.csi(b"m")
    }
    /// Restore the defaults.
    ///
    /// This will reset color, position, cursor state, and so on. It is recommended that you use
    /// this before you exit your program, to avoid messing up the user's terminal.
    fn restore(&mut self) -> io::Result<usize> {
        Ok(try!(self.reset()) + try!(self.clear()) + try!(self.goto(0, 0)) + try!(self.show_cursor()))
    }

    /// Go to a given position.
    ///
    /// The position is 0-based.
    fn goto(&mut self, mut x: u16, mut y: u16) -> io::Result<usize> {
        x += 1;
        y += 1;

        self.csi(&[
            b'0' + (y / 10000) as u8,
            b'0' + (y / 1000) as u8 % 10,
            b'0' + (y / 100) as u8 % 10,
            b'0' + (y / 10) as u8 % 10,
            b'0' + y as u8 % 10,
            b';',
            b'0' + (x / 10000) as u8,
            b'0' + (x / 1000) as u8 % 10,
            b'0' + (x / 100) as u8 % 10,
            b'0' + (x / 10) as u8 % 10,
            b'0' + x as u8 % 10,
            b'H',
        ])
    }
    /// Set graphic rendition.
    fn rendition(&mut self, r: u8) -> io::Result<usize> {
        self.csi(&[
            b'0' + r / 100,
            b'0' + r / 10 % 10,
            b'0' + r % 10,
            b'm',
        ])
    }
    /// Set foreground color.
    fn color(&mut self, color: Color) -> io::Result<usize> {
        let ansi = color.to_ansi_val();
        self.csi(&[
            b'3',
            b'8',
            b';',
            b'5',
            b';',
            b'0' + ansi / 100,
            b'0' + ansi / 10 % 10,
            b'0' + ansi % 10,
            b'm',
        ])
    }
    /// Set background color.
    fn bg_color(&mut self, color: Color) -> io::Result<usize> {
        let ansi = color.to_ansi_val();
        self.csi(&[
            b'4',
            b'8',
            b';',
            b'5',
            b';',
            b'0' + ansi / 100,
            b'0' + ansi / 10 % 10,
            b'0' + ansi % 10,
            b'm',
        ])
    }
    /// Set rendition mode (SGR).
    fn style(&mut self, mode: Style) -> io::Result<usize> {
        self.rendition(mode as u8)
    }
}

impl<W: Write> TermWrite for W {
    fn csi(&mut self, b: &[u8]) -> io::Result<usize> {
        Ok(try!(self.write(b"\x1B[")) + try!(self.write(b)))
    }
    fn osc(&mut self, b: &[u8]) -> io::Result<usize> {
        Ok(try!(self.write(b"\x1B]")) + try!(self.write(b)))
    }
    fn dsc(&mut self, b: &[u8]) -> io::Result<usize> {
        Ok(try!(self.write(b"\x1BP")) + try!(self.write(b)))
    }
}

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

    #[test]
    fn test_csi() {
        let mut buf = Cursor::new(Vec::new());
        buf.csi(b"bluh").unwrap();

        assert_eq!(buf.get_ref(), b"\x1B[bluh");

        buf.csi(b"blah").unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[bluh\x1B[blah");
    }
    #[test]
    fn test_csi_partial() {
        let mut buf = [0; 3];
        let mut buf = &mut buf[..];
        assert_eq!(buf.csi(b"blu").unwrap(), 3);
        assert_eq!(buf.csi(b"").unwrap(), 0);
        assert_eq!(buf.csi(b"nooooo").unwrap(), 0);
    }
    #[test]
    fn test_osc() {
        let mut buf = Cursor::new(Vec::new());
        buf.osc(b"bluh").unwrap();

        assert_eq!(buf.get_ref(), b"\x1B]bluh");

        buf.osc(b"blah").unwrap();
        assert_eq!(buf.get_ref(), b"\x1B]bluh\x1B]blah");
    }
    #[test]
    fn test_osc_partial() {
        let mut buf = [0; 3];
        let mut buf = &mut buf[..];
        assert_eq!(buf.osc(b"blu").unwrap(), 3);
        assert_eq!(buf.osc(b"").unwrap(), 0);
        assert_eq!(buf.osc(b"nooooo").unwrap(), 0);
    }
    #[test]
    fn test_dsc() {
        let mut buf = Cursor::new(Vec::new());
        buf.dsc(b"bluh").unwrap();

        assert_eq!(buf.get_ref(), b"\x1BPbluh");

        buf.dsc(b"blah").unwrap();
        assert_eq!(buf.get_ref(), b"\x1BPbluh\x1BPblah");
    }
    #[test]
    fn test_dsc_partial() {
        let mut buf = [0; 3];
        let mut buf = &mut buf[..];
        assert_eq!(buf.dsc(b"blu").unwrap(), 3);
        assert_eq!(buf.dsc(b"").unwrap(), 0);
        assert_eq!(buf.dsc(b"nooooo").unwrap(), 0);
    }
    #[test]
    fn test_clear() {
        let mut buf = Cursor::new(Vec::new());
        buf.clear().unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[2J");
        buf.clear().unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[2J\x1B[2J");
    }
    #[test]
    fn test_goto() {
        let mut buf = Cursor::new(Vec::new());
        buf.goto(34, 43).unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[00044;00035H");
        buf.goto(24, 45).unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[00044;00035H\x1B[00046;00025H");
    }
    #[test]
    fn test_style() {
        use Style;

        let mut buf = Cursor::new(Vec::new());
        buf.style(Style::Bold).unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[001m");
        buf.style(Style::Italic).unwrap();
        assert_eq!(buf.get_ref(), b"\x1B[001m\x1B[003m");
    }
}
<|endoftext|>


<commit_before>use evaluation::Level;
use types::PokeType;

mod generated_species;
pub use self::generated_species::*;

pub const NUM_SPECIES: u16 = 251;

#[derive(Debug, Eq, PartialEq, Hash)]
/// Information about a specific Pokemon species.
pub struct PokeSpecies {
    id: u16,
    attack: u16,
    defense: u16,
    stamina: u16,
    primary_type: PokeType,
    secondary_type: Option<PokeType>,
    english: &'static str,
    japanese: &'static str,
    japanese_transliterated: &'static str,
    korean: &'static str,
    chinese: &'static str,
    french: &'static str,
    german: &'static str,
    spanish: &'static str,
    italian: &'static str,
}

impl PokeSpecies {
    /// Given the id of a species, return its corresponding data. Return `None` if no data is found
    /// for the given id.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::species::PokeSpecies;
    ///
    /// let dragonite = PokeSpecies::from_id(149).unwrap();
    /// assert_eq!((263, 201, 182), dragonite.base_stats());
    ///
    /// let no_such_pokemon = PokeSpecies::from_id(500);
    /// assert!(no_such_pokemon.is_none());
    /// ```
    pub fn from_id(id: u16) -> Option<&'static PokeSpecies> {
        if id == 0 || id > NUM_SPECIES - 1 {
            return None
        }

        Some(generated_species::ALL_SPECIES[(id - 1) as usize])
    }

    /// Return a list of all `PokeSpecies`, sorted by id.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::species::PokeSpecies;
    ///
    /// let all_species = PokeSpecies::all_species();
    ///
    /// assert_eq!(251, all_species.len());
    /// assert_eq!(1, all_species[0].id());
    /// ```
    pub fn all_species() -> &'static [&'static PokeSpecies] {
        generated_species::ALL_SPECIES
    }

    /// This species' id.
    pub fn id(&self) -> u16 {
        self.id
    }

    /// This species' base attack value.
    pub fn attack(&self) -> u16 {
        self.attack
    }

    /// This species's base defense value.
    pub fn defense(&self) -> u16 {
        self.defense
    }

    /// This species' base stamina value.
    pub fn stamina(&self) -> u16 {
        self.stamina
    }

    /// This species' base stats, as an `(attack, defense, stamina)` triple.
    pub fn base_stats(&self) -> (u16, u16, u16) {
        (self.attack, self.defense, self.stamina)
    }

    /// This species' primary `PokeType`.
    pub fn primary_type(&self) -> PokeType {
        self.primary_type
    }

    /// If this species is dual-typed, returns the secondary `PokeType`.
    pub fn secondary_type(&self) -> Option<PokeType> {
        self.secondary_type
    }

    /// Returns `true` if this species has two `PokeType`s.
    pub fn is_dual_type(&self) -> bool {
        self.secondary_type.is_some()
    }

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

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

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

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

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

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

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

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

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

    /// Returns the highest possible stats for this pokemon (e.g., perfect IVs).
    pub fn perfect_stats(&self) -> (u16, u16, u16) {
        (self.attack() + 15, self.defense() + 15, self.stamina() + 15)
    }

    /// Returns the species' max combat power at the given `Level`, assuming perfect IVs.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::{Level, species};
    ///
    /// let level_30 = Level::new(30).unwrap();
    /// assert_eq!(188, species::Magikarp.max_cp_at_level(level_30));
    /// ```
   pub fn max_cp_at_level(&self, level: Level) -> u16 {
        let (attack, defense, stamina) = self.perfect_stats();

        PokeSpecies::calculate_cp(attack, defense, stamina, level)
    }

    /// Returns this species' max Combat Power at level 39, assuming perfect IVs.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::species;
    ///
    /// assert_eq!(3_617, species::Tyranitar.max_cp());
    /// ```
    pub fn max_cp(&self) -> u16 {
        let (attack, defense, stamina) = self.perfect_stats();

        PokeSpecies::calculate_cp(attack, defense, stamina, Level::max())
    }

    fn calculate_cp(attack: u16, defense: u16, stamina: u16, level: Level) -> u16 {
        let attack_calc = attack as f64;
        let defense_calc = (defense as f64).sqrt();
        let stamina_calc = (stamina as f64).sqrt();

        let cp_multiplier = level.cp_multiplier().powi(2);

        let inner = attack_calc * defense_calc * stamina_calc * cp_multiplier / 10.;

        ::std::cmp::max(10, inner.floor() as u16)
    }
}

#[cfg(test)]
mod tests {
    use evaluation::Level;
    use types::PokeType;
    use species::*;

    #[test]
    fn species_by_id() {
        let pokemon = PokeSpecies::from_id(1).unwrap();
        assert_eq!(Bulbasaur, pokemon);

        let pokemon = PokeSpecies::from_id(161).unwrap();
        assert_eq!(Sentret, pokemon);

        let pokemon = PokeSpecies::from_id(249).unwrap();
        assert_eq!(Lugia, pokemon);

        assert!(PokeSpecies::from_id(252).is_none());
    }

    #[test]
    fn poketype() {
        assert_eq!(PokeType::Fire, Charizard.primary_type());
        assert_eq!(Some(PokeType::Flying), Charizard.secondary_type());

        assert_eq!(PokeType::Water, Squirtle.primary_type());
        assert!(Squirtle.secondary_type().is_none());
    }

    #[test]
    fn all_species() {
        let all_pokemon = PokeSpecies::all_species();
        let num_pokemon = 251;

        assert_eq!(num_pokemon, all_pokemon.len());

        for i in 0..num_pokemon {
            assert!(
                all_pokemon[i].id() == (i + 1) as u16,
                format!("Couldn't find pokemon #{}", i)
            );
        }
    }

    #[test]
    fn max_cp_at_level() {
        let level = Level::new(20).unwrap();

        assert_eq!(224, Kakuna.max_cp_at_level(level));
    }

    #[test]
    fn max_cp() {
        assert_eq!(955, Eevee.max_cp());
        assert_eq!(3_530, Dragonite.max_cp());
    }
}
<commit_msg>Improve all_species doc test<commit_after>use evaluation::Level;
use types::PokeType;

mod generated_species;
pub use self::generated_species::*;

pub const NUM_SPECIES: u16 = 251;

#[derive(Debug, Eq, PartialEq, Hash)]
/// Information about a specific Pokemon species.
pub struct PokeSpecies {
    id: u16,
    attack: u16,
    defense: u16,
    stamina: u16,
    primary_type: PokeType,
    secondary_type: Option<PokeType>,
    english: &'static str,
    japanese: &'static str,
    japanese_transliterated: &'static str,
    korean: &'static str,
    chinese: &'static str,
    french: &'static str,
    german: &'static str,
    spanish: &'static str,
    italian: &'static str,
}

impl PokeSpecies {
    /// Given the id of a species, return its corresponding data. Return `None` if no data is found
    /// for the given id.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::species::PokeSpecies;
    ///
    /// let dragonite = PokeSpecies::from_id(149).unwrap();
    /// assert_eq!((263, 201, 182), dragonite.base_stats());
    ///
    /// let no_such_pokemon = PokeSpecies::from_id(500);
    /// assert!(no_such_pokemon.is_none());
    /// ```
    pub fn from_id(id: u16) -> Option<&'static PokeSpecies> {
        if id == 0 || id > NUM_SPECIES - 1 {
            return None
        }

        Some(generated_species::ALL_SPECIES[(id - 1) as usize])
    }

    /// Return a list of all `PokeSpecies`, sorted by id.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::species::{NUM_SPECIES, PokeSpecies};
    ///
    /// let all_species = PokeSpecies::all_species();
    ///
    /// assert_eq!(NUM_SPECIES as usize, all_species.len());
    /// assert_eq!(1, all_species[0].id());
    /// ```
    pub fn all_species() -> &'static [&'static PokeSpecies] {
        generated_species::ALL_SPECIES
    }

    /// This species' id.
    pub fn id(&self) -> u16 {
        self.id
    }

    /// This species' base attack value.
    pub fn attack(&self) -> u16 {
        self.attack
    }

    /// This species's base defense value.
    pub fn defense(&self) -> u16 {
        self.defense
    }

    /// This species' base stamina value.
    pub fn stamina(&self) -> u16 {
        self.stamina
    }

    /// This species' base stats, as an `(attack, defense, stamina)` triple.
    pub fn base_stats(&self) -> (u16, u16, u16) {
        (self.attack, self.defense, self.stamina)
    }

    /// This species' primary `PokeType`.
    pub fn primary_type(&self) -> PokeType {
        self.primary_type
    }

    /// If this species is dual-typed, returns the secondary `PokeType`.
    pub fn secondary_type(&self) -> Option<PokeType> {
        self.secondary_type
    }

    /// Returns `true` if this species has two `PokeType`s.
    pub fn is_dual_type(&self) -> bool {
        self.secondary_type.is_some()
    }

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

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

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

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

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

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

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

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

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

    /// Returns the highest possible stats for this pokemon (e.g., perfect IVs).
    pub fn perfect_stats(&self) -> (u16, u16, u16) {
        (self.attack() + 15, self.defense() + 15, self.stamina() + 15)
    }

    /// Returns the species' max combat power at the given `Level`, assuming perfect IVs.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::{Level, species};
    ///
    /// let level_30 = Level::new(30).unwrap();
    /// assert_eq!(188, species::Magikarp.max_cp_at_level(level_30));
    /// ```
   pub fn max_cp_at_level(&self, level: Level) -> u16 {
        let (attack, defense, stamina) = self.perfect_stats();

        PokeSpecies::calculate_cp(attack, defense, stamina, level)
    }

    /// Returns this species' max Combat Power at level 39, assuming perfect IVs.
    ///
    /// ## Example:
    ///
    /// ```
    /// use pokemon_go_data::species;
    ///
    /// assert_eq!(3_617, species::Tyranitar.max_cp());
    /// ```
    pub fn max_cp(&self) -> u16 {
        let (attack, defense, stamina) = self.perfect_stats();

        PokeSpecies::calculate_cp(attack, defense, stamina, Level::max())
    }

    fn calculate_cp(attack: u16, defense: u16, stamina: u16, level: Level) -> u16 {
        let attack_calc = attack as f64;
        let defense_calc = (defense as f64).sqrt();
        let stamina_calc = (stamina as f64).sqrt();

        let cp_multiplier = level.cp_multiplier().powi(2);

        let inner = attack_calc * defense_calc * stamina_calc * cp_multiplier / 10.;

        ::std::cmp::max(10, inner.floor() as u16)
    }
}

#[cfg(test)]
mod tests {
    use evaluation::Level;
    use types::PokeType;
    use species::*;

    #[test]
    fn species_by_id() {
        let pokemon = PokeSpecies::from_id(1).unwrap();
        assert_eq!(Bulbasaur, pokemon);

        let pokemon = PokeSpecies::from_id(161).unwrap();
        assert_eq!(Sentret, pokemon);

        let pokemon = PokeSpecies::from_id(249).unwrap();
        assert_eq!(Lugia, pokemon);

        assert!(PokeSpecies::from_id(252).is_none());
    }

    #[test]
    fn poketype() {
        assert_eq!(PokeType::Fire, Charizard.primary_type());
        assert_eq!(Some(PokeType::Flying), Charizard.secondary_type());

        assert_eq!(PokeType::Water, Squirtle.primary_type());
        assert!(Squirtle.secondary_type().is_none());
    }

    #[test]
    fn all_species() {
        let all_pokemon = PokeSpecies::all_species();
        let num_pokemon = 251;

        assert_eq!(num_pokemon, all_pokemon.len());

        for i in 0..num_pokemon {
            assert!(
                all_pokemon[i].id() == (i + 1) as u16,
                format!("Couldn't find pokemon #{}", i)
            );
        }
    }

    #[test]
    fn max_cp_at_level() {
        let level = Level::new(20).unwrap();

        assert_eq!(224, Kakuna.max_cp_at_level(level));
    }

    #[test]
    fn max_cp() {
        assert_eq!(955, Eevee.max_cp());
        assert_eq!(3_530, Dragonite.max_cp());
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::str;
use std::char;
use std::convert;

use byteorder::{ByteOrder, BigEndian};
use unicode_names;
use unicode_width::UnicodeWidthChar;

use super::ascii;

pub fn describe(c: char) {
    println!("{}", Describable::from(c));
}

struct Describable {
    c: char,
}

impl fmt::Display for Describable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let cp : Codepoint = self.c.into();
        try!(cp.fmt(f));
        let printable : Printable = self.c.into();
        try!(write!(f, "\n{}", printable));
        let unicode_name = unicode_names::name(self.c);
        if let Some(n) = unicode_name.clone() {
            try!(write!(f, "\nUnicode name: {}\n", n));
        }
        if let Some(ascii) = ascii::additional_names(self.c) {
            let mut synonyms = vec!();
            let mut xmls: Option<&str> = None;
            let mnemos: Vec<&str> = ascii.mnemonics.iter().filter(|n| n.len() != 1).map(|s| *s).collect();
            for syn in ascii.synonyms {
                if syn.starts_with('&') && syn.ends_with(';') {
                    xmls = Some(syn);
                } else if let Some(unicode) = unicode_name.clone() {
                    if format!("{}", unicode).as_str().to_lowercase() != *syn.to_lowercase() {
                        synonyms.push(syn.clone());
                    }
                } else {
                    synonyms.push(syn.clone());
                }
            }
            if mnemos.len() > 0 {
                try!(write!(f, "Called: {}\n", mnemos.join(", ")));
            }
            if synonyms.len() > 0 {
                try!(write!(f, "Also known as: {}\n", synonyms.join(", ")));
            }
            if let Some(xml) = xmls {
                try!(write!(f, "Escapes in XML as: {}\n", xml));
            }
            if let Some(n) = ascii.note {
                try!(write!(f, "Note: {}\n", n));
            }
        }
        Ok(())
    }
}

impl convert::From<char> for Describable {
    fn from(c: char) -> Describable {
        Describable{c: c}
    }
}

struct Printable {
    c: char,
}

impl convert::From<char> for Printable {
    fn from(c: char) -> Printable {
        Printable{c: c}
    }
}

fn control_char(ch: char) -> char {
    match ch as u8 {
        0x7f => '?',
        _ => ('@' as u8 + (ch as u8 & 0x1f)) as char
    }
}

impl fmt::Display for Printable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let quote : String = self.c.escape_default().collect();
        if self.c.is_control() {
            try!(write!(f, "Control character; quotes as {}, called ^{}\n", quote, control_char(self.c)));
        } else {
            if let (Some(width), Some(cjk_width)) = (self.c.width(), self.c.width_cjk()) {
                if width == cjk_width {
                    try!(write!(f, "Width: {}, ", width));
                } else {
                    try!(write!(f, "Width: {} ({} in CJK context), ", width, cjk_width));
                }
            }
            if ! self.c.is_whitespace() {
                try!(write!(f, "prints as {}", self.c));
            } else {
                try!(write!(f, "prints as `{}'", self.c));
            }

            // Check if we can up/downcase:
            let mut caseflipped = String::new();
            if self.c.is_uppercase() {
                for c in self.c.to_lowercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nUpper case. Downcases to {}", caseflipped));
            } else if self.c.is_lowercase() {
                for c in self.c.to_uppercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nLower case. Upcases to {}", caseflipped));
            }

            // If we have quotable text, print that too:
            if quote.len() > 1 {
                try!(write!(f, "\nQuotes as {}", quote));
            }
        }
        Ok(())
    }
}

enum Codepoint {
    ASCII7bit(char),
    Latin1(char),
    UnicodeBasic(char),
    UnicodeWide(char)
}

impl convert::From<char> for Codepoint {
    fn from(c: char) -> Codepoint {
        match c as u32 {
            0 ... 128 => Codepoint::ASCII7bit(c),
            128 ... 256 => Codepoint::Latin1(c),
            256 ... 65536 => Codepoint::UnicodeBasic(c),
            _ => Codepoint::UnicodeWide(c),
        }
    }
}

impl fmt::Display for Codepoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Codepoint::ASCII7bit(c) => {
                let num = c as u32;
                write!(f, "ASCII {:1x}/{:1x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       (num & 0xf0) >> 4, num & 0x0f, num, num, num, num)
            }
            &Codepoint::Latin1(c) => {
                let num = c as u32;
                write!(f, "LATIN1 {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::UnicodeBasic(c) | &Codepoint::UnicodeWide(c) => {
                let num = c as u32;
                let mut string = String::new();
                string.push(c);
                let s = string.as_str();
                let utf8 = ByteRepresentation::from(s.bytes());
                let utf16 = ByteRepresentation::from(s.encode_utf16());
                let width = match self {
                    &Codepoint::UnicodeWide(_) => 8,
                    _ => 4,
                };
                write!(f, "U+{:0width$X}, &#{:}; 0x{:0width$X}, \\0{:o}, UTF-8: {}, UTF-16BE: {}",
                       num, num, num, num, utf8, utf16, width = width)
            }
        }
    }
}

enum ByteRepresentation {
    UTF8(Vec<u8>),
    UTF16BE(Vec<u8>),
}

impl<'a> convert::From<str::EncodeUtf16<'a>> for ByteRepresentation {
    fn from(bs: str::EncodeUtf16<'a>) -> ByteRepresentation {
        let words: Vec<u16> = bs.collect();
        let mut buf: Vec<u8> = Vec::with_capacity(words.len() * 2);
        for word in words {
            let mut split_word = [0; 2];
            BigEndian::write_u16(&mut split_word, word);
            buf.extend_from_slice(&split_word);
        }

        ByteRepresentation::UTF16BE(buf)
    }
}

impl<'a> convert::From<str::Bytes<'a>> for ByteRepresentation {
    fn from(bs: str::Bytes<'a>) -> ByteRepresentation {
        let bytes: Vec<u8> = bs.collect();
        ByteRepresentation::UTF8(bytes)
    }
}

impl fmt::Display for ByteRepresentation {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &ByteRepresentation::UTF8(ref bytes) => {
                let mut byte_iter = bytes.iter();
                try!(write!(f, "{:02x}", byte_iter.next().unwrap()));
                for byte in byte_iter {
                    try!(write!(f, " {:02x}", byte));
                }
            },
            &ByteRepresentation::UTF16BE(ref bytes) => {
                for byte in bytes.iter() {
                    try!(write!(f, "{:02x}", byte));
                }
            }
        }
        Ok(())
    }
}
<commit_msg>Fix newlines for characters without a name<commit_after>use std::fmt;
use std::str;
use std::char;
use std::convert;

use byteorder::{ByteOrder, BigEndian};
use unicode_names;
use unicode_width::UnicodeWidthChar;

use super::ascii;

pub fn describe(c: char) {
    println!("{}\n", Describable::from(c));
}

struct Describable {
    c: char,
}

impl fmt::Display for Describable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let cp : Codepoint = self.c.into();
        try!(cp.fmt(f));
        let printable : Printable = self.c.into();
        try!(write!(f, "\n{}", printable));
        let unicode_name = unicode_names::name(self.c);
        if let Some(n) = unicode_name.clone() {
            try!(write!(f, "\nUnicode name: {}", n));
        }
        if let Some(ascii) = ascii::additional_names(self.c) {
            let mut synonyms = vec!();
            let mut xmls: Option<&str> = None;
            let mnemos: Vec<&str> = ascii.mnemonics.iter().filter(|n| n.len() != 1).map(|s| *s).collect();
            for syn in ascii.synonyms {
                if syn.starts_with('&') && syn.ends_with(';') {
                    xmls = Some(syn);
                } else if let Some(unicode) = unicode_name.clone() {
                    if format!("{}", unicode).as_str().to_lowercase() != *syn.to_lowercase() {
                        synonyms.push(syn.clone());
                    }
                } else {
                    synonyms.push(syn.clone());
                }
            }
            if mnemos.len() > 0 {
                try!(write!(f, "Called: {}", mnemos.join(", ")));
            }
            if synonyms.len() > 0 {
                try!(write!(f, "Also known as: {}", synonyms.join(", ")));
            }
            if let Some(xml) = xmls {
                try!(write!(f, "Escapes in XML as: {}", xml));
            }
            if let Some(n) = ascii.note {
                try!(write!(f, "Note: {}", n));
            }
        }
        Ok(())
    }
}

impl convert::From<char> for Describable {
    fn from(c: char) -> Describable {
        Describable{c: c}
    }
}

struct Printable {
    c: char,
}

impl convert::From<char> for Printable {
    fn from(c: char) -> Printable {
        Printable{c: c}
    }
}

fn control_char(ch: char) -> char {
    match ch as u8 {
        0x7f => '?',
        _ => ('@' as u8 + (ch as u8 & 0x1f)) as char
    }
}

impl fmt::Display for Printable {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        let quote : String = self.c.escape_default().collect();
        if self.c.is_control() {
            try!(write!(f, "Control character; quotes as {}, called ^{}", quote, control_char(self.c)));
        } else {
            if let (Some(width), Some(cjk_width)) = (self.c.width(), self.c.width_cjk()) {
                if width == cjk_width {
                    try!(write!(f, "Width: {}, ", width));
                } else {
                    try!(write!(f, "Width: {} ({} in CJK context), ", width, cjk_width));
                }
            }
            if ! self.c.is_whitespace() {
                try!(write!(f, "prints as {}", self.c));
            } else {
                try!(write!(f, "prints as `{}'", self.c));
            }

            // Check if we can up/downcase:
            let mut caseflipped = String::new();
            if self.c.is_uppercase() {
                for c in self.c.to_lowercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nUpper case. Downcases to {}", caseflipped));
            } else if self.c.is_lowercase() {
                for c in self.c.to_uppercase() {
                    caseflipped.push(c);
                }
                try!(write!(f, "\nLower case. Upcases to {}", caseflipped));
            }

            // If we have quotable text, print that too:
            if quote.len() > 1 {
                try!(write!(f, "\nQuotes as {}", quote));
            }
        }
        Ok(())
    }
}

enum Codepoint {
    ASCII7bit(char),
    Latin1(char),
    UnicodeBasic(char),
    UnicodeWide(char)
}

impl convert::From<char> for Codepoint {
    fn from(c: char) -> Codepoint {
        match c as u32 {
            0 ... 128 => Codepoint::ASCII7bit(c),
            128 ... 256 => Codepoint::Latin1(c),
            256 ... 65536 => Codepoint::UnicodeBasic(c),
            _ => Codepoint::UnicodeWide(c),
        }
    }
}

impl fmt::Display for Codepoint {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &Codepoint::ASCII7bit(c) => {
                let num = c as u32;
                write!(f, "ASCII {:1x}/{:1x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       (num & 0xf0) >> 4, num & 0x0f, num, num, num, num)
            }
            &Codepoint::Latin1(c) => {
                let num = c as u32;
                write!(f, "LATIN1 {:02x}, {:3}, 0x{:02x}, 0{:03o}, bits {:08b}",
                       num, num, num, num, num)
            }
            &Codepoint::UnicodeBasic(c) | &Codepoint::UnicodeWide(c) => {
                let num = c as u32;
                let mut string = String::new();
                string.push(c);
                let s = string.as_str();
                let utf8 = ByteRepresentation::from(s.bytes());
                let utf16 = ByteRepresentation::from(s.encode_utf16());
                let width = match self {
                    &Codepoint::UnicodeWide(_) => 8,
                    _ => 4,
                };
                write!(f, "U+{:0width$X}, &#{:}; 0x{:0width$X}, \\0{:o}, UTF-8: {}, UTF-16BE: {}",
                       num, num, num, num, utf8, utf16, width = width)
            }
        }
    }
}

enum ByteRepresentation {
    UTF8(Vec<u8>),
    UTF16BE(Vec<u8>),
}

impl<'a> convert::From<str::EncodeUtf16<'a>> for ByteRepresentation {
    fn from(bs: str::EncodeUtf16<'a>) -> ByteRepresentation {
        let words: Vec<u16> = bs.collect();
        let mut buf: Vec<u8> = Vec::with_capacity(words.len() * 2);
        for word in words {
            let mut split_word = [0; 2];
            BigEndian::write_u16(&mut split_word, word);
            buf.extend_from_slice(&split_word);
        }

        ByteRepresentation::UTF16BE(buf)
    }
}

impl<'a> convert::From<str::Bytes<'a>> for ByteRepresentation {
    fn from(bs: str::Bytes<'a>) -> ByteRepresentation {
        let bytes: Vec<u8> = bs.collect();
        ByteRepresentation::UTF8(bytes)
    }
}

impl fmt::Display for ByteRepresentation {
    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> {
        match self {
            &ByteRepresentation::UTF8(ref bytes) => {
                let mut byte_iter = bytes.iter();
                try!(write!(f, "{:02x}", byte_iter.next().unwrap()));
                for byte in byte_iter {
                    try!(write!(f, " {:02x}", byte));
                }
            },
            &ByteRepresentation::UTF16BE(ref bytes) => {
                for byte in bytes.iter() {
                    try!(write!(f, "{:02x}", byte));
                }
            }
        }
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::borrow::Cow;
use std::fmt;
use std::io;
use std::ops::Deref;

use ansi::RESET;
use difference::Difference;
use style::{Style, Colour};
use write::AnyWrite;

/// An ANSIGenericString includes a generic string type and a Style to
/// display that string.  ANSIString and ANSIByteString are aliases for
/// this type on str and [u8], respectively.
#[derive(PartialEq, Debug)]
pub struct ANSIGenericString<'a, S: 'a + ToOwned + ?Sized>
where <S as ToOwned>::Owned: fmt::Debug {
    style: Style,
    string: Cow<'a, S>,
}

/// Cloning an ANSIGenericString will clone its underlying string.
///
/// ### Examples
///
/// ```
/// use ansi_term::ANSIString;
///
/// let plain_string = ANSIString::from("a plain string");
/// let clone_string = plain_string.clone();
/// assert_eq!(clone_string, plain_string);
/// ```
impl<'a, S: 'a + ToOwned + ?Sized> Clone for ANSIGenericString<'a, S>
where <S as ToOwned>::Owned: fmt::Debug {
    fn clone(&self) -> ANSIGenericString<'a, S> {
        ANSIGenericString {
            style: self.style.clone(),
            string: self.string.clone(),
        }
    }
}

// You might think that the hand-written Clone impl above is the same as the
// one that gets generated with #[derive]. But it’s not *quite* the same!
//
// `str` is not Clone, and the derived Clone implementation puts a Clone
// constraint on the S type parameter (generated using --pretty=expanded):
//
//                  ↓_________________↓
//     impl <'a, S: ::std::clone::Clone + 'a + ToOwned + ?Sized> ::std::clone::Clone
//     for ANSIGenericString<'a, S> where
//     <S as ToOwned>::Owned: fmt::Debug { ... }
//
// This resulted in compile errors when you tried to derive Clone on a type
// that used it:
//
//     #[derive(PartialEq, Debug, Clone, Default)]
//     pub struct TextCellContents(Vec<ANSIString<'static>>);
//                                 ^^^^^^^^^^^^^^^^^^^^^^^^^
//     error[E0277]: the trait `std::clone::Clone` is not implemented for `str`
//
// The hand-written impl above can ignore that constraint and still compile.

/// An ANSI String is a string coupled with the Style to display it
/// in a terminal.
///
/// Although not technically a string itself, it can be turned into
/// one with the `to_string` method.
///
/// ### Examples
///
/// ```no_run
/// use ansi_term::ANSIString;
/// use ansi_term::Colour::Red;
///
/// let red_string = Red.paint("a red string");
/// println!("{}", red_string);
/// ```
///
/// ```
/// use ansi_term::ANSIString;
///
/// let plain_string = ANSIString::from("a plain string");
/// assert_eq!(&*plain_string, "a plain string");
/// ```
pub type ANSIString<'a> = ANSIGenericString<'a, str>;

/// An ANSIByteString represents a formatted series of bytes.  Use
/// ANSIByteString when styling text with an unknown encoding.
pub type ANSIByteString<'a> = ANSIGenericString<'a, [u8]>;

impl<'a, I, S: 'a + ToOwned + ?Sized> From<I> for ANSIGenericString<'a, S>
where I: Into<Cow<'a, S>>,
      <S as ToOwned>::Owned: fmt::Debug {
    fn from(input: I) -> ANSIGenericString<'a, S> {
        ANSIGenericString {
            string: input.into(),
            style:  Style::default(),
        }
    }
}

impl<'a, S: 'a + ToOwned + ?Sized> Deref for ANSIGenericString<'a, S>
where <S as ToOwned>::Owned: fmt::Debug {
    type Target = S;

    fn deref(&self) -> &S {
        self.string.deref()
    }
}

/// A set of `ANSIGenericString`s collected together, in order to be
/// written with a minimum of control characters.
pub struct ANSIGenericStrings<'a, S: 'a + ToOwned + ?Sized>
    (pub &'a [ANSIGenericString<'a, S>])
    where <S as ToOwned>::Owned: fmt::Debug;

/// A set of `ANSIString`s collected together, in order to be written with a
/// minimum of control characters.
pub type ANSIStrings<'a> = ANSIGenericStrings<'a, str>;

/// A function to construct an ANSIStrings instance.
#[allow(non_snake_case)]
pub fn ANSIStrings<'a>(arg: &'a [ANSIString<'a>]) -> ANSIStrings<'a> {
    ANSIGenericStrings(arg)
}

/// A set of `ANSIByteString`s collected together, in order to be
/// written with a minimum of control characters.
pub type ANSIByteStrings<'a> = ANSIGenericStrings<'a, [u8]>;

/// A function to construct an ANSIByteStrings instance.
#[allow(non_snake_case)]
pub fn ANSIByteStrings<'a>(arg: &'a [ANSIByteString<'a>]) -> ANSIByteStrings<'a> {
    ANSIGenericStrings(arg)
}

// ---- paint functions ----

impl Style {

    /// Paints the given text with this colour, returning an ANSI string.
    pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> ANSIGenericString<'a, S>
    where I: Into<Cow<'a, S>>,
          <S as ToOwned>::Owned: fmt::Debug {
        ANSIGenericString {
            string: input.into(),
            style:  self,
        }
    }
}

impl Colour {

    /// Paints the given text with this colour, returning an ANSI string.
    /// This is a short-cut so you don’t have to use `Blue.normal()` just
    /// to get blue text.
    ///
    /// ```
    /// use ansi_term::Colour::Blue;
    /// println!("{}", Blue.paint("da ba dee"));
    /// ```
    pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> ANSIGenericString<'a, S>
    where I: Into<Cow<'a, S>>,
          <S as ToOwned>::Owned: fmt::Debug {
        ANSIGenericString {
            string: input.into(),
            style:  self.normal(),
        }
    }
}

// ---- writers for individual ANSI strings ----

impl<'a> fmt::Display for ANSIString<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let w: &mut fmt::Write = f;
        self.write_to_any(w)
    }
}

impl<'a> ANSIByteString<'a> {
    /// Write an ANSIByteString to an io::Write.  This writes the escape
    /// sequences for the associated Style around the bytes.
    pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
        let w: &mut io::Write = w;
        self.write_to_any(w)
    }
}

impl<'a, S: 'a + ToOwned + ?Sized> ANSIGenericString<'a, S>
where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
    fn write_to_any<W: AnyWrite<wstr=S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
        write!(w, "{}", self.style.prefix())?;
        w.write_str(self.string.as_ref())?;
        write!(w, "{}", self.style.suffix())
    }
}

// ---- writers for combined ANSI strings ----

impl<'a> fmt::Display for ANSIStrings<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let f: &mut fmt::Write = f;
        self.write_to_any(f)
    }
}

impl<'a> ANSIByteStrings<'a> {
    /// Write ANSIByteStrings to an io::Write.  This writes the minimal
    /// escape sequences for the associated Styles around each set of
    /// bytes.
    pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
        let w: &mut io::Write = w;
        self.write_to_any(w)
    }
}

impl<'a, S: 'a + ToOwned + ?Sized> ANSIGenericStrings<'a, S>
where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
    fn write_to_any<W: AnyWrite<wstr=S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
        use self::Difference::*;

        let first = match self.0.first() {
            None => return Ok(()),
            Some(f) => f,
        };

        write!(w, "{}", first.style.prefix())?;
        w.write_str(first.string.as_ref())?;

        for window in self.0.windows(2) {
            match Difference::between(&window[0].style, &window[1].style) {
                ExtraStyles(style) => write!(w, "{}", style.prefix())?,
                Reset              => write!(w, "{}{}", RESET, window[1].style.prefix())?,
                NoDifference       => {/* Do nothing! */},
            }

            w.write_str(&window[1].string)?;
        }

        // Write the final reset string after all of the ANSIStrings have been
        // written, *except* if the last one has no styles, because it would
        // have already been written by this point.
        if let Some(last) = self.0.last() {
            if !last.style.is_plain() {
                write!(w, "{}", RESET)?;
            }
        }

        Ok(())
    }
}

// ---- tests ----

#[cfg(test)]
mod tests {
    pub use super::super::ANSIStrings;
    pub use style::Style;
    pub use style::Colour::*;

    #[test]
    fn no_control_codes_for_plain() {
        let one = Style::default().paint("one");
        let two = Style::default().paint("two");
        let output = format!("{}", ANSIStrings( &[ one, two ] ));
        assert_eq!(&*output, "onetwo");
    }
}
<commit_msg>clippy: Fix clone on copy warning.<commit_after>use std::borrow::Cow;
use std::fmt;
use std::io;
use std::ops::Deref;

use ansi::RESET;
use difference::Difference;
use style::{Style, Colour};
use write::AnyWrite;

/// An ANSIGenericString includes a generic string type and a Style to
/// display that string.  ANSIString and ANSIByteString are aliases for
/// this type on str and [u8], respectively.
#[derive(PartialEq, Debug)]
pub struct ANSIGenericString<'a, S: 'a + ToOwned + ?Sized>
where <S as ToOwned>::Owned: fmt::Debug {
    style: Style,
    string: Cow<'a, S>,
}

/// Cloning an ANSIGenericString will clone its underlying string.
///
/// ### Examples
///
/// ```
/// use ansi_term::ANSIString;
///
/// let plain_string = ANSIString::from("a plain string");
/// let clone_string = plain_string.clone();
/// assert_eq!(clone_string, plain_string);
/// ```
impl<'a, S: 'a + ToOwned + ?Sized> Clone for ANSIGenericString<'a, S>
where <S as ToOwned>::Owned: fmt::Debug {
    fn clone(&self) -> ANSIGenericString<'a, S> {
        ANSIGenericString {
            style: self.style,
            string: self.string.clone(),
        }
    }
}

// You might think that the hand-written Clone impl above is the same as the
// one that gets generated with #[derive]. But it’s not *quite* the same!
//
// `str` is not Clone, and the derived Clone implementation puts a Clone
// constraint on the S type parameter (generated using --pretty=expanded):
//
//                  ↓_________________↓
//     impl <'a, S: ::std::clone::Clone + 'a + ToOwned + ?Sized> ::std::clone::Clone
//     for ANSIGenericString<'a, S> where
//     <S as ToOwned>::Owned: fmt::Debug { ... }
//
// This resulted in compile errors when you tried to derive Clone on a type
// that used it:
//
//     #[derive(PartialEq, Debug, Clone, Default)]
//     pub struct TextCellContents(Vec<ANSIString<'static>>);
//                                 ^^^^^^^^^^^^^^^^^^^^^^^^^
//     error[E0277]: the trait `std::clone::Clone` is not implemented for `str`
//
// The hand-written impl above can ignore that constraint and still compile.

/// An ANSI String is a string coupled with the Style to display it
/// in a terminal.
///
/// Although not technically a string itself, it can be turned into
/// one with the `to_string` method.
///
/// ### Examples
///
/// ```no_run
/// use ansi_term::ANSIString;
/// use ansi_term::Colour::Red;
///
/// let red_string = Red.paint("a red string");
/// println!("{}", red_string);
/// ```
///
/// ```
/// use ansi_term::ANSIString;
///
/// let plain_string = ANSIString::from("a plain string");
/// assert_eq!(&*plain_string, "a plain string");
/// ```
pub type ANSIString<'a> = ANSIGenericString<'a, str>;

/// An ANSIByteString represents a formatted series of bytes.  Use
/// ANSIByteString when styling text with an unknown encoding.
pub type ANSIByteString<'a> = ANSIGenericString<'a, [u8]>;

impl<'a, I, S: 'a + ToOwned + ?Sized> From<I> for ANSIGenericString<'a, S>
where I: Into<Cow<'a, S>>,
      <S as ToOwned>::Owned: fmt::Debug {
    fn from(input: I) -> ANSIGenericString<'a, S> {
        ANSIGenericString {
            string: input.into(),
            style:  Style::default(),
        }
    }
}

impl<'a, S: 'a + ToOwned + ?Sized> Deref for ANSIGenericString<'a, S>
where <S as ToOwned>::Owned: fmt::Debug {
    type Target = S;

    fn deref(&self) -> &S {
        self.string.deref()
    }
}

/// A set of `ANSIGenericString`s collected together, in order to be
/// written with a minimum of control characters.
pub struct ANSIGenericStrings<'a, S: 'a + ToOwned + ?Sized>
    (pub &'a [ANSIGenericString<'a, S>])
    where <S as ToOwned>::Owned: fmt::Debug;

/// A set of `ANSIString`s collected together, in order to be written with a
/// minimum of control characters.
pub type ANSIStrings<'a> = ANSIGenericStrings<'a, str>;

/// A function to construct an ANSIStrings instance.
#[allow(non_snake_case)]
pub fn ANSIStrings<'a>(arg: &'a [ANSIString<'a>]) -> ANSIStrings<'a> {
    ANSIGenericStrings(arg)
}

/// A set of `ANSIByteString`s collected together, in order to be
/// written with a minimum of control characters.
pub type ANSIByteStrings<'a> = ANSIGenericStrings<'a, [u8]>;

/// A function to construct an ANSIByteStrings instance.
#[allow(non_snake_case)]
pub fn ANSIByteStrings<'a>(arg: &'a [ANSIByteString<'a>]) -> ANSIByteStrings<'a> {
    ANSIGenericStrings(arg)
}

// ---- paint functions ----

impl Style {

    /// Paints the given text with this colour, returning an ANSI string.
    pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> ANSIGenericString<'a, S>
    where I: Into<Cow<'a, S>>,
          <S as ToOwned>::Owned: fmt::Debug {
        ANSIGenericString {
            string: input.into(),
            style:  self,
        }
    }
}

impl Colour {

    /// Paints the given text with this colour, returning an ANSI string.
    /// This is a short-cut so you don’t have to use `Blue.normal()` just
    /// to get blue text.
    ///
    /// ```
    /// use ansi_term::Colour::Blue;
    /// println!("{}", Blue.paint("da ba dee"));
    /// ```
    pub fn paint<'a, I, S: 'a + ToOwned + ?Sized>(self, input: I) -> ANSIGenericString<'a, S>
    where I: Into<Cow<'a, S>>,
          <S as ToOwned>::Owned: fmt::Debug {
        ANSIGenericString {
            string: input.into(),
            style:  self.normal(),
        }
    }
}

// ---- writers for individual ANSI strings ----

impl<'a> fmt::Display for ANSIString<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let w: &mut fmt::Write = f;
        self.write_to_any(w)
    }
}

impl<'a> ANSIByteString<'a> {
    /// Write an ANSIByteString to an io::Write.  This writes the escape
    /// sequences for the associated Style around the bytes.
    pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
        let w: &mut io::Write = w;
        self.write_to_any(w)
    }
}

impl<'a, S: 'a + ToOwned + ?Sized> ANSIGenericString<'a, S>
where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
    fn write_to_any<W: AnyWrite<wstr=S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
        write!(w, "{}", self.style.prefix())?;
        w.write_str(self.string.as_ref())?;
        write!(w, "{}", self.style.suffix())
    }
}

// ---- writers for combined ANSI strings ----

impl<'a> fmt::Display for ANSIStrings<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let f: &mut fmt::Write = f;
        self.write_to_any(f)
    }
}

impl<'a> ANSIByteStrings<'a> {
    /// Write ANSIByteStrings to an io::Write.  This writes the minimal
    /// escape sequences for the associated Styles around each set of
    /// bytes.
    pub fn write_to<W: io::Write>(&self, w: &mut W) -> io::Result<()> {
        let w: &mut io::Write = w;
        self.write_to_any(w)
    }
}

impl<'a, S: 'a + ToOwned + ?Sized> ANSIGenericStrings<'a, S>
where <S as ToOwned>::Owned: fmt::Debug, &'a S: AsRef<[u8]> {
    fn write_to_any<W: AnyWrite<wstr=S> + ?Sized>(&self, w: &mut W) -> Result<(), W::Error> {
        use self::Difference::*;

        let first = match self.0.first() {
            None => return Ok(()),
            Some(f) => f,
        };

        write!(w, "{}", first.style.prefix())?;
        w.write_str(first.string.as_ref())?;

        for window in self.0.windows(2) {
            match Difference::between(&window[0].style, &window[1].style) {
                ExtraStyles(style) => write!(w, "{}", style.prefix())?,
                Reset              => write!(w, "{}{}", RESET, window[1].style.prefix())?,
                NoDifference       => {/* Do nothing! */},
            }

            w.write_str(&window[1].string)?;
        }

        // Write the final reset string after all of the ANSIStrings have been
        // written, *except* if the last one has no styles, because it would
        // have already been written by this point.
        if let Some(last) = self.0.last() {
            if !last.style.is_plain() {
                write!(w, "{}", RESET)?;
            }
        }

        Ok(())
    }
}

// ---- tests ----

#[cfg(test)]
mod tests {
    pub use super::super::ANSIStrings;
    pub use style::Style;
    pub use style::Colour::*;

    #[test]
    fn no_control_codes_for_plain() {
        let one = Style::default().paint("one");
        let two = Style::default().paint("two");
        let output = format!("{}", ANSIStrings( &[ one, two ] ));
        assert_eq!(&*output, "onetwo");
    }
}
<|endoftext|>


<commit_before>use std::collections::BTreeMap;
use std::cmp::Ord;
use std::sync::Arc;
use error::Result;

pub trait ReadTransaction<K, V>
    where K: Ord
{
    fn get(&self, key: K) -> Result<V>;
    fn len(&self) -> usize;
}

pub trait WriteTransaction<K, V>
    where K: Ord
{
    fn update(&self, key: K, value: V) -> Result<V>;
    fn remove(&self, key: K) -> Result<V>;
}

#[derive(Debug)]
pub struct Transaction<K: Ord, V> {
    pub store: Arc<BTreeMap<K, V>>,
}

impl<K, V> Transaction<K, V>
    where K: Ord
{
    pub fn new(store: Arc<BTreeMap<K, V>>) -> Transaction<K, V> {
        Transaction { store: store }
    }

    fn commit() -> Result<()> {
        unimplemented!()
    }

    fn rollback() -> Result<()> {
        unimplemented!()
    }
}

impl<K, V> ReadTransaction<K, V> for Transaction<K, V>
    where K: Ord
{
    fn get(&self, key: K) -> Result<V> {
        unimplemented!()
    }

    fn len(&self) -> usize {
        self.store.len()
    }
}

impl<K, V> WriteTransaction<K, V> for Transaction<K, V>
    where K: Ord
{
    fn update(&self, key: K, value: V) -> Result<V> {
        unimplemented!()
    }

    fn remove(&self, key: K) -> Result<V> {
        unimplemented!()
    }
}
<commit_msg>feat: basic implementation of update and remove<commit_after>use std::collections::BTreeMap;
use std::cmp::Ord;
use std::sync::Arc;

use error::Result;

pub trait ReadTransaction<K, V>
    where K: Ord
{
    fn get(&self, key: K) -> Option<&V>;
    fn len(&self) -> usize;
    fn is_empty(&self) -> bool;
}

pub trait WriteTransaction<K, V>
    where K: Ord
{
    fn update(&mut self, key: K, value: V) -> Result<Option<V>>;
    fn remove(&mut self, key: K) -> Result<Option<V>>;
}

#[derive(Debug)]
pub struct Transaction<K: Ord, V> {
    pub store: Arc<BTreeMap<K, V>>,
}

impl<K, V> Transaction<K, V>
    where K: Ord
{
    pub fn new(store: Arc<BTreeMap<K, V>>) -> Transaction<K, V> {
        Transaction { store: store }
    }

    fn commit() -> Result<()> {
        unimplemented!()
    }

    fn rollback() -> Result<()> {
        unimplemented!()
    }
}

impl<K, V> ReadTransaction<K, V> for Transaction<K, V>
    where K: Ord
{
    fn get(&self, key: K) -> Option<&V> {
        self.store.get(&key)
    }

    fn len(&self) -> usize {
        self.store.len()
    }

    fn is_empty(&self) -> bool {
        self.store.is_empty()
    }
}

impl<K, V> WriteTransaction<K, V> for Transaction<K, V>
    where K: Ord
{
    fn update(&mut self, key: K, value: V) -> Result<Option<V>> {
      Ok(Arc::get_mut(&mut self.store).unwrap().insert(key, value))
    }

    fn remove(&mut self, key: K) -> Result<Option<V>> {
      Ok(Arc::get_mut(&mut self.store).unwrap().remove(&key))
    }
}
<|endoftext|>


<commit_before><commit_msg>Remove unused file<commit_after><|endoftext|>


<commit_before>
use gen::NoiseGen;
use gen::simplex::Simplex;
use utils::bound;

pub struct FBM {
    simp: Simplex,
    octaves: int,
    persitence: f64,
    gain: f64,
    maxVal: f64
}

impl FBM {
    pub fn new_rand(octaves: int, persitence: f64, gain: f64) -> FBM {
        FBM {   simp: Simplex::new_rand(),
                octaves: octaves,
                persitence: persitence,
                gain: gain,
                maxVal: FBM::calc_max(octaves, persitence)
            }
    }

    pub fn from_seed(seed:u32, octaves: int, persitence: f64, gain: f64) -> FBM {
        FBM {   simp: Simplex::from_seed(seed),
                octaves: octaves,
                persitence: persitence,
                gain: gain,
                maxVal: FBM::calc_max(octaves, persitence)
            }
    }

    pub fn get_seed(&mut self) -> u32 {
        self.simp.get_seed()
    }

    // static function for calculating the max/min values the noise can have
    // used to bound the noise to [-1,1]
    // If the octaves or persitence ever change, maxVal must be recalculated
    fn calc_max(octaves: int, persitence: f64) -> f64 {
        let mut a = 1.0;
        let mut n = 0.0;
        for i in range(0, octaves) {
            n += a;
            a *= persitence;
        }

        n
    }
}

impl NoiseGen for FBM {
    fn get_value2d(&mut self, x: f64, y: f64) -> f64 {
        let mut n = 0.0;
        let mut f = 1.0;
        let mut amp = 1.0;

        for i in range(0, self.octaves) {
            n += amp * self.simp.get_value2d(x*f, y*f);
            f *= self.gain;
            amp *= self.persitence;
        }

        bound(n, 0.0, 1.0, -self.maxVal, self.maxVal)
    }

    fn get_value3d(&mut self, x: f64, y: f64, z: f64) -> f64 {
        let mut n = 0.0;
        let mut f = 1.0;
        let mut amp = 1.0;

        for i in range(0, self.octaves) {
            n += amp * self.simp.get_value3d(x*f, y*f, z*f);
            f *= self.gain;
            amp *= self.persitence;
        }

        bound(n, 0.0, 1.0, -self.maxVal, self.maxVal)
    }
}

<commit_msg>Remove snake case<commit_after>
use gen::NoiseGen;
use gen::simplex::Simplex;
use utils::bound;

pub struct FBM {
    simp: Simplex,
    octaves: int,
    persitence: f64,
    gain: f64,
    max_val: f64
}

impl FBM {
    pub fn new_rand(octaves: int, persitence: f64, gain: f64) -> FBM {
        FBM {   simp: Simplex::new_rand(),
                octaves: octaves,
                persitence: persitence,
                gain: gain,
                max_val: FBM::calc_max(octaves, persitence)
            }
    }

    pub fn from_seed(seed:u32, octaves: int, persitence: f64, gain: f64) -> FBM {
        FBM {   simp: Simplex::from_seed(seed),
                octaves: octaves,
                persitence: persitence,
                gain: gain,
                max_val: FBM::calc_max(octaves, persitence)
            }
    }

    pub fn get_seed(&mut self) -> u32 {
        self.simp.get_seed()
    }

    // static function for calculating the max/min values the noise can have
    // used to bound the noise to [-1,1]
    // If the octaves or persitence ever change, max_val must be recalculated
    fn calc_max(octaves: int, persitence: f64) -> f64 {
        let mut a = 1.0;
        let mut n = 0.0;
        for i in range(0, octaves) {
            n += a;
            a *= persitence;
        }

        n
    }
}

impl NoiseGen for FBM {
    fn get_value2d(&mut self, x: f64, y: f64) -> f64 {
        let mut n = 0.0;
        let mut f = 1.0;
        let mut amp = 1.0;

        for i in range(0, self.octaves) {
            n += amp * self.simp.get_value2d(x*f, y*f);
            f *= self.gain;
            amp *= self.persitence;
        }

        bound(n, 0.0, 1.0, -self.max_val, self.max_val)
    }

    fn get_value3d(&mut self, x: f64, y: f64, z: f64) -> f64 {
        let mut n = 0.0;
        let mut f = 1.0;
        let mut amp = 1.0;

        for i in range(0, self.octaves) {
            n += amp * self.simp.get_value3d(x*f, y*f, z*f);
            f *= self.gain;
            amp *= self.persitence;
        }

        bound(n, 0.0, 1.0, -self.max_val, self.max_val)
    }
}

<|endoftext|>


<commit_before>//! Nadezhda's brain control program grammar
//!
//! The brain of our space cockroach is controlled by a program. The allowed
//! programs are described by the following grammar.
//!
//! ```plain
//! S -> forward S
//!    | backward S
//!    | ''
//! ```
//!
//! # Examples
//! We  show how to create a `Program` by hand
//!
//! ```rust
//! extern crate nadezhda;
//!
//! use nadezhda::grammar::Program;
//!
//! fn main() {
//!     let program: Program = Program::Forward(
//!       Box::new(Program::Forward(
//!         Box::new(Program::Stop)
//!       ))
//!     );
//!
//!     let message = match program {
//!       Program::Forward(_)  => "right",
//!       Program::Backward(_) => "wrong",
//!       Program::Stop        => "not even close",
//!     };
//!
//!     assert_eq!(message, "right");
//! }
//! ```

/// A `Program` is either
///
/// 1. `Forward` followed by a `Program`
/// 2. `Backward` followed by a `Program`
/// 3. nothing, this is signified by `Stop`
pub enum Program {
    /// forward alternative of the grammar
    Forward(Box<Program>),
    /// backward alternative of the grammar
    Backward(Box<Program>),
    /// empty alternative of the grammar
    Stop,
}
<commit_msg>Improve reading of documentation<commit_after>//! Nadezhda's brain control program grammar
//!
//! The brain of our space cockroach is controlled by a program. The allowed
//! programs are described by the following grammar.
//!
//! ```plain
//! S -> forward S
//!    | backward S
//!    | ''
//! ```
//!
//! # Examples
//! We  show how to create a `Program` by hand
//!
//! ```rust
//! extern crate nadezhda;
//!
//! use nadezhda::grammar::Program;
//!
//! fn main() {
//!     let program: Program = Program::Forward(
//!       Box::new(Program::Forward(
//!         Box::new(Program::Stop)
//!       ))
//!     );
//!
//!     let message = match program {
//!       Program::Forward(_)  => "right",
//!       Program::Backward(_) => "wrong",
//!       Program::Stop        => "not even close",
//!     };
//!
//!     assert_eq!(message, "right");
//! }
//! ```

/// A `Program` for the cockroach brain
///
/// It is either
/// 1. `Forward` followed by a `Program
/// 2. `Backward` followed by a `Program`
/// 3. nothing, this is signified by `Stop`
pub enum Program {
    /// forward alternative of the grammar
    Forward(Box<Program>),
    /// backward alternative of the grammar
    Backward(Box<Program>),
    /// empty alternative of the grammar
    Stop,
}
<|endoftext|>


<commit_before>use webcore::value::Reference;
use webcore::try_from::TryInto;
use webcore::reference_type::ReferenceType;

/// A blob object represents a file-like object of immutable, raw data.
/// Blobs represent data that isn't necessarily in a JavaScript-native format.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
// https://w3c.github.io/FileAPI/#dfn-Blob
pub trait IBlob: ReferenceType {
    /// The size, in bytes, of the data contained in the Blob object.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/size)
    // https://w3c.github.io/FileAPI/#ref-for-dfn-size%E2%91%A0
    fn len( &self ) -> u64 {
        let reference = self.as_ref();
        let length: u64 = js!( return @{reference}.size; ).try_into().unwrap();
        length
    }

    /// A string indicating the MIME type of the data contained in the `Blob`.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/type)
    // https://w3c.github.io/FileAPI/#ref-for-dfn-type%E2%91%A0
    fn mime( &self ) -> Option< String > {
        let reference = self.as_ref();
        let mime: String = js!( return @{reference}.type; ).try_into().unwrap();
        if mime.is_empty() {
            None
        } else {
            Some( mime )
        }
    }
}

/// A reference to a JavaScript object which implements the [IBlob](trait.IBlob.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
// https://w3c.github.io/FileAPI/#dfn-Blob
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Blob")]
pub struct Blob( Reference );

impl IBlob for Blob {}

impl Blob {
    /// Creates a new `Blob`.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob)
    // https://w3c.github.io/FileAPI/#constructorBlob
    pub fn new() -> Self {
        js! (
            return new Blob();
        ).try_into().unwrap()
    }
}
<commit_msg>Add `IBlob::slice` and `IBlob::slice_with_content_type` (#349)<commit_after>use std::ops::{RangeBounds, Bound};

use webcore::value::Reference;
use webcore::try_from::TryInto;
use webcore::reference_type::ReferenceType;
use webcore::number::Number;
use webcore::optional_arg::OptionalArg;

// https://w3c.github.io/FileAPI/#ref-for-dfn-slice
fn slice_blob< T, U >( blob: &T, range: U, content_type: Option< &str > ) -> Blob
    where T: IBlob, U: RangeBounds< u64 >
{
    let start: Number = match range.start_bound() {
        Bound::Included(&n) => n,
        Bound::Excluded(&n) => n + 1,
        Bound::Unbounded => 0
    }.try_into().unwrap();

    let end: OptionalArg< Number > = match range.end_bound() {
        Bound::Included(&n) => Some(n + 1),
        Bound::Excluded(&n) => Some(n),
        Bound::Unbounded => None
    }.try_into().unwrap();

    let content_type: OptionalArg< &str > = content_type.into();
    let reference = blob.as_ref();
    js! (
        return @{reference}.slice(@{start}, @{end}, @{content_type});
    ).try_into().unwrap()
}

/// A blob object represents a file-like object of immutable, raw data.
/// Blobs represent data that isn't necessarily in a JavaScript-native format.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
// https://w3c.github.io/FileAPI/#dfn-Blob
pub trait IBlob: ReferenceType {
    /// The size, in bytes, of the data contained in the Blob object.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/size)
    // https://w3c.github.io/FileAPI/#ref-for-dfn-size%E2%91%A0
    fn len( &self ) -> u64 {
        let reference = self.as_ref();
        let length: u64 = js!( return @{reference}.size; ).try_into().unwrap();
        length
    }

    /// A string indicating the MIME type of the data contained in the `Blob`.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/type)
    // https://w3c.github.io/FileAPI/#ref-for-dfn-type%E2%91%A0
    fn mime( &self ) -> Option< String > {
        let reference = self.as_ref();
        let mime: String = js!( return @{reference}.type; ).try_into().unwrap();
        if mime.is_empty() {
            None
        } else {
            Some( mime )
        }
    }

    /// Create a new `Blob` object containing the data in the specified range of bytes of the
    /// source `Blob`.
    ///
    /// See also [slice_with_content_type](IBlob::slice_with_content_type).
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/slice)
    fn slice< T >( &self, range: T ) -> Blob
        where T: RangeBounds<u64>
    {
        slice_blob(self, range, None)
    }

    /// [slice](IBlob::slice) `Blob` with the provided `content_type`.
    fn slice_with_content_type< T >( &self, range: T, content_type: &str ) -> Blob
        where T: RangeBounds<u64>
    {
        slice_blob(self, range, Some(content_type))
    }
}

/// A reference to a JavaScript object which implements the [IBlob](trait.IBlob.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob)
// https://w3c.github.io/FileAPI/#dfn-Blob
#[derive(Clone, Debug, PartialEq, Eq, ReferenceType)]
#[reference(instance_of = "Blob")]
pub struct Blob( Reference );

impl IBlob for Blob {}

impl Blob {
    /// Creates a new `Blob`.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Blob/Blob)
    // https://w3c.github.io/FileAPI/#constructorBlob
    pub fn new() -> Self {
        js! (
            return new Blob();
        ).try_into().unwrap()
    }
}
<|endoftext|>


<commit_before>use std::fmt;
use std::error;

use webcore::value::{Reference, FromReference};
use webcore::try_from::TryInto;
use webapi::event_target::{IEventTarget, EventTarget};
use webapi::node_list::NodeList;

/// A structure denoting that the specified DOM [Node](trait.INode.html) was not found.
#[derive(Debug)]
pub struct NotFoundError( String );
impl error::Error for NotFoundError {
    fn description( &self ) -> &str {
        self.0.as_str()
    }
}

impl fmt::Display for NotFoundError {
    fn fmt( &self, formatter: &mut fmt::Formatter ) -> fmt::Result {
        write!( formatter, "{}", self.0 )
    }
}

/// An enum which determines whenever the DOM [Node](trait.INode.html)'s children will also be cloned or not.
///
/// Mainly used in [INode::clone_node](trait.INode.html#method.clone_node).
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum CloneKind {
    /// Will not clone the children.
    Shallow,
    /// Will clone the children.
    Deep
}

/// `INode` is an interface from which a number of DOM API object types inherit.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node)
pub trait INode: IEventTarget + FromReference {
    /// Adds a node to the end of the list of children of a specified parent node.
    ///
    /// If the given child is a reference to an existing node in the document then
    /// it is moved from its current position to the new position (there is no requirement
    /// to remove the node from its parent node before appending it to some other node).
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)
    fn append_child< T: INode >( &self, child: &T ) {
        js! { @(no_return)
            @{self.as_ref()}.appendChild( @{child.as_ref()} );
        }
    }

    /// Removes a child node from the DOM.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild)
    fn remove_child< T: INode >( &self, child: &T ) -> Result< (), NotFoundError > {
        // TODO: Return the removed node.
        let status = js! {
            try {
                @{self.as_ref()}.removeChild( @{child.as_ref()} );
                return true;
            } catch( exception ) {
                if( exception instanceof NotFoundError ) {
                    return false;
                } else {
                    throw exception;
                }
            }
        };

        if status == true {
            Ok(())
        } else {
            Err( NotFoundError( "The node to be removed is not a child of this node.".to_owned() ) )
        }
    }

    /// Returns a duplicate of the node on which this method was called.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode)
    fn clone_node( &self, kind: CloneKind ) -> Self {
        let is_deep = match kind {
            CloneKind::Deep => true,
            CloneKind::Shallow => false
        };

        let cloned = js! {
            return @{self.as_ref()}.cloneNode( @{is_deep} );
        };

        cloned.into_reference().unwrap().downcast::< Self >().unwrap()
    }

    /// Checks whenever a given node is a descendant of this one or not.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/contains)
    fn contains< T: INode >( &self, node: &T ) -> bool {
        js!(
            return @{self.as_ref()}.contains( @{node.as_ref()} );
        ).try_into().unwrap()
    }

    /// Inserts the specified node before the reference node as a child of the current node.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore)
    fn insert_before< T: INode, U: INode >( &self, new_node: &T, reference_node: &U ) {
        js! { @(no_return)
            @{self.as_ref()}.insertBefore( @{new_node.as_ref()}, @{reference_node.as_ref()} );
        }
    }

    /// Replaces one hild node of the specified node with another.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/replaceChild)
    fn replace_child< T: INode, U: INode >( &self, new_child: &T, old_child: &U ) {
        js! { @(no_return)
            @{self.as_ref()}.replaceChild( @{new_child.as_ref()}, @{old_child.as_ref()} );
        }
    }

    /// Returns the parent of this node in the DOM tree.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode)
    fn parent_node( &self ) -> Option< Node > {
        js!(
            return @{self.as_ref()}.parentNode;
        ).try_into().ok()
    }

    /// Returns the node's first child in the tree, or `None` if the node is childless.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en/docs/Web/API/Node/firstChild)
    fn first_child( &self ) -> Option< Node > {
        js!(
            return @{self.as_ref()}.firstChild;
        ).try_into().ok()
    }

    /// A property which represents the "rendered" text content of a node and its descendants.
    /// It approximates the text the user would get if they highlighted the contents of the element
    /// with the cursor and then copied to the clipboard.
    ///
    /// This feature was originally introduced by Internet Explorer, and was formally specified in the HTML
    /// standard in 2016 after being adopted by all major browser vendors.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/innerText)
    fn inner_text( &self ) -> String {
        js!(
            return @{self.as_ref()}.innerText;
        ).try_into().unwrap()
    }

    /// A property which represents the text content of a node and its descendants.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
    fn text_content( &self ) -> Option< String > {
        js!(
            return @{self.as_ref()}.textContent;
        ).try_into().unwrap()
    }

    /// Sets the text content of this node; calling thil removes all
    /// of node's children and replaces them with a single text node
    /// with the given value.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
    fn set_text_content( &self, text: &str ) {
        js! { @(no_return)
            @{self.as_ref()}.textContent = @{text};
        }
    }

    /// Returns a live collection of child nodes of this node.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes)
    fn child_nodes( &self ) -> NodeList {
        unsafe {
            js!(
                return @{self.as_ref()}.childNodes;
            ).into_reference_unchecked().unwrap()
        }
    }
}

/// A reference to a JavaScript object which implements the [INode](trait.INode.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node)
pub struct Node( Reference );

impl IEventTarget for Node {}
impl INode for Node {}

reference_boilerplate! {
    Node,
    instanceof Node
    convertible to EventTarget
}<commit_msg>Add `as_node` to `INode`<commit_after>use std::fmt;
use std::error;
use std::mem;

use webcore::value::{Reference, FromReference};
use webcore::try_from::TryInto;
use webapi::event_target::{IEventTarget, EventTarget};
use webapi::node_list::NodeList;

/// A structure denoting that the specified DOM [Node](trait.INode.html) was not found.
#[derive(Debug)]
pub struct NotFoundError( String );
impl error::Error for NotFoundError {
    fn description( &self ) -> &str {
        self.0.as_str()
    }
}

impl fmt::Display for NotFoundError {
    fn fmt( &self, formatter: &mut fmt::Formatter ) -> fmt::Result {
        write!( formatter, "{}", self.0 )
    }
}

/// An enum which determines whenever the DOM [Node](trait.INode.html)'s children will also be cloned or not.
///
/// Mainly used in [INode::clone_node](trait.INode.html#method.clone_node).
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub enum CloneKind {
    /// Will not clone the children.
    Shallow,
    /// Will clone the children.
    Deep
}

/// `INode` is an interface from which a number of DOM API object types inherit.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node)
pub trait INode: IEventTarget + FromReference {
    /// Casts a reference to this object into a reference to a [Node](struct.Node.html).
    fn as_node( &self ) -> &Node {
        let reference: &Reference = self.as_ref();
        unsafe {
            mem::transmute( reference )
        }
    }

    /// Adds a node to the end of the list of children of a specified parent node.
    ///
    /// If the given child is a reference to an existing node in the document then
    /// it is moved from its current position to the new position (there is no requirement
    /// to remove the node from its parent node before appending it to some other node).
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/appendChild)
    fn append_child< T: INode >( &self, child: &T ) {
        js! { @(no_return)
            @{self.as_ref()}.appendChild( @{child.as_ref()} );
        }
    }

    /// Removes a child node from the DOM.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild)
    fn remove_child< T: INode >( &self, child: &T ) -> Result< (), NotFoundError > {
        // TODO: Return the removed node.
        let status = js! {
            try {
                @{self.as_ref()}.removeChild( @{child.as_ref()} );
                return true;
            } catch( exception ) {
                if( exception instanceof NotFoundError ) {
                    return false;
                } else {
                    throw exception;
                }
            }
        };

        if status == true {
            Ok(())
        } else {
            Err( NotFoundError( "The node to be removed is not a child of this node.".to_owned() ) )
        }
    }

    /// Returns a duplicate of the node on which this method was called.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode)
    fn clone_node( &self, kind: CloneKind ) -> Self {
        let is_deep = match kind {
            CloneKind::Deep => true,
            CloneKind::Shallow => false
        };

        let cloned = js! {
            return @{self.as_ref()}.cloneNode( @{is_deep} );
        };

        cloned.into_reference().unwrap().downcast::< Self >().unwrap()
    }

    /// Checks whenever a given node is a descendant of this one or not.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/contains)
    fn contains< T: INode >( &self, node: &T ) -> bool {
        js!(
            return @{self.as_ref()}.contains( @{node.as_ref()} );
        ).try_into().unwrap()
    }

    /// Inserts the specified node before the reference node as a child of the current node.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/insertBefore)
    fn insert_before< T: INode, U: INode >( &self, new_node: &T, reference_node: &U ) {
        js! { @(no_return)
            @{self.as_ref()}.insertBefore( @{new_node.as_ref()}, @{reference_node.as_ref()} );
        }
    }

    /// Replaces one hild node of the specified node with another.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/replaceChild)
    fn replace_child< T: INode, U: INode >( &self, new_child: &T, old_child: &U ) {
        js! { @(no_return)
            @{self.as_ref()}.replaceChild( @{new_child.as_ref()}, @{old_child.as_ref()} );
        }
    }

    /// Returns the parent of this node in the DOM tree.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/parentNode)
    fn parent_node( &self ) -> Option< Node > {
        js!(
            return @{self.as_ref()}.parentNode;
        ).try_into().ok()
    }

    /// Returns the node's first child in the tree, or `None` if the node is childless.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en/docs/Web/API/Node/firstChild)
    fn first_child( &self ) -> Option< Node > {
        js!(
            return @{self.as_ref()}.firstChild;
        ).try_into().ok()
    }

    /// A property which represents the "rendered" text content of a node and its descendants.
    /// It approximates the text the user would get if they highlighted the contents of the element
    /// with the cursor and then copied to the clipboard.
    ///
    /// This feature was originally introduced by Internet Explorer, and was formally specified in the HTML
    /// standard in 2016 after being adopted by all major browser vendors.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/innerText)
    fn inner_text( &self ) -> String {
        js!(
            return @{self.as_ref()}.innerText;
        ).try_into().unwrap()
    }

    /// A property which represents the text content of a node and its descendants.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
    fn text_content( &self ) -> Option< String > {
        js!(
            return @{self.as_ref()}.textContent;
        ).try_into().unwrap()
    }

    /// Sets the text content of this node; calling thil removes all
    /// of node's children and replaces them with a single text node
    /// with the given value.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent)
    fn set_text_content( &self, text: &str ) {
        js! { @(no_return)
            @{self.as_ref()}.textContent = @{text};
        }
    }

    /// Returns a live collection of child nodes of this node.
    ///
    /// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes)
    fn child_nodes( &self ) -> NodeList {
        unsafe {
            js!(
                return @{self.as_ref()}.childNodes;
            ).into_reference_unchecked().unwrap()
        }
    }
}

/// A reference to a JavaScript object which implements the [INode](trait.INode.html)
/// interface.
///
/// [(JavaScript docs)](https://developer.mozilla.org/en-US/docs/Web/API/Node)
pub struct Node( Reference );

impl IEventTarget for Node {}
impl INode for Node {}

reference_boilerplate! {
    Node,
    instanceof Node
    convertible to EventTarget
}
<|endoftext|>