<commit_before>#[macro_use] extern crate conrod;
extern crate find_folder;
extern crate glutin_window;
extern crate graphics;
extern crate rebind;
extern crate piston;
extern crate opengl_graphics;
extern crate viewport;

use conrod::{
    Background,
    Color,
    Colorable,
    Frameable,
    Labelable,
    Positionable,
    Sizeable,
    Theme,
    Toggle,
    Ui,
    Widget,
};
use conrod::color::{black, grayscale, green, red};
use glutin_window::GlutinWindow;
use graphics::*;
use opengl_graphics::{GlGraphics, OpenGL};
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event_loop::{EventMap, Events};
use piston::input::{
    Event,
    Input,
    Motion,
    RenderArgs,
    RenderEvent,
    UpdateArgs,
    UpdateEvent
};
use piston::input::keyboard::Key;
use piston::input::Button::Keyboard;
use piston::window::{Window, WindowSettings};
use rebind::{Action, InputTranslator, RebindBuilder, Translated};
use std::cell::RefCell;
use std::rc::Rc;

type RcWindow = Rc<RefCell<GlutinWindow>>;
type RcGraphics = Rc<RefCell<GlGraphics>>;
type RcUi = Rc<RefCell<Ui<GlyphCache<'static>>>>;

struct App {
    window: RcWindow,
    graphics: RcGraphics,
    ui: RcUi,
    translator: InputTranslator<CharacterAction>,
    character: Character,
    cursor: VirtualCursor,
    bg_color: Color
}

impl App {
    fn input(&mut self, input: &Input) {
        if let Some(t) = self.translator.translate(input) {
            match t {
                Translated::Press(action) => {
                    const CHARACTER_WALK_SPEED_INCREMENT: f64 = 400.0;
                    match action {
                        CharacterAction::Jump => {
                            println!("You jumped! Yay!");
                        },
                        CharacterAction::MoveLeft => {
                            if self.character.current_velocity[0] > (self.character.max_velocity[0] * -1.0) {
                                self.character.current_velocity[0] -= CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        },
                        CharacterAction::MoveRight => {
                            if self.character.current_velocity[0] < self.character.max_velocity[0] {
                                self.character.current_velocity[0] += CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        }
                    }
                },
                Translated::Release(_) => {
                    self.character.current_velocity = [0.0, 0.0];
                },
                Translated::Move(Motion::MouseCursor(x, y)) => {
                    self.cursor.position = [x, y];
                },
                _ => { }
            }
        }
    }

    fn update(&mut self, args: &UpdateArgs) {
        // we need to pass the window to update (and set the size here) because using
        // the update event from the window events queue is currently broken.
        self.translator.set_size(self.window.borrow().size());

        // update the character's velocity
        let ctl = self.character.topleft;
        let v = self.character.current_velocity;

        self.character.topleft = [ctl[0] + (v[0] * args.dt), ctl[1] + (v[1] * args.dt)];
    }

    fn render(&mut self, args: &RenderArgs) {
        let mut gl_graphics = self.graphics.borrow_mut();
        let ui = &mut *self.ui.borrow_mut();
        let mut rebind = self.translator.clone().into_rebind();

        // declare widget ids
        widget_ids! {
            X_INVERT_TOGGLE,
            Y_INVERT_TOGGLE
        }

        // draw the ui
        gl_graphics.draw(args.viewport(), |c, gl| {
            Background::new().color(self.bg_color).set(ui);

            Toggle::new(rebind.get_x_motion_inverted())
                .xy(-350.0, 260.0)
                .dimensions(80.0, 40.0)
                .color(grayscale(0.4))
                .frame(1.0)
                .label(&"Invert x")
                .label_color(self.bg_color.plain_contrast())
                .label_font_size(16)
                .react(|b| rebind.set_x_motion_inverted(b))
                .set(X_INVERT_TOGGLE, ui);

            Toggle::new(rebind.get_y_motion_inverted())
                .xy(-350.0, 200.0)
                .dimensions(80.0, 40.0)
                .color(grayscale(0.4))
                .frame(1.0)
                .label(&"Invert y")
                .label_color(self.bg_color.plain_contrast())
                .label_font_size(16)
                .react(|b| rebind.set_y_motion_inverted(b))
                .set(Y_INVERT_TOGGLE, ui);

            ui.draw(c, gl)
        });

        // draw the character
        {
            let square = rectangle::square(self.character.topleft[0],
                                           self.character.topleft[1],
                                           self.character.size);

            gl_graphics.draw(args.viewport(), |c, gl| rectangle(self.character.color.to_fsa(),
                                                                square,
                                                                c.transform,
                                                                gl));
        }

        // draw the cursor dot
        {
            let dot = ellipse::circle(self.cursor.position[0],
                                      self.cursor.position[1],
                                      self.cursor.size);
            gl_graphics.draw(args.viewport(), |c, gl| ellipse(self.cursor.color.to_fsa(),
                                                              dot,
                                                              c.transform,
                                                              gl));
        }

        self.translator = rebind.into();
    }
}

struct Character {
    color: Color,
    topleft: [f64; 2],
    current_velocity: [f64; 2],
    max_velocity: [f64; 2],
    size: f64
}

impl Character {
    fn new(col: Color, tl: [f64; 2], sz: f64) -> Self {
        Character {
            color: col,
            topleft: tl,
            current_velocity: [0.0, 0.0],
            max_velocity: [800.0, 0.0],
            size: sz
        }
    }
}

struct VirtualCursor {
    position: [f64; 2],
    color: Color,
    size: f64
}

impl VirtualCursor {
    fn new() -> Self {
        VirtualCursor {
            position: [0.0, 0.0],
            color: green(),
            size: 5.0
        }
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
enum CharacterAction {
    Jump,
    MoveLeft,
    MoveRight
}

impl Action for CharacterAction { }

fn main() {
    const OPENGL: OpenGL = OpenGL::V3_2;
    const WINDOW_SIZE: (u32, u32) = (800, 600);

    let window = WindowSettings::new("rebind-example", WINDOW_SIZE)
        .exit_on_esc(true)
        .fullscreen(false)
        .opengl(OPENGL)
        .vsync(true)
        .build()
        .ok()
        .expect("Could not create main window");

    let gl_graphics = GlGraphics::new(OPENGL);

    let translator = RebindBuilder::new(WINDOW_SIZE)
        .with_action_mapping(Keyboard(Key::Space), CharacterAction::Jump)
        .with_action_mapping(Keyboard(Key::Left),  CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::A),     CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::Right), CharacterAction::MoveRight)
        .with_action_mapping(Keyboard(Key::D),     CharacterAction::MoveRight)
        .build_translator();

    let character = {
        const INITIAL_CHARACTER_POS: [f64; 2] = [WINDOW_SIZE.0 as f64 / 20.0,
                                                 WINDOW_SIZE.1 as f64 * 0.85];
        Character::new(red(), INITIAL_CHARACTER_POS, 50.0)
    };

    let ui = {
        let glyph_cache = {
            let font_path = find_folder::Search::ParentsThenKids(3, 3)
                .for_folder("assets")
                .ok()
                .expect("Could not find assets folder")
                .join("fonts/NotoSans/NotoSans-Regular.ttf");

            GlyphCache::new(&font_path)
                .ok()
                .expect("Could not find font file within assets folder")
        };

        Ui::new(glyph_cache, Theme::default())
    };

    let mut app = App {
        window: Rc::new(RefCell::new(window)),
        graphics: Rc::new(RefCell::new(gl_graphics)),
        ui: Rc::new(RefCell::new(ui)),
        translator: translator,
        character: character,
        cursor: VirtualCursor::new(),
        bg_color: black()
    };

    for e in app.window.clone().events() {
        app.ui.borrow_mut().handle_event(&e);
        match e {
            Event::Input(i) => { app.input(&i); },
            Event::Update(u) => { app.update(&u); },
            Event::Render(r) => { app.render(&r); },
            _ => { }
        }
    }
}<commit_msg>Capitalise axis names in toggle labels<commit_after>#[macro_use] extern crate conrod;
extern crate find_folder;
extern crate glutin_window;
extern crate graphics;
extern crate rebind;
extern crate piston;
extern crate opengl_graphics;
extern crate viewport;

use conrod::{
    Background,
    Color,
    Colorable,
    Frameable,
    Labelable,
    Positionable,
    Sizeable,
    Theme,
    Toggle,
    Ui,
    Widget,
};
use conrod::color::{black, grayscale, green, red};
use glutin_window::GlutinWindow;
use graphics::*;
use opengl_graphics::{GlGraphics, OpenGL};
use opengl_graphics::glyph_cache::GlyphCache;
use piston::event_loop::{EventMap, Events};
use piston::input::{
    Event,
    Input,
    Motion,
    RenderArgs,
    RenderEvent,
    UpdateArgs,
    UpdateEvent
};
use piston::input::keyboard::Key;
use piston::input::Button::Keyboard;
use piston::window::{Window, WindowSettings};
use rebind::{Action, InputTranslator, RebindBuilder, Translated};
use std::cell::RefCell;
use std::rc::Rc;

type RcWindow = Rc<RefCell<GlutinWindow>>;
type RcGraphics = Rc<RefCell<GlGraphics>>;
type RcUi = Rc<RefCell<Ui<GlyphCache<'static>>>>;

struct App {
    window: RcWindow,
    graphics: RcGraphics,
    ui: RcUi,
    translator: InputTranslator<CharacterAction>,
    character: Character,
    cursor: VirtualCursor,
    bg_color: Color
}

impl App {
    fn input(&mut self, input: &Input) {
        if let Some(t) = self.translator.translate(input) {
            match t {
                Translated::Press(action) => {
                    const CHARACTER_WALK_SPEED_INCREMENT: f64 = 400.0;
                    match action {
                        CharacterAction::Jump => {
                            println!("You jumped! Yay!");
                        },
                        CharacterAction::MoveLeft => {
                            if self.character.current_velocity[0] > (self.character.max_velocity[0] * -1.0) {
                                self.character.current_velocity[0] -= CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        },
                        CharacterAction::MoveRight => {
                            if self.character.current_velocity[0] < self.character.max_velocity[0] {
                                self.character.current_velocity[0] += CHARACTER_WALK_SPEED_INCREMENT;
                            }
                        }
                    }
                },
                Translated::Release(_) => {
                    self.character.current_velocity = [0.0, 0.0];
                },
                Translated::Move(Motion::MouseCursor(x, y)) => {
                    self.cursor.position = [x, y];
                },
                _ => { }
            }
        }
    }

    fn update(&mut self, args: &UpdateArgs) {
        // we need to pass the window to update (and set the size here) because using
        // the update event from the window events queue is currently broken.
        self.translator.set_size(self.window.borrow().size());

        // update the character's velocity
        let ctl = self.character.topleft;
        let v = self.character.current_velocity;

        self.character.topleft = [ctl[0] + (v[0] * args.dt), ctl[1] + (v[1] * args.dt)];
    }

    fn render(&mut self, args: &RenderArgs) {
        let mut gl_graphics = self.graphics.borrow_mut();
        let ui = &mut *self.ui.borrow_mut();
        let mut rebind = self.translator.clone().into_rebind();

        // declare widget ids
        widget_ids! {
            X_INVERT_TOGGLE,
            Y_INVERT_TOGGLE
        }

        // draw the ui
        gl_graphics.draw(args.viewport(), |c, gl| {
            Background::new().color(self.bg_color).set(ui);

            Toggle::new(rebind.get_x_motion_inverted())
                .xy(-350.0, 260.0)
                .dimensions(80.0, 40.0)
                .color(grayscale(0.4))
                .frame(1.0)
                .label(&"Invert X")
                .label_color(self.bg_color.plain_contrast())
                .label_font_size(16)
                .react(|b| rebind.set_x_motion_inverted(b))
                .set(X_INVERT_TOGGLE, ui);

            Toggle::new(rebind.get_y_motion_inverted())
                .xy(-350.0, 200.0)
                .dimensions(80.0, 40.0)
                .color(grayscale(0.4))
                .frame(1.0)
                .label(&"Invert Y")
                .label_color(self.bg_color.plain_contrast())
                .label_font_size(16)
                .react(|b| rebind.set_y_motion_inverted(b))
                .set(Y_INVERT_TOGGLE, ui);

            ui.draw(c, gl)
        });

        // draw the character
        {
            let square = rectangle::square(self.character.topleft[0],
                                           self.character.topleft[1],
                                           self.character.size);

            gl_graphics.draw(args.viewport(), |c, gl| rectangle(self.character.color.to_fsa(),
                                                                square,
                                                                c.transform,
                                                                gl));
        }

        // draw the cursor dot
        {
            let dot = ellipse::circle(self.cursor.position[0],
                                      self.cursor.position[1],
                                      self.cursor.size);
            gl_graphics.draw(args.viewport(), |c, gl| ellipse(self.cursor.color.to_fsa(),
                                                              dot,
                                                              c.transform,
                                                              gl));
        }

        self.translator = rebind.into();
    }
}

struct Character {
    color: Color,
    topleft: [f64; 2],
    current_velocity: [f64; 2],
    max_velocity: [f64; 2],
    size: f64
}

impl Character {
    fn new(col: Color, tl: [f64; 2], sz: f64) -> Self {
        Character {
            color: col,
            topleft: tl,
            current_velocity: [0.0, 0.0],
            max_velocity: [800.0, 0.0],
            size: sz
        }
    }
}

struct VirtualCursor {
    position: [f64; 2],
    color: Color,
    size: f64
}

impl VirtualCursor {
    fn new() -> Self {
        VirtualCursor {
            position: [0.0, 0.0],
            color: green(),
            size: 5.0
        }
    }
}

#[derive(Copy, Clone, Eq, Hash, Ord, PartialEq, PartialOrd)]
enum CharacterAction {
    Jump,
    MoveLeft,
    MoveRight
}

impl Action for CharacterAction { }

fn main() {
    const OPENGL: OpenGL = OpenGL::V3_2;
    const WINDOW_SIZE: (u32, u32) = (800, 600);

    let window = WindowSettings::new("rebind-example", WINDOW_SIZE)
        .exit_on_esc(true)
        .fullscreen(false)
        .opengl(OPENGL)
        .vsync(true)
        .build()
        .ok()
        .expect("Could not create main window");

    let gl_graphics = GlGraphics::new(OPENGL);

    let translator = RebindBuilder::new(WINDOW_SIZE)
        .with_action_mapping(Keyboard(Key::Space), CharacterAction::Jump)
        .with_action_mapping(Keyboard(Key::Left),  CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::A),     CharacterAction::MoveLeft)
        .with_action_mapping(Keyboard(Key::Right), CharacterAction::MoveRight)
        .with_action_mapping(Keyboard(Key::D),     CharacterAction::MoveRight)
        .build_translator();

    let character = {
        const INITIAL_CHARACTER_POS: [f64; 2] = [WINDOW_SIZE.0 as f64 / 20.0,
                                                 WINDOW_SIZE.1 as f64 * 0.85];
        Character::new(red(), INITIAL_CHARACTER_POS, 50.0)
    };

    let ui = {
        let glyph_cache = {
            let font_path = find_folder::Search::ParentsThenKids(3, 3)
                .for_folder("assets")
                .ok()
                .expect("Could not find assets folder")
                .join("fonts/NotoSans/NotoSans-Regular.ttf");

            GlyphCache::new(&font_path)
                .ok()
                .expect("Could not find font file within assets folder")
        };

        Ui::new(glyph_cache, Theme::default())
    };

    let mut app = App {
        window: Rc::new(RefCell::new(window)),
        graphics: Rc::new(RefCell::new(gl_graphics)),
        ui: Rc::new(RefCell::new(ui)),
        translator: translator,
        character: character,
        cursor: VirtualCursor::new(),
        bg_color: black()
    };

    for e in app.window.clone().events() {
        app.ui.borrow_mut().handle_event(&e);
        match e {
            Event::Input(i) => { app.input(&i); },
            Event::Update(u) => { app.update(&u); },
            Event::Render(r) => { app.render(&r); },
            _ => { }
        }
    }
}<|endoftext|>


<commit_before>use postgres;
use uuid::Uuid;
use error::Error;
use chrono::{NaiveDateTime, Utc};
use super::{conn, Model};
use model::enclosure::Enclosure;
use scraper;
use Track;
use Playlist;
use Album;
use model::PaginatedCollection;
use serde_json::Value;
use feed_rs;

static PROPS: [&'static str; 20]  = ["id",
                                     "url",
                                     "title",
                                     "description",
                                     "visual_url",
                                     "locale",

                                     "summary",
                                     "content",
                                     "author",
                                     "crawled",
                                     "published",
                                     "updated",
                                     "fingerprint",
                                     "origin_id",
                                     "alternate",
                                     "keywords",
                                     "enclosure",

                                     "feed_id",

                                     "created_at",
                                     "updated_at"];

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Entry {
    pub id:          Uuid,
    pub url:         String,
    pub title:       Option<String>,
    pub description: Option<String>,
    pub visual_url:  Option<String>,
    pub locale:      Option<String>,
    pub summary:     Option<String>,
    pub content:     Option<String>,
    pub author:      Option<String>,
    pub crawled:     NaiveDateTime,
    pub published:   NaiveDateTime,
    pub updated:     Option<NaiveDateTime>,
    pub fingerprint: String,
    pub origin_id:   String,
    pub alternate:   Value,
    pub keywords:    Value,
    pub enclosure:   Value,
    pub feed_id:     Option<Uuid>,
    pub created_at:  NaiveDateTime,
    pub updated_at:  NaiveDateTime,
    pub tracks:      Vec<Track>,
    pub playlists:   Vec<Playlist>,
    pub albums:      Vec<Album>,
}

impl<'a> Model<'a> for Entry {
    fn table_name() -> String {
        "entries".to_string()
    }
    fn props_str(prefix: &str) -> String {
        PROPS
            .iter()
            .map(|&p| format!("{}{}", prefix, p))
            .collect::<Vec<String>>().join(",")
    }
    fn rows_to_items(rows: postgres::rows::Rows) -> Vec<Entry> {
        let mut entries = Vec::new();
        for row in rows.iter() {
            entries.push(Entry {
                id:          row.get(0),
                url:         row.get(1),
                title:       row.get(2),
                description: row.get(3),
                visual_url:  row.get(4),
                locale:      row.get(5),
                summary:     row.get(6),
                content:     row.get(7),
                author:      row.get(8),
                crawled:     row.get(9),
                published:   row.get(10),
                updated:     row.get(11),
                fingerprint: row.get(12),
                origin_id:   row.get(13),
                alternate:   row.get(14),
                keywords:    row.get(15),
                enclosure:   row.get(16),
                feed_id:     row.get(17),
                created_at:  row.get(18),
                updated_at:  row.get(19),
                tracks:      Track::find_by_entry_id(row.get(0)),
                playlists:   Playlist::find_by_entry_id(row.get(0)),
                albums:      Album::find_by_entry_id(row.get(0)),
            })
        }
        entries
    }
    fn create(&self) -> Result<Entry, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO entries (url, published) VALUES ($1, $2) RETURNING id"));
        let rows = try!(stmt.query(&[&self.url, &NaiveDateTime::from_timestamp(0, 0)]));
        let mut entry = self.clone();
        for row in rows.iter() {
            entry.id = row.get(0);
        }
        Ok(entry)
    }
    fn save(&mut self) -> Result<(), Error> {
        self.updated_at = Utc::now().naive_utc();
        let conn = try!(conn());
        let stmt = try!(conn.prepare("UPDATE entries SET
                                   url         = $2,
                                   title       = $3,
                                   description = $4,
                                   visual_url  = $5,
                                   locale      = $6,
                                   summary     = $7,
                                   content     = $8,
                                   author      = $9,
                                   crawled     = $10,
                                   published   = $11,
                                   updated     = $12,
                                   fingerprint = $13,
                                   origin_id   = $14,
                                   alternate   = $15,
                                   keywords    = $16,
                                   enclosure   = $17,
                                   feed_id     = $18,
                                   created_at  = $19,
                                   updated_at  = $20
                                 WHERE id = $1"));
        let result = stmt.query(&[&self.id,
                                  &self.url,
                                  &self.title,
                                  &self.description,
                                  &self.visual_url,
                                  &self.locale,
                                  &self.summary,
                                  &self.content,
                                  &self.author,
                                  &self.crawled,
                                  &self.published,
                                  &self.updated,
                                  &self.fingerprint,
                                  &self.origin_id,
                                  &self.alternate,
                                  &self.keywords,
                                  &self.enclosure,
                                  &self.feed_id,
                                  &self.created_at,
                                  &self.updated_at]);
        try!(result);
        Ok(())
    }
}

impl Entry {
    pub fn new(url: String) -> Result<Entry, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO entries (url) VALUES ($1) RETURNING id"));
        let rows = try!(stmt.query(&[&url]));
        for row in rows.iter() {
            let entry = Entry {
                id:          row.get(0),
                url:         url,
                title:       None,
                description: None,
                visual_url:  None,
                locale:      None,

                summary:     None,
                content:     None,
                author:      None,
                crawled:     NaiveDateTime::from_timestamp(0, 0),
                published:   NaiveDateTime::from_timestamp(0, 0), // exclude from api response
                updated:     None,
                fingerprint: "".to_string(),
                origin_id:   "".to_string(),
                alternate:   Value::Null,
                keywords:    Value::Null,
                enclosure:   Value::Null,
                feed_id:     None,

                created_at:  Utc::now().naive_utc(),
                updated_at:  Utc::now().naive_utc(),

                tracks:      Vec::new(),
                playlists:   Vec::new(),
                albums:      Vec::new(),
            };
            return Ok(entry);
        }
        Err(Error::Unexpected)
    }

    pub fn find_by_url(url: &str) -> Result<Entry, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare(
            &format!("SELECT {} FROM entries
                        WHERE url = $1", Self::props_str(""))));
        let rows = try!(stmt.query(&[&url]));
        let entries = Entry::rows_to_items(rows);
        if entries.len() > 0 {
            return Ok(entries[0].clone());
        }
        return Err(Error::NotFound)
    }

    pub fn find_or_create_by_url(url: String) -> Result<Entry, Error> {
        match Entry::find_by_url(&url) {
            Ok(entry) => Ok(entry),
            Err(Error::NotFound) => Entry::create_by_url(url),
            Err(e) => Err(e),
        }
    }

    pub fn find_by_feed_id(feed_id: Uuid, newer_than: Option<NaiveDateTime>, page: i64, per_page: i64) -> PaginatedCollection<Entry> {
        let conn = conn().unwrap();
        let stmt = conn.prepare(
            &format!("SELECT {} FROM entries
                        WHERE entries.feed_id = $1 AND entries.published >= $2
                        ORDER BY entries.published DESC
                        LIMIT $4 OFFSET $3",
                     Entry::props_str(""))).unwrap();
        let offset = page * per_page;
        let published = newer_than.unwrap_or(NaiveDateTime::from_timestamp(1000, 0)); // ignore 0 timestamp
        let rows   = stmt.query(&[&feed_id, &published, &offset, &per_page]).unwrap();
        let items  = Self::rows_to_items(rows);
        let mut total: i64 = 0;
        let sql = "SELECT COUNT(*) FROM entries WHERE entries.feed_id = $1";
        for row in conn.query(&sql, &[&feed_id]).unwrap().iter() {
            total = row.get(0);
        }
        PaginatedCollection {
            page:     page,
            per_page: per_page,
            total:    total,
            items:    items,
        }
    }

    pub fn create_by_url(url: String) -> Result<Entry, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO entries (url, published) VALUES ($1, $2) RETURNING id"));
        let rows = try!(stmt.query(&[&url, &NaiveDateTime::from_timestamp(0, 0)]));
        for row in rows.iter() {
            let entry = Entry {
                id:          row.get(0),
                url:         url,
                title:       None,
                description: None,
                visual_url:  None,
                locale:      None,

                summary:     None,
                content:     None,
                author:      None,
                crawled:     Utc::now().naive_utc(),
                published:   Utc::now().naive_utc(),
                updated:     None,
                fingerprint: "".to_string(),
                origin_id:   "".to_string(),
                alternate:   Value::Null,
                keywords:    Value::Null,
                enclosure:   Value::Null,
                feed_id:     None,

                created_at:  Utc::now().naive_utc(),
                updated_at:  Utc::now().naive_utc(),

                tracks:      Vec::new(),
                playlists:   Vec::new(),
                albums:      Vec::new(),
            };
            return Ok(entry);
        }
        Err(Error::Unexpected)
    }

    pub fn is_valid(&self) -> bool {
        self.published.timestamp() >= 1000
    }

    pub fn find_or_create_by_url_if_invalid(url: String) -> Result<Entry, Error> {
        match Entry::find_by_url(&url) {
            Ok(entry) => {
                if !entry.is_valid() {
                    Ok(entry)
                } else {
                    Err(Error::NotFound)
                }
            },
            Err(_) => {
                Entry::create_by_url(url)
            }
        }
    }

    pub fn update_with_feed_entry(&mut self, entry: &feed_rs::Entry) {
        self.title       = entry.title.clone();
        self.summary     = entry.summary.clone();
        self.content     = entry.content.clone();
        self.author      = entry.author.clone();
        self.crawled     = Utc::now().naive_utc();
        self.published   = entry.published;
        self.updated     = entry.updated;
        self.fingerprint = entry.fingerprint.clone();
        self.origin_id   = entry.id.clone();
        self.alternate   = json!(entry.alternate);
        self.keywords    = json!(entry.keywords);
        self.enclosure   = json!(entry.enclosure);

        self.updated_at  = Utc::now().naive_utc();
    }

    pub fn has_title(&self) -> bool {
        let title = &self.title.clone().unwrap_or("".to_string());
        !title.is_empty()
    }

    pub fn playlistify(&mut self) -> Result<(), Error> {
        let product = try!(scraper::extract(&self.url));
        match product.og_obj {
            Some(og_obj) => {
                if !self.has_title() {
                    self.title = Some(og_obj.title);
                }
                self.description = og_obj.description;
                self.locale      = og_obj.locale;
                self.visual_url  = og_obj.images.first().map(|i| i.url.clone());
            },
            None => (),
        }
        for t in product.tracks {
            let new_track = try!(Track::find_or_create(t.provider, t.identifier.to_string()));
            let mut track = t.clone();
            track.id      = new_track.id;
            try!(track.fetch_detail().save());
            match self.tracks.iter().find(|&t| t.id == track.id) {
                Some(_) => (),
                None    => try!(self.add_track(track.clone())),
            }
        }
        for p in product.playlists {
            let new_playlist = try!(Playlist::find_or_create(p.provider, p.identifier.to_string()));
            let mut playlist = p.clone();
            playlist.id      = new_playlist.id;
            try!(playlist.save());
            match self.playlists.iter().find(|&p| p.id == playlist.id) {
                Some(_) => (),
                None    => try!(self.add_playlist(playlist.clone())),
            }
        }
        for a in product.albums {
            let new_album = try!(Album::find_or_create(a.provider, a.identifier.to_string()));
            let mut album = a.clone();
            album.id      = new_album.id;
            try!(album.save());
            match self.albums.iter().find(|&a| a.id == album.id) {
                Some(_) => (),
                None    => try!(self.add_album(album.clone())),
            }
        }

        Ok(())
    }

    pub fn add_track(&mut self, track: Track) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO track_entries (track_id, entry_id)
                                 VALUES ($1, $2)"));
        try!(stmt.query(&[&track.id, &self.id]));
        self.tracks.push(track);
        Ok(())
    }

    pub fn add_playlist(&mut self, playlist: Playlist) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO playlist_entries (playlist_id, entry_id)
                                 VALUES ($1, $2)"));
        try!(stmt.query(&[&playlist.id, &self.id]));
        self.playlists.push(playlist);
        Ok(())
    }

    pub fn add_album(&mut self, album: Album) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO album_entries (album_id, entry_id)
                                 VALUES ($1, $2)"));
        try!(stmt.query(&[&album.id, &self.id]));
        self.albums.push(album);
        Ok(())
    }
}
<commit_msg>Trim Entry.title and description and content<commit_after>use postgres;
use uuid::Uuid;
use error::Error;
use chrono::{NaiveDateTime, Utc};
use super::{conn, Model};
use model::enclosure::Enclosure;
use scraper;
use Track;
use Playlist;
use Album;
use model::PaginatedCollection;
use serde_json::Value;
use feed_rs;

static PROPS: [&'static str; 20]  = ["id",
                                     "url",
                                     "title",
                                     "description",
                                     "visual_url",
                                     "locale",

                                     "summary",
                                     "content",
                                     "author",
                                     "crawled",
                                     "published",
                                     "updated",
                                     "fingerprint",
                                     "origin_id",
                                     "alternate",
                                     "keywords",
                                     "enclosure",

                                     "feed_id",

                                     "created_at",
                                     "updated_at"];

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Entry {
    pub id:          Uuid,
    pub url:         String,
    pub title:       Option<String>,
    pub description: Option<String>,
    pub visual_url:  Option<String>,
    pub locale:      Option<String>,
    pub summary:     Option<String>,
    pub content:     Option<String>,
    pub author:      Option<String>,
    pub crawled:     NaiveDateTime,
    pub published:   NaiveDateTime,
    pub updated:     Option<NaiveDateTime>,
    pub fingerprint: String,
    pub origin_id:   String,
    pub alternate:   Value,
    pub keywords:    Value,
    pub enclosure:   Value,
    pub feed_id:     Option<Uuid>,
    pub created_at:  NaiveDateTime,
    pub updated_at:  NaiveDateTime,
    pub tracks:      Vec<Track>,
    pub playlists:   Vec<Playlist>,
    pub albums:      Vec<Album>,
}

impl<'a> Model<'a> for Entry {
    fn table_name() -> String {
        "entries".to_string()
    }
    fn props_str(prefix: &str) -> String {
        PROPS
            .iter()
            .map(|&p| format!("{}{}", prefix, p))
            .collect::<Vec<String>>().join(",")
    }
    fn rows_to_items(rows: postgres::rows::Rows) -> Vec<Entry> {
        let mut entries = Vec::new();
        for row in rows.iter() {
            entries.push(Entry {
                id:          row.get(0),
                url:         row.get(1),
                title:       row.get(2),
                description: row.get(3),
                visual_url:  row.get(4),
                locale:      row.get(5),
                summary:     row.get(6),
                content:     row.get(7),
                author:      row.get(8),
                crawled:     row.get(9),
                published:   row.get(10),
                updated:     row.get(11),
                fingerprint: row.get(12),
                origin_id:   row.get(13),
                alternate:   row.get(14),
                keywords:    row.get(15),
                enclosure:   row.get(16),
                feed_id:     row.get(17),
                created_at:  row.get(18),
                updated_at:  row.get(19),
                tracks:      Track::find_by_entry_id(row.get(0)),
                playlists:   Playlist::find_by_entry_id(row.get(0)),
                albums:      Album::find_by_entry_id(row.get(0)),
            })
        }
        entries
    }
    fn create(&self) -> Result<Entry, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO entries (url, published) VALUES ($1, $2) RETURNING id"));
        let rows = try!(stmt.query(&[&self.url, &NaiveDateTime::from_timestamp(0, 0)]));
        let mut entry = self.clone();
        for row in rows.iter() {
            entry.id = row.get(0);
        }
        Ok(entry)
    }
    fn save(&mut self) -> Result<(), Error> {
        self.updated_at = Utc::now().naive_utc();
        let conn = try!(conn());
        let stmt = try!(conn.prepare("UPDATE entries SET
                                   url         = $2,
                                   title       = $3,
                                   description = $4,
                                   visual_url  = $5,
                                   locale      = $6,
                                   summary     = $7,
                                   content     = $8,
                                   author      = $9,
                                   crawled     = $10,
                                   published   = $11,
                                   updated     = $12,
                                   fingerprint = $13,
                                   origin_id   = $14,
                                   alternate   = $15,
                                   keywords    = $16,
                                   enclosure   = $17,
                                   feed_id     = $18,
                                   created_at  = $19,
                                   updated_at  = $20
                                 WHERE id = $1"));
        let result = stmt.query(&[&self.id,
                                  &self.url,
                                  &self.title,
                                  &self.description,
                                  &self.visual_url,
                                  &self.locale,
                                  &self.summary,
                                  &self.content,
                                  &self.author,
                                  &self.crawled,
                                  &self.published,
                                  &self.updated,
                                  &self.fingerprint,
                                  &self.origin_id,
                                  &self.alternate,
                                  &self.keywords,
                                  &self.enclosure,
                                  &self.feed_id,
                                  &self.created_at,
                                  &self.updated_at]);
        try!(result);
        Ok(())
    }
}

impl Entry {
    pub fn new(url: String) -> Result<Entry, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO entries (url) VALUES ($1) RETURNING id"));
        let rows = try!(stmt.query(&[&url]));
        for row in rows.iter() {
            let entry = Entry {
                id:          row.get(0),
                url:         url,
                title:       None,
                description: None,
                visual_url:  None,
                locale:      None,

                summary:     None,
                content:     None,
                author:      None,
                crawled:     NaiveDateTime::from_timestamp(0, 0),
                published:   NaiveDateTime::from_timestamp(0, 0), // exclude from api response
                updated:     None,
                fingerprint: "".to_string(),
                origin_id:   "".to_string(),
                alternate:   Value::Null,
                keywords:    Value::Null,
                enclosure:   Value::Null,
                feed_id:     None,

                created_at:  Utc::now().naive_utc(),
                updated_at:  Utc::now().naive_utc(),

                tracks:      Vec::new(),
                playlists:   Vec::new(),
                albums:      Vec::new(),
            };
            return Ok(entry);
        }
        Err(Error::Unexpected)
    }

    pub fn find_by_url(url: &str) -> Result<Entry, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare(
            &format!("SELECT {} FROM entries
                        WHERE url = $1", Self::props_str(""))));
        let rows = try!(stmt.query(&[&url]));
        let entries = Entry::rows_to_items(rows);
        if entries.len() > 0 {
            return Ok(entries[0].clone());
        }
        return Err(Error::NotFound)
    }

    pub fn find_or_create_by_url(url: String) -> Result<Entry, Error> {
        match Entry::find_by_url(&url) {
            Ok(entry) => Ok(entry),
            Err(Error::NotFound) => Entry::create_by_url(url),
            Err(e) => Err(e),
        }
    }

    pub fn find_by_feed_id(feed_id: Uuid, newer_than: Option<NaiveDateTime>, page: i64, per_page: i64) -> PaginatedCollection<Entry> {
        let conn = conn().unwrap();
        let stmt = conn.prepare(
            &format!("SELECT {} FROM entries
                        WHERE entries.feed_id = $1 AND entries.published >= $2
                        ORDER BY entries.published DESC
                        LIMIT $4 OFFSET $3",
                     Entry::props_str(""))).unwrap();
        let offset = page * per_page;
        let published = newer_than.unwrap_or(NaiveDateTime::from_timestamp(1000, 0)); // ignore 0 timestamp
        let rows   = stmt.query(&[&feed_id, &published, &offset, &per_page]).unwrap();
        let items  = Self::rows_to_items(rows);
        let mut total: i64 = 0;
        let sql = "SELECT COUNT(*) FROM entries WHERE entries.feed_id = $1";
        for row in conn.query(&sql, &[&feed_id]).unwrap().iter() {
            total = row.get(0);
        }
        PaginatedCollection {
            page:     page,
            per_page: per_page,
            total:    total,
            items:    items,
        }
    }

    pub fn create_by_url(url: String) -> Result<Entry, Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO entries (url, published) VALUES ($1, $2) RETURNING id"));
        let rows = try!(stmt.query(&[&url, &NaiveDateTime::from_timestamp(0, 0)]));
        for row in rows.iter() {
            let entry = Entry {
                id:          row.get(0),
                url:         url,
                title:       None,
                description: None,
                visual_url:  None,
                locale:      None,

                summary:     None,
                content:     None,
                author:      None,
                crawled:     Utc::now().naive_utc(),
                published:   Utc::now().naive_utc(),
                updated:     None,
                fingerprint: "".to_string(),
                origin_id:   "".to_string(),
                alternate:   Value::Null,
                keywords:    Value::Null,
                enclosure:   Value::Null,
                feed_id:     None,

                created_at:  Utc::now().naive_utc(),
                updated_at:  Utc::now().naive_utc(),

                tracks:      Vec::new(),
                playlists:   Vec::new(),
                albums:      Vec::new(),
            };
            return Ok(entry);
        }
        Err(Error::Unexpected)
    }

    pub fn is_valid(&self) -> bool {
        self.published.timestamp() >= 1000
    }

    pub fn find_or_create_by_url_if_invalid(url: String) -> Result<Entry, Error> {
        match Entry::find_by_url(&url) {
            Ok(entry) => {
                if !entry.is_valid() {
                    Ok(entry)
                } else {
                    Err(Error::NotFound)
                }
            },
            Err(_) => {
                Entry::create_by_url(url)
            }
        }
    }

    pub fn update_with_feed_entry(&mut self, entry: &feed_rs::Entry) {
        self.title       = entry.title.clone().map(|s| s.trim().to_string());
        self.summary     = entry.summary.clone().map(|s| s.trim().to_string());
        self.content     = entry.content.clone().map(|s| s.trim().to_string());
        self.author      = entry.author.clone();
        self.crawled     = Utc::now().naive_utc();
        self.published   = entry.published;
        self.updated     = entry.updated;
        self.fingerprint = entry.fingerprint.clone();
        self.origin_id   = entry.id.clone();
        self.alternate   = json!(entry.alternate);
        self.keywords    = json!(entry.keywords);
        self.enclosure   = json!(entry.enclosure);

        self.updated_at  = Utc::now().naive_utc();
    }

    pub fn has_title(&self) -> bool {
        let title = &self.title.clone().unwrap_or("".to_string());
        !title.is_empty()
    }

    pub fn playlistify(&mut self) -> Result<(), Error> {
        let product = try!(scraper::extract(&self.url));
        match product.og_obj {
            Some(og_obj) => {
                if !self.has_title() {
                    self.title = Some(og_obj.title);
                }
                self.description = og_obj.description;
                self.locale      = og_obj.locale;
                self.visual_url  = og_obj.images.first().map(|i| i.url.clone());
            },
            None => (),
        }
        for t in product.tracks {
            let new_track = try!(Track::find_or_create(t.provider, t.identifier.to_string()));
            let mut track = t.clone();
            track.id      = new_track.id;
            try!(track.fetch_detail().save());
            match self.tracks.iter().find(|&t| t.id == track.id) {
                Some(_) => (),
                None    => try!(self.add_track(track.clone())),
            }
        }
        for p in product.playlists {
            let new_playlist = try!(Playlist::find_or_create(p.provider, p.identifier.to_string()));
            let mut playlist = p.clone();
            playlist.id      = new_playlist.id;
            try!(playlist.save());
            match self.playlists.iter().find(|&p| p.id == playlist.id) {
                Some(_) => (),
                None    => try!(self.add_playlist(playlist.clone())),
            }
        }
        for a in product.albums {
            let new_album = try!(Album::find_or_create(a.provider, a.identifier.to_string()));
            let mut album = a.clone();
            album.id      = new_album.id;
            try!(album.save());
            match self.albums.iter().find(|&a| a.id == album.id) {
                Some(_) => (),
                None    => try!(self.add_album(album.clone())),
            }
        }

        Ok(())
    }

    pub fn add_track(&mut self, track: Track) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO track_entries (track_id, entry_id)
                                 VALUES ($1, $2)"));
        try!(stmt.query(&[&track.id, &self.id]));
        self.tracks.push(track);
        Ok(())
    }

    pub fn add_playlist(&mut self, playlist: Playlist) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO playlist_entries (playlist_id, entry_id)
                                 VALUES ($1, $2)"));
        try!(stmt.query(&[&playlist.id, &self.id]));
        self.playlists.push(playlist);
        Ok(())
    }

    pub fn add_album(&mut self, album: Album) -> Result<(), Error> {
        let conn = try!(conn());
        let stmt = try!(conn.prepare("INSERT INTO album_entries (album_id, entry_id)
                                 VALUES ($1, $2)"));
        try!(stmt.query(&[&album.id, &self.id]));
        self.albums.push(album);
        Ok(())
    }
}
<|endoftext|>


<commit_before>use std::mem;

use grammar::*;
use grammar::ClassMember::*;
use grammar::OperatorType::*;

pub struct Settings {
    pub transform_block_scope: bool,
    pub transform_arrow: bool,
    pub transform_object: bool,
    pub transform_exponentation: bool,
    pub transform_class_properties: bool,
}

trait Take {
    fn take(&mut self) -> Self;
}

impl<T> Take for Vec<T> {
    #[inline]
    fn take(&mut self) -> Self {
        mem::replace(self, Vec::new())
    }
}

impl Take for Expression {
    #[inline]
    fn take(&mut self) -> Self {
        mem::replace(self, Expression::This)
    }
}

#[inline]
fn bind_this(function: Expression) -> Expression {
    Expression::call(Expression::member(function, "bind"), vec![Expression::This])
}

impl Settings {
    pub fn target_es5() -> Settings {
        let mut settings = Settings::target_es2015();

        settings.transform_block_scope = true;
        settings.transform_arrow = true;
        settings.transform_object = true;

        settings
    }

    pub fn target_es2015() -> Settings {
        let mut settings = Settings::no_transform();

        settings.transform_exponentation = true;
        settings.transform_class_properties = true;

        settings
    }

    pub fn no_transform() -> Settings {
        Settings {
            transform_block_scope: false,
            transform_arrow: false,
            transform_object: false,
            transform_exponentation: false,
            transform_class_properties: false,
        }
    }
}

/// The `Transformable` trait provides an interface for instances of grammar
/// to alter the AST.
trait Transformable {
    fn transform(&mut self, _: &Settings) {}

    #[inline]
    fn contains_this(&self) -> bool {
        false
    }
}

impl Transformable for Parameter {}

impl Transformable for Expression {
    fn transform(&mut self, settings: &Settings) {
        *self = match *self {
            Expression::ArrowFunction {
                ref mut params,
                ref mut body,
            } => {
                params.transform(settings);
                body.transform(settings);

                // transformation flag check
                if !settings.transform_arrow {
                    return;
                }

                let body = match **body {
                    Statement::Block { ref mut body }   => body.split_off(0),
                    Statement::Expression { ref mut value } => vec![
                        Statement::Return {
                            value: Some(value.take())
                        }
                    ],
                    ref statement => {
                        panic!("Invalid arrow function body {:#?}", statement);
                    }
                };

                let bind = body.contains_this();

                let function = Expression::Function {
                    name: None,
                    params: params.split_off(0),
                    body: body,
                };

                if bind {
                    bind_this(function)
                } else {
                    function
                }
            },

            Expression::Array(ref mut items) => {
                items.transform(settings);
                return;
            },

            Expression::Object(ref mut members) => {
                members.transform(settings);

                // transformation flag check
                if !settings.transform_object {
                    return;
                }

                let mut computed = Vec::new();
                let indexes = 0 .. members.len();

                for index in indexes.rev() {
                    match members[index] {
                        ObjectMember::Computed { .. } => {
                            let member = members.remove(index);
                            computed.push(member);
                        },
                        _ => {}
                    }
                }

                if computed.is_empty() {
                    return;
                }

                let literal = members.take();

                let mut body = Vec::with_capacity(computed.len() + 2);

                body.push(Statement::VariableDeclaration {
                    kind: VariableDeclarationKind::Var,
                    declarators: vec![
                        VariableDeclarator {
                            name: OwnedSlice::from_static("___"),
                            value: Some(Expression::Object(literal)),
                        }
                    ]
                });

                for member in computed.drain(..) {
                    if let ObjectMember::Computed { key, value } = member {
                        body.push(Statement::Expression {
                            value: Expression::Binary {
                                left: Box::new(Expression::ComputedMember {
                                    object: Box::new(Expression::ident("___")),
                                    property: Box::new(key),
                                }),
                                operator: Assign,
                                right: Box::new(value),
                            }
                        });
                    }
                }

                body.push(Statement::Return {
                    value: Some(Expression::ident("___"))
                });

                Expression::call(Expression::Function {
                    name: None,
                    params: Vec::new(),
                    body: body,
                }, Vec::new())
            },

            Expression::Call {
                ref mut callee,
                ref mut arguments,
            } => {
                callee.transform(settings);
                arguments.transform(settings);
                return;
            },

            Expression::Binary {
                ref mut left,
                ref mut operator,
                ref mut right,
            } => {
                left.transform(settings);
                right.transform(settings);

                if !settings.transform_exponentation {
                    return;
                }

                match *operator {
                    Exponent => Expression::call(
                        Expression::member(Expression::ident("Math"), "pow"),
                        vec![left.take(), right.take()]
                    ),

                    ExponentAssign => {
                        *operator = Assign;
                        *right = Box::new(Expression::call(
                            Expression::member(Expression::ident("Math"), "pow"),
                            vec![left.take(), right.take()]
                        ));
                        return;
                    },

                    _ => return,
                }
            }

            _ => return,
        }
    }

    fn contains_this(&self) -> bool {
        match *self {
            Expression::This => true,

            Expression::Array(ref items) => items.contains_this(),

            Expression::Object(ref members) => members.contains_this(),

            Expression::Member {
                ref object,
                ..
            } => object.contains_this(),

            Expression::Call {
                ref callee,
                ref arguments,
            } => callee.contains_this() || arguments.contains_this(),

            Expression::Binary {
                ref left,
                ref right,
                ..
            } => left.contains_this() || right.contains_this(),

            _ => false,
        }
    }
}

impl Transformable for ObjectMember {
    fn transform(&mut self, settings: &Settings) {
        *self = match *self {

            ObjectMember::Shorthand {
                ref mut key,
            } => {
                // transformation flag check
                if !settings.transform_object {
                    return;
                }

                ObjectMember::Literal {
                    key: *key,
                    value: Expression::Identifier(*key),
                }
            },

            ObjectMember::Literal {
                ref mut value,
                ..
            } => {
                value.transform(settings);
                return;
            },

            ObjectMember::Computed {
                ref mut key,
                ref mut value,
            } => {
                key.transform(settings);
                value.transform(settings);
                return;
            },

            ObjectMember::Method {
                ref name,
                ref mut params,
                ref mut body,
            } => {
                body.transform(settings);
                params.transform(settings);

                // transformation flag check
                if !settings.transform_object {
                    return;
                }

                ObjectMember::Literal {
                    key: *name,
                    value: Expression::Function {
                        name: Some(*name),
                        params: params.take(),
                        body: body.take(),
                    }
                }
            },

            ObjectMember::ComputedMethod {
                ref mut name,
                ref mut params,
                ref mut body,
            } => {
                body.transform(settings);
                params.transform(settings);

                // transformation flag check
                if !settings.transform_object {
                    return;
                }

                ObjectMember::Computed {
                    key: name.take(),
                    value: Expression::Function {
                        name: None,
                        params: params.take(),
                        body: body.take(),
                    }
                }
            },
        }
    }

    fn contains_this(&self) -> bool {
        match *self {
            ObjectMember::Literal {
                ref value,
                ..
            } => value.contains_this(),

            ObjectMember::Computed {
                ref key,
                ref value,
            } => key.contains_this() || value.contains_this(),

            _ => false,
        }
    }
}

impl Transformable for ClassMember {
    fn transform(&mut self, settings: &Settings) {
        match *self {
            Constructor {
                ref mut params,
                ref mut body,
            } => {
                params.transform(settings);
                body.transform(settings);
            },

            Method {
                ref mut params,
                ref mut body,
                ..
            } => {
                params.transform(settings);
                body.transform(settings);
            },

            Property {
                ref mut value,
                ..
            } => {
                value.transform(settings);
            }
        }
    }
}

impl Transformable for VariableDeclarator {
    fn transform(&mut self, settings: &Settings) {
        match self.value {
            Some(ref mut expression) => expression.transform(settings),
            _                        => {},
        }
    }

    fn contains_this(&self) -> bool {
        match self.value {
            Some(ref expression) => expression.contains_this(),
            _                    => false,
        }
    }
}

fn add_props_to_body(body: &mut Vec<Statement>, props: &mut Vec<ClassMember>) {
    // for prop in props {
    //     match prop {
    //         ClassMember::Property {
    //             ref is_static,
    //             ref name,
    //         } => {

    //         }
    //     }
    // }
}

impl Transformable for Statement {
    fn transform(&mut self, settings: &Settings) {
        *self = match *self {
            Statement::Block {
                ref mut body,
            } => {
                body.transform(settings);
                return;
            },

            Statement::Labeled {
                ref mut body,
                ..
            } => {
                body.transform(settings);
                return;
            },

            Statement::VariableDeclaration {
                ref mut kind,
                ref mut declarators,
            } => {
                declarators.transform(settings);

                // transformation flag check
                if !settings.transform_block_scope {
                    return;
                }

                *kind = VariableDeclarationKind::Var;
                return;
            },

            Statement::Expression {
                ref mut value,
            } => {
                value.transform(settings);
                return;
            },

            Statement::If {
                ref mut test,
                ref mut consequent,
                ref mut alternate,
                ..
            } => {
                test.transform(settings);
                consequent.transform(settings);
                if let Some(ref mut alternate) = *alternate {
                    alternate.transform(settings);
                }
                return;
            },

            Statement::Class {
                ref mut body,
                ..
            } => {
                body.transform(settings);

                if !settings.transform_class_properties {
                    return;
                }

                let (mut props, mut methods): (Vec<ClassMember>, Vec<ClassMember>)
                = body.drain(..).partition(|member| {
                    match *member {
                        ClassMember::Property { .. } => true,
                        _                            => false,
                    }
                });

                if !props.is_empty() {
                    // copy the props into the class constructor
                    for method in methods.iter_mut() {
                        match *method {
                            ClassMember::Constructor {
                                ref mut body,
                                ..
                            } => {
                                add_props_to_body(body, &mut props);
                                break
                            }
                            _ => continue
                        }
                    }
                }

                *body = methods;

                return;
            }

            _ => return,
        }
    }

    fn contains_this(&self) -> bool {
        match *self {
            Statement::VariableDeclaration {
                ref declarators,
                ..
            } => declarators.contains_this(),

            Statement::Expression {
                ref value,
            } => value.contains_this(),

            Statement::Return {
                value: Some(ref expression)
            } => expression.contains_this(),

            _ => false,
        }
    }
}

impl<T: Transformable> Transformable for Vec<T> {
    #[inline]
    fn transform(&mut self, settings: &Settings) {
        for item in self.iter_mut() {
            item.transform(settings);
        }
    }

    #[inline]
    fn contains_this(&self) -> bool {
        for item in self {
            if item.contains_this() {
                return true;
            }
        }
        return false;
    }
}

pub fn transform(program: &mut Program, settings: Settings) {
    program.body.transform(&settings);
}
<commit_msg>Transform class props<commit_after>use std::mem;

use grammar::*;
use grammar::ClassMember::*;
use grammar::OperatorType::*;

pub struct Settings {
    pub transform_block_scope: bool,
    pub transform_arrow: bool,
    pub transform_object: bool,
    pub transform_exponentation: bool,
    pub transform_class_properties: bool,
}

trait Take {
    fn take(&mut self) -> Self;
}

impl<T> Take for Vec<T> {
    #[inline]
    fn take(&mut self) -> Self {
        mem::replace(self, Vec::new())
    }
}

impl Take for Expression {
    #[inline]
    fn take(&mut self) -> Self {
        mem::replace(self, Expression::This)
    }
}

#[inline]
fn bind_this(function: Expression) -> Expression {
    Expression::call(Expression::member(function, "bind"), vec![Expression::This])
}

impl Settings {
    pub fn target_es5() -> Settings {
        let mut settings = Settings::target_es2015();

        settings.transform_block_scope = true;
        settings.transform_arrow = true;
        settings.transform_object = true;

        settings
    }

    pub fn target_es2015() -> Settings {
        let mut settings = Settings::no_transform();

        settings.transform_exponentation = true;
        settings.transform_class_properties = true;

        settings
    }

    pub fn no_transform() -> Settings {
        Settings {
            transform_block_scope: false,
            transform_arrow: false,
            transform_object: false,
            transform_exponentation: false,
            transform_class_properties: false,
        }
    }
}

/// The `Transformable` trait provides an interface for instances of grammar
/// to alter the AST.
trait Transformable {
    fn transform(&mut self, _: &Settings) {}

    #[inline]
    fn contains_this(&self) -> bool {
        false
    }
}

impl Transformable for Parameter {}

impl Transformable for Expression {
    fn transform(&mut self, settings: &Settings) {
        *self = match *self {
            Expression::ArrowFunction {
                ref mut params,
                ref mut body,
            } => {
                params.transform(settings);
                body.transform(settings);

                // transformation flag check
                if !settings.transform_arrow {
                    return;
                }

                let body = match **body {
                    Statement::Block { ref mut body }   => body.split_off(0),
                    Statement::Expression { ref mut value } => vec![
                        Statement::Return {
                            value: Some(value.take())
                        }
                    ],
                    ref statement => {
                        panic!("Invalid arrow function body {:#?}", statement);
                    }
                };

                let bind = body.contains_this();

                let function = Expression::Function {
                    name: None,
                    params: params.split_off(0),
                    body: body,
                };

                if bind {
                    bind_this(function)
                } else {
                    function
                }
            },

            Expression::Array(ref mut items) => {
                items.transform(settings);
                return;
            },

            Expression::Object(ref mut members) => {
                members.transform(settings);

                // transformation flag check
                if !settings.transform_object {
                    return;
                }

                let mut computed = partition_vec(members, |member| {
                    match member {
                        &ObjectMember::Computed { .. } => false,
                        _                              => true,
                    }
                });

                if computed.is_empty() {
                    return;
                }

                let literal = members.take();

                let mut body = Vec::with_capacity(computed.len() + 2);

                body.push(Statement::VariableDeclaration {
                    kind: VariableDeclarationKind::Var,
                    declarators: vec![
                        VariableDeclarator {
                            name: OwnedSlice::from_static("___"),
                            value: Some(Expression::Object(literal)),
                        }
                    ]
                });

                for member in computed.drain(..) {
                    if let ObjectMember::Computed { key, value } = member {
                        body.push(Statement::Expression {
                            value: Expression::Binary {
                                left: Box::new(Expression::ComputedMember {
                                    object: Box::new(Expression::ident("___")),
                                    property: Box::new(key),
                                }),
                                operator: Assign,
                                right: Box::new(value),
                            }
                        });
                    }
                }

                body.push(Statement::Return {
                    value: Some(Expression::ident("___"))
                });

                Expression::call(Expression::Function {
                    name: None,
                    params: Vec::new(),
                    body: body,
                }, Vec::new())
            },

            Expression::Call {
                ref mut callee,
                ref mut arguments,
            } => {
                callee.transform(settings);
                arguments.transform(settings);
                return;
            },

            Expression::Binary {
                ref mut left,
                ref mut operator,
                ref mut right,
            } => {
                left.transform(settings);
                right.transform(settings);

                if !settings.transform_exponentation {
                    return;
                }

                match *operator {
                    Exponent => Expression::call(
                        Expression::member(Expression::ident("Math"), "pow"),
                        vec![left.take(), right.take()]
                    ),

                    ExponentAssign => {
                        *operator = Assign;
                        *right = Box::new(Expression::call(
                            Expression::member(Expression::ident("Math"), "pow"),
                            vec![left.take(), right.take()]
                        ));
                        return;
                    },

                    _ => return,
                }
            }

            _ => return,
        }
    }

    fn contains_this(&self) -> bool {
        match *self {
            Expression::This => true,

            Expression::Array(ref items) => items.contains_this(),

            Expression::Object(ref members) => members.contains_this(),

            Expression::Member {
                ref object,
                ..
            } => object.contains_this(),

            Expression::Call {
                ref callee,
                ref arguments,
            } => callee.contains_this() || arguments.contains_this(),

            Expression::Binary {
                ref left,
                ref right,
                ..
            } => left.contains_this() || right.contains_this(),

            _ => false,
        }
    }
}

impl Transformable for ObjectMember {
    fn transform(&mut self, settings: &Settings) {
        *self = match *self {

            ObjectMember::Shorthand {
                ref mut key,
            } => {
                // transformation flag check
                if !settings.transform_object {
                    return;
                }

                ObjectMember::Literal {
                    key: *key,
                    value: Expression::Identifier(*key),
                }
            },

            ObjectMember::Literal {
                ref mut value,
                ..
            } => {
                value.transform(settings);
                return;
            },

            ObjectMember::Computed {
                ref mut key,
                ref mut value,
            } => {
                key.transform(settings);
                value.transform(settings);
                return;
            },

            ObjectMember::Method {
                ref name,
                ref mut params,
                ref mut body,
            } => {
                body.transform(settings);
                params.transform(settings);

                // transformation flag check
                if !settings.transform_object {
                    return;
                }

                ObjectMember::Literal {
                    key: *name,
                    value: Expression::Function {
                        name: Some(*name),
                        params: params.take(),
                        body: body.take(),
                    }
                }
            },

            ObjectMember::ComputedMethod {
                ref mut name,
                ref mut params,
                ref mut body,
            } => {
                body.transform(settings);
                params.transform(settings);

                // transformation flag check
                if !settings.transform_object {
                    return;
                }

                ObjectMember::Computed {
                    key: name.take(),
                    value: Expression::Function {
                        name: None,
                        params: params.take(),
                        body: body.take(),
                    }
                }
            },
        }
    }

    fn contains_this(&self) -> bool {
        match *self {
            ObjectMember::Literal {
                ref value,
                ..
            } => value.contains_this(),

            ObjectMember::Computed {
                ref key,
                ref value,
            } => key.contains_this() || value.contains_this(),

            _ => false,
        }
    }
}

impl Transformable for ClassMember {
    fn transform(&mut self, settings: &Settings) {
        match *self {
            Constructor {
                ref mut params,
                ref mut body,
            } => {
                params.transform(settings);
                body.transform(settings);
            },

            Method {
                ref mut params,
                ref mut body,
                ..
            } => {
                params.transform(settings);
                body.transform(settings);
            },

            Property {
                ref mut value,
                ..
            } => {
                value.transform(settings);
            }
        }
    }
}

impl Transformable for VariableDeclarator {
    fn transform(&mut self, settings: &Settings) {
        match self.value {
            Some(ref mut expression) => expression.transform(settings),
            _                        => {},
        }
    }

    fn contains_this(&self) -> bool {
        match self.value {
            Some(ref expression) => expression.contains_this(),
            _                    => false,
        }
    }
}

fn add_props_to_body(body: &mut Vec<Statement>, mut props: Vec<ClassMember>) {
    for prop in props.iter_mut() {
        if let &mut ClassMember::Property {
            ref is_static,
            ref name,
            ref mut value,
        } = prop {
            body.push(Statement::Expression {
                value: Expression::Binary {
                    left: Box::new(Expression::Member {
                        object: Box::new(Expression::This),
                        property: *name,
                    }),
                    operator: Assign,
                    right: Box::new(value.take()),
                }
            });
        }
    }
}

impl Transformable for Statement {
    fn transform(&mut self, settings: &Settings) {
        *self = match *self {
            Statement::Block {
                ref mut body,
            } => {
                body.transform(settings);
                return;
            },

            Statement::Labeled {
                ref mut body,
                ..
            } => {
                body.transform(settings);
                return;
            },

            Statement::VariableDeclaration {
                ref mut kind,
                ref mut declarators,
            } => {
                declarators.transform(settings);

                // transformation flag check
                if !settings.transform_block_scope {
                    return;
                }

                *kind = VariableDeclarationKind::Var;
                return;
            },

            Statement::Expression {
                ref mut value,
            } => {
                value.transform(settings);
                return;
            },

            Statement::If {
                ref mut test,
                ref mut consequent,
                ref mut alternate,
                ..
            } => {
                test.transform(settings);
                consequent.transform(settings);
                if let Some(ref mut alternate) = *alternate {
                    alternate.transform(settings);
                }
                return;
            },

            Statement::Class {
                ref mut body,
                ..
            } => {
                body.transform(settings);

                if !settings.transform_class_properties {
                    return;
                }

                let prop_count = body.iter().filter(|member| match **member {
                    ClassMember::Property { .. } => true,
                    _                            => false,
                }).count();

                if prop_count == 0 {
                    return;
                }

                let mut constructor = None;
                let mut methods = Vec::with_capacity(body.len());
                let mut props = Vec::with_capacity(prop_count);

                for member in body.drain(..) {
                    match member {
                        ClassMember::Property {
                            ..
                        } => props.push(member),

                        ClassMember::Constructor {
                            params,
                            body,
                        } => constructor = Some((params, body)),

                        _ => methods.push(member),
                    }
                }

                let (cnst_params, mut cnst_body) = match constructor {
                    Some(constructor) => constructor,
                    _                 => (Vec::new(), Vec::new())
                };

                add_props_to_body(&mut cnst_body, props);

                methods.insert(0, ClassMember::Constructor {
                    params: cnst_params,
                    body: cnst_body,
                });

                *body = methods;

                return;
            }

            _ => return,
        }
    }

    fn contains_this(&self) -> bool {
        match *self {
            Statement::VariableDeclaration {
                ref declarators,
                ..
            } => declarators.contains_this(),

            Statement::Expression {
                ref value,
            } => value.contains_this(),

            Statement::Return {
                value: Some(ref expression)
            } => expression.contains_this(),

            _ => false,
        }
    }
}

impl<T: Transformable> Transformable for Vec<T> {
    #[inline]
    fn transform(&mut self, settings: &Settings) {
        for item in self.iter_mut() {
            item.transform(settings);
        }
    }

    #[inline]
    fn contains_this(&self) -> bool {
        for item in self {
            if item.contains_this() {
                return true;
            }
        }
        return false;
    }
}

#[inline]
fn partition_vec<T, F: Fn(&T) -> bool>(source: &mut Vec<T>, f: F) -> Vec<T> {
    let mut other = Vec::new();
    let indexes = 0 .. source.len();

    for index in indexes.rev() {
        unsafe {
            if !f(source.get_unchecked(index)) {
                let item = source.remove(index);
                other.push(item)
            }
        }
    }

    other
}

pub fn transform(program: &mut Program, settings: Settings) {
    program.body.transform(&settings);
}
<|endoftext|>


<commit_before>use object::{Object, ObjectSection};
use std::{env, fs, process};

fn main() {
    let arg_len = env::args().len();
    if arg_len <= 1 {
        eprintln!("Usage: {} <file> ...", env::args().next().unwrap());
        process::exit(1);
    }

    for file_path in env::args().skip(1) {
        if arg_len > 2 {
            println!();
            println!("{}:", file_path);
        }

        let file = match fs::File::open(&file_path) {
            Ok(file) => file,
            Err(err) => {
                println!("Failed to open file '{}': {}", file_path, err,);
                return;
            }
        };
        let file = match unsafe { memmap::Mmap::map(&file) } {
            Ok(mmap) => mmap,
            Err(err) => {
                println!("Failed to map file '{}': {}", file_path, err,);
                return;
            }
        };
        let file = match object::File::parse(&*file) {
            Ok(file) => file,
            Err(err) => {
                println!("Failed to parse file '{}': {}", file_path, err);
                return;
            }
        };

        if let Some(uuid) = file.mach_uuid() {
            println!("Mach UUID: {}", uuid);
        }
        if let Some(build_id) = file.build_id() {
            println!("Build ID: {:x?}", build_id);
        }
        if let Some((filename, crc)) = file.gnu_debuglink() {
            println!(
                "GNU debug link: {} CRC: {:08x}",
                String::from_utf8_lossy(filename),
                crc
            );
        }

        for segment in file.segments() {
            println!("{:?}", segment);
        }

        for section in file.sections() {
            println!("{:?}", section);
        }

        for section in file.sections() {
            if section.relocations().next().is_some() {
                println!(
                    "\n{} relocations",
                    section.name().unwrap_or("<invalid name>")
                );
                for relocation in section.relocations() {
                    println!("{:?}", relocation);
                }
            }
        }
    }
}
<commit_msg>objdump: print symbols<commit_after>use object::{Object, ObjectSection};
use std::{env, fs, process};

fn main() {
    let arg_len = env::args().len();
    if arg_len <= 1 {
        eprintln!("Usage: {} <file> ...", env::args().next().unwrap());
        process::exit(1);
    }

    for file_path in env::args().skip(1) {
        if arg_len > 2 {
            println!();
            println!("{}:", file_path);
        }

        let file = match fs::File::open(&file_path) {
            Ok(file) => file,
            Err(err) => {
                println!("Failed to open file '{}': {}", file_path, err,);
                return;
            }
        };
        let file = match unsafe { memmap::Mmap::map(&file) } {
            Ok(mmap) => mmap,
            Err(err) => {
                println!("Failed to map file '{}': {}", file_path, err,);
                return;
            }
        };
        let file = match object::File::parse(&*file) {
            Ok(file) => file,
            Err(err) => {
                println!("Failed to parse file '{}': {}", file_path, err);
                return;
            }
        };

        if let Some(uuid) = file.mach_uuid() {
            println!("Mach UUID: {}", uuid);
        }
        if let Some(build_id) = file.build_id() {
            println!("Build ID: {:x?}", build_id);
        }
        if let Some((filename, crc)) = file.gnu_debuglink() {
            println!(
                "GNU debug link: {} CRC: {:08x}",
                String::from_utf8_lossy(filename),
                crc
            );
        }

        for segment in file.segments() {
            println!("{:?}", segment);
        }

        for (index, section) in file.sections().enumerate() {
            println!("{}: {:?}", index, section);
        }

        for (index, symbol) in file.symbols() {
            println!("{}: {:?}", index.0, symbol);
        }

        for section in file.sections() {
            if section.relocations().next().is_some() {
                println!(
                    "\n{} relocations",
                    section.name().unwrap_or("<invalid name>")
                );
                for relocation in section.relocations() {
                    println!("{:?}", relocation);
                }
            }
        }
    }
}
<|endoftext|>


<commit_before>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
#![feature(io, os, path)]

extern crate googl;

use std::old_io::fs::File;
use std::os::args;

fn main() {
    let arg = args();
    let longurl = &*arg[1];
    let mut file = File::open(&Path::new("key.txt")).unwrap();
    let key = file.read_to_string().unwrap();
    println!("{:?}", googl::shorten(&*key, &*longurl));
}
<commit_msg>Fix example<commit_after>// Copyright © 2015, Peter Atashian
// Licensed under the MIT License <LICENSE.md>
extern crate googl;

use std::env::{args};
use std::fs::{File};
use std::io::{Read};
use std::path::{Path};

fn main() {
    let longurl = args().next().unwrap();
    let mut file = File::open(&Path::new("key.txt")).unwrap();
    let mut key = String::new();
    file.read_to_string(&mut key).unwrap();
    println!("{:?}", googl::shorten(&key, &longurl));
}
<|endoftext|>


<commit_before>//! Jacobi matrix for time-evolution function

use ndarray::*;
use ndarray_linalg::prelude::*;
use itertools::iterate;
use std::mem::replace;

use super::traits::TimeEvolution;

pub use ndarray::linalg::Dot;

pub struct Jacobian<'a, TEO>
    where TEO: 'a + TimeEvolution<Ix1>
{
    f: &'a TEO,
    x: RcArray1<f64>,
    fx: RcArray1<f64>,
    alpha: f64,
}

pub trait NumDifferentiable: Sized + TimeEvolution<Ix1> {
    fn jacobian<'a>(&'a self, x: RcArray1<f64>, alpha: f64) -> Jacobian<'a, Self>;
}

impl<TEO> NumDifferentiable for TEO
    where TEO: TimeEvolution<Ix1>
{
    fn jacobian<'a>(&'a self, x: RcArray1<f64>, alpha: f64) -> Jacobian<'a, Self> {
        let fx = self.iterate(x.clone());
        Jacobian {
            f: self,
            x: x,
            fx: fx,
            alpha: alpha,
        }
    }
}

impl<'a, S, TEO> Dot<ArrayBase<S, Ix1>> for Jacobian<'a, TEO>
    where TEO: 'a + TimeEvolution<Ix1>,
          S: Data<Elem = f64>
{
    type Output = RcArray1<f64>;
    fn dot(&self, dx: &ArrayBase<S, Ix1>) -> Self::Output {
        let nrm = self.x.norm_l2().max(dx.norm_l2());
        let n = self.alpha / nrm;
        let x = n * dx + &self.x;
        (self.f.iterate(x.into_shared()) - &self.fx) / n
    }
}

impl<'a, S, TEO> Dot<ArrayBase<S, Ix2>> for Jacobian<'a, TEO>
    where TEO: 'a + TimeEvolution<Ix1>,
          S: Data<Elem = f64>
{
    type Output = Array2<f64>;
    fn dot(&self, dxs: &ArrayBase<S, Ix2>) -> Self::Output {
        hstack(&dxs.axis_iter(Axis(1))
                .map(|dx| self.dot(&dx))
                .collect::<Vec<_>>())
            .unwrap()
    }
}

impl<'a, TEO> Jacobian<'a, TEO>
    where TEO: 'a + TimeEvolution<Ix1>
{
    pub fn clv_forward(&self, q: &Array2<f64>) -> (Array2<f64>, Array2<f64>) {
        self.dot(q).qr().unwrap()
    }
}

pub fn clv_backward(c: &Array2<f64>, r: &Array2<f64>) -> (Array2<f64>, Array1<f64>) {
    let cd = r.solve_upper(c).expect("Failed to solve R");
    let (c, d) = normalize(cd, NormalizeAxis::Column);
    let f = Array::from_vec(d).mapv_into(|x| 1.0 / x);
    (c, f)
}

pub fn exponents<TEO>(teo: &TEO, x0: RcArray1<f64>, alpha: f64, duration: usize) -> Array1<f64>
    where TEO: NumDifferentiable
{
    let n = x0.len();
    let ts = iterate(x0, |y| teo.iterate(y.clone()));
    ts.scan(Array::eye(n), |q, x| {
            let (q_next, r) = teo.jacobian(x.clone(), alpha).clv_forward(q);
            *q = q_next;
            let d = r.diag().map(|x| x.abs().ln());
            Some(d)
        })
        .skip(duration / 10)
        .take(duration)
        .fold(Array::zeros(n), |x, y| x + y) / (teo.get_dt() * duration as f64)
}

pub fn clv<TEO>(teo: &TEO,
                x0: RcArray1<f64>,
                alpha: f64,
                duration: usize)
                -> Vec<(Array1<f64>, Array2<f64>, Array1<f64>)>
    where TEO: NumDifferentiable
{
    let n = x0.len();
    let ts = iterate(x0, |y| teo.iterate(y.clone()));
    let qr_series = ts.scan(Array::eye(n), |q, x| {
            let (q_next, r) = teo.jacobian(x.clone(), alpha).clv_forward(q);
            let q = replace(q, q_next);
            Some((x, q, r))
        })
        .skip(duration / 10)
        .take(duration)
        .collect::<Vec<_>>();
    let clv_rev = qr_series.into_iter()
        .rev()
        .scan(Array::eye(3), |c, (x, q, r)| {
            let (c_now, f) = clv_backward(c, &r);
            let v = q.dot(&c_now);
            *c = c_now;
            Some((x.into_owned(), v, f))
        })
        .collect::<Vec<_>>();
    clv_rev.into_iter().rev().collect()
}
<commit_msg>Add document and remove unused codes<commit_after>//! Jacobi matrix for time-evolution function

use ndarray::*;
use ndarray_linalg::prelude::*;
use itertools::iterate;
use std::mem::replace;

use super::traits::TimeEvolution;

pub use ndarray::linalg::Dot;

/// Jacobian operator using numerical-differentiation
pub struct Jacobian<'a, TEO>
    where TEO: 'a + TimeEvolution<Ix1>
{
    f: &'a TEO,
    x: RcArray1<f64>,
    fx: RcArray1<f64>,
    alpha: f64,
}

/// Trait for Jacobian using numerical-differentiation
pub trait NumDifferentiable: Sized + TimeEvolution<Ix1> {
    fn jacobian<'a>(&'a self, x: RcArray1<f64>, alpha: f64) -> Jacobian<'a, Self>;
}

impl<TEO> NumDifferentiable for TEO
    where TEO: TimeEvolution<Ix1>
{
    fn jacobian<'a>(&'a self, x: RcArray1<f64>, alpha: f64) -> Jacobian<'a, Self> {
        let fx = self.iterate(x.clone());
        Jacobian {
            f: self,
            x: x,
            fx: fx,
            alpha: alpha,
        }
    }
}

impl<'a, S, TEO> Dot<ArrayBase<S, Ix1>> for Jacobian<'a, TEO>
    where TEO: 'a + TimeEvolution<Ix1>,
          S: Data<Elem = f64>
{
    type Output = RcArray1<f64>;
    fn dot(&self, dx: &ArrayBase<S, Ix1>) -> Self::Output {
        let nrm = self.x.norm_l2().max(dx.norm_l2());
        let n = self.alpha / nrm;
        let x = n * dx + &self.x;
        (self.f.iterate(x.into_shared()) - &self.fx) / n
    }
}

impl<'a, S, TEO> Dot<ArrayBase<S, Ix2>> for Jacobian<'a, TEO>
    where TEO: 'a + TimeEvolution<Ix1>,
          S: Data<Elem = f64>
{
    type Output = Array2<f64>;
    fn dot(&self, dxs: &ArrayBase<S, Ix2>) -> Self::Output {
        hstack(&dxs.axis_iter(Axis(1))
                .map(|dx| self.dot(&dx))
                .collect::<Vec<_>>())
            .unwrap()
    }
}

fn clv_backward(c: &Array2<f64>, r: &Array2<f64>) -> (Array2<f64>, Array1<f64>) {
    let cd = r.solve_upper(c).expect("Failed to solve R");
    let (c, d) = normalize(cd, NormalizeAxis::Column);
    let f = Array::from_vec(d).mapv_into(|x| 1.0 / x);
    (c, f)
}

/// Calculate all Lyapunov exponents
pub fn exponents<TEO>(teo: &TEO, x0: RcArray1<f64>, alpha: f64, duration: usize) -> Array1<f64>
    where TEO: NumDifferentiable
{
    let n = x0.len();
    let ts = iterate(x0, |y| teo.iterate(y.clone()));
    ts.scan(Array::eye(n), |q, x| {
            let (q_next, r) = teo.jacobian(x.clone(), alpha).dot(q).qr().unwrap();
            *q = q_next;
            let d = r.diag().map(|x| x.abs().ln());
            Some(d)
        })
        .skip(duration / 10)
        .take(duration)
        .fold(Array::zeros(n), |x, y| x + y) / (teo.get_dt() * duration as f64)
}

/// Calculate Covariant Lyapunov Vector
///
/// **CAUTION**
/// This function consumes much memory since this saves matrices duraing the time evolution.
pub fn clv<TEO>(teo: &TEO,
                x0: RcArray1<f64>,
                alpha: f64,
                duration: usize)
                -> Vec<(Array1<f64>, Array2<f64>, Array1<f64>)>
    where TEO: NumDifferentiable
{
    let n = x0.len();
    let ts = iterate(x0, |y| teo.iterate(y.clone()));
    let qr_series = ts.scan(Array::eye(n), |q, x| {
            let (q_next, r) = teo.jacobian(x.clone(), alpha).dot(q).qr().unwrap();
            let q = replace(q, q_next);
            Some((x, q, r))
        })
        .skip(duration / 10)
        .take(duration)
        .collect::<Vec<_>>();
    let clv_rev = qr_series.into_iter()
        .rev()
        .scan(Array::eye(3), |c, (x, q, r)| {
            let (c_now, f) = clv_backward(c, &r);
            let v = q.dot(&c_now);
            *c = c_now;
            Some((x.into_owned(), v, f))
        })
        .collect::<Vec<_>>();
    clv_rev.into_iter().rev().collect()
}
<|endoftext|>


<commit_before>use {osc_types, errors};

use std::{io, string, mem, error};
use std::io::BufRead;

use byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg, size)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(errors::OscError::BadOscPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);
    let mut pos: u64 = 0;

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            pos = pad_four(cursor.position());
            println!("{}, {}", addr, pos);
        }
        Err(e) => {
            println!("{}", e)
        }
    }

    Ok(osc_types::OscPacket::Message(osc_types::OscMessage))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> osc_types::OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => String::from_utf8(str_buf).map_err(|e| errors::OscError::StringError(e)),
        Err(e) => Err(errors::OscError::ReadError(e)),
    }
}

fn decode_bundle(msg: &[u8]) -> osc_types::OscResult<osc_types::OscPacket> {
    Err(errors::OscError::BadOscBundle)
}

fn pad_four(pos: u64) -> u64 {
    let d: u64 = pos % 4;
    match d {
        0 => pos,
        _ => pos + (4 - d),
    }
}
<commit_msg>Refactor `pad_four` to change position of Cursor directly<commit_after>use {osc_types, errors};

use std::{io, string, mem, error};
use std::io::BufRead;

use byteorder;
use byteorder::{BigEndian, ReadBytesExt};

/// Common MTP size for ethernet
pub const MTP: usize = 1536;

pub fn decode(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    match msg[0] as char {
        '/' => {
            decode_message(msg, size)
        }
        '#' => {
            decode_bundle(msg)
        }
        _ => Err(errors::OscError::BadOscPacket("Unknown message format.".to_string())),
    }
}

fn decode_message(msg: &[u8], size: usize) -> osc_types::OscResult<osc_types::OscPacket> {
    let mut cursor: io::Cursor<&[u8]> = io::Cursor::new(msg);
    let mut pos: u64 = 0;

    match read_osc_string(&mut cursor) {
        Ok(s) => {
            let addr: String = s;
            println!("{}, {}", addr, pos);

            pad_cursor(&mut cursor);
        }
        Err(e) => {
            println!("{}", e)
        }
    }

    Ok(osc_types::OscPacket::Message(osc_types::OscMessage))
}

fn read_osc_string(cursor: &mut io::Cursor<&[u8]>) -> osc_types::OscResult<String> {
    let mut str_buf: Vec<u8> = Vec::new();
    match cursor.read_until(0, &mut str_buf) {
        Ok(_) => String::from_utf8(str_buf).map_err(|e| errors::OscError::StringError(e)),
        Err(e) => Err(errors::OscError::ReadError(e)),
    }
}

fn decode_bundle(msg: &[u8]) -> osc_types::OscResult<osc_types::OscPacket> {
    Err(errors::OscError::BadOscBundle)
}

fn pad_cursor(cursor: &mut io::Cursor<&[u8]>) {
    let pos = cursor.position();
    match pos % 4 {
        0 => (),
        d => cursor.set_position(pos + (4 - d)),
    }
}<|endoftext|>