<commit_before>extern crate rustbox;
extern crate chrono;

use rustbox::*;
use chrono::*;

use screen::common::*;
use utility::string::*;
use model::ShowItem;
use model::ShowReplyItem;
use reply_model::*;

pub struct Show<'a> {
    rustbox: &'a rustbox::RustBox,
    scrollY: usize,
}

impl<'a> Show<'a> {
    pub fn new(rustbox: &'a rustbox::RustBox) -> Self {
        Show {
            rustbox: &rustbox,
            scrollY: 0,
        }
    }
    pub fn print(&mut self, title: &str, item: &ShowItem) {

        self.print_header(&format!("{} - {} [{}/{}]",
                                   item.title,
                                   title,
                                   item.page,
                                   item.max_page));
        self.print_body(2, &item);
    }

    fn print_separator_top(&mut self, reply: &ShowReplyItem, y: usize) {
        if y > self.scrollY + 1 {
            let (replier_name, time) = self.build_separator_content(&reply);
            self.rustbox.print(0,
                               y - self.scrollY,
                               rustbox::RB_NORMAL,
                               Color::Green,
                               Color::Black,
                               &self.build_separator_top(&replier_name, &time));
        }
    }

    fn print_separator_bottom(&mut self, y: usize) {
        if y > self.scrollY + 1 {
            self.rustbox.print(0,
                               y - self.scrollY,
                               rustbox::RB_NORMAL,
                               Color::Green,
                               Color::Black,
                               &self.build_separator_bottom());
        }
    }

    fn print_header(&mut self, text: &str) {
        let title_len = jks_len(text);
        let padding = (if self.rustbox.width() >= title_len {
            self.rustbox.width() - title_len
        } else {
            0
        }) / 2;

        let header_bottom = seq_str_gen(0, self.rustbox.width(), "─", "");

        clearline(&self.rustbox, self.rustbox.width(), 0, 0);
        self.rustbox.print(padding,
                           0,
                           rustbox::RB_BOLD,
                           Color::White,
                           Color::Black,
                           text);
        self.rustbox.print(0,
                           1,
                           rustbox::RB_BOLD,
                           Color::Yellow,
                           Color::Black,
                           &header_bottom);
    }

    pub fn print_body(&mut self, offset_y: usize, item: &ShowItem) {
        let width = self.body_width();
        let rows = self.body_height();
        let rustbox = self.rustbox;
        let scrollY = self.scrollY;

        let mut y = offset_y;

        for (i, reply) in item.replies.iter().take(rows).enumerate() {

            y += print_reply(&reply.body, 0, scrollY, y, &rustbox);

            self.print_separator_top(&reply, y);
            y += 1;

            self.print_separator_bottom(y);
            y += 1;
        }
    }

    fn build_separator_content(&mut self, reply: &ShowReplyItem) -> (String, String) {
        let now = Local::now();

        let replier_name = reply.username.clone();

        let published_at = reply.published_at.clone();

        let published_at_dt = match Local.datetime_from_str(&published_at, "%d/%m/%Y %H:%M") {
            Ok(v) => v,
            Err(e) => now,
        };
        let time = published_at_format(&(now - published_at_dt));
        (replier_name, time)
    }

    fn build_separator_arguments(&mut self) -> (usize, usize, String) {
        let width = self.body_width();
        let rustbox = self.rustbox;

        let separator_width = if rustbox.width() >= 2 {
            rustbox.width() - 2
        } else {
            0
        };
        let separator_padding_width = if rustbox.width() > separator_width {
            rustbox.width() - separator_width
        } else {
            0
        } / 2;

        let separator_padding = seq_str_gen(0, separator_padding_width, " ", "");

        (separator_width, separator_padding_width, separator_padding)
    }

    fn build_separator_top(&mut self, replier_name: &str, time: &str) -> String {
        let replier_max_width = 14;
        let time_max_width = 5;
        let (separator_width, separator_padding_width, separator_padding) =
            self.build_separator_arguments();
        make_separator_top(separator_width,
                           &separator_padding,
                           replier_max_width,
                           &replier_name,
                           time_max_width,
                           &time)
    }

    fn build_separator_bottom(&mut self) -> String {
        let (separator_width, separator_padding_width, separator_padding) =
            self.build_separator_arguments();
        make_separator_bottom(separator_width, &separator_padding)
    }

    pub fn resetY(&mut self) {
        self.scrollY = 0;
    }

    pub fn scrollUp(&mut self, value: usize) -> bool {
        let tmp = self.scrollY;
        if tmp > value {
            self.scrollY = tmp - value;
            true
        } else if tmp != 0 {
            self.scrollY = 0;
            true
        } else {
            false
        }
    }

    pub fn scrollDown(&mut self, value: usize) -> bool {
        let tmp = self.scrollY;
        if tmp < 10000 {
            self.scrollY = tmp + value;
            return true;
        }
        false
    }

    pub fn body_height(&self) -> usize {
        if self.rustbox.height() >= 3 {
            self.rustbox.height() - 3
        } else {
            0
        }
    }

    pub fn body_width(&self) -> usize {
        if self.rustbox.width() >= 2 {
            self.rustbox.width() - 2
        } else {
            0
        }
    }
}

fn print_default(rustbox: &rustbox::RustBox, x: usize, y: usize, s: String) {
    rustbox.print(0, y, rustbox::RB_NORMAL, Color::White, Color::Black, &s);
}

fn print_reply(vec: &Vec<NodeType>,
               depth: usize,
               scrollY: usize,
               y: usize,
               rustbox: &rustbox::RustBox)
               -> usize {
    let padding = seq_str_gen(0, depth, "├─", "");
    let mut m = 0;
    let mut recursive_offset = 0;
    let mut total_y = 0;
    let mut line = String::new();

    // clean up lines (end)
    let vec2 = {
        let vec_length = vec.len();
        let vec_check_cleanup = vec.clone();

        // check if last 4 elements match the EMPTY PATTERN
        let is_last4_empty = vec_check_cleanup.iter()
                                              .rev()
                                              .take(4)
                                              .enumerate()
                                              .all(|(j, node)| match node.clone() {
                                                  NodeType::Br(n) => j == 1 || j == 2 || j == 3,
                                                  NodeType::Text(n) => j == 0 && n.data.is_empty(),
                                                  _ => false,
                                              });

        let vec_short_length = if vec_length > 4 && is_last4_empty {
            vec_length - 4
        } else {
            vec_length
        };

        vec.iter().take(vec_short_length)
    };

    // clean up lines (start)
    let vec3 = {
        let vec2_cloned = vec2.clone();
        let mut result: Vec<NodeType> = Vec::new();
        for (j, node) in vec2_cloned.enumerate() {
            let node2 = node.clone();
            let node3 = node.clone();
            match node2 {
                NodeType::Br(n) => {
                    if !result.is_empty() {
                        result.push(node3);
                    }
                }
                _ => result.push(node3),
            }
        }
        result.clone()
    };

    let mut is_first = true;
    for (j, node) in vec3.iter().enumerate() {
        total_y = y + m + recursive_offset;
        if scrollY + 1 < total_y {
            let node2 = node.clone();
            match node2 {
                NodeType::Text(n) => {
                    if n.data != "" {
                        line = format!("{}{}", line, n.data);
                    }
                }
                NodeType::Image(n) => {
                    if n.data != "" {
                        line = format!("{}[img {}]", line, n.data);
                    }
                }
                NodeType::BlockQuote(n) => {
                    recursive_offset += print_reply(&n.data, depth + 1, scrollY, total_y, &rustbox);
                    is_first = false;
                }
                NodeType::Br(n) => {
                    if !line.is_empty() {
                        print_default(rustbox,
                                      0,
                                      total_y - scrollY,
                                      format!(" {}{}", padding, line));
                        line = String::new();
                        is_first = false;
                    }

                    // prevent first line empty
                    if !is_first {
                        m += 1;
                    }

                }
            }
        }
    }

    if !line.is_empty() {
        total_y = y + m + recursive_offset;
        print_default(rustbox,
                      0,
                      total_y - scrollY,
                      format!(" {}{}  ", padding, line));
        line = String::new();
        m += 1;
    }

    m + recursive_offset
}

fn make_separator_replier_name(separator_width: usize,
                               separator_padding: &str,
                               replier_max_width: usize,
                               replier_name: &str)
                               -> String {
    let replier_name_len = jks_len(&replier_name);
    let replier_name_spacing_width = replier_max_width - replier_name_len;
    let is_replier_name_spacing_width_odd = replier_name_spacing_width & 1 == 1;
    let replier_name_right_spacing_width = replier_name_spacing_width / 2;
    let replier_name_left_spacing_width = if is_replier_name_spacing_width_odd {
        replier_name_right_spacing_width + 1
    } else {
        replier_name_right_spacing_width
    };

    let replier_name_left_spacing = seq_str_gen(0, replier_name_left_spacing_width, "─", "");
    let replier_name_right_spacing = seq_str_gen(0, replier_name_right_spacing_width, "─", "");

    let separator_replier = format!("{}{}{}{}{}",
                                    "╭",
                                    replier_name_left_spacing,
                                    replier_name,
                                    replier_name_right_spacing,
                                    "");

    return separator_replier;
}

fn make_separator_time(separator_width: usize,
                       separator_padding: &str,
                       time_max_width: usize,
                       time: &str)
                       -> String {
    let time_len = jks_len(&time);
    let time_spacing_width = if time_max_width > time_len {
        time_max_width - time_len
    } else {
        0
    };

    let is_time_spacing_width_odd = time_spacing_width & 1 == 1;
    let time_right_spacing_width = time_spacing_width / 2;
    let time_left_spacing_width = if is_time_spacing_width_odd {
        time_right_spacing_width + 1
    } else {
        time_right_spacing_width
    };

    let time_left_spacing = seq_str_gen(0, time_left_spacing_width, "─", "");
    let time_right_spacing = seq_str_gen(0, time_right_spacing_width, "─", "");

    let separator_time = format!("{}{}{}{}{}",
                                 "",
                                 time_left_spacing,
                                 time,
                                 time_right_spacing,
                                 "╮");

    return separator_time;
}

fn make_separator_top(separator_width: usize,
                      separator_padding: &str,
                      replier_max_width: usize,
                      replier_name: &str,
                      time_max_width: usize,
                      time: &str)
                      -> String {

    let separator_replier = make_separator_replier_name(separator_width,
                                                        &separator_padding,
                                                        replier_max_width,
                                                        &replier_name);

    let separator_replier_width = jks_len(&separator_replier);

    let separator_time = make_separator_time(separator_width,
                                             &separator_padding,
                                             time_max_width,
                                             &time);

    let separator_time_width = jks_len(&separator_time);

    let separator_top_middle_width = if separator_width >=
                                        (separator_replier_width + separator_time_width) {
        separator_width - separator_replier_width - separator_time_width
    } else {
        0
    };

    let separator_top_middle = seq_str_gen(0, separator_top_middle_width, " ", "");
    let separator_top = format!("{}{}{}{}{}",
                                separator_padding,
                                separator_top_middle,
                                separator_replier,
                                separator_time,
                                separator_padding);
    return separator_top;
}

fn make_separator_bottom(separator_width: usize, separator_padding: &str) -> String {
    let style_box_width = 1;
    let separator_bottom_middle_width = if separator_width > style_box_width {
        separator_width - style_box_width
    } else {
        0
    };
    let separator_bottom_middle = seq_str_gen(0, separator_bottom_middle_width, "─", "");

    let separator_bottom = format!("{}{}{}{}",
                                   separator_padding,
                                   separator_bottom_middle,
                                   "╯",
                                   separator_padding);
    return separator_bottom;
}

fn published_at_format(duration: &Duration) -> String {
    let weeks = duration.num_weeks();
    let days = duration.num_days();
    let hours = duration.num_hours();
    let minutes = duration.num_minutes();

    if weeks > 0 {
        format!("{}w", weeks)
    } else if days > 0 {
        format!("{}d", days)
    } else if hours > 0 {
        format!("{}h", hours)
    } else if minutes > 0 {
        format!("{}m", minutes)
    } else {
        String::from("1m")
    }
}

fn seq_str_gen(start: usize, end: usize, sym: &str, join_sym: &str) -> String {
    (start..end).map(|_| sym.clone()).collect::<Vec<_>>().join(&join_sym)
}
<commit_msg>show - move print reply in show class<commit_after>extern crate rustbox;
extern crate chrono;

use rustbox::*;
use chrono::*;

use screen::common::*;
use utility::string::*;
use model::ShowItem;
use model::ShowReplyItem;
use reply_model::*;

pub struct Show<'a> {
    rustbox: &'a rustbox::RustBox,
    scrollY: usize,
}

impl<'a> Show<'a> {
    pub fn new(rustbox: &'a rustbox::RustBox) -> Self {
        Show {
            rustbox: &rustbox,
            scrollY: 0,
        }
    }
    pub fn print(&mut self, title: &str, item: &ShowItem) {

        self.print_header(&format!("{} - {} [{}/{}]",
                                   item.title,
                                   title,
                                   item.page,
                                   item.max_page));
        self.print_body(2, &item);
    }

    fn print_separator_top(&mut self, reply: &ShowReplyItem, y: usize) {
        if y > self.scrollY + 1 {
            let (replier_name, time) = self.build_separator_content(&reply);
            self.rustbox.print(0,
                               y - self.scrollY,
                               rustbox::RB_NORMAL,
                               Color::Green,
                               Color::Black,
                               &self.build_separator_top(&replier_name, &time));
        }
    }

    fn print_separator_bottom(&mut self, y: usize) {
        if y > self.scrollY + 1 {
            self.rustbox.print(0,
                               y - self.scrollY,
                               rustbox::RB_NORMAL,
                               Color::Green,
                               Color::Black,
                               &self.build_separator_bottom());
        }
    }

    fn print_header(&mut self, text: &str) {
        let title_len = jks_len(text);
        let padding = (if self.rustbox.width() >= title_len {
            self.rustbox.width() - title_len
        } else {
            0
        }) / 2;

        let header_bottom = seq_str_gen(0, self.rustbox.width(), "─", "");

        clearline(&self.rustbox, self.rustbox.width(), 0, 0);
        self.rustbox.print(padding,
                           0,
                           rustbox::RB_BOLD,
                           Color::White,
                           Color::Black,
                           text);
        self.rustbox.print(0,
                           1,
                           rustbox::RB_BOLD,
                           Color::Yellow,
                           Color::Black,
                           &header_bottom);
    }

    pub fn print_body(&mut self, offset_y: usize, item: &ShowItem) {
        let width = self.body_width();
        let rows = self.body_height();
        let rustbox = self.rustbox;
        let scrollY = self.scrollY;

        let mut y = offset_y;

        for (i, reply) in item.replies.iter().take(rows).enumerate() {

            y += self.print_reply(&reply.body, 0, y);

            self.print_separator_top(&reply, y);
            y += 1;

            self.print_separator_bottom(y);
            y += 1;
        }
    }

    fn print_reply(&mut self, vec: &Vec<NodeType>,
                   depth: usize,
                   y: usize)
                   -> usize {

       let rustbox = self.rustbox;
       let scrollY = self.scrollY;

        let padding = seq_str_gen(0, depth, "├─", "");
        let mut m = 0;
        let mut recursive_offset = 0;
        let mut total_y = 0;
        let mut line = String::new();

        // clean up lines (end)
        let vec2 = {
            let vec_length = vec.len();
            let vec_check_cleanup = vec.clone();

            // check if last 4 elements match the EMPTY PATTERN
            let is_last4_empty = vec_check_cleanup.iter()
                                                  .rev()
                                                  .take(4)
                                                  .enumerate()
                                                  .all(|(j, node)| match node.clone() {
                                                      NodeType::Br(n) => j == 1 || j == 2 || j == 3,
                                                      NodeType::Text(n) => j == 0 && n.data.is_empty(),
                                                      _ => false,
                                                  });

            let vec_short_length = if vec_length > 4 && is_last4_empty {
                vec_length - 4
            } else {
                vec_length
            };

            vec.iter().take(vec_short_length)
        };

        // clean up lines (start)
        let vec3 = {
            let vec2_cloned = vec2.clone();
            let mut result: Vec<NodeType> = Vec::new();
            for (j, node) in vec2_cloned.enumerate() {
                let node2 = node.clone();
                let node3 = node.clone();
                match node2 {
                    NodeType::Br(n) => {
                        if !result.is_empty() {
                            result.push(node3);
                        }
                    }
                    _ => result.push(node3),
                }
            }
            result.clone()
        };

        let mut is_first = true;
        for (j, node) in vec3.iter().enumerate() {
            total_y = y + m + recursive_offset;
            if scrollY + 1 < total_y {
                let node2 = node.clone();
                match node2 {
                    NodeType::Text(n) => {
                        if n.data != "" {
                            line = format!("{}{}", line, n.data);
                        }
                    }
                    NodeType::Image(n) => {
                        if n.data != "" {
                            line = format!("{}[img {}]", line, n.data);
                        }
                    }
                    NodeType::BlockQuote(n) => {
                        recursive_offset += self.print_reply(&n.data, depth + 1, total_y);
                        is_first = false;
                    }
                    NodeType::Br(n) => {
                        if !line.is_empty() {
                            print_default(rustbox,
                                          0,
                                          total_y - scrollY,
                                          format!(" {}{}", padding, line));
                            line = String::new();
                            is_first = false;
                        }

                        // prevent first line empty
                        if !is_first {
                            m += 1;
                        }

                    }
                }
            }
        }

        if !line.is_empty() {
            total_y = y + m + recursive_offset;
            print_default(rustbox,
                          0,
                          total_y - scrollY,
                          format!(" {}{}  ", padding, line));
            line = String::new();
            m += 1;
        }

        m + recursive_offset
    }

    fn build_separator_content(&mut self, reply: &ShowReplyItem) -> (String, String) {
        let now = Local::now();

        let replier_name = reply.username.clone();

        let published_at = reply.published_at.clone();

        let published_at_dt = match Local.datetime_from_str(&published_at, "%d/%m/%Y %H:%M") {
            Ok(v) => v,
            Err(e) => now,
        };
        let time = published_at_format(&(now - published_at_dt));
        (replier_name, time)
    }

    fn build_separator_arguments(&mut self) -> (usize, usize, String) {
        let width = self.body_width();
        let rustbox = self.rustbox;

        let separator_width = if rustbox.width() >= 2 {
            rustbox.width() - 2
        } else {
            0
        };
        let separator_padding_width = if rustbox.width() > separator_width {
            rustbox.width() - separator_width
        } else {
            0
        } / 2;

        let separator_padding = seq_str_gen(0, separator_padding_width, " ", "");

        (separator_width, separator_padding_width, separator_padding)
    }

    fn build_separator_top(&mut self, replier_name: &str, time: &str) -> String {
        let replier_max_width = 14;
        let time_max_width = 5;
        let (separator_width, separator_padding_width, separator_padding) =
            self.build_separator_arguments();
        make_separator_top(separator_width,
                           &separator_padding,
                           replier_max_width,
                           &replier_name,
                           time_max_width,
                           &time)
    }

    fn build_separator_bottom(&mut self) -> String {
        let (separator_width, separator_padding_width, separator_padding) =
            self.build_separator_arguments();
        make_separator_bottom(separator_width, &separator_padding)
    }

    pub fn resetY(&mut self) {
        self.scrollY = 0;
    }

    pub fn scrollUp(&mut self, value: usize) -> bool {
        let tmp = self.scrollY;
        if tmp > value {
            self.scrollY = tmp - value;
            true
        } else if tmp != 0 {
            self.scrollY = 0;
            true
        } else {
            false
        }
    }

    pub fn scrollDown(&mut self, value: usize) -> bool {
        let tmp = self.scrollY;
        if tmp < 10000 {
            self.scrollY = tmp + value;
            return true;
        }
        false
    }

    pub fn body_height(&self) -> usize {
        if self.rustbox.height() >= 3 {
            self.rustbox.height() - 3
        } else {
            0
        }
    }

    pub fn body_width(&self) -> usize {
        if self.rustbox.width() >= 2 {
            self.rustbox.width() - 2
        } else {
            0
        }
    }
}

fn print_default(rustbox: &rustbox::RustBox, x: usize, y: usize, s: String) {
    rustbox.print(0, y, rustbox::RB_NORMAL, Color::White, Color::Black, &s);
}

fn make_separator_replier_name(separator_width: usize,
                               separator_padding: &str,
                               replier_max_width: usize,
                               replier_name: &str)
                               -> String {
    let replier_name_len = jks_len(&replier_name);
    let replier_name_spacing_width = replier_max_width - replier_name_len;
    let is_replier_name_spacing_width_odd = replier_name_spacing_width & 1 == 1;
    let replier_name_right_spacing_width = replier_name_spacing_width / 2;
    let replier_name_left_spacing_width = if is_replier_name_spacing_width_odd {
        replier_name_right_spacing_width + 1
    } else {
        replier_name_right_spacing_width
    };

    let replier_name_left_spacing = seq_str_gen(0, replier_name_left_spacing_width, "─", "");
    let replier_name_right_spacing = seq_str_gen(0, replier_name_right_spacing_width, "─", "");

    let separator_replier = format!("{}{}{}{}{}",
                                    "╭",
                                    replier_name_left_spacing,
                                    replier_name,
                                    replier_name_right_spacing,
                                    "");

    return separator_replier;
}

fn make_separator_time(separator_width: usize,
                       separator_padding: &str,
                       time_max_width: usize,
                       time: &str)
                       -> String {
    let time_len = jks_len(&time);
    let time_spacing_width = if time_max_width > time_len {
        time_max_width - time_len
    } else {
        0
    };

    let is_time_spacing_width_odd = time_spacing_width & 1 == 1;
    let time_right_spacing_width = time_spacing_width / 2;
    let time_left_spacing_width = if is_time_spacing_width_odd {
        time_right_spacing_width + 1
    } else {
        time_right_spacing_width
    };

    let time_left_spacing = seq_str_gen(0, time_left_spacing_width, "─", "");
    let time_right_spacing = seq_str_gen(0, time_right_spacing_width, "─", "");

    let separator_time = format!("{}{}{}{}{}",
                                 "",
                                 time_left_spacing,
                                 time,
                                 time_right_spacing,
                                 "╮");

    return separator_time;
}

fn make_separator_top(separator_width: usize,
                      separator_padding: &str,
                      replier_max_width: usize,
                      replier_name: &str,
                      time_max_width: usize,
                      time: &str)
                      -> String {

    let separator_replier = make_separator_replier_name(separator_width,
                                                        &separator_padding,
                                                        replier_max_width,
                                                        &replier_name);

    let separator_replier_width = jks_len(&separator_replier);

    let separator_time = make_separator_time(separator_width,
                                             &separator_padding,
                                             time_max_width,
                                             &time);

    let separator_time_width = jks_len(&separator_time);

    let separator_top_middle_width = if separator_width >=
                                        (separator_replier_width + separator_time_width) {
        separator_width - separator_replier_width - separator_time_width
    } else {
        0
    };

    let separator_top_middle = seq_str_gen(0, separator_top_middle_width, " ", "");
    let separator_top = format!("{}{}{}{}{}",
                                separator_padding,
                                separator_top_middle,
                                separator_replier,
                                separator_time,
                                separator_padding);
    return separator_top;
}

fn make_separator_bottom(separator_width: usize, separator_padding: &str) -> String {
    let style_box_width = 1;
    let separator_bottom_middle_width = if separator_width > style_box_width {
        separator_width - style_box_width
    } else {
        0
    };
    let separator_bottom_middle = seq_str_gen(0, separator_bottom_middle_width, "─", "");

    let separator_bottom = format!("{}{}{}{}",
                                   separator_padding,
                                   separator_bottom_middle,
                                   "╯",
                                   separator_padding);
    return separator_bottom;
}

fn published_at_format(duration: &Duration) -> String {
    let weeks = duration.num_weeks();
    let days = duration.num_days();
    let hours = duration.num_hours();
    let minutes = duration.num_minutes();

    if weeks > 0 {
        format!("{}w", weeks)
    } else if days > 0 {
        format!("{}d", days)
    } else if hours > 0 {
        format!("{}h", hours)
    } else if minutes > 0 {
        format!("{}m", minutes)
    } else {
        String::from("1m")
    }
}

fn seq_str_gen(start: usize, end: usize, sym: &str, join_sym: &str) -> String {
    (start..end).map(|_| sym.clone()).collect::<Vec<_>>().join(&join_sym)
}
<|endoftext|>


<commit_before>use na::{Inverse, Cross, Norm};
use na::{abs, zero};

use ::{Transform, Point2f, Point3f, Vector3f, max_dimension, permute_v, permute_p,
       coordinate_system};
use bounds::Bounds3f;
use interaction::{Interaction, SurfaceInteraction};
use ray::Ray;
use shapes::Shape;

pub struct TriangleMesh {
    object_to_world: Transform,
    world_to_object: Transform,
    n_triangles: usize,
    n_vertices: usize,
    vertex_indices: Vec<usize>,
    p: Vec<Point3f>,
    n: Option<Vec<Vector3f>>,
    s: Option<Vec<Vector3f>>,
    uv: Option<Vec<Point2f>>, // TODO alpha mask
}

impl TriangleMesh {
    pub fn new(object_to_world: &Transform,
               n_triangles: usize,
               vertex_indices: &[usize],
               n_vertices: usize,
               p: &[Point3f],
               s: Option<&[Vector3f]>,
               n: Option<&[Vector3f]>,
               uv: Option<&[Point2f]>)
               -> Self {
        let points: Vec<Point3f> = p.iter().map(|pt| *object_to_world * *pt).collect();
        TriangleMesh {
            object_to_world: *object_to_world,
            world_to_object: object_to_world.inverse().unwrap(),
            n_triangles: n_triangles,
            n_vertices: n_vertices,
            vertex_indices: Vec::from(vertex_indices),
            p: points,
            n: n.map(Vec::from),
            s: s.map(Vec::from),
            uv: uv.map(Vec::from),
        }
    }
}

pub struct Triangle<'a> {
    mesh: &'a TriangleMesh,
    v: &'a [usize],
}

impl<'a> Triangle<'a> {
    pub fn new(mesh: &'a TriangleMesh, tri_number: usize) -> Triangle<'a> {
        Triangle {
            mesh: mesh,
            v: &mesh.vertex_indices[tri_number * 3..tri_number * 3 + 1],
        }
    }

    fn get_uvs(&self) -> [Point2f; 3] {
        if let Some(ref uv) = self.mesh.uv {
            [uv[self.v[0]], uv[self.v[1]], uv[self.v[2]]]
        } else {
            [Point2f::new(0.0, 0.0), Point2f::new(1.0, 0.0), Point2f::new(1.0, 1.0)]
        }
    }
}

impl<'a> Shape for Triangle<'a> {
    fn intersect(&self, ray: &Ray) -> Option<(SurfaceInteraction, f32)> {
        let p0 = self.mesh.p[self.v[0]];
        let p1 = self.mesh.p[self.v[1]];
        let p2 = self.mesh.p[self.v[2]];

        // Perform ray-triangle intersection test
        // - transform triangle vertices to ray coordinate space
        // -- translate vertices based on ray origin
        let mut p0t = p0 - ray.o.to_vector();
        let mut p1t = p1 - ray.o.to_vector();
        let mut p2t = p2 - ray.o.to_vector();
        // -- permute components of triangle vertices and ray direction
        let kz = max_dimension(abs(&ray.d));
        let mut kx = kz + 1;
        if kx == 3 {
            kx = 0;
        }
        let mut ky = kx + 1;
        if ky == 3 {
            ky = 0;
        }
        let d = permute_v(&ray.d, kx, ky, kz);
        p0t = permute_p(&p0t, kx, ky, kz);
        p1t = permute_p(&p1t, kx, ky, kz);
        p2t = permute_p(&p2t, kx, ky, kz);
        // -- apply shear transformation to translated vertex positions
        let sx = -d.x / d.z;
        let sy = -d.y / d.z;
        let sz = 1.0 / d.z;
        p0t.x += sx * p0t.z;
        p0t.y += sy * p0t.z;
        p1t.x += sx * p1t.z;
        p1t.y += sy * p1t.z;
        p2t.x += sx * p2t.z;
        p2t.y += sy * p2t.z;
        // - compute edge function coefficients
        let e0 = p1t.x * p2t.y - p1t.y * p2t.x;
        let e1 = p2t.x * p0t.y - p2t.y * p0t.x;
        let e2 = p0t.x * p1t.y - p0t.y * p1t.x;
        // - fall back to double precision at edges
        // TODO
        // - perform triangle edge and determinant test
        if (e0 < 0.0 || e1 < 0.0 || e2 < 0.0) && (e0 > 0.0 || e1 > 0.0 || e2 > 0.0) {
            return None;
        }
        let det = e0 + e1 + e2;
        if det == 0.0 {
            return None;
        }
        // - compute scaled hit distance to triangle and test against ray t range
        p0t.z *= sz;
        p1t.z *= sz;
        p2t.z *= sz;
        let t_scaled = e0 * p0t.z + e1 * p1t.z + e2 * p2t.z;
        if det < 0.0 && (t_scaled >= 0.0 || t_scaled < ray.t_max * det) {
            return None;
        } else if det > 0.0 && (t_scaled <= 0.0 || t_scaled > ray.t_max * det) {
            return None;
        }
        // - compute barycentric coordinates and t value for triangle intersection
        let inv_det = 1.0 / det;
        let b0 = e0 * inv_det;
        let b1 = e1 * inv_det;
        let b2 = e2 * inv_det;
        let t = t_scaled * inv_det;
        // - ensure that computed triangle t is conservatively greater than zero
        // Compute triangle partial derivatives
        let uv = self.get_uvs();
        // - compute deltas for partial derivatives
        let duv02 = uv[0] - uv[2];
        let duv12 = uv[1] - uv[2];
        let dp02 = p0 - p2;
        let dp12 = p1 - p2;
        let determinant = duv02[0] * duv12[1] - duv02[1] * duv12[0];
        let (dpdu, dpdv) = if determinant == 0.0 {
            // handle zero determinant
            coordinate_system(&(p2 - p0).cross(&(p1 - p0)).normalize())
        } else {
            let inv_det = 1.0 / determinant;
            let dpdu = (duv12[1] * dp02 - duv02[1] * dp12) / inv_det;
            let dpdv = (-duv12[0] * dp02 + duv02[0] * dp12) / inv_det;
            (dpdu, dpdv)
        };
        // Compute error bounds for triangle intersection
        let p_error = zero();
        // interpolate (u,v) parametric coordinates and hit point
        let p_hit = (p0.to_vector() * b0 + p1.to_vector() * b1 + p2.to_vector() * b2).to_point();
        let uv_hit = (uv[0].to_vector() * b0 + uv[1].to_vector() * b1 + uv[2].to_vector() * b2)
            .to_point();
        // test intersection against alpha texture if present
        // TODO
        // Fill in SurfaceInteraction from triangle hit
        let mut isect = SurfaceInteraction::new(p_hit, p_error, uv_hit, -ray.d, dpdu, dpdv, self);
        // - Override surface normal
        let n = dp02.cross(&dp12).normalize();
        isect.n = n;
        isect.shading.n = n;
        // Initialize triangle shading geometry
        // - shading normal
        let mut ns = if let Some(ref n) = self.mesh.n {
            (n[self.v[0]] * b0 + n[self.v[1]] * b1 + n[self.v[2]] * b2).normalize()
        } else {
            isect.n
        };
        // - shading tangent
        let mut ss = if let Some(ref s) = self.mesh.s {
            (s[self.v[0]] * b0 + s[self.v[1]] * b1 + s[self.v[2]] * b2).normalize()
        } else {
            isect.dpdu.normalize()
        };
        // - shading bitangent
        let mut ts = ss.cross(&ns);
        if ts.norm_squared() > 0.0 {
            ts = ts.normalize();
            // adjust ss to make sure it's orthogonal with ns and ts
            ss = ts.cross(&ns);
        } else {
            let (ss1, ts1) = coordinate_system(&ns);
            ss = ss1;
            ts = ts1;
        }
        isect.shading.n = ns;
        isect.shading.dpdu = ss;
        isect.shading.dpdv = ts;
        // Ensure correct orientation of the geometric normal TODO

        Some((isect, t))
    }

    fn area(&self) -> f32 {
        let p0 = self.mesh.p[self.v[0]];
        let p1 = self.mesh.p[self.v[1]];
        let p2 = self.mesh.p[self.v[2]];

        0.5 * (p1 - p0).cross(&(p2 - p0)).norm()
    }

    fn object_bounds(&self) -> Bounds3f {
        let p0 = self.mesh.world_to_object * self.mesh.p[self.v[0]];
        let p1 = self.mesh.world_to_object * self.mesh.p[self.v[1]];
        let p2 = self.mesh.world_to_object * self.mesh.p[self.v[2]];
        Bounds3f::union_point(&Bounds3f::from_points(&p0, &p1), &p2)
    }

    fn world_bounds(&self) -> Bounds3f {
        let p0 = self.mesh.p[self.v[0]];
        let p1 = self.mesh.p[self.v[1]];
        let p2 = self.mesh.p[self.v[2]];
        Bounds3f::union_point(&Bounds3f::from_points(&p0, &p1), &p2)
    }

    fn sample(&self, u: &Point2f) -> (Interaction, f32) {
        unimplemented!();
    }
}
<commit_msg>Properly error bounds for triangle intersection point<commit_after>use na::{Inverse, Cross, Norm};
use na::{abs, zero};

use ::{Transform, Point2f, Point3f, Vector3f, max_dimension, permute_v, permute_p,
       coordinate_system, gamma};
use bounds::Bounds3f;
use interaction::{Interaction, SurfaceInteraction};
use ray::Ray;
use shapes::Shape;

pub struct TriangleMesh {
    object_to_world: Transform,
    world_to_object: Transform,
    n_triangles: usize,
    n_vertices: usize,
    vertex_indices: Vec<usize>,
    p: Vec<Point3f>,
    n: Option<Vec<Vector3f>>,
    s: Option<Vec<Vector3f>>,
    uv: Option<Vec<Point2f>>, // TODO alpha mask
}

impl TriangleMesh {
    pub fn new(object_to_world: &Transform,
               n_triangles: usize,
               vertex_indices: &[usize],
               n_vertices: usize,
               p: &[Point3f],
               s: Option<&[Vector3f]>,
               n: Option<&[Vector3f]>,
               uv: Option<&[Point2f]>)
               -> Self {
        let points: Vec<Point3f> = p.iter().map(|pt| *object_to_world * *pt).collect();
        TriangleMesh {
            object_to_world: *object_to_world,
            world_to_object: object_to_world.inverse().unwrap(),
            n_triangles: n_triangles,
            n_vertices: n_vertices,
            vertex_indices: Vec::from(vertex_indices),
            p: points,
            n: n.map(Vec::from),
            s: s.map(Vec::from),
            uv: uv.map(Vec::from),
        }
    }
}

pub struct Triangle<'a> {
    mesh: &'a TriangleMesh,
    v: &'a [usize],
}

impl<'a> Triangle<'a> {
    pub fn new(mesh: &'a TriangleMesh, tri_number: usize) -> Triangle<'a> {
        Triangle {
            mesh: mesh,
            v: &mesh.vertex_indices[tri_number * 3..tri_number * 3 + 1],
        }
    }

    fn get_uvs(&self) -> [Point2f; 3] {
        if let Some(ref uv) = self.mesh.uv {
            [uv[self.v[0]], uv[self.v[1]], uv[self.v[2]]]
        } else {
            [Point2f::new(0.0, 0.0), Point2f::new(1.0, 0.0), Point2f::new(1.0, 1.0)]
        }
    }
}

impl<'a> Shape for Triangle<'a> {
    fn intersect(&self, ray: &Ray) -> Option<(SurfaceInteraction, f32)> {
        let p0 = self.mesh.p[self.v[0]];
        let p1 = self.mesh.p[self.v[1]];
        let p2 = self.mesh.p[self.v[2]];

        // Perform ray-triangle intersection test
        // - transform triangle vertices to ray coordinate space
        // -- translate vertices based on ray origin
        let mut p0t = p0 - ray.o.to_vector();
        let mut p1t = p1 - ray.o.to_vector();
        let mut p2t = p2 - ray.o.to_vector();
        // -- permute components of triangle vertices and ray direction
        let kz = max_dimension(abs(&ray.d));
        let mut kx = kz + 1;
        if kx == 3 {
            kx = 0;
        }
        let mut ky = kx + 1;
        if ky == 3 {
            ky = 0;
        }
        let d = permute_v(&ray.d, kx, ky, kz);
        p0t = permute_p(&p0t, kx, ky, kz);
        p1t = permute_p(&p1t, kx, ky, kz);
        p2t = permute_p(&p2t, kx, ky, kz);
        // -- apply shear transformation to translated vertex positions
        let sx = -d.x / d.z;
        let sy = -d.y / d.z;
        let sz = 1.0 / d.z;
        p0t.x += sx * p0t.z;
        p0t.y += sy * p0t.z;
        p1t.x += sx * p1t.z;
        p1t.y += sy * p1t.z;
        p2t.x += sx * p2t.z;
        p2t.y += sy * p2t.z;
        // - compute edge function coefficients
        let e0 = p1t.x * p2t.y - p1t.y * p2t.x;
        let e1 = p2t.x * p0t.y - p2t.y * p0t.x;
        let e2 = p0t.x * p1t.y - p0t.y * p1t.x;
        // - fall back to double precision at edges
        // TODO
        // - perform triangle edge and determinant test
        if (e0 < 0.0 || e1 < 0.0 || e2 < 0.0) && (e0 > 0.0 || e1 > 0.0 || e2 > 0.0) {
            return None;
        }
        let det = e0 + e1 + e2;
        if det == 0.0 {
            return None;
        }
        // - compute scaled hit distance to triangle and test against ray t range
        p0t.z *= sz;
        p1t.z *= sz;
        p2t.z *= sz;
        let t_scaled = e0 * p0t.z + e1 * p1t.z + e2 * p2t.z;
        if det < 0.0 && (t_scaled >= 0.0 || t_scaled < ray.t_max * det) {
            return None;
        } else if det > 0.0 && (t_scaled <= 0.0 || t_scaled > ray.t_max * det) {
            return None;
        }
        // - compute barycentric coordinates and t value for triangle intersection
        let inv_det = 1.0 / det;
        let b0 = e0 * inv_det;
        let b1 = e1 * inv_det;
        let b2 = e2 * inv_det;
        let t = t_scaled * inv_det;
        // - ensure that computed triangle t is conservatively greater than zero
        // Compute triangle partial derivatives
        let uv = self.get_uvs();
        // - compute deltas for partial derivatives
        let duv02 = uv[0] - uv[2];
        let duv12 = uv[1] - uv[2];
        let dp02 = p0 - p2;
        let dp12 = p1 - p2;
        let determinant = duv02[0] * duv12[1] - duv02[1] * duv12[0];
        let (dpdu, dpdv) = if determinant == 0.0 {
            // handle zero determinant
            coordinate_system(&(p2 - p0).cross(&(p1 - p0)).normalize())
        } else {
            let inv_det = 1.0 / determinant;
            let dpdu = (duv12[1] * dp02 - duv02[1] * dp12) / inv_det;
            let dpdv = (-duv12[0] * dp02 + duv02[0] * dp12) / inv_det;
            (dpdu, dpdv)
        };
        // Compute error bounds for triangle intersection
        let x_abs_sum = (b0 * p0.x).abs() + (b1 * p1.x).abs() + (b2 * p2.x).abs();
        let y_abs_sum = (b0 * p0.y).abs() + (b1 * p1.y).abs() + (b2 * p2.y).abs();
        let z_abs_sum = (b0 * p0.z).abs() + (b1 * p1.z).abs() + (b2 * p2.z).abs();
        let p_error = gamma(7) * Vector3f::new(x_abs_sum, y_abs_sum, z_abs_sum);
        // interpolate (u,v) parametric coordinates and hit point
        let p_hit = (p0.to_vector() * b0 + p1.to_vector() * b1 + p2.to_vector() * b2).to_point();
        let uv_hit = (uv[0].to_vector() * b0 + uv[1].to_vector() * b1 + uv[2].to_vector() * b2)
            .to_point();
        // test intersection against alpha texture if present
        // TODO
        // Fill in SurfaceInteraction from triangle hit
        let mut isect = SurfaceInteraction::new(p_hit, p_error, uv_hit, -ray.d, dpdu, dpdv, self);
        // - Override surface normal
        let n = dp02.cross(&dp12).normalize();
        isect.n = n;
        isect.shading.n = n;
        // Initialize triangle shading geometry
        // - shading normal
        let mut ns = if let Some(ref n) = self.mesh.n {
            (n[self.v[0]] * b0 + n[self.v[1]] * b1 + n[self.v[2]] * b2).normalize()
        } else {
            isect.n
        };
        // - shading tangent
        let mut ss = if let Some(ref s) = self.mesh.s {
            (s[self.v[0]] * b0 + s[self.v[1]] * b1 + s[self.v[2]] * b2).normalize()
        } else {
            isect.dpdu.normalize()
        };
        // - shading bitangent
        let mut ts = ss.cross(&ns);
        if ts.norm_squared() > 0.0 {
            ts = ts.normalize();
            // adjust ss to make sure it's orthogonal with ns and ts
            ss = ts.cross(&ns);
        } else {
            let (ss1, ts1) = coordinate_system(&ns);
            ss = ss1;
            ts = ts1;
        }
        isect.shading.n = ns;
        isect.shading.dpdu = ss;
        isect.shading.dpdv = ts;
        // Ensure correct orientation of the geometric normal TODO

        Some((isect, t))
    }

    fn area(&self) -> f32 {
        let p0 = self.mesh.p[self.v[0]];
        let p1 = self.mesh.p[self.v[1]];
        let p2 = self.mesh.p[self.v[2]];

        0.5 * (p1 - p0).cross(&(p2 - p0)).norm()
    }

    fn object_bounds(&self) -> Bounds3f {
        let p0 = self.mesh.world_to_object * self.mesh.p[self.v[0]];
        let p1 = self.mesh.world_to_object * self.mesh.p[self.v[1]];
        let p2 = self.mesh.world_to_object * self.mesh.p[self.v[2]];
        Bounds3f::union_point(&Bounds3f::from_points(&p0, &p1), &p2)
    }

    fn world_bounds(&self) -> Bounds3f {
        let p0 = self.mesh.p[self.v[0]];
        let p1 = self.mesh.p[self.v[1]];
        let p2 = self.mesh.p[self.v[2]];
        Bounds3f::union_point(&Bounds3f::from_points(&p0, &p1), &p2)
    }

    fn sample(&self, u: &Point2f) -> (Interaction, f32) {
        unimplemented!();
    }
}
<|endoftext|>


<commit_before>use associations::HasTable;
#[cfg(any(feature = "sqlite", feature = "postgres", feature = "mysql"))]
use dsl::Update;
use query_builder::{AsChangeset, IntoUpdateTarget};
#[cfg(any(feature = "sqlite", feature = "postgres", feature = "mysql"))]
use query_dsl::{LoadQuery, RunQueryDsl};
use result::QueryResult;
#[cfg(any(feature = "sqlite", feature = "mysql"))]
use associations::Identifiable;
#[cfg(any(feature = "sqlite", feature = "mysql"))]
use dsl::Find;
#[cfg(any(feature = "sqlite", feature = "mysql"))]
use query_dsl::methods::{ExecuteDsl, FindDsl};

pub trait InternalSaveChangesDsl<Conn, T>: Sized {
    fn internal_save_changes(self, connection: &Conn) -> QueryResult<T>;
}

#[cfg(feature = "postgres")]
use pg::PgConnection;

#[cfg(feature = "postgres")]
impl<T, U> InternalSaveChangesDsl<PgConnection, U> for T
where
    T: Copy + AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget,
    Update<T, T>: LoadQuery<PgConnection, U>,
{
    fn internal_save_changes(self, conn: &PgConnection) -> QueryResult<U> {
        ::update(self).set(self).get_result(conn)
    }
}

#[cfg(feature = "sqlite")]
use sqlite::SqliteConnection;

#[cfg(feature = "sqlite")]
impl<T, U> InternalSaveChangesDsl<SqliteConnection, U> for T
where
    T: Copy + Identifiable,
    T: AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget,
    T::Table: FindDsl<T::Id>,
    Update<T, T>: ExecuteDsl<SqliteConnection>,
    Find<T::Table, T::Id>: LoadQuery<SqliteConnection, U>,
{
    fn internal_save_changes(self, conn: &SqliteConnection) -> QueryResult<U> {
        try!(::update(self).set(self).execute(conn));
        T::table().find(self.id()).get_result(conn)
    }
}

#[cfg(feature = "mysql")]
use mysql::MysqlConnection;

#[cfg(feature = "mysql")]
impl<T, U> InternalSaveChangesDsl<MysqlConnection, U> for T
where
    T: Copy + Identifiable,
    T: AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget,
    T::Table: FindDsl<T::Id>,
    Update<T, T>: ExecuteDsl<MysqlConnection>,
    Find<T::Table, T::Id>: LoadQuery<MysqlConnection, U>,
{
    fn internal_save_changes(self, conn: &MysqlConnection) -> QueryResult<U> {
        try!(::update(self).set(self).execute(conn));
        T::table().find(self.id()).get_result(conn)
    }
}

pub trait SaveChangesDsl<Conn> {
    /// Sugar for types which implement both `AsChangeset` and `Identifiable`
    ///
    /// `foo.save_changes(&conn)` is equivalent to
    /// `update(foo::table().find(foo.id())).set(&foo).get_result(&conn)`
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// # use schema::animals;
    /// #
    /// # #[derive(AsChangeset, Debug, PartialEq, Identifiable, Queryable)]
    /// # struct Animal {
    /// #    id: i32,
    /// #    species: String,
    /// #    legs: i32,
    /// #    name: Option<String>,
    /// # }
    /// #
    /// # fn main() {
    /// #     use animals::dsl::*;
    /// #     let connection = establish_connection();
    /// let mut spider = animals.filter(species.eq("spider"))
    ///     .first::<Animal>(&connection)
    ///     .expect("Too scary to load");
    ///
    /// spider.species = String::from("solifuge");
    /// spider.legs = 10;
    ///
    /// spider.save_changes::<Animal>(&connection).expect("Error saving changes");
    ///
    /// let changed_animal = animals.find(spider.id())
    ///     .first::<Animal>(&connection);
    ///
    /// assert_eq!(Ok(Animal { id: 2, species: "solifuge".to_string(), legs: 10, name: None }), changed_animal);
    /// # }
    /// ```
    fn save_changes<T>(self, connection: &Conn) -> QueryResult<T>
    where
        Self: InternalSaveChangesDsl<Conn, T>,
    {
        self.internal_save_changes(connection)
    }
}

impl<T, Conn> SaveChangesDsl<Conn> for T
where
    T: Copy + AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget,
{
}
<commit_msg>Rework the docs on `SaveChangesDsl`.<commit_after>use associations::HasTable;
#[cfg(any(feature = "sqlite", feature = "postgres", feature = "mysql"))]
use dsl::Update;
use query_builder::{AsChangeset, IntoUpdateTarget};
#[cfg(any(feature = "sqlite", feature = "postgres", feature = "mysql"))]
use query_dsl::{LoadQuery, RunQueryDsl};
use result::QueryResult;
#[cfg(any(feature = "sqlite", feature = "mysql"))]
use associations::Identifiable;
#[cfg(any(feature = "sqlite", feature = "mysql"))]
use dsl::Find;
#[cfg(any(feature = "sqlite", feature = "mysql"))]
use query_dsl::methods::{ExecuteDsl, FindDsl};

pub trait InternalSaveChangesDsl<Conn, T>: Sized {
    fn internal_save_changes(self, connection: &Conn) -> QueryResult<T>;
}

#[cfg(feature = "postgres")]
use pg::PgConnection;

#[cfg(feature = "postgres")]
impl<T, U> InternalSaveChangesDsl<PgConnection, U> for T
where
    T: Copy + AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget,
    Update<T, T>: LoadQuery<PgConnection, U>,
{
    fn internal_save_changes(self, conn: &PgConnection) -> QueryResult<U> {
        ::update(self).set(self).get_result(conn)
    }
}

#[cfg(feature = "sqlite")]
use sqlite::SqliteConnection;

#[cfg(feature = "sqlite")]
impl<T, U> InternalSaveChangesDsl<SqliteConnection, U> for T
where
    T: Copy + Identifiable,
    T: AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget,
    T::Table: FindDsl<T::Id>,
    Update<T, T>: ExecuteDsl<SqliteConnection>,
    Find<T::Table, T::Id>: LoadQuery<SqliteConnection, U>,
{
    fn internal_save_changes(self, conn: &SqliteConnection) -> QueryResult<U> {
        try!(::update(self).set(self).execute(conn));
        T::table().find(self.id()).get_result(conn)
    }
}

#[cfg(feature = "mysql")]
use mysql::MysqlConnection;

#[cfg(feature = "mysql")]
impl<T, U> InternalSaveChangesDsl<MysqlConnection, U> for T
where
    T: Copy + Identifiable,
    T: AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget,
    T::Table: FindDsl<T::Id>,
    Update<T, T>: ExecuteDsl<MysqlConnection>,
    Find<T::Table, T::Id>: LoadQuery<MysqlConnection, U>,
{
    fn internal_save_changes(self, conn: &MysqlConnection) -> QueryResult<U> {
        try!(::update(self).set(self).execute(conn));
        T::table().find(self.id()).get_result(conn)
    }
}

pub trait SaveChangesDsl<Conn> {
    /// Sugar for types which implement both `AsChangeset` and `Identifiable`
    ///
    /// On backends which support the `RETURNING` keyword,
    /// `foo.save_changes(&conn)` is equivalent to
    /// `update(&foo).set(&foo).get_result(&conn)`.
    /// On other backends, two queries will be executed.
    ///
    /// # Example
    ///
    /// ```rust
    /// # #[macro_use] extern crate diesel;
    /// # include!("../doctest_setup.rs");
    /// # use schema::animals;
    /// #
    /// #[derive(Queryable, Debug, PartialEq)]
    /// struct Animal {
    ///    id: i32,
    ///    species: String,
    ///    legs: i32,
    ///    name: Option<String>,
    /// }
    ///
    /// #[derive(AsChangeset, Identifiable)]
    /// #[table_name = "animals"]
    /// struct AnimalForm<'a> {
    ///     id: i32,
    ///     name: &'a str,
    /// }
    ///
    /// # fn main() {
    /// #     run_test();
    /// # }
    /// #
    /// # fn run_test() -> QueryResult<()> {
    /// #     use animals::dsl::*;
    /// #     let connection = establish_connection();
    /// let form = AnimalForm { id: 2, name: "Super scary" };
    /// let changed_animal = form.save_changes(&connection)?;
    /// let expected_animal = Animal {
    ///     id: 2,
    ///     species: String::from("spider"),
    ///     legs: 8,
    ///     name: Some(String::from("Super scary")),
    /// };
    /// assert_eq!(expected_animal, changed_animal);
    /// #     Ok(())
    /// # }
    /// ```
    fn save_changes<T>(self, connection: &Conn) -> QueryResult<T>
    where
        Self: InternalSaveChangesDsl<Conn, T>,
    {
        self.internal_save_changes(connection)
    }
}

impl<T, Conn> SaveChangesDsl<Conn> for T
where
    T: Copy + AsChangeset<Target = <T as HasTable>::Table> + IntoUpdateTarget,
{
}
<|endoftext|>


<commit_before>use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

use actix_codec::{AsyncRead, AsyncWrite, Framed};

use crate::body::{BodySize, MessageBody, ResponseBody};
use crate::error::Error;
use crate::h1::{Codec, Message};
use crate::response::Response;

/// Send http/1 response
#[pin_project::pin_project]
pub struct SendResponse<T, B> {
    res: Option<Message<(Response<()>, BodySize)>>,
    #[pin]
    body: Option<ResponseBody<B>>,
    framed: Option<Framed<T, Codec>>,
}

impl<T, B> SendResponse<T, B>
where
    B: MessageBody,
{
    pub fn new(framed: Framed<T, Codec>, response: Response<B>) -> Self {
        let (res, body) = response.into_parts();

        SendResponse {
            res: Some((res, body.size()).into()),
            body: Some(body),
            framed: Some(framed),
        }
    }
}

impl<T, B> Future for SendResponse<T, B>
where
    T: AsyncRead + AsyncWrite,
    B: MessageBody + Unpin,
{
    type Output = Result<Framed<T, Codec>, Error>;

    // TODO: rethink if we need loops in polls
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut this = self.project();

        let mut body_done = this.body.is_none();
        loop {
            let mut body_ready = !body_done;
            let framed = this.framed.as_mut().unwrap();

            // send body
            if this.res.is_none() && body_ready {
                while body_ready && !body_done && !framed.is_write_buf_full() {
                    match this.body.as_mut().as_pin_mut().unwrap().poll_next(cx)? {
                        Poll::Ready(item) => {
                            // body is done when item is None
                            body_done = item.is_none();
                            if body_done {
                                let _ = this.body.take();
                            }
                            framed.write(Message::Chunk(item))?;
                        }
                        Poll::Pending => body_ready = false,
                    }
                }
            }

            // flush write buffer
            if !framed.is_write_buf_empty() {
                match framed.flush(cx)? {
                    Poll::Ready(_) => {
                        if body_ready {
                            continue;
                        } else {
                            return Poll::Pending;
                        }
                    }
                    Poll::Pending => return Poll::Pending,
                }
            }

            // send response
            if let Some(res) = this.res.take() {
                framed.write(res)?;
                continue;
            }

            if body_done {
                if body_ready {
                    continue;
                } else {
                    return Poll::Pending;
                }
            } else {
                break;
            }
        }
        Poll::Ready(Ok(this.framed.take().unwrap()))
    }
}
<commit_msg>Fixed condition for finishing  transfer of response<commit_after>use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};

use actix_codec::{AsyncRead, AsyncWrite, Framed};

use crate::body::{BodySize, MessageBody, ResponseBody};
use crate::error::Error;
use crate::h1::{Codec, Message};
use crate::response::Response;

/// Send http/1 response
#[pin_project::pin_project]
pub struct SendResponse<T, B> {
    res: Option<Message<(Response<()>, BodySize)>>,
    #[pin]
    body: Option<ResponseBody<B>>,
    framed: Option<Framed<T, Codec>>,
}

impl<T, B> SendResponse<T, B>
where
    B: MessageBody,
{
    pub fn new(framed: Framed<T, Codec>, response: Response<B>) -> Self {
        let (res, body) = response.into_parts();

        SendResponse {
            res: Some((res, body.size()).into()),
            body: Some(body),
            framed: Some(framed),
        }
    }
}

impl<T, B> Future for SendResponse<T, B>
where
    T: AsyncRead + AsyncWrite,
    B: MessageBody + Unpin,
{
    type Output = Result<Framed<T, Codec>, Error>;

    // TODO: rethink if we need loops in polls
    fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
        let mut this = self.project();

        let mut body_done = this.body.is_none();
        loop {
            let mut body_ready = !body_done;
            let framed = this.framed.as_mut().unwrap();

            // send body
            if this.res.is_none() && body_ready {
                while body_ready && !body_done && !framed.is_write_buf_full() {
                    match this.body.as_mut().as_pin_mut().unwrap().poll_next(cx)? {
                        Poll::Ready(item) => {
                            // body is done when item is None
                            body_done = item.is_none();
                            if body_done {
                                let _ = this.body.take();
                            }
                            framed.write(Message::Chunk(item))?;
                        }
                        Poll::Pending => body_ready = false,
                    }
                }
            }

            // flush write buffer
            if !framed.is_write_buf_empty() {
                match framed.flush(cx)? {
                    Poll::Ready(_) => {
                        if body_ready {
                            continue;
                        } else {
                            return Poll::Pending;
                        }
                    }
                    Poll::Pending => return Poll::Pending,
                }
            }

            // send response
            if let Some(res) = this.res.take() {
                framed.write(res)?;
                continue;
            }

            if !body_done {
                if body_ready {
                    continue;
                } else {
                    return Poll::Pending;
                }
            } else {
                break;
            }
        }
        Poll::Ready(Ok(this.framed.take().unwrap()))
    }
}
<|endoftext|>


<commit_before>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::AttrBinding;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::Window;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window;
use dom::virtualmethods::vtable_for;
use servo_util::atom::Atom;
use servo_util::namespace;
use servo_util::namespace::Namespace;
use servo_util::str::{DOMString, HTML_SPACE_CHARACTERS};
use std::cell::{Ref, RefCell};
use std::mem;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[deriving(PartialEq, Clone, Encodable)]
pub enum AttrValue {
    StringAttrValue(DOMString),
    TokenListAttrValue(DOMString, Vec<(uint, uint)>),
    UIntAttrValue(DOMString, u32),
    AtomAttrValue(Atom),
}

impl AttrValue {
    pub fn from_tokenlist(list: DOMString) -> AttrValue {
        let mut indexes = vec![];
        let mut last_index: uint = 0;
        let length = list.len() - 1;
        for (index, ch) in list.as_slice().char_indices() {
            if HTML_SPACE_CHARACTERS.iter().any(|&space| space == ch) {
                if last_index != index {
                    indexes.push((last_index, index));
                }
                last_index = index + 1;
            } else if index == length {
                indexes.push((last_index, index + 1));
            }
        }
        return TokenListAttrValue(list, indexes);
    }

    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result: u32 = from_str(string.as_slice()).unwrap_or(default);
        UIntAttrValue(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(string.as_slice());
        AtomAttrValue(value)
    }

}

impl Str for AttrValue {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            StringAttrValue(ref value) |
            TokenListAttrValue(ref value, _) |
            UIntAttrValue(ref value, _) => value.as_slice(),
            AtomAttrValue(ref value) => value.as_slice(),
        }
    }
}

#[deriving(Encodable)]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: Traceable<RefCell<AttrValue>>,
    pub name: Atom,
    pub namespace: Namespace,
    pub prefix: Option<DOMString>,

    /// the element that owns this attribute.
    owner: JS<Element>,
}

impl Reflectable for Attr {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue,
                     name: Atom, namespace: Namespace,
                     prefix: Option<DOMString>, owner: &JSRef<Element>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: Traceable::new(RefCell::new(value)),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: JS::from_rooted(owner),
        }
    }

    pub fn new(window: &JSRef<Window>, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<DOMString>, owner: &JSRef<Element>) -> Temporary<Attr> {
        let attr = Attr::new_inherited(local_name, value, name, namespace, prefix, owner);
        reflect_dom_object(box attr, &Window(*window), AttrBinding::Wrap)
    }

    pub fn set_value(&self, set_type: AttrSettingType, value: AttrValue) {
        let owner = self.owner.root();
        let node: &JSRef<Node> = NodeCast::from_ref(&*owner);
        let namespace_is_null = self.namespace == namespace::Null;

        match set_type {
            ReplacedAttr => {
                if namespace_is_null {
                    vtable_for(node).before_remove_attr(
                        self.local_name(),
                        self.value().as_slice().to_string())
                }
            }
            FirstSetAttr => {}
        }

        *self.value.deref().borrow_mut() = value;

        if namespace_is_null {
            vtable_for(node).after_set_attr(
                self.local_name(),
                self.value().as_slice().to_string())
        }
    }

    pub fn value<'a>(&'a self) -> Ref<'a, AttrValue> {
        self.value.deref().borrow()
    }

    pub fn local_name<'a>(&'a self) -> &'a Atom {
        &self.local_name
    }
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
    fn LocalName(&self) -> DOMString {
        self.local_name().as_slice().to_string()
    }

    fn Value(&self) -> DOMString {
        self.value().as_slice().to_string()
    }

    fn SetValue(&self, value: DOMString) {
        let owner = self.owner.root();
        let value = owner.deref().parse_attribute(
            &self.namespace, self.local_name(), value);
        self.set_value(ReplacedAttr, value);
    }

    fn Name(&self) -> DOMString {
        self.name.as_slice().to_string()
    }

    fn GetNamespaceURI(&self) -> Option<DOMString> {
        match self.namespace.to_str() {
            "" => None,
            url => Some(url.to_string()),
        }
    }

    fn GetPrefix(&self) -> Option<DOMString> {
        self.prefix.clone()
    }
}

pub trait AttrHelpersForLayout {
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
}

impl AttrHelpersForLayout for Attr {
    unsafe fn value_ref_forever(&self) -> &'static str {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref());
        value.as_slice()
    }

    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref());
        match *value {
            AtomAttrValue(ref val) => Some(val.clone()),
            _ => None,
        }
    }
}
<commit_msg>Implemented Attribute's tokens() iterator<commit_after>/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use dom::bindings::codegen::Bindings::AttrBinding;
use dom::bindings::codegen::Bindings::AttrBinding::AttrMethods;
use dom::bindings::codegen::InheritTypes::NodeCast;
use dom::bindings::global::Window;
use dom::bindings::js::{JS, JSRef, Temporary};
use dom::bindings::trace::Traceable;
use dom::bindings::utils::{Reflectable, Reflector, reflect_dom_object};
use dom::element::{Element, AttributeHandlers};
use dom::node::Node;
use dom::window::Window;
use dom::virtualmethods::vtable_for;
use servo_util::atom::Atom;
use servo_util::namespace;
use servo_util::namespace::Namespace;
use servo_util::str::{DOMString, split_html_space_chars};
use std::cell::{Ref, RefCell};
use std::mem;
use std::slice::Items;

pub enum AttrSettingType {
    FirstSetAttr,
    ReplacedAttr,
}

#[deriving(PartialEq, Clone, Encodable)]
pub enum AttrValue {
    StringAttrValue(DOMString),
    TokenListAttrValue(DOMString, Vec<Atom>),
    UIntAttrValue(DOMString, u32),
    AtomAttrValue(Atom),
}

impl AttrValue {
    pub fn from_tokenlist(tokens: DOMString) -> AttrValue {
        let atoms = split_html_space_chars(tokens.as_slice())
            .map(|token| Atom::from_slice(token)).collect();
        TokenListAttrValue(tokens, atoms)
    }

    pub fn from_u32(string: DOMString, default: u32) -> AttrValue {
        let result: u32 = from_str(string.as_slice()).unwrap_or(default);
        UIntAttrValue(string, result)
    }

    pub fn from_atomic(string: DOMString) -> AttrValue {
        let value = Atom::from_slice(string.as_slice());
        AtomAttrValue(value)
    }

    pub fn tokens<'a>(&'a self) -> Option<Items<'a, Atom>> {
        match *self {
            TokenListAttrValue(_, ref tokens) => Some(tokens.iter()),
            _ => None
        }
    }
}

impl Str for AttrValue {
    fn as_slice<'a>(&'a self) -> &'a str {
        match *self {
            StringAttrValue(ref value) |
            TokenListAttrValue(ref value, _) |
            UIntAttrValue(ref value, _) => value.as_slice(),
            AtomAttrValue(ref value) => value.as_slice(),
        }
    }
}

#[deriving(Encodable)]
pub struct Attr {
    reflector_: Reflector,
    local_name: Atom,
    value: Traceable<RefCell<AttrValue>>,
    pub name: Atom,
    pub namespace: Namespace,
    pub prefix: Option<DOMString>,

    /// the element that owns this attribute.
    owner: JS<Element>,
}

impl Reflectable for Attr {
    fn reflector<'a>(&'a self) -> &'a Reflector {
        &self.reflector_
    }
}

impl Attr {
    fn new_inherited(local_name: Atom, value: AttrValue,
                     name: Atom, namespace: Namespace,
                     prefix: Option<DOMString>, owner: &JSRef<Element>) -> Attr {
        Attr {
            reflector_: Reflector::new(),
            local_name: local_name,
            value: Traceable::new(RefCell::new(value)),
            name: name,
            namespace: namespace,
            prefix: prefix,
            owner: JS::from_rooted(owner),
        }
    }

    pub fn new(window: &JSRef<Window>, local_name: Atom, value: AttrValue,
               name: Atom, namespace: Namespace,
               prefix: Option<DOMString>, owner: &JSRef<Element>) -> Temporary<Attr> {
        let attr = Attr::new_inherited(local_name, value, name, namespace, prefix, owner);
        reflect_dom_object(box attr, &Window(*window), AttrBinding::Wrap)
    }

    pub fn set_value(&self, set_type: AttrSettingType, value: AttrValue) {
        let owner = self.owner.root();
        let node: &JSRef<Node> = NodeCast::from_ref(&*owner);
        let namespace_is_null = self.namespace == namespace::Null;

        match set_type {
            ReplacedAttr => {
                if namespace_is_null {
                    vtable_for(node).before_remove_attr(
                        self.local_name(),
                        self.value().as_slice().to_string())
                }
            }
            FirstSetAttr => {}
        }

        *self.value.deref().borrow_mut() = value;

        if namespace_is_null {
            vtable_for(node).after_set_attr(
                self.local_name(),
                self.value().as_slice().to_string())
        }
    }

    pub fn value<'a>(&'a self) -> Ref<'a, AttrValue> {
        self.value.deref().borrow()
    }

    pub fn local_name<'a>(&'a self) -> &'a Atom {
        &self.local_name
    }
}

impl<'a> AttrMethods for JSRef<'a, Attr> {
    fn LocalName(&self) -> DOMString {
        self.local_name().as_slice().to_string()
    }

    fn Value(&self) -> DOMString {
        self.value().as_slice().to_string()
    }

    fn SetValue(&self, value: DOMString) {
        let owner = self.owner.root();
        let value = owner.deref().parse_attribute(
            &self.namespace, self.local_name(), value);
        self.set_value(ReplacedAttr, value);
    }

    fn Name(&self) -> DOMString {
        self.name.as_slice().to_string()
    }

    fn GetNamespaceURI(&self) -> Option<DOMString> {
        match self.namespace.to_str() {
            "" => None,
            url => Some(url.to_string()),
        }
    }

    fn GetPrefix(&self) -> Option<DOMString> {
        self.prefix.clone()
    }
}

pub trait AttrHelpersForLayout {
    unsafe fn value_ref_forever(&self) -> &'static str;
    unsafe fn value_atom_forever(&self) -> Option<Atom>;
}

impl AttrHelpersForLayout for Attr {
    unsafe fn value_ref_forever(&self) -> &'static str {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref());
        value.as_slice()
    }

    unsafe fn value_atom_forever(&self) -> Option<Atom> {
        // cast to point to T in RefCell<T> directly
        let value = mem::transmute::<&RefCell<AttrValue>, &AttrValue>(self.value.deref());
        match *value {
            AtomAttrValue(ref val) => Some(val.clone()),
            _ => None,
        }
    }
}
<|endoftext|>